pcre-8.36$ ./pcretest -C
PCRE version 8.36 2014-09-26
Compiled with
8-bit support
UTF-8 support
Unicode properties support
No just-in-time compiler support
Newline sequence is LF
\R matches all Unicode newlines
Internal link size = 2
POSIX malloc threshold = 10
Parentheses nest limit = 250
Default match limit = 10000000
Default recursion depth limit = 10000000
Match recursion uses stack
pcre-8.36$ ./pcretest -d
PCRE version 8.36 2014-09-26
re>"^\x61\x00"
------------------------------------------------------------------
0 8 Bra
3 ^
4 a\x00
8 8 Ket
11 End
------------------------------------------------------------------
Capturing subpattern count = 0
Options: anchored
No first char
No need char
data> a
No match
data> a\x00
0: a\x00
data> a\x00b
0: a\x00
data> ab
No match
data>
当正则表达式搜索条件中包含
\x00
(或者\u0000
,\0
,null
)这个特殊字符时,可能得到非预期的结果,我们可以一步一步来验证:1.
\x00
是一个合法的Value
mongodb对文档的定义可以参考
http://docs.mongodb.org/manual/core/document/#field-value-limit
,这里面提到,key
不能包含null
,但是value
是可以的,实际测试下来也是这样的:2. 为了方便对比测试再添加几个文档
3. 使用简单查询可以正确取到文档
4. 使用正则表达式搜索会返回非预期文档
a\x00
为前缀的文档,{ "_id" : "a" }
不应该出现\x00
开头,期望不返回任何文档,结果是返回所有文档\x00RandomString
开头,期望不返回任何文档,结果是返回所有文档\x00RandomString
,期望不返回任何文档,结果是返回所有文档5. 正则表达式是可以正确匹配
\x00
的mongodb使用的正则表达式是
Perl compatible regular expressions (i.e. “PCRE” ) version 8.36 with UTF-8 support
(http://docs.mongodb.org/manual/reference/operator/query/regex/)下载地址:http://sourceforge.net/projects/pcre/?source=typ_redirect
编译参数:
./configure --enable-utf8 --enable-unicode-properties
6. 确认mongodb shell正确将请求发送给mongodb
抓取这个请求的包
结果:
在
0x0070
行能看到6100 62
,0x61
是a
,0x62
是b
,中间的字符是\x00
,确认mongodb shell正确将查询请求发送给了mongodb,mongodb处理有问题,返回了非预期的结果。7. 简单分析
mongodb在正则表达式处理上面有问题,
\x00
这个字符有可能直接将整个正则表达式截断了,使用不完整的正则表达式进行匹配得到错误的结果。根据bsonspec对正则表达式的定义:
正则表达式是由4部分组成:
\x0B
,一个标志位。e_name
是正则表达式的名字。cstring
是正则表达式字符串。cstring
是正则表达式的标志位。再看
cstring
的定义,就是一个字节数组,以\x00
结束。官方也明确说cstring
是不能包含\x00
字符的:如果mongodb使用bson来存储正则表达式,看起来是天然有问题的,首先正则表达式是可以使用
\x00
字符,但是bson的正则表达式不允许使用\x00
字符,如果使用了整个正则表达式会被截断。如果正则表达式部分使用
string
而不是cstring
存储就不会有问题,看一下string
的定义:string
的组成里面,第一部分是一个int32的数,表示整个字符串长度,因为长度明确,那么即使中间出现\x00
也不会被截断。这个问题终归到底看起来是bson的设计问题,正则表达式应该使用
string
存储而不是cstring
存储。mongodb自身也没处理好,如果不允许使用
\x00
,应该明确指出,在用户使用的时候需要报一个错,而不是返回错误的结果。8. 风险
如果用户输入中包含
\x00
字符,有可能会取得非预期结果,有可能会获取整个collection
里面的所有内容,这个还是需要重视的。测试会影响所有版本的mongodb。9. 如何规避风险
在mongodb修复这个bug之前,可以采取几种措施:
\x00
字符。\x00
字符,需要对mongodb返回的结果用标准正则表达式再匹配一次。10. 其他
已经向mongodb官方报bug:https://jira.mongodb.org/browse/SERVER-18824,欢迎围观。
The text was updated successfully, but these errors were encountered: