FlawOpen

flawopen.com/Teardowns/cve-2026-21589-atlassian-arbitrary-file-access

● CVE-2026-21589 · CVSS v4 9.3 · Kritis
Riset Keamanan · FlawOpen

CVE-2026-21589: akses file Atlassian Data Center

Imbauan Atlassian dan laporan MS-ISAC pada 12 Oktober menunjukkan risiko dan urgensi, tetapi tidak membuktikan eksploitasi pada instans pelanggan tertentu.[1], [4], [5], [10]

💡 Penjelasan Sederhana (ELI5)

Bayangkan perpustakaan yang menerima lokasi rak dari pengunjung. Pengunjung tidak bisa melihat semua rak, tetapi jika sudah tahu letak buku tertentu, pemeriksaan batas yang keliru dapat membuat petugas mengambilnya dari luar area baca umum. Perbaikan menjaga setiap jalur yang diurai tetap di area yang diizinkan dan memasang pembaruan produk terkait.[1], [4]

Konsep Kunci & Istilah

Akses file arbitrer
Permintaan dapat menjangkau file di luar cakupan yang dimaksud. Atlassian menjelaskan akses ke file tertentu di bawah akar web aplikasi, bukan seluruh sistem berkas.[1], [4]
Path traversal
Komponen jalur melewati batas direktori yang seharusnya. Mitigasi Atlassian menargetkan penanda traversal dan bentuk URL yang dikodekan.[1], [4]
Data Center
Model penerapan mandiri Atlassian. Penasihat mencantumkan delapan produk terdampak; Atlassian menyatakan produk Cloud telah diperbaiki.[1]
Jalur yang diketahui
Nama dan jalur file yang tepat harus diketahui sebelumnya; penasihat menyatakan kerentanan ini tidak dapat membuat daftar atau enumerasi direktori.[1]
CVSS 4.0
Atlassian menilai kerentanan ini Critical dengan CVSS 4.0 9,3 berdasarkan penilaian internalnya.[1]
Router.unescapeSlashes()
Pustaka bersama mengubah separator berkode :: kembali menjadi / sebelum menangani resource; batas decoding ini menjadi inti analisis sumber watchTowr.[1], [4]
ResourceServingHelpers
Helper ini menyelesaikan nama resource lalu meneruskan sisa jalur relatif ke createResourceWithRelativePath().[1], [4]
Rantai kredensial Crowd
Tahap lanjutan bersyarat: file properti Crowd yang dapat dibaca mungkin mengungkap kata sandi aplikasi; jaringan dan otorisasi menentukan apakah kredensial dapat digunakan.[4], [5]
CWE-22
Pemetaan editorial FlawOpen untuk kelemahan path traversal: jalur tidak dibatasi secara memadai ke direktori yang dimaksud. Advisory Atlassian tidak menetapkan CWE.[6]

Pemetaan kerangka kerja

  • Pemetaan konseptual FlawOpen ke MITRE CWE; tidak ada vendor atau catatan CVE yang menetapkan ID kelemahan ini untuk demonstrasi riset tersebut. CWE-22

Analisis Akar Masalah (Root Cause)

Analisis watchTowr terhadap pustaka bersama atlassian-plugins-webresource menunjukkan batas decoding jalur. Router.unescapeSlashes() mengubah :: menjadi /; rute resource menerapkan fungsi ini pada komponen jalur yang dikendalikan permintaan sebelum memanggil handler resource. Pencarian berikutnya memisahkan nama resource dan meneruskan sisa jalur relatif ke createResourceWithRelativePath(), tempat representasi pemisah alternatif dapat melewati asumsi pemeriksaan traversal. Peneliti menunjukkan pembacaan file di dalam konteks aplikasi Tomcat pada Jira, Confluence, dan Bitbucket; Atlassian menyebut delapan produk terdampak. Laporan menyatakan pengujian tidak keluar dari konteks Tomcat. Dalam rantai bersyarat, WEB-INF/classes/crowd.properties yang dapat dibaca mungkin mengungkap kata sandi aplikasi Crowd dalam teks biasa; dampak bergantung pada konfigurasi dan keterjangkauan Crowd. BleepingComputer melaporkan sensor Previdian melihat percobaan beberapa jam setelah laporan teknis dan PoC dipublikasikan. Itu adalah percobaan terhadap honeypot, bukan bukti akses berhasil ke sistem pelanggan. Cuplikan Java rentan di bawah berasal dari laporan watchTowr. Contoh pertahanan adalah pola containment umum, bukan patch Atlassian yang kode lengkapnya belum dipublikasikan; pasang pembaruan resmi tiap produk.[1], [4], [5]

