Bitbucket is a code hosting site with unlimited public and private repositories. We're also free for small teams!

Close

セキュリティリリース

本日 Django チームはセキュリティの問題に対する報告を修正した複数のリリース -- Django 1.2.6 と Django 1.3.1 -- することをお知らせします。 加えてこの発表では、Django 自体の変更は必要とされなかったけれども、Django を 使っているユーザーにかかわるような、他の問題に対する勧告も含んでいます。

全ユーザーが Django をアップグレードして、ただちに勧告にあるような修正を行なうことをお勧めします。

セッション操作

Django のセッションフレームワーク django.contrib.sessions は セッションデータの保管に複数バックエンドを使えるように設定可能になっています。 Django が提供しているバックエンドのひとつは、Django のキャッシュフレームワークと統合して、 キャッシュをセッションデータのストレージとして使用しています。

メモリベースのセッションとキャッシュを使う設定の場合、Django のセッションは キャッシュのルート名前空間に、セッションの識別子をキーとして直接保存されます。

これは、ユーザーの入力したデータをキャッシュに保存するようなアプリケーションの場合、 攻撃される可能性があります。もし攻撃者が、正当なセッション識別子であるキーを使って データをキャッシュさせることができた場合、Django のセッションフレームワークは (辞書ライクなオブジェクトでありさえすれば)そのデータをセッションとして扱ってしまいます。 このため、攻撃者はセッションキーがわかれば、任意のデータをセッションに書き込むことが可能になります。

これを軽減するには、セッションを保存するのに使われるキーを、キャッシュのルート名前空間ではなく、 キャッシュ内の名前空間に保存することです。(?よくわからん) しかしながら、これは修正セッションのコードを反映された全サイトにおいて、 現在のセッションを無効にしてしまうこと、またセッションデータは一時的なものなので、 後方互換性は考慮されていないことに注意して下さい。

URLField 経由でのサービスアタックの拒否

Django's model system includes a field type -- URLField -- which validates that the supplied value is a valid URL, and if the boolean keyword argument verify_exists is true, attempts to validate that the supplied URL also resolves, by issuing a request to it.

By default, the underlying socket libraries in Python do not have a timeout. This can manifest as a security problem in three different ways:

  1. An attacker can supply a slow-to-respond URL. Each request will tie up a server process for a period of time; if the attacker is able to make enough requests, they can tie up all available server processes.
  2. An attacker can supply a URL under his or her control, and which will simply hold an open connection indefinitely. Due to the lack of timeout, the Django process attempting to verify the URL will similarly spin indefinitely. Repeating this can easily tie up all available server processes.
  3. An attacker can supply a URL under his or her control which not only keeps the connection open, but also sends an unending stream of random garbage data. This data will cause the memory usage of the Django process (which will hold the response in memory) to grow without bound, thus consuming not only server processes but also server memory.

To resolve this, URLField will be modified in the following ways: the verify_exists argument will be defaulted to a false value; for more recent Python versions which support setting a timeout, a timeout of ten seconds will be set; verify_exists will be deprecated and ultimately removed from a future version of Django, as its utility is insufficient to warrant the potential risks it creates.

URLField のリダイレクト

The regular expression which validates URLs is used to check the supplied URL before issuing a check to verify that it exists, but if that URL issues a redirect in response to the request, no validation of the resulting redirected URL is performed, including basic checks for supported protocols (HTTP, HTTPS and FTP).

This creates a small window for an attacker to gain knowledge of, for example, server layout; a redirect to a file:// URL, for example, will tell an attacker whether a given file exists locally on the server.

Additionally, although the initial request issued by Django uses the HEAD method for HTTP/HTTPS, the request to the target of the redirect is issued using GET. This may create further issues for systems which implicitly trust GET requests from the local machine/network.

This issue is ultimately rooted in a bug in Python itself, which has been fixed, but as that fix does not yet appear to be in wide use, we will be modifying Django's URL-checking functions -- for their remaining lifetime before removal due to deprecation -- to use a whitelist of allowed protocols for redirects, and to treat a redirect as a URL which exists, but not to follow the redirect.

Host ヘッダのキャッシュポイズニング

Django 自身が(開発者とは関係なく) URL を生成する個所がいくつかあります (例えば HTTP リダイレクトを発行する時など)。 最近では、URL を組み立てるのにリクエストの HTTP ホストの値を利用していますが、 これはキャッシュポイズニングの危険を含んでいます。 攻撃者はホストヘッダを自由に選んでリクエストを送信することができ、 そのホストヘッダを使って生成された URL を使ったレスポンスを受けとります。 そしてそのレスポンスがキャッシュされれば、それ以上のリクエストが 攻撃者が選んだホストのURLを使ってキャッシュから配信されてしまいます。

