Антон Чурюмов, 16.02.2015.
Користувачі Яндекс.Денег підтверджують кожну витратну операцію за допомогою одноразового пароля. Це повинно захистити їхні гроші, проте на практиці в багатьох випадках захист не працює.
Яндекс.Деньги пропонують два способи отримання одноразових паролів - SMS і коди з мобільного додатку «Яндекс.Деньги» для iOS, Android і Windows Phone.
Якщо користувач вибирає SMS, то коли він робить транзакцію, наприклад переводить 10 рублів на гаманець № 123456, він отримає SMS такого змісту «Пароль: 1234. Переклад на рахунок 123456 10р.». Якщо користувач насправді хотів перевести іншу суму на інший гаманець або зовсім не намагався перекладати ніякі гроші, то він не введе SMS-пароль, і його гроші залишаться з ним. Це приклад, коли другий фактор захисту - SMS-пароль - працює.
Якщо ж користувач вибрав, що він хоче підтверджувати транзакції за допомогою одноразових паролів з програми «Яндекс.Деньги», то йому потрібно відкрити програму і переписати 6 цифр одноразового пароля (які змінюються кожні 30 секунд) з додатка на сторінку сайту Яндекс.Денег. Тут чогось не вистачає? Правильно - користувач не контролює зміст транзакції, яку він підтверджує. Перераховує він 10 рублів або 100 000 рублів, своєму другові або Бендеру Остапу Ібрагімовичу, в будь-якому випадку він тупо переписує 6 цифр з телефону в комп'ютер, і транзакція вважається підтвердженою.
Виходячи зі сказаного, вектор атаки стає очевидним. Якщо на комп'ютер користувача впроваджується троян, який може змінювати вміст сторінок, які бачить користувач, і може змінювати зміст даних, які відправляються з браузера на сервер Яндекс.Денег, то цей троян може легко підробити вміст транзакції, яку відправляє користувач, і ніщо не викличе його підозра, коли він буде підтверджувати транзакцію за допомогою одноразового пароля з програми. Для Яндекс.Денег це буде виглядати так ніби користувач дійсно створив переклад на 100 000 руб. на гаманець Бендера О.І. і підтвердив переклад правильним одноразовим паролем з програми. Такий тип атаки називається man-in-the-browser (MitB).
Фундаментальна помилка Яндекс.Денег в тому, що за допомогою одноразового пароля з програми вони перевіряють справжність користувача, тоді як необхідно перевіряти справжність транзакції. І Яндекс.Деньги не перші, хто робить цю помилку. Говорячи про банках, відомий криптограф і фахівець в області IT безпеки Брюс Шнайер, писав про небезпеку підміни аутентифікації транзакції аутентификацией користувача ще в 2005 році : "By concentrating on authenticating the individual rather than authenticating the transaction, banks are forced to defend against criminal tactics rather than the crime itself.". У підсумку, та захист, що є зараз, допоможе користувачеві Яндекс.Денег зберегти свої гроші якщо у нього вкрали пароль, але не допоможе, якщо в його браузер впроваджений спеціально написаний троян.
Так чи складно написати такий троян? Для цього достатньо кваліфікації середнього програміста, знайомого з javascript і суттю атаки.
Всі основні браузери дозволяють розширювати і доповнювати свою функціональність за допомогою браузерних розширень. Розширення як правило пишуться на javascript і їм є зміст будь-якої сторінки, яку відвідує користувач, більш того, вони можуть його змінювати. Наприклад, є розширення, які блокують рекламу або попереджають користувача, коли він відвідує потенційно небезпечні сайти.
Підміна даних транзакції в Яндекс.Деньгах може бути легко зроблена за допомогою браузерного розширення. Для демонстрації я витратив трохи часу, щоб написати таке proof-of-concept розширення для браузера Google Chrome . Розширення активується тільки коли користувач заходить в свій особистий кабінет в Яндекс.Деньгах і намагається поповнити телефон за допомогою Яндекс.Денег ( «Товари та послуги» далі «Мобільний зв'язок») на суму менше 20 рублів. Номер телефону, який вводить користувач, розширення замінить на номер + 1, тобто наприклад якщо користувач хоче покласти гроші на номер (903) 555 5555, то гроші реально потраплять на номер (903) 555 5556. Розширення попереджає про те, що номер підмінений. Будь-, кому не шкода втратити невелику суму до 20 рублів, може поставити це розширення в свій браузер Chrome і спробувати поповнити свій номер Яндекс.Деньгами, потім перевірити в історії транзакцій, що реально гроші пішли на номер + 1. (Якщо ви введете свій номер мінус 1, то гроші потраплять на ваш реальний номер). Саме розширення дуже просте, його вихідний код я виклав на github . Публікація розширення і вихідного коду призначена тільки для ознайомлення і для того, щоб показати, що підміна даних в браузері не представляє ніякої складності.
Очевидно, що атакуючий, який хотів би позбавити користувачів їх Яндекс.Денег, міг би написати розширення, яке підміняє дані транзакції, і рекламувати його як розширення яке блокує рекламу, дозволяє побачити, хто заходив на вашу сторінку Вконтакте і т.д. Знайдеться чимало користувачів, які його встановлять, і при черговій виплаті Яндекс.Деньгами їх платіж буде перенаправлений на реквізити атакуючого.
Зазначена вразливість безпосередньо стосується користувачів Яндекс.Денег, які вибрали в налаштуваннях підтвердження транзакцій за допомогою одноразових паролів в додатку. Ті, хто вибрали SMS, краще захищені, тому що мають можливість контролювати зміст транзакції, яку вони підтверджують. Однак і для них картина не така райдужна, бо Яндекс.Деньги надали потенційним хакерам ще одну лазівку - аварійні коди.
Аварійні коди дозволяють користувачам підтверджувати транзакції, коли немає можливості підтвердити транзакцію звичайним способом, наприклад, коли поруч немає телефону або не доходить SMS. Користувачі роздруковують аварійні коди заздалегідь і використовують в таких надзвичайних ситуаціях. По суті, це ті ж одноразові паролі, і, також як і одноразові паролі з програми, вони страждають тим же недоліком: дозволяють підтвердити справжність користувача, але не справжність транзакції. Тому при підтвердженні аварійними кодами атакуючий знову може підробити вміст транзакції (суму та реквізити отримувача), і ні користувач, ні Яндекс.Деньги нічого не помітять до того, як транзакція буде виконана. Атакуючому не обов'язково чекати того моменту коли користувач сам добровільно скористається аварійними кодами - його троян може видавати користувачу неправдиві повідомлення про помилки про те, що нібито «не вдалося відправити SMS, скористайтеся, будь ласка, аварійними кодами».
Оскільки про атаки типу MitB відомо вже більше 10 років і їх реалізація гранично проста, а незахищеність Яндекс.Денег по відношенню до MitB видно неозброєним поглядом, цілком ймовірно, що користувачі Яндекс.Денег вже неодноразово піддавалися таким атакам і втрачали гроші.
Я написав Яндекс.Деньги про існуючі вразливості, і ось що отримав у відповідь:
Ми знаємо про існування MitB. Але, в даному випадку, описаний сценарій складно вважати вразливістю сервісу. Як ви розумієте, подібний сценарій можливий не тільки з сервісом Яндекс.Денег, але і з будь-яким сайтом. Ми робимо все можливе, щоб убезпечити платежі на своєму боці, а користувачі за умовами угоди користувача (п.4.21.7) повинні забезпечити безпеку з'єднання і комп'ютера, використовуючи звичайні засоби захисту (антивірус і т.д). Проте, заходи щодо захисту від атак типу MitB нами теж опрацьовуються.
Таким чином, Яндекс.Деньги визнають марність існуючих заходів захисту проти атак типу MitB і помилково вважають, що проти таких атак не захищений ніхто. Це означає, що гроші на гаманці в Яндекс.Деньгах захищені так само добре (або також погано), як і комп'ютер, на якому працює користувач, а другий фактор захисту, яким повинен бути одноразовий пароль, не працює. Таким чином, весь цей ритуал з переписуванням шести нічого не значущих цифр з телефону в комп'ютер створює лише помилкове відчуття безпеки (це називається security theater) і не захищає від однієї з найбільш легко експлуатованих загроз.
Ми в TeddyID робимо телефон повноцінним другим фактором захисту . Незалежно від того, що є першим фактором захисту і як він міг бути скомпрометований (вкрадений пароль, фішинг, MitB, ...), на телефоні користувач побачить справжній зміст транзакції, і якщо воно не відповідає очікуванням користувача, він просто натисне кнопку «Ні» та транзакція буде скасована. Таким чином, користувач зможе зберегти свої гроші навіть якщо його комп'ютер вражений трояном (MitB). Якщо ж з транзакцією все в порядку, користувач просто натисне кнопку «Так». Це підтвердження автентичності транзакції і це повний контроль користувача над транзакцією. А також фантастична простота використання - користувач натискає всього лише одну кнопку, ніяких кодів, ніяких переписувань безглуздих цифр.
Що робити користувачам поки Яндекс.Деньги опрацьовують заходи щодо захисту від атак типу MitB? Якщо ви не можете на 100% бути впевненими, що ні підхопите ніякої троян, то перейдіть на паролі в SMS, якщо зараз підтверджуєте транзакції за допомогою одноразових паролів з програми, а також не використання аварійних кодів. Але більш правильно, якщо Яндекс.Деньги самі не будуть пропонувати користувачам свідомо небезпечні опції: одноразові паролі з програми і аварійні коди.
Я розповів про цю уразливість в Яндекс.Деньгах для того щоб допомогти пересічним користувачам відрізняти реальну багаторівневий захист від security theater. А також застерегти інші сервіси від повторення помилки, яка відома вже більше 10 років. Для них, ми не тільки заявляємо про проблему, а й пропонуємо продукт для надійної двухфакторной захисту .
Тут чогось не вистачає?Так чи складно написати такий троян?
Деньги опрацьовують заходи щодо захисту від атак типу MitB?