Beberapa waktu yang lalu saya menemukan  sebuah website dengan vulnerability SQL injection. Sengaja nama website  tersebut tidak saya publikasikan, karena artikel ini bukan tentang SQL  injection melainkan bagaimana memecahkan enkripsi.
Berbeda dengan website lainnya, website  tersebut menyimpan password dalam tabel user tidak dalam bentuk one-way  hash (contohnya MD5 atau SHA1), melainkan dalam bentuk ter-enkripsi.  Enkripsi yang dipakai juga unik karena tidak memakai algoritma enkripsi  yang sudah dikenal luas.
Dalam kasus tersebut saya ingin  melakukan privilege-escalation dari user dengan hak akses biasa menjadi  user dengan hak akses penuh. Sebagai user biasa saya bisa melakukan  SQLinjection untuk membaca username dan password dari tabel user. Dengan  teknik tersebut saya mendapatkan encrypted password dari seorang user  yang memiliki hak admin. Namun saya tidak bisa memakai password itu  untuk menjadi admin sebelum saya mengerti pesan tersembunyi dalam  chiphertext tersebut.
Analisa CiphertextSaya mencoba menggali informasi lebih  dalam lagi tentang enkripsi unik di website tersebut. Saya mulai  mengumpulkan banyak ciphertext dari user-user lainnya. Berikut beberapa  ciphertext yang saya kumpulkan:
- 804881451156416021528145
- 9436353935332546555225378546953924846491
- 11763273927622732276427712808233523172328227
Ada beberapa poin penting yang saya  dapatkan dari pengumpulan ciphertext tersebut:
- Panjang ciphertext bervariasi
Panjang  ciphertext yang bervariasi  membuat saya yakin bahwa itu bukan fungsi  hash, karena ciri khas fungsi  hash adalah panjang hash yang selalu  tetap. Panjang ciphertext yang  bervariasi kemungkinan besar tergantung  dari panjang atau pendeknya  password user tersebut. Nanti saya akan coba  konfirmasi hipotesa ini  dengan mengubah password user biasa yang saya  pakai.
- Ciphertext hanya terdiri dari angka
Ciphertext yang semua berupa angka  membuat saya curiga bahwa ini adalah kode, semacam kode ASCII namun  sudah dikalkulasi dengan formula matematis tertentu.
Chosen-Plaintext Attack
Chosen-Plaintext attack adalah salah  satu cara “code breaking” (cryptanalysis) dengan cara membandingkan dan  menganalisa contoh plaintext dan ciphertextnya. Dalam chosen plaintext  attack, code breaker memiliki kebebasan untuk menentukan plaintext yang  diiginkannya.
Untuk mendapatkan contoh plaintext dan  ciphertextnya, saya melakukan langkah berikut ini setelah login sebagai  seorang user biasa:
- Ubah Password
- Lihat ciphertext dari tabel user dengan SQLinjection
Pertama saya ubah password menjadi ‘d’,  kemudian saya lihat ciphertext untuk plaintext ‘d’. Saya ulangi langkah  itu dengan contoh plaintext yang lain berkali-kali.
Apa saja plaintext yang saya pilih?  Berikut chosen-plaintext dan ciphertextnya yang saya pilih:
| Plaintext | Ciphertext | 
|---|---|
| d | 92254325 | 
| dd | 831214121412 | 
| ddd | 6180128012807280 | 
| dddd | 15013601660186017601 | 
| abcd1234 | 433034273428242944308379538023819382 | 
Perhatikan bahwa panjang ciphertext  tergantung dari panjang plaintext.  Plaintext sepanjang 1 karakter,  ciphertext panjangnya 8 digit. Setiap penambahan satu karakter  plaintext, ciphertext bertambah 4 digit.
Saya sengaja memilih plaintext berurutan  (d,dd,ddd,dddd) untuk melihat apa ada pola yang muncul. Perhatikan pada  plaintext “dd”, ciphertextnya adalah 831214121412, terlihat pola  berulang pada angka 412 sebanyak 2x. Dalam ciphertext ini saya  menyimpulkan bahwa 412 adalah kode untuk karakter ‘d’.
Untuk plaintext “ddd”, ciphertextnya  adalah 6180128012807280, terlihat pola berulang pada angka 280 sebanyak 3  kali. Dalam ciphertext ini saya menyimpulkan bahwa 280 adalah kode  untuk karakter ‘d’.
Begitu juga pada plaintext “dddd”,  ciphertextnya adalah 15013601660186017601, dengan pola berulang pada  angka 601 sebanyak 4 kali. Dalam ciphertext ini, saya menyimpulkan bahwa  601 adalah kode untuk karakter ‘d’.
Ingat bahwa untuk setiap penambahan satu  karakter plaintext membuat ciphertext bertambah 4 digit. Ternyata 4  digit tersebut adalah satu digit apapun diikuti dengan 3 digit kode  karakter. Chosen plaintext dalam contoh sebelumnya saya pecah-pecah  menjadi kelompok 4 digit dipisahkan dengan karakter ‘#’ dan dari 4 digit  tersebut saya pecah dua menjadi 1 digit dan 3 digit dengan karakter  ‘-’.
| Plaintext | Ciphertext | Kode | 
|---|---|---|
| d | 9-225#4-325 | 325 = ‘d’ | 
| dd | 8-312#1-412#1-412 | 412 = ‘d’ | 
| ddd | 6-180#1-280#1-280#7-280 | 280 = ‘d’ | 
| dddd | 1-501#3-601#6-601#8-601#7-601 | 601 = ‘d’ | 
Oke sampai disini saya sudah mendapatkan  titik terang. Saya sudah mengetahui komposisi dan posisi tiap karakter  pada plaintext ketika dipetakan pada ciphertext. Tapi masih ada yang  belum jelas, dalam contoh tersebut kode untuk krakter ‘d’ ternyata  berbeda-beda, pada contoh pertama kodenya adalah 325, pada contoh lain  kode untuk ‘d’ adalah 412, 280 dan 601.
Kini saya harus mengetahui bagaimana  hubungan antara kode yang berurutan, untuk itu saya memilih plaintext  “abcd1234″ dengan ciphertext 433034273428242944308379538023819382. Mari  kita pecah ciphertext tersebut menjadi kelompok 4 digit seperti tabel di  atas.
4-330#3-427#3-428#2-429#4-430#8-379#5-380#2-381#9-382
Dari pengelompokan tersebut kita bisa  simpulkan bahwa:
427 = ‘a’, 428 = ‘b’, 429 = ‘c’, 430 =  ‘d’, 379 = ’1′, 380 = ’2′, 381=’3′, 382=’4′
Perhatikan bahwa kode-kode tersebut  sengaja saya pilih berurut ‘a’->’b'->’c'->’d’ dan ternyata  ciphertextnya pun ikut berurut 427->428->429->430. Begitu juga  untuk ’1′->’2′->’3′->’4′, ciphertextnya juga berurut  379->380->381->382. Saya mencurigai bahwa enkripsi ini memakai  kode ASCII karena memang kode ASCII untuk ‘abcd’ dan ’1234′  berurutan.Kode ASCII untuk  ‘a’=97,  ‘b’=98,’c'=99,’d'=100,’1′=49,’2′=50,’3′=51,’4′=52.
Terlihat ada jarak yang cukup jauh  antara kode ASCII dan kode pada ciphertext. Contohnya ‘a’ dengan ASCII  97, dalam ciphertext dikodekan dengan 427, selisihnya 427-97 adalah 330.  Begitu juga dengan ’1′ dengan ASCII 49, dalam ciphertext dikodekan  menjadi 379, dengan selisih 379-49 adalah 330. Ternyata kalau dilihat  semua kode pada ciphertext juga berjarak 330 dengan kode ASCII.  Pertanyaannya, darimana angka 330 ini muncul?
Mari kita lihat sekali lagi ciphertext  dari ‘abcd1234′ (setelah dikelompokkan 4 digit):
4-330#3-427#3-428#2-429#4-430#8-379#5-380#2-381#9-382
Adakah angka 330 dalam ciphertext  tersebut? Aha, ternyata ada! Ingat bahwa plaintext satu karakter,  ciphertextnya adalah 8 digit, padahal tiap karakter dikodekan dalam 4  digit, jadi ada kelebihan 4 digit. Ternyata pada kelompok 4 digit  pertama mengandung offset dengan kode ASCII, yaitu pada digit ke-2  hingga ke-4.
Jadi sekarang misteri enkripsi ini  terpecahkan. Mari kita coba dekrip contoh ciphertext yang saya kumpulkan  di awal:
- 804881451156416021528145
Pertama kita kelompokkan menjadi  kelompok 4 digit: 8-048#8-145#1-156#4-160#2-152#8-145. Kelompok 4 digit  pertama 8048 menunjukkan offset yaitu 048. Kelompok 4 digit kedua, 8145  menunjukkan kode karakter pertama adalah 145, dikonversi ke kode ASCII  menjadi 145-048=97. ASCII 97 ini adalah ‘a’. Jadi kita temukan karakter  pertama ‘a’. Berikutnya, 156-48=108, yaitu kode untuk ‘l’. Berikutnya,  160-48=112, yaitu kode untuk ‘p’. Berikutnya 152-48=104, yaitu kode  untuk ‘h’. Berikutnya 145, sama dengan karakter pertama, ‘a’. Jadi hasil  dekripsinya adalah ‘alpha’.
- 9436353935332546555225378546953924846491
Kita kelompokkan menjadi kelompok 4  digit: 9-436#3-539#3-533#2-546#5-552#2-537#8-546#9-539#2-484#6-491.  Karakter pertama: 539-436=103=’g’. Karakter ke-2: 533-436=97=’a’.  Karakter ke-3: 546-436=110=’n’. Karakter ke-4: 552-436=116=’t’. Karakter  ke-5: 537-436=110=’e’. Karakter ke-6 sama dengan ke-3, ‘n’. Karakter  ke-7 sama dengan karakter ke-1, ‘g’. Karakter ke-8: 484-436=48=’0′.  Karakter ke-9: 491-436=55=’7′. Jadi hasil dekripsinya adalah  ‘ganteng07′.
Pada akhirnya dengan mengetahui teknik  enkripsi yang dipakai, saya berhasil mendapatkan password seseorang  dengan hak administrator. Tidak lama kemudian GAME OVER, webshell  uploaded  
 
Kesimpulan
Pelajaran yang bisa diambil dari kasus  tersebut adalah bahwa membuat algoritma kriptografi yang kuat tidaklah  mudah, jangan pernah memakai enkripsi buatan sendiri, walaupun  algoritmanya anda rahasiakan. Selalu gunakan algoritma enkripsi terbuka  yang sudah teruji oleh para ahli.
Sedangkan untuk password, sebaiknya  jangan gunakan enkripsi, tapi gunakan one-way hash function yang kuat  seperti SHA1. Enkripsi tidak cocok dipakai untuk menyimpan password  karena ketika terjadi compromised, maka semua password yang ada di tabel  akan bisa diambil attacker dengan cara menjalankan rutin dekripsi yang  pasti tersedia di salah satu file script seperti PHP pada web tersebut.
Walaupun algoritma dekripsinya anda  rahasiakan, suatu saat ketika terjadi compromised, seorang attacker akan  bisa melakukan dekripsi dengan membaca source code php untuk men-dekrip  password. Biasanya rutin dekripsinya tidak jauh dari file php yang  terkait dengan halaman login.
 
 
Tidak ada komentar:
Posting Komentar
Setelah membaca artikel di atas.
Apa komentar anda ??