Dalam tulisan kali ini kita akan 
membahas tentang side channel attack khususnya timing attack. Kita tentu
 sering mendengar kata pepatah bahwa ‘Time is money”, ternyata selain 
dianggap uang, waktu juga bisa dijadikan senjata maut untuk memecahkan 
kode, kriptografi atau mendapatkan informasi rahasia lainnya.
Side Channel Attack
Timing attack adalah bagian dari 
keluarga besar side channel attack. Side channel attack adalah serangan 
yang memanfaatkan kebocoran informasi yang ditimbulkan karena aktivitas 
yang dilakukan mesin atau program. Seperti halnya di dunia fisik, setiap
 aktivitas yang dilakukan program sebenarnya menimbulkan “efek samping” 
atau jejak yang bisa diamati. Seperti menyelesaikan puzzle, dengan 
mengumpulkan kepingan-kepingan informasi yang bocor ini kita bisa 
menyelesaikan puzzle.
Kebocoran informasi yang bisa dimanfaatkan untuk side channel attack antara lain:
- Informasi waktu respons
- Konsumsi listrik
- Suara
- Radiasi elektromagnet
Sebagai ilustrasi coba bayangkan, bagaimana caranya mengetahui apakah Pentagon sedang merencanakan suatu operasi besar ?

Mungkin ada yang menjawab, kita harus 
menyelundupkan mata-mata ke sana. Cara itu memang bisa dilakukan, tapi 
mengingat Pentagon penjagaannya super ketat, cara itu bisa dibilang 
mission impossible, sangat sulit, mahal dan beresiko tinggi. Cara lain 
yang bisa dilakukan dengan mudah dan murah adalah dengan Pizza!
Lho kok bisa, apa hubungannya Pentagon 
dan Pizza ? Ternyata penjualan pizza Domino berhubungan dengan aktivitas
 yang dilakukan pegawai Pentagon. Ketika Pentagon sedang merencanakan 
atau melakukan sesuatu yang besar, maka akan terjadi aktivitas tinggi. 
Ketika aktivitas tinggi, banyak pegawai yang memesan Pizza sehingga 
penjualan pizza Domino akan melonjak.
Jadi ternyata informasi yang tampaknya 
sepele, penjualan pizza, bisa menjadi indikator yang cukup akurat untuk 
mengetahui apakah Pentagon sedang merencakan operasi besar. Mengenai 
indikator pizza ini pernah ditulis di washingtonpost.com tahun 1998 lalu.
Lie to Me
Saya termasuk penggemar serial TV “Lie 
to Me” yang menceritakan tentang seorang bernama Dr. Lightman yang 
memiliki kemampuan khusus untuk mendekteksi perasaan seseorang hanya 
dengan mengamati body language seseorang ketika menjawab suatu 
pertanyaan. Salah satu keahliannya adalah dia bisa menjadi “human lie 
detector” artinya dia bisa mengetahui apakah seseorang berbohong atau 
jujur.
Ekspresi di wajah menunjukkan isi hati 
seseorang, apakah dia sedang sedih, gembira, marah atau berbohong. 
Ekspresi ini akan muncul secara alami jadi sulit untuk ditutup-tutupi 
atau dibuat-buat, kecuali mungkin orang yang sudah sangat terlatih atau 
mungkin seorang psikopat.
Bisa dikatakan ekspresi di wajah ini 
adalah bentuk kebocoran informasi yang bila dibaca oleh orang yang ahli 
bisa membocorkan informasi isi hati seseorang, jadi serangan dengan 
membaca ekspresi wajah ini juga salah satu bentuk side channel attack.
Timing Attack
Kalau kita cari-cari di internet, banyak sumber yang menyebutkan indikator yang bisa dipakai sebagai lie indicator.
seorang yang berbohong membutuhkan waktu processing lebih lama dari pada kalau dia sedang jujur
Ketika seseorang berbohong dia akan 
cenderung mengulur-ngulur waktu atau menunda waktu karena dia butuh 
waktu lebih banyak untuk berpikir. Kata-kata atau gerak gerik yang 
mengindikasikan bahwa dia sedang mengulur waktu karena butuh waktu 
processing lebih lama antara lain (sumber) :
- repeat the question
- adjust their clothing
- start by speaking slowly, until confident
- start with ‘well’, ‘actually’ and other words that delay
Cara mendeteksi kebohongan dengan 
melihat waktu respons yang dibutuhkan untuk menjawab pertanyaan adalah 
salah satu bentuk side channel attack atau lebih khusus lagi timing 
attack.
Timing attack ini adalah serangan yang sulit untuk dicegah karena setiap
 operasi di komputer membutuhkan waktu untuk mengekesekusinya. Secepat 
apapun operasi komputer dilakukan tetap saja ada waktu yang terpakai 
walaupun hanya sekian nanosecond. Waktu eksekusi suatu program bisa 
berbeda bila input yang diberikan berbeda. Dengan pengukuran yang akurat
 dari waktu untuk mengerjakan suatu operasi, seorang penyerang bisa 
membaca dan menebak informasi rahasia
String Matching
Programmer ketika membuat program 
umumnya menggunakan algoritma yang seefisien dan secepat mungkin waktu 
eksekusinya, ini sudah menjadi insting dasar seorang programmer. Namun 
yang jadi masalah adalah insting dasar untuk mempersingkat waktu dalam 
tempo sesingkat-singkatnya ini justru menjadi kelemahan yang bisa 
dieksploitasi attacker.
Pseudo code untuk mengetahui apakah dua string sama atau tidak biasanya seperti ini:
Perhatikan pseudo-code di atas yang 
pertama dilakukan adalah memeriksa apakah panjang string A dan B sama? 
Bila berbeda, fungsi langsung berhenti di situ dengan nilai false. Hal 
ini terlihat sangat logis, bila panjangnya saja sudah berbeda, untuk apa
 lagi harus memeriksa isinya.
Bila panjang A dan B sama, maka 
dilakukan pengecekan apakah byte pertama isinya sama? Bila byte pertama 
sama, fungsi akan berlanjut untuk memeriksa byte kedua, ketiga, keempat 
dan seterusnya. Namun bila byte pertama isinya berbeda, fungsi juga 
berhenti disini dengan nilai false. Ini juga sangat sesuai dengan 
insting programmer, bila byte pertama saja sudah berbeda, untuk apa 
memeriksa byte kedua, ketiga dan seterusnya.
Lalu dimana sebenarnya masalahnya 
pseudo-code di atas? Bukankah ini sangat logis dan sesuai dengan insting
 dasar programmer, menyelesaikan masalah tanpa masalah dan dalam tempo 
yang sesingkat-singkatnya?
Kebocoran Informasi Waktu
Diagram di bawah ini menunjukkan 
aktivitas yang dilakukan server untuk memeriksa apakah password yang 
dikirim client sama dengan password yang tersimpan di server. Setiap 
aktivitas yang dilakukan server tentu akan memakan waktu yang dalam 
gambar di bawah ini dilambangkan dengan t0, t1, t2, t3 dan seterusnya.
Perhatikan pada t0, attacker mengirimkan
 password. Server akan memeriksa apakah panjang password yang dikirim 
client sama dengan panjang password yang tersimpan.
- Bila panjang tidak sama, server akan memberi respons pada waktu t1
- Bila panjang sama, tapi byte pertama tidak sama, server akan memberi respons pada waktu t2
- Bila panjang dan byte pertama sama, tapi byte kedua tidak sama, server akan memberi respons pada waktu t3
- Panjang password di server
- Posisi byte yang salah
Sebenarnya timing attack ada banyak 
bentuk dan variasinya, tidak hanya string matching saja. Pada dasarnya 
timing attack bisa dilakukan pada aplikasi yang membocorkan informasi 
pada clientnya dalam bentuk perbedaan waktu respons.
Sebagai contoh, potongan pseudo-code di 
bawah ini menunjukkan logika bahwa bila secret key adalah bilangan 
ganjil maka program akan memanggil fungsi doA() yang diketahui 
menghabiskan waktu 10 ms, sedangkan bila secret key adalah bilangan 
genap, maka program akan memanggil fungsi doB() yang lebih lama 
dibandingkan doA().
Dengan cara mengirimkan informasi ke 
server dan mengamati waktu responsnya, apakah 10 ms atau 15 ms, seorang 
attacker bisa mengetahui bahwa secretkey yang dipakai adalah bilangan 
ganjil atau genap.

