从任意文件下载到命令执行

前言

上两周去北京打攻防了,第一周主要围绕母公司打,结果发现打不动,后面就打了百分百控股的子公司,摸了一个靶标的0day直接怼进内网了,后面看同事内网各种花里胡哨的操作的时候,我人都傻了。本来打完后,想着要去休息一下,打算调休的,领导临时安排了一个渗透任务。

任务的要求比较简单,能挖多少漏洞就挖多少,客户那边的系统,马上要被总部检查了,因此需要我们先测试一波。

渗透开始

分到我手上的目标一共三个端口,且都提供了测试账号。

链接
http://x.x.x.x:8080/
http://x.x.x.x/
https://x.x.x.x/

针对8080端口的测试

在进行目录遍历的时候,发现存在WEB-INF目录,因此判断出当前web系统是通过java开发的,中间件是tomcat
image

在把网站的每一个功能点都点击后,发现好像没啥有用的东西。

image

不过测试的时候发现了一些一级目录,如:Portal、idata、SZCMCCX等等

image

通过tomcat部署的网站一般会有多个应用,那么较大几率在webapps目录下会存在这些应用的备份文件,也就是源码包。

尝试访问了Portal.warPortal.zipSZCMCCX.war等一系列的压缩文件,发现都是404,很难受啊。

image

似乎是在此之前,网站就已经被测试过几轮了,因此很难发现一些比较常规的漏洞。

发现疑似任意文件下载的接口

在对burpsuitesite map进行检查时,发现了一个非常像任意文件下载漏洞的接口。

image

于是对其添加有效的Cookie之后,就尝试路径穿越。

因为不确定当前的web应用权限有多高,所以就不尝试路径穿越读取系统配置文件,这里我选择的是读取home.jsp的源码。

image

成功读到home.jsp后,第一反应是想办法读取到配置文件。

这里的配置文件就有两类了,一般是web应用的配置文件和tomcat的配置文件。

web应用的配置文件通常放在/webapps/(web应用名)/WEB-INF/classes/下,以.properties后缀的文件。

tomcat的配置文件一般是读取/Conf/tomcat-users.xml

这里我就直接开始路径拼接+路径穿越了。

image

首先先尝试fuzz数据库配置文件,一般情况这类文件名一般是db.properties或者database.properties等等,形式有很多种。

image

读取成功,但是发现数据库的账号密码被加密了,猜测是AES加密,原因是登录窗口的账号密码就是用AES加密的,不过这里对数据库账号密码加密所使用的密钥(key)偏移量(iv)是不知道的,也就难以进行解密。

尝试读取tomcat的配置

image

读取成功,但是发现web应用(manager/html)是404,那就难受了。

image

获取到网站整站源码

后面无意将参数值置空后,居然将物理路径爆了出来。

image

此时大胆猜测,该网站应用是外包商直接将中间件,jdk,web应用等全部一次性打包,然后再给甲方进行部署的。

那么也就是说C盘路径下有较大几率是存在一个名字可能叫做Portal3ND_V4.zipPortal3ND_V4.rarPortal3ND_V4.rarPortal3ND_V4.exePortal3ND_V4.iso等压缩文件的。如果是exe的话,名字较大几率不是Portal3ND_V4.exe,具体原因我也不知道,这是根据我自己的经验来判断的。

这里我就直接尝试路径穿越,尝试下载这些可能存在的压缩文件。

结果美梦成真,成功拿到网站整站的源码。

效果

image

此时在webapps目录下发现的确存在我之前猜测的war包,但是由于tomcat配置的缘故,这里无法直接访问下载。

image

拿到源码后,肯定是得想方设法的获取到权限,以及挖掘到更多的漏洞。

现实是,好像根本没有上传、只找到了一个像RCE的点,但是由于web.xml里面没有引入,因此也就无法尝试去RCE。

image

这里tablename和url可控。

那么理论上只要闭合的好,就能rce成功,如下图所示

image

image

image

最后也确定了url这个值是可控的,通过post传入,但是这里的功能还写到web.xml中,因此也就无法利用。

image

审计到多个SQL注入漏洞

此时只能想办法通过注入漏洞去获取权限了,因此尝试审计SQL注入,不过很快发现,注入的确很多。

image

此处uc参数就存在注入漏洞。

image

权限是dba权限,因此尝试能不能直接利用sqlmap进行osshell的操作。

image

不过这里osshell失败了,失败的原因较大几率是由secure_file_priv的值造成的。

有尝试过去跑数据,拿到高权限的账号,不过客户的数据库经常奔溃,这里也就只能放弃通过注入漏洞,拿到高权限账号了。

混日子水漏洞(任意用户登录)

发现此处还是存在一个长得很像任意用户登录的漏洞,不过也可以叫做用户枚举漏洞。

image

存在漏洞的文件,还是上面那个注入的文件,这里当用户名是真实存在时,即可看到网站的站点设置。

admin账号存在时,左侧出现站点设置。

image

test账号不存在时,左侧无站点设置。

image

使用客户提供的测试账号进行登录时,仍然也是可以的。

image

水一个反射性的XSS漏洞

