EKSPLOITASI BUFFER OVERFLOW



EKSPLOITASI BUFFER OVERFLOW

Pendahuluan

Buffer Overflow merupakan salah satu penyebab yang paling banyak menimbulkan masalah pada keamanan komputer baik yang bersifat lokal maupun jaringan. Menurut laporan CERT/CC, buffer overflow merupkan penyebab dari 50% semua bug keamanan yang dilaporkan dan dijadikan advisori oleh CERT/CC. Riset yang dilakukan oleh Crispin Cowan dan teamnya menganggap buffer overflow sebagai Vulnerbility of Decade.

Dengan tersedianya program-program eksploitasi di Internet, baik dalam bentuk source code maupun binary seringkali menjadi menjadi alat untuk membuka celah keamanan sehingga membuat orang tertarik untuk melakukan eksperimen yang sporadis tanpa memperdulikan akibat yang dapat ditimbulkannya. Banyak orang yang mengklaim dirinya sebagai seorang cracker jika sudah berhasil mengekspoitasi komputer orang lain, tanpa memahami cara kerja eksploitasi tersebut sesungguhnya.

Terlepas dari masalah tersebut diatas, tulisan ini akan membahas apakah sebenarnya buffer overflow itu dan bagaimana mekanisme untuk mengeksploitasinya/penyerangan menggunakan buffer over flow, cara memperbaiki sistem yang ter-buffer overflow dan bagaimana cara menghindari/mencegah agar sistem kita aman dari serangan melalui eksploitasi buffer overflow. Untuk memahami hal tersebut diatas diperlukan juga pemahaman mengenai cara kerja sistem prosesor di level bawah, seperti pemrograman asembly, manajemen memori text, stack, data dan sebagainya. Pada tulisan ini sebagai referensi dipilih prosesor Intel x86 yang mengorganisasi sistem memori menggunakan 4 byte dan menggunakan Linux sebagai sistem operasinya.

Pengertian Dasar

Manajemen Memori pada Proses

Sebuah proses dipandang dari sudut manajemen memori dibedakan menjadi tiga bagian :

1. Text; memuat instruksi kode program. Bagian ini biasanya hanya bisa dibaca, dan setiap usaha untuk menuliskan data ke bagian ini akan menyebabkan kesalahan segmentation violation.

2. Data; memuat data, baik yang telah diinisialisasi maupun yang belum. Selain dapat dibaca, biasanya bagian ini juga memperbolehkan suatu proses untuk melakukan penulisan padanya.

3. Stack; yang dapat dialokasikan secara dinamis, biasanya dimanfaatkan untuk menyimpan variabel lokal maupun untuk melewatkan parameter fungsi.

Pengaksesan data ke bagian ini menggunakan metoda yang disebut LIFO (Last In First Out). Jenis data yang harus juga diketahui adalah buffer yang pada bahasa C diimplementasikan sebagai array. Array dapat dibedakan ke dalam dua jenis berdasarkan metoda pengalokasiannya, yaitu array statis dan array dinamis. Array statis dialokasikan di bagian data saat program dimuatkan ke memori, sedangkan array dinamis dialokasikan di dalam stack saat run time.

Stack

Stack dapat dibayangkan sebagai sebuah blok dari memori yang dapat memuat data secara dinamis.

|msb | | |lsb |

| | | | |

| | | | |

| | | | |

| | | | |

| | | | |

Gambar 1. Blok memori stack pada prosesor Intel

Beberapa hal yang harus diketahui pada prosesor Intel sehubungan dengan stack adalah :

1. Penggunaan metoda Big Edian dalam mengorganisasikan sistem memori. Di sini MSB (Most Significant Bit) terletak pada alamat memori yang lebih kecil dibandingkan LSB (Least Significant Bit).

2. Penambahan besar stack dilakukan kearah alamat memori yang lebih kecil. Di sini posisi bawah dari stack mempunyai alamat yang tetap. Posisi atas stack yang alamat memorinya lebih kecil dari posisi bawah selalu berubah.

3. Register stack pointer (SP) selalu menunjuk ke posisi atas dari stack.

4. Untuk memindahkan data ke stack digunakan instruksi PUSH yang secara otomatis akan menurunkan nilai SP sebesar 4 byte. Sedangkan untuk mengambil data dari stack digunakan instruksi POP yang secara otomatis juga akan menaikkan nilai SP sebesar 4 byte.

Gambar 1 memperlihatkan diagram dari sebuah memori stack dari prosesor Intel.

