Cross-site scripting атаките са лесни за подценяване. Отгоре изглеждат като „някой хакер може да изпълнява alert
в браузъра на потребителите“, но е по-дълбоко. Ще ви разкажа за определен тип уязвимост, която често виждам да се подценява, а е много лесна са сериозна експлоатация.
Именно „има XSS през URL параметър, но той не се записва в базата“.
Пример
Нека си представим, че говорим за online магазин. Някъде в него има следния код:
<h1><? echo $_GET['title'] ?></h1>
Ако това е достъпно http://example.com/hack, то на следното URL е проблематично:
Ако потребителя го отвори, ще изпълни alert('hi')
.
Въпреки това, този текст не се записва в базата. Няма как злонамерен човек да го изпълни в браузърите на останалите потребители. Единственият начин е да им изпрати URL-то по друг канал. Това може да е много трудно (един клиент обикновено не знае за другите) и слабо ефективно (по-опитни потребители ще разпознаят URL-то, много други няма да го отворят въобще).
И все пак, как това може да се експлоатира сериозно? Един вариант е чрез търговските представители (a.k.a. customer support).
Атаката
Ето как един „хакер“ може да се възползва от уязвимостта.
- Харесва си един продукт.
- Създава URL с JS код, който бърка в cookie-тата, вади session_id-то и го праща на друга система (например чрез GET). След това прави redirect към продукта.
- Минава адреса през bit.ly за да го направи по-малко притеснителен.
- Пише на support-а с въпрос като „Този продукт имате ли го наличен?“ или „Харесал съм тези две неща, кое бихте ми препоръчали“ и bit.ly адреса. От гледна точка на търговския представител това е валиден въпрос, на който иска да отговори.
- Две неща са много вероятни за support-а – (1) да не са силни технически и (2) да имат повече права в системата (или дори да са админи). Вероятно е да отвори линка и атакуващия да получи session_id-то му. Също е вероятно да не отрази артефактите около редиректа след първоначалното отваряне. Съответно, линка бива отворен.
- Атакуващия получава session_id-то и вече може да се log-не като support. Ако има админ права, може да ползва това за каквото си поиска (например да си даде 100% отстъпка за продукт). Ако няма – може да се ползва като стъпка към някакъв social engineering (ако има вътрешна messaging система, може да се представи за служител).
Безопасно на пръв поглед, но ето как резултира до админски достъп.
Вариации, защита и уточнения
Реалния свят обикновено не е толкова прост. Ред неща биха могли да бъдат различни и за двете страни:
- Магазина може да пази IP адресите заедно със session_id-тата. Това обикновено е непрактично, понеже много хора имат динамични адреси. Също, има по-добри решения.
- Сесията може да ползва HTTP-only cookie-та, които са недостъпни за JavaScript-а.
- Горните две предотвратяват само достъпа до cookie-та. Не биха защитавали от това атакуващия да изпълнява действия от името на потребителя:
POST /logout
за безопасен пример,DELETE /my_account
за по-опасен. - Customer support-а би могъл да е обучен как да се пази от такива неща или да ползва система която им помага (например нещо като магически Zendesk, който не ти позволява да отваряш XSS връзки). Това е добре да се направи, но винаги оставя възможността за човешка грешка (или пращане на линк в „извънработен“ канал като Facebook или Twitter).
Като цяло, най-сигурния начин да се пазите от това е да нямате XSS уязвимости. Което обикновено се казва по-лесно, отколкото се прави.
TL;DR
XSS атаките са лесни за подценяване най-вече защото са сложни и завъртяни. В сравнение с тях SQL injection-а е тривиален за разбиране – всеки схваща защо е лошо да може да изпълни DROP TABLE users
с GET заявка. При XSS трябва повече подготовка, строене на сложно URL и дори пускане на сървър някъде другаде, който може да приема „открадната информация“. Въпреки това, привидно незначителни уязвимости могат да се окажат сериозни.
Не подценявайте XSS.
alert(1)