-
Notifications
You must be signed in to change notification settings - Fork 1
Формация П 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