6

网鼎杯2020-小知识点

 2 years ago
source link: https://afkl-cuit.github.io/2020/05/11/%E7%BD%91%E9%BC%8E%E6%9D%AF2020-%E5%B0%8F%E7%9F%A5%E8%AF%86%E7%82%B9/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
2 years ago6 minutes read (About 902 words)  17 visits

网鼎杯2020-小知识点

在网鼎杯中遇见了许多令人迷惑的问题、以及不知道的知识,故在此记录。

php反序列化中对象属性问题

在这次的一道php反序列化的一道题中。我们要利用的属性被设置为了protected,这意味着我们的序列化字符串中将会出现%00这个不可见字符,但题目中ban掉了所有不可见字符,需要进行绕过。

我正当想着怎么绕过,突然有师傅说不必理会那个%00,利用的属性直接按照public得到的序列化字符串也可以被利用。
当时的我:???????我之前的一道ctf中,因为没有注意到某一个属性的可见性是private导致痛失一题。

故在这里尝试不同版本php的反序列化处理
尝试以下代码

<?php
echo phpversion().'<br>';

class test
{
    public $a;
    private $b;
    protected $c;

    public function __construct()
    {
        $this->a = 1;
        $this->b = 2;
        $this->c = 3;
    }

    private function outputAll()
    {
        echo 'a:'.$this->a.'<br>';
        echo 'b:'.$this->b.'<br>';
        echo 'c:'.$this->c;
    }

    public function __destruct()
    {
        $this->outputAll();
    }
}

if(isset($_GET['str']))
    $obj = unserialize($_GET['str']);
else
{
    $obj = new test;
    echo serialize($obj);
}

环境为linux加apache2
设置get参数为str=O:4:"test":3:{s:1:"a";i:1;s:1:"b";i:2;s:1:"c";i:3;}
分别获得以下输出

php:7.4-apache:
    7.4.5<br>a:1<br>b:2<br>c:3
php:7.3-apache:
    7.3.17<br>a:1<br>b:2<br>c:3
php:7.2-apache:
    7.2.30<br>a:1<br>b:2<br>c:3
php:7.1-apache:
    7.1.33<br>a:1<br>b:<br>c:
php:7.0-apache:
    7.0.33<br>a:1<br>b:<br>c:
php:5.6-apache:
    5.6.40<br>a:1<br>b:<br>c:

可以看到,在7.2以后的版本(包括7.2)php在进行反序列化处理时并没有对属性的可见性进行检验
这便是矛盾的来源,之后在进行反序列化时,一定要注意php的版本,这上述的情况可能会带来意想不到的漏洞。

php反序列化中的S类型

在一个对象被序列化后的字符串中的字符有特殊的含意
O:4:"test":3:{s:1:"a";i:1;s:1:"b";i:2;s:1:"c";i:3;}
在上面的字符串中,O为对象、s为字符串、i为数字…
这里要讲一种S类型,S类型指的是是已经被转义的字符串
在一个privateprotected的对象属性中,序列化后,会有特殊的字符

以上面的代码为例(PS:%00为hex值为00的字符)
序列化b为:s:7:"%00test%00b";i:2;
序列化c为:s:4:"%00*%00c";i:3;
可以看到,当在浏览器这么输入后,会向服务器发送不可见字符。

但对于S类型则没有必要了,将s替换为S后:
序列化b为:S:7:"\00test\00b";i:2;
序列化c为:S:4:"\00*\00c";i:3;
这样传入的是3个字符组成的字符串\00而不是00这个不可见字符

这么做的目的其实在这次的CTF便可以见得。有时候,服务器会BAN掉不可见的字符,防止这些字符导致系统错误。但对于php的反序列化字符串来说,S类型恰好绕过了这个限制。

目前就学到这么多(,之后靠复现来学习吧。
当时java的xxe试了半天没有出网,还以为payload的锅,结果复现发现一模一样的payload,buuoj可以出网(指靶机内网)。不知道为什么脑壳痛(
还有就是吐槽一下那个/web那个目录有点坑(以后先尝试去读一下httpd.conf
PS:php真是博大精深(((


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK