tässä osiossa kuvataan joitakin yleisiä periaatteita, joilla estetään sivuston rajat ylittäviä skriptaushaavoittuvuuksia ja tapoja käyttää erilaisia yhteisiä tekniikoita suojautumiseen XSS-hyökkäyksiltä.
Cross-site scripting prevention voidaan yleensä saavuttaa kahdella puolustuskerroksella:
- koodaa tiedot tuotoksesta
- validoi syöte saavuttaessa
voit käyttää Burp skanneri skannata web-sivustoja lukuisia tietoturva-aukkoja, kuten XSS. Burp: n huippuluokan skannauslogiikka jäljittelee taitavan hyökkääjän toimia ja pystyy vastaavasti peittämään XSS: n haavoittuvuudet. Voit käyttää Burp-skanneria saadaksesi varmuuden siitä, että puolustuksesi XSS-hyökkäyksiä vastaan toimii tehokkaasti.
koodaa tiedot ulostulosta
koodaus tulee käyttää suoraan ennen käyttäjän hallittavissa olevan tiedon kirjoittamista sivulle, koska konteksti, johon kirjoitat, määrittää, millaista koodausta sinun tulee käyttää. Esimerkiksi JavaScript-merkkijonon sisällä olevat arvot vaativat erilaista pakenemista kuin HTML-kontekstissa olevat arvot.
HTML-kontekstissa ei-whitelistatut arvot tulisi muuntaa HTML-entiteeteiksi:
-
<
muuntaa:<
-
>
muuntaa:>
JavaScript-merkkijonoyhteydessä ei-aakkosnumeeristen arvojen tulisi olla Unicode-karanneita:
-
<
muuntaa:\u003c
-
>
muuntaa:\u003e
joskus sinun täytyy soveltaa useita kerroksia koodaus, oikeassa järjestyksessä. Esimerkiksi, turvallisesti upottaa käyttäjän syöttää sisällä tapahtuman käsittelijä, sinun täytyy käsitellä sekä JavaScript yhteydessä ja HTML yhteydessä. Joten sinun täytyy ensin Unicode-paeta Tulo, ja sitten HTML-koodata se:
<a href="#" onclick="x='This string needs two layers of escaping'">test</a>
validoi tulo saavuttaessa
koodaus on luultavasti XSS: n puolustuksen tärkein linja, mutta se ei riitä estämään XSS: n haavoittuvuuksia joka asiayhteydessä. Sinun pitäisi myös vahvistaa syöte mahdollisimman tiukasti siinä vaiheessa, kun se on ensimmäisen kerran vastaanotettu käyttäjältä.
esimerkkejä syöttötietojen validoinnista ovat:
- jos käyttäjä lähettää URL-osoitteen, joka palautetaan vastauksissa, vahvistaen, että se alkaa turvallisella protokollalla, kuten HTTP ja HTTPS. Muuten joku saattaa hyödyntää sivustoasi haitallisella protokollalla, kuten
javascript
taidata
. - jos käyttäjä antaa arvon, jonka se oletti olevan numeerinen, hän vahvistaa, että arvo sisältää kokonaisluvun.
- tämän syöteen validointi sisältää vain odotetun joukon merkkejä.
Syötevalidoinnin pitäisi mieluiten toimia estämällä virheellinen syöte. Vaihtoehtoinen lähestymistapa, jolla yritetään puhdistaa virheellinen syöte, jotta se olisi pätevä, on virhealtis ja sitä olisi vältettävä aina, kun se on mahdollista.
Whitelisting vs. blacklisting
Input validation-menetelmässä olisi yleensä käytettävä mustaluetteloiden sijasta whitelistejä. Esimerkiksi sen sijaan, että yritettäisiin tehdä lista kaikista haitallisista protokollista (javascript
, data
jne.), yksinkertaisesti tehdä listan turvallinen protokollia (HTTP, HTTPS) ja kieltää mitään ei luettelossa. Tämä varmistaa, että puolustuksesi ei murru, kun uusia haitallisia protokollia ilmestyy ja tekee siitä vähemmän alttiita hyökkäyksille, jotka pyrkivät hämärtämään virheellisiä arvoja välttääkseen mustan listan.
”turvallisen” HTML
sallimista käyttäjille HTML-merkinnän julkaisemiseksi tulisi välttää aina, kun se on mahdollista, mutta joskus se on liiketoiminnan vaatimus. Esimerkiksi blogisivusto saattaa sallia kommenttien julkaisemisen, jotka sisältävät jonkin verran rajoitettua HTML-merkintää.
klassinen lähestymistapa on yrittää suodattaa pois mahdollisesti haitalliset tunnisteet ja JavaScript. Voit yrittää toteuttaa tämän käyttämällä turvallisten tunnisteiden ja attribuuttien whitelistiä, mutta selainten jäsennysmoottoreiden ja mutaatio XSS: n kaltaisten omituisuuksien ansiosta tätä lähestymistapaa on erittäin vaikea toteuttaa turvallisesti.
vähiten huono vaihtoehto on käyttää JavaScript-kirjastoa, joka suorittaa suodatuksen ja koodauksen käyttäjän selaimessa, kuten DOMPurify. Muut kirjastot antavat käyttäjille mahdollisuuden tarjota sisältöä markdown-muodossa ja muuntaa markdown HTML: ksi. Valitettavasti kaikissa näissä kirjastoissa on ajoittain XSS-haavoittuvuuksia, joten tämä ei ole täydellinen ratkaisu. Jos käytät yhtä, sinun pitäisi seurata tarkasti tietoturvapäivityksiä.
Note
JavaScriptin lisäksi muu sisältö, kuten CSS ja jopa tavallinen HTML voivat olla joissain tilanteissa haitallisia.
hyökkäykset käyttäen haitallista CSS
Miten estää XSS käyttämällä template engine
monet nykyaikaiset verkkosivustot käyttävät palvelinpuolen template-moottoreita kuten Twig ja Freemarker upottamaan dynaamista sisältöä HTML: ään. Nämä määrittelevät tyypillisesti Oman pakojärjestelmänsä. Esimerkiksi Twigissä voidaan käyttää e()
– suodatinta, jonka argumentti määrittelee asiayhteyden:
{{ user.firstname | e('html') }}
jotkin muut template-moottorit, kuten Jinja ja React, pakenevat oletusarvoisesti dynaamista sisältöä, joka estää tehokkaasti useimmat XSS: n esiintymät.
suosittelemme tarkistamaan pakoominaisuudet tarkasti, kun arvioit, käytetäänkö tiettyä mallimoottoria tai kehystä.
Huomautus
jos suoraan yhdistät käyttäjän syötteen mallinimiin, olet altis palvelinpuolen mallineulokselle, joka on usein vakavampi kuin XSS.
miten XSS voidaan estää PHP: ssä
PHP: ssä on sisäänrakennettu funktio koodata entiteettejä, joita kutsutaan nimellä htmlentities
. Sinun pitäisi kutsua tätä toimintoa paeta syötettäsi, kun sisällä HTML-kontekstissa. Funktiota kutsutaan kolmella argumentilla:
- syöttönarusi.
-
ENT_QUOTES
, joka on lippu, joka määrittää kaikki lainausmerkit on koodattava. - merkistö, jonka tulisi useimmissa tapauksissa olla UTF-8.
esimerkiksi:
<?php echo htmlentities($input, ENT_QUOTES, 'UTF-8');?>
kun JavaScript merkkijono yhteydessä, sinun täytyy Unicode-paeta syöte kuten jo kuvattu. Valitettavasti PHP ei tarjoa API Unicode-escape a string. Tässä on joitakin koodi tehdä, että PHP:
<?php
function jsEscape($str) {
$output = '';
$str = str_split($str);
for($i=0;$i<count($str);$i++) {
$chrNum = ord($str);
$chr = $str;
if($chrNum === 226) {
if(isset($str) && ord($str) === 128) {
if(isset($str) && ord($str) === 168) {
$output .= '\u2028';
$i += 2;
continue;
}
if(isset($str) && ord($str) === 169) {
$output .= '\u2029';
$i += 2;
continue;
}
}
}
switch($chr) {
case "'":
case '"':
case "\n";
case "\r";
case "&";
case "\";
case "<":
case ">":
$output .= sprintf("\u%04x", $chrNum);
break;
default:
$output .= $str;
break;
}
}
return $output;
}
?>
näin käytät jsEscape
– funktiota PHP: ssä:
<script>x = '<?php echo jsEscape($_GET)?>';</script>
Vaihtoehtoisesti voit käyttää template-moottoria.
Miten estää XSS client-puolella JavaScript
paeta käyttäjän syöttää HTML yhteydessä JavaScript, tarvitset oman HTML kooderi, koska JavaScript ei tarjoa API koodata HTML. Tässä on esimerkki JavaScript-koodi, joka muuntaa merkkijono HTML entities:
function htmlEncode(str){
return String(str).replace(//gi, function(c){
return '&#'+c.charCodeAt(0)+';';
});
}
tämän jälkeen voit käyttää tätä toimintoa seuraavasti:
<script>document.body.innerHTML = htmlEncode(untrustedValue)</script>
jos syöte on JavaScript-merkkijonon sisällä, tarvitset kooderin, joka suorittaa Unicode-pakenemisen. Tässä on näyte Unicode-kooderi:
function jsEscape(str){
return String(str).replace(//gi, function(c){
return '\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4);
});
}
tämän jälkeen voit käyttää tätä toimintoa seuraavasti:
<script>document.write('<script>x="'+jsEscape(untrustedValue)+'";<\/script>')</script>
XSS: n estäminen jqueryssä
yleisin XSS: n muoto jqueryssä on, kun käyttäjä syöttää jQuery-valitsimelle. Web-kehittäjät käyttäisivät usein location.hash
ja välittäisivät sen valitsimelle, joka aiheuttaisi XSS: n jQueryn renderöidessä HTML: n. jQuery tunnisti tämän ongelman ja paikkasi valintalogiikkansa tarkistaakseen, alkaako syöttö hashilla. Nyt jQuery tekee HTML: ää vain, jos ensimmäinen merkki on <
. Jos syötät epäluotettavia tietoja jQuery-valitsimelle, varmista, että vältät arvon oikein käyttämällä yllä olevaa funktiota jsEscape
.
Mitigating XSS using content security policy (CSP)
Content security policy (CSP) on viimeinen puolustuslinja cross-site scriptingiä vastaan. Jos XSS-esto epäonnistuu, voit käyttää CSP: tä lieventämään XSS: ää rajoittamalla sitä, mitä hyökkääjä voi tehdä.
CSP: n avulla voi hallita erilaisia asioita, kuten sitä, voidaanko ulkoisia skriptejä ladata ja toteutetaanko inline-skriptejä. Jos haluat ottaa CSP: n käyttöön, sinun on sisällytettävä HTTP-vasteotsikko Content-Security-Policy
, jonka arvo sisältää käytäntösi.
esimerkki CSP on seuraava:
default-src 'self'; script-src 'self'; object-src 'none'; frame-src 'none'; base-uri 'none';
tämä käytäntö määrittää, että resurssit, kuten kuvat ja skriptit, voidaan ladata vain samasta alkuperästä kuin Pääsivu. Joten vaikka hyökkääjä voi onnistuneesti pistää XSS hyötykuorma he voivat vain ladata resursseja nykyisestä alkuperästä. Tämä vähentää huomattavasti hyökkääjän mahdollisuutta hyödyntää XSS-haavoittuvuutta.
jos tarvitset ulkoisten resurssien lataamista, varmista, että sallit sivustosi hyödyntämisen vain skripteillä, jotka eivät auta hyökkääjää. Jos esimerkiksi luetteloit tietyt verkkotunnukset, hyökkääjä voi ladata minkä tahansa skriptin kyseisiltä verkkotunnuksilta. Jos mahdollista, yritä isännöidä resursseja omalla verkkotunnuksellasi.
jos tämä ei ole mahdollista, voit käyttää hash – tai nonce-pohjaista käytäntöä salliaksesi skriptit eri alueilla. Nonce on satunnainen merkkijono, joka lisätään komentosarjan tai resurssin attribuutiksi ja joka suoritetaan vain, jos satunnainen merkkijono vastaa palvelimen luomaa merkkijonoa. Hyökkääjä ei pysty arvaamaan satunnaistettua merkkijonoa, eikä siksi voi kutsua komentosarjaa tai resurssia, jolla on voimassa oleva nonce, joten resurssia ei suoriteta.