in Cryptography

Padding Oracle Attack

oraclematrix

Apa itu padding oracle attack ? Banyak yang mengira ini pasti sejenis SQL injection atau exploit pada database Oracle. Sebenarnya padding oracle attack tidak ada hubungannya sama sekali dengan database oracle, ini adalah jenis serangan yang meng-interogasi ‘the oracle’ kemudian dengan matematika sederhana (operasi XOR) menggunakan jawaban ‘the oracle’ untuk mendekrip ciphertext.

Block Cipher vs Stream Cipher

Secara umum ada dua pendekatan bagaimana algoritma enkripsi dan dekripsi memproses data:

  • Block Cipher. Enkripsi dan dekripsi dilakukan terhadap satu blok plaintext dan ciphertext berukuran tertentu (contohnya blok berukuran 64 bit atau 128 bit). Dalam enkripsi block-cipher, bila data terdiri dari banyak blok, semua blok dienkrip/dekrip dengan kunci yang sama. Contoh algoritma enkripsi block-cipher adalah DES dan AES.

  • Stream-cipher. Data dianggap sebagai aliran bit/byte, proses enkrip dan dekrip dilakukan terhadap satu bit atau satu byte setiap waktu seperti pada aliran produksi barang melalui assembly line/conveyor belt di pabrik. Bila dalam block-cipher semua blok menggunakan kunci yang sama, dalam stream-cipher setiap bit/byte dienkrip/dekrip dengan kunci yang berbeda menggunakan aliran kunci (keystream) pseudo-random yang di-generate dari suatu kunci berukuran tertentu (40 bit-128 bit). Contoh algoritma enkripsi stream-cipher adalah RC4.

Mode Operasi Block-Cipher

Algoritma enkripsi block cipher seperti AES/DES sendiri sebenarnya hanya dirancang untuk melakukan enkripsi/dekripsi terhadap satu blok plaintext atau blok ciphretext saja. Contohnya AES, dirancang untuk mengubah plaintext berukuran 128 bit (dengan kunci berukuran 128/192/256 bit) menjadi ciphertext berukuran 128 bit juga.

Screen Shot 2013-03-12 at 7.00.58 AM

Bila hanya ada satu blok plaintext/ciphertext, maka enkripsi dan dekripsi dapat dilakukan secara langsung pada blok tersebut. Namun bila ciphertext/plaintextnya besar dan setelah dipotong-potong tersusun dalam lebih dari satu blok, tentu harus ada cara/prosedur untuk memproses blok-blok tersebut, prosedur ini disebut mode operasi. Dalam mode operasi dijelaskan bagaimana enkripsi/dekripsi dilakukan terhadap blok-blok plaintext/ciphertext tersebut, bagaimana hubungan antara satu blok dengan blok lainnya, blok manakah yang harus dienkrip/dekrip duluan dan sebagainya.

Beberapa contoh mode operasi adalah ECB dan CBC. Perlu diingat bahwa mode operasi bukanlah algoritma enkripsi, algoritma enkripsi seperti AES/DES dapat dioperasikan dalam banyak mode operasi yang berbeda seperti AES-CBC (AES dalam mode operasi CBC), AES-EBC (AES dalam mode operasi EBC) dan sebagainya. Jadi mode operasi lebih mirip protokol/prosedur untuk mengoperasikan suatu algoritma enkripsi tertentu.

Electronic Code Book (ECB) Mode

Pendekatan yang paling sederhana adalah dengan dengan meng-enkrip/dekrip setiap blok tersebut sendiri-sendiri, secara independen. Blok satu dan blok yang lain tidak ada hubungannya dan diproses sendiri-sendiri. Mode operasi yang seperti ini disebut sebagai mode ECB (electronic code book). Gambar di bawah ini memperlihatkan proses enkripsi dan dekripsi dalam mode ECB.

Screen Shot 2013-03-10 at 8.54.01 PM

Dalam gambar di atas terlihat bahwa masing-masing blok akan dienkrip/dekrip terpisah, tidak ada hubungan satu sama lain. Apa yang terjadi bila Plaintext 1 dan Plaintext 2 isinya sama ? Karena dalam algoritma block cipher semua blok menggunakan kunci yang sama, tentu saja bila plaintext blok 1 dan plaintext blok 2 identik akan menghasilkan ciphertext blok 1 dan ciphertext blok 2 yang juga identik. Ini adalah kelemahan mode ECB, bila ada blok-blok plaintext yang identik, maka ciphertextnya akan identik juga sehingga akan memperlihatkan pola yang mudah dilihat dalam ciphertext.

Screen Shot 2013-03-10 at 10.55.09 PM

Kelemahan mode EBC ini akan terlihat jelas ketika meng-enkrip dokumen/data yang memiliki banyak data yang sama seperti gambar yang biasanya memiliki banyak deretan pixel yang warnanya sama. Pada gambar di atas (gambar wikipedia), karena banyak area yang warnanya sama seperti latar putih, warna hitam dan kuning yang luas, membuat file gambar tersebut ketika dipotong-potong akan mempunyai banyak blok yang identik. Mode ECB bahkan tidak bisa menjamin confidentiality karena gambar pinguinnya masih terlihat jelas setelah dienkripsi.

Kelemahan ini adalah kelemahan mode operasi, bukan algoritma enkripsinya. Jadi sekuat apapun algoritma enkripsinya, bila dioperasikan dalam mode ECB, hasilnya juga akan mengandung kelemahan yang sama (blok plaintext identik menghasilkan blok ciphertext identik).

Cipher Block Chaining (CBC) Mode

Bila dalam mode ECB (electronic code book) setiap blok di-enkrip/dekrip sendiri-sendiri secara independen, dalam mode CBC (cipher block chaining), suatu blok dan blok lain saling terkait (chained). Saling terkait disini maksudnya adalah enkripsi dan dekripsi suatu blok data selalu melibatkan ciphertext (hasil enkripsi) blok sebelumnya.

