Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Készítette: Rick Anderson
A helyek közötti szkriptelés (XSS) egy biztonsági rés, amely lehetővé teszi, hogy a kiberbűnözők ügyféloldali szkripteket (általában JavaScriptet) helyezzenek el a weboldalakon. Amikor más felhasználók betöltik az érintett oldalakat, a kiberattacker szkriptjei futnak, lehetővé téve a kiberbűnöző számára a cookie-k és munkamenet-jogkivonatok ellopását, a weblap tartalmának MÓDOSÍTÁSÁT DOM-manipulációval, vagy a böngésző átirányítását egy másik oldalra. Az XSS biztonsági rései általában akkor fordulnak elő, ha egy alkalmazás felhasználói bemenetet használ, és azokat egy lapra irányítja ellenőrzés, kódolás vagy menekülés nélkül.
Ez a cikk elsősorban az ASP.NET Core MVC-hez vonatkozik, amely nézetekkel, oldalakkal és más olyan alkalmazásokkal rendelkezik, Razor amelyek olyan HTML-t adnak vissza, amely sebezhető lehet az XSS-sel szemben. Azok a webes API-k, amelyek HTML, XML vagy JSON formátumban adnak vissza adatokat, XSS-támadásokat aktiválhatnak az ügyfélalkalmazásaikban, ha nem megfelelően fertőtlenítik a felhasználói bemenetet attól függően, hogy az ügyfélalkalmazás mennyire bízik az API-ban. Ha például egy API elfogadja a felhasználó által létrehozott tartalmat, és HTML-válaszban adja vissza, a kiberbűnözők rosszindulatú szkripteket injektálhatnak a felhasználó böngészőjében a válasz megjelenítésekor végrehajtó tartalomba.
Az XSS-támadások megakadályozása érdekében a webes API-knak bemeneti ellenőrzést és kimeneti kódolást kell implementálniuk. A bemeneti ellenőrzés biztosítja, hogy a felhasználói bemenet megfeleljen a várt feltételeknek, és ne tartalmazzon rosszindulatú kódot. A kimeneti kódolás biztosítja, hogy az API által visszaadott adatok megfelelően legyenek megtisztítva, hogy a felhasználó böngészője ne hajthassa végre kódként. További információkért tekintse meg ezt a GitHub-problémát.
Az alkalmazás védelme az XSS ellen
Alapszinten az XSS úgy működik, hogy becsapja az alkalmazást egy <script> címke beszúrásával a renderelt lapra, vagy egy On* esemény elembe való beszúrásával. A fejlesztőknek az alábbi megelőzési lépéseket kell követniük az XSS alkalmazásba való bevezetésének elkerülése érdekében:
- Soha ne tegyen nem megbízható adatokat a HTML-bemenetbe, hacsak nem követi az alábbi lépéseket. A nem megbízható adatok olyan adatok, amelyeket egy kiberbűnöző szabályozhat, például HTML-űrlapbemenetek, lekérdezési sztringek, HTTP-fejlécek vagy akár adatbázisból származó adatforrások, mivel a kibertámadások akkor is feltörhetik az adatbázist, ha nem tudják feltörni az alkalmazást.
- Mielőtt nem megbízható adatokat helyez egy HTML-elembe, győződjön meg arról, hogy HTML-kódolású. A HTML-kódolás olyan karaktereket, mint például <, biztonságos formába alakítja át, például <.
- Mielőtt nem megbízható adatokat helyez egy HTML-attribútumba, győződjön meg arról, hogy a HTML-attribútum kódolva van. A HTML-kódolás ezen speciális formája kettős idézőjeleket ("), egyszeri idézőjeleket ('), ampersands (>) és kisebb (<) karaktereket kezel. A nem megbízható bemenetek kezelésekor használjon HTML-kódolást az általános HTML-tartalmakhoz és HTML-attribútumok kódolását a HTML-attribútumok esetében.
- Mielőtt nem megbízható adatokat helyez a JavaScriptbe, helyezze az adatokat egy HTML-elembe, amelynek tartalmát futásidőben kéri le. Ha ez nem lehetséges, győződjön meg arról, hogy az adatok JavaScript-kódolásúak. A JavaScript veszélyes karaktereit úgy kódolja, hogy azok hexadecimális ábrázolásra cserélődnek, például a < kódolása
\u003Cformában történik. - Mielőtt nem megbízható adatokat helyez egy URL-lekérdezési sztringbe, győződjön meg arról, hogy az URL-cím kódolva van.
HTML-kódolás a következő használatával: Razor
Az Razor motor, amelyet az MVC használ, automatikusan kódolja a változókból eredő összes kimenetet, hacsak nem tesz nagyon sokat azért, hogy ezt megakadályozza. Html-attribútumkódolási szabályokat használ az @ irányelv használatakor. Mivel a HTML-attribútumok kódolása a HTML-kódolás szuperhalmaza, ez azt jelenti, hogy nem kell foglalkoznia azzal, hogy HTML-kódolást vagy HTML-attribútumkódolást kell-e használnia. Győződjön meg arról, hogy a @-t csak HTML-környezetben használja, nem pedig akkor, ha nem megbízható bemenetet próbál közvetlenül a JavaScriptbe beszúrni. A címkesegédek a címkeparaméterekben használt bemenetet is kódolni fogják.
Tekintse meg a következő Razor nézetet:
@{
var untrustedInput = "<\"123\">";
}
@untrustedInput
Ez a nézet a nem megbízhatóInput változó tartalmát adja ki. Ez a változó tartalmaz néhány karaktert, amelyeket az XSS-támadásokban használnak, nevezetesen <a " és >a . A forrás vizsgálata a renderelt kimenetet a következőképpen kódolja:
<"123">
Figyelmeztetés
ASP.NET Core MVC olyan osztályt HtmlString biztosít, amely nem lesz automatikusan kódolva a kimenet alapján. Ezt soha nem szabad nem megbízható bemenettel kombinálni, mivel ez egy XSS-biztonsági rést tesz elérhetővé.
JavaScript-kódolás a következő használatával: Razor
Előfordulhat, hogy be szeretne szúrni egy értéket a JavaScriptbe a nézetben való feldolgozáshoz. Ezt kétféleképpen teheti meg. Az értékek beszúrásának legbiztonságosabb módja, ha az értéket egy címke adatattribútumában helyezi el, és lekéri a JavaScriptben. Például:
@{
var untrustedInput = "<script>alert(1)</script>";
}
<div id="injectedData"
data-untrustedinput="@untrustedInput" />
<div id="scriptedWrite" />
<div id="scriptedWrite-html5" />
<script>
var injectedData = document.getElementById("injectedData");
// All clients
var clientSideUntrustedInputOldStyle =
injectedData.getAttribute("data-untrustedinput");
// HTML 5 clients only
var clientSideUntrustedInputHtml5 =
injectedData.dataset.untrustedinput;
// Put the injected, untrusted data into the scriptedWrite div tag.
// Do NOT use document.write() on dynamically generated data as it
// can lead to XSS.
document.getElementById("scriptedWrite").innerText += clientSideUntrustedInputOldStyle;
// Or you can use createElement() to dynamically create document elements
// This time we're using textContent to ensure the data is properly encoded.
var x = document.createElement("div");
x.textContent = clientSideUntrustedInputHtml5;
document.body.appendChild(x);
// You can also use createTextNode on an element to ensure data is properly encoded.
var y = document.createElement("div");
y.appendChild(document.createTextNode(clientSideUntrustedInputHtml5));
document.body.appendChild(y);
</script>
Az előző korrektúra a következő HTML-t hozza létre:
<div id="injectedData"
data-untrustedinput="<script>alert(1)</script>" />
<div id="scriptedWrite" />
<div id="scriptedWrite-html5" />
<script>
var injectedData = document.getElementById("injectedData");
// All clients
var clientSideUntrustedInputOldStyle =
injectedData.getAttribute("data-untrustedinput");
// HTML 5 clients only
var clientSideUntrustedInputHtml5 =
injectedData.dataset.untrustedinput;
// Put the injected, untrusted data into the scriptedWrite div tag.
// Do NOT use document.write() on dynamically generated data as it can
// lead to XSS.
document.getElementById("scriptedWrite").innerText += clientSideUntrustedInputOldStyle;
// Or you can use createElement() to dynamically create document elements
// This time we're using textContent to ensure the data is properly encoded.
var x = document.createElement("div");
x.textContent = clientSideUntrustedInputHtml5;
document.body.appendChild(x);
// You can also use createTextNode on an element to ensure data is properly encoded.
var y = document.createElement("div");
y.appendChild(document.createTextNode(clientSideUntrustedInputHtml5));
document.body.appendChild(y);
</script>
Az előző kód a következő kimenetet hozza létre:
<script>alert(1)</script>
<script>alert(1)</script>
<script>alert(1)</script>
Figyelmeztetés
NE fűzz össze nem megbízható bemenetet a JavaScriptben DOM-elemek létrehozásához vagy dinamikusan létrehozott tartalomhoz való használatáhozdocument.write().
Az alábbi módszerek egyikével megakadályozhatja, hogy a kód a DOM-alapú XSS-nek legyen kitéve:
-
createElement()tulajdonságértékek hozzárendelése megfelelő módszerekkel vagy tulajdonságokkal, példáulnode.textContent=vagynode.InnerText=. -
document.CreateTextNode()és fűzze hozzá a megfelelő DOM-helyen. element.SetAttribute()element[attribute]=
Kódkódolók elérése
A HTML-, JavaScript- és URL-kódolók kétféleképpen érhetők el a kódhoz:
- Függőségi injektáláson keresztül illessze be őket.
- Használja a névtérben
System.Text.Encodings.Webtalálható alapértelmezett kódolókat.
Az alapértelmezett kódolók használatakor a biztonságosként kezelendő karaktertartományokra alkalmazott testreszabások nem lépnek érvénybe. Az alapértelmezett kódolók a lehető legbiztonságosabb kódolási szabályokat használják.
A konfigurálható kódolók DI-en keresztüli használatához a konstruktoroknak szükség szerint egy HtmlEncoder, JavaScriptEncoder és UrlEncoder paramétert kell használniuk. Például;
public class HomeController : Controller
{
HtmlEncoder _htmlEncoder;
JavaScriptEncoder _javaScriptEncoder;
UrlEncoder _urlEncoder;
public HomeController(HtmlEncoder htmlEncoder,
JavaScriptEncoder javascriptEncoder,
UrlEncoder urlEncoder)
{
_htmlEncoder = htmlEncoder;
_javaScriptEncoder = javascriptEncoder;
_urlEncoder = urlEncoder;
}
}
URL-paraméterek kódolása
Ha nem megbízható bemenettel rendelkező URL-lekérdezési sztringet szeretne építeni, az érték kódolásához használja a UrlEncoder elemet. Például
var example = "\"Quoted Value with spaces and &\"";
var encodedValue = _urlEncoder.Encode(example);
A kódolás után a kódoltValue változó tartalmazza a következőt %22Quoted%20Value%20with%20spaces%20and%20%26%22: . A szóközök, idézőjelek, írásjelek és egyéb nem biztonságos karakterek a hexadecimális értékükhöz vannak kódolva, például egy szóköz karakter %20lesz.
Figyelmeztetés
Ne használjon nem megbízható bemenetet URL-elérési út részeként. Mindig adjon meg nem megbízható bemenetet lekérdezési sztringértékként.
A Kódolók testreszabása
Alapértelmezés szerint a kódolók az egyszerű latin Unicode-tartományra korlátozott biztonságos listát használnak, és az adott tartományon kívüli karaktereket a karakterkód megfelelőiként kódolják. Ez a viselkedés a TagHelper és a HtmlHelper renderelésére is hatással van, mivel a kódolókkal adja ki a karakterláncokat Razor.
Ennek indoka az ismeretlen vagy jövőbeli böngészőhibák elleni védelem (a korábbi böngészőhibák megbotlották a nem angol karakterek feldolgozása alapján történő elemzést). Ha a webhely nem latin karaktereket használ, például kínai, cirill vagy más karaktereket, akkor valószínűleg nem ez a viselkedés.
A kódoló biztonságos listái testre szabhatók úgy, hogy tartalmazzák az alkalmazásnak megfelelő Unicode-tartományokat az indítás során a következő helyen Program.cs:
Az alapértelmezett konfigurációt például az Razor alábbihoz hasonló HtmlHelper használatával használhatja:
<p>This link text is in Chinese: @Html.ActionLink("汉语/漢語", "Index")</p>
Az előző korrektúra kínai kódolású szöveggel jelenik meg:
<p>This link text is in Chinese: <a href="/">汉语/漢語</a></p>
A kódoló által biztonságosként kezelt karakterek kibővítéséhez szúrja be a következő sort: Program.cs.
builder.Services.AddSingleton<HtmlEncoder>(
HtmlEncoder.Create(allowedRanges: new[] { UnicodeRanges.BasicLatin,
UnicodeRanges.CjkUnifiedIdeographs }));
Testre szabhatja a kódoló biztonságos listáit úgy, hogy az alkalmazásnak megfelelő Unicode-tartományokat tartalmazzon az indítás során.ConfigureServices()
Például az alapértelmezett konfigurációt használva így használhatja a Razor HtmlHelper-t:
<p>This link text is in Chinese: @Html.ActionLink("汉语/漢語", "Index")</p>
Amikor megtekinti a weblap forrását, láthatja, hogy az a következőképpen lett renderelve, a kínai szöveg kódolással;
<p>This link text is in Chinese: <a href="/">汉语/漢語</a></p>
A kódoló által biztonságosként kezelt karakterek körének szélesítéséhez illessze be a következő sort a ConfigureServices() metódusába a startup.cs helyére.
services.AddSingleton<HtmlEncoder>(
HtmlEncoder.Create(allowedRanges: new[] { UnicodeRanges.BasicLatin,
UnicodeRanges.CjkUnifiedIdeographs }));
Ez a példa kibővíti az engedélyezett listát, hogy tartalmazza a Unicode-tartomány CJK Unified Ideographs. A renderelt kimenet mostantól a következő lesz
<p>This link text is in Chinese: <a href="/">汉语/漢語</a></p>
A biztonságos listatartományok Unicode-kóddiagramként vannak megadva, nem nyelvekként. A Unicode szabvány a karaktereket tartalmazó diagramok kereséséhez használható kóddiagramok listáját tartalmazza. Minden kódolót, HTML-t, JavaScriptet és URL-címet külön kell konfigurálni.
Megjegyzés:
A biztonságos lista testreszabása csak a DI-en keresztül forrásként használt kódolókat érinti. Ha közvetlenül hozzáfér egy kódolóhoz a System.Text.Encodings.Web.*Encoder.Default segítségével, akkor az alapértelmezett, csak egyszerű latin betűs biztonságos lista kerül használatra.
Hol történjen a kódolás?
Az általánosan elfogadott gyakorlat az, hogy a kódolás a kimenet helyén történik, és a kódolt értékeket soha nem szabad adatbázisban tárolni. A kódolás a kimenetnél lehetővé teszi az adatok felhasználásának megváltoztatását, például HTML-ről lekérdezési sztringértékre. Emellett lehetővé teszi az adatok egyszerű keresését anélkül, hogy értékeket kellene kódolnia a keresés előtt, és kihasználhatja a kódolók által végzett módosításokat vagy hibajavításokat.
Az érvényesítés, mint XSS-megelőzési technika
Az érvényesítés hasznos eszköz lehet az XSS-támadások korlátozásában. Például egy olyan numerikus sztring, amely csak a 0-9 karaktert tartalmazza, nem indít el XSS-támadást. Az érvényesítés bonyolultabbá válik a HTML felhasználói bemenetben való elfogadásakor. A HTML-bemenet elemzése nehéz, ha nem lehetetlen. A Markdown egy beágyazott HTML-et csíkozó elemzővel párosítva biztonságosabb megoldás a gazdag bemenetek elfogadásához. Soha ne támaszkodjon egyedül az ellenőrzésre. A kimenet előtt mindig kódolja a nem megbízható bemeneteket, függetlenül attól, hogy milyen ellenőrzést vagy fertőtlenítést hajtottak végre.