Json: PHP zu JavaScript sicher oder nicht?

Lesezeit: 6 Minuten

Benutzer-Avatar
whamsicore

Ich verstehe, dass die Verwendung von eval(json_str) auf dem Client ist anfällig für bösartigen Code. Meine Frage ist, ob json_str war ein Array, das von der PHP-Funktion erstellt wurde json_encodewäre ich sicher?

Zum Beispiel,

json_str = json_encode(array(record1, 
                             record2, 
                             record3));

wäre es jetzt völlig sicher zu verwenden eval(json_str) im clientseitigen Code?

  • Verwenden Sie nicht eval. Es ist langsam und schwer zu debuggen. Benutze einen echter Parser

    – QUentin

    25. Juli 2011 um 13:26 Uhr

In Bezug auf reines JavaScript sind Sie sicher: die Ausgabe von json_encode kann niemals etwas anderes als statische Werte enthalten, die bei der Übergabe keine unerwarteten Nebeneffekte haben eval. (Obwohl Sie Ihre JSON-Zeichenfolge normalerweise mit umgeben müssen () beim Benutzen evalum zu vermeiden, dass ein Objektliteralausdruck fälschlicherweise als Anweisungsblock interpretiert wird.)

Abgesehen davon: Dies gilt nicht unbedingt für alle JSON-Encoder, da es einige Zeichen gibt, die roh in eine JSON-Zeichenfolge aufgenommen werden können, die in JavaScript nicht roh gültig sind. Am bemerkenswertesten sind U+2028 und U+2029, die in JavaScript-String-Literalen nicht unescaped bleiben können, da sie Zeilenumbrüche darstellen. Der Encoder von PHP codiert jedoch alle Nicht-ASCII-Zeichen (z "\u2028") also kein Problem hier.

In Bezug auf JavaScript, das in eine andere Sprache eingebettet ist (typischerweise: HTML), sind Sie nicht unbedingt sicher. Zum Beispiel:

<script type="text/javascript">
    var v= <?php echo json_encode($value); ?>;
</script>

In diesem Beispiel was wäre wenn value enthält einen String mit der Zeichenfolge </script? Dadurch würde der Wert den Skriptblock vorzeitig beenden und so in das HTML-Markup entkommen, wo er dann andere schädliche Skripte einschleusen könnte.

Um dieses Problem zu vermeiden, codieren Sie beim Einfügen von JSON-Inhalten in HTML immer die < Zeichen in Zeichenfolgenliteralen, wie \x3C oder, in JSON-konformen Begriffen, \u003C. Aus Gründen der Kompatibilität mit XHTML-Nicht-CDATA-Skriptblöcken tun & auch. Setzen Sie für die Kompatibilität mit JS-innerhalb von Event-Handler-Attributen auch Anführungszeichen.

PHP wird dies mit den richtigen Optionen für Sie tun json_encode():

var v= <?php echo json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); ?>;

(Möglicherweise möchten Sie eine Verknüpfungsfunktion definieren, um das Schreiben zu beschleunigen.)

  • Was passiert wenn json_encode wird böswillig von einer anderen Funktion überschrieben? Was passiert, wenn einige der Skripte unterwandert werden, um einen Virus zu übertragen? Es gibt keinen Grund, das zuzulassen gesamte Anwendung stürzt ab und brennt, nur weil Teil davon wurde kompromittiert.

    – zzzzBov

    25. Juli 2011 um 14:02 Uhr


  • @zzzzBov: Wenn eine deiner Funktionen überschrieben wurde, hast du schon komplett verloren. In JavaScript und PHP gibt es keine ausreichende Kapselung, um einen beliebigen Teil einer Anwendung vor einem anderen Teil davon zu schützen (es sei denn, Sie gehen mit mehreren Dokumenten unter Verwendung verschiedener Domänen), sodass durch den Aufruf einer Funktion absolut nichts weiter zu verlieren ist. Wenn Sie eine Funktion nicht aufrufen können, weil Sie befürchten, dass sie sabotiert wurde, werden Sie nicht viel (sprich: gar nichts) erreichen.

    – Bobin

    25. Juli 2011 um 16:23 Uhr


  • json_encode mit default flags slashes würde es also geben "<\/script>"das ist also in Ordnung <\/script> beendet das script-Tag in HTML nicht. Sie müssten explizit verwenden JSON_UNESCAPED_SLASHES Flagge, um davon gebissen zu werden.

    – Esailija

    1. August 2012 um 22:07 Uhr


  • @Esailija: Ja, das ist eine neue Funktion (und eine willkommene Standardeinstellung) in PHP 5.4. Brauchen wir wohl noch JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS bis diese Version weiter verbreitet ist, oder für Skript-in-XHTML-Kompatibilität.

    – Bobin

    2. August 2012 um 7:32 Uhr

  • @bobince, das ist nicht neu in PHP 5.4. echo json_encode(‘

    ‘) gibt <\/script> in PHP 5.2.9 aus

    – David Barnes

    29. Januar 2013 um 19:02 Uhr


Benutzer-Avatar
Mike

Wenn Sie verwenden möchten Inhaltssicherheitsrichtlinie (CSP), werden Sie daran gehindert, Inline-Skript-Tags auszuführen. Dies würde daher die ansonsten erstaunliche Antwort von Bobince unmöglich machen, da CSP erfordert, dass sich das gesamte JavaScript in separaten Dateien befindet.

So erhalten Sie Ihr JavaScript in einer separaten Datei:

Eine Möglichkeit, dies zu umgehen, besteht darin, den JSON mit PHP zu codieren (was XSS verhindern sollte) und ihn dann an ein verstecktes Element zurückzugeben und dann JavaScript zu verwenden, um den Inhalt dieses Tags abzurufen (angepasst von OWASP):

Setzen Sie dies inline (beachten Sie, dass es nicht wirklich ausgeführt wird):

<script id="jsonString" type="application/json">
<?php
// OWASP uses a <script> tag with an invalid "type" attribute, but 
// you can just as easily use a <span style="display:none"> or other
// hidden tag.
//
// Note, this probably won't actually be valid JSON because we are using 
// htmlspecialcharacters() on the JSON data. That doesn't matter because
// this is never actually executed by the browser due to the incorrect
// script type. We will decode it later into valid JSON.
echo htmlspecialchars(json_encode($object), ENT_NOQUOTES); 
?>
</script>

Dann in Ihrer JavaScript-Datei:

var dataElement = document.getElementById('jsonString');
// Get innerText, which also has the side effect of html decoding
// the string returned, which is just what we want
var jsonString = dataElement.textContent || dataElement.innerText;
// Now you can parse the JSON string
var jsonObj = JSON.parse(jsonString);

Benutzer-Avatar
zzzzov

Verwenden Sie eval nicht für das JSON-Parsing

Tu es nicht.

Es ist sehr wahrscheinlich, dass Ihr Server niemals kompromittiert wird und dass Ihre Anwendung größtenteils sicher ist, bla bla bla, das ist nicht der Punkt. Es ist möglich, dass ein Server teilweise kompromittiert wird (zu viele Angriffsvektoren, was wäre, wenn die php json_encode Funktion wurde auf Ihrem Server kompromittiert?).

Die einfache Lösung ist, nicht zu vertrauen irgendetwas gesendet von jeder. Moderne Browser haben native JSON-Parser und www.json.org bietet eine lange Liste von JSON-Parsern für verschiedene Sprachen. Die JS-Versionen greifen aus Geschwindigkeitsgründen auf die native Implementierung zurück.

Was das alles bedeutet, ist, dass es gibt kein triftiger grund benutzen eval für JSON-Parsing.

  • Wie sende ich mein Array genau von PHP an JS?

    – Whamsicore

    26. Juli 2011 um 18:55 Uhr

  • @whamsicore, Sie senden JSON von PHP mit json_encodeaber du unterlassen Sie benutzen eval um die Daten zu analysieren; Sie nutzen JSON.parse(data). Der Unterschied ist, dass wenn json_encode wurde kompromittiert und gesendet "(function(){...malicious code here...})();"würden Sie diesen bösartigen Code automatisch mit aufrufen eval. JSON.parse Auf der anderen Seite wird ein Fehler ausgegeben, der verhindert, dass Ihre Website Ihren Benutzern Schaden zufügt.

    – zzzzBov

    26. Juli 2011 um 19:56 Uhr

Ja und nein:

Ja: PHP erzeugt gültiges JSON

Nein: PHP kann genauso gut bösartigen Code zurückgeben wie in JSON.

Wenn Sie der Quelle vertrauen können oder sogar die volle Kontrolle darüber haben (weil sie Ihnen gehört), gibt es kein Problem.

Es sollte sicher sein, aber auf dem Client wird Ihnen nicht garantiert, dass dies der Fall ist json_str wurde nicht von einer anderen Quelle injiziert.

  • Stimmt, aber es liegt außerhalb des Rahmens der Frage. Die Zeichenfolge php_encode()d ist sicher, ob whamsicore den Rest seiner App angemessen gesichert hat, um zu verhindern, dass jemand Code einfügt und den eval () Teil täuscht, ist etwas anderes.

    – El Yobo

    25. Juli 2011 um 13:30 Uhr

  • Stimmt, aber es liegt außerhalb des Rahmens der Frage. Die Zeichenfolge php_encode()d ist sicher, ob whamsicore den Rest seiner App angemessen gesichert hat, um zu verhindern, dass jemand Code einfügt und den eval () Teil täuscht, ist etwas anderes.

    – El Yobo

    25. Juli 2011 um 13:30 Uhr

1015090cookie-checkJson: PHP zu JavaScript sicher oder nicht?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy