it-swarm.com.de

Verhindern der SQL-Injection in Node.js

Ist es möglich, SQL-Injections in Node.js (vorzugsweise mit einem Modul) auf die gleiche Weise zu verhindern, wie PHP vor ihnen geschützte Prepared Statements hatte?.

Wenn das so ist, wie? Wenn nicht, was sind einige Beispiele die den von mir bereitgestellten Code umgehen könnten (siehe unten).


Ein wenig Kontext:

Ich erstelle eine Webanwendung mit einem Back-End-Stack, der aus Node.js + MySql besteht, unter Verwendung des Moduls node-mysql . Aus der Sicht der Benutzerfreundlichkeit ist das Modul großartig, aber es hat noch nichts Ähnliches wie PHP implementiert Prepared Statements (obwohl ich mir bewusst bin, dass es sich um das todo handelt).

Nach meinem Verständnis hat die Implementierung von vorbereiteten Anweisungen durch PHP unter anderem wesentlich zur Verhinderung von SQL-Injections beigetragen. Ich mache mir allerdings Sorgen, dass meine node.js-App möglicherweise ähnlichen Angriffen ausgesetzt ist, selbst wenn die Zeichenfolge standardmäßig ausgeblendet wird (wie im folgenden Codeausschnitt).

node-mysql scheint der beliebteste MySQL-Connector für node.js zu sein. Daher habe ich mich gefragt, was andere möglicherweise tun (wenn überhaupt), um dieses Problem zu beheben - oder ob es überhaupt ein Problem mit node.js ist (Ich bin mir nicht sicher, wie dies nicht sein würde, da es sich um eine benutzer-/clientseitige Eingabe handelt.).

Soll ich vorerst zu node-mysql-native wechseln, da es vorbereitete Anweisungen liefert? Ich zögere, dies zu tun, da es nicht so aktiv zu sein scheint wie Node-MySQL (obwohl dies nur bedeuten kann, dass es vollständig ist).

Hier ist ein Ausschnitt aus dem Benutzerregistrierungscode, der das Modul sanitizer zusammen mit der von node-mysql vorbereiteten anweisungsähnlichen Syntax (die, wie oben erwähnt, die Zeichenumbrüche vornimmt) verwendet, um Cross-Site-Scripting und SQL-Injektionen zu verhindern , beziehungsweise:

// Prevent xss
var clean_user = sanitizer.sanitize(username);

// assume password is hashed already
var post = {Username: clean_user, Password: hash};

// This just uses connection.escape() underneath
var query = connection.query('INSERT INTO users SET ?', post,
   function(err, results)
   {
       // Can a Sql injection happen here?
   });
73
funseiki

Die node-mysql-Bibliothek führt automatisch ein Escape-Verfahren durch, wenn sie wie bereits verwendet verwendet wird. Siehe https://github.com/felixge/node-mysql#escaping-query-values ​​

48
Michael Pratt

Mir ist klar, dass dies ein älterer Beitrag ist, aber es scheint, dass eine Antwort nie markiert wurde, also werde ich diese hier rausschmeißen.

In Bezug auf das Testen, ob ein Modul, das Sie verwenden, sicher ist oder nicht, gibt es mehrere Routen, die Sie verwenden können. Ich werde auf die Vor-/Nachteile eines jeden eingehen, damit Sie eine fundiertere Entscheidung treffen können.

Derzeit gibt es keine Sicherheitslücken für das von Ihnen verwendete Modul. Dies kann jedoch oft zu einem falschen Sicherheitsgefühl führen, da eine Sicherheitslücke sehr wahrscheinlich das von Ihnen verwendete Modul/Software-Paket ausnutzt und Sie nicht gewarnt werden auf ein Problem, bis der Anbieter einen Fix/Patch anwendet.

  1. Um mit den Schwachstellen Schritt zu halten, müssen Sie sich in Mailinglisten, Foren, IRC und anderen Diskussionen rund um das Thema Hacken aufhalten lassen. PRO: Sie können oft auf potenzielle Probleme in einer Bibliothek aufmerksam werden, bevor ein Anbieter aufgetreten ist alarmiert oder ein Fix/Patch herausgegeben, um mögliche Angriffe auf ihre Software zu beheben. CON: Dies kann sehr zeitaufwändig und ressourcenintensiv sein. Wenn Sie diese Route über RSS-Feeds, Protokollanalyse (IRC-Chat-Protokolle) und/oder einen Web-Scrapper mit Schlüsselphrasen (in diesem Fall node-mysql-native) und Benachrichtigungen verwenden, kann die für das Ressourcenaufrufen dieser Ressourcen benötigte Zeit reduziert werden.

  2. Erstellen Sie einen Fuzzer, verwenden Sie ein fuzzer oder ein anderes Schwachstellen-Framework wie metasploit , sqlMap etc., um Probleme zu testen, nach denen der Anbieter möglicherweise nicht gesucht hat . PRO: This Sie können sich als sichere Methode erweisen, um auf einem akzeptablen Niveau sicherzustellen, ob das Modul/die Software, die Sie implementieren, für den öffentlichen Zugriff sicher ist oder nicht. CON: Dies wird auch zeit- und kostenaufwändig. Das andere Problem wird durch falsch positive Ergebnisse sowie durch eine ungelernte Überprüfung der Ergebnisse hervorgerufen, bei denen ein Problem vorliegt, aber nicht bemerkt wird.