Agar blok-blok plaintext yang identik tidak menghasilkan blok-blok ciphertext yang identik pula, mode CBC (cipher block chaining) mengaitkan (chaining) satu blok dengan blok ciphertext sebelumnya dan menggunakan random initialization vector (IV) sebagai ciphertext blok ke-0. Cara kerja mode CBC adalah seperti pada gambar di bawah ini.

Screen Shot 2013-03-08 at 9.45.53 AM

Setiap blok plaintext di-XOR dengan ciphertext hasil enkripsi blok plaintext sebelumnya baru kemudian hasil operasi XOR ini dienkrip untuk menghasilkan blok ciphertext. Begitu pula sebaliknya ketika dekripsi. Dekripsi yang dilakukan terhadap suatu blok ciphertext tidak langsung menghasilkan blok plaintext, hasil dekripsi tersebut harus di-XOR dulu dengan blok ciphertext sebelumnya untuk menghasilkan blok plaintext. Jadi enkripsi maupun dekripsi selalu melibatkan blok ciphertext sebelumnya.

Dalam bentuk notasi matematika, bisa dilihat di bawah ini:

Screen Shot 2013-03-10 at 6.54.29 PM

Variabel yang dipakai dalam formula di atas:
⊕ = Notasi untuk eXclusive OR
P = Plaintext
C = Ciphertext
IV = Initialization Vector (boleh dianggap sebagai C0)
Ek = Enkripsi dengan kunci k
Dk = Dekripsi dengan kunci k
P1 = Plaintext blok ke-1
P2 = Plaintext blok ke-2
Pn = Plaintext block ke-n
C1 = Ciphertext block ke-1
C2 = Ciphertext block ke-2
Cn = Ciphertext block ke-n

IV (Initialization Vector)

Kalau dalam setiap enkripsi/dekripsi harus melibatkan ciphertext blok sebelumnya, bagaimana dengan enkripsi/dekripsi blok pertama ? Karena posisinya adalah blok pertama, maka tentu saja tidak ada ciphertext blok ke-0 (C0).

Karena tidak ada C0, maka diperlukan suatu data yang berfungsi sebagai C0, data ini disebut dengan IV. Dengan adanya IV, enkripsi/dekripsi blok pertama yang membutuhkan ciphertext blok sebelum pertama (yang sebenarnya tidak ada), bisa menggunakan IV sebagai (seolah-olah) ciphertext blok ke-0.

Pemilihan IV tidak boleh sembarangan, IV sebisa mungkin random dan unik, jangan menggunakan IV yang predictable dan berulang (IV yag sama dipakai lagi untuk kunci yang sama). IV sebenarnya tidak perlu dirahasiakan, karena IV bisa juga dianggap sebagai bagian dari ciphertext juga (C0), tapi kalau IV dirahasiakan memang akan menyulitkan attacker mendapatkan blok pertama.

Padding

Dalam block-cipher plaintext dan ciphertext harus dipotong-potong dan disusun dalam blok-blok data berukuran sama. Sebagai contoh, DES dan Blowfist menggunakan blok berukuran 64 bit, AES menggunakan blok berukuran 128 bit. Karena data harus masuk dalam blok berukuran sama, maka dibutuhkan padding byte sebagai pengganjal untuk menggenapi data agar pas dengan ukuran blok.

Aturan mengenai padding dijelaskan dalam standar PKCS#7 dan PKCS#5 (Public Key Cryptographic Standard). Padding dilakukan dengan mengisi byte bernilai N bila dibutuhkan padding sebanyak N byte. Sebagai contoh, bila dibutuhkan padding 3 byte, maka paddingnya berisi ’03 03 03′, bila dibutuhkan padding 5 byte, maka paddingnya berisi ’05 05 05 05 05′.

Beberapa contoh padding yang benar terlihat pada gambar di bawah ini.

Screen Shot 2013-03-11 at 3.20.40 PM

Mungkin ada yang melihat keanehan pada cara padding di atas. Bila datanya sudah berisi 8 byte ‘ABCDEFGH’ kenapa masih perlu padding? Bukankah padding hanya untuk data yang tidak genap 8 byte?

Dalam standar PKCS memang sudah diatur bahwa padding harus ditambahkan pada semua data, walaupun data tersebut sudah genap seukuran blok yang diperlukan. Jadi bila blok datanya adalah 8 byte, maka berapapun ukuran datanya, padding tetap harus ditambahkan, minimal 1 byte, maksimal 8 byte.

Byte padding ‘dummy’ ini perlu ditambahkan untuk menghindarkan kebingungan. Bayangkan bila aturan paddingnya tidak menambahkan padding pada blok yang sudah seukuran blok yang diperlukan. Bila urutan byte dalam blok adalah ’41 42 43 44 45 46 47 01′ seperti gambar di atas, sistem akan bingung menentukan apakah blok data tersebut adalah ‘ABCDEFG’ dan 01 byte padding, atau memang datanya adalah ‘ABCDEFG’+byte 01 (byte 01 adalah bagian dari data, bukan padding byte).

Beberapa contoh lain padding yang valid seperti pada gambar di bawah ini. Bila dalam satu blok 8 byte isinya adalah byte 01 semua, maka byte 01 terakhir dianggap sebagai padding byte, sehingga yang dianggap sebagai data adalah 7 byte saja. Begitu pula bila dalam satu blok, 5 byte terakhirnya bernilai 02, maka dua byte terakhir dianggap sebagai padding byte, sehingga yang dianggap data adalah 6 byte pertama.

Screen Shot 2013-03-11 at 4.20.22 PM

Invalid Padding

Padding oracle attack bekerja dengan mendeteksi respons dari server yang memberitahukan client apakah padding valid atau tidak. Perlu diingat bahwa pengecekan padding dilakukan setelah dekripsi selesai dilakukan.

