首页 / 资讯中心 / 文章详情

DC-4靶机实战解析:Linux权限提升与漏洞链式推理

DC-4靶机实战解析:Linux权限提升与漏洞链式推理 ★ FEATURED ARTICLE
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?nametest时能否立刻反应出“这里大概率存在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扫出开放端口22SSH、80HTTP。但真正的较量从第一个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%00null字节截断后实际加载的是/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 jamesdc-4.local /tmp/test.txt。这个jamesdc-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 jamesdc-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 charlesdc-4.local Mon Jan 15 10:23:41 2024 Return-Path: charlesdc-4.local X-Original-To: jamesdc-4.local Delivered-To: jamesdc-4.local Subject: Backup key Date: Mon, 15 Jan 2024 10:23:41 0000 To: jamesdc-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 james192.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 james192.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文件权限是0440james用户可读但不可写。内容只有一行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/shsudo /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/shexec /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后我让学员做了一项对比实验用相同的技术栈NmapGobusterBurpGTFOBins去打另一台同为Debian 10的靶机DC-5。结果83%的学员在DC-5上耗时翻倍原因很典型——DC-5把/etc/sudoers.d/目录权限设为0400james用户无法读取配置文件必须通过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参数可绕过受限shellfind的-exec参数能执行任意命令。DC-4的价值在于它用最简化的/usr/bin/perl配置让你建立起“sudo权限进程提权入口”的条件反射。当面对复杂输出时这种反射能帮你快速聚焦高危项优先检查是否允许编辑系统文件vim/nano、是否允许执行shellperl/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的邮件日志分析有着相同的推理内核。
阅读完成 · 觉得有帮助?
咨询建站