Приветствую юных белых хакеров. Продолжаем решать задачки по информационной безопасности web-серверов. Сегодня задачка с портала root-me.org, называется "Flask - Unsecure session". За решение задачки дают 20 баллов, лёгкий уровень.
Из задачи сразу понимаем, что дело придётся иметь с Flask.
Flask — лёгкий и мощный фреймворк для создания веб-приложений на Python, использующий набор инструментов Werkzeug, а также шаблонизатор Jinja2.
Веб разработчик говорит вам, что нет смысла использовать сложные секретные ключи, докажите ему, что он не прав.
Ссылки
https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/flask
Решение
Переходим на страницу задания:
http://challenge01.root-me.org/web-serveur/ch84/
Открывается некий сайт. Написано, что я всего лишь гость (guest), если вдруг я админ (admin), то можно попасть в консоль администратора. Тыкаю на ссылку ADMIN.
Написано, что здесь находится консоль администратора, но, поскольку я не администратор, то она не отображается.
Беглое исследование сайта больше ничего не дало, других разделов на сайте нет.
Устанавливаю в браузере расширение Cookie-Editor и смотрю на куки.
Как и ожидалось, находится куки с названием session. Это название переменной по умолчанию для хранения сессии в Flask.
eyJhZG1pbiI6ImZhbHNlIiwidXNlcm5hbWUiOiJndWVzdCJ9.ZZp9QA.uHaJPvnjKc52Px1o_qppe_4mVj4
Сессия состоит из трёх частей, разделённых точками. Очень похоже на JSON Web Token (JWT), но несколько отличается. Представляет собой строку вида "payload.timestamp.signature". Где:
- payload — полезная нагрузка. JSON объект в формате Base64.
- timestamp — время жизни сессии. В формате Base64.
- signature — подпись. В формате Base64. Вычисляется с помощью секретного ключа известного web серверу.
У Flask сессии полезная нагрузка содержится в первой части. Проверить легко, воспользовавшись любым BASE64 конвертером.
Выделяем первую часть сессии и декодируем.
eyJhZG1pbiI6ImZhbHNlIiwidXNlcm5hbWUiOiJndWVzdCJ9
Получаем:
{"admin":"false","username":"guest"}
В полезной нагрузке содержатся данные об имени пользователя и о том, что он не админ. Авторизация и аутентификация в одном флаконе (flask).
Из задания понятно, что секретный ключ не должен быть очень сложным. Будем подбирать брутфорсом. Воспользуемся Kali Linux, у меня Windows, буду разворачивать виртуалку на WSL 2.
Разбираться с работой сессий нам не придётся, всё придумано за нас. Воспользуемся пакетом flask-unsign.
pip3 install flask-unsign
Отлично, пакет установился. Сначала я попробовал его на старой Ubuntu поставить — не прокатило. С Kali гораздо лучше дело пошло. Проверим как всё работает, декодируем cookie.
flask-unsign --decode --cookie 'eyJhZG1pbiI6ImZhbHNlIiwidXNlcm5hbWUiOiJndWVzdCJ9.ZZp9QA.uHaJPvnjKc52Px1o_qppe_4mVj4'
Получаем ту же самую полезную нагрузку, которую уже вычислили ранее BASE64 декодером.
Для подбора секретного ключа нам понадобится словарь. Можно его скачать в Интернете. В Kali Linux он уже имеется в директории /usr/share/wordlists. Вот только он заархивирован, распакуем.
cd /usr/share/wordlists
gunzip rockyou.txt.gz
Запускаем брутфорс.
flask-unsign --wordlist /usr/share/wordlists/rockyou.txt --unsign --cookie 'eyJhZG1pbiI6ImZhbHNlIiwidXNlcm5hbWUiOiJndWVzdCJ9.ZZp9QA.uHaJPvnjKc52Px1o_qppe_4mVj4' --no-literal-eval
После семидесяти тысяч итераций секретный ключ подобран.
b's3cr3t'
Теперь нам ничто не мешает сгенерировать свою сессию, естественно, нужно поменять полезную нагрузку таким образом, чтобы стать админом.
{"admin":"true","username":"admin"}
Генерируем сессию.
flask-unsign --sign --cookie "{'admin':'true','username':'admin'}" --secret "b's3cr3t'"
Получаем:
eyJhZG1pbiI6InRydWUiLCJ1c2VybmFtZSI6ImFkbWluIn0.ZZp_7w.59bTkveMfroqJp-eu6xvhJxXquY
Подменяем куки:
И...
Good job, use this flag: получаем флаг! Валидируем.
Флаг подходит, зарабатываем 20 очков.
Безопасность
Админ использовал простой секретный ключ для генерации сессий. Если вы уж задаёте где-то пароли, секретные ключи или подписи, то позаботьтесь о том, чтобы они были достаточно сложными и стойкими к брутфорсу — перебору паролей.
Использование фреймворков при разработке web приложений требует уделать достаточное внимание безопасности. Для распространённых фреймворков типа Flask уже давно написаны инструменты подбора паролей, декодирования и генерации сессий.