flawopen.com/Incidents/equifax-struts-ognl-rce-july-2017
Equifax: data hampir 150 juta orang terdampak
CVE-2017-5638 memungkinkan injeksi OGNL melalui header Content-Type pada portal Struts Equifax yang belum diperbaiki. Serangan berlangsung sekitar 76 hari dan memengaruhi data hampir 150 juta orang.[1], [4]
Bayangkan perangkat lunak pengiriman memasukkan label paket yang ditolak ke dalam pesan kesalahan. Jika pesan itu memperlakukan label sebagai templat instruksi yang dapat dijalankan, pengirim dapat membuat perangkat lunak mengikuti instruksi, bukan sekadar melaporkan alamat yang salah. Patch Struts sudah tersedia, tetapi pemberitahuan Equifax dikirim ke daftar administrator yang usang dan pemindaian jaringan tidak mendeteksi kerentanan pada portal tersebut.[1], [4]
Konsep Kunci & Istilah
OGNL- Object-Graph Navigation Language, bahasa ekspresi yang dipakai Struts untuk membaca dan mengatur properti objek Java. Mengevaluasi teks penyerang sebagai OGNL berarti menjalankan kode penyerang.[1], [6]
Parser multipart Jakarta- Komponen Struts yang menangani unggahan berkas. Saat menolak Content-Type yang salah bentuk, komponen ini menyusun pesan galat yang kemudian dievaluasi.[1], [3], [2]
Injeksi ekspresi (CWE-917)- Masukan tak tepercaya masuk ke dalam ekspresi yang dievaluasi interpreter, sehingga data berubah menjadi instruksi.[6]
Inventaris aset- Catatan perangkat lunak dan versi apa yang berjalan di sistem mana. Tanpanya, pemberitahuan patch tidak bisa dicocokkan dengan mesin yang membutuhkannya.[4]
Pemetaan kerangka kerja
- Referensi CWE untuk kelemahan yang dijelaskan dalam panduan ini: CWE-20 CWE-917
- CISA KEV — ditambahkan 2021-11-03 — CVE-2017-5638
Kronologi Insiden
Apache menerbitkan buletin keamanan S2-045 dan versi perbaikan Struts 2.3.32 serta 2.5.10.1.[1]
Equifax kemudian memberi tahu GAO bahwa intrusi terpisah dimulai pada 13 Mei dan penyerang mulai mengambil data pribadi; akses tanpa izin yang lebih awal sudah terjadi, tetapi belum ada data yang diambil.[4]
Equifax mendeteksi lalu lintas mencurigakan setelah memperbarui sertifikat kedaluwarsa pada perangkat inspeksi lalu lintas.[4]
Equifax mengumumkan pembobolan secara publik. GAO kemudian melaporkan bahwa data setidaknya 145,5 juta orang di AS dan hampir 1 juta orang di luar AS terdampak.[4]
Alur Serangan Langkah demi Langkah
Header Content-Type rekaan
Penyerang mengirim permintaan unggahan yang header Content-Type-nya berisi ekspresi OGNL, bukan tipe media.[1]
Pencurian data yang pelan dan senyap
Penyerang menggunakan kredensial yang ditemukan di repositori data untuk memperluas akses dari tiga basis data portal ke 48 basis data lain yang tidak terkait dengan portal. GAO melaporkan sekitar 9.000 kueri dan serangan selama kira-kira 76 hari; sertifikat kedaluwarsa membuat lalu lintas terenkripsi tidak dapat diperiksa.[4]
Kode Sumber: Rentan vs Aman
Java ilustratif, bukan kode sumber Struts; perbaikan sebenarnya di 2.3.32 dan 2.5.10.1 mengubah cara galat multipart disusun. Versi yang diperkuat memakai kunci pesan tetap dan meneruskan header hanya sebagai argumen posisi, sehingga ia diformat sebagai teks dan tidak pernah menjadi bagian dari ekspresi. Versi ini juga mengganti nilai apa pun yang tidak tampak seperti tipe media dengan penanda, sehingga perubahan pesan di masa depan pun tidak dapat mengembalikan header ke dalam string yang dievaluasi.[3], [2], [6]
import com.opensymphony.xwork2.TextProvider;
import javax.servlet.http.HttpServletRequest;
public final class UploadErrors {
private final TextProvider text; // resolves messages and evaluates expressions in them
public UploadErrors(TextProvider text) {
this.text = text;
}
public String describe(HttpServletRequest request) {
String contentType = request.getHeader("Content-Type");
// Header mentah menjadi bagian dari pesan yang dievaluasi.
return text.getText("Invalid content type: " + contentType);
}
}import com.opensymphony.xwork2.TextProvider;
import java.util.Locale;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
public final class UploadErrors {
private static final Pattern MEDIA_TYPE = Pattern.compile(
"^[a-z]+/[a-z0-9.+-]+(;\\s*[a-z0-9-]+=[a-z0-9._-]+)*$");
private final TextProvider text;
public UploadErrors(TextProvider text) {
this.text = text;
}
public String describe(HttpServletRequest request) {
String contentType = request.getHeader("Content-Type");
boolean wellFormed = contentType != null && contentType.length() <= 256
&& MEDIA_TYPE.matcher(contentType.toLowerCase(Locale.ROOT)).matches();
// Gunakan kunci pesan tetap; header hanya boleh menjadi argumen posisi,
// dan itu pun hanya jika bentuknya menyerupai tipe media.
return text.getText("upload.invalid.content.type",
new String[] { wellFormed ? contentType : "(malformed)" });
}
}Daftar Periksa Penguatan Sistem Rekayasa
- ✓Simpan SBOM untuk setiap aplikasi yang diterapkan dan pastikan Anda bisa menjawab "di mana kita menjalankan Struts 2.3.x?" dalam hitungan jam setelah imbauan seperti S2-045.[4]
- ✓Cocokkan target pemindai kerentanan dengan inventaris aset; hasil pindai bersih dari host yang tidak pernah masuk cakupan bukan bukti bahwa patch sudah terpasang.[4]
- ✓Picu peringatan kedaluwarsa sertifikat pada perangkat inspeksi TLS dan pemantauan paling lambat 30 hari sebelumnya; di sini sertifikat kedaluwarsa menyembunyikan pencurian data berbulan-bulan.[4]
- ✓Dalam tinjauan kode, tolak setiap panggilan yang meneruskan teks tak tepercaya hasil penggabungan ke resolver pesan, mesin templat, atau pengevaluasi ekspresi; teruskan sebagai argumen.[6]
- ✓Pisahkan basis data dari aplikasi yang menghadap internet, jauhkan kredensial dari berkas aplikasi, dan picu peringatan untuk volume kueri tak wajar dari akun aplikasi.[4]
Sumber
- Apache Struts — buletin keamanan S2-045 (CVE-2017-5638)
- Apache Struts — multipart parser error-message fix (commit 3523064)
- Apache Struts — upstream multipart error-handling fix (commit 6b8272c)
- GAO AS — Perlindungan data: tindakan Equifax dan lembaga federal setelah pembobolan 2017 (GAO-18-559)
- CVE-2017-5638 — catatan CVE
- MITRE CWE-917 — injeksi bahasa ekspresi
- Log4Shell: saat menulis ke berkas log menjadi eksekusi kode jarak jauh
- Injeksi perintah — referensi lengkap kelas