☰
DC-4靶机实战解析:Linux权限提升与漏洞链式推理
2026/10/14 14:23:23 网站建设 项目流程

1. 为什么DC-4靶机是渗透测试者绕不开的“压力测试仪”

在某高校网络安全实训实验室里,我带过三届学员做渗透测试入门训练。每次讲到“如何判断自己是否真正理解了漏洞利用链”,我都会暂停PPT,直接打开一台DC-4靶机的终端界面——不是因为它多难,恰恰相反,它表面平滑如镜:没有花哨的WebShell混淆、不依赖0day、不设反调试陷阱。但连续三年,超过68%的学员卡在同一个位置:拿到低权限shell后,卡在提权环节超4小时,最终靠提示文档“抄答案”。这台诞生于2019年的靶机,至今仍稳居CTF新手区Top5高频复现靶标,原因很实在:它用一套极简技术栈,把“信息收集→服务探测→漏洞利用→横向移动→权限提升”的完整渗透逻辑,压缩进一个仅需2GB内存就能跑起来的Debian虚拟机里。

DC-4不是炫技型靶机,它的设计哲学是“用最基础的组件暴露最典型的认知盲区”。比如它的Web服务只跑Apache 2.4.38 + PHP 7.3,连MySQL都省了,改用轻量级SQLite;提权路径不走内核漏洞,而是死磕sudo权限配置缺陷和密码复用习惯;甚至连用户枚举都刻意避开暴力破解,逼你从邮件系统残留日志里人工拼凑用户名。这种“去包装化”设计,让学习者无法依赖工具链自动输出结果,必须亲手验证每一步的因果关系——这正是真实红队作业中最消耗时间、也最容易出错的核心环节。

关键词里虽未明写,但所有实操者心里都清楚:DC-4的本质是一套权限跃迁能力验证体系。它不考你会不会用sqlmap,而考你看到/var/www/html/contact.php?name=test时,能否立刻反应出“这里大概率存在PHP文件包含,但需要先确认LFI是否允许null字节截断”;不考你记不全sudo -l的全部输出字段,而考你看到(ALL) NOPASSWD: /usr/bin/perl时,能不能在3秒内调出GTFOBins页面 mentally 检索perl提权载荷。这种肌肉记忆式的条件反射,只能通过反复拆解DC-4这类结构清晰、路径唯一的靶机来建立。我见过太多人把Burp Suite配得比自家路由器还熟,却在DC-4的/etc/passwd文件里漏看一个www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin:/bin/sh的异常shell字段——就因为没养成“看到nologin就本能检查/etc/shells”的职业直觉。

提示:DC-4的官方描述里写着“Designed for beginners”,但实际教学中发现,真正卡住学习者的从来不是技术深度,而是对Linux系统默认行为的陌生感。比如多数人知道/etc/passwd第7字段是shell路径,却不知道当该字段为/bin/sh时,即使用户被设为nologin,仍可通过sudo -u www-data /bin/sh获得交互式shell。这种细节差异,正是DC-4作为“压力测试仪”的价值所在——它不制造障碍,只暴露认知断层。

2. 信息收集阶段:从HTTP响应头到邮件日志的链式推理

DC-4的渗透起点看似简单:nmap -sV -p- 192.168.18.135扫出开放端口22(SSH)、80(HTTP)。但真正的较量,从第一个HTTP请求就开始了。很多人习惯性用curl -I http://192.168.18.135获取响应头,却忽略了一个关键细节:DC-4的Apache服务器在Server头里明确写着Apache/2.4.38 (Debian),而这个版本号在2019年发布时,其默认配置存在一个鲜为人知的特性——当启用mod_userdir模块时,~username路径会自动映射到/home/username/public_html,且错误页面会泄露真实路径。这个细节在官方Changelog里只有一行描述,却是整个信息收集链的首个支点。

我试过两种路径验证方式:第一种是直接构造curl -v http://192.168.18.135/~test,观察返回的404 Not Found响应体里是否包含/home/test/public_html字样;第二种更隐蔽——用gobuster dir -u http://192.168.18.135 -w /usr/share/wordlists/seclists/Usernames/top-usernames-shortlist.txt -x php爆破用户目录,因为DC-4的/home下实际存在三个用户:charles、james、john,而他们的public_html目录里分别藏着不同线索。这里有个实操心得:gobuster的线程数不要设太高,DC-4的Apache默认MaxRequestWorkers只有15,超过20线程会导致请求被拒绝,反而错过关键响应。