この問題を解決するには、Django のコードにおいてこの問題の原因となっている X-Forwarded-Host ヘッダを Django 利用者は今後明示的に有効にする必要があります。 しかし、Django 自体でもユーザーが作成したコードでも、以下に挙げるような対策 ("ホストヘッダと CSRF" という勧告です)をしなければ、この類の攻撃には弱いままでしょう。

勧告: ホストヘッダと CSRF

幾つかのウェブサーバの設定によっては、攻撃者が Django の CSRF 保護機構を突破できてしまいます。 以下のような攻撃の手順になります:

  • 攻撃者は attacker.com にページをホストしていて、サブドメイン subdomain.attacker.com で ターゲットサイト victim.com を指すように CNAME を設定しています。
  • attacker.com の訪問者には、JavaScript で subdomain.attacker.com にリクエストが 送信されるようなサイトが表示されます。 これは Same-Origin ポリシーで許可されていますし、攻撃者がリクエストと共に送信する クッキーやデータを、POST リクエストで使う CSRF クッキーやトークンを含め 自由に操作できます。
  • CNAME によって subdomain.attacker.com へのリクエストは victim.com に送られます。 victim のウェブサーバにおいて、送られてくる HTTP ホストヘッダの 正当性をチェックしていない場合(または特定の名前のバーチャルホストにマッチしない 全てのリクエストに応答する catch-all なバーチャルホストがある場合)、 そのリクエストを Django まで通過させ、CSRF クッキーとトークンの存在によって Django の CSRF 機構はリクエストを許可してしまいます。

これは知る限り、悪意のあるデータ操作や、CSRF の穴として考えられるような 権限の拡大を許可するものではありません(攻撃者が被害サイトのクッキー/セッションに アクセスしたり操作できないため)が、CSRF の穴とみなされています。

このような攻撃の可能性を避けるためには、Django ユーザーはウェブサーバの設定で、 送られてくる HTTP ホストヘッダが期待するホスト名かどうか、常に正当かどうかをチェックすること、 ホストヘッダの無いリクエストを許可しないこと、Django アプリケーションにリクエストを 転送するような cache-all バーチャルホストの設定をしないことをお勧めします。

Advisory: Cross-subdomain CSRF attacks

Due to the nature of HTTP cookies, a cookie can be set from a subdomain which will be valid for the entire domain. This means that an attacker who controls a subdomain can, for example, set a CSRF cookie which will be valid for the entire domain.

This is not a bug in Django itself, but is a potential vector for attack that users of Django should be aware of; to avoid this attack, ensure that subdomains of your domain are only under the control of trusted users (which is a standard best practice). Some notes on this are included in Django's CSRF documentation.

Advisory: DEBUG pages and sensitive POST data

When the DEBUG setting is True, Django will handle exceptions by generating a nicely-formatted error page, including the full traceback and a display of the HTTP request and relevant settings.

Sensitive settings -- such as passwords -- are already obscured in this display, but by default data submitted with the HTTP request is not. Thus, for example, an error in a login view could result in a DEBUG page displaying the plain-text password (from the POST data).

To mitigate this, the development version of Django adds two decorators which will obscure specific information in debugging reports. Users whose applications handle sensitive data are advised to read the documentation for these decorators and use them appropriately.

Affected versions

All of the issues described above are present in the following versions of Django:

  • Django development trunk
  • Django 1.3
  • Django 1.2

Resolution

Patches have been applied to Django trunk, and to the 1.3 and 1.2 release branches, which resolve the three security issues described above. The patches may be obtained directly from the following changesets:

The following new releases have been issued:

As Django trunk is currently in a pre-alpha state, users are strongly advised not to be running production deployments from it; if you are currently doing so, however, you are urged to upgrade imediately to the latest trunk, which contains the above patches.

Credits

The first three security issues above were all reported to us by Paul McMillan, who -- due to his prolific work on identifying and helping to mitigate security issues in Django -- has now been added to the Django core development team. The patches for the above issues were also developed primarily by Paul.

The Host-header cache-poisoning vulnerability was discovered by the core team, through an article reporting the possibility of such attacks.

The cross-subdomain CSRF report was originally supplied by Mozilla.

The issue of sensitive data displaying in DEBUG pages, and the mechanism for mitigating this, both came courtesy of Julien Phalip, who has also recently joined the Django core team.

General notes regarding security

As always, we ask that potential security issues be reported via private email to security@djangoproject.com, and not via Django's Trac instance or the django-developers list.

If you are or represent a third-party distributor of Django and did not receive a notification email regarding this announcement from the Django release manager, please contact james@b-list.org .

Posted by James Bennett on September 9, 2011

Recent activity

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.