building a secure web application

7

Click here to load reader

Upload: telkom-institute-of-management

Post on 20-Jun-2015

722 views

Category:

Education


0 download

DESCRIPTION

a guide on how to build a secure web application, an experience at IMTelkom (http://www.imtelkom.ac.id)

TRANSCRIPT

Page 1: Building a Secure Web Application

STANDAR PEMROGRAMAN

DAN DATABASE Sisfo IM Telkom

STANDAR PEMBUATAN PROGRAM APLIKASI

PHP dan MySQL DI SISFO IM TELKOM

--- sebagai acuan pembuatan program aplikasi ---

Tanggal Revisi 22 Agustus 2008

oleh

Nyoman Bogi Aditya Karna

UNIT SISTEM INFORMASI INSTITUT MANAJEMEN TELKOM

BANDUNG

2008

Page 2: Building a Secure Web Application

© Institut Manajemen Telkom http://www.imtelkom.ac.id

Prakata

Buku ini ditujukan sebagai acuan untuk memudahkan programmer Team Sisfo maupun programmer mitra dalam mengembangkan aplikasi berbasis PHP.

Diharapkan dengan adanya standar pembuatan aplikasi ini, semua program dapat dimengerti dengan lebih mudah oleh database manager dan programmer lainnya, baik programmer di database server level 1 maupun di level 2.

Aturan Dasar Aplikasi Beberapa aturan dasar dalam pembuatan setiap aplikasi di database server level 1 dan level 2 :

1. Setiap aplikasi menggunakan CSS agar jenis font dan ukuran tidak dapat diubah

di sisi client

<style type="text/css">

<!--

.title {font-family: Tahoma, Verdana; font-size: 16px;}

.p1 {font-family: Tahoma, Verdana; font-size: 12px;}

.p2 {font-family: Tahoma, Verdana; font-size: 12px;color: #FF0000;}

-->

</style>

Cara menggunakannya : <p class=title>Judul Aplikasi</p><br>

<p class=p1>menu1 | menu2</p>

Catatan : CSS harus dideklarasikan ditiap kolom tabel <table><tr>

<td><p class=p1> menu1 </p></td>

<td><p class=p1> menu2 </p></td>

<td><p class=p1> menu3 </p></td>

</tr></table>

2. Tampilan aplikasi mencakup header dan footer yang tidak berubah untuk semua

halaman (page). Ini berarti header dan footer merupakan file PHP terpisah

("header.php" dan "footer.php") yg di-include di setiap content aplikasi. Desain tampilan diserahkan sepenuhnya pada programmer dengan catatan bahwa warna tampilan bernuansa biru-putih

Judul Aplikasi menu1 | menu2 | menu3

bagian header

content aplikasi

feedback (mailto:[email protected]) © 2008 Sisfo

bagian footer

Page 3: Building a Secure Web Application

© Institut Manajemen Telkom http://www.imtelkom.ac.id

3. Tidak ada hyperlink ke SIM lainnya untuk memudahkan updating (jika suatu SIM yg lain akan dipindahkan atau dihapus), karena telah dikembangkan sistem

informasi 1-account.

4. Hyperlink ke suatu script (dalam aplikasi yg sama) menggunakan alamat relative

untuk memudahkan updating (jika SIM akan pindah URL), contoh : (misal suatu SIM ada di URL http://host/sim) <a href=http://host/sim/1.php> diganti <a href=1.php>

<a href=http://host/sim/app/1.php> diganti <a href=app/script1.php>

<a href=http://host/1.php> diganti <a href=../script1.php>

5. Setiap halaman pertama (login dan password) harus selalu menggunakan SSL

(HTTPS), jika user tidak menggunakan SSL lakukan redirection ke HTTPS dengan menggunakan script PHP berikut di awal halaman pertama if ($_SERVER['SERVER_PORT'] == '80') {

$host = $_SERVER['HTTP_HOST'];

$uri = $_SERVER['PHP_SELF'];

header("Location: https://$host$uri");

}

Dan halaman login harus selalu mengunakan 3 masukan dari user, yaitu : 1. username 2. password 3. tulisan dalam image (captcha)

6. Daftar koneksi MySQL yg digunakan (nama server, nama database, nama user,

password) disimpan dalam 1 file "koneksi.php" untuk memudahkan maintenance

dan updating (membuat account ketika MySQL diinstalasi ulang) $conn_selectonly = array (

"server" => "nama_server_yg_melakukan_query",

"db" => "nama_database",

"user_selectonly => "user_dgn_privilege_select_only",

"pass_selectonly => "pass_dgn_privilege_select_only",

"user_all => "user_dgn_all_privilege",

"pass_all => "pass_dgn_all_privilege");

7. Query ke suatu tabel di MySQL menyertakan nama database-nya, contoh :

$result=mysql_query("select * from $conn_selectonly[db].nama_table");

8. Query yang menghasilkan result lebih dari 20 row dipecah menjadi banyak

halaman dengan menggunakan fasilitas LIMIT, contoh : $result=mysql_query("select * from $conn_selectonly[db].nama_table limit

$page,20");

Page 4: Building a Secure Web Application

© Institut Manajemen Telkom http://www.imtelkom.ac.id

Aturan Untuk Security

Beberapa aturan tambahan dalam pembuatan aplikasi di database server level 2 perlu dibuat untuk meningkatkan security, mengingat aplikasi di database server

level 2 dapat diakses oleh publik : 9. Setiap parameter yang masuk ke halaman pertama (login dan password) harus

selalu di-check dengan fungsi "anti_sql_injection.php" : function check_input($str) {

$ch1=strpos($str,',');$ch2=strpos($str,"'");$ch3=strpos($str,'"');

$ch4=strpos($str,';');$ch5=strpos($str,'=');$ch6=strpos($str,'-');

$ch7=strpos($str,'%');$ch8=strpos($str,'$');$ch9=strpos($str,'<');

$ch10=strpos($str,'>');

if (($ch1===false) && ($ch2===false) && ($ch3===false) &&

($ch4===false) && ($ch5===false) && ($ch6===false) &&

($ch7===false) && ($ch8===false) && ($ch9===false) &&

($ch10===false)) {return true;} else {return false;}

}

10. Jika jumlah account (login+password) untuk mengakses aplikasi hanya sedikit (kurang dari 5), maka daftar account tersebut disimpan dalam bentuk file ("user.php"), untuk menghindari exhaustive-query yang menyebabkan koneksi ke

MySQL habis. $account = array (

"user" => "user1",

"pass" => "pass1");

if (($login==$account[user]) && ($pass==$account[pass])) {

<aplikasi>

}

Catatan 1 : jika login gagal (login/pass tidak sesuai dengan daftar account),

jangan berikan keterangan apapun untuk mengurangi kemungkinan serangan Brute Force Attack yg mencoba semua kombinasi login+password dan akan berhenti jika keterangan "login gagal" tidak didapatkan lagi.

Catatan 2 : file "koneksi.php" di no 6 tidak boleh digabungkan dengan file "user.php" karena account (login+password) untuk mengakses aplikasi harus dibedakan dengan account untuk mengakses MySQL

11. Selalu menggunakan session dalam database setelah login berhasil dengan

kemampuan untuk mengeset lifetime dari session

12. Pengecekan alamat IP dari client dilakukan untuk membatasi akses dan

mengurangi kemungkinan serangan if (substr($_SERVER['REMOTE_ADDR'],0,6)=='10.14.') {

<application>

} else {print "Sorry, this feature is available only from intranet";}

Page 5: Building a Secure Web Application

© Institut Manajemen Telkom http://www.imtelkom.ac.id

Catatan : untuk mengurangi serangan Brute Force Attack, alamat IP dari client yg

terakhir mengakses dapat disimpan di suatu file beserta kapan waktu mengaksesnya (jam:menit:detik). Jika yg mengakses saat ini memiliki alamat IP yg sama dan selisih waktunya kurang dari 1 detik, maka akses akan ditolak dan

alamat IP tsb dilaporkan ke SuperUser untuk di-block menggunakan firewall seperti script di bawah ini : <?php

$ip=$_SERVER['REMOTE_ADDR'];

$now=time();

settype($now,"integer");

$file = "./last_ip.txt";

$fp = fopen($file,"r");

$row = fgetcsv($fp,100," ");

settype($row[1],"integer");

fclose($fp);

if (($row[0]==$ip) && (($now-$row[1])<3)) {

$fp = fopen($file,"w");

fputs($fp,"$ip $now");

fclose($fp);

$fp = fopen("./block.sh","a+");

fputs($fp,"/sbin/ipfw add 100 deny ip from $ip to any\n");

fclose($fp);

} else {

$fp = fopen($file,"w");

fputs($fp,"$ip $now");

fclose($fp);

}

?>

Script di atas akan membuat file "block.sh" (di folder yg sama dengan aplikasi)

yg berisi command line firewall yg nantinya akan dieksekusi dan dihapus oleh cron : # cat /root/block_BFA.sh

/bin/chmod 700 /data/web/block.sh

/data/web/block.sh

/bin/rm /data/web/block.sh

# crontab –l | grep block_BFA.sh

*/1 * * * * /root/block_BFA.sh

Page 6: Building a Secure Web Application

© Institut Manajemen Telkom http://www.imtelkom.ac.id

Aturan Database

Beberapa aturan perlu ditambahkan untuk menjaga struktur database dan tabel yang lebih efisien dan sekaligus menjamin keamanan datanya :

1. Database Manager membuat database dan menyediakan 2 buah account untuk

mengakses database tersebut :

1 account dengan hanya privilege "select" 1 account dengan privilege "select, insert, update, delete"

2. Pembuatan dan pengubahan struktur tabel harus seijin Database Manager, untuk mempertahankan kestabilan sistem, efisiensi ruang hard disk, kecepatan pengaksesan data, dan mempermudah penggunaan tabel oleh programmer lain

3. Setiap penamaan program, database, tabel, dan account harus sesuai dengan

peruntukannya, agar mudah mengidentifikasi fungsinya jika dibaca oleh user, database manager, maupun programmer lain

4. Type column diusahakan agar NOT NULL untuk mempercepat akses, karena jika

ada column yg boleh NULL maka column tsb bisa tidak ada alokasi spasi jika

kosong (tidak ada data) 5. Menghindari penggunaan type column variable spt "varchar" untuk mempercepat

akses ke suatu record (row) karena "varchar" akan membuat panjang setiap row (record) menjadi tidak sama, sehingga untuk mencari suatu data akan menjadi lebih lama (jika mekanisme akses-nya sekuensial)

6. Selalu membuat index pada primary key untuk mempercepat akses, karena

dengan index (versi tabel yg tersorting) mekanisme pencarian tidak lagi

sekuensial (berurutan satu demi satu) 7. Membuat tabel sekecil mungkin (dari sisi jumlah field/column dan jumlah

record/row) untuk mempercepat akses, karena tabel yg berukuran kecil akan

dapat di-load seluruhnya ke memory 8. Selalu menjaga agar tabel selalu tersorting berdasarkan primary key untuk

mempercepat akses ke suatu record (row), karena jika record di suatu tabel tidak berurutan maka pencarian akan sekuensial

Catatan: rule nomor 16 s.d. 20 mengacu pada manual MySQL, bukan berdasarkan pengalaman maupun eksperimen

Page 7: Building a Secure Web Application

© Institut Manajemen Telkom http://www.imtelkom.ac.id

Contoh Format Dasar

<html>

<head><title>Judul Aplikasi</title></head>

<style>

</style>

<body>

<p class=p1>

<?php

include("anti_sql_injection.php");

include("user.php");

include("koneksi.php");

if (substr($_SERVER['REMOTE_ADDR'],9) == '10.14.203') {

if (check_input($login) && check_input($pass)) {

if ($link=mysql_connect("localhost","$user","$password") {

$result=mysql_query("select ip from $db.nilai where nim='$login'");

$data=mysql_fetch_array($result,BOTH);

print "$data[0]";

} else {print "can not connect to database, please try again later";}

} else {print "illegal character found";}

} else { print "sorry, you’re not allowed to access this application";}

?>

</body>

</html>