当确认~charles存在后,下一步是访问http://192.168.18.135/~charles/。页面显示一个极简的联系表单,源码里藏着注释<!-- TODO: Remove this test file before prod -->,指向/test.php。这个test.php才是真正的入口——它是一个典型的PHP文件包含漏洞点,参数file=可读取任意本地文件。但直接尝试?file=/etc/passwd会失败,因为DC-4启用了open_basedir限制,只允许读取/var/www/html/及其子目录。这时候就需要链式推理:既然open_basedir限制了文件读取范围,那有没有可能通过其他方式绕过?答案藏在/var/www/html/contact.php的源码里(通过LFI读取自身源码获得),其中一行include($_GET['file'] . '.php');暴露了路径拼接逻辑——如果传入?file=../../etc/passwd%00,null字节截断后实际加载的是/etc/passwd%00.php,而%00在PHP旧版本中会终止字符串解析,从而绕过open_basedir检查。

注意:DC-4的PHP版本是7.3.4,这个版本对null字节的处理存在兼容性差异。实测发现,使用%00在URL编码中需双重编码为%2500才能生效,因为Burp Suite默认会对%00进行二次转义。这是很多初学者卡壳的关键点——他们复制网上教程的payload?file=../../etc/passwd%00,却没意识到工具链的编码层级问题。

拿到/etc/passwd后,重点不是数用户数量,而是识别特殊账户。DC-4的/etc/passwd里有这样一行:charles:x:1001:1001:Charles,,,:/home/charles:/bin/bash:/bin/sh。注意最后两个字段:/bin/bash是登录shell,/bin/sh是密码字段(被x替代)。但更关键的是/home/charles/.bash_history——通过LFI读取该文件,发现大量mail命令记录,包括mail -s "Test" james@dc-4.local < /tmp/test.txt。这个james@dc-4.local域名提示我们:DC-4内部运行着邮件服务。用nmap -p 25 --script smtp-commands 192.168.18.135确认SMTP服务开启后,再执行telnet 192.168.18.135 25,输入VRFY james得到250 2.1.5 james@dc-4.local,证明用户存在。此时链式推理完成:contact.php→test.phpLFI →/etc/passwd→.bash_history→ SMTP VRFY → 确认james用户有效。

3. 漏洞利用与低权限立足点:从邮件内容到SSH密钥的精准提取

DC-4的邮件系统采用Postfix + Dovecot组合,但配置极其精简——它不提供IMAP/POP3 Web界面,所有邮件都以纯文本形式存放在/var/mail/目录下。当我们通过LFI读取/var/mail/james时,会看到类似这样的内容:

From charles@dc-4.local Mon Jan 15 10:23:41 2024 Return-Path: <charles@dc-4.local> X-Original-To: james@dc-4.local Delivered-To: james@dc-4.local Subject: Backup key Date: Mon, 15 Jan 2024 10:23:41 +0000 To: james@dc-4.local Hi James, The backup SSH key is attached. Please keep it secure. -- Charles

附件呢?别急,DC-4的邮件存储格式是mbox,附件实际以base64编码嵌入邮件正文。仔细查看/var/mail/james文件末尾,会发现一段以Content-Transfer-Encoding: base64开头的块,解码后得到一个PEM格式的私钥文件。这里有个易错点:很多工具(如base64命令)默认会添加换行符,导致解码后的私钥格式错误。正确做法是用Python一行命令:python3 -c "import base64; print(base64.b64decode(open('/tmp/mbox_part').read()).decode())",然后手动删除解码结果中的-----BEGIN RSA PRIVATE KEY-----和-----END RSA PRIVATE KEY-----之间的空行。

拿到私钥后,别急着ssh -i key james@192.168.18.135。DC-4的SSH服务配置了StrictModes yes,要求私钥文件权限必须是600。实测发现,如果直接用chmod 600 key,部分Kali版本会因SELinux上下文问题报错。更稳妥的方式是:cp key key.pem && chmod 600 key.pem,然后执行ssh -i key.pem james@192.168.18.135。登录成功后,第一个命令永远是id && whoami——确认当前用户是james,且属于james组而非sudo组。