Contoh lain adalah potongan pseudo-code 
di bawah ini. Ceritanya ini adalah potongan kode yang menangani proses 
transfer ke suatu rekening tujuan. Bila potongan kodenya seperti ini, 
maka seseorang yang mengirimkan uang ke rekening tujuan bisa mengetahui 
saldo rekening tujuan dengan cara mengamati waktu transfer.
Bila ketika transfer ke rekening XXX 
waktu yang dibutuhkan adalah 1 ms, maka isi rekening XXX diyakini di 
bawah 100 ribu. Bila ketika transfer ke rekening XXX waktu yang 
dibutuhkan adalah 5 ms, maka isi rekening XXX diyakini antara 100 ribu 
sampai 1 juta rupiah. Namun bila waktu yang dibutuhkan untuk transfer 
adalah 20 ms, maka isi rekening tersebut diyakini berisi lebih dari  
satu juta.

Itu adalah beberapa contoh bentuk-bentuk timing attack. Ada masih banyak lagi bentuk yang lain, tapi dalam tulisan ini saya akan fokuskan pembahasan pada timing attack pada string matching untuk mendapatkan secret key.
Ada yang bisa memberi contoh lain timing
 attack atau side channel attack di dunia nyata ? Mungkin waktu yang 
dibutuhkan KPK untuk menetapkan seseorang menjadi tersangka bisa 
dijadikan suatu indikator, lonjakan jumlah nasi box yang dikirim ke 
gedung KPK mungkin menandakan akan ada tersangka baru atau akan ada 
operasi tangkap tangan baru.
Contoh KasusSebagai ilustrasi saya akan memberi contoh kasus yang bisa menunjukkan bagaimana timing attack bisa dilakukan untuk mencuri kunci rahasia. Berikut adalah contoh source code aplikasi (kita sebut sebagai guessme) yang vulnerable terhadap timing attack.

Aplikasi guessme tersebut membaca file 
secretkey.txt yang berisi kunci rahasia, kemudian membandingkan dengan 
input dari user (argv). Bila input argument dari user sama dengan isi 
kunci dalam file secretkey.txt, maka program akan menampilkan ‘CORRECT’,
 namun bila salah program akan langsung keluar tanpa pesan apapun. 
Program di atas vulnerable karena ketika melakukan perbandingan dua 
string, program akan berhenti ketika panjang tidak sama atau ketika 
karakter pada posisi tertentu tidak sama.
Karena aplikasi tersebut membutuhkan 
file secretkey.txt, kita harus membuat file secretkey.txt dulu. Saya 
membuat script bash kecil untuk men-generate teks random dengan panjang 
4-9. Script bash makerandom.sh ini digunakan untuk men-generate kunci 
rahasia secara random. Dalam skenario ini, sebagai proof of concept, 
saya sendiri tidak membaca isi file secretkey.txt dan kita harus 
mengetahui isinya dengan timing attack.

Setelah program dicompile, berikut 
adalah apa yang terjadi ketika kita menjalankan program tersebut tapi 
tidak tahu kunci rahasianya. Setiap kali kita memasukkan kunci yang 
salah, program akan langsung keluar tanpa berkomentar apa-apa.

Mengukur Waktu Eksekusi
Cara untuk mengukur waktu eksekusi 
adalah dengan mencatat waktu sebelum dan sesudah eksekusi kemudian 
menghitung perbedaan dua waktu tersebut. Agar pengukurannya akurat, kita
 membutuhkan fungsi yang bisa mendapatkan waktu dengan akurasi sampai 
nanosecond. Saya menggunakan fungsi clock_gettime() di Linux untuk 
mendapatkan waktu dengan akurasi sampai nanosecond.
Berikut adalah contoh program yang melakukan pengukuran waktu eksekusi. Perhatikan apa yang dilakukan program ini:
- Mengambil waktu sebelum eksekusi dengan clock_gettime
- Mengeksekusi program yang akan diukur waktu (dalam contoh ini: guessme) di child process
- Parent process menunggu dengan wait() sampai child process selesai menjalankan guessme
- Setelah child selesai mengeksekusi guessme, parent mengambil waktu sekarang dengan clock_gettime
- Menghitung selisih waktu dalam nanosecond antara sesudah dan sebelum eksekusi
Bila source di atas dicompile (jangan 
lupa tambahkan -lrt di gcc) dan dijalankan, maka hasilnya seperti gambar
 di bawah ini. Output dari program ini adalah input string dan waktu 