Mendeteksi byte padding apakah valid atau tidak, dimulai dengan melihat byte terakhir pada blok terakhir kemudian baru melihat byte-byte sebelumnya tergantung isi dari byte terakhirnya. Sebagai contoh, beberapa kondisi yang menentukan padding pada blok berukuran 8 byte (64 bit) valid atau tidak valid antara lain :

  • Bila byte terakhir bernilai diluar range 01 – 08, maka padding pasti tidak valid
  • Bila byte terakhir bernilai 01, maka padding pasti valid
  • Bila byte terakhir bernilai 02, maka padding valid bila 1 byte sebelumnya juga 02
  • Bila byte terakhir bernilai 03, maka padding valid bila 2 byte sebelumnya juga 03
  • Bila byte terakhir bernilai 04, maka padding valid bila 3 byte sebelumnya juga 04
  • Bila byte terakhir bernilai 05, maka padding valid bila 4 byte sebelumnya juga 05
  • Bila byte terakhir bernilai 06, maka padding valid bila 5 byte sebelumnya juga 06
  • Bila byte terakhir bernilai 07, maka padding valid bila 6 byte sebelumnya juga 07
  • Bila byte terakhir bernilai 08, maka padding valid bila 7 byte sebelumnya juga 08

Beberapa contoh invalid padding terlihat pada gambar di bawah ini.

Screen Shot 2013-03-11 at 7.10.32 PM

Proses Enkripsi

Mari kita lihat lebih detil proses enkripsi suatu data. Dalam contoh ini kita akan melihat proses enkripsi plaintext ‘ABCDEFGHIJKLM’ dengan kunci ‘rahasia’ menggunakan DES dalam mode CBC. Dalam contoh ini IV yang digunakan adalah deretan byte (01 02 03 04 05 06 07 08).

Screen Shot 2013-03-12 at 2.58.09 PM

Karena panjang plaintext adalah 13 byte, maka padding yang dibutuhkan adalah 3 byte agar genap menjadi 2 blok berukuran 8 byte. Setelah ditambahkan padding, blok pertama berisi ‘ABCDEFGH’, blok kedua berisi ‘IJKLM’+03+03+03.

Perlu diingat! Pada saat enkripsi, padding ditambahkan pada plaintext. Pada saat dekripsi, plaintext hasil dekripsi akan diperiksa, apakah padding bytenya valid atau tidak.

Setelah terbentuk 2 blok, proses enkripsi bisa dimulai dari plaintext blok pertama (P1) diXOR dengan IV, kemudian hasilnya di-enkrip dan menjadi ciphertext blok pertama (C1). Plaintext blok kedua (P2) diXOR dengan ciphertext blok pertama (C1), kemudian hasilnya dienkrip menjadi ciphertext blok kedua (C2). Perhatikan prosesnya byte per byte dalam gambar di bawah ini.

Screen Shot 2013-03-12 at 3.39.58 PM

Proses Dekripsi

Setelah proses enkripsi selesai, sekarang kita juga akan melihat proses dekripsinya. C1 didekrip menjadi deretan byte ’40 40 40 40 40 40 40 40′ kemudian diXOR dengan IV sehingga menghasilkan plaintext blok 1 (P1). Berikutnya blok C2 didekrip menjadi deretan byte ’64 32 1B B8 0A AA 08 86′ kemudian diXOR dengan C1 sehingga menghasilkan plaintext blok 2 (P2).

Screen Shot 2013-03-12 at 4.04.25 PM

Karena kunci dan ciphertext yang di-dekrip benar, maka proses dekripsi pada gambar di atas menghasilkan plaintext yang benar. Namun bila ciphertext yang didekrip bukan ciphertext yang benar, atau kuncinya salah, maka proses dekripsi tetap akan dilakukan sesuai prosedur, namun hasilnya bukan plaintext semula, namun data-data byte tak beraturan (garbled text).

Perlu diingat. Proses dekripsi akan tetap dilakukan meskipun ciphertext atau kuncinya salah. Ciphertext dan kunci yang benar akan didekrip menjadi plaintext yang benar, namun ciphertext atau kunci yang salah akan didekrip menjadi plaintext yang salah (deretan byte tak beraturan, garbled text)

Validasi Padding

Rangkaian proses dekripsi tidak berhenti setelah dekripsi selesai. Setelah ciphertext di-dekrip, selanjutnya akan dilakukan pemisahan byte mana yang berupa data (plaintext) dan byte mana yang berupa padding byte.

Pemisahan data dan padding hanya bisa dilakukan bila hasil dekripsinya mengandung byte padding yang valid. Ingat bahwa hasil dekripsi belum tentu menghasilkan plaintext yang benar (bila ciphertext atau kunci salah, hasilnya juga salah), jadi ada kemungkinan hasil dekripsinya adalah data byte tak beraturan yang tentu saja byte paddingnya tidak valid.

Dalam contoh gambar di atas, karena ciphertext dan kuncinya benar, maka hasil dekripsinya juga menghasilkan plaintext yang benar dengan byte padding yang valid (rangkaian byte 03 03 03). Pada contoh di atas, karena byte paddingnya adalah ’03 03 03′, maka bisa dipisahkan antara plaintext data dan byte padding dengan cara membuang 3 byte terakhir, sisanya (‘ABCDEFGHIJKLM’) adalah plaintext data. Kalau disederhanakan gambar proses dekripsi di atas menjadi (warna hijau=blok 1, warna biru=blok 2):

Screen Shot 2013-03-12 at 4.52.42 PM

Namun bagaimana bila ciphertextnya salah? Mari kita lihat contoh ciphertext yang salah, dan kita lihat apa hasilnya bila ciphertext salah tersebut didekrip. Bagaimana bila ciphertext blok pertama diubah byte terakhirnya dari 0x85 menjadi 0x83.

Screen Shot 2013-03-12 at 5.02.11 PM

Walaupun ciphertextnya sudah diubah, proses dekripsi tetap berjalan seperti biasa karena algoritma enkripsi/dekripsi bekerja mengubah kumpulan bit berukuran satu blok, apapun isi inputnya, menjadi kumpulan bit lain berukuran satu blok juga.

