Buffer Overflow pada Proses Login

Artikel ini merupakan tulisan ulang dari tugas kuliah EL5215 Keamanan Perangkat Lunak, yaitu membuat aplikasi menjadi crash/segmentation fault. Aplikasi yang akan dibuat adalah implementasi buffer overflow pada proses login di aplikasi sederhana. Tugas ini merupakan tugas kedua dengan batas waktu pengumpulan 21 Maret 2017.

Pendahuluan

Buffer Overflow

Buffer overflow merupakan situasi di mana program yang sedang berjalan mencoba untuk menulis data di luar buffer memori yang tidak dimaksudkan untuk menyimpan data program tersebut. [2]⁠ Buffer memori merupakan area di memori komputer (RAM) yang dimaksudkan untuk menyimpan data sementara. Jenis buffer tersebut dapat ditemukan di semua program dan digunakan untuk menyimpan data untuk input, output dan proses. Contoh dari situasi buffer overflow adalah ketika suatu program menulis 10 byte data pada buffer yang berukuran 8 byte (ilustrasi lihat Gambar 1).

Contoh buffer overflow
Gambar 1. Contoh buffer overflow

Buffer overflow error dicirikan dengan menimpa fragmen memori dari suatu proses, yang seharusnya tidak pernah berubah, baik secara sengaja maupun tidak sengaja. [3]⁠ Menimpa nilai-nilai instruction pointer (IP), base pointer (BP), dan register lainnya sehingga menyebabkan segmentation fault, dan error lainnya. Biasanya error tersebut terjadi dengan cara yang tidak terduga. Buffer overflow error terjadi ketika user mengoperasikan buffer dari tipe karakter (char).

Persiapan Percobaan

Pada tugas ini akan dilakukan simulasi buffer overflow, yaitu percobaan pada login yang sangat sederhana menggunakan bahasa C, source code dapat dilihat pada login.c (lihat Lampiran). Percobaan ini dilakukan pada environment sebagai berikut.

  • Prosesor : Intel® Core™ i7-4720HQ CPU @ 2.60GHz × 8

  • Memory/RAM : 8 GB (available 7,3 GB)

  • Sistem Operasi : Ubuntu 16.04 (64-bit)

Percobaan

Password yang Diizinkan

Pada program tersebut, user akan diminta untuk memasukan password untuk melakukan login. Password yang diizinkan adalah sebagai berikut.

pass_alt_2

pass_alt_3

pass_alt_5

pass_alt_7

pass_alt_11

pass_alt_13

pass_alt_17

pass_alt_19

Pesan saat Login

Password selain yang di atas akan ditolak dan proses login akan gagal. Setelah memasukan password, program akan menampilkan pesan sebagai berikut.

  • Jika password benar:

    Password input = [password]. Login Success!

  • Jika password salah:

    Password input = [password]. Login Failed!

Tampilan pesan di atas muncul setelah program melakukan pemeriksaan pada masukan user dengan fungsi auth_check(). Fungsi auth_check() berfungsi memeriksa masukan user dan mencocokannya1 dengan nilai yang diperbolehkan. Jika masukan user merupakan salah satu dari password yang diizinkan, maka variabel auth_flag bernilai 1 dan kemudian menganggap bahwa password tersebut benar. Sebaliknya, jika masukan pengguna bukan salah satu dari password yang diizinkan, maka variabel auth_flag tetap bernilai 0 dan program menganggap password tersebut salah.

File Testing

Pada percobaan ini, percobaan login dilakukan dengan menjalankan file test.sh2 (lihat Lampiran) dengan menggunakan perintah berikut pada Terminal.

sh test.sh > test_output

Keluaran yang didapat dari percobaan tersebut adalah seperti pada file test_output (lihat Lampiran). Berdasarkan keluaran tersebut, didapat bahwa program berjalan sesuai dengan fungsi yang telah ditentukan, yaitu memberi tampilan bahwa login berhasil ketika masukan user merupakan password yang diizinkan dan memberi tampilan bahwa login gagal ketika masukan user bukan merupakan password yang diizinkan.

Alamat Memori

Sebelum melakukan percobaan kasus buffer overflow, perlu diketahui alamat memori yang digunakan oleh program, terutama alamat memori yang digunakan untuk menyimpan nilai pass_buff dan auth_flag. Untuk mengetahui hal tersebut, dilakukan pemanggilan perintah yang ada pada test.sh, yaitu:

gdb -q login < gdb_input_3 > gdb_output_3

gdb -q login < gdb_input_8 > gdb_output_8

File Output Debugging