eksekusi dalam nanosecond.
Ternyata setelah dijalankan waktu 
eksekusi guessme berbeda-beda dengan rentang yang lebar, terkadang 
rendah terkadang tinggi atau bahkan tinggi sekali. Mari kita coba 
jalankan program timingattack ini sebanyak 5.000 kali lalu kita plot 
hasilnya pada chart.
Wow hasilnya ternyata cukup berantakan, 
ada banyak noise dengan nilai yang sangat tinggi atau sangat rendah. 
Sepintas kalau dilihat logika timing attack itu sederhana, kita hanya 
mengirim input ke server kemudian mengamati apakah waktu respons dari 
server adalah t1, t2 atau t3 dan seterusnya. Namun sebenarnya mengukur 
waktu respons server tidak sesederhana itu, waktu dari respons tidak 
pasti dan berubah-ubah, tergantung dari banyak faktor, antara lain load 
CPU, bandwidth jaringan dan faktor lain yang kita sebut sebagai 
noise/jitter.
Karena adanya noise/jitter itu maka kita
 tidak bisa mengukur hanya satu kali, kita harus melakukan banyak 
pengukuran dan mengambil rata-ratanya. Sebelum mengambil rata-ratanya 
akan lebih baik lagi kalau kita menyaring data agar data dengan nilai 
yang sangat tinggi atau sangat rendah dihilangkan sehingga lebih 
mencerminkan waktu eksekusi yang sebenarnya.
Saya menggunakan pendekatan sederhana 
untuk memfilter noise, semua data hasil sekian banyak pengukuran 
diurutkan dulu secara ascending, kemudian saya membuang 15% data 
tertinggi dan 15% data terendah sehingga hanya menyisakan 70% data di 
tengah yang tidak terlalu tinggi dan tidak terlalu rendah. Data yang 
telah difilter inilah yang kemudian akan diambil reratanya.
Berikut adalah source code program yang 
melakukan pengukuran waktu eksekusi sebanyak 10.000 kali, memfilter 
datanya kemudian mengeluarkan rata-rata waktu eksekusi.
 Source code di atas mirip dengan yang sebelumnya hanya saja ada 
penambahan kode di bawahnya untuk melakukan sorting dengan QuickSort, 
kemudian 15% data tertinggi dan terendah dibuang kemudian dihitung 
rata-ratanya.Mencari Panjang Kunci dengan Timing Attack
Pertama yang harus kita lakukan adalah 
mencari tahu panjang kunci dari waktu respons server. Bila waktu 
response dari server adalah t1, maka kemungkinan besar panjang password 
yang kita kirim salah, dan kita harus mencoba lagi dengan password yang 
berbeda panjangnya, sampai akhirnya kita mendapatkan waktu respons t2 
yang berarti panjang password benar, tapi byte pertama salah.
Jadi cara mencari panjang kunci adalah 
dengan brute force (trial/error), dimulai dengan password yang 
panjangnya satu, bila salah, coba dengan password yang panjangnya dua, 
tiga, empat dan seterusnya.
Berikut adalah script bash yang digunakan untuk mencoba password dengan panjang 4-9.
Dan berikut adalah hasil eksekusi script bash di atas.

Bila data di atas kita plot dalam chart 
maka akan terlihat jelas ada perbedaan waktu ketika kita mengirim guess 
dengan panjang 7 karakter. Ketika menerima input yang panjangnya 7, 
waktu responsnya sedikit lebih lama dibandingkan kalau panjang input 
bukan 7. Berdasarkan hasil pengukuran ini, kita cukup yakin bahwa 
panjang kunci adalah 7 karakter.

Mencari Karakter ke-1
Setelah mengetahui bahwa panjang kunci 
adalah 7 karakter, selanjutnya kita harus mulai mencari isinya dimulai 
dari byte pertama. Cara mencari tahu isi byte pertama adalah dengan 
mengirimkan input sepanjang 7 karakter “a######”, “b######”, “c######” 
sampai dengan “z######” dan mengamati waktu respons dari setiap input 
tersebut. Dari semua input string tersebut, input string yang membuat 
waktu respons relatif lebih lama dibanding yang lain adalah tersangka 
utama isi byte pertama.
Kita membutuhkan satu script lagi untuk 
melakukan brute force dari a sampai z. Script brutetime.sh di atas 
membutuhkan  argument berupa prefix (kecuali byte pertama tidak perlu) 
yang akan diconcat dengan byte yang dicoba dari a-z dan diakhiri dengan 
postfix berupa deretan karakter ‘#’. Berikut adalah output dari script 
brutetime.sh di atas.

