flawopen.com/Teardowns/cve-2026-21589-atlassian-arbitrary-file-access
CVE-2026-21589: Atlassian Data Center 파일 접근 취약점
Atlassian 권고문과 10월 12일 MS-ISAC 보고는 위험과 긴급성을 보여 주지만, 특정 고객 인스턴스의 악용을 입증하지는 않습니다.[1], [4], [5], [10]
방문객이 말한 서가 위치를 받아들이는 도서관을 떠올려 보세요. 모든 서가를 둘러볼 수는 없지만 특정 책의 위치를 이미 알고 있다면, 경계 검사 오류로 직원이 공개 열람 구역 밖에서 책을 가져올 수 있습니다. 수정은 해석된 경로를 허용된 범위 안에 두고 제품별 업데이트를 적용하는 것입니다.[1], [4]
핵심 개념 및 용어
임의 파일 접근- 요청이 의도된 범위 밖의 파일에 접근할 수 있는 상태입니다. Atlassian은 전체 파일 시스템이 아니라 웹 애플리케이션 루트 아래 특정 파일에 대한 접근을 설명합니다.[1], [4]
Data Center- Atlassian의 자체 관리형 배포 모델입니다. 공지는 제품 8종을 나열하며 Atlassian은 Cloud 제품은 패치되었다고 밝혔습니다.[1]
경로 사전 지식- 대상 파일의 정확한 이름과 경로를 미리 알아야 합니다. 공지에 따르면 이 취약점으로 디렉터리를 열거할 수는 없습니다.[1]
CVSS 4.0- Atlassian은 자체 평가에서 이 취약점을 Critical, CVSS 4.0 9.3으로 분류했습니다.[1]
Router.unescapeSlashes()- 공유 라이브러리는 리소스 처리 전에 인코딩된 구분자
::를/로 되돌립니다. watchTowr의 소스 분석에서 이 디코딩 경계가 핵심입니다.[1], [4] Crowd 자격 증명 체인- 구성에 따라 이어질 수 있는 단계입니다. 읽을 수 있는 Crowd 속성 파일이 애플리케이션 암호를 노출할 수 있으며, 사용 가능성은 네트워크 접근과 권한에 달립니다.[4], [5]
CWE-22- 경로 탐색 약점에 대한 FlawOpen의 편집상 분류입니다. 경로가 의도한 디렉터리 안으로 충분히 제한되지 않았습니다. Atlassian 공지에는 CWE가 지정되지 않았습니다.[6]
프레임워크 매핑
- MITRE CWE에 대한 FlawOpen의 개념적 매핑입니다. 공급업체나 CVE 레코드가 이 연구 시연에 해당 약점 ID를 지정한 것은 아닙니다. CWE-22
근본 원인 분석 (Root Cause)
watchTowr의 공유 라이브러리 atlassian-plugins-webresource 분석은 경로 디코딩 경계를 짚습니다. Router.unescapeSlashes()는 ::를 /로 바꾸며, 리소스 경로는 핸들러를 호출하기 전에 요청자가 제어하는 경로 구성 요소에 이 함수를 적용합니다. 후속 조회는 리소스 이름을 분리해 남은 상대 경로를 createResourceWithRelativePath()에 전달합니다. 이때 대체 구분자 표현이 경로 순회 검사 가정을 우회할 수 있습니다. 연구진은 Jira, Confluence, Bitbucket에서 Tomcat 애플리케이션 컨텍스트 안의 파일 읽기를 시연했고 Atlassian은 8개 제품을 영향 대상으로 명시했습니다. 보고서에 따르면 테스트한 경로는 Tomcat 컨텍스트 밖으로 나가지 않았습니다. 조건이 맞으면 읽을 수 있는 WEB-INF/classes/crowd.properties에서 Crowd 애플리케이션 암호가 평문으로 노출될 수 있으며, 실제 영향은 구성과 Crowd 네트워크 접근성에 달립니다. BleepingComputer는 기술 보고서와 PoC 공개 몇 시간 뒤 Previdian 센서가 시도를 관찰했다고 보도했습니다. 이는 허니팟 대상 시도이며 고객 시스템 침해 성공의 증거는 아닙니다. 아래 취약 Java 발췌는 watchTowr 보고서에 공개된 내용입니다. 안전한 코드는 일반적인 경로 제한 패턴이며 공개되지 않은 Atlassian 패치 코드가 아닙니다. 제품별 공식 업데이트를 적용하세요.[1], [4], [5]
단계별 공격 실행 흐름
디코딩된 경로가 리소스 조회로 전달
헬퍼가 경로 구성 요소를 나누고 남은 상대 경로를 리소스 팩토리에 전달합니다. 대체 구분자는 순회 검사 가정을 우회할 수 있습니다.[4]
관찰된 시도는 긴급성을 높이지만 침해를 증명하지 않음
10월 12일 Center for Internet Security의 MS-ISAC 권고문은 CVE-2026-21589가 실제 환경에서 악용되고 있다는 보고가 있다고 밝혔습니다. 피해자를 특정하거나 사건 증거를 공개하지 않았으므로, 이를 MS-ISAC가 전한 악용 보고로 표현해야 하며 특정 고객에 대한 접근이 확인된 것으로 말해서는 안 됩니다. Atlassian의 10월 5일 권고문은 Cloud 제품에서 악용 증거를 찾지 못했다고 밝혔으며, 해당 제품에는 패치가 적용되었다고 했습니다. 이 조사 결과는 Cloud에 한정되므로 취약점 악용 보고를 전한 MS-ISAC의 발표와 모순되지 않습니다. 어느 발표도 특정 인스턴스에서 발생한 일을 확정하지 않습니다.[1], [10]
소스 코드 비교: 취약한 구현 vs 보안 패치
취약 코드 발췌는 watchTowr가 공개한 영향을 받는 web-resource 라이브러리의 소스 경로 변환을 보여주며, 익스플로잇 요청이 아닙니다. 아래 예시는 일반적인 Java 방어 방법이며 Atlassian 패치가 아닙니다. 신뢰할 수 있는 루트에서 SecureDirectoryStream 핸들을 사용해 경로를 단계별로 탐색하고, 각 구성 요소의 심볼릭 링크를 거부하며, 읽는 바이트 수를 제한합니다. 호출자는 한 번만 디코딩된 상대 경로와 신뢰할 수 있는 디렉터리를 루트로 연 SecureDirectoryStream을 전달해야 합니다. 일부 파일 시스템 공급자는 SecureDirectoryStream을 지원하지 않으므로, 이 경우 안전하게 실패해야 합니다. 제품별 공급자 수정 버전을 설치하세요.이 예시는 신뢰할 수 있는 리소스 트리를 전제로 합니다. 신뢰할 수 없는 주체가 디렉터리와 파일을 변경할 수 없어야 하며 일반 파일만 포함해야 합니다. 코드 자체가 파일 유형을 검증하지는 않습니다. 바이트 제한과 진행이 없는 읽기에 대한 제한된 처리는 읽기량을 제한하지만, 범용 파일 제공 루틴은 아닙니다. 호출자는 한 번만 디코딩된 상대 경로를 전달하고 신뢰할 수 있는 루트 스트림을 열린 상태로 유지해야 합니다. 파일 시스템 공급자가 SecureDirectoryStream을 지원하지 않을 수 있으므로 사용할 수 없으면 안전하게 실패하세요.[4], [7]
public static String unescapeSlashes(String string) {
return string.replaceAll("::", "/");
}
static byte[] readUnder(SecureDirectoryStream<Path> root, Path relative, int maxBytes) throws IOException {
if (relative.isAbsolute() || relative.getNameCount() == 0 || maxBytes < 0) {
throw new SecurityException("Expected a relative path and non-negative limit");
}
List<SecureDirectoryStream<Path>> opened = new ArrayList<>();
SecureDirectoryStream<Path> parent = root;
try {
for (int i = 0; i < relative.getNameCount() - 1; i++) {
Path part = relative.getName(i);
if (part.toString().isEmpty() || part.toString().equals(".") || part.toString().equals("..")) {
throw new SecurityException("Invalid path component");
}
parent = parent.newDirectoryStream(part, LinkOption.NOFOLLOW_LINKS);
opened.add(parent);
}
Path leaf = relative.getFileName();
if (leaf.toString().isEmpty() || leaf.toString().equals(".") || leaf.toString().equals("..")) {
throw new SecurityException("Invalid file name");
}
try (SeekableByteChannel channel = parent.newByteChannel(
leaf, Set.of(StandardOpenOption.READ, LinkOption.NOFOLLOW_LINKS))) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteBuffer buffer = ByteBuffer.allocate(8192);
int total = 0;
int zeroReads = 0;
while (true) {
int count = channel.read(buffer);
if (count == -1) break;
if (count == 0) {
if (++zeroReads >= 3) throw new IOException("Resource read made no progress");
continue;
}
zeroReads = 0;
if (count > maxBytes - total) throw new IOException("Resource exceeds size limit");
out.write(buffer.array(), 0, count);
total += count;
buffer.clear();
}
return out.toByteArray();
}
} finally {
for (int i = opened.size() - 1; i >= 0; i--) opened.get(i).close();
}
}
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓최소 수정 버전: Bitbucket 9.4.26 / 10.2.8 / 10.5.1, Confluence 9.2.26 / 10.2.19, Jira Service Management 5.12.40 / 10.3.26 / 11.3.12, Jira Software 9.12.40 / 10.3.26 / 11.3.12, Bamboo 10.2.24 / 12.1.12, Crowd 6.3.7 / 7.0.3 / 7.1.7 / 7.2.4, Crucible 및 Fisheye 4.9.15입니다. 제품별 버전 계열을 확인하세요.[1]
- ✓영향받는 자체 관리형 제품 8종(Data Center로 명시된 6개와 Crucible, Fisheye), 노드와 미러, 인터넷에 노출된 인스턴스를 파악하세요. Atlassian은 Cloud 제품은 패치했다고 밝혔습니다.[1]
- ✓각 영향받는 설치를 공지의 수정 버전으로 업데이트하고 클러스터의 모든 노드에서 실제 실행 버전을 확인하세요.[1]
- ✓즉시 패치할 수 없다면 패치나 완화 조치를 적용할 때까지 외부 접근을 제한하세요. 모든 관련 노드에 제품에 맞는 임시 WAF/프록시, Tomcat RewriteValve 또는 Bitbucket urlrewrite.xml 규칙을 적용하고, 이를 신뢰하기 전에 인코딩 변형을 테스트하세요.[1]
- ✓Atlassian 지침대로 접근 로그의 URL을 최대 두 차례 디코딩해
/,\,::에 인접한..를 찾고 원본 로그를 보존하세요.[1], [9] - ✓일치하는 요청은 조사 신호이지 파일이 반환되었다는 증거가 아닙니다. Atlassian은 침해 여부를 확인하지 못했습니다. 당시 존재한 민감 파일을 평가하고 확보한 증거에 따라 대응 조치를 결정하세요.[1], [9]
- ✓자체 코드에서는 정규화 단계를 하나로 정하고 허용된 루트 안에 경로가 포함되는지 강제하며 심볼릭 링크, 경쟁 조건, 각 디코딩 계층을 고려하세요.[7], [6]
출처
- Atlassian 보안 공지 — CVE-2026-21589
- CERT-EU — Atlassian 제품 다수의 중대 취약점
- 캐나다 사이버보안센터 — Atlassian 공지 AV26-1002
- watchTowr Labs — CVE-2026-21589 technical analysis
- BleepingComputer — observed CVE-2026-21589 exploitation attempts
- MITRE CWE-22 — Path Traversal (FlawOpen editorial mapping)
- Oracle Java API — SecureDirectoryStream
- Previdian — sensor telemetry and exploitation methodology
- NIST SP 800-61 Rev. 3 — 사고 대응 권고사항
- Center for Internet Security MS-ISAC — CVE-2026-21589 exploitation report (October 12, 2026)