Hasil dari perintah tersebut dapat dilihat pada file gdb_output_3 dan gdb_output_8 (lihat Lampiran). Pada masing-masing file tersebut terdapat dua breakpoint, yaitu pada baris ke-16 dan ke-31. Breakpoint pada baris ke-16 bertujuan untuk melihat alamat beserta nilai dari pass_buff dan auth_flag sesaat sebelum perintah strcpy() dieksekusi, sedangkan breakpoint pada baris ke-31 bertujuan untuk melihat alamat beserta nilai dari pass_buff dan auth_flag sesaat setelah perintah strcpy() dieksekusi.

Analisis: Nilai auth_flag

Berdasarkan hasil pada file gdb_output_3, didapat bahwa nilai auth_flag awal adalah nol dan setelah perintah strcpy() dieksekusi berubah menjadi 1. Hal tersebut sesuai dengan fungsi program, yaitu nilai variabel auth_flag akan bernilai 1 jika password yang dimasukkan merupakan salah satu password yang diizinkan. Lalu, berdasarkan hasil pada file gdb_output_8, didapat bahwa nilai auth_flag awal adalah nol dan setelah perintah strcpy() dieksekusi tetap bernilai nol. Hal tersebut juga sesuai dengan fungsi program, yaitu nilai variabel auth_flag akan tetap bernilai 0 jika password yang dimasukkan bukan merupakan salah satu password yang diizinkan. Walaupun begitu, hasil yang didapat akan berbeda jika user memasukan password dengan panjang melebihi batas nilai buffer penampung nilai password, yaitu lebih dari 16 karakter, yang kemudian akan menyebabkan terjadinya buffer overflow.

Analisis: Variabel pass_buff

Berdasarkan source code login.c (lihat Lampiran), buffer overflow rentan terjadi pada program3 tersebut. Hal ini terjadi karena variabel pass_buff merupakan array statik sehingga rentan terhadap buffer overflow jika diberi nilai masukan lebih dari 16 karakter, lalu alamat pass_buff (0x7fffffffdce0) yang berada di sebelum alamat auth_flag (0x7fffffffdcfc) sehingga memungkinkan nilai auth_flag tertimpa oleh nilai yang seharusnya berada di alamat pass_buff. Oleh karena itu, program memungkinkan memberikan keluaran yang salah. Misalnya, program seharusnya memberikan pesan gagal login, namun memberikan pesan berhasil login.

Pengujian Buffer Overflow

Nilai Masukan Password

Untuk menguji proses terjadinya buffer overflow, maka dilakukan percobaan dengan memasukan password dengan panjang lebih dari 16 karakter. Pada percobaan ini, masukan password yang dipakai adalah sebagai berikut.

  • pass_alt_12345678 (17 karakter)
  • pass_alt_123456789 (18 karakter)
  • pass_alt_1234567890 (19 karakter)
  • pass_alt_12345678901234567890 (29 karakter)
  • pass_alt_1234567890123456789012345 (34 karakter)
  • pass_alt_123456789012345678901234567890 (39 karakter)

File Output

Hasil dari percobaan tersebut dapat dilihat pada file test_output (lihat Lampiran) untuk melihat tampilan keluaran yang diberikan oleh program. Berikut ini adalah potongan keluaran yang ada pada file test_output.

Password input = pass_alt_12345678. Login Failed!

Password input = pass_alt_123456789. Login Failed!

Password input = pass_alt_1234567890. Login Failed!

Password input = pass_alt_12345678901234567890. Login Success!

Hasil Debugging

Berdasarkan hasil di atas, didapat bahwa tidak ada keluaran untuk nilai masukan dengan 34 karakter dan 39 karakter. Alasan terjadinya hal tersebut akan dijelaskan setelah pembahasan tentang hasil debugging pada percobaan kasus buffer overflow. Hasil debugging tersebut dapat dilihat pada file-file berikut (lihat Lampiran).

  • gdb_output_buffover1 (input 17 karakter)

  • gdb_output_buffover2 (input 18 karakter)

  • gdb_output_buffover3 (input 19 karakter)

  • gdb_output_buffover4 (input 29 karakter)

  • gdb_output_buffover5 (input 34 karakter)

  • gdb_output_buffover6 (input 39 karakter)

Analisis: auth_flag dan pass_buff

Berdasarkan hasil debugging di atas, didapat bahwa percobaan untuk password dengan jumlah karakter 17, 18, dan 19 memberikan keluaran bahwa login gagal dilakukan. Hal tersebut terjadi karena alamat memori yang menyimpan variable auth_flag masih bernilai nol, tidak tertimpa dengan isi dari alamat memori untuk pass_buff.

