# Week1

# A Dark Room


查看网页源码就能拿到 flag

# 喵喵喵 ´・ﻌ・`


没有什么过滤,直接执行系统命令

# md5 绕过欸


经典 md5 绕过,不管是强比较还是弱比较,利用数组绕过即可

# HTTP 是什么呀


对基础 http 信息头和请求头的考察,按要求更改即可,其中 get 的内容中由于含有特殊字符,仅对特殊字符 url 编码即可

# upload


普通文件上传问题,在 png 文件中写入一句话木马,然后抓包修改后缀


显示传入成功后利用 uploads 这个目录去利用 1.php

# Aura 酱的礼物


这题涉及到了伪协议与 SSRF 漏洞的处理还有一些骚操作
首先 pan 的传入可以使用 data 伪协议来直接构造 Arua 这个内容;
challenge 即需要开头为 http://jamineaura.github.io 这个字符,又需要能利用 file_get_contents 函数读出含有 ' 已经收到 KengWang 的礼物啦 ' 这个字符串的内容。但是发现上述网址是无法利用的,也就无法通过日志包含等操作写入内容,骚操作就是利用当前题目网址,直接读取题目内容。这就转变成典型 ssrf 问题,通过 @ 就能让函数读取到指定网址;
最后的 gift 传入,通过 php://filter 伪协议就行了,读取 base64 编码后的 flag.php

解码就得到 flag

# Week2

# RCEisamazingwithspace


题目利用 \s 过滤了空白字符,所以无法利用 tab 键等来代替空格,这里可以通过 ${IFS} 来绕过:

成功拿到 flag

# 一起吃豆豆


检查网页源码,发现源码泄漏,在游戏结束的段落发现一段 base64 编码的字符串
直接解码即可拿到 flag

# 你听不到我的声音


shell_exec 不会直接输出执行结果,可以通过 > (流重定向符号)可以将内容写入指定文件,在 url 处查看文件内容

# ez_ser



反序列化永远的痛,想不明白,去复现官方 wp:
首先,入口一般为 __wakeup__destruct__construct
这里发现在 Crypto 中的 wakeup 方法和 getflag 方法都是无效的,需要利用 Misc 类中的 getflag 来实现 flag 获取;
发现可以通过 pwn 类来执行,但需要绕过对于 dusk 内容的判断,输入内容可以依靠 get 魔术方法,但触发需要利用不存在变量,题目中的不存在变量即为nononono;nononono; 而 nononono 存在于 re 类中,而 re 中存在的 tostring 魔术方法将在把对象当作字符串来使用时会自动调用,所以目标就切换成获得一个字符串;
字符串的获得方法就存在于 web 类中,把kw当作字符串输出,只需令kwre的对象,将kw当作字符串输出,只需令kw为re的对象,将 chou 赋值即可

# 所以你说你懂 MD5?



前两处比较很好绕过,第一个直接利用数组绕过
apple[]=1&banana[]=2

第二个利用转化后的 0e 开头 md5 值使 php 将其认为科学计数法来绕过字符串的弱比较(0e 开头字符串转化为 0)
appple=240610708&bananana=s878926199a

第三处是字符 md5 值的强比较,需要找到本身值不同但转化为 md5 值后相同的内容(fastcoll 或者 hashclash)
apppple=TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak&banananana=TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak

第四处需要利用哈希长度拓展攻击,利用脚本生成
https://github.com/luoingly/attack-scripts/blob/main/logic/md5-extension-attack.py
关于长度,是这么来的:

在这一部分生成 random 的过程中, random_bytes(16) 会随机产生 16 字节数据, bin2hex 函数将二进制字节转换成十六进制,由于一个字节是 8 位,所以 16 个字节共有 16X8 位,一个十六进制数有 4 位,所以一轮 bin2hex(random_bytes(16)) 能产生 32 个十六进制字符,进行 3 轮就是 96 个

拿到 name 和 md5 的值
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=cdae0001abf73a64129e2651ea28708a

# 数学大师



靠手算肯定不行,这一看就得写脚本,需要注意的是存在 session,要将 cookie 加上来进行循环求解
脚本如下:

import requests
import re
s=requests.session()
url="http://gz.imxbt.cn:20805"
response=s.get(url)
for i in range (50):
    preg=re.search(r'\d+[×÷\-\+\*\/]\d+', response.text)
    expression=preg.group(0).replace('×', '*').replace('÷', '//')
    answer=eval(expression)
    result={"answer": answer}
    response=s.post(url,data=result)
print(response.text)

拿到 flag

# Week3

# 滤个不停


第一重判定很好解决,直接将 incompetent 的内容定为 HelloWorld 就行;之后题目利用 foreach 循环来判断字符是否存在,需要包含's','e','v' 等内容,不能含有 'php://' 等伪协议;最后还需要 $Datch 所包含的文件名正确。这里涉及文件包含知识点,在不能利用伪协议的情况下,考虑到利用文件日志包含的方法来写入木马:

在 User-Agent 处写入一句话木马,通过 get 执行,获得所有文件名,抓取 flag

# 玩原神玩的


审计代码发现,第一部分通过 len 的长度等于array数组的长度这个判断后进入到ysopen函数中;当array数组的长度这个判断后进入到`ys_open`函数中; 当 tip 的内容若等于 "我要玩原神" 时就能进入到 dumpFlag 函数中;
dumpFlag 函数中 post 传入的 m 数组的长度被限制在了 2,分别赋值给aa和 b; 其中a的内容需要是"100a的内容需要是 "100%",b 的内容为 "love100%" 拼接上 $a 的 md5 值;
最后一部分所做的操作就是将 flag 的每一个内容转换成对应 ascii 码之后与当前位置进行异或处理,最后转化成对应 md5 值传入 flag 数组并以 json 的形式输出

一个个绕过,首先对于 len 的验证,由于 flag 的长度是 45(固定已知),随便填入 len 数组的内容使之长度为 45,再让 tip 为 "我要玩原神",最后通过加密方式,逆向解密

# ez_php_jail


审计发现 get 的参数名为 Jail_by.Happy ,在 PHP 版本小于 8 时,点号会被转化成下划线,需要利用 [ 来绕过,因为了解到,参数名中如果含有 [ , [ 就会被转换成 _ ,而 [ 后面跟的 . 号则会保持不变

关于判断 php 版本,这题将信息藏在了网页元素中
base64 解码:

访问即可了解到版本信息:

发现版本是小于 8 的,需要用到上述绕过

在后面的 Like_Jail 函数中,对可能的利用方式进行了过滤,但过滤了字母 a 和 s 之后发现很多查看目录或者访问文件的操作都失效了,翻了老半天以前的笔记才记起来还有 glob 函数可以看文件(glob 伪协议由于路径含有 a 所以也失效了),glob 函数利用的话也是通过没有被过滤的 highlight_file 函数来实现,因为要查找的 flag 文件也含有过滤字母 a,所以直接用通配符绕过:

由于 glob 返回的是一个列表,整个列表在网页上没有回显,不知道是因为什么限制,所以我直接取了第一项内容,成功拿到 flag

4. 复读机

复读机?SSTI!
测试一下都 fuzz 了什么关键词