flawopen.com/AI Security/hermes-agent-native-signin-redirect-parser-confusion
Hermes Agent 네이티브 로그인 리디렉션 파싱 취약점
Tenable은 Hermes Agent 네이티브 로그인에서 심각한 리디렉션 검증 취약점을 공개했습니다. 0.21.6 이전 버전이 영향을 받습니다. 0.21.6 수정본은 Docker/Hermes Cloud와 CLI/git 설치에 제공됐고, 10월 11일 공개된 0.21.7에는 Desktop 앱, Microsoft Store/MSIX, 설치 프로그램, Docker, Hermes Cloud도 배포 대상으로 나옵니다. 확인한 릴리스 노트에는 Termux가 언급되지 않아 해당 채널은 별도로 확인해야 합니다. Tenable은 이를 High(CVSS 4.0 8.6)로 평가했으며 CVE는 할당되지 않았습니다. CWE-601은 리디렉션 결과에 대한 편집상 분류입니다.[1], [2], [5]
접수 담당자가 한 지도에서 주소를 확인하고 입력된 문자를 그대로 적어 다른 지도를 쓰는 배달원에게 전달한다고 생각해 보세요. 배달원은 승인되지 않은 장소로 갈 수 있습니다. Hermes는 Python 파서로 callback을 검사한 뒤 정규화되지 않은 원문을 브라우저에 넘겼고, 브라우저는 이를 다르게 해석할 수 있었습니다.[1]
핵심 개념 및 용어
프레임워크 매핑
- MITRE CWE에 대한 FlawOpen의 개념적 매핑입니다. 공급업체나 CVE 레코드가 이 연구 시연에 해당 약점 ID를 지정한 것은 아닙니다. CWE-601
단계별 공격 실행 흐름
소스 코드 비교: 취약한 구현 vs 보안 패치
이 코드는 보안 경계를 보여주는 예시이며 Hermes Agent 전체 소스나 exploit이 아닙니다. 취약 예시는 “파싱된 host를 검사한 뒤 원문 입력 사용” 패턴을 요약합니다. 강화 예시는 병합된 수정의 속성, 즉 모호한 입력 거부, 정규 loopback authority만 허용, canonical URI 반환 및 동일 값 저장/사용을 설명합니다. 실제 구현과 테스트는 연결된 PR을 참조하세요.[1], [3]
from urllib.parse import urlparse
def validate_callback(raw):
parsed = urlparse(raw)
# 기존 흐름은 파싱된 호스트를 확인한 뒤에도 원본 URL을 그대로 유지했습니다.
if parsed.scheme == "http" and parsed.hostname in {"127.0.0.1", "::1"}:
return raw
raise ValueError("callback must be loopback")
from urllib.parse import urlparse, urlunparse
LOOPBACK_HOSTS = {"127.0.0.1": "127.0.0.1", "::1": "[::1]"}
def validate_callback(raw):
if not raw.isascii() or "\\" in raw or any(ord(c) <= 0x20 or ord(c) == 0x7f for c in raw):
raise ValueError("callback must use canonical loopback syntax")
try:
parsed = urlparse(raw)
host, port = parsed.hostname, parsed.port
except ValueError as exc:
raise ValueError("invalid callback") from exc
if parsed.scheme != "http" or "#" in raw or parsed.username is not None or parsed.password is not None:
raise ValueError("callback must be a plain loopback URL")
authority_host = LOOPBACK_HOSTS.get(host)
if authority_host is None:
raise ValueError("callback host must be a loopback IP literal")
authority = authority_host + (f":{port}" if port is not None else "")
if parsed.netloc != authority:
raise ValueError("callback authority is not canonical")
return urlunparse(parsed._replace(path=parsed.path or "/"))
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓Hermes Agent 버전과 설치 채널을 파악한 뒤 실제 실행 중인 빌드를 확인하세요. 0.21.7 릴리스 노트에는 Desktop 앱, Microsoft Store/MSIX, 설치 프로그램, Docker, Hermes Cloud가 나옵니다.[5]
- ✓해당 지원 채널을 통해 0.21.7 이상으로 업데이트하세요. 확인한 릴리스 노트에는 Termux가 없어 별도 확인이 필요합니다.[2], [5]
- ✓검증 함수가 canonical 값을 반환하고 인증 흐름이 그 동일한 값을 저장하고 사용하는지 확인하세요. 다른 표현을 검증한 뒤 원래 입력을 사용하면 안 됩니다.[3]
- ✓파서 불일치, userinfo, 역슬래시, fragment, 비정규 IP 및 포트에 대한 회귀 테스트를 추가하고 거부된 값이 코드 발급에 도달하지 않는지 확인하세요.[3]