Perhatikan bahwa byte terakhir plaintext bernilai 05, tapi 5 byte terakhir plaintext bukan berisi 05 sesuai standar padding PKCS, artinya plaintext tersebut mengandung kesalahan padding. Jadi algoritma dekripsi tetap akan mendekrip semua input yang masuk, apapun isi inputnya, walaupun nanti hasil dekripsinya tidak valid paddingnya.

Sekarang kita coba lagi dengan ciphertext lain, kali ini byte terakhir ciphertext blok pertama diubah menjadi byte 0x86. Mari kita lihat apa yang terjadi.

Screen Shot 2013-03-12 at 5.15.34 PM

Setelah didekrip ternyata byte terakhir hasil dekripsinya bernilai 00, artinya bukan padding byte yang valid juga (padding byte yang valid bernilai 01-08 untuk blok berukuran 64 bit).

Oke, mari kita coba sekali lagi untuk ciphertext lainnya. Kali ini byte terakhir ciphertext blok pertama diubah mejadi 0x87, mari kita lihat apa yang terjadi.

Screen Shot 2013-03-12 at 5.29.21 PM

Kali ini ternyata byte terakhir hasil dekripsinya bernilai 0x01. Karena byte terakhir bernilai 01, maka bisa dipastikan paddingnya valid tanpa perlu melihat byte-byte lain sebelumnya.

Malleability

Mari kita perhatikan sekali lagi perbedaan antara ciphertext yang asli dan yang sudah dimodifikasi di bawah ini.

Screen Shot 2013-03-14 at 9.33.26 PM

Sebelum diubah, padding byte plaintextnya adalah 03-03-03 sehingga yang dianggap sebagai data adalah ‘ABCDEFGHIJKLM’. Dengan mengubah ciphertextnya satu byte saja dari 0x85 menjadi 0x87, kini byte terakhir plaintextnya bukan lagi 0x03, berubah menjadi 0x01 sehingga yang dianggap data adalah ‘ABCDEFGHIJKLM’+03+03 (kini byte 03 dianggap data, bukan bagian dari padding).

Perhatikan bahwa ternyata dengan mengubah satu byte saja dari ciphertext, bisa menghasilkan plaintext yang sama-sama valid, namun isinya berbeda. Sifat ini disebut dengan malleability.

Untuk memahami bahayanya properti malleability ini, bayangkan ada man-in-the-middle mencegat suatu ciphertext, kemudian mengubah satu byte saja dari ciphertext tersebut sebelum meneruskan ke tujuan. Setelah tiba di tujuan, ciphertext yang sudah diubah tadi ketika didekrip menghasilkan pesan yang berbeda dengan yang dimaksud dalam pesan aslinya. Hal ini tentu berbahaya bila isi pesannya berubah dari “kirim uang 1 juta ke rekening 123” berubah menjadi “kirim uang 1 juta ke rekening 124”.

The Oracle
oracleneo

Dalam padding oracle attack, yang dimaksud dengan Oracle disini tidak ada hubungannya sama sekali dengan SQL, dan database Oracle.

Oracle yang dimaksud adalah validation oracle, dimana kita bisa bertanya dan akan dijawab oleh oracle dengan jawaban ya atau tidak, benar atau salah, atau kondisi-kondisi lain. Terkadang oracle ini tidak menjawab secara verbal (blind-answer), mungkin hanya berupa perbedaan waktu (timing-attack), bila jawabannya benar, maka waktu memprosesnya lebih lama dibandingkan bila jawabannya salah.

Apapun dan bagaimanapun caranya merespons bila client bisa membedakan mana respons yang berarti valid padding, dan mana respons yang berarti invalid padding, artinya server itu telah menjadi ‘the oracle’.

Dalam web application, biasanya oracle menjawab dengan teks pada html “Error”, “Stacktrace”, “Invalid Padding Exception” atau pesan error sejenis. Cara lain menjawab adalah dengan membedakan status code HTTP, bila jawabannya salah, statusnya ‘500 Internal Server Error’, bila benar statusnya ‘200 OK’.

Cara kerja padding oracle attack adalah seperti pada gambar di bawah ini.

Screen Shot 2013-03-14 at 10.12.21 PM

Attacker melakukan brute force dengan mengirimkan banyak varian ciphertext untuk mendapatkan mana varian ciphertext yang menghasilkan valid padding. Ciphertext yang dikirim ke ‘the oracle’ dalam bentuk 2 blok, blok pertama selalu berubah-ubah ketika melakukan brute force untuk mencari varian blok ciphertext yang menghasilkan respons padding valid, sedangkan blok kedua adalah ciphertext yang ingin didekrip dan tidak berubah ketika melakukan brute force.

Perhatikan bahwa blok yang ingin didekrip diletakkan sebagai blok kedua dari ciphertext yang dikirim ke ‘the oracle’. Bila dalam ciphertext ada lebih dari satu blok ciphertext, kita bisa bebas memilih untuk mendekrip blok mana dulu, yang jelas caranya adalah dengan meletakkan blok ciphertext yang ingin didekrip sebagai blok kedua dari 2 blok ciphertext yang dikirim ke ‘the oracle’.

Lalu tepatnya bagaimana prosesnya, kenapa hanya dengan mengamati response valid atau invalid padding, kok bisa mendekrip ciphertext tanpa mengetahui kuncinya ? Agar lebih jelasnya saya akan jelaskan dengan contoh berikut.

Skenario Contoh

Suatu aplikasi web menyimpan encrypted data di client dalam parameter URL ‘crypted’. Seorang pelanggan warnet menemukan URL berikut dalam daftar history address bar komputer di warnet :

 
http://localhost:8888/kripto/thematrixoracle.php?crypted=2D7850F447A90B87123B36A038A8682F