Wirkliche Sicherheit und Anwendungssicherheit im Allgemeinen können sehr zeit- und ressourcenintensiv sein. Manager werden immer eine Formel verwenden, um die Kosteneffizienz (Arbeitskräfte, Ressourcen, Zeit, Entgelt usw.) der oben genannten zwei Optionen zu bestimmen.

Jedenfalls ist mir klar, dass dies kein "Ja" oder "Nein" ist, auf das vielleicht gehofft wurde, aber ich glaube nicht, dass irgendjemand Ihnen das geben kann, bis er eine Analyse der fraglichen Software durchführt.

9
jas-

Die Bibliothek hat einen Abschnitt in der Readme-Datei zum Fluchen. Es ist Javascript-native, daher empfehle ich nicht, zu node-mysql-native zu wechseln. In der Dokumentation werden folgende Richtlinien für die Flucht angegeben:

Edit:node-mysql-native ist auch eine reine Javascript-Lösung.

  • Zahlen bleiben unberührt
  • Boolesche Werte werden in true/false-Zeichenfolgen konvertiert
  • Datumsobjekte werden in YYYY-mm-dd HH:ii:ss-Zeichenfolgen konvertiert
  • Puffer werden in Hex-Strings umgewandelt, z. X'0fa5'
  • Zeichenfolgen werden sicher entkommen
  • Arrays werden in eine Liste umgewandelt, z. ['a', 'b'] wird zu 'a', 'b'
  • Verschachtelte Arrays werden in gruppierte Listen (für Bulk-Inserts) umgewandelt, z. [['a', 'b'], ['c', 'd']] wird zu ('a', 'b'), ('c', 'd')
  • Objekte werden in key = 'val'-Paare umgewandelt. Verschachtelte Objekte werden in Strings umgewandelt.
  • undefined/null werden in NULL konvertiert
  • NaN/Infinity bleiben unverändert. MySQL unterstützt diese nicht, und der Versuch, sie als Werte einzufügen, löst MySQL-Fehler aus, bis sie Unterstützung implementieren.

Dies ermöglicht es Ihnen, folgende Dinge zu tun:

var userId = 5;
var query = connection.query('SELECT * FROM users WHERE id = ?', [userId], function(err, results) {
  //query.sql returns SELECT * FROM users WHERE id = '5'
});

So gut wie das:

var post  = {id: 1, title: 'Hello MySQL'};
var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) {
  //query.sql returns INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
});

Abgesehen von diesen Funktionen können Sie auch die Escape-Funktionen verwenden:

connection.escape(query);
mysql.escape(query);

Um zu verhindern, Abfrage-IDs:

mysql.escapeId(identifier);

Und als Antwort auf Ihren Kommentar zu vorbereiteten Aussagen:

Aus Sicht der Benutzerfreundlichkeit ist das Modul großartig, aber es wurde noch nicht etwas implementiert, das den vorbereiteten Anweisungen von PHP ähnelt.

Die vorbereiteten Anweisungen befinden sich in der Liste todo für diesen Connector. In diesem Modul können Sie jedoch zumindest benutzerdefinierte Formate angeben, die den vorbereiteten Anweisungen sehr ähnlich sein können. Hier ein Beispiel aus der Readme:

connection.config.queryFormat = function (query, values) {
  if (!values) return query;
  return query.replace(/\:(\w+)/g, function (txt, key) {
    if (values.hasOwnProperty(key)) {
      return this.escape(values[key]);
    }
    return txt;
  }.bind(this));
};

Dadurch wird das Abfrageformat der Verbindung geändert, sodass Sie Abfragen wie folgt verwenden können:

connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });
//equivalent to
connection.query("UPDATE posts SET title = " + mysql.escape("Hello MySQL");
9
hexacyanide

Ich weiß, dass diese Frage alt ist, aber für alle, die daran interessiert sind, ist Mysql-native veraltet, also wurde es MySQL2 das ist ein neues Modul, das mit Hilfe des ursprünglichen MySQL-Modulteams erstellt wurde. Dieses Modul hat mehr Funktionen und ich denke, es hat das, was Sie wollen, da es Anweisungen (von using.execute ()) wie in PHP für mehr Sicherheit vorbereitet hat. 

Es ist auch sehr aktiv (die letzte Änderung war von 2-1 Tagen) Ich habe es vorher nicht ausprobiert, aber ich denke, es ist das, was man will und mehr.

1
Boy pro

Am einfachsten ist es, alle Ihre Datenbankinteraktionen in einem eigenen Modul zu behandeln, das Sie in Ihre Routen exportieren. Wenn Ihre Route keinen Kontext für die Datenbank hat, kann SQL sie trotzdem nicht berühren.

0
Bird Dad