Django CVE-2024-42005 の脆弱性を確認する | SEの道標
django

Django CVE-2024-42005 の脆弱性を確認する

CVE-2024-42005 について

Django のクエリーセットの values() と values_list() にクリティカルな脆弱性。SQL インジェクションの可能性あり。CVSS 基本値は 9.8 と高レート。

【セキュリティ ニュース】ウェブアプリフレームワーク「Django」に脆弱性 - 「クリティカル」も(1ページ目 / 全1ページ):Security NEXT
ウェブアプリケーションフレームワーク「Django」に複数の脆弱性が明らかとなっ...
Django security releases issued: 5.0.8 and 4.2.15
Posted by Sarah Boyce on August 6, 2024

LTS の 4.2. 台だと 4.2.14 までが脆弱性対象、4.2.15 が修正バージョン。

修正箇所

4.2.15 のコミットを見てみる。

JSONField の各フィールドに対して self.check_alias(field) を適用している。

[4.2.x] Fixed CVE-2024-42005 -- Mitigated QuerySet.values() SQL injec… · django/django@f4af67b · GitHub

check_alias は SQL インジェクションの原因となるメタ文字が混入してないかをチェックし、混入している場合はエラーを raise する。

試してみる

まずは Django 4.2.14 で試してみる。

なお、JSONField をサポートしている DB を使う必要があるため、PostgreSQL を用意する必要がある。

今回は Windows でセットアップ。PostgreSQL も普通にインストールし、psql -U postgres でログインし、create database cvetest; で cvetest という名前のデータベースを作成するだけ。

適当に temp フォルダを作り、そのフォルダ内で以下を実行。

> python -m venv .venv
> .venv\Script\activate

> python -m pip install -U pip
> pip install django==4.2.14
> pip install psycopg

> django-admin startproject config .
> python manage.py startapp cvetest

config/settings.py を以下のように追記。

INSTALLED_APPS = [
    ...
    'cvetest',  # 追記
]

...

# DATABASES を SQLite3 の設定から置き換え
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "cvetest",
        "USER": "postgres",
        "PASSWORD": "postgres",
        "HOST": "127.0.0.1",
        "TIME_ZONE": "Asia/Tokyo",
    }
}

cvetest/models.py に以下を記述。

from django.db import models

class JSONFieldModel(models.Model):
    data = models.JSONField(null=True)

そしてマイグレートし shell へ移動。

> python manage.py makemigrations
> python manage.py migrate

> python manage.py shell

4.2.14 の場合

上記コミットに追記された test の内容を模倣し、実際に試してみる。

>>> from cvetest.models import JSONFieldModel
>>> a = JSONFieldModel.objects.create(data={"hoge": "fuga"})

>>> crafted_alias = """secret" from "secret_table"; --"""
>>> j = JSONFieldModel.objects.values(f"data__{crafted_alias}")

4.2.14 の場合、エラーにはならない。そして以下の SQL 発行が確認できた。

SELECT ("cvetest_jsonfieldmodel"."data" -> 'secret" from "secret_table"; --') FROM "cvetest_jsonfieldmodel" LIMIT 21

ちなみにこれを見て craft_alias に ' (シングルクォーテーション) を入れたら攻撃成功しそうだと思いやってみたが、これはエラーにならず '' (シングルクォーテーション 2 つ) にサニタイジングされた。

つまり、今回のこの脆弱性単体では実攻撃は相当困難であることが分かった。

仮に今回の脆弱性を使って Django の Web UI から攻撃を成功させるには、以下の条件が必要となる。

  1. WebUI から入力可能なパラメーターを JSONField のカラムの values() あるいは values_list() の引数に入れられること
  2. その際、シングルクォーテーションのサニタイジングを突破する等の別の脆弱性を使って SQL を実行できること
  3. その SQL 実行結果を Web UI へ出力できること

4.2.15 の場合

pip install django==4.2.15 を実行し、上記と同じことを実行するとエラーになる。

>>> j = JSONFieldModel.objects.values(f"data__{crafted_alias}")
Traceback (most recent call last):
  File "", line 1, in 
  File "C:\Users\daisf\work\temp\.venv\Lib\site-packages\django\db\models\manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\daisf\work\temp\.venv\Lib\site-packages\django\db\models\query.py", line 1313, in values
    clone = self._values(*fields, **expressions)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\daisf\work\temp\.venv\Lib\site-packages\django\db\models\query.py", line 1308, in _values
    clone.query.set_values(fields)
  File "C:\Users\daisf\work\temp\.venv\Lib\site-packages\django\db\models\sql\query.py", line 2419, in set_values
    self.check_alias(field)
  File "C:\Users\daisf\work\temp\.venv\Lib\site-packages\django\db\models\sql\query.py", line 1125, in check_alias
    raise ValueError(
ValueError: Column aliases cannot contain whitespace characters, quotation marks, semicolons, or SQL comments.

SQL が発行されていないことも確認できた。

コメント

タイトルとURLをコピーしました