Djangoの脆弱性CVE-2019–3498について解説
明けましておめでとうございます。筒井です。今年もよろしくお願いします。
さて、年明け早々に何ですが、今回の記事はDjangoの脆弱性の話です。2019年1月4日のリリースで修正されたCVE-2019–3498について解説します。
Django公式サイトのリリース記事については以下を参照してください。
Django security releases issued: 2.1.5, 2.0.10, and 1.11.18 | Weblog | Django
影響を受けるバージョン
以下のバージョンが影響を受けます。
- Django master branch
- Django 1.11
- Django 2.0
- Django 2.1
以下のバージョンで修正されています。
- Django 1.11.18
- Django 2.0.10
- Django 2.1.5
脆弱性の内容
handler404
がデフォルト値のdjango.views.defaults.page_not_found()
の場合、404ページに攻撃者が偽装したコンテンツを挿入することができます。
自分で書いたビューを指定している場合は、「 request.path
をURLエンコードせずにテンプレート上で表示させる」というコードになっていないか注意してください。
判断が難しければ、後述の「脆弱性を利用した攻撃の例」を参考に検証してください。
該当する場合は、後述の「どのように修正されたか」を参考に自分でコードを修正してください。
脆弱性を利用した攻撃の例
実際にサンプルコードを作って試してみましょう。この記事では Django==1.11.17
を使っています。
まず、django-admin startproject
でプロジェクトを作成します。
ローカル環境でもデフォルトの404ページを表示させるために、 DEBUG
には False
、 ALLOWED_HOSTS
には ['*']
を設定してください。あとは ./manage.py migrate && ./manage.py runserver
で開発サーバーを立ち上げます。
404ページは以下のように表示されるはずです。
URLの部分をちょっと工夫すると、以下のように表示させることができます。あまりいい例文が思いつかなかったのですが、 %20
をスペースとして表示できるので、工夫次第で自然な文章が作れそうです。
どのように修正されたか
デフォルトの404ページに「URLの一部が画面上に表示される」という仕様が廃止されました。先述のサンプルコードをDjango 1.11.18で動かしてみると、以下のように表示されます。
また、表示に使われていたコンテキスト変数 request_path
( request.path
の内容が入っている)はURLエンコードされるようになり、 %20
はそのまま %20
として表示されるようになりました。
もし、テンプレートファイルだけ入れ替えて request_path
を使うようにしても、偽装コンテンツを挿入されることはありません。
実際のコードは以下のリンクを参照してください。