Skip to content

Формация П IV

Alexander Borzunov edited this page Dec 7, 2016 · 1 revision

Формация П IV

  • Категория: Web
  • Стоимость: 500
  • Автор идеи: Артур Лисс
  • Автор реализации: Александр Борзунов
  • Репозиторий

Условие

Формация П использует собственный поисковик, каждому пользователю которого выделяется личная база данных. Поисковик работает во внутренней сети формации.

Недавно произошла утечка части исходного кода поисковика. Узнайте пароль пользователя Minister в этой сети.

Решение

В условии дана ссылка на простейший поисковик, построенный на движке Elasticsearch. Если зарегистрироваться в нём, станет доступно две функции: проиндексировать небольшую часть Интернета, начиная с введённого URL (уходя от него не дальше, чем на расстояние в две ссылки), и найти в проиндексированных страницах определённые слова с помощью русскоязычного полнотекстового поиска.

В архиве с исходниками посмотрим, как устроена аутентификация в самом поисковике. За процесс входа на сайт отвечает функция login_submit в файле search_engine/front/auth.py:

@app.route('/login', methods=['POST'])
def login_submit():
    ...

    response = requests.get(urljoin(settings.AUTH_SERVICE_URI, '/login/' + username))
    if not response.ok:
        flash('Сервис аутентификации недоступен', 'error')
        return redirect(url_for('index'))

    user = response.json()
    if 'error' in user or request.form['password'] != user['password']:
        flash('Неправильный логин или пароль', 'error')
        return redirect(url_for('index'))

    ...

Константе AUTH_SERVICE_URI в файле search_engine/settings/production.py присвоено значение http://auth.local. Получается, при входе на сайт выполняется запрос по адресу http://auth.local/login/username, где username — введёное имя пользователя. Аналогично, при регистрации выполняется другой запрос по адресу http://auth.local/register.

Так как в Интернете доменов .local не существует, ясно, что это домен какого-то ресурса внутренней сети, отвечающего за аутентификацию. Именно оттуда мы получим пароль пользователя Minister (с ним можно будет залогиниться и в сам поисковик).

Рассмотрим процесс аутентификации подробнее. Запрос выполняется с помощью популярной библиотеки requests, после чего у объекта, представляющего ответ сервера, вызывается метод .json(), который декодирует содержимое страницы как JSON-документ. Если при аутентификации не произошло ошибки, документ содержит поле password с паролем пользователя, который в дальнейшем сравнивается со строкой, введённой в форме авторизации.

Так, если мы получим содержимое страницы http://auth.local/login/Minister, мы получим JSON-документ, в котором будет пароль искомого пользователя. Чтобы его получить, можно воспользоваться функцией индексации страниц в поисковике. Давайте с помощью формы на главной странице проиндексируем страницу с нужным URL, а затем сделаем поиск по строке password, чтобы посмотреть в поисковой выдаче фрагмент искомого документа.

Однако, если сразу вставить такой URL в поисковую строку, мы получим сообщение «Запрещено индексировать ресурсы внутренней сети».

Эта проверка реализована в файле search_engine/front/profile.py:

if '.local' in url:
    flash('Запрещено индексировать ресурсы внутренней сети')
    return redirect(url_for('index'))

Легко заметить, что она реализована с ошибками. Во-первых, она выполняется только по отношению к URL, с которого начинается индексация. Можно сделать пост в социальной сети со ссылкой на http://auth.local/login/Minister или создать следующую HTML-страничку:

<a href="http://auth.local/login/Minister">Link</a>

Тогда, если начать индексацию с этого поста или странички, поисковый робот обработает ссылку http://auth.local/login/Minister уже без выполнения проверки.

Во-вторых, проверка не учитывает, что URL не чувствителен к регистру, поэтому можно сразу в форму ввести строку http://auth.LOCAL/login/Minister и в поисковой выдаче получить содержимое страницы. Обнаружив одну из этих ошибок, несложно получить пароль.

Искомый пароль: QCTF_Ha_Ha_Hackers_Cant_Invade_In_Out_Network