2020年9月1日に修正されたDjangoの脆弱性CVE-2020-24583・CVE-2020-24584について解説します。
公式サイトでのリリース情報は以下を参照してください。
Django security releases issued: 3.1.1, 3.0.10 and 2.2.16 | Weblog | Django
影響を受けるバージョン
以下のバージョンが影響を受けます。
- Django master branch
- Django 3.1
- Django 3.0
- Django 2.2
脆弱性の内容
CVE-2020-24583: Incorrect permissions on intermediate-level directories on Python 3.7+
Python 3.7以上を使っている、かつFILE_UPLOAD_DIRECTORY_PERMISSIONS
を使っている場合、collectstatic
コマンド実行時に以下のディレクトリにFILE_UPLOAD_DIRECTORY_PERMISSIONS
が適用されていませんでした。
- ファイルをアップロードする過程で作成された中間レベルのディレクトリ
- 中間レベルの収集された静的ディレクトリ
なお、Djnagoのバージョンアップを行っても既に作成されたディレクトリのパーミッションは変更されません。手動でパーミッションを変更する必要があります。
CVE-2020-24584: Permission escalation in intermediate-level directories of the file system cache on Python 3.7+
Python 3.7以上を使っている、かつファイルシステムキャッシュを使っている場合、キャッシュが置かれる中間レベルのディレクトリは、システム標準のumaskの値の影響を受けるようになっていました。本来は、umaskには0o077が適用されるべきです。
(つまり、「所有グループ」「その他」へのパーミッションは常に0になるべき)
脆弱性を利用した攻撃の例
サンプルコードで使っている環境のバージョンは以下の通りです。
- Django 3.1
- Python 3.8.5
- Ubuntu 18.04.5
CVE-2020-24583: Incorrect permissions on intermediate-level directories on Python 3.7+
settings.py
に以下の設定を追加します。
|
|
collectstatic
の実行後に作られるstatic
ディレクトリのパーミッションを調べてみます。
|
|
FILE_UPLOAD_DIRECTORY_PERMISSIONS
の設定どおりなら0o700のはずですが、0o777になっています。
CVE-2020-24584: Permission escalation in intermediate-level directories of the file system cache on Python 3.7+
settings.py
に以下の設定を追加します。
|
|
umask 022
を実行してからshell
コマンドで以下のコードを実行します。
|
|
作成されたディレクトリのパーミッションを調べます。
|
|
foo
ディレクトリを一旦消して、umask 000
を実行してからshell
コマンドで以下コード(前述のコードと同じ)を実行します。
|
|
作成されたディレクトリのパーミッションを調べます。
|
|
作成されたディレクトリのパーミッションがumaskの影響を受けていることが分かります。
どのコードに問題があったか・どのように修正されたか
実際の変更内容は以下のGitHubコードを参照してください。
CVE-2020-24583:
- On the master branch
- On the 3.1 release branch
- On the 3.0 release branch
- On the 2.2 release branch
CVE-2020-24584:
- On the master branch
- On the 3.1 release branch
- On the 3.0 release branch
- On the 2.2 release branch
CVE-2020-24583・CVE-2020-24584どちらもPython 3.7以降でのos.makedirs
の仕様変更が原因です。
公式ドキュメントでのos.makedirs
に関する説明を以下に引用します。
Changed in version 3.7: The mode argument no longer affects the file permission bits of newly-created intermediate-level directories.
引用元: os — Miscellaneous operating system interfaces — Python 3.8.6 documentation
検証のために、以下のコードを用意しました(Python 3.7以上が必要)。
|
|
一見、常にパーミッション0o700でディレクトリが作られるように見えますが、foo
の「所有グループ」「その他」のパーミッションはumaskの値に依存します。
上記コードをumask 022
の後実行するとfoo
のパーミッションは0o755、umast 000
なら0o777になります。
これを回避するために、Djangoではos.makedirs
のmode
を指定しているコードでは前後にos.umask
を使うようになりました。
以下は上記のコードの修正例です。
|
|