SQL注入漏洞是Web层面最高危的漏洞之一,多年来一直霸占OWASP top10 首位。能一直高居首位,主要都是因为如果存在SQL注入漏洞,将导致严重的后果,拖库,挂马,都可能让你的站岌岌可危。
0x01:sql注入定义
本质:代码和数据不区分
成因:未对用户提交的数据进行校验或者有效的过滤,直接进行sql语句拼接,改变了原有语句的句意,传进数据库中运行。
0x02:常见的闭合方式
select * from user where id=$id;(数字型)
select * from user where id='$id';(字符型)
select * from user where id="$id";
select * from user where id=($id);
select * from user where id=('$id');
闭合方式判断:
1 and 1=2 返回无结果界面,不报语法错误,即为数字型。
1' and '1'='2 返回无结果界面,不报语法错误,即为单引号。
1" and "1"="2 返回无结果界面,不报语法错误,即为双引号。
1)and (1)=(2 返回无结果界面,不报语法错误,即为括号。
0x03:数据库注释语法
0x04:数字型注入
- 数字型的注入的注入点的数据类型是数字型,没有单引号保护的类型。
- sql=“SELECT * FROM users WHERE id=$id LIMIT 0,1”;
post方式,使用burp抓取数据包
-
判断列数,使用order by语句(如果by3 出现错误,但是by2不出错,说明为2列)
-
判断显示位
-
查询关于数据库的一些信息(库名,版本,用户)
- 查询pikachu数据库里边表的信息
- 查询users表中都有哪些列
- 爆出表中的内容
0x05:字符型注入
- 字符型的注入的注入点的数据类型是字符型,有单引号保护的类型。
- sql=“SELECT * FROM users WHERE id=’$id’ LIMIT 0,1”;
- 判断好类型是字符型后,使用单引号报错并使用注释符号闭合好后,后续的注入语句和上边数字型输入过程相似,此处不再做注入演示。
0x06:布尔型盲注(页面返回结果只有true和false)
-
利用的函数:
ascii()返回字符和ascii值。
substr(str,begin,length)返回从begin开始长度为length的字符串的字串
length()返回字符串的长度。 -
逐字判断数据库名(第一个字母为s,完整数据库名为security)
-
判断表名(第一个字母为u,完整表名为users)
0x07:基于时间的盲注 -
利用的函数:
if(expr1,expr2,expr3)判断如果第一个语句正确就执行第二个语句如果错误执行第三个语句。
sleep(n):将程序挂起一段时间 n单位为秒。 -
判读数据库名(延时5秒返回结果,数据库名为security,s:115)
-
判断表名(取到users表,测到第一个值为u,延时5秒返回结果)
0x08:update注入 -
update users set passwd=‘passwd’ where username=‘username’
-
利用mysql的updatexml(xml_target,xml_expr,xml_new)函数的报错信息
-
or updatexml(1,concat(0x3a,(database()),0x3a),0)–+
-
爆表名
-
爆字段名
-
爆数据(将select出来的结果作为from的派生表进行查询)
-
利用mysql对xml文档更新函数extractvalue(xml,value)
-
or extractvalue(0,concat(0x3a,database(),0x3a))–+
-
or extractvalue(0,concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’),0x3a))–+
0x09:insert注入(头部信息user-agent为注入点)
跟update注入利用函数相同,但是这个地方需要注意提前按照insert的格式进行了闭合。
INSERT INTO security
.uagents
(uagent
, ip_address
, username
) VALUES (‘
u
a
g
e
n
t
′
,
′
uagent', '
uagent′,′IP’, $uname)";
-
利用updatexml()函数
-
利用extractvalue()函数
0x10二次注入查询(less24) -
二次注入也称为存储型注入,就是将可能导致 SQL 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发 SQL 注入。
-
通过构造数据的形式,在浏览器或者其他软件中提交 HTTP 数据报文请求到服务
端进行处理,提交的数据报文请求中可能包含了构造的 SQL 语句或者命令。 -
服务端应用程序会将提交的数据信息进行存储,通常是保存在数据库中,保存的
数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。 -
向服务端发送第二个与第一次不相同的请求数据信息。
-
服务端接收到提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致在第一次请求中构造的 SQL 语句或者命令在服务端环境中执行。
服务端返回执行的处理结果数据信息,便可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。
参考文章:https://www.jianshu.com/p/c6a861507292
0x11:过滤型注入
-
less23:过滤注释符号(–+,#),注释的作用是为了提前闭合,注释掉后边的闭合符合,使其不会报错。注释符号被过滤后,再额外构造一个闭合(||‘1’='1),使闭合完整,效果是一样的。
-
less25:过滤字符中的or&and,本质就是黑名单,将名单中的字符进行替换为空格。常见的绕过手段有:重写,大小写绕过,编码绕过,或者利用运算符(&&;||)好代替等等方法,具体用那种还是要看实际的情况进行选择。
-
过滤空格:空格的URL编码代替(空格被过滤也可以使用不用空格的语句,如updatexml和extractvalue函数)。
%09 TAB 键(水平)
%0a 新建一行
%0b TAB 键(垂直)
%0c 新的一页
%0d return 功能 -
http://127.0.0.1/sqli-labs-master/Less-27/?id=0’||updatexml(1,concat(0x3a,(SeleCt(group_concat(table_name))from(information_schema.tables)where(table_schema=‘security’)),0x3a),0)||‘1’='1
-
http://127.0.0.1/sqli-labs-master/Less-27/?id=0’||updatexml(1,concat(0x3a,(SeleCt%0agroup_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema=‘security’),0x3a),0)||‘1’='1
-
上边两个payload分别使用小括号分割和空格编码来代替空格的作用。
0x12:宽字节注入(less32&33)
-
宽字节注入只要是因为数据库的编码方式是gbk等编码方式导致的,在理解宽字节注入之前建议先去查查中文的集中常见编码方式,了解编码会对理解宽字节注入有大大的好处。
-
在宽字节注入的页面中,程序通过GET获取参数ID,通常会对参数进行转义,对输入的参数中的 ‘(单引号)) "(双引号)\(反斜杠)NULL等通过添加反斜杠(\)进行转义,在PHP.ini的配置文件中存在magic_quotes_gpc选项,当该选项打开时,通过get,post,cookie接收到的’(单引号)) "(双引号)\(反斜杠)NULL都会被转义,或者可以通过addslashes()函数实现。
-
function check_addslashes($string)
{
$string = preg_replace(’/’. preg_quote(’\’) .’/’, “\\\”, $string); //escape any backslash
$string = preg_replace(’/’/i’, ‘\’’, $string); //escape single quote with a backslash
$string = preg_replace(’/"/’, “\”", $string); //escape double quote with a backslash
return $string;
} -
注入思路,一般网站的编码方式如果是gbk等宽字节编码方式,就是两个字节编码为一个字符。我们在输入1’(%27)后会被转义加一个\(%5c),如果我们输入的参数时1%bb%27,系统检测到%27为单引号会加一个%5c,那么就会变成1%bb%5c%27。%bb%5c就会被认为是一个字符而而被译码,这样的话单引号就逃逸了啊。(URLencode)
0x13:HTTP首部字段注入(cookie,x-forwarded-for)
- http首部字段中cookie和x-forwarded-for这两个字段经常也容易出现SQL注入漏洞,因为好多web应用都会用到这两个字段的值,和数据库进行交互。
- XFF头部信息用来显示客户端的ip地址,web应用根据ip地址判断你的位置,而很多钓鱼网站也会记录你这个信息,然后存储在数据库中,所以这个地方容易出现SQL出入。
- 可以使用BP抓取可能存在注入的请求报文,保存为post.txt文件,把这两个字段的值用*代替。然后使用sqlmap -r post.txt 测试是否有SQL注入。
0x14:SQL注入修复方法
- 过滤特殊字符串如单引号,双引号,斜杠,反斜杠,等一些特殊的符号和字母。常用到的方法是str_replace(),将一些危险敏感数据在传入数据库之前进行替换成空格。常见的黑名单手法,其实也是不太靠谱的,可以通过编码,大小写,复写(scrscriptipt)等手段绕过后端的黑名单。建议使用白名单,相比黑名单较安全。
- 使用PDO预编译语句,注意,不要讲变量直接拼接到PDO语句中,而是使用占位符(?)进行数据库的增删改查。
- 严格的数据类型(针对数字型,严格判断输入数据为数字型,使用ctype_digit()函数判断数据类型)。
- 特殊字符转义(magic_quotes_gpc,addslashes(),mysql_real_escape_string())
- 存储过程:存储过程是大型数据库中,一组为了完成特定功能或者常用的SQL语句集,经编译后存储在数据库中,存储过程具有较高的安全性。