Berdasakan hasil keluaran proses debugging, didapat bahwa selisih antara alamat memori untuk auth_flag dan pass_buff adalah 0x1c atau 28 bit. Oleh karena itu, nilai pada auth_flag tidak akan berubah untuk masukan password dengan panjang sampai dengan 28 bit walaupun panjang buffer yang dideklarasikan pada program adalah 16 karakter.

Nilai auth_flag Tidak Nol

Program mulai memberikan keluaran bahwa login berhasil dilakukan ketika masukan password memiliki panjang lebih dari atau sama dengan 29 karakter. Proses login berhasil tersebut bukan disebabkan bahwa password tersebut diizinkan, melainkan karena nilai pada auth_flag tidak lagi nol. Nilai auth_flag tidak nol karena nilai pada alamat memori yang dialokasikan untuk variabel auth_flag (0x7fffffffdcd0) telah tertimpa oleh nilai pada memori yang dialokasikan untuk variabel pass_buff (0x7fffffffdcec). Dalam hal ini, nilai pada alamat 0x7fffffffdcec yang seharusnya bernilai 0x00 atau 0 berubah menjadi 0x30 atau 48. Oleh karena itu, program akan selalu memberikan keluaran berupa login berhasil untuk masukan password dengan panjang karakter lebih dari atau sama dengan 29 karakter sampai dengan 32 karakter.

Program akan memberikan keluaran yang berbeda ketika diberi masukan password dengan panjang 34 karakter atau 39 karakter. Segmentation fault [4]⁠ merupakan suatu kondisi ketika program mengakses memori yang bukan haknya atau tidak dialokasikan untuk program tersebut. Biasanya hal tersebut terjadi ketika:

  • menggunakan pointer untuk sesuatu yang tidak dialokasikan (deallocated)

  • menggunakan pointer null

  • menggunakan pointer yang tidak diinisialiasi

  • buffer overflow

Panjang Password 39 Karakter

Berbeda ketika diberi masukan password dengan panjang 39 karakter, program memberikan pesan Bus error (core dumped). Bus error [4]⁠ merupakan suatu kondisi ketika prosesor bahkan tidak dapat mencoba mengakses memori yang diminta. Biasanya, hal tersebut terjadi pada penggunaan instruksi proses dengan alamat yang tidak memenuhi persyaratan.

Jika melihat hasil debugging, didapat bahwa nilai memori yang dialokasikan untuk variabel auth_flag (0x7fffffffdcdc) adalah 0x30 namun bernilai 858927408 (seharusnya 48). Ketika diberi masukan password dengan panjang 34 karakter, program tidak selesai eksekusi dan memberikan pesan Segmentation fault (core dumped). Namun, jika melihat hasil debugging, didapat bahwa nilai memori yang dialokasikan untuk variabel auth_flag (0x7fffffffdcdc) sama dengan sebelumnya, yaitu 0x30 namun bernilai 858927408 (seharusnya 48).

Daftar Pustaka

[1] Tutorials Point, “C library function – strcmp().” [Online]. Available: https://www.tutorialspoint.com/c_standard_library/c_function_strcmp.htm. [Accessed: 14-Mar-2017].

[2] Hacking Tutorials, “Buffer overflow explained: The basics.” [Online]. Available: http://www.hackingtutorials.org/exploit-tutorials/buffer-overflow-explained-basics/. [Accessed: 14-Mar-2017].

[3] OWASP, “Buffer Overflow Attack,” 2004. [Online]. Available: https://www.owasp.org/index.php/Buffer_overflow_attack. [Accessed: 14-Mar-2017].

[4] Stack Overflow Community, “What is a bus error?,” 2008. [Online]. Available: http://stackoverflow.com/questions/212466/what-is-a-bus-error. [Accessed: 14-Mar-2017].


Footnote

1 Dilakukan dengan membandingkan nilai pada variabel pass_buff dengan password yang diizinkan. Nilai pada pass_buff didapat dari variabel pass yang merupakan masukan dari user. Perbandingan tersebut menggunakan strcmp(const char *str1, const char *str2) yang menghasilkan nilai nol apabila nilai string yang ditunjuk oleh str1 sama dengan nilai string yang ditunjuk oleh str2, lalu menghasilkan nilai selain nol apabila nilai string yang ditunjuk oleh str1 berbeda dengan string yang ditunjuk oleh str2. [1]⁠

2 Beriisi kumpulan perintah untuk melakukan percobaan dengan berbagai kemungkinan masukan. File test.sh dibuat dengan menjalankan program dengan source code seperti pada file test_generator.c (lihat Lampiran).

3 Progam yang merupakan hasil compile dari source code login.c.

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

one × 1 =