Як обійти двох факторну аутенфікацію Authy с ../sms

За допомогою простого введення ../sms можна було обійти другий фактор на сайтах використовують 2FA через authy.com (а їх досить багато).


Найцікавіше що така прикра вразливість з'явилася не з вини Authy, та й знайшов я весь цей ланцюжок багів з великою удачею.

Отже, процес роботи з authy простий і складається з двох API викликів: api.authy.com/protected/json/sms/AUTHY_ID?api_key=KEY для запиту нового токена і api.authy.com/protected/json/verify/SUPPLIED_TOKEN/AUTHY_ID?api_key=KEY для верифікації отриманого токена від юзера. Обидва виклики повинні повернути 200 статус, тоді запит вважається успішним.

1. Почалося все з перевірки їх SDK бібліотек. Все виглядало добре крім authy-node, яка взагалі не кодувала токен перед вставкою в URL - this._request ("get", "/protected/json/verify/" "+ token +" "/" "+ id, {}, callback, qs);

Можна було просто вставити VALID_TOKEN_FOR_OTHER_AUTHY_ID/OTHER_AUTH_ID # в поле токена і перезаписати API запит так, щоб він завжди повертав 200 статус, що вважалося за підтвердження другого кроку і пускало атакуючого в аккаунт. Справа в тому що все після # вважається фрагментом і не відсилається на сервер, і запит виду/ protected/json/verify/VALID_TOKEN_FOR_OTHER_AUTHY_ID/OTHER_AUTH_ID буде повертати 200 і його неможливо відрізнити від звичайних запитів.

2. Далі був помічений цікавий  в authy-python: urllib.quote кодував всі знаки крім слішу (чому - не зрозумію). Хм, а що можна зробити зі злішем? Може спробувати вставити/../? Як ви знаєте ,/../,/% 2e% 2e/і навіть/% 252e% 252e/значать «перейти на одну директорію вгору» в браузерах. Але сервери зовсім не зобов'язані мати таку функцію. Однак я вирішив заради тесту послати ../sms і це спрацювало! Я поки ще поняття не маю чому, але тепер вставляючи ../sms ми перетворювали/verify виклик в/sms виклик (/verify/../sms/authy_id) який повертав 200 і пускав нас в акаунт.

3. І тут я згадав, що читав інтерв'ю Деніела з архітектури Authy зовсім недавно. Там говорилося, що Authy використовує Sinatra, яка за собою тягне rack-protection, який як я пам'ятаю мав модуль під назвою path_traversal.

І тут найцікавіше - виявилося що path_traversal навіщо декодував path назад і вбивав директорії перед/../. Ну, в теорії, це повинно було захищати розробників від потенційних path traversal вразливостей. На практиці ж це і стало причиною такої серйозної вразливості.

Отже, за порядком:

1. Я вводжу ../sms в поле токена

2. Клієнт кодує це як..% 2fsms і робить запит на api.authy.com/protected/json/verify/..%2fsms/authy_id

3. path_traversal декодує отриманий URL на ранньому етапі в api.authy.com/protected/json/verify/../sms/authy_id, ділить все по/і видаляє директорію/verify

4. Тепер сам додаток отримує модифікований шлях api.authy.com/protected/json/sms/authy_id який посилає СМС жертві і повертає 200 статус і відповіддю {«success»:true,«message»:«SMS token was sent»,«cellphone»:""+1-XXX-XXX-XX85""}

5. Наш клієнт який хотів перевірити наш токен бачить 200 статус і робить висновок що токен правильний. Навіть якщо використовується кастомна реалізація API, клієнт швидше за все шукає success = true що в нашій відповіді теж присутній.

Просто кажучи ввівши ../sms в поле токена можна було обійти двох факторну аутенфікацію на всіх сайтах використовують Authy.

Є ще один чудовий текст про схожу вразливість з обходом першого фактора через вставку символу | в іншому популярному 2FA провайдері Duo Security, але мені його лінь перекладати.

Тут було посилання що ми шукаємо хакерів, але його видалили. Напишіть в личку будь ласка, якщо ви знаходите такого роду вразливості під час ранкової зарядки.