Data di atas bila diplot dalam chart akan terlihat seperti gambar di bawah ini.

Dari grafik di atas terlihat bahwa 
ketika kita mencoba guess dengan string ‘z######’ waktu responsenya 
lebih tinggi daripada yang lainnya sehingga kita bisa yakin bahwa 
karakter pertama adalah ‘z’.
Mencari karakter ke-2
Setelah kita yakin bahwa karakter 
pertama adalah ‘z’ selanjutnya kita harus mencari karakter ke-2. Caranya
 adalah dengan mengirimkan input string sepanjang 7 karakter: ‘za#####’,
 ‘zb#####’, ‘zc#####’ sampai ‘zz#####’ kemudia mengamati waktu respons 
dari setiap input tersebut. Input string yang membuat waktu responsnya 
relatif lebih lama dibanding yang lain diduga adalah isi karakter ke-2.

Chart di bawah ini menunjukkan bahwa 
waktu respons dari input string ‘zf#####’ relatif lebih tinggi dibanding
 yang lain, sehingga kita bisa menduga dengan keyakinan tinggi bahwa 
huruf kedua adalah ‘f’.

Mencari karakter ke-3
Kita lanjutkan dengan cara yang sama untuk mencari karakter sesudah ‘zf’.

Dari hasil chart di bawah ini terlihat 
bahwa input string ‘zfa####’ mendapatkan waktu respons yang relatif 
lebih lama dibanding yang lain sehingga kita yakin bahwa karakter ke-3 
adalah huruf ‘a’.

Mencari karakter ke-4
Mari kita mencari tahu karakter ke-4 
sesudah ‘zfa’. Gambar di bawah ini adalah output dari script 
brutetime.sh dengan argument zfa (3 karater yang sudah diketahui).

Pada chart di bawah ini ada satu titik 
data outlier yang terpencil, berbeda sendiri dari kelompoknya, data ini 
bisa diabaikan dan dianggap sebagai noise. Waktu respons untuk input 
string ‘zfam###’ terlihat konsisten lebih tinggi dibanding yang lain 
sehingga kita bisa meyakini bahwa karakter ke-4 adalah huruf ‘m’.

Mencari karakter ke-5
Ayo tinggal 3 lagi byte lagi. Gambar di 
bawah ini adalah output dari script brutetime.sh dengan argument zfam (4
 byte yang sudah diketahui).

Berikut adalah chart dari output data di atas.

Kali ini hasilnya tidak sebagus 
sebelumnya. Ada tiga kandidat yang diduga sebagai karakter ke-5, yaitu 
i, o atau x yang nilainya tidak berbeda banyak. Kalau ada kasus begini 
kita bisa uji sekali lagi untuk tiga huruf tersebut. Berikut adalah 
hasil pengujiannya.

Ternyata hasilnya kandidat zfami## 
hasilnya konsisten lebih tinggi dari 741 ribu, sedangkan zfamo## dan 
zfamx## hasilnya jauh di bawah zfami dan setara dengan huruf lainnya. 
Input string ‘zfamo’ dan ‘zfamx’ ketika ditest terlihat lebih tinggi 
dari seharusnya mungkin karena CPU load kebetulan sedang tinggi.
Mencari karakter ke-6
Satu lagi karakter yang harus kita cari 
dengan timing attack adalah karakter ke-6. Dengan cara yang sama dengan 
yang sebelumnya, berikut adalah output dari script brutetime.

Hasil di atas ketika diplot sebagai 
chart memperlihatkan bahwa input string ‘zfamip#’ mendapatkan waktu 
respons lebih tinggi di banding yang lain sehingga kita yakin bahwa 6 
karakter pertama adalah zfamip.

Mencari karakter terakhir
Mencari karakter terakhir tidak perlu 
dengan timing attack karena input string yang benar akan meresponse 
dengan ‘CORRECT’. Kita butuh script untuk melakukan brute force karakter
 terakhir mulai dari ‘a’ sampai ‘z’. Script di bawah ini adalah script 
untuk melakukan brute force karakter terakhir.
Bila script di atas dijalankan kita bisa
 mendapatkan konfirmasi positif bahwa kunci rahasia yang panjangnya 7 
karakter adalah ‘zfamipd’.






 
 




 
0 komentar:
Posting Komentar