Blok memori dari stack ini biasanya di bagi lagi menjadi apa yang disebut dengan stack frame. Setiap stack frame berisi data yang berhubungan dengan pemanggilan sebuah fungsi. Biasanya posisi awal dari frame ini akan ditunjuk oleh frame pointer (FP). Dengan bantuan FP ini, maka pengaksesan ke variabel lokal maupun parameter fungsi dapat dilakukan menggunakan sistem pengalamatan relatif. Pada prosesor Intel, register EBP berfungsi sebagai frame pointer.

Cara Kerja Stack

Untuk lebih mengerti bagaimana cara kerja stack pada pemanggilan suatu fungsi, sebagai contoh akan dibuat program kecil dalam bahasa C, dan kemudian akan dikonversikan ke dalam bahasa assembly.

# coba1.c

#include

void fungsi(int satu, int dua)

{

int buffer[2];

buffer[0]=satu;

buffer[1]=dua;

}

int main()

{

fungsi(1,2);

return 0;

}

Untuk menghasilkan kode assembly dapat digunakan program gcc dengan menyertakan option –S saat mengkompilasi file di atas :

$ gcc –S –o coba1.s coba1.c

Di fungsi main() pemanggilan fungsi fungsi() diubah ke dalam bahasa assembly sebagai berikut :

push $2

Push $1

call fungsi

| | | | | | |

|Buffer[0] |Buffer[1] |EBP |RET |satu |dua |

Gambar 2. Blok memori dari stack pada pemanggilan fungsi

Sebelum memanggil fungsi fungsi() dua buah argumen sebagai parameter ditambahkan ke stack. Instruksi call di atas secara implisit juga akan menyimpan instruction pointer (IP) ke stack. IP ini selanjutnya akan di sebut dengan return address (RET).

Kode assembly yang di bangkitkan pada fungsi fungsi();

1. pushl %ebp

2. movl %esp, %ebp

3. subl $24,%esp

Baris pertama akan menyimpan frame pointer EBP ke stack untuk kemudian di baris kedua menggunakan SP sebagai frame pointer yang aktual. Pada baris ketiga 24 byte memori untuk variabel lokal buffer[ ] dialokasikan di stack, walau hanya 8 byte yang digunakan.

1. movl 8(%ebp), %eax

2. movl %eax, -8(%ebp)

3. movl 12(%ebp), %eax

4. movl %eax, -4(%ebp)

Baris diatas adalah pengesetan variabel buffer [ ] dengan parameter dari fungsi. Seperti telihat pada baris pertama, pengaksesan ke parameter satu di stack dilakukan dengan pengalamatan relatif terhadap frame pointer EBP. Setelah nilai ini disimpan di register EAX maka dengan cara yang sama nilai ini di simpan ke stack yang jaraknya –8 byte terhadap frame pointer EBP (baris kedua). Stack ini identik dengan variable buffer[0]. Baris ketiga dan keempat melakukan hal yang sama untuk parameter dua. Dari uraian diatas, maka blok memori stack dapat dilukiskan seperti gambar 2.

Seperti yang sudah dikemukakan diatas, prosesor yang digunakan adalah Intel x86 yang menggunakan bus 32-bit atau 4 byte dalam pengaksesan ke memori, sehingga pengalamatan ke memori selalu merupakan kelipatan 4 byte, sedangkan besar dari tipe data int dan pointer adalah 4 byte juga.

Dari gambar diatas terlihat jelas bahwa memori parameter fungsi mempunyai jarak relatif yang positif terhadap frame pointer EBP, sedangkan variable local seperti buffer mempunyai jarak relatif yang negatif.

Jika variable lokal merupakan sebuah array, maka array dengan indeks terkecil mempunyai alamat memori yang paling kecil juga. Dengan kata lain elemen variable array di simpan dengan indeks membesar ke arah alamat memori yang juga membesar. Pada stack, ini adalah arah ke posisi bawah dari blok memori stack. Sifat stack inilah yang memungkinkan terjadinya buffer overflow.

Buffer Overflow

Buffer overflow memiliki arti suatu keadaan di mana data yang diisikan ke suatu buffer mempunyai ukuran yang lebih besar dibandingkan ukuran buffer itu sendiri. Untuk lebih memahami buffer overflow, dapat dianalogikan dengan kehidupan sehari-hari, yaitu saat kita mengisi bak mandi melebihi daya tampungnya, maka air yang kita isikan akan meluap (overflow).

Berikut ini contoh sebuah program dalam bahasa C yang mengandung buffer overflow.

# Coba2.c

#include

void fungsi(char* txt)

{

char buffer[4];

strcpy(buffer, txt);

}

int main()

{

char buffer[17];

int i;

for (I=0; i ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download