Di dalam tutorial Form PHP sebelumnya, kita telah membahas cara melalakukan pengecekan variabel form apakah telah tersedia untuk diproses (dengan fungsi isset()), apakah variabel tersebut kosong (dengan fungsi empty()), atau apakah variabel form tersebut memiliki tipe data tertentu.
Masih berkaitan dengan proses validasi form, kali ini kita akan membahas tentang cara mencegah user untuk memasukkan kode ’khusus’ seperti JavaScript atau kode HTML kedalam form. Dalam tutorial kali ini kita akan mempelajari Cara Validasi Form untuk Mencegah Cross-site Scripting dan HTML injection.
Pengertian Cross-site Scripting dan HTML injection
Cross-site Scripting atau sering disingkat dengan XSS adalah jenis serangan ke sebuah situs dengan cara ’menyisipkan’ kode script (biasanya JavaScript) ke dalam sebuah situs. Hal ini hanya akan berhasil jika situs tersebut memiliki fitur untuk menampilkan kembali isian form ke web browser, seperti form komentar. Sedangkan HTML injection adalah istilah yang lebih spesifik kepada cara ’menyisipkan’ kode HTML kedalam sebuah situs.
Sebagai programmer web, penanganan untuk Cross-site Scripting maupun HTML injection merupakan hal yang sangat penting, terutama dalam pembuatan kode form dengan PHP. Karena form pada dasarnya dapat diinput oleh siapa saja, maka kita perlu memproteksi situs dari kode-kode berbahaya yang bisa diinput oleh user melalui form.
Contoh Cross-site Scripting dan HTML injection
Agar lebih memahami maksud dari Cross-site Scripting dan HTML injection, kita akan coba menginputnya melalui contoh halaman form.html dan proses.php dari tutorial sebelumnya.
Silahkan buka halaman form kita (form.html), lalu input kode dibawah ini kedalam dalam salah satu kotak inputan form:
<script>alert('Selamat datang di duniailkom')</script>
Dan anda akan mendapati tampilan berikut:
Tampilan tersebut adalah hasil dari kode JavaScript yang baru saja kita input melalui form. Kode tersebut dapat berjalan karena pada halaman proses.php kita langsung menampilkan data yang diinput oleh user tanpa melakukan proses filter.
Hal ini sangat berbahaya karena dengan kode JavaScript seseorang bisa melakukan ’hampir segalanya’ dengan situs kita. Tidak hanya sekedar menampilkan ucapan selamat seperti kode diatas, tetapi seseorang juga bisa merubah background, mengubah tampilan seluruh web, bahkan mengarahkan pengunjung ke situs lain (redirect).
Sebagai contoh lainnya, seseorang bisa menginput kode berikut ke dalam kotak input nama:
Dunia <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> Ilkom
Walaupun kode diatas tidak mengandung script, namun kode HTML tersebut akan membuat tampilan hasil form menjadi berantakan (bayangkan jika kita memiliki halaman yang berisi tabel berisi nama-nama seluruh user, dan kode diatas akan menghancurkan desain web yang telah dirancang).
Cara Mencegah Cross-site Scripting dan HTML injection
Salah satu cara sederhana untuk menghindari Cross-site Scripting dan HTML injection adalah dengan membuat karakter-karakter yang memiliki ’makna’ di dalam HTML dan JavaScript untuk diubah menjadi named entity, yaitu menkonversi karakter khusus seperti < menjadi <, dan karakter > menjadi >. Atau cara lainnya adalah dengan menghilangkan sama sekali seluruh tag HTML atau script dari inputan user.
Untuk kedua keperluan ini, PHP memiliki fungsi htmlspecialchars() dan fungsi strip_tags().
Fungsi htmlspecialchars() akan mengkonversi 4 karakter ’khusus’ HTML menjadi named entity sehingga tidak akan di ’proses’ oleh web browser. Keempat karakter tersebut adalah: <, >, & dan “. Keempat karakter khusus inilah yang membuat web browser akan menerjemahkan sebuah string menjadi kode HTML/JavaScript.
Sedangkan fungsi strip_tags() akan menghapus seluruh tag HTML dari inputan user.
Sebagai contoh, kita akan mengupdate halaman proses.php agar bisa mencegah seseorang menyisipkan Cross-site Scripting dan HTML injection. Berikut adalah perintah PHP pada file proses.php:
<?php if (isset($_GET['nama']) AND isset($_GET['email'])) { $nama=$_GET['nama']; $email=$_GET['email']; $nama=htmlspecialchars($nama); $email=strip_tags($email); } else { die("Maaf, anda harus mengakses halaman ini dari form.html"); } if(empty($nama)) { die("Maaf, anda harus mengisi nama"); } else { if (is_numeric($nama)) { die("Maaf, nama harus berupa huruf"); } else { echo "Nama: $nama <br /> Email: $email"; } } ?>
Di dalam kode diatas, saya hanya menambahkan fungsi htmlspecialchars() untuk variabel $nama, dan fungsi strip_tags () untuk variabel $email.
Untuk mengujinya, silahkan anda coba memasukkan kode JavaScript kita sebelumnya ke dalam kotak input nama, yakni:
<script> alert('Selamat datang di duniailkom')</script>
dan nilai berikut ke dalam kotak input email:
Dunia <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> Ilkom
Kemudian perhatikan hasil tampilan dari proses.php. Seperti yang dirancang, kali ini hasil inputan tersebut akan difilter agar lebih aman.
Jika anda melihat kode yang dihasilkan, maka akan terlihat bahwa fungsi htmlspecialchars() akan mengubah
<script> alert('Selamat datang di duniailkom')</script>
menjadi
<script> alert('Selamat datang di duniailkom')</script>
Perhatikan bahwa karakter khusus seperti < dan > telah diubah menjadi named entity.
Sedangkan untuk kotak inputan email, seluruh tag <br> telah di filter dan dihapus secara otomatis.
Validasi dengan htmlspecialchars atau strip_tags?
Pilihan apakan menggunakan fungsi htmlspecialchars() atau strip_tags() tergantung kepada alur logika form yang kita buat. Untuk isian form seperti user_name, email, dan alamat akan lebih aman jika kita tidak membolehkan tag HTML sama sekali (menggunakan fungsi strip_tags()), namun untuk kotak form komentar, mungkin kita akan membolehkan beberapa tag untuk diproses seperti tag <b>, tag <i>, atau mungkin juga tag <a>.
Fungsi strip_tags() memiliki argumen kedua yang bisa diisi dengan tag-tag HTML apa saja yang ’dibolehkan’. Jika kita membolehkan tag <a>, <b> dan tag <i> untuk variabel $komentar, maka penulisannya bisa dibuat menjadi:
$komentar=strip_tags($komentar, '<a><b><i>').
Sedangkan untuk fungsi htmlspecialchars(), jika anda ingin karakter tanda kutip ( ’ ) juga diubah menjadi named entity, kita bisa menambahkan 1 argumen optional untuk fungsi htmlspecialchars(), dengan pilihan ENT_QUOTES. Sehingga dalam contoh variabel $nama, kita bisa menulisnya menjadi:
$nama=htmlspecialchars($nama, ENT_QUOTES);
Dengan demikian, jika diinput:
<script>alert('Selamat datang di duniailkom')</script>
Akan diproses menjadi:
<script> alert('Selamat datang di duniailkom')</script>
Perhatikan bahwa karakter kutip ( ‘ ) diganti menjadi kode '.
Mengenal Fungsi htmlentities()
Selain fungsi htmlspecialchars() dan fungsi strip_tags(), dalam pembahasan mengenai validasi dan karakter entity HTML, PHP masih memiliki 1 lagi fungsi yang sering dipakai, yakni fungsi htmlentities().
Fungsi htmlentities() akan mengkonversi seluruh karakter khusus di dalam sebuah string menjadi entity, tidak hanya karakter <, >, & dan ” seperti pada fungsi htmlspecialchars(). Fungsi htmlentities() akan memproses karakter khusus lain seperti: ™, ©, ®, atau Σ menjadi named entity.
Sebagai contoh, berikut adalah hasil konversi fungsi htmlentities():
<?php $string = "Hâäållòó Dunìaîlkom™©"; echo htmlentities($string); ?>
Dan berikut adalah hasilnya:
Seperti yang terlihat bahwa fungsi htmlentities() akan mengubah seluruh karakter khusus menjadi named entity HTML.
Dalam tutorial kali ini, kita telah membahas penggunaan fungsi htmlspecialchars(), fungsi strip_tags() dan fungsi htmlentities() untuk membuat form kita lebih aman. Dalam tutorial berikutnya, kita akan membahas trik dalam menampilkan pesan kesalahan di halaman form.html, bukan di halaman proses.php seperti yang kita tampilkan pada tutorial ini dan tutorial form PHP sebelumnya.
gan bedanya penggunaan htmlspecialchars sama htmlentities apa gan ?
Fungsi htmlspecialchars hanya akan mengkonversi 4 karakter saja, yakni <, >, $ dan “. Sedangkan fungsi htmlentities akan menkonversi seluruh karakter khusus lain seperti â, ©, atau γ.
Mengenai penggunaannya, fungsi htmlspecialchars sudah mencukupi jika yang kita inginkan adalah untuk mengamankan form. Sedangkan fungsi htmlentities lebih banyak ditujukan untuk menampilkan karakter khusus HTML.
Oh ya, tutorial di atas juga sudah saya update mengenai pembahasan fungsi htmlentities :)
web saya dulu pernah di inject sama seseorang yang sirik. Saya waktu itu, menemukan bisnis briliant, saking briliantnya ada yang iri dan dengki dan menghancurkan web saya. padahal kalo bisnis itu terus berjalan sampai sekarang, saya yakin orang-orang di seluruh indonesia jadi sukses. dasar orang dengki. gak bisa ngeliat orang sukses.
Setiap usaha memang ada resikonya mas, tidak terkecuali website / bisnis online. Situs duniailkom juga pernah mengalaminya. Tetapi bisa menjadi pelajaran dan bersiap untuk kemungkinan terburuk. Salah satunya membuat backup secara reguler.
Tetap semangan mas.. :)
Mas Kalau untuk mengamankan form login yang paling bagus menggunakan filter apa saja , soalnya banyak banget filter-filter yang ada dan kalau di masukin semua takutnya ada yang error atau bernilai ganda,,
Tergantung keperluannya mas, filter yang ada dalam tutorial ini: htmlspecialchars() dan htmlentities() hanya untuk mencegah penulisan script kedalam kode program kita.
Sebelum itu, kita juga harus menvalidasi inputan tersebut, misalnya kalau untuk form login, menghapus spasi dengan fungsi trim(), mengecek apakah username tersebut valid, apakah boleh user menulis dalam huruf besar atau kecil (case sensitif), dll.
Pembahasan mengenai keamanan form memang cukup rumit dan termasuk pembahasan PHP tingkat advanced. Apalagi untuk mencegah form kita di bobol dengan brute force (kombinasi user dan password dicoba2 secara terus menerus). Oleh karena itu kebanyakan situs juga menambahkan form CAPTCHA.
Kalo saya biasanya proteksinya pake javascript, jd membatasi katakter yg akan di input, misalkan sya hanya membolehkan karakter angka, maka kalo di ketik huruf otomatis akan hilang karakter tersebut, kemudian membatasi panjang karakter yg bisa di input sesuai dengan yg kita inginkan, ,
Betul mas, proses validasi lebih pas dibuat dengan JavaScript. Tp mau g mau kita juga harus buat di sisi PHPnya, soalnya JavaScript bisa dimatikan dari web browser.
Memakai Csrf mas
terima kasih om
Pernah ngebahas cara validasi CSRF belum? Atau possible server unix? Dan cara mengamankan file upload min?
Belum ada mas… mungkin suatu saat nanti, hehe…
ebook tentang phpnya belum ada ya mas andre?, apakah sedang dibuat?
Sedang dibuat mas, saat ini sudah 80%. Mudah2an akhir bulan ini bisa selesai. Tp rencana saya dalam beberapa hari ini mau buat versi pre-rilisnya (sisa materi akan diupdate bertahap), ini lagi edit2 dulu, hehe…
semangat terus mas yah saya banyak belajar dari sini :D
Sip, terimakasih mas. Semoga tutorialnya bisa bermanfaat…
terima kasih mas tutorial-tutorialnya mudah dimengerti,dari pada dosen yang ngajarin haha (:
Hehe, siip.. semoga bisa bermanfaat…
Haha thanks ya buat dunia ilkom.
Kemarin saya lebih fokus ke alur garis besar fungsi web. sampai banyak lupa dengan artikel di atas web saya di serang dengan metode di atas hhhh… sekarang itu membuat saya fokus ke security…
Siip, sama2 gan…
Tanya dong mas. Saya mau validasi "ID", dimana hanya boleh pakai a-z, 0-9, karakter – . _ dan hanya huruf yg bs di awal "ID", misal: tria.16,pakai fungsi apa dan bgmn penulisannya? Trs apakah masih perlu ditambah dgn fungsi strip_tags? Mohon jawabannya. Trims
Kalau pengen yang seperti itu harus menggunakan "regular expression" menggunakan fungsi preg_match(). Materi tentang regular expression cukup panjang (dan lumayan rumit), silahkan dicari2 di Google karena artikelnya belum ada di duniailkom. Manual resminya bisa kesini: http://php.net/manual/en/function.preg-match.php
Atau jika berminat bisa pesan buku PHP Uncover Duniailkom, disana saya membahas 70 halaman lebih tentang validasi form, termasuk regular expression dan preg_match(). Fungsi strip_tags() sendiri g ada hubungannya dengan validasi, hanya untuk mengamankan data inputan saja.
Sepertinya masalah pengaman web harus dibuat bab khusus mas. Bisa diperlebar ke SQL injection, LFI, atau membahas isu keamanan terbaru misalkan Image Tragick.
Requestnya ditampung :)
Keamanan web menurut saya termasuk kategori advanced. Untuk bisa memahaminya mesti paham dulu prinsip dasar kenapa bisa "bobol". Misalnya SQL Injection, mau g mau mesti paham apa itu SQL. Untuk Image Tragick, mesti paham dulu apa itu ImageMagick dan bagaimana cara menggunakannya.
Terkait penanganan SQL Injection dan XSS (cross site scripting) saya bahas sekilas di buku PHP Uncover.
Tanya di luar tema boss.
Saya membuat captcha menggunakan php
Ketika di jalankan di xampp berjalan gambar captcha nya tampil.
Tapi kenapa ketika onlinekan menggunakan webhosting gambar captcha nya tidak tampil.
Apa penyebap nya. Dan apa solusinya supaya gambar captcha tampil.
# dan bagaimana cara menganmankan form imputan jika tidak menggunakan captcha.
Terimakasih.
Semoga ada solusi nya.
Biasanya captcha yang digenerate langsung dari PHP menggunakan library khusus seperti GD library.
Mungkin di hostingnya library ini tidak aktif secara default. Bisa coba diperiksa apakah kode PHPnya menggunakan library seperti ini atau tidak. Jika iya, bisa tanya ke web hosting apakah library tersebut bisa diaktifkan…
<h1><b><i> Ngetes Doang ya .. hehe </i> </b> </h1>
Hehe, di kolom komentar duniailkom tag HTML sengaja saya non-aktifkan.
Klo filter isian field yg kosong menggunakan "required" tp msh tetap bs dikosongi itu cara mengatasinya gmn ya gan?
Nanti di PHP bisa dipakai lagi fungsi trim() untuk menghapus whitespace, termasuk karakter enter atau tab yang bisa mengakali sistem required bawaan HTML5.
Siiiaap, kebetulan sudah pake fungsi trim(). Tp fungsi tersebut blm bs mengatasi masalah seperti komentar saya yg dibawah komentar ini.
Contohnya komen saya ini gan, utk field yg wajib diisi saya ketikkan kombinasi alt+0160 (pd keyboard numeric) hasilnya bs dilihat sendiri klo nama dan isi komentar bisa dikosongi, padahal harusnya wajib diisi. Mohon bisa share solusinya. Terima kasih.
Salah satu solusinya sudah saya bahas di dalam artikel ini, yakni melakukan pengecekan isian form menggunakan fungsi empty(), seperti:
if(empty($_GET['nama'])) {
die("Maaf, anda harus mengisi nama");
}
Tapi ini masih versi yang paling sederhana karena seharusnya tidak langsung dihandle oleh fungsi die(). Agar user friendly, nanti pesan error dari setiap isian form harus ditampung dan ditampilkan sekaligus.
Teknik validasi ini lumayan rumit, karena mengecek apakah isian form sudah diisi atau belum itu baru satu pemeriksaan. Proses pemeriksaan selanjutnya apakah data sudah sesuai atau belum, misalnya bagaimana jika isian umur malah diisi dengan huruf, atau bagaimana jika isian email diisi sembarangan (yang bukan alamat email).
Karena cukup kompleks, saat ini tutorial tentang validasi form baru tersedia di buku PHP Uncover duniailkom.
Sebagai tambahan, di HTML5 terdapat 1 atribut baru yang bisa dipakai untuk mewajibkan isian form diisi, yakni atribut required. Contoh penggunaannya seperti ini:
Nama Anda: <input type="text" name="nama" required>
Saya sdh coba pake fungsi empty() gan, scriptnya seperti ini:
$nama=trim($_POST['isi_nama']);
$komentar=trim($_POST['komen']);
if (!empty($nama) && !empty($komentar) {
….
}
else{
?>
alert('Nama dan komentar wajib diisi');
document.location='javascript:history.go(-1)';
<?
}
Tapi tetep aja msh bisa input nama dan komentar kosong dg kombinasi alt+0160 menggunakan keyboard numeric. Bahkan untuk field form isian nama dan komentar jg sudah saya beri atribut "required", tapi hasilnya sama saja.
Ada saran/solusi lainnya kah??
Ternyata gak bs klo pake fungsi $_POST harus $_GET,oke gan case closed…
Terima kasih.
mau nanya mas, di penjelasan diatas htmlspecialchars akan mengkonversi 4 karakter html menjadi named entity, tapi disaya kenapa tidak berubah ya, kaya saya nulis <br><br><br> di nama, fungsi <br> nya memang ga aktif sesuai penjelasan diatas, tapi tulisan <br> nya tetep muncul diform nya tidak berubah menjadi named entity
makasih sebelum nya mas
Tampilan di web memang akan tetap <br>, tapi jika di lihat di source code (klik kanan halama web – > View Page Source), nanti akan kelihatan sudah dikonversi menjadi named entity.
Bisa di test dengan kode berikut, lalu lihat source code HTMLnya:
<script>halo, saya ganteng<script>
Hallo mas, saya punya case spt ini :
http://domainsaya.com/berita/detail/D42FAda <— ini id yg saya coba decrypte
Discan lewat toools akunetik kena mas high vurnerability XSS, padahal saya udh kasih fungsi spt diatas utk penagangan GET nya
Mohon pencerhannya
Kurang tau juga nih apa masalahnya, tapi itu decrypte untuk apa ya? biasanya kalau web2 umum URL hanya berupa alamat file saja.
mass saxa mao nanya ne mengani metode metacharacter.. dlaam pembahasan mas tentang validasi mnggunakan htmlspecialchar diatas apa kah itu termasuk metode metacharacter? apa beda nya metacharacter dengan filtering..? toling jawab ya mas.. bsok saya presentasikan ini diklas..terimakasih mas..
Saya juga kurang tau tentang "metode metacharacter" yang dimaksud. Tapi kalau itu sekedar menginput karakter non-ascii, kemungkinan besar sudah bisa ditangani oleh htmlspecialchar.
saya dapat jurnal tentang metacharacter tp intinya sma mas, mengkonversi kan karakter2 tu..jadi saya rasa sma mas spesialchar itu.
<script>alert('Selamat datang di duniailkom')</script>
Mas mau tanya , kalo misalnya isi form ada Gmail , trus yang kita input asal asalan , cara memberitahu supaya ada notifikasi misalnya pemberitahuan misalnya contoh , Gmail harus mengandung " Gmail.com " gitu gimana mas ? Dan contoh isi form yang lainnya . Kalo boleh tau minta contoh kode programnya boleh mas ? , Dan itu menggunakan PHP javascript atau html ?
Trimakasih
Ini dikenal sebagai proses validasi form, dan bisa dilakukan pakai JavaScript maupun PHP. Untuk proses pemeriksaan apakah sebuah kata tertentu ada di sebuah teks yang diinput, bisa menggunakan regular expression.
Mengenai contohnya lumayan panjang karena harus paham juga konsep event dan DOM (kalau di JavaScript), serta pemrosesan form menggunakan variabel $POST (kalau di PHP).
alert(‘Selamat datang di duniailkom’)