题目平台:buuctf
题目名称:[安洵杯 2019]easy_serialize_php
本题涉及知识点
-
extract() 变量覆盖
-
PHP反序列化:
- 正常情况下,序列化的对象是一个类的实例,但实际上,数组也能序列化
- 字符逃逸 (知识点学习链接 )
<?php$function &#61; &#64;$_GET[&#39;f&#39;];function filter($img){$filter_arr &#61; array(&#39;php&#39;,&#39;flag&#39;,&#39;php5&#39;,&#39;php4&#39;,&#39;fl1g&#39;);$filter &#61; &#39;/&#39;.implode(&#39;|&#39;,$filter_arr).&#39;/i&#39;;return preg_replace($filter,&#39;&#39;,$img);
}if($_SESSION){ unset($_SESSION);
}$_SESSION["user"] &#61; &#39;guest&#39;;
$_SESSION[&#39;function&#39;] &#61; $function;extract($_POST);if(!$function){echo &#39;source_code&#39;;
}if(!$_GET[&#39;img_path&#39;]){$_SESSION[&#39;img&#39;] &#61; base64_encode(&#39;guest_img.png&#39;);
}else{$_SESSION[&#39;img&#39;] &#61; sha1(base64_encode($_GET[&#39;img_path&#39;]));
}$serialize_info &#61; filter(serialize($_SESSION));if($function &#61;&#61; &#39;highlight_file&#39;){highlight_file(&#39;index.php&#39;);
}else if($function &#61;&#61; &#39;phpinfo&#39;){eval(&#39;phpinfo();&#39;);
}else if($function &#61;&#61; &#39;show_image&#39;){$userinfo &#61; unserialize($serialize_info);echo file_get_contents(base64_decode($userinfo[&#39;img&#39;]));
}
?>
一、审计代码
先分析与变量$function
有关的代码
$function &#61; &#64;$_GET[&#39;f&#39;];if(!$function){echo &#39;source_code&#39;;
}f($function &#61;&#61; &#39;highlight_file&#39;){ highlight_file(&#39;index.php&#39;);
}else if($function &#61;&#61; &#39;phpinfo&#39;){ eval(&#39;phpinfo();&#39;);
}else if($function &#61;&#61; &#39;show_image&#39;){ $userinfo &#61; unserialize($serialize_info);echo file_get_contents(base64_decode($userinfo[&#39;img&#39;]));
}
&#xff08;1&#xff09; 令/index.php?f&#61;phpinfo&#xff0c;查看phpinfo中的隐藏信息&#xff08;2&#xff09; 发现d0g3_f1ag.php文件&#xff08;3&#xff09;最终肯定是需要/index.php?f&#61;show_image利用反序列化漏洞来获取flag
分析有关$_SESSION
部分的代码
if($_SESSION){unset($_SESSION);
}
$_SESSION["user"] &#61; &#39;guest&#39;;
$_SESSION[&#39;function&#39;] &#61; $function;extract($_POST);if(!$_GET[&#39;img_path&#39;]){$_SESSION[&#39;img&#39;] &#61; base64_encode(&#39;guest_img.png&#39;);
}else{$_SESSION[&#39;img&#39;] &#61; sha1(base64_encode($_GET[&#39;img_path&#39;]));
}$serialize_info &#61; filter(serialize($_SESSION));
function filter($img){$filter_arr &#61; array(&#39;php&#39;,&#39;flag&#39;,&#39;php5&#39;,&#39;php4&#39;,&#39;fl1g&#39;);$filter &#61; &#39;/&#39;.implode(&#39;|&#39;,$filter_arr).&#39;/i&#39;;return preg_replace($filter,&#39;&#39;,$img);
}$userinfo &#61; unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo[&#39;img&#39;]))
- 首先&#xff0c;粗略的过一遍代码&#xff0c;file_get_contents函数读取文件的内容肯定是
d0g3_f1ag.php
&#xff0c;因此base64_decode($userinfo[&#39;img&#39;])
的结果也得是d0g3_f1ag.php
。不会有sha1()
这个加密过程&#xff0c;也就是说$_GET[&#39;img_path&#39;]
变量为空&#xff0c;但这样,$_SESSION[&#39;img&#39;]
似乎是固定值base64_encode(&#39;guest_img.png&#39;);
-
还有一点extract($_POST);
是可以通过提交post请求&#xff0c;覆盖当前已经定义了的变量&#xff0c;也就是说&#xff0c;是能改变$_SESSION[&#39;function&#39;]
与$_SESSION["user"]
的值
-
同时&#xff0c;本题存在对序列后的字符串进行过滤处理&#xff0c;也就是序列化后的字符串是会减少的情况&#xff0c;导致与对应的长度不匹配&#xff0c;出现无法反序列化。这里是存在字符逃逸漏洞的&#xff01;&#xff08;知识点学习链接 &#xff09;
二、漏洞利用
- 发现flag文件在
/d0g3_fllllllag
中 /d0g3_fllllllag
base64后为L2QwZzNfZmxsbGxsbGFn
- 得到flag{61011a5f-08cc-4884-9666-6b639382f93b}
三、反思总结
题目有两个坑的点
-
第一个&#xff0c;why post请求中会是 _SESSION[user]
而不是_SESSION["user"]
&#xff0c;这有涉及到啥知识&#xff0c;是真搜不到。。。。。。&#xff08;求求大佬&#xff01;&#xff01;&#xff01;&#xff09;
-
第二个&#xff0c;为什么post提交的参数_SESSION[function]提交的参数是;s:8:"function";s:10:"show_image";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
-
在看大佬的writeup之前我一直;s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
-
我不懂;s:8:"function";s:10:"show_image"
的意义所在。虽然有$_SESSION[&#39;function&#39;] &#61; $function;
这一步操作&#xff0c;我以为也想过改变$_SESSION[&#39;function&#39;]
的值后$function;
可能会跟着改变&#xff0c;但怎么可能&#xff01;改变也是改变到与$userinfo[‘function’]的值相同才符合题意啊&#xff01;&#xff01;&#xff01;
-
。。。。。。。。。。好了&#xff0c;我才把字码到这&#xff0c;突然灵光一闪。。。是的悟了。。
-
由于序列化后的字符串是a:3:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw&#61;&#61;";}
&#xff0c;注意&#xff0c;宝&#xff0c;开头是a:3
&#xff0c;代表的是反序列化的对象是数组&#xff0c;且有三个元素&#xff0c;所以我必须保障反序列后生成的数组有三个元素
-
实际上我也能这么写;s:8:"function";s:10:"wozaizheli";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
(只要不是过滤函数中数组里面的字符串即可&#xff09;