FlawOpen

flawopen.com/Teardowns/cve-2026-77244-mcp-atlassian-http-auth-bypass

● CVE-2026-77244 · CVSS 10.0[1] · 심각
보안 연구 · FlawOpen

CVE-2026-77244: mcp-atlassian 미인증 HTTP 도구 접근

CVE-2026-77244는 미인증 호출자가 커뮤니티 프로젝트 mcp-atlassian의 HTTP 도구 핸들러에 도달해 운영자 환경에 설정된 Jira 또는 Confluence 자격 증명을 사용하게 할 수 있었습니다. 주요 수정은 0.22.0에 포함됐으며, SSE 사용자는 별도의 관련 전송 문제를 해결한 0.23.1 이상이 필요합니다.[1], [4], [5], [6]

CVSS 벡터CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N[1]
💡 알기 쉬운 설명 (ELI5)

접수 직원은 직원 전용 문을 열기 전에 방문자의 배지를 확인해야 합니다. 이전 절차에서는 배지가 없으면 접수 직원이 마스터 키를 빌려줬습니다. 검증된 사용자 ID 없이 HTTP 요청이 도구에 도달하고 도구가 운영자의 공유 Atlassian 자격 증명을 사용할 수 있는 두 가지 누락된 검사가 결합된 문제입니다. 수정은 미인증 HTTP 요청을 거부하고 자격 증명 fallback을 명시적으로 허용하도록 바꿉니다.[1], [3]

핵심 개념 및 용어

MCP 전송
클라이언트와 서버 사이에서 Model Context Protocol 요청을 전달하는 채널입니다. 이 CVE는 mcp-atlassian HTTP 전송에 해당하며, 공지에 따르면 stdio는 영향받지 않습니다.[1], [4]
전역 자격 증명 fallback
요청에 개별 사용자 ID가 없을 때 서버 환경에 설정된 Jira 또는 Confluence 자격 증명을 사용하는 동작입니다. 원격에서 접근 가능한 HTTP에서는 익명 요청이 운영자 권한의 작업이 될 수 있습니다.[1], [4]
인증 경계
요청이 보호된 도구 핸들러에 도달하기 전에 서버가 호출자의 ID를 확인하는 검사입니다. 네트워크 접근성, 비어 있지 않은 토큰 문자열, 프록시에 대한 가정된 신뢰만으로는 신원이 증명되지 않습니다.[1], [7]
CWE-287
부적절한 인증: 접근을 허용하기 전에 애플리케이션이 주장된 신원을 충분히 증명하지 않습니다.[1], [7]
CWE-303
토큰 검증기는 인증을 잘못 구현해 토큰의 유효성을 확인하지 않고 비어 있지 않은 모든 토큰을 받아들입니다.[1], [9]
CWE-862
HTTP 요청은 검증된 사용자 ID를 요구하는 권한 확인 없이 특권 도구 핸들러에 도달할 수 있었습니다.[1], [10]

프레임워크 매핑

근본 원인 분석 (Root Cause)

GitHub 보안 권고는 Atlassian 제품 취약점이 아니라 커뮤니티 프로젝트 mcp-atlassian의 공격 경로를 설명합니다. 0.22.0 이전에는 HTTP 미들웨어가 사용자 ID가 없는 요청을 도구 핸들러로 전달할 수 있었습니다. 배포 환경 변수가 운영자 자격 증명을 제공하면 JiraFetcher 또는 ConfluenceFetcher가 해당 전역 자격 증명으로 fallback할 수 있었습니다. 권고는 비어 있지 않은 모든 문자열을 받아들이는 opaque token 검증기도 설명하지만, 이는 호출자의 실제 신원을 증명하지 않습니다. 보안 경계는 요청 ID와 자격 증명 선택을 함께 보호해야 합니다. ID가 없거나 검증되지 않은 사용자가 운영자의 특권 자격 증명을 상속해서는 안 됩니다. 0.22.0 수정은 미인증 streamable-HTTP MCP POST에 HTTP 401을 반환하고, 단일 사용자 배포에서 ALLOW_GLOBAL_CRED_FALLBACK=true를 명시적으로 설정하지 않으면 HTTP 컨텍스트에서 전역 fallback을 차단합니다. stdio 동작은 바뀌지 않습니다. 별도로 GHSA-5j8j-256g-vvp5는 0.23.1에서 해결된 SSE 경로 매칭 문제를 다룹니다. 이는 CVE-2026-77244가 아닙니다. SSE 배포는 0.23.1 이상으로 업데이트하고 CVE의 0.22.0 수정이 별도 권고도 해결한다고 가정하지 마세요. 권고는 확인된 악용을 보고하지 않으며, 이 글도 실제 침해를 주장하지 않습니다. CVE 권고는 이 경로의 인증, 토큰 검증, 권한 부여 결함을 CWE-287, CWE-303, CWE-862로 분류합니다. 이 보안 권고는 제보자로 crazydude123을 명시합니다.[1], [3], [4], [5], [6], [7], [9], [10]

단계별 공격 실행 흐름

단계 1

MCP HTTP 엔드포인트에 접근 가능

커뮤니티 mcp-atlassian 서버가 HTTP로 실행되고 미인증 당사자가 전송 계층에 도달할 수 있습니다. stdio만 사용하는 배포는 이 CVE의 영향 경로에 포함되지 않습니다.[1]

단계 2

검증된 사용자 없이 요청이 도구에 도달

0.22.0 이전에는 사용자 ID가 없는 HTTP 요청이 전송 경계에서 거부되지 않고 미들웨어를 통과할 수 있었습니다. 권고는 비어 있지 않은 문자열도 독립적인 신원으로 검증되지 않았다고 설명합니다.[1], [3]

단계 3

도구가 운영자의 공유 자격 증명을 선택

사용자 ID가 없고 서버 환경에 Jira 또는 Confluence 자격 증명이 있으면 fetcher가 전역 자격 증명을 쓸 수 있습니다. 요청은 운영자가 활성화한 도구 권한을 행사할 수 있으며 정확한 영향은 권한과 설정에 달려 있습니다.[1], [3]

단계 4

전송 계층에서 거부하고 자격 증명 선택도 fail closed로 처리

0.22.0은 미인증 streamable-HTTP 요청에 HTTP 401을 반환하고 명시적 허용 없이는 HTTP 컨텍스트의 전역 fallback을 차단합니다. SSE는 별도 경로 매칭 문제가 수정된 0.23.1 이상을 사용하세요.[1], [4], [5], [6]

소스 코드 비교: 취약한 구현 vs 보안 패치

영향받는 제어 흐름을 축약해 표현한 것이며 전체 함수의 그대로 복사한 코드는 아닙니다. upstream 수정은 전송 경계에서 HTTP 401을 반환하고 HTTP 컨텍스트에서 전역 fetcher를 반환하기 전에 두 번째 검사를 추가합니다.[1], [3], [4]

취약한 구현
# 영향을 받은 제어 흐름을 간략히 나타낸 것입니다.
async def handle_request(scope, ctx):
    user_identity = scope.get("state", {}).get("user_atlassian_auth_type")
    # HTTP 경계에서 신원 정보가 없는 요청을 거부하지 않았습니다.
    return await call_tool_handler(ctx, user_identity=user_identity)

def get_fetcher(user_identity, global_config):
    if user_identity:
        return fetcher_for_user(user_identity)
    # 환경에 설정된 운영자 자격 증명으로 대체합니다.
    return fetcher_from_config(global_config)
보안 강화 패치
# 0.22.0에 통합된 보호 조치를 간략히 나타낸 것입니다.
async def handle_request(scope, ctx):
    user_identity = scope.get("state", {}).get("user_atlassian_auth_type")
    if is_mcp_http_post(scope) and not user_identity and not allow_global_fallback():
        return http_401("Authentication required")
    return await call_tool_handler(ctx, user_identity=user_identity)

def get_fetcher(user_identity, global_config, *, in_http_context):
    if user_identity:
        return fetcher_for_user(user_identity)
    if in_http_context and not allow_global_fallback():
        raise PermissionError("Refusing operator credentials for an unauthenticated HTTP request")
    return fetcher_from_config(global_config)

엔지니어링 및 시스템 보안 강화 체크리스트

출처