Bila URL tersebut dibuka, ciphertext dikirim ke server dalam parameter crypted, kemudian server akan memberi respons:

  • ‘500 Internal Server Error’ bila paddingnya tidak valid.
  • ‘200 OK’ bila paddingnya valid.

Algoritma block cipher yang dipakai adalah DES berukuran 64 bit dalam mode CBC (apapun algoritma block-cipher yang dipakai tidaklah penting, padding oracle attack menyerang mode CBC apapun algoritma block-cipher yang dipakai). Dalam skenario ini source code yang digunakan di server sebagai the oracle adalah:

Screen Shot 2013-03-13 at 7.13.15 AM

Tanpa mengetahui kuncinya, hanya menggunakan jawaban dari the oracle, bagaimana cara si pelanggan warnet tadi untuk mendekrip isi parameter crypted ?

Mendapatkan byte terakhir P2

Sekarang saatnya melakukan serangan padding oracle. Kita akan mencoba mendekrip C2 satu byte per satu byte dimulai dari byte terakhir lalu maju sampai byte pertama.

Pertama yang harus dilakukan adalah memecah ciphertext yang ditemukan dari history browsing di atas, menjadi blok-blok. Karena panjang parameter crypted pada URL adalah 32 byte hexa string, artinya panjangnya adalah 16 byte, maka bisa diduga bahwa ini adalah block-cipher dengan panjang satu blok sebesar adalah 8 byte.

Berikutnya adalah memecah ciphertext menjadi blok. Setelah dipecah menjadi 2 blok, didapatkan C1 = ‘2D7850F447A90B87’ dan C2= ‘123B36A038A8682F’. Ini adalah blok C1 dan C2 yang asli ditemukan di URL dari browsing history.

Kita mulai dengan mendekrip blok terakhir dulu C2 (‘123B36A038A8682F’). Seperti yang sudah dijelaskan sebelumnya, kita harus mengirim dua blok ciphertext ke ‘the oracle’ :

  1. Blok pertama adalah blok ciphertext custom yang dibuat attacker. Blok ini byte awalnya bisa berisi apapun (random atau null byte), yang penting adalah byte terakhir yang mempengaruhi padding harus dicari dengan cara brute force untuk membuat padding menjadi valid.
  2. Blok target yang akan didekrip (‘123B36A038A8682F’). Blok ini tetap dalam setiap request karena blok inilah yang akan didekrip

Contoh dua blok cipher yang dikirim ke server adalah seperti di bawah ini.

Screen Shot 2013-03-14 at 3.49.37 PM

Dalam gambar di atas kita menggunakan deretan 7 null byte (byte 00) dan satu byte terakhir untuk brute force mulai dari 00-FF, sebagai ciphertext blok pertama. Sedangkan blok kedua tetap tidak berubah selama brute force karena ini adalah blok target yang akan didekrip.

Dua blok ciphertext pada gambar di atas digandeng kemudian dikirim ke server. Server sebagai ‘the oracle’ akan mendekrip 2 blok ciphertext tersebut dan memberikan response apakah menghasilkan plaintext dengan padding yang valid atau invalid.

Kita akan mulai mendekrip C2 dari byte terakhir, kemudian beranjak satu byte per satu byte sampai byte pertama C2. Karena yang dicari adalah byte terakhir P2 (hasil dekripsi C2), maka kita harus mencari byte terakhir ciphertext blok pertama yang membuat P2 menjadi bernilai 01 (valid padding). Situasinya tergambar seperti gambar di bawah ini.

Screen Shot 2013-03-15 at 5.49.31 AM

Dalam gambar di atas, ada satu persamaan tapi dengan dua variabel yang tidak diketahui, A XOR B = 01, seharusnya persamaan ini tidak bisa diselesaikan. Tapi untungnya kita punya ‘the oracle’, dia akan membantu kita menyelesaikan persamaan tersebut. Bagaimanakah caranya?

Kita bisa menginterogasi ‘the oracle’ dengan mencoba semua kemungkinan B mulai dari 00-FF karena antara 00-FF pasti ada B yang membuat ‘A XOR B = 01’ menjadi benar. Kita bisa bertanya pada ‘the oracle’ pertanyaan-pertanyaan berikut:

  1. Apakah A XOR 00 = 01 ?
  2. Apakah A XOR 01 = 01 ?
  3. Apakah A XOR 02 = 01 ?
  4. Apakah A XOR 03 = 01 ?
  5. Apakah A XOR 04 = 01 ?
  6. Apakah A XOR 05 = 01 ? dst

Bila ‘the oracle’ menjawab dengan ‘invalid padding’, artinya jawaban pertanyaan di atas adalah ‘tidak’ dan kita harus mengajukan pertanyaan dengan byte berikutnya sampai FF. Sebaliknya bila the oracle menjawab dengan ‘valid padding’, artinya jawaban pertanyaan di atas adalah ‘ya’ dan kita sudah berhasil menemukan B.

Brute Force Byte Terakhir

Agar lebih jelas mari kita perhatikan lebih dalam lagi proses brute force untuk mendapatkan byte terakhir C1 yang membuat byte terakhir P2 menjadi 01 sehingga paddingnya valid.

Screen Shot 2013-03-14 at 10.47.22 PM

Dalam gambar di atas terlihat client mengirim 3 varian ciphertext. Pada varian pertama, byte terakhir blok ciphertext pertama adalah 00, setelah mendekrip ciphertext ini, ‘the oracle’ pun menjawab dengan ‘invalid padding’. Ketika mengirimkan ciphertext ini, sebenarnya kita sedang menginterogasi ‘the oracle’ dengan pertanyaan ‘Apakah A XOR 00 = 01 ?’, dan ternyata jawabannya adalah ‘tidak’ sehingga kita harus mencoba dengan pertanyaan lain.