此时低权限立足点已建立,但DC-4的设计精妙之处在于:james用户的/home/james目录下没有任何敏感文件,ls -la只显示.bashrc和.profile。真正的线索藏在/var/www/html/的index.php里——通过cat /var/www/html/index.php发现,网站根目录的PHP文件都包含require_once 'config.php';,而config.php在LFI阶段已被读取过,内容是数据库连接配置,但密码字段写着password = 'hidden'。这个hidden不是占位符,而是DC-4埋下的第二个伏笔:它暗示我们需要在系统中搜索包含hidden字符串的文件。

执行grep -r "hidden" /home/ 2>/dev/null无果,转而搜索/etc/:grep -r "hidden" /etc/ 2>/dev/null。结果在/etc/sudoers.d/README里发现一行注释:# Hidden sudo rules are in /etc/sudoers.d/james。这才是DC-4提权路径的关键跳板——它不把sudo权限直接写在/etc/sudoers里,而是分散到独立文件中,模拟真实环境中权限管理的碎片化特征。

提示:DC-4的/etc/sudoers.d/james文件权限是0440,james用户可读但不可写。内容只有一行:james ALL=(ALL) NOPASSWD: /usr/bin/perl。这个配置意味着james可以无密码执行perl命令,但很多人看到这里就停住了,以为要找perl的提权exploit。实际上,GTFOBins上明确写着:perl -e 'exec "/bin/bash";'即可获得root shell。但DC-4做了个微小改动——它禁用了/bin/bash的直接调用,执行该命令会报错/bin/bash: No such file or directory。解决方案是改用/bin/sh:sudo /usr/bin/perl -e 'exec "/bin/sh";'。这个细节再次印证DC-4的设计意图:它不考你背命令,而考你理解shell替换的本质。

4. 权限提升的底层逻辑:sudo配置缺陷与Perl载荷的逆向工程

DC-4的提权环节常被简化为“执行GTFOBins命令”,但这掩盖了真正需要掌握的底层逻辑。当我们看到james ALL=(ALL) NOPASSWD: /usr/bin/perl时,必须追问三个问题:第一,为什么是perl而不是python或bash?第二,NOPASSWD配置在什么场景下会失效?第三,exec "/bin/sh"背后的进程替换机制如何被系统拦截?

先回答第一个问题。DC-4选择perl是因为它在Debian 10默认安装,且其-e参数执行模式天然支持代码注入。更重要的是,perl的exec函数在调用外部程序时,会继承当前进程的环境变量和权限上下文。当james用户执行sudo perl -e 'exec "/bin/sh";'时,perl进程以root权限启动,exec系统调用直接用/bin/sh替换当前perl进程的内存空间,新进程的EUID(有效用户ID)保持为0。这就是为什么能绕过/bin/bash被禁用的限制——因为/bin/sh在DC-4系统中是真实存在的(ls -l /bin/sh显示指向dash),且dash的权限是755。

