Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
ツール/GitHubGitHub/zer0qs/cve-2021-35042
脆弱性分析エクスプロイトウェブセキュリティ論文と研究学習と教育
GitHubzer0qs/cve-2021-35042

CVE-2021-35042

CVE-2021-35942に関する基本的な分析。DjangoにおけるSQLインジェクション。

リポジトリを見る
2114年前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2021-35042: Django SQLインジェクションの脆弱性

I. 概要

Djangoは、Pythonで書かれたオープンソースのWebアプリケーションフレームワークであり、MVC(Model - View - Controller)モデルに基づいて構築されています。当初は、ローレンス出版グループが所有するニュースコンテンツサイトを管理するために構築されたCMS(コンテンツ管理システム)ソフトウェアでした。

Djangoバージョン3.1.xから3.1.13、およびバージョン3.2.xから3.2.5には、SQLインジェクションの脆弱性が存在します。

この脆弱性の原因は、QuerySet.order_by() におけるユーザーが制御する入力データのフィルタリング機能が、SQLインジェクション攻撃を防ぐのに十分ではなかったためです。この脆弱性が悪用されると、攻撃者が不正な操作を実行し、機密データの漏えいにつながる可能性があります。

CVE - IDCVE-2021-35042
深刻度9.8 - CRITICAL
CWE - IDCWE-89: SQLコマンドに使用される特殊要素の不適切な無効化('SQLインジェクション')
脆弱性公開日2021年7月1日
影響を受けるソフトウェア3.1.x < 3.1.13, 3.2.x < 3.2.5
認証要件不要

II. 概要 x2

0x01. Djangoのモデル

Djangoでは、データベース内のテーブルの作成とフィールドの定義は、models.py ファイル内でモデルクラスを宣言することによって行われます。この例では、Wolf という名前のテーブルと、name という名前のフィールドを宣言します。

0x02. DjangoにおけるQuerySetとOrder_by()

Djangoに組み込まれているORMフレームワークはデータベースを操作するために使用され、クエリの結果はコレクションであり、このコレクションはQuerySetです。

order_by(fields) デフォルトでは、order_by() は、ModelのMeta内のorderingオプションで指定された順序でソートされたQuerySetを返します。各クエリでorder_by()メソッドを使用して、order_by条件を上書きできます。

例

wolves = Wolf.objects.order_by('-name', 'id')

上記のクエリの結果は、name フィールドで降順にソートされ、次に id で昇順にソートされます。name フィールド名の前にあるマイナス記号は、結果を降順でソートすることを示します。

次の例では、ユーザーから受け取ったフィールドで返された結果をソートします。値が渡されない場合は、id フィールドでソートされます。

結果

バージョン3.1および3.2では、Djangoはクエリメソッドとテーブル名をorder_byクエリに組み合わせることを許可しています。これがこの脆弱性の主な原因でもあります。

テーブル名を渡すと、通常のフィールド名を渡すのと同じ結果が得られます。

cve202135042_wolf はテーブル名です

まず、アプリケーションはorder_by()関数を直接呼び出します。order_by()関数を処理するコードは、以下で定義されています: django/db/models/query.py

order_by()関数は2つのことを行います

  1. order_by()によって現在呼び出されているすべてのメソッドを削除し、order_byが別の値を受け取ったときに渡されるデフォルトパラメータを削除します。
  1. パラメータをorder_byに渡します。add_ordering() 関数がこれを実行します。
def add_ordering(self, *ordering):
        """
        Add items from the 'ordering' sequence to the query's "order by"
        clause. These items are either field names (not column names) --
        possibly with a direction prefix ('-' or '?') -- or OrderBy
        expressions.

        If 'ordering' is empty, clear all ordering from the query.
        """
        errors = []
        for item in ordering:
            if isinstance(item, str):
                if '.' in item:
                    warnings.warn(
                        'Passing column raw column aliases to order_by() is '
                        'deprecated. Wrap %r in a RawSQL expression before '
                        'passing it to order_by().' % item,
                        category=RemovedInDjango40Warning,
                        stacklevel=3,
                    )
                    continue
                if item == '?':
                    continue
                if item.startswith('-'):
                    item = item[1:]
                if item in self.annotations:
                    continue
                if self.extra and item in self.extra:
                    continue
                # names_to_path() validates the lookup. A descriptive
                # FieldError will be raise if it's not.
                self.names_to_path(item.split(LOOKUP_SEP), self.model._meta)
            elif not hasattr(item, 'resolve_expression'):
                errors.append(item)
            if getattr(item, 'contains_aggregate', False):
                raise FieldError(
                    'Using an aggregate in order_by() without also including '
                    'it in annotate() is not allowed: %s' % item
                )
        if errors:
            raise FieldError('Invalid order_by arguments: %s' % errors)
        if ordering:
            self.order_by += ordering
        else:
            self.default_ordering = False
            

add_ordering() に渡されるパラメータは配列です。

例えば、パラメータが次のように渡された場合: wolves = Wolf.objects.order_by( 'name' , 'id' ) その場合、アプリケーションはデータベース内の次のクエリに変換します:

SELECT "cve202135042_wolf"."id", "cve202135042_wolf"."name" FROM "cve202135042_wolf" ORDER BY "cve202135042_wolf"."name" ASC, "cve202135042_wolf"."id" ASC

渡されると、add_ordering関数は配列内の各要素をチェックします。それがstringの場合、次の5つのケースがチェックされます:

  1. if '.' in item: それがSQL文で指定されたテーブル名を持つ列名のクエリであるかどうかをチェックします。もしそうなら、警告を出してcontinueします。
  2. if item == '?': 要素の値が'?'記号の場合、出力結果はランダムにソートされ、continueします。
  3. if item.startswith('-'): アイテムが'-'文字で始まる場合、クエリの結果はDESC(降順)でソートされます。
  4. if item in self.annotations: コメントが含まれているかどうかをチェックし、含まれている場合はcontinueします。
  5. if self.extra and item in self.extra: 追加があるかどうかを判断し、ある場合はcontinueします。

5回のチェックの後、パラメータはself.names_to_path(item.split(LOOKUP_SEP), self.model._meta)関数に渡され、それが有効な列名であるかどうかを引き続きチェックします。その後、有効であれば、それらはQueryクラスのself.orderingに追加されて処理が続行されます。

III. DjangoにおけるSQLインジェクションの脆弱性の分析

0x31. 原因

DjangoのORMは、クエリに入力されるデータを非常に厳密にフィルタリングしますが、今回のソースコードの変更によりSQLインジェクションが発生したのは、作成者が、列名がUUID(汎用一意識別子)列の場合、order_byクエリを実行できないという仮説を立てたためです。

つまり、入力データがxxx-xxx-xxx-xxx(UUIDの形式)の場合、クエリを実行できません。

変更前のコード

# django/db/models/sql/constants.py 
ORDER_PATTERN  =  _lazy_re_compile ( r '\?|[-+]?[.\w]+$' )
ツールをダウンロード