Client tidak tahu hasil dekripsi ciphertext yang dia kirim menjadi apa. Client hanya bisa menduga-duga berdasarkan response dari ‘the oracle’. Karena responsnya adalah invalid padding, client menduga dan yakin bahwa byte terakhirnya pasti bukan 01. Walaupun client tidak tahu hasil dekripsinya apa, tapi client tahu bahwa byte terakhirnya pasti bukan 01, information-leak sekecil itu saja sudah cukup untuk mendekrip ciphertext tanpa mengetahui kuncinya.

Pada varian kedua, byte terakhir blok ciphertext pertama dinaikkan menjadi 01, namun jawaban ‘the oracle’ masih sama, yaitu ‘invalid padding’ yang artinya hasil dekripsinya pasti bukan diakhiri dengan byte 01. Kali ini kita mengajukan pertanyaan ‘Apakah A XOR 01 = 01 ?’, ternyata jawabannya masih ‘tidak’.

Pada varian ketiga, byte terakhir blok ciphertext pertama dinaikkan lagi menjadi 02, namun masih juga jawaban dari ‘the oracle’ adalah ‘invalid padding’. Dalam request ini kita mengajukan pertanyaan ‘Apakah A XOR 02 = 01 ?’, sayangnya jawabannya masih juga ‘tidak’.

Client harus terus mencoba menaikkan byte terakhir blok ciphertext pertama dari 00-FF karena di antara 00-FF pasti ada satu byte yang menghasilkan status padding valid. Gambar di bawah ini lanjutan dari proses brute force di atas sampai akhirnya client menemukan bahwa byte terakhir 0x87 akan membuat status padding menjadi valid.

Screen Shot 2013-03-14 at 11.01.57 PM

Hore, setelah mencoba dari byte 00, akhirnya pada request ke 88, didapatkan bahwa byte terakhir 87 menghasilkan respons valid padding. Kali ini kita mendapat jawaban ‘Ya’ dari ‘the oracle’ untuk pertanyaan ‘Apakah A XOR 87 = 01 ?’.

Setelah dapat valid padding, so what ? Sebenarnya ada sesuatu yang cetar membahana disini, mari kita lihat lebih detil lagi byte per byte apa yang terjadi (Byte yang berisi ‘??’ artinya tidak diketahui isinya oleh client).

Screen Shot 2013-03-14 at 11.21.55 PM

Gambar di atas penting sekali untuk memahami padding oracle attack. Kita lihat kembali apa yang terjadi.

  1. Client mengirimkan 2 blok ciphertext dengan byte terakhir blok pertama bernilai 0x87
  2. Server mendekrip ciphertext dari client
  3. Setelah didekrip ternyata byte terakhirnya bernilai 01 (padding valid)
  4. Client mendeteksi response dari server bahwa padding valid
  5. Karena padding valid, client menduga (dan yakin) bahwa byte terakhir hasil dekripsi ciphertext yang dia kirim adalah 01

Okey, so far client hanya mengetahui byte 0x87 dan byte 0x01, apa yang bisa didapatkan dari itu ? Jawabannya ada pada gambar di atas, kita sebut saja byte yang berwarna hijau sebagai A.

Dari persamaan sebelumnya ‘the oracle’ sudah menjawab ‘Ya’ untuk pertanyaan: Apakah A XOR 0x87 = 0x01. Tadinya persamaan ini punya 2 variabel yang tidak diketahui, sekarang tinggal satu, artinya persamaan ini bisa diselesaikan. Lalu berapakah A ?

Jawabannya mudah, A adalah 0x87 ⊕ 0x01 = 0x86. Hore! Dengan mendeteksi response padding valid/tidak dari server, kini client bisa mengetahui A adalah 0x86, tapi tunggu dulu, A itu apa ? Jawabannya ada juga pada gambar di atas.

Pada gambar di atas jelas, A yang berwarna hijau adalah byte terakhir dari Decrypt(C2). Tapi jangan keburu senang dulu, ingat bahwa Decrypt(C2) bukan P2, masih ada satu langkah lagi untuk menjadi P2, masih harus di-XOR dulu dengan C1 untuk menghasilkan P2.

Karena byte terakhir C1 adalah 0x85 sehingga kita bisa dapatkan byte terakhir P2 adalah 0x86 XOR 0x85 = 0x03

Screen Shot 2013-03-14 at 11.27.01 PM

Mendapatkan byte ke-7 P2

Setelah berhasil mendapatkan byte terakhir P2 berikutnya adalah mendekrip 1 byte sebelum byte terakhir.

Caranya mirip dengan sebelumnya, yaitu dengan membuat agar padding hasil dekripsi ciphertext yang dikirim client, menjadi valid. Namun sedikit berbeda dengan sebelumnya, kali ini kondisi padding valid yang diinginkan adalah berakhiran dengan byte 02-02. Situasinya terlihat pada gambar di bawah ini.

Screen Shot 2013-03-15 at 6.26.50 AM

Kenapa byte terakhir blok ciphertext pertama sudah kita tetapkan berisi 0x84 ? Pada gambar di atas sudah jelas, bahwa 0x86 XOR sesuatu = 0x02, maka sesuatu itu adalah 0x84, simple math :).

Sekarang tinggal byte sebelum terakhir yang masih belum tahu harus diisi berapa agar menghasilkan 0x02 sebab ada dua tanda tanya disitu, jadi kalau ditulis persamaannya: A XOR B = 02, berapakah A dan B ?

Satu persamaan dengan dua variabel yang tidak diketahui mestinya tidak bisa diselesaikan. Cara mencari A dan B sama dengan sebelumnya, kita akan menginterogasi ‘the oracle’ untuk membantu menyelesaikan persamaan itu dalam bentuk brute force berikut:

  1. Apakah A XOR 00 = 02 ?
  2. Apakah A XOR 01 = 02 ?
  3. Apakah A XOR 02 = 02 ?
  4. Apakah A XOR 03 = 02 ?
  5. Apakah A XOR 04 = 02 ?
  6. Apakah A XOR 05 = 02 ? dst