Alur Serangan Langkah demi Langkah

Langkah 1

Decoder bersama mengubah jalur

Router web-resource Atlassian mengubah pemisah alternatif :: menjadi / sebelum menyajikan resource. Decoding ini bagian dari routing resource normal.[1], [4]

Langkah 2

Pencarian resource menerima jalur terdekode

Helper memisahkan komponen jalur lalu meneruskan sisa jalur relatif ke resource factory. Pemisah alternatif dapat melewati asumsi pemeriksaan traversal.[4]

Langkah 3

File dalam konteks aplikasi dapat dibaca

watchTowr menunjukkannya pada Jira, Confluence, dan Bitbucket. Laporan menyebut jalur uji tidak keluar dari konteks Tomcat; jangan menyimpulkan semua file host dapat dibaca.[1], [4]

Langkah 4

Rantai identitas bergantung pada konfigurasi

Jika konfigurasi Crowd yang terbaca berisi kata sandi aplikasi dan Crowd dapat dijangkau serta menerima kredensial itu, fungsi identitas mungkin dapat diakses. Daftar izin jaringan dan konfigurasi menentukan dampaknya.[4], [5]

Langkah 5

Percobaan yang diamati meningkatkan urgensi, bukan membuktikan kompromi

Pada 12 Oktober, imbauan MS-ISAC dari Center for Internet Security menyatakan ada laporan eksploitasi CVE-2026-21589 di lingkungan nyata. Imbauan itu tidak menyebut korban atau menerbitkan bukti insiden, jadi perlakukan ini sebagai sinyal eksploitasi yang dilaporkan MS-ISAC, bukan konfirmasi akses ke pelanggan tertentu. Imbauan Atlassian pada 5 Oktober menyatakan penyelidikannya tidak menemukan bukti eksploitasi pada produk Cloud, yang menurutnya telah ditambal. Temuan itu terbatas pada Cloud dan tidak bertentangan dengan laporan MS-ISAC mengenai eksploitasi kerentanan ini. Tidak satu pun pernyataan memastikan apa yang terjadi pada instans tertentu.[1], [10]

Kode Sumber: Rentan vs Aman

Cuplikan rentan menunjukkan transformasi jalur pada kode sumber yang diterbitkan watchTowr untuk pustaka web-resource yang terdampak; ini bukan permintaan eksploitasi. Contoh di bawah adalah pertahanan umum Java, bukan patch Atlassian: penelusuran dari root tepercaya melalui handle SecureDirectoryStream, penolakan tautan simbolis pada setiap komponen, dan pembatasan jumlah byte yang dibaca. Pemanggil harus memberikan jalur relatif yang didekode tepat satu kali dan SecureDirectoryStream yang dibuka dari direktori tepercaya. Sebagian provider sistem berkas mungkin tidak mendukung SecureDirectoryStream; jika demikian, gagalkan operasi dengan aman. Pasang perbaikan vendor untuk produk yang sesuai.Contoh ini mengasumsikan pohon sumber daya tepercaya, dengan direktori dan berkas yang tidak dapat diubah oleh pihak tak tepercaya serta hanya berisi berkas reguler; contoh ini tidak memeriksa jenis berkas secara mandiri. Batas byte dan penanganan terbatas untuk pembacaan tanpa progres membatasi pembacaan, tetapi ini bukan rutinitas penyajian berkas universal. Pemanggil harus memberikan jalur relatif yang didekode tepat satu kali dan mempertahankan stream root tepercaya tetap terbuka. Provider sistem berkas mungkin tidak mendukung SecureDirectoryStream; gagalkan operasi dengan aman jika tidak tersedia.[4], [7]

IMPLEMENTASI RENTAN
public static String unescapeSlashes(String string) {
    return string.replaceAll("::", "/");
}
PERBAIKAN AMAN & KUAT
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();
    }
}

Daftar Periksa Penguatan Sistem Rekayasa

Sumber