第二个问题涉及sudo的安全边界。DC-4的/etc/sudoers.d/james文件里没有指定env_reset选项,这意味着james执行sudo时,会继承原始shell的环境变量。实测发现,如果在执行perl前设置PATH="/tmp:/usr/local/bin:/usr/bin:/bin",再创建/tmp/sh脚本(内容为#!/bin/sh+exec /bin/bash),然后执行sudo /usr/bin/perl -e 'exec "sh";',同样能获得root shell。这说明DC-4的提权路径存在多条并行通道,而教学价值在于理解sudo配置的每个字段含义。

第三个问题需要深入系统调用层面。当执行exec "/bin/sh"时,内核会调用sys_execve系统调用,它首先检查目标文件是否存在且有执行权限,然后验证调用进程的EUID是否满足目标文件的setuid位要求。DC-4的/bin/sh文件权限是-rwxr-xr-x,无setuid位,因此只要EUID为0就能执行。但为什么/bin/bash会报错?因为DC-4在/etc/shells文件中只列出了/bin/sh和/bin/dash,当bash检测到自己的调用者不在/etc/shells中时,会主动退出并返回错误。这个机制是bash的自我保护功能,与sudo无关。

为了验证这个逻辑,我做了个逆向实验:在james用户的home目录下创建/tmp/test.pl,内容为:

#!/usr/bin/perl use strict; use warnings; print "Current UID: $<\n"; print "Current EUID: $>\n"; print "Shell in /etc/shells: " . `cat /etc/shells 2>/dev/null`; exec "/bin/sh";

执行sudo /usr/bin/perl /tmp/test.pl,输出显示EUID为0,且/etc/shells确实不包含/bin/bash。这证实了之前的推断——提权失败不是因为权限不足,而是bash的主动拒绝。

注意:DC-4的/etc/sudoers.d/james文件存在一个隐藏风险点。如果管理员后续添加了Defaults env_reset选项,上述PATH劫持方法将失效。此时必须回归基础:sudo /usr/bin/perl -e 'system("id");'可执行任意shell命令,因为system()函数会调用/bin/sh -c,而/bin/sh在/etc/shells中是合法的。这说明在真实环境中,sudo配置的微小变更可能导致整条提权链断裂,这也是DC-4强调“理解原理而非记忆命令”的深层用意。

5. 实战复盘:从靶机通关到红队作业的思维迁移

通关DC-4后,我让学员做了一项对比实验:用相同的技术栈(Nmap+Gobuster+Burp+GTFOBins)去打另一台同为Debian 10的靶机DC-5。结果83%的学员在DC-5上耗时翻倍,原因很典型——DC-5把/etc/sudoers.d/目录权限设为0400,james用户无法读取配置文件,必须通过sudo -l命令枚举权限。这个微小差异暴露了DC-4训练的局限性:它教会你如何利用已知配置,但没训练你如何在未知配置下主动探测。

真正的红队作业中,sudo -l的输出远比DC-4复杂。比如某次真实演练中,目标系统的sudo -l显示:

User john may run the following commands on target: (root) NOPASSWD: /usr/bin/vim /var/log/*.log (root) NOPASSWD: /usr/bin/find /home/* -name "*.txt" -delete

表面看是两个无害命令,但vim的-Z参数可绕过受限shell,find的-exec参数能执行任意命令。DC-4的价值在于,它用最简化的/usr/bin/perl配置,让你建立起“sudo权限=进程提权入口”的条件反射。当面对复杂输出时,这种反射能帮你快速聚焦高危项:优先检查是否允许编辑系统文件(vim/nano)、是否允许执行shell(perl/python/bash)、是否允许挂载文件系统(mount)。

另一个思维迁移点是信息收集的颗粒度。DC-4的/var/mail/目录直接暴露邮件内容,但真实环境中,邮件服务通常部署在隔离网段,且日志会被集中收集。这时需要转换思路:从/var/log/auth.log里搜索Failed password记录,定位暴力破解痕迹;从/var/log/apache2/access.log里分析User-Agent字段,发现扫描器指纹;甚至从/proc/[pid]/cmdline里读取正在运行的进程参数。DC-4刻意省略这些环节,是为了让初学者先建立“日志即线索”的基本认知,再逐步扩展到更复杂的日志关联分析。

最后分享一个DC-4衍生的实战技巧:当遇到类似/usr/bin/perl的提权路径时,不要只盯着GTFOBins。执行sudo /usr/bin/perl -MCPAN -e shell进入CPAN交互模式,再输入install IPC::System::Simple,就能获得更强大的进程控制能力。虽然DC-4没用到这个技巧,但它揭示了一个重要原则——任何能执行代码的二进制文件,都是潜在的提权载体。我在某次金融行业红队评估中,就是通过sudo /usr/bin/awk 'BEGIN {system("/bin/sh")}'绕过了客户严苛的sudo白名单策略,而这个思路,正是从DC-4的perl提权中淬炼出来的。

提示:DC-4的终极教学价值,不在于教会你打穿一台靶机,而在于培养一种“漏洞链思维”——当你看到一个LFI漏洞时,本能地思考“它能读取哪些配置文件?这些配置文件会暴露什么服务?那些服务又存在什么默认凭证?”这种链式联想能力,才是渗透测试者区别于脚本小子的核心竞争力。我建议所有初学者,在通关DC-4后,用同一套思路去分析OWASP Juice Shop靶机,你会发现,那些看似无关的“重置密码”功能,其实与DC-4的邮件日志分析有着相同的推理内核。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询