Sekali lagi, brute force yang kita lakukan dengan mengirim banyak varian ciphertext pada dasarnya menginterogasi ‘the oracle’ untuk membantu memecahkan persamaan di atas. Jika ‘the oracle’ merespons dengan status ‘invalid padding’ artinya jawaban untuk pertanyaan di atas adalah ‘tidak’, artinya harus mencoba dengan pertanyaan berikutnya. Bila ‘the oracle’ merespons dengan status ‘valid padding’ artinya jawaban untuk pertanyaan di atas adalah ‘ya’.

Gambar di bawah ini adalah gambaran proses brute force yang dilakukan.

Screen Shot 2013-03-15 at 12.11.47 AM

Setelah dibrute force mulai dari 00, status padding valid didapatkan ketika 2 byte terakhir bernilai 0A-84. Kembali lagi ke persamaan di atas, jawaban status padding valid ini sama artinya dengan jawaban ‘ya’ untuk pertanyaan ‘Apakah A XOR 0A = 02 ?’ sehingga A bisa dihitung dengan mudah, yaitu 0A XOR 02 = 08. Situasinya kini menjadi seperti gambar di bawah ini.

Screen Shot 2013-03-15 at 12.17.17 AM

Isi byte ke-7 dari P2 sekarang sudah bisa dihitung yaitu 08 XOR 0B (0B adalah byte ke-7 C1 yang asli) = 03.

Screen Shot 2013-03-15 at 12.21.43 AM

Mendapatkan byte ke-6 P2

Kali ini client harus mengirim dua blok ciphertext sedemikian sehingga ketika didekrip di server, hasilnya adalah P2 dengan 3 byte terakhir berisi 03-03-03. Situasinya kini adalah seperti gambar di bawah ini.

Screen Shot 2013-03-15 at 6.37.56 AM

Pada gambar di atas, dua byte terakhir ciphertext blok pertama diisi dengan 0B-85 untuk memastikan ketika diXOR menghasilkan 2 byte terakhir P2 03-03. Sekarang byte ke-6 yang harus dicari dengan cara brute force, menginterogasi ‘the oracle’ untuk menyelesaikan persamaan A XOR B = 03. Proses brute force untuk mendapatkan padding yang valid terlihat pada gambar di bawah ini.

Screen Shot 2013-03-15 at 6.49.32 AM

Setelah mendapat status valid padding, artinya kita sudah mendapat jawaban ‘Ya’ untuk pertanyaan ‘Apakah A XOR A9 = 03’ sehingga bisa dihitung A adalah 0xAA. Byte ke-6 P2 yang sesungguhnya adalah 0xAA XOR 0xA9 (A9 adalah byte ke-6 C1 yang asli) = 0x03. Situasinya sekarang menjadi seperti gambar di bawah ini.

Screen Shot 2013-03-15 at 6.56.27 AM

Sejauh ini kita sudah berhasil mendapatkan 3 byte terakhir dari hasil dekripsi C2, yaitu 03-03-03.

Mendapatkan byte ke-5 P2

Mendapatkan byte ke-5 juga dilakukan dengan mengirimkan dua blok cipher sedemikian hingga ketika didekrip di server menghasilkan padding yang valid dengan byte terakhir 04-04-04-04. Situasinya seperti gambar di bawah ini.

Screen Shot 2013-03-15 at 7.08.10 AM

Tiga byte terakhir blok pertama ciphertext berisi AE-0C-82 untuk memastikan bahwa ketika diXOR menghasilkan 3 byte terakhir P2 04-04-04, menginterogasi ‘the oracle’ untuk menyelesaikan persamaan A XOR B = 04. Proses brute force untuk mendapatkan padding yang valid terlihat pada gambar di bawah ini.

Screen Shot 2013-03-15 at 7.14.33 AM

Setelah mendapat status valid padding, artinya kita sudah mendapat jawaban ‘Ya’ untuk pertanyaan ‘Apakah A XOR 0E = 04’ sehingga kita bisa hitung A yaitu 0A. Setelah mendapatkan 0A, kita bisa hitung byte ke-5 P2 yang asli, yaitu 0A XOR 47 = 4D. Sejauh ini yang sudah kita dapatkan tergambar di bawah ini.

Screen Shot 2013-03-15 at 7.19.14 AM

Mendapatkan byte ke-4 P2

Mendapatkan byte ke-4 dilakukan dengan mengirimkan dua blok ciphertext sedemikian sehingga ketika didekrip di server menghasilkan padding yang valid dengan byte terakhir 05-05-05-05-05. Gambar di bawah ini menggambarkan situasinya.

Screen Shot 2013-03-15 at 7.27.22 AM

Dengan cara brute force yang sama dengan sebelumnya, diketahui bahwa bila byte ke-4 blok pertama ciphertext berisi 0xBD, response dari server adalah padding valid.

Screen Shot 2013-03-15 at 7.39.23 AM

Dengan mendapatkan status padding valid artinya kita mendapat jawaban ‘Ya’ dari ‘the oracle’ untuk pertanyaan ‘Apakah A XOR BD = 05’ sehingga A bisa dihitung yaitu BD XOR 05 = B8 dan byte ke-4 P2 menjadi B8 XOR F4 = 4C. Gambar di bawah ini menunjukkan situasi terkini.

Screen Shot 2013-03-15 at 7.31.27 AM

3 Lagi!

Tinggal 3 byte lagi yang belum. Mari kita lanjutkan. Mendapatkan byte ke-3 P2 dilakukan dengan mengirim 2 blok ciphertext yang membuat 6 byte terakhir P2 menjadi 06-06-06-06-06-06.

Screen Shot 2013-03-15 at 7.49.39 AM

Kita harus membrute force byte ke 3 dari C1 (‘??’ berwarna biru cyan) sampai mendapatkan response dari ‘the oracle’ bahwa padding valid. Ketika mendapatkan padding valid, client bisa yakin bahwa byte ke-3 P2 bernilai 06, sehingga 6 byte terakhir menjadi 06-06-06-06-06-06.

