Что это вообще такое?
MongoDB — документо-ориентированная СУБД с открытым
исходным кодом, не требующая описания схемы таблиц. (wiki)
Особенности:
1. Документо-ориентированное хранилище.
2. Достаточно гибкий язык для формирования запросов
3. Динамические запросы
4. Полная поддержка индексов
5. Профилирование запросов
6. Поддержка отказоустойчивости и масштабируемости
А на чем он?
./mongod — это серверная часть,
написанная на C++
./mongo – офф. клиент,
написанный на C++ и JS
У Mongodb существуют официальные
драйвера для основных ЯП:
C
C++
Java
Javascript
.NET (C# F#, PowerShell,
etc)
Node.js
Perl
PHP
Python
Ruby
Scala
Где используются
Краткий список компаний использующих MongoDB:
1. SAP (Крупный производитель программного обеспечения)
2. SourceForge (Хостинг открытого исходного кода)
3. The New York Times
4. GitHub (Проект социального хостинга)
5. Foursquare (Достаточно крупный и известный стартап)
6. Yandex (некоторые сервисы)
Что такое RESTful?
Веб-службы RESTful в MongoDB используют
интерфейс API для связи с базами данных,
просмотра логов и исполнения других ф-ций
администрирования.
А как я узнаю его?
Он по дефолту запускается на порту «28017».
Он может быть запущен без параметра –rest, тогда будет вот эта ошибка:
Какие там уязвимости?
Во время исследования были найдены следующие уязвимости:
Исполнение произвольного серверного JS кода
Хранимая XSS в логах обращения к БД
Хранимая XSS в журнале запросов
CSRF в удаленном обращении к БД
Our SSJS code
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
Admin’s browser
Hacker’s
Server
MongoDB
--REST
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
Admin’s browser
2) В результате
нашего запроса, в
REST интерфейсе
будет
подгружаться наш
скрипт
Hacker’s
Server
MongoDB
--REST
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
Admin’s browser
2) В результате
нашего запроса, в
REST интерфейсе
будет
подгружаться наш
скрипт
Hacker’s
Server 3) Через XSS в браузере
MongoDB подгружается наш скрипт
--REST
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
4) Посылаем
команду, Admin’s browser
браузеру
жертвы
2) В результате
нашего запроса, в
REST интерфейсе
будет
подгружаться наш
скрипт
Hacker’s
Server 3) Через XSS в браузере
MongoDB подгружается наш скрипт
--REST
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
4) Посылаем
команду, Admin’s browser
браузеру
жертвы
2) В результате
нашего запроса, в
REST интерфейсе
будет
5) Ждем, пока скрипт не запросит подгружаться наш
команду (JSONP) ( скрипт скрипт
запрашивает новую команду
каждые 30 секунд)
Hacker’s
Server 3) Через XSS в браузере
MongoDB подгружается наш скрипт
--REST
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
4) Посылаем
команду, Admin’s browser
браузеру
жертвы
2) В результате
нашего запроса, в 6) Выполняем полученную
REST интерфейсе команду, через
будет недокументированное
5) Ждем, пока скрипт не запросит подгружаться наш
команду (JSONP) ( скрипт исполнение SSJS, и получаем
скрипт ответ
запрашивает новую команду
каждые 30 секунд)
Hacker’s
Server 3) Через XSS в браузере
MongoDB подгружается наш скрипт
--REST
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
4) Посылаем
команду, Admin’s browser
браузеру 7) Отправляем результат исполнения
жертвы команды на запись в БД
2) В результате
нашего запроса, в 6) Выполняем полученную
REST интерфейсе команду, через
будет недокументированное
5) Ждем, пока скрипт не запросит подгружаться наш
команду (JSONP) ( скрипт исполнение SSJS, и получаем
скрипт ответ
запрашивает новую команду
каждые 30 секунд)
Hacker’s
Server 3) Через XSS в браузере
MongoDB подгружается наш скрипт
--REST
Проведение атаки
1) Посылаем запрос с тегом script, и адресом
Site with
нашего скрипта.
mongoDB
driver support
Hacker
4) Посылаем
команду, 8) Получаем Admin’s browser
браузеру результат 7) Отправляем результат исполнения
жертвы исполнения команды на запись в БД
команды
2) В результате
нашего запроса, в 6) Выполняем полученную
REST интерфейсе команду, через
будет недокументированное
5) Ждем, пока скрипт не запросит подгружаться наш
команду (JSONP) ( скрипт исполнение SSJS, и получаем
скрипт ответ
запрашивает новую команду
каждые 30 секунд)
Hacker’s
Server 3) Через XSS в браузере
MongoDB подгружается наш скрипт
--REST
Стабильный CRASH
MongoDB очень часто падает если вызвать ф-цию с
нестандартными параметрами. На скриншотах можно
увидеть результат:
Интересные фичи
Ф-ции ls, cat, (остальные - help admin) работают только из самой консоли Mongo.
Скорее всего существуют и другие варианты NoSQL-инъекций, с другими языками
программирования.
Очень интересна ф-ция nativeHelper, которая как раз и отвечает за работу с ФС из консоли
mongo.
Чаще всего путь к файлам бд – «/data/db» или «/var/lib/mongodb». Структура каталога
простая: (dbname).(num). Чтобы извлечь информацию достаточно сделать
$ strings users.*
Сетевое взаимодействие
Логика работы скрипта, для перехвата и перебора паролей:
Перехватываем n Получаем
пакетов, связанных следующую
строку из
с mongodb словаря key2 = md5(nonce + user +
md5(user + ":mongo:" + passw)),
где passw это строка из словаря
Получаем из данных
key, nonce, login
Проверяем key == key2 Выводим
их на user:passwd
наличие
пакетов
авторизации false
true
Нашли
Выход
Не нашли
Сетевое взаимодействие. MiTM атака
1. Запрос
авторизации
mongoDB
admin 2. Отдаем nonce, под
который
сгенерированы
rainbow tables
Hacker
Сетевое взаимодействие. MiTM атака
1. Запрос
авторизации
mongoDB
admin 2. Отдаем nonce, под
который
сгенерированы
rainbow tables
Hacker
3. Клиент отдает нам
login и получившийся
key
Сетевое взаимодействие. MiTM атака
4. Подбираем
1. Запрос
пароль по заранее
авторизации
сгенерированным mongoDB
к этому nonce
радужным
admin 2. Отдаем nonce, под таблицам
который
сгенерированы
rainbow tables
Hacker
3. Клиент отдает нам
login и получившийся
key
Сетевое взаимодействие. MiTM атака
4. Подбираем
1. Запрос
пароль по заранее
авторизации
сгенерированным mongoDB
к этому nonce
радужным
admin 2. Отдаем nonce, под таблицам
который
сгенерированы
rainbow tables
5. Успешно авторизовываемся
с полученными данными
Hacker
3. Клиент отдает нам
login и получившийся
key
Что такое BSON
Что такое BSON? Типы данных
Это Бинарный JSON. BSON это string – строка
расширение JSON, которое int - целое число
позволяет хранить данные в double - двойное число с плавающей
различных форматах: дата и запятой
время, бинарные данные и т.п. DateTime – дата
byte[] - массив байт (бинарные
данные)
bool - булевые (true/false)
null - ноль
Пример? BsonObject - BSON объект
BsonObject[] - массив BSON
объектов
Перезапись переменных
Имеется таблица с двумя записями:
Также запрос, в который мы можем внедриться:
Вставляем BSON документ, который перезаписывает переменную isadmin:
Проверяем:
Особенности разных ЯП
JSON injection в NodeJS + MongoDB:
SEND
SEND
VULNERABLE SOURCE CODE:
VULNERABLE SOURCE CODE:
RESULT QUERY:
RESULT QUERY:
Хакер 02/12 (157)
Уязвимости
Типы обнаруженных уязвимостей:
Обход авторизации через подстановку массива в
php
Внедрение SSJS (Server Side JavaScript) кода
Слепое внедрение SSJS, Time-based
Особенности разных ЯП
Как известно, php обрабатывает символы “[]” из GPC как массив:
password[$ne]=parol1
В официальном классе mongoDB для для php есть ф-ция find()
Особенности разных ЯП
Формируется вот такой NoSQL запрос к MongoDB, и авторизация проходит
успешно:
Таким образом, если в коде нет проверки, мы можем обойти авторизацию
разными способами:
Особенности разных ЯП
Внедрение напрямую в js запрос.
Предположим в коде вот такие вот строки:
$q = “function() { var loginn = ‘$login’; var passs = ‘$pass’; db.members.insert({id : 2,
login : loginn, pass : passs}); }”;
$db->execute($q);
Также в ответ выводятся наш id и login.
Теперь пробуем внедриться в запрос:
Видно, что тут идет перезапись переменной «loginn» на
результат команды db.version()
Особенности разных ЯП
Иногда невозможно увидеть результат исполнения SSJS-кода.
Для этих случаем лучше использовать технику Time-based:
Специально для этого был написан скрипт для перебора и вывода
нужных пользователю данных.
NoSQL-injection Cheat Sheet
db.getName() - имя текущей БД можно просто db
db.members.count() - количество записей в таблице members
db.members.validate({ full : true}) - основная информация о таблице
members
db.members.stats() - почти то же что и предыдущее, но немного в
укороченном варианте
db.members.remove() - очистить таблицу members, синтаксис такой-же
как и у ф-ции find()
db.members.find().skip(0).limit(1) - еще один способ получения записи.
Просто перебираем значение skip.
db.getMongo().getDBNames().toString() – Получаем список всех
доступных БД
db.members.find()[0][‘pass’] – получаем значение поля pass из первой
записи