这里就直接贴导致xss存在的漏洞源码了,就不放截图和完整代码了。

1
2
3
4
5
String userurl=request.getParameter("uc");  
users=userurl;
...

<p id="uc"/><%=users%></p>

image

发现硬编码漏洞

发现mysql的账号密码

image

发现postgresql的账号密码

image

发现外包公司员工的邮箱账号密码

image

测出水平越权漏洞

检查的时候,发现还有一处水平越权,通过cookie来发现的。
数据包中有有userId参数和userInfoId参数
参数值是一个整型
数据包如下:

1
2
3
4
5
6
7
8
9
GET /SZCMCCX/NavConfigController?userId=2219 HTTP/1.1
Host: x.x.x.x
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=F182755597AE19ECB1A55DB4AD508C09; userInfoId=2219
Connection: close

通过修改userId的值,页面响应信息是无变化的
后面发现,页面的响应内容是由userInfoId的值决定了

后面遍历的时候,发现,可以通过遍历userInfoId的值,获取到其他用户在另外一个系统的凭证。

后面开发说漏洞修复了,我一看,只是把userInfoId的值进行了加密,盲猜是AES加密,因为它前端用的就是aes加密,所以我猜它可能为了偷懒,所以就继续使用AES了

漏洞修补前

admin的身份凭证

image

admin2的身份凭证

image

在我收到复测通知后再看漏洞

image

实际上只是对userInfoId的值进行了加密,并且我尝试了多次的退出并且重新登录,发现测试账号的userInfoId的值是没有任何变化的,也就是说如果它是AES加密的话,那么key(密钥)iv(偏移量)是写死在代码里面了的,也就是硬编码漏洞。

那么这里的话,实际上水平越权仍然没被修复。

image

为什么会这样判断,即把userInfoId的值置空以后,也就明白了。

即这里的页面回显的内容判断仍是通过userInfoId的值来判断的,而不是通过JSESSIONID

此时已经混了一堆漏洞了,在8080端口发现,已经很难再获取到有用的东西了。因此换端口再战。

针对443端口的测试

443端口是一个qlik scene

image

尝试搜索过历史漏洞,发现好像没啥历史漏洞可以直接利用,因此直接就用测试账号登录进去了。

进来后发现,这玩意似乎能够创建数据库连接,并且能对数据库的内容进行查看和管理

image

尝试连接mysql

image

账号密码填写2.1.6获取到的mysql连接账号密码。

芜湖,连接成功。

image

因为之前的时候通过注入漏洞,已经发现拿不到权限了,所以这里也就不采取udf这类的提权方法了。

尝试解密上面的高权限账号的密码,解密失败,所以我直接放弃了。哈哈哈,直接写了一个mysql弱口令。

尝试连接postgresql

image

这里连接成功后,我有想到可以利用postgresql获取权限,结果我死活找不到哪里能够去执行sql语句。

尝试利用CVE-2019-9193获取权限

后面我眼睛终于好使了,也就看到了Filter data

在这里去执行sql语句的时候,一定得尝试完美闭合语句,不然一定会出错

image

CVE-2019-9193的payload如下:

1
2
3
4
5
6
7
8
9
# 删除并创建用于保存系统命令执行结果的表 
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);

# 命令执行测试
COPY cmd_exec FROM PROGRAM 'whoami';

# 查看结果
SELECT * FROM cmd_exec;

这里直接就命令执行了,权限是system。

1=1 limit 50;COPY cmd_exec FROM PROGRAM 'whoami';select * from public.cmd_exec where 1=1

image

最后的漏洞报告

成果如下:

image

总结

最开始跑注入的时候,跑到一半,不出数据了,我以为客户秒修漏洞,但实际上是客户数据库崩了。在当我拿到了数据库连接账号密码,一直连不上数据库,我以为是站库分离,ip地址不是localhost,但是用注入查了一下当前的数据库连接用户,回显是root@localhost,一度让我怀疑这是什么破烂环境。实际上是客户的mysql数据库崩了,后面的时候才连接上。

假设这里的测试环境的系统是linux,即使的站库分离,在我找不到数据库的ip地址的情况下,我可以通过读取linux系统的网卡文件,得到当前服务器的ip,然后c段一个个ip试,也是有较大几率连上这个mysql的。但是windows系统的话,真就特别难了。很多时候,读系统配置也没啥作用。比如linux可以读取/用户/.bash_hostry,找用户的敏感操作,较大几率是非常容易拿到源码的,但是windows的话,我知识点不够庞大,也不太清楚哪些文件有没有记录用户的敏感操作。

在利用任意文件下载漏洞的时候,在尝试获取网站源码之前,我有尝试去找过upload.jsp这类具备上传功能的文件。实际上,这套系统似乎还没写完,许多功能点写了根本没用。upload.jsp根本不存在,根本就无上传的功能点,不过也可以当作一个思路进行积累了。

对了,你问我为什么80端口为什么不测试了,客户说修不过来了,所以我就放弃了,并且权限都拿到,垃圾洞也就没必要混了,嘿嘿嘿。

image

Author: jdr
Link: https://jdr2021.github.io/2021/12/31/从任意文件下载到命令执行/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.