是否可以使用 Mongoid 在 Rails 上对 Ruby 进行 nosql 注入?
Is nosql injection possible for Ruby on Rails with Mongoid?
我正在尝试调查是否可以使用 mongo 和 mongoid gems 在 Rails 上的 Ruby 上进行 nosql 注入。
我使用 Mongo::Client
包含 Mongoid::Document
的集合和模型完成了 Mongodb 的请求。
我试图传递一些命令字符,例如 ' " \ ; { }
,但已被清除。通过 GET search?title[$ne]=foo
的特征类似于 {"title"=>"{\"$ne\"=>\"foo\"}"}
,因此这里似乎没有任何问题。
如果我使用这个技术栈的普通方法,是否可以进行nosql注入?
这来自 mongdodb
文档
As a client program assembles a query in MongoDB, it builds a BSON
object, not a string. Thus traditional SQL injection attacks are not a
problem. More details and some nuances are covered below.
MongoDB represents queries as BSON objects. Typically client libraries
provide a convenient, injection free, process to build these objects.
Consider the following C++ example:
https://docs.mongodb.com/manual/faq/fundamentals/#how-does-mongodb-address-sql-or-query-injection
常见操作包括查询和 Mongoid 中的 inserts/updates 会清理它们的输入,因此大多数时候不需要担心 "nosql injection"。
但是,有一些方法可以将命令直接传递到数据库,在这些情况下,仔细考虑未过滤的用户输入是否最终会成为数据库命令很重要。例如,如果 Post 是一个 Mongoid 模型,可以 运行 以下命令在 MongoDB 服务器中创建一个无限循环:
Post.all.map_reduce('function(){while(true);}','function(){}').out(inline:1).count
另一个例子是驱动程序提供的Database#command
方法运行任意数据库命令:http://api.mongodb.com/ruby/current/Mongo/Database.html#command-instance_method。如果应用程序将用户输入放入提供给此方法的参数中,这会产生 "nosql injection".
的可能性
另请注意,没有必要将意外的 command 传递给数据库 - 有时意外的 data 就足够了。例如,参见 https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS。假设 Post 模型有一个主体字段,从用户传递任意正则表达式可能会有问题:
# This might take a while
Post.where('body' => {'$regex' => '((a|a?|a*)*)*$'}).count
可能,但容易被忽视。
事实上,你很接近。
不信任来源不仅仅来自 GET 参数。
Mongoid 不会帮你做任何事情;在您的示例中,阻止成功利用的是这样一个事实,即在 RoR 中,您不能将 Hash
作为 GET 参数传递。
未过滤的参数可以来自 JSON,例如这个。
posts = PrivatePost.where({ owner_id: json_params[:owner_id] }).each.to_a
其中 json_params[:owner_id]
可能包含 { '$ne': 'the owner' }
,
这可能会 posts
泄露给其他人。
或者通过基于 POST 的 API:
扰乱操作范围
Post.where({ _id: json_params[:id] }).delete_all
我正在尝试调查是否可以使用 mongo 和 mongoid gems 在 Rails 上的 Ruby 上进行 nosql 注入。
我使用 Mongo::Client
包含 Mongoid::Document
的集合和模型完成了 Mongodb 的请求。
我试图传递一些命令字符,例如 ' " \ ; { }
,但已被清除。通过 GET search?title[$ne]=foo
的特征类似于 {"title"=>"{\"$ne\"=>\"foo\"}"}
,因此这里似乎没有任何问题。
如果我使用这个技术栈的普通方法,是否可以进行nosql注入?
这来自 mongdodb
文档
As a client program assembles a query in MongoDB, it builds a BSON object, not a string. Thus traditional SQL injection attacks are not a problem. More details and some nuances are covered below.
MongoDB represents queries as BSON objects. Typically client libraries provide a convenient, injection free, process to build these objects. Consider the following C++ example:
https://docs.mongodb.com/manual/faq/fundamentals/#how-does-mongodb-address-sql-or-query-injection
常见操作包括查询和 Mongoid 中的 inserts/updates 会清理它们的输入,因此大多数时候不需要担心 "nosql injection"。
但是,有一些方法可以将命令直接传递到数据库,在这些情况下,仔细考虑未过滤的用户输入是否最终会成为数据库命令很重要。例如,如果 Post 是一个 Mongoid 模型,可以 运行 以下命令在 MongoDB 服务器中创建一个无限循环:
Post.all.map_reduce('function(){while(true);}','function(){}').out(inline:1).count
另一个例子是驱动程序提供的Database#command
方法运行任意数据库命令:http://api.mongodb.com/ruby/current/Mongo/Database.html#command-instance_method。如果应用程序将用户输入放入提供给此方法的参数中,这会产生 "nosql injection".
另请注意,没有必要将意外的 command 传递给数据库 - 有时意外的 data 就足够了。例如,参见 https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS。假设 Post 模型有一个主体字段,从用户传递任意正则表达式可能会有问题:
# This might take a while
Post.where('body' => {'$regex' => '((a|a?|a*)*)*$'}).count
可能,但容易被忽视。
事实上,你很接近。
不信任来源不仅仅来自 GET 参数。
Mongoid 不会帮你做任何事情;在您的示例中,阻止成功利用的是这样一个事实,即在 RoR 中,您不能将 Hash
作为 GET 参数传递。
未过滤的参数可以来自 JSON,例如这个。
posts = PrivatePost.where({ owner_id: json_params[:owner_id] }).each.to_a
其中 json_params[:owner_id]
可能包含 { '$ne': 'the owner' }
,
这可能会 posts
泄露给其他人。
或者通过基于 POST 的 API:
扰乱操作范围Post.where({ _id: json_params[:id] }).delete_all