[备份]CVE-2018-1271分析

简介

SpringMVC的一个目录穿越漏洞,或者说目录遍历漏洞。SpringMVC是Java开发界最常用的框架之一,当静态资源存放在Windows系统上时,攻击可以通过构造特殊URL导致目录遍历漏洞

漏洞有限制条件

漏洞复现

下载官方示例:https://github.com/spring-projects/spring-mvc-showcase

修改spring的版本

修改配置文件:org\springframework\samples\mvc\config\WebMvcConfig.java 这里的作用主要是配置资源映射,将url的/resources/**映射到file协议的resources下,其实真实开发场景一般不这样配

使用mvn命令启动:mvn jetty:run(可在IDEA中配置启动方式为Maven后加入参数) img

访问特殊url后成功读到文件:http://localhost:8080/spring-mvc-showcase/resources/%255c%255c..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/key.txt(由于我项目不在c盘,就没有读win.ini文件,自己新建了一个文件) img

 

漏洞分析

org\springframework\web\servlet\resource\ResourceHttpRequestHandler.java 这里是处理请求的类,方法是handleRequest,一开始调用了getResource方法,跟入

进入request.getAttribute有多种实现,不方便继续跟入分析,尝试动态调试,发现这里得到的path是进行一次url解码后的结果 img

后续有processPath和isInvalidPath方法对path进行处理和校验,其中processPath方法作用是处理斜杠的问题,比如多个斜杠或者丢失斜杠的问题,和这里无关系,程序经过它是path也没有变化。isInvalidPath是需要重点关注的

首先禁止了WEB-INF和META-INF等关键路径,然后处理是url(带有:/)的情况,最后是处理带有..的情况,而..正是目录遍历漏洞需要用到的

跟入cleanPath方法,稍显复杂,实现的功能是将/foo/bar/../这样的路径转换为/foo/,其中delimitedListToStringArray方法会返回一个目录数组,比如上面的foobar..。如果传入的是/foo/bar//../,数组中会有一个空值,cleanPath会解析为/foo/bar/,但系统中认为是/foo/。我们的payload%5c%5c..%5c/..%5c/..%5c/..%5c/..%5c/在这里按照/分割后,没有等于..的,所以cleanPath后原样返回

而上文的getResource方法的后半部分,又调用了一次isInvalidPath方法。此时path中还是包含%,所以成功进入了if,进行url解码后变成\\..\/..\/..\/..\/..\/..\/这种格式,经过cleanPath处理后,变成了//key.txt,返回false,通过了校验

img

img

经过以上一系列复杂的处理后得到一个resource,path其实并没有变化,只是经过一次url解码后的结果:%5c%5c..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/key.txt

其中getLocations是我们之前配置的file:./src/main/resources/,跟入resolveResource,一条很长的调用链,最终到PathResourceResolvergetResource

继续跟入getResource方法,

经过createRelative方法拼接后得到file:src/main/resources/%5c%5c..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/key.txt

在配置文件中修改为file:是因为isFileURL

跟入getFile

getSchemeSpecificPart方法中,有一次url的解码

层层返回,验证通过,但路径还是没有变:/%5c%5c..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/key.txt

handleRequest方法后续,验证通过,准备工作结束后,开始往response里面写入

程序会在openConnection方法处进行URL解码

补丁分析

https://github.com/spring-projects/spring-framework/commit/0e28bee0f155b9bf240b4bafc4646e4810cb23f8#diff-ca3a08ce8b5af11bfc5f03aa7f426cd9