Breaking the AWS MCP Python Sandbox
AWS MCP Python 샌드박스 탈출하기
AWS MCP Server의 Python 실행 도구에서 match/case의 암묵적 속성 조회와 가변 프록시 타입을 연결해 샌드박스를 탈출한 과정을 분석합니다. Lambda에서 명령 실행과 실행 역할 자격 증명 노출을 확인했지만, 테스트에서는 해당 자격 증명과 세션 경계가 피해를 제한했습니다.
- 주제
에디터 노트
이 사례에서 직접 확인된 문제는 Python 코드의 명령 실행과 Lambda 실행 역할 자격 증명 노출입니다. 연구자가 회수한 자격 증명은 테스트에서 sts:GetCallerIdentity 외 AWS API 호출이 거부됐고, 다른 세션이나 고객 데이터 접근도 확인되지 않았습니다. 따라서 샌드박스 탈출 자체와 고객 계정 침해를 구분해야 합니다. 설명된 공격 경로는 AST 검사에서 빠진 암묵적 속성 조회와, 함수 타입을 제한하려다 변경 가능한 프록시를 만든 동작을 연결합니다. Reddit에서는 MCP Inspector로 사용자 입력을 보낼 수 있다는 실용적 지적과 CLI를 만든 이유가 오갔지만, 이는 취약점의 재현성이나 영향 범위를 반박하지 않습니다. LLM을 "협력자"라고 부르는 표현에 관한 논쟁은 기술적 검증과 별개입니다.
AI 요약
AWS MCP Server의 aws___run_script는 여러 AWS API 호출을 Python 코드 한 번으로 묶어 처리하도록 Lambda 샌드박스에서 코드를 실행합니다. 연구자는 AST 검사와 제한된 내장 함수로 보호하던 이 샌드박스에서 Python의 구조적 패턴 매칭(match/case)이 속성을 암묵적으로 읽는 점을 이용해 탈출 경로를 만들었습니다.
샌드박스의 검사 우회
보호 계층은 코드 실행 전 AST를 검사하고, 실행 중에는 제한된 내장 함수와 프록시 객체를 제공했습니다. 예를 들어 obj.__class__, getattr(), operator.attrgetter()를 통한 민감한 속성 접근을 차단했습니다. 그러나 클래스 패턴은 런타임에 클래스의 __match_args__를 읽어 대상 객체의 속성을 조회합니다. AST에는 해당 속성 이름이 직접 나타나지 않으며, 속성 조회는 CPython 내부에서 이뤄집니다.
연구자는 collections.namedtuple()로 만든 클래스의 __match_args__를 바꿔 패턴 매칭이 __class__ 같은 금지 속성을 읽게 했습니다. 검사기가 dunder 이름이 포함된 문자열을 거부하자 chr(95)로 밑줄을 조합해 문자열을 런타임에 만들었습니다. namedtuple은 샌드박스에서 일반 클래스 정의를 막는 __build_class__ 없이도 클래스를 만들어 주었습니다.
함수 전역 변수까지 이어진 경로
다음 단계에서는 __match_args__를 __reduce_ex__로 설정해 namedtuple 인스턴스에서 직렬화 복원 정보를 얻었습니다. 그 결과 copyreg.__newobj__라는 실제 Python 함수를 확보했습니다. 이 함수의 __globals__에는 모듈 전역 변수와 원래 내장 함수 사전이 들어 있습니다.
함수 타입은 불변이라 __match_args__를 직접 바꿀 수 없었습니다. 하지만 샌드박스가 type() 대신 제공한 _safe_type()은 함수 타입을 복제해 제한하려다 실패하면 새 프록시 클래스를 만듭니다. 이 새 클래스는 변경 가능했고, 실제 함수에 대해 isinstance() 검사를 통과했습니다. 연구자는 프록시의 __match_args__를 __globals__로 설정한 뒤 패턴 매칭으로 실제 함수의 전역 변수에 접근했습니다. 이어 원래 __builtins__에서 __import__를 얻어 os와 subprocess를 불러왔습니다.
확인된 영향과 범위
전체 경로는 namedtuple, __match_args__, __reduce_ex__, copyreg.__newobj__, type() 프록시, __globals__, __builtins__, __import__, subprocess 순서입니다. 연구자는 Lambda 컨테이너에서 id 명령을 실행해 uid=993(sbx_user1051) 결과를 확인했습니다. env 명령에서는 해당 세션 Lambda 실행 역할의 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN도 확인했습니다. 샌드박스 소스 파일을 포함해 프로세스 사용자가 읽을 수 있는 파일에도 접근했습니다.
연구자가 회수한 역할 자격 증명은 sts:GetCallerIdentity를 제외한 AWS API 호출에서 명시적 거부 응답을 받았습니다. 자격 증명은 고객 계정이 아니라 AWS 소유 계정의 IAM 역할에 속했습니다. 테스트에서는 다른 세션이나 고객 데이터에 접근하지 못했고, 세션마다 분리된 컨테이너와 인터넷 연결 차단도 확인했다고 설명합니다. AWS는 2026년 7월 26일 제보를 접수했고 9월 15일 수정 작업을 확인했으며, 10월 23일 취약점 보고를 해결된 상태로 표시했습니다.
Reddit 반응
- @sn1ped_u — 링크를 제출했습니다.
- @ak_sys — 악성 에이전트가 이 글을 보게 되면 정말 곤란하겠네요.
- @whatisuser — "Claude Opus 4.6과 협력해 연구했다" 같은 문장은 여전히 어색합니다. 사람들이 LLM을 사람처럼 여기는 듯한 의인화 표현입니다.
- @etan1 — 어떤 Linux 배포판이나 MacBook 모델을 썼는지 적는 것과 비슷한 것 아닌가요?
- @sn1ped_u — 그 표현이 LLM을 사람으로 여긴다는 뜻은 아닐 수 있습니다. 앞으로 더 흔히 보게 될 표현입니다. 그래도 글 맨 앞에 사용 사실을 밝혀 두고 싶었습니다.
- @whatisuser — 협력이란 말은 문자 그대로 다른 사람들과 함께 일한다는 뜻입니다. 사람 중심 용어이며 추측 기계와 함께 일한다는 뜻은 아닙니다.
- @voronaam — MCP 서버에 사용자가 통제하는 입력을 보내는 개발 도구가 있습니다. 예를 들어 Model Context Protocol의 Inspector가 있습니다. Python CLI를 따로 만들 필요는 없었습니다.
- @sn1ped_u — CLI는 재미로 만들었고, 에이전트가 사용자 지정 로직과 조정 사항을 넣은 도구를 쉽게 쓰게 하려는 목적도 있었습니다. 다음에는 Inspector를 써보겠습니다. 감사합니다.
원문: xplo1t-sec / 번역·요약: Trawling