一.环境准备
本次环境准备的流程与之前文章相同,所以简述以下,首先就是根据vulhub下spring文件中CVE-2017-8046文件,之后docker-compose up -d就会启用对应靶场,之后利用docker ps查看进程ID
之后根据对应的容器ID进入对应容器
之后ls查看目录下面有什么文件
看到spring-rest-data-demo-2.0.0.BUILD.jar文件就可以知道这是一个springboot程序,之后退出容器利用docker ps e33897b9164a:/spring-rest-data-demo-2.0.0.BUILD.jar /home/ubuntu命令就可以将这个jar文件复制到家目录中,之后就可以下载下来这个文件放入jd-gui中进行反编译,之后结果为
之后将对应文件放入IDEA中,记住要将包名进行修改。
对应文件如上图,自此就完成了对于环境的搭建。
二.漏洞复现
本次漏洞的成因主要是PATCH方法处理不当,导致攻击者能够利用JSON数据造成RCE,主要原因还是对于SPEL表达式没有进行过滤,稍后会详细阐述原因。
因此本次复现只需要首先打开对应springboot项目,之后在浏览器输入http://127.0.0.1:8080
就会出现对应的json解析后的样式,之后点击customers进入
进入至此就可以利用burp进行抓包之后修改对应数据
对饮输入的json数据就是通过replace实现对于path中的spel表达式进行命令执行,由于我本机为windows操作系统,因此new byte[]{99,97,108,99}代表calc命令,如果可以正常弹出计算器就可以说明可以执行命令执行,点击发包
可以看到对应的相应包以及弹出计算器的界面,因此说明本次漏洞复现成功。
三.漏洞原理
本次漏洞原理分析主要是从org.springframework.data.rest.webmvc.config包下的JsonPatchHandler类中的apply方法开始,这个方法主要的用处就是处理Json请求的。
首先我们按两次shift在IDEA中全局搜索JsonPatchHandler这个类,知道找到对应的apply方法
之后再这个打一个断点,然后启动IDEA的debug模式,用burp发包
之后我们运行到这里,看一下具体的语句
return request.isJsonPatchRequest() ? this.applyPatch(request.getBody(), target) : this.applyMergePatch(request.getBody(), target);
这个就是一个三目比较,首先根据提示找到isJsonppatchRequest()方法,我们只需要按住ctrl健,然后鼠标移动到方法名字上面点击就可以跳转到对应的方法实现中去
这里有两个方法,首先是判断请求的方法是否为PATCH之后判断以下contentType是否为application/json-patch+json,因此在我们之前发包时必须注意这两点
之后回到之前的方法中去如果判断成功我们就会进入到applyPatch方法中,因此我们继续跟进
运行到这里我们就可以知道target就是我们需要改的数据
根据上述函数名字我们可以大概了解到主要目的就是获得Patch需要修改的操作方法,我么传入的时replace方法因此最终一定会和这个有关
之后进入到实现方法中,找到convert也就是转换方法
这部分看上去代码可能很长但是实际就是为了创造我们需要replace因此ops中加入一个ReplaceOperation这个类这个方法最终结束的时候
return new Patch(ops);
因此我们去寻找Patch的构造方法
是传入一个PatchOperation这个列表,之后进入对应的实现方法
发现有对应的spel表达式也就是要解析我们需要的el表达式,我们进入到pahToExpression()方法查看对应的实现
其中SPEL_EXPRESSION_PARSER的定义如下,其实就是解析path中的spel表达式
private static final SpelExpressionParser SPEL_EXPRESSION_PARSER = new SpelExpressionParser();
因此我们只需要进入到pathToSpEL中查看是否对于输入的参数进行了过滤,如果没有我们就可以进行远程RCE了
对应的方法如上,并没有进行过多的过滤,只是用/进行了分割
此时的path值分割之后正是我们需要的执行语句
之后野兵,没有进行过过滤一直返回到applyPatch方法
这时getPatchOperations方法返回的就是一个Patch对象因此调用Patch对象中的apply方法
到这里就是遍历,因为PatchOperation时一个抽象类,而根据我们刚才的调用发信啊我们现在获得的是ReplaceOperation类了,因此会调用ReplaceOperation中的perform方法
这个方法中还调用了setValueOnTarget方法,因此我们进入跟入
就发现了setValue这个方法,根据spel的规则我们就可以知道到此我们就可以实现远程RCE了,继续debug下一步就可以弹出计算机
到此我们就可以实现对于CVE-2017-8046的完整复现
四.总结
本次CVE复现是根据IDEA中DEBUG模式下一步步跟进的,对于spel也可以做到进一步的了解,对于本次漏洞产生的原因也主要是对于path中的spel表达式解析时,没有考虑到过滤一些恶意攻击的函数,因此导致了远程RCE,在之后的系列文章中也会继续复现相应的java spring漏洞。