人気のあるSequelizeライブラリの危険な脆弱性





こんにちは、Habr!この記事は、すでにSequelizeライブラリを使用している人、またはそれを使用する予定の人を対象としています。カットの下で、組み込みのoperatorAliases機能がどのように有害である可能性があるか、および独自のデータベースからのリークを回避する方法について説明します。



Sequelizeとは何ですか、どこで使用され、何のために使用されますか?



Sequelizeは、Postgres、MySQL、MariaDB、SQLite、およびMicrosoft SQLServer用のNode.jsORMライブラリであり、データベース内のテーブルとそれらのクラスとの関係をマップします。Sequelizeを使用する場合、SQLクエリを作成する必要はありませんが、通常のオブジェクトと同様にデータを処理する必要があります。堅牢なトランザクションサポート、関係、アクティブおよび遅延読み込み、読み取りレプリケーションなどがあります。



operatorAliasesとは何ですか?危険は何ですか?



Sequelizeはデフォルトで文字演算子を使用します。もちろん、シンボリックエイリアスなしでSequelizeを使用すると、セキュリティが向上します。文字列エイリアスがないため、演算子の挿入はほとんどありませんが、ユーザー入力を常に正しく検証してクリーンアップする必要があります。



また、operatorAliasesオプション自体を使用すると、エイリアス演算子を使用できるかどうかを設定できます。コードでのアクティベーションの例は次のとおりです。







すべてが正しく機能するとき



デモアプリケーションのコードを見てみましょう。モデルファイルuser.model.jsには次のものが含まれています。users







テーブルに3つのフィールドがあり、それらはすべて文字列データ型であること がわかります。



auth.controller.jsコントローラーファイルには次







のものが含まれます 。コードはユーザーモデルでfindOneメソッドを使用します。また、findOneメソッドは、渡されたクエリ条件に従ってデータベースから最初の行を返します。この場合、アプリケーションはユーザーからユーザー名とパスワードのデータを受け取り、それらをusersテーブルに対するクエリに適用します。



この場合に生成されるリクエストは次のようになります。

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







ORMはクエリの形成に使用されるため、簡単なSQLインジェクションは機能しません。データベースに一致するユーザーが見つからない場合、アプリケーションは「ユーザーが見つかりません」エラーを返します。入力データがデータベースレベルで一致する場合、アプリケーションは入力されたパスワードをデータベースに保存されているパスワードと比較し、「無効なパスワード!」を返します。一致しない場合、または成功した場合は認証トークン。入力データ検証アルゴリズムは、脆弱性をテストするために特別に選択されました。



このテーブルには、次のデータが含まれ











ます。認証は正しく機能しています。



演算子とエイリアスはどうですか?









エイリアスは「$」記号で示され、エイリアスの構文はMongoDBに似ています。検索演算子、比較、その他多くの情報をご利用いただけます。モデル内のデータの強い型付けにもかかわらず、JSON形式でユーザーからORMにデータを転送するには、正規化が必要です。そしてここで楽しみが始まります!



トラブルがDOMをノックしたとき



バッチ攻撃







アプリケーションへのこの種の要求は、データベースへの要求を開始します。

実行中(デフォルト): この攻撃では、サーバーへの1回の要求で、特定のパスワードの有効性について多くのログインをチェックできます。この攻撃は、2020年12月の最新バージョンのライブラリ(6.3.5)で機能し、operatorsAliasesオプションが無効になっています。 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;











データ型変換攻撃



...







...のようなデータをアプリケーション渡した場合、この場合 は何も起こりません。データベースの論理条件は正しいですが、調査中のアプリケーションのパスワードをアプリケーションレベルで確認し、さまざまなデータ型を比較してもtrueを返すことはできません。



比較演算子攻撃







スクリーンショットのデータによると、次の形式のデータベースに対してクエリが生成されます 。username= adminと「aaa」に等しくないパスワードが一致するため、データベースはデータを返します。認証プロセスを完全に完了するには、パスワードを取得する必要があります。

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











正規表現と文字列検索攻撃



$ like検索演算子または正規表現を操作するための$ regexp演算子のエイリアスを使用して、生データを取得できます。







シンボルが収束しない場合、ユーザーが見つからなかったというエラーがスローされます。







記号が一致する場合、間違ったパスワードに関するエラーが発生します。フォームのクエリがデータベースに対して実行されます。 したがって、文字ごとに、テーブルからデータを復元できます。

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











テーブル内の列比較攻撃



フィールドをフィールドと比較できる興味深いエイリアス$ colがあります。







データベースへのクエリ は次のようになります。データベースに対して次のクエリを実行します。 したがって、データベースレベルで論理条件を満たすことになります。

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;









脆弱性を取り除く



  • エイリアスのサポートが削除された最新バージョンのSequalizeライブラリをインストールする必要があります。



    出典

  • operatorAliases:falseを設定して、エイリアスの使用を無効にします。
  • ORMで使用する前に、ユーザーからのデータ型とその値を徹底的に検証します。


ご関心をお寄せいただきありがとうございます!



All Articles