Eine gefährliche Sicherheitslücke in der beliebten Sequelize-Bibliothek





Hallo Habr! Dieser Artikel ist für diejenigen von Interesse, die die Sequelize-Bibliothek bereits verwenden oder nur damit arbeiten werden. Im Rahmen des Schnitts erfahren Sie, wie schädlich die integrierte OperatorAliases-Funktionalität sein kann und wie Sie ein Leck in Ihrer eigenen Datenbank vermeiden können.



Was ist Sequelize, wo wird es verwendet und wofür?



Sequelize ist eine Node.js ORM-Bibliothek für Postgres, MySQL, MariaDB, SQLite und Microsoft SQL Server, die Tabellen in Datenbanken und ihre Beziehungen zu Klassen abbildet. Bei der Verwendung von Sequelize müssen wir keine SQL-Abfragen schreiben, sondern müssen mit Daten wie mit normalen Objekten arbeiten. Es bietet robuste Transaktionsunterstützung, Beziehungen, aktives und verzögertes Laden, Lesereplikation und mehr.



Was ist operatorAliases und was ist die Gefahr?



Sequelize verwendet standardmäßig Zeichenoperatoren. Die Verwendung von Sequelize ohne symbolische Aliase verbessert natürlich die Sicherheit. Obwohl das Fehlen von String-Aliasen eine Bedienerinjektion äußerst unwahrscheinlich macht, müssen wir Benutzereingaben immer korrekt validieren und bereinigen.



Mit der Option operatorAliases selbst können Sie festlegen, ob Alias-Operatoren verfügbar sein sollen. So sieht ein Beispiel für die Aktivierung im Code aus:







Wenn alles richtig funktioniert



Schauen wir uns den Demo-Anwendungscode an. Die Modelldatei user.model.js enthält: Sie







können sehen, dass die Benutzertabelle drei Felder enthält , die alle einen Zeichenfolgendatentyp haben.



Die Controller-Datei auth.controller.js enthält:







Der Code verwendet die findOne-Methode im Benutzermodell. Die findOne-Methode gibt die erste Zeile aus der Datenbank gemäß der übergebenen Abfragebedingung zurück. In diesem Fall empfängt die Anwendung die Benutzernamen- und Kennwortdaten vom Benutzer und wendet sie auf eine Abfrage für die Benutzertabelle an.



Die generierte Anfrage sieht in diesem Fall ungefähr so ​​aus:

SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = :username AND `users`.`password` = :password LIMIT 1;







Da ORM zum Erstellen von Abfragen verwendet wird, funktioniert die einfache SQL-Injection nicht. Wenn in der Datenbank keine Benutzerübereinstimmungen gefunden werden, gibt die Anwendung den Fehler Benutzer nicht gefunden zurück. Wenn die Eingabedaten auf Datenbankebene übereinstimmen, vergleicht die Anwendung das eingegebene Kennwort mit dem in der Datenbank gespeicherten Kennwort und gibt entweder ein "Ungültiges Kennwort!" Zurück. Wenn es nicht übereinstimmt, oder ein Autorisierungstoken, wenn es erfolgreich ist. Der Algorithmus zur Validierung der Eingabedaten wurde speziell zum Testen der Sicherheitsanfälligkeit ausgewählt.



Die Tabelle enthält die folgenden Daten: Die











Autorisierung funktioniert ordnungsgemäß.



Was ist mit Operatoren und Aliasnamen?









Aliase werden mit dem Symbol "$" gekennzeichnet. Die Syntax für Aliase ähnelt MongoDB. Suchoperatoren, Vergleiche und viele andere stehen uns zur Verfügung. Trotz der starken Typisierung der Daten im Modell führt die Übertragung von Daten vom Benutzer zum ORM im JSON-Format zu einer Normalisierung. Und hier beginnt der Spaß!



Wenn Probleme am DOM auftreten



Batching-Angriff







Diese Art von Anforderung an die Anwendung initiiert eine Anforderung an die Datenbank:

Ausführen (Standard): Bei diesem Angriff können Sie viele Anmeldungen auf ein bestimmtes Kennwort auf Gültigkeit in einer Anforderung an den Server überprüfen und umgekehrt. Der Angriff funktioniert in der neuesten Version der Bibliothek für Dezember 2020 (6.3.5) und mit deaktivierter Option operatorAliases. SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` IN ('admin', 'more', 'much more') AND `users`.`password` = 'wrong pass' LIMIT 1;











Datentypkonvertierungsangriff



Wenn Sie Daten wie ...







... an die Anwendung übergeben , geschieht in unserem Fall nichts. Obwohl die logische Bedingung in der Datenbank korrekt ist, kann das Überprüfen des Kennworts in der untersuchten Anwendung auf Anwendungsebene und das Vergleichen verschiedener Datentypen nicht true zurückgeben.



Vergleich Operator Attack







Entsprechend den Daten auf dem Screenshot wird eine Abfrage an die Datenbank des Formulars generiert: Die Datenbank gibt Daten zurück, da eine Übereinstimmung zwischen Benutzername = admin und einem Kennwort besteht, das nicht gleich "aaa" ist. Um den Autorisierungsprozess vollständig durchlaufen zu können, benötigen wir ein Passwort.

SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = 'admin' AND `users`.`password` != 'aaa' LIMIT 1;











Regex- und String-Suchangriff



Sie können die Rohdaten abrufen, indem Sie die Aliase für die $ like-Suchoperatoren oder die $ regexp-Operatoren für die Arbeit mit regulären Ausdrücken verwenden.







Wenn das Symbol nicht konvergiert, wird ein Fehler ausgegeben, dass der Benutzer nicht gefunden wurde.







Wenn das Symbol übereinstimmt, wird ein Fehler bezüglich des falschen Passworts angezeigt. Eine Abfrage des Formulars wird in der Datenbank ausgeführt: So können Sie zeichenweise Daten aus der Tabelle wiederherstellen.

SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = 'admin' AND `users`.`password` LIKE 'E%' LIMIT 1;











Spaltenvergleichsangriff in einer Tabelle



Es gibt einen interessanten Alias ​​$ col, mit dem Sie ein Feld mit einem Feld vergleichen können.







Die Abfrage an die Datenbank wird: Die folgende Abfrage an die Datenbank ausführen: Somit wird die logische Bedingung auf Datenbankebene erfüllt.

SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = 'admin' AND `users`.`password` = `aaaaa` LIMIT 1;













SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = 'admin' AND `users`.`password` = `password` LIMIT 1;









Schwachstellen beseitigen



  • Sie müssen die neueste Version der Sequalize-Bibliothek installieren, in der die Unterstützung für Aliase entfernt wurde.



    ( Quelle )

  • Deaktivieren Sie die Verwendung von Aliasen, indem Sie operatorAliases: false festlegen.
  • Überprüfen Sie die Datentypen und ihre Werte vom Benutzer gründlich, bevor Sie sie im ORM verwenden.


Danke für dein Interesse!



All Articles