目录
一、SQL注入的原理
SQL注入漏洞的条件
二、SQL注入的危害
三、SQL注入的分类
1、注入点数据类型分类
(1)数字型注入
(2)字符型注入
2、注入点位置分类
3、注入方法分类
(1)布尔型注入
(2)报错型注入
(3)延时注入
(4)联合查询注入
(5)宽字节注入
(6)多语句查询注入
四、SQL注入的防御
五、WAF绕过方法
六、SQLMAP
SQL注入是一种针对后台数据库的攻击手段,攻击者把精心构造的恶意SQL命令插入到Web表单的输入域或页面请求中,服务器执行SQL命令以达到对数据库的猜解、查询、删除、添加等。
●输入参数用户可控
●参数被带到数据库查询,即用户输入的数据被拼接成攻击者可控的SQL语句,并被带入到了数据库查询
●猜解后台数据库,盗用网站的敏感信息。
●绕过验证,如:用万能密码绕过验证登陆网站后台。
●注入可以借助数据库的存储过程进行提权等操作。
● 数字型注入是指输入的参数类型为整数,是最简单的一种注入。其对应的SQL语句可能如下:
SELECT * FROM news_table WHERE id=123 //我们输入的为123
●对其的测试也很简单,只要在末尾添加单引号或“AND 1=1”或“AND 1=2”类似的逻辑判断即可。
——> 输入单引号会导致SQL语句中的单引号配对出错,导致查询异常
——> 输入AND 1=1不会影响页面返回
——> 输入AND 1=2会导致返回空页面或错误页面
——> 若这三个都满足,则基本可以确定存在SQL数字型注入漏洞。
●数字型注入漏洞多出现在PHP等弱类型语言中,因为这种语言会对参数类型进行自动推导。但对于Java等强类型语言,将字符串转换为整型的操作会抛出异常,因此强类型语言很少存在数字型注入漏洞。
●具体步骤可以参考:
17.注入篇————MYSQL数字型注入_Fly_鹏程万里-CSDN博客
●字符型注入是指输入的参数类型为字符串。其与数字型注入的最大不同在于字符型注入一般需要对SQL语句中的单引号进行闭合,否则会出错。其对应的SQL语句有可能如下:
SELECT * FROM users WHERE username='admin' AND 1=1 --'
//我们输入的是admin' AND 1=1 --
//此时admin对应的单引号被闭合,后面的单引号被--注释掉(--和#在SQL里起注释作用)
●对其的测试也很简单
——> 输入单引号会导致SQL语句中的单引号配对出错,导致查询异常
——> 输入' AND '1'='1不会影响页面返回
——> 输入' AND '1'='2会导致返回空页面或错误页面
——> 若这三个都满足,则基本可以确定存在SQL字符型注入漏洞。
●具体步骤可以参考:
18、注入篇——————MYSQL字符型注入_Fly_鹏程万里-CSDN博客
SQL注入(二):pikachu(一):MySQL字符型注入(post) --- 字符型注入_天威一号-CSDN博客
按照注入点位置对SQL注入进行分类还可以分为GET注入、POST注入、Cookie注入。
盲注:不能通过直接显示的途径来获取数据库的方法。一般有三种:布尔盲注、报错型盲注、延时盲注。
当查询的结果不会显示在界面,同时不会显示报错信息时,若能从页面反馈结果得知SQL语句的成功与否则可以考虑布尔盲注。
●具体步骤可以参考:
布尔型盲注基本思路_刘启明-CSDN博客
布尔盲注详解_AaronLuo-CSDN博客_布尔盲注
SQL布尔型盲注思路分析(入门必看)_Pz_mstr's Blog-CSDN博客_sql布尔盲注
当输入特殊字符页面出现报错信息时,则可以考虑使用基于错误的注入。攻击者故意在查询中注入无效输入或者SQL令牌来产生语法错误、类型不匹配,或者逻辑错误。适用于无回显数据但是有数据库报错输出的场景。主要为xpath报错和group by报错。
●限制条件:后台没有屏蔽数据库报错信息,在语法发生错误时会输出到前端。
●xpath报错
①常用函数:
updatexml()函数:
extractvalue()函数:
②部分代码:
查表名:
?id=1 union select updatexml(1,concat(0x7e,select group_concat(table_name) from information_schema.tables where table_schema='test',0x7e),1) #
查列名:
?id=1 union select updatexml(1,concat(0x7e,select group_concat(column_name) from information_schema.columns where table_schema='test' and table_name='test1'),0x7e),1) #
查test2字段数据:
?id=1 union select updatexml(1,concat(0x7e,select group_concat(test2) from test.test1),0x7e),1) #
concat()函数:用于连接两个或多个数组,将其拼接后输出到前端
group_concat()函数:将查询产生的同一个分组的值连接起来,返回一个字符串结果,可以排除重复值。一般显示内容很少时可以用这个将行与列互换显示。
0x7e:是特殊符号“~”,为了区分报错后的有用信息
●group by报错
①常用函数:
floor()函数:向下取整
floor(x)返回小于或等于x的最大整数
floor报错要求:数据库中要查询的数据至少3条以上
②部分代码:
查库名:
?id=-1 and (select 1 from (select count(*),concat(database(),floor(rand(0)*2)x from information_schema.tables group by x)) a)
查表名:
?id=-1 and (select 1 from (select count(*),concat((select concat(table_name) from information_schema.tables where table_schema="test" limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)) a)
查列名:
?id=-1 and (select 1 from (select count(*),concat((select concat(column_name) from information_schema.columns where table_name="test1" limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)) a)
查test2字段数据:
?id=-1 and (select 1 from (select count(*),concat((select concat(test2) from test1 limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)) a)
延时注入是一种基于时间差异的注入技术,通过向数据库注入时间延迟并检查服务器响应是否也已经延迟来获取数据库信息。攻击者可以采取页面加载的时间来决定注入的语句是否正确。
●常用函数:
benchmark(count,expr):将expr语句执行count次来达到延迟目的
sleep(time):直接延迟time时间
if(T,a,b):判断T,若真则执行a,若假则执行b
●具体步骤可以参考:
一次手工和工具的延时注入(时间注入)_liam liang的博客-CSDN博客_时间注入SQL盲注(延时注入)_JKding123的博客-CSDN博客一次手工和工具的延时注入(时间注入)_liam liang的博客-CSDN博客_时间注入
union关键字将两个或多个查询结果组合成为单个结果集,即联合查询。多数数据库支持union查询。需要注意的是所有查询的列数必须相同且数据类型兼容。
●条件:页面上有显示位
●具体步骤可以参考:
WEB漏洞-SQL注入之联合查询注入_钓鱼的猫咪的博客-CSDN博客
mssql注入实例--联合查询注入_buffedon的博客-CSDN博客
利用数据库的编码转换使得引号闭合的注入方式。
●相关函数:addslashes()、mysql_real_escape_string()、 mysql_escape_string() 函数或者开启magic_quotes_gpc=on的方式来防止注入,也就是给单引号(' )、 双引号(")、反斜杠(\)和NULL加上反斜杠转义。但是如果在使用PHP连接MySQL的时候,又设置了“set character_set_client = gbk" 时又会导致一个编码转换的注入问题,也就是我们所熟悉的宽字节。但一般都不是直接设置character_set_client=gbk,通常的设置方法是SET NAMES 'gbk'。
●具体步骤可以参考:
宽字节注入_heiseweiye的博客-CSDN博客_宽字节注入
●针对宽字节注入的防御:
A.在执行查询之前先执行SET NAMES 'gbk',character_set_client=binary设置 character_set_client 为binary。
B.使用 mysql_set_charset(‘gbk’) 设置编码,然后使用 mysql_real_escape_string() 函数被参数过滤。
C.使用pdo方式,在PHP5.3.6及以下版本需要设置setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 来禁用 prepared statements 的仿真效果。
多语句查询注入又称为堆叠查询注入,攻击者利用分隔符(如:;)攻击数据库,在原始的查询基础上附加额外的查询。通常第一个查询是合法查询,后面的查询是攻击者附加的非法查询。攻击者可以向数据库注入任意命令。
(1)对输入数据进行校验
通常可以把输入数据审核技术分成以下几类:对非法数据进行修整而将其转化为合法数据、拒绝未知的非法语句输入(黑名单)、只接受已知的合法数据(白名单)。
对于数据的校验可以从前端和后端两个层面来进行。前端可以基于Javascript等脚本语言进行输入合法性校验,后端由后台开发语言代码负责数据合法性校验。单纯的前端校验没有太大意义,因为攻击者可以通过将前端校验的数据截获,然后修改后再发送给后台服务器的方式绕过前端检测。后端校验发生在数据传送到服务器以后进行,一般情况下攻击者没有权限修改到达服务器后台的数据,因此后端校验可以保证输入数据的合法性和正确性。
(2)对输入数据进行编码或数据类型校验
●数据类型校验
对于PHP等弱类型语言,数字型注入也是一种常见形式。该种类型注入的防御也比较简单,只需要在后端程序中对数据类型进行严格判断即可(如:is_numeric()函数)。
●对输入数据进行编码
对用户输入的数据进行适当的编码,这样服务器就不会执行恶意语句。如:在字符型注入攻击中,攻击者在字符型注入中为了闭合语句,必然会用到单引号等特殊字符,那么将攻击者输入的特殊字符进行转义或编码就可以防御字符型注入攻击。
在OWASP ESAPI中提供了对数据库转码的接口,其针对不同的数据库实现了不同的编码器,对于不知道需要转义这些特殊字符的用户可以直接根据数据库类型进行选择使用相应的ESAPI即可。
(3)使用预编译语句或存储过程
PHP、Java、C#等语言都提供了预编译语句,可以很好的屏蔽动态SQL语句,从而起到预防SQL注入的效果。如:Java的Statement、PreparedStatement、CallableStatement等。
(4)使用ORM或框架技术
专门与数据库进行交互的框架被称为持久化框架,如:Hibernate(开源、对JDBC进行了封装)、JORM等。
(5)不要开启数据库的错误显示
(6)限制输入长度
(7)限制好数据库权限,drop/create/truncate等权限谨慎grant
(8)数据库信息加密,可以采用一次md5后加盐再md5
可以参考:
WAF绕过方法_bandongshen9543的博客-CSDN博客
SQLMAP是一款基于Python开发的开源的SQL注入漏洞测试工具,它可以自动检测并完成SQL注入漏洞的利用。
●使用教程可以参考:
sqlmap详细使用教程_星落的博客-CSDN博客_sqlmap使用教程