Screen Shot 2013-03-15 at 7.54.28 AM

Dengan mendapatkan status padding valid artinya kita mendapat jawaban ‘Ya’ dari ‘the oracle’ untuk pertanyaan ‘Apakah A XOR 1D = 06′ sehingga A bisa dihitung yaitu 1D XOR 06 = 1B dan byte ke-3 P2 menjadi 1B XOR 50 = 4B. Gambar di bawah ini menunjukkan situasi terkini.

Screen Shot 2013-03-15 at 8.29.30 AM

2 Lagi!

Tinggal 2 lagi, ayo sedikit lagi nih! Sekarang client harus mengirim dua blok ciphertext yang membuat P2 menjadi 07-07-07-07-07-07-07.

Screen Shot 2013-03-15 at 8.36.11 AM

Berikut adalah proses brute force untuk mencari byte yang menghasilkan valid padding.

Screen Shot 2013-03-15 at 8.41.54 AM

Dengan mendapatkan status padding valid artinya kita mendapat jawaban ‘Ya’ dari ‘the oracle’ untuk pertanyaan ‘Apakah A XOR 35 = 07′ sehingga A bisa dihitung yaitu 35 XOR 07 = 32 dan byte ke-3 P2 menjadi 32 XOR 78 = 4A. Gambar di bawah ini menunjukkan situasi terkini.

Screen Shot 2013-03-15 at 8.45.04 AM
Terakhir!

Sekarang tiba saatnya kita mencari byte pertama dari P2.

Screen Shot 2013-03-13 at 2.10.29 PM

Gambar berikut adalah proses brute force untuk mendapatkan valid padding.

Screen Shot 2013-03-13 at 2.20.57 PM

Dengan mendapatkan byte yang menyebabkan valid padding adalah 6C, artinya kita mendapat jawaban ‘Ya’ untuk pertanyaan ‘Apakah A XOR 6C = 08’ sehingga A bisa dihitung: 6C XOR 08 = 64. Setelah itu kita bisa menghitung byte pertama P2, yaitu 64 XOR 2D (byte pertama C1 yang asli) = 0x49.

C2 Decrypted!

Jadi kita sekarang sudah berhasil mendekrip C2 (‘123B36A038A8682F’) mejadi ‘IJKLM’+03+03+03 dimulai dari byte terakhir sampai byte pertama tanpa mengetahui kunci dan algoritma apa yang dipakai.

Screen Shot 2013-03-13 at 2.31.08 PM

Hebatnya lagi dekripsi ini dilakukan sama sekali tidak menggunakan teknik komputasi kompleks tingkat tinggi (permutasi, S-BOX tidak dibutuhkan sama sekali), hanya XOR disana XOR disini, datapun berhasil didekrip. Kok bisa begitu ? Hal ini bisa terjadi karena yang melakukan dekripsi adalah server, serverlah yang akan melakukan komputasi kompleks untuk mendekrip ciphertext, attacker di luar tinggal mengamati respons dari server sebagai ‘the oracle’.

Jadi sehebat apapun algoritma enkripsinya, bila memakai mode CBC dan memberikan respons pada client apakah padding valid atau tidak valid, akan vulnerable, walaupun algoritma enkripsinya sendiri sebenarnya tidak vulnerable. Serangan oracle padding attack ini bukan menyerang algoritma enkripsi seperti DES/AES, serangan ini menyerang mode operasi CBC.

Decrypt C1

Setelah C2 berhasil didekrip, bagaimana cara mendekrip C1 (‘2D7850F447A90B87’) ?

Sama seperti mendekrip C2, cara untuk mendekrip C1 adalah dengan membentuk dua blok ciphertext berikut:

  1. Blok custom yang dibuat attacker
  2. Blok C1 (’2D7850F447A90B87’) sebagai target yang akan didekrip

Kemudian dua blok tersebut digabung (concat) dan dikirim ke server. Selanjutnya caranya sama dengan sebelumnya. Berikut adalah gambaran situasi ketika mencari byte terakhir dari dekripsi C1. Sama seperti sebelumnya, blok pertama berisi null byte kecuali byte terakhir yang akan dibrute force, blok kedua berisi 2D-78-50-F4-47-A9-0B-87 yang akan didekrip.

Screen Shot 2013-03-15 at 9.04.37 AM

Disini kita mulai dari awal lagi, berangkat dari byte terakhir sampai byte pertama. Kita harus menginterogasi ‘the oracle’ untuk membantu menyelesaikan persamaan ‘A XOR B = 01’ berapakah A dan B ? Berikut adalah proses brute force untuk mencari byte terakhir yang membuat valid padding.

Screen Shot 2013-03-15 at 9.26.34 AM

Setelah mendapatkan status valid padding artinya kita telah mendapat jawaban ‘Ya’ dari ‘the oracle’ untuk pertanyaan ‘Apakah A XOR 41 = 01’ sehingga kita bisa menghitung A adalah 0x40.

Ingat untuk mendekrip suatu blok, kita membutuhkan blok ciphertext sebelumnya. Sebelumnya ketika kita mendekrip C2 kita meng-XOR-kan hasil Decrypt(C2) dengan C1, sekarang karena kita sedang mendekrip C1, maka kita membutuhkan ciphertext blok sebelumnya juga, yaitu C0 atau Initialization Vector (IV). Dalam contoh ini IV yang dipakai adalah deretan byte 01-02-03-04-05-06-07-08.

Byte yang sudah kita dapatkan adalah 0x40 harus kita XOR dulu dengan byte terakhir IV 0x08 untuk mendapatkan plaintext byte terakhir, yaitu 0x40 XOR 0x08 = 0x48.

Screen Shot 2013-03-15 at 9.37.52 AM

Kita telah mendapatkan byte terakhir dari hasil dekripsi C1, proses ini bisa terus dilanjutkan untuk mendapatkan byte-byte lain sebelum byte terakhir dengan cara yang sama dengan yang sebelumnya.

Write a Comment

Comment