1、概念
总的来说就是攻击者利用特定的输入来读取服务器上的任意文件内容。
任意文件读取漏洞通常出现在Web应用程序中,当应用程序没有正确过滤用户输入的文件路径时,攻击者就可以通过构造特定的路径来读取服务器上的任意文件。
2、任意文件读取漏洞常见触发点
(1)文件上传功能
(2)文件下载功能
(3)日志文件查看功能
(4)配置文件读取功能
3、常见文件路径绕过技巧
(1)使用相对路径(如 ../
)来遍历文件系统
(2)使用绝对路径(如 /etc/passwd
)直接访问特定文件
(3)使用特殊字符(如 NULL
字符 %00
)来截断路径
4、任意文件读取漏洞的检测与利用
(1)检测任意文件读取漏洞
<1>识别潜在的任意文件读取功能
找到应用程序中可能涉及文件读取的功能,例如文件下载、日志查看等
<2>测试文件路径输入
尝试在这些功能中输入不同的文件路径,观察应用程序的响应。例如:
../etc/passwd/etc/passwdC:\Windows\System32\drivers\etc\hosts(Windows 系统)
<3>检查错误信息
如果应用程序返回错误信息,可能会泄露文件路径或文件内容。例如,如果返回“文件不存在”,说明路径是有效的,但文件不存在。
(2)利用任意文件读取漏洞
一旦确认存在任意文件读取漏洞,就可以利用它来读取关键文件,例如配置文件、日志文件或系统文件。
常见的目标文件:
/etc/passwd(Linux 系统用户信息)
/etc/shadow(Linux 系统用户密码)
/etc/hosts(主机名和IP地址映射)
C:\Windows\System32\drivers\etc\hosts(Windows 系统主机名和IP地址映射)
C:\Windows\System32\config\SAM(Windows 系统用户密码)
C:\Windows\win.ini(Windows 系统配置文件)
C:\Windows\repair\sam(Windows 系统用户密码备份)
5、绕过路径限制
如果应用程序对路径进行了限制,可以尝试以下技巧来绕过这些限制:
(1)路径截断
使用特殊字符(如 NULL
字符 %00
)来截断路径。例如:
../../../../etc/passwd%00../../../../etc/passwd%00.jpg
(2)路径遍历
使用多个 ../
来遍历文件系统。例如:
../../../../etc/passwd../../../../../../../../etc/passwd
(3)绝对路径
直接使用绝对路径来访问文件。例如:
/etc/passwdC:\Windows\System32\drivers\etc\hosts
6、示例
假设我们发现了一个文件下载功能,URL如下:
http://example.com/download.php?file=example.txt
就可以尝试以下路径来检测任意文件读取漏洞:
http://example.com/download.php?file=../../../../etc/passwd
http://example.com/download.php?file=C:\Windows\System32\drivers\etc\hosts
如果应用程序没有正确过滤输入,你可能会成功读取到 /etc/passwd 或C: \Windows\System32\drivers\etc\hosts 的内容
7、例题
NSSCTF
【SWPUCTF 2024 秋季新生赛】PHP 躲猫猫
开启题目是让传参
不安全就直接用GET随便传一个值1看看
POST方法会把参数放到body里面,不会直接显示在URL上,所以更加安全
所以用POST传参得到一个提示
然后得到了源码
$NSS=$_POST['NSS'];
$ATM=$_GET['CTF'];
$CTF=$_GET['ATM']
从超全局数组$_POST中获取NSS的表单字段值,并赋值给$NSS; (POST传参NSS的值);
从超全局变量$_GET中分别获取CTF和ATM的URL参数值,并分别赋值给$CTF和$ATM。
审了一下主要是中后部分:
if ($CTF!=$ATM ){
判断如果$CTF是否等于$ATM
if (is_string($CTF)&&is_string($ATM)){
判断$CTF和$ATM是否都为字符串
if (md5($ATM)==md5($CTF)){
再判断$CTF和 $ATM的MD5哈希值是否相等
include($NSS);//f1ag在/f1ag里面,快通过include拿到它
以上条件都满足,执行 include($NSS),尝试包含$NSS指定的文件
}else{echo '诶嘿,但是我就是要让ATM==CTF,不然你就别想拿到f1ag,不服进nss来揍我';
这个是两个变量的哈希值不相等时的报错
}else{echo '不准无脑用数组,实打实的学才能学得好';
这个是两个变量不是字符串时的报错
}else{echo 'ATM怎么能是CTF呢';
如果两个变量(字符串)相等时的报错
if ($NSS=='I love CTF'){echo $f1agfile;
}
如果变量$NSS的值是 I love CTF,输出变量$f1agfile 里的值
那就先传一个I love CTF看看变量$f1agfile里的东西是什么
提示flag在f1ag.php里面,用include查找
所以这题的关键就在这里
当$ATM与$CTF的MD5哈希值相等时,执行include($NSS),用来包含$NSS的指定文件,
而这里的提示flag在 /f1ag 文件中就是暗示包含的$NSS指定文件是 /f1ag 就能拿到flag
所以思路就是用GET传参传入两个MD5哈希值相等的不同字符串分别赋值给ATM和CTF;
再用POST传参传入NSS使之等于指定文件 /f1ag 即可
然后我让AI给了我两个MD5值相等的字符串
但是执行后发现没有绕过
又让它给我重新找了两个但发现还是不行
只好去看看博客,然后发现大家都是用的相同的一组:
240610708QNKCDZO
这一组的MD5哈希值的确相等,但执行发现可以绕过
回去重新问了一下AI,问题出在哈希冲突,也就是找到哈希值相等的两个字符串不容易
这么说也就是其实它给我的那两个字符串的MD5哈希值并不相等,而我追问了一下事实也的确如此
只能说 ,六百六十六
这样一来就需要记一下这组MD5哈希值相等的字符串了
【MoeCTF 2022】baby_file
这题我也是醉了,写了一早上结果忘记保存了,下午回来没了。。。
重新写吧
还是先审一下代码
判断是否含有GET传参传入file的参数,并把数组$_GET['file']的值传递给变量$file;
include($file)表示函数include()包含指定变量文件$file并执行;
然后如果if条件不成立(没有通过URL传递参数file),执行else分支;
highlight_file()函数用于显示文件源代码,并高亮;
_FILE_是一个PHP魔术常亮,表示显示文件当前路径和文件名
也就是如果没有通过URL传递file参数,那么显示当前脚本文件的源代码,并进行语法高亮。
这里思考片刻后锁定php伪协议:
php://filter是 PHP 提供的一种伪协议,用于对数据流(stream)进行过滤和转换。它允许操作者在读取或写入文件、网络资源等数据流时,对数据进行预处理或后处理
比如现在读一下index.php:
得到一对加密,用base64解码一下
得到和网页一样的源码
说明当前网页所在目录就是Index.php
说明伪协议过滤、转换数据流可行
那就把目录替换为flag.php
下面先给出payload:
/?file=php://filter/read=convert.base64-encode/resource=flag.php
总的来说这是构造的GET请求,就刚对代码的分析可以知道 php://filter/read=convert.base64-encode/resource=flag.php 作为file的参数值,需要知道的是,
php://filter协议的标准语法是 :
php://filter<filter_name>=<filter_params>/resource=<resource>
所以read是指定要使用的过滤器;
convert.base64-encode是过滤器的参数;
flag.php则是要处理的资源。
总的来说就是用这个协议,告诉PHP:使用convert.base64-encode过滤器,对flag.php文件的内容进行处理,PHP会读取flag.php文件的内容,并将其进行Base64编码然后输出
最后执行,得到base64编码
解码得到flag