Эксплуатация SQL-инъекции в токене авторизации
Этичный Хакер
Данная статья является переводом и ведётся со слов автора, оригинал тут.
Небольшое введение в токены авторизации
- Токен авторизации генерируется и подписывается серверами и используется для верификации пользователей по уникальным токенам.
- После успешного входа сервер отправляет токен авторизации и веб-разработчики часто хранят его в локальном хранилище браузера или сессии.
- Современные веб-сайты используют JWT (веб-токены JSON) для авторизации пользователей. Это не означает, что каждый токен авторизации является JWT. Это зависит от бэкенда и фреймворка, который использует веб-сайт.
Не теряя времени, давайте перейдем к истории
Я не регулярно занимаюсь багхантингом. Можно сказать, что я сезонный багхантер. Мне было скучно, и я попытался найти какие-нибудь частные программы по поиску ошибок через google dorks, и выбрал случайную программу для охоты. Я не проводил базовую разведку, такую как перечисление поддоменов или какой-либо доркинг, поскольку начал с основной цели.
Для меня это был обычный день. Я просто запустил Burp и открыл главный сайт компании. Cогласно их политике, я не буду раскрывать наименование организации.
С помощью плагина Wappalyzer я заметил, что цель работает на PHP. Для меня, PHP уязвим по своей природе. Как у веб-разработчика, у меня много опыта создания сайтов на PHP и устранения уязвимостей.
У меня есть практика перебора каталогов и проверка файла robots.txt на начальном этапе моего процесса разведки.
Я использовал Dirsearch для поиска скрытых каталогов, но безуспешно. Ничего подозрительного, кроме страницы администратора.
Я попытался открыть страницу администратора, посетив target/admin/
Но не повезло, сервер выдает ошибку 403 Forbidden

Я не сдался слишком быстро и попытался провести фаззинг внутри страницы администратора, используя Dirsearch. На этот раз страница /events вернула ответ 200.
Без промедления я открыл страницу target/admin/events/
Я заметил, что она представляет собой обычную страницу входа в систему, на которой есть два способа входа: один - для автора, другой - для супер админа.
Эксплуатация начинается здесь
Как я уже сказал, есть две ссылки для входа, одна для автора, а другая для админа. Я выбрал первую, и она перенаправила меня на
target/admin/events/?classic_login=true

и показала всплывающее окно для ввода логина и пароля. Я начал вводить неправильный учетные данные и наблюдать за ответом сервера. Попробовав несколько вариантов, я решил ввести в поле имени и пароля значение 1'.
На это сервер выдал ошибку SQL.

Я попытался воспроизвести это снова, но это не работало, и всплывающее окно входа перестало отображаться. Даже после обновления страницы там отображается сообщение об ошибке. Я решил, что это может быть какая-то ошибка на бэкэнде.
Я зашел в историю burp и не заметил отправленных POST или JSON данных.
Некоторое время я был в замешательстве, а позже открыл ссылку в режиме инкогнито и всплывающее окно опять появилось для входа в систему. Я снова наблюдал запрос и ответ.
Позже я заметил заголовок авторизации с токеном.

Как веб-разработчик, я знаю, как работают токены авторизации, и у меня есть хорошие знание PHP, стека MERN и немного по фреймворку Django. Я легко понимаю как разработчики используют токенизацию.
Заголовок выглядит следующим образом.
Authorization: Basic Base64Values
Вы можете часто видеть этот заголовок в современных веб-приложениях.
Authorization: Bearer <TOKEN>
Профессиональный совет: на стороне сервера в большинстве случаев Bearer игнорируется, и разработчики сопоставляют токен с выданым токеном. Если это JWT, то разработчики часто декодируют его вместо того, чтобы проверять там неправильный контроль доступа или захват учетной записи.
Продолжим рассказ. Я отправил запрос на Repeater, выбрал токен и расшифровал его используя декодер Burp. Так как я угадал тип шифрования по его длине и характеру. Это был не JWT, а значение в base64 1':1'.
Я быстро вспомнил об инструменте Sqlmap, перехватил весь запрос и сохранил его в текстовый файл.
Я попытался запустить sqlmap, но проблема возникает при кодировке в base64. Хотя sqlmap и поддерживает кодировку base64, проблема была в двоеточии : между значениями.
Приложение принимает имя пользователя и пароль, а затем кодирует эти значения с помощью base64 с разделением через двоеточие:
Например: username:password
base64 <username>:<password>
Я решил провести ручную эксплуатацию SQL-инъекции с кодировкой полезной нагрузки в Repeater. Для этого я попытался определить количество столбцов и вставил полезную нагрузку для имени пользователя и пароля:
1' Order By 1-- -:1' Order By 1-- -
Полезная нагрузка авторизации выглядит следующим образом.
Authorization: Basic MScgT3JkZXIgQnkgMS0tIC06MScgT3JkZXIgQnkgMS0tIC0=
Ошибки SQL не было, и отобразилась обычная страница несанкционированного доступа.
Я попытался увеличить число столбцов, но сервер выдал ошибку. Я узнал, что там был только один столбец и попытался ввести операторы union.
При введении полезной нагрузки:
1' Union Select 1-- -:1' Union Select 1-- -
Значение токена авторизации было:
Authorization: Basic MScgVW5pb24gU2VsZWN0IDEtLSAtOjEnIFVuaW9uIFNlbGVjdCAxLS0gLQ==
И я успешно вошел в панель администратора:

Извините, я скрыл некоторую информацию здесь, вот POC без размытия:
