Djangoの脆弱性CVE-2019–6975について解説
こんにちは。筒井です。今日は、2019年2月11日のリリースで修正されたDjangoの脆弱性CVE-2019–6975について解説します。
Django公式サイトのリリース記事については以下を参照してください。
https://www.djangoproject.com/weblog/2019/feb/11/security-releases/
影響を受けるバージョン
以下のバージョンが影響を受けます。
- Django master branch
- Django 2.2
- Django 2.1
- Django 2.0
- Django 1.11
以下のバージョンで修正されています。
- Django 1.11.19
- Django 2.0.11
- Django 2.1.6
脆弱性の内容
django.utils.numberformat.format()
関数は、Decimal型の巨大な値を受け取るとメモリ使用量が通常より増大します。悪用すればDoS攻撃が可能です。django.utils.numberformat.format()
関数は以下で使われています。
django.contrib.admin
に属するコードfloatformat
フィルターfilesizeformat
フィルターintcomma
フィルター
脆弱性を利用した攻撃の例
では、Django 1.11.18でサンプルプロジェクトを作成し、 python manage.py shell
で以下コードを実行してみましょう。
>>> from django.utils.numberformat import format
>>> from decimal import Decimal
>>> number = Decimal('9e9999')
>>> format(number, ".", grouping=3, thousand_sep=",", force_grouping=True) # 出力結果は長いので間を「...」で省略
'9,000,000,000,000,000,000,000,.........................,000'
かなり長い文字列が出力されました。
次に、Django 1.11.20にアップデートして同じコードを実行してみましょう。
(2019年2月14日現在、1.11.19はPyPIに公開されてなかったので、1.11.20を使いました)
>>> from django.utils.numberformat import format
>>> from decimal import Decimal
>>> number = Decimal('9e9999')
>>> format(number, ".", grouping=3, thousand_sep=",", force_grouping=True)
'9e+9999'
今度は数字が指数表記 9e+9999
に変換されるようになりました。
どのように修正されたか
django.utils.numberformat.format()
関数に渡される入力値が以下の条件すべてに一致するときに、指数表記に変換されるようになりました。
- 型がDecimal
- 整数部分と小数部分の桁数の合計が200超
具体的な変更内容は以下のGitHubコードを参照してください。