pillinetwork hesabınızla giriş yapın.

Güvenli PHP Uygulamaları Yazmak İçin Edinmeniz Gereken 7 Alışkanlık

PHP uygulamasında güvenlik uzaktan ve yerel güvenlik endişelerini içerir. PHP geliştiricilerinin her iki karakteristiği de içine alan uygulamalar geliştirebilmeleri için sahip olmaları gereken 7 alışkanlığı bu makalede listelemeye çalışacağım.

Konu güvenliğe geldiğinde, işletim sistemi ve platform güvenlik sorunlarının yanısıra kendi yazdığınız uygulamaların da güvenli olduğuna emin olmanız gerekmektedir. PHP uygulamaları yazarken aşağıdaki 7 maddeyi alışkanlık haline getirirseniz uygulamalarınızın mümkün olan en güvenli şekilde olacağına emin olabillrsiniz.

  • Girdiyi doğrulayın
  • Dosya sistemini koruyun
  • Veritabanını koruyun
  • Oturum verinizi koruyun
  • Çapraz-site betikleme açıklarına (XSS) karşı koruyun
  • Forum gönderilerini doğrulayın
  • Çapraz-site istek sahteciliğine (CSRF) karşı koruyun.

Girdiyi doğrulayın
Konu güvenliğe geldiğinde veriyi doğulamak belki de sahip olmanız gereken en önemli alışkanlıklardan biri olmalıdır. Ve konu girdiye geldiğinde ise bu çok basittir: Kullanıcılarınıza güvenmeyin. Kullanıcılarınız muhtemelen iyi insanlardır ve muhtemelen uygulamalarınızı tam istediğiniz gibi kullanacaklardır. Ancak nerede kullanıcının veri girmesine izin verilirse, orada küçük de olsa gerçekten ama gerçekten kötü verilerin girilme ihtimali de mevcuttur. Bir uygulama geliştiricisi olarak uygulamalarınızı kötü girdilere karşı korumanız gerekmektedir. Kullanıcılarınızın girdilerinin nereye gideceğini ve netip veriler girebileceğini ince eleyip sık dokumak, güçlü ve güvenli uygulamalar geliştirmenize önayak olacaktır.

Her ne kadar dosya sistemi ve veritabanı etkileşimi hakkında yazının ilerleyen kesimlerinde konuşacak olsak da, her tür doğrulamayı içine alacak genel doğrulama ipuçları bulunmaktadır:

  • Güvenilir değerler (white-listed values) kullanın
  • Sınırlı seçimleri (limited selections) daima yeniden doğrulayın
  • Bütünleşik kaçış fonksiyonları (escape functions) kullanın
  • Doğru veri tipleri için doğrulama uygulayın, numaralar gibi.

Güvenilir değerler, geçerli olan veriler iken, güvenilir olmayan değerler geçersiz verilerdir. Buradaki ayrım, doğrulama yapılırken, muhtemel değerlerin listesi geçersiz değerlerin listesinden genellikle daha küçüktür ve bunlardan bir çoğu bilinmeyen ya da beklenmeyen değerlerdir.

Doğrulama yaparken, tüm bilinmeyen değerlere karşı korunmaya çalışmaktansa, uygulamanın sadece izin verdiklerini doğrulamak ve bunları işler kılmak genellikle daha kolaydır. Örneğin bir alan içerisindeki değerleri tüm rakamlara sınırlamak için girdinin sadece numaralardan oluşup oluşmadığını kontrol etmek daha verimli olacaktır. Nümerik olmayan veriler üzerinde arama yapacak ve bulunması durumunda onları geçersiz olarak işaretleyecek rutinler yazmayın.

Dosya Sisteminizi Koruyun
Temmuz 2000'de bir web sitesi, web sunucusu üzerinde bulunan müşteri verilerini sızdırdı. Web sitesini ziyaret eden bir ziyaretçi URL'yi, bu verileri gösterecek şekilde ayarladı. Her ne kadar dosyalar hatalı bir biçimde yerleştirilmiş olsa da, bu örnek, dosya sisteminizi saldırılara karşı korumanın önemine dikkat çekiyor.

Eğer PHP uygulamanız dosyalar üzerinde herhangi birşey yaparsa ve kullanıcının giriş yapabileceği değişken bir verisi varsa, kullanıcı girdisini temizleyerek onların herhangi bir girdi ile dosya sistemi üzerinde herhangi bir şey yapamayacaklarından emin olun. Aşağıdaki kod örneği 1, isim atanmış bir imajı indiren bir PHP sitesini örneklendiriyor.

Kod Örneği 1: Dosya İndirmek

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
if ($_POST['submit'] == 'Download') {
$file = $_POST['fileName'];
header("Content-Type: application/x-octet-stream");
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename=\"" . $file . "\";" );
$fh = fopen($file, 'r');
while (! feof($fh))
{
echo(fread($fh, 1024));
}
fclose($fh);
} else {
echo("
1
2
3
4
5
6
7
8
9
<head><");
echo("title>Guard your filesystem</title></head>");
echo("<body><form id=\"myFrom\" action=\"" . $_SERVER['PHP_SELF'] .
"\" method=\"post\">");
echo("<div><input type=\"text\" name=\"fileName\" value=\"");
echo(isset($_REQUEST['fileName']) ? $_REQUEST['fileName'] : '');
echo("\" />");
echo("<input type=\"submit\" value=\"Download\" name=\"submit\" /></div>");
echo("</form></body>
");
}

Sizin de görebileceğiniz gibi Kod Örneği 1 üzerindeki görece tehlikeli olan bu betik, web sunucusunun okuma yetkisi olan her dosyayı listeleyebiliyor, bunlar arasında oturum dizininizdeki dosyalar da yer alıyor (aşağıdaki oturm verisini korumak başlıklı yazıyı okuyun) ve hatta /etc/passwd üzerindeki bazı dosyaları bile listeliyor. Bu örnek, kullanıcının örnekteki gerekçeler için veri girişi yapabileceği bir dosya adı metin kutusunu içeriyor, ancak dosya adının bir sorgu satırından (query string) oluşmaması için hiçbir neden yok.

Kullanıcı girdisi ile dosya sistemi yetkisini ayarlamak tehlikelidir, bu yüzden yapabileceğiniz en iyi şey, uygulamanızı veritabanının yanısıra gizli, oluşturulmuş dosya adları kullanacak şekilde tasarlayarak her ikisinden de kaçınmaktır. Kod örneği iki, dosya adlarını doğrulayan bir örneği içeriyor. Betik, dosya adında sadece geçerli karakterlerin kullanılıp kullanılmadığını kontrol etmek için kurallı ifadeler kullanıyor ve özellikle nokta-nokta karakterlerini kontrol ediyor: ...

Kod Örneği 2: Geçerli Dosya Adı Karakterlerini Kontrol Etmek

1
2
3
4
function isValidFileName($file) {
/* .. karakterlerine izin verme ve her "kelime" karakterine izin ver \ / */
return preg_match('/^(((?:\.)(?!\.))|\w)+$/', $file);
}

Veritabanınızı Koruyun
Nisan 2008'de bir Birleşik Devletler Eyaleti'nin Islah Bakanlığı, SQL sütun adlarının sorgu satırlarında kullanılmasının sonucunda gizli verilerin sızmasına sebep oldu. Bu sızıntı, şüpheli kullanıcıların görüntülemek istedikleri sütunları seçebilmesinin, sayfayı gönderebilmesinin ve veriyi alabilmesinin önünü açtı. Bu sızıntı, kullanıcıların kendi girdilerinin, geliştiricilerinin önceden göremediği şeyleri nasıl yaptırmayı akıl edebileceklerini örneklendirirken, SQL enjeksiyon saldırılarına karşı önlem alınmasının önemine işaret ediyor.

Kod örneği 3, bir SQL komutunu çalıştıran bir betik örneğini gösteriyor. Bu örnekte, SQL komutu benzer bir saldırıya izin verecek bir dinamik komutu içeriyor. Bu formun sahipleri liste seçimleri için sütun isimlerini limitlendirdikleri için kendilerini güvende hissedebilirler. Ancak, kod, seçimi sadece açılır kutular ile sınırlandırmanın, kullanıcının istediği herhangi bir şeyi içeren (asterisk [*] dahil) form göndermesinin önüne geçmediğini unutuyor.

Kod Örneği 3: SQL komutnu çalıştırmak

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<html>
<head>
<title>SQL Injection Example</title>
</head>
<body>
<form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>"
method="post">
<div><input type="text" name="account_number"
value="<?php echo(isset($_POST['account_number']) ?
$_POST['account_number'] : ''); ?>" />
<select name="col">
<option value="account_number">Account Number</option>
<option value="name">Name</option>
<option value="address">Address</option>
</select>
<input type="submit" value="Save" name="submit" /></div>
</form>
<?php
if ($_POST['submit'] == 'Save') {
/* do the form processing */
$link = mysql_connect('hostname', 'user', 'password') or
die ('Could not connect' . mysql_error());
mysql_select_db('test', $link);
$col = $_POST['col'];
$select = "SELECT " . $col . " FROM account_data WHERE account_number = "
. $_POST['account_number'] . ";" ;
echo '<p>' . $select . '</p>';
$result = mysql_query($select) or die('<p>' . mysql_error() . '</p>');
echo '<table>';
while ($row = mysql_fetch_assoc($result)) {
echo '<tr>';
echo '<td>' . $row[$col] . '</td>';
echo '</tr>';
}
echo '</table>';
mysql_close($link);
}
?>
</body>

Yukarıdaki örneğin ışığında veritabanınızı korumayı bir alışkanlık haline getirmek için mümkün olduğu kadar dinamik SQL kodlarından kaçının. Eğer dinamik SQL kodu kullanmak zorundaysanız, sütunlar için doğrudan girdileri kullanmayın. Kod örneği 4, basit bir doğrulama limiti kullanılarak nümerik olmayan verilerin önüne geçerken statik sütunların kullanımının gücünü gösteriyor.

Kod Örneği 4: Doğrulamayı Korumak ve mysql_real_escape_string()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<html>
<head>
<title>SQL Enjeksiyon Örneği</title>
</head>
<body>
<form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>"
method="post">
<div><input type="text" name="account_number"
value="<?php echo(isset($_POST['account_number']) ?
$_POST['account_number'] : ''); ?>" /> <input type="submit"
value="Save" name="submit" /></div>
</form>
<?php
function isValidAccountNumber($number)
{
return is_numeric($number);
}
if ($_POST['submit'] == 'Save') {
/* #1 Verinizi doğrulayın alışkanlığını hatırlayın! */
if (isset($_POST['account_number']) &&
isValidAccountNumber($_POST['account_number'])) {
/* form işlemeyi yap */
$link = mysql_connect('hostname', 'user', 'password') or
die ('Could not connect' . mysql_error());
mysql_select_db('test', $link);
$select = sprintf("SELECT account_number, name, address " .
" FROM account_data WHERE account_number = %s;",
mysql_real_escape_string($_POST['account_number']));
echo '<p>' . $select . '</p>';
$result = mysql_query($select) or die('<p>' . mysql_error() . '</p>');
echo '<table>';
while ($row = mysql_fetch_assoc($result)) {
echo '<tr>';
echo '<td>' . $row['account_number'] . '</td>';
echo '<td>' . $row['name'] . '</td>';
echo '<td>' . $row['address'] . '</td>';
echo '</tr>';
}
echo '</table>';
mysql_close($link);
} else {
echo "<span style=\"font-color:red\">" .
"Lütfen geçerli bir hesap numarası girin!</span>";
}
}
?>
</body>

Bu örnek mysql_real_escape_string() fonksiyonunun kullanımını gösteriyor. Bu fonksiyon girdiyi düzgün bir şekilde temizleyerek geçersiz bir karakter içermesinin önüne geçiyor. Eğer bugüne kadar magic_quotes_gpc fonksiyonuna sırtınızı yasladıysanız, PHP V6 ile birlikte bu fonksiyonun artık kullanılamayacağını unutmayın. Artık onu kullanmayın ve PHP uygulamalarını onsuz bir şekilde güvenli olarak yazın. Ayrıca eğer bir ISP kullanıyorsanız, magic_quotes_gpc fonksiyonunun aktif olmama ihtimalini gözden çıkarmayın.

Son olarak, geliştirilmiş örnekte, SQL komutunun ve çıktının dinamik sütun seçimini içermediğini görebilirsiniz. Bu sayede eğer tablonuza daha sonra farklı veriler içeren sütunlar eklerseniz, onların çıktısını alabilirsiniz. Eğer veritabınızla çalışmak için bir framework kullanıyorsanız, o zaman kullandığınız framework'ün sizin için SQL doğrulamasını halihazırda yapıyor olmasını ihtimali vardır. Emin olmak için kullandığınız framework'ün belgelerine bir göz atın; eğer hala emin değilseniz, sadece güvende olmak için err'e doğrulama uygulayın. Veritabanı etkileşimi için bir framework kullanıyor olsanız bile, diğer doğrulamayı yürütmeniz gerektiğini unutmayın.

Oturumunuzu Koruyun
Varsayılan olarak PHP'de oturum (session) bilgileri geçici bir dizin üzerine yazılır. Kod Örneği 5'te bulunan ve kullanıcının ID'si ile hesap numarasını oturumda depolayan forma dikkat edin.

Kod Örneği 5: Veriyi Oturumda Depolamak

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
session_start();
?>
<html>
<head>
<title>Oturum bilgisini depolamak</title>
</head>
<body>
<?php
if ($_POST['submit'] == 'Save') {
$_SESSION['userName'] = $_POST['userName'];
$_SESSION['accountNumber'] = $_POST['accountNumber'];
}
?>
<form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>"
method="post">
<div><input type="hidden" name="token" value="<?php echo $token; ?>" />
<input type="text" name="userName"
value="<?php echo(isset($_POST['userName']) ? $_POST['userName'] : ''); ?>" />
<br />
<input type="text" name="accountNumber"
value="<?php echo(isset($_POST['accountNumber']) ?
$_POST['accountNumber'] : ''); ?>" />
<br />
<input type="submit" value="Save" name="submit" /></div>
</form>
</body>

Kod Örneği 6, /tmp dizininin içeriğini gösteriyor.

Kod Örneği 6: /tmp dizinindeki oturm dosyaları

1
-rw------- 1 _www wheel 97 Aug 18 20:00 sess_9e4233f2cd7cae35866cd8b61d9fa42b

Sizin de gördüğünüz üzere, oturm dosyası, yazdırıldığı zaman (Kod Örneği 7'ye bakın), veriyi neredeyse okunması imkansız bir biçimde içeriyor. Dosyanın web sunucu kullanıcısı tarafından hem okunabilir hem de yazılabilir olması gerektiğinden paylaşımlı sunucular üzerinde bulunanlar için oturum dosyaları sorun oluşturabilir. Sizin dışınızda birisi bir betik yazarak bu verileri okuyabilir ve bu sayede oturumdan istedikleri değerleri çekip alabilirler.

Kod Örneği 7: Oturum Dosyasının İçeriği

1
userName|s:5:"ngood";accountNumber|s:9:"123456789";

Oturum verinizi korumak için iki şey yapabilirsiniz. Bunlardan ilki, oturuma dahil ettiğiniz her şeyi şifrelemektir (encrypt). Ancak verinizi sadece şifrelemek, onun güvenli olduğu anlamına gelmez o yüzden oturum verilerinizi güvence altına almak için sadece bu yönteme sırtınızı yaslamayın. Bir diğer alternatif ise oturum verilerinizi farklı bir yerde depolamaktır, örneğin veritabanı gibi. Buna rağmen veritabanınızı kilitlemeyi unutmamalısınız, ancak bu yaklaşım iki problemi çözüyor: İlk, verinizi paylaşımlı bir dosya sisteminden ziyade daha güvenli bir yerde depolaması; ikincisi, uygulamanızın birden fazla web sunucusu üzerinde aynı anda çalışabilmesini sağlaması.

Kendi oturum izinizi uygulamanıza dahil etmek için PHP'deki session_set_save_handler() fonksiyonuna bir göz atın. Bununla oturum bilgilerini veritabanında depolayabilir ya da tüm verilerinizi şifrelemek ve deşifrelemek için bir işleyici (handler) geliştirebilirsiniz. Kod örneği 8 bu fonksiyonun kullanıldığı bir örneği ve bunun dahil edilebilmesi için bir fonksiyonlar iskeletini gösteriyor. Dilerseniz buna benzer diğer örnekleri yazının devamındaki Kaynaklar bölümünde görebilirsiniz.

Kod Örneği 8: session_set_save_handler() fonksiyon örneği

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function open($save_path, $session_name)
{
/* özel kod */
return (true);
}
function close()
{
/* özel kod */
return (true);
}
function read($id)
{
/* özel kod */
return (true);
}
function write($id, $sess_data)
{
/* özel kod */
return (true);
}
function destroy($id)
{
/* özel kod */
return (true);
}
function gc($maxlifetime)
{
/* özel kod */
return (true);
}
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");

Çapraz-site betikleme açıklarına (XSS) karşı koruyun
XSS açıkları 2007 yılındaki web site açıklarının büyük bir kısmını oluşturuyor. Bir XSS açığı, kullanıcının web sitenize HTML kodu enjekte edebilmesi durumunda ortaya çıkıyor. HTML kodu script etiketleri içerisinde bir JavaScript kodu içerebilir ve JavaScript'e izin vermek sayfanın görüntülendiği her zaman kod çalıştırmaya izin vermek anlamına gelir. Kod Örneği 9'daki form bir forumu, wikiyi, sosyal ağı ya da metin girmenin normal olduğu herhangi bir sitede görülebilir.

1
2
3
4
5
6
7
8
9
10
<html>
<head>
<title>XSS girebileceğiniz bir form</title>
</head>
<body>
<form id="myFrom" action="showResults.php" method="post">
<div><textarea name="myText" rows="4" cols="30"></textarea><br />
<input type="submit" value="Delete" name="submit" /></div>
</form>
</body>

Kod örneği 10, bu formun sonuçları nasıl yazdırabileceğini ve bu sayede XSS saldırılarına izin verebileceğini gösteriyor.

Kod Örneği 10: showResults.php

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head>
<title>XSS örneklendiren sonuçlar</title>
</head>
<body>
<?php
echo("<p>Bunu yazdınız:</p>");
echo("<p>");
echo($_POST['myText']);
echo("</p>");
?>
</body>

Kod örneği 11 Google ana sayfasını yeni pencerede açabilen bir örneği gösteriyor. Eğer web uygulamanız XSS saldırılarına karşı korunmalı değil ise, verilebilecek zararın büyüklüğü tamamen saldırganın hayalgücü ile sınırlıdır. Örneğin birisi sitenin tarzını yansıtan ve sazan avlama (phishing) olarak bilinen sitelere yönlendiren bir bağlantıyı sisteminize dahil edebilir.

Kod Örneği 11: Şüpheli metin girişi örneği

1
2
<script type="text/javascript">myRef = window.open('http://www.google.com.tr','mywin',
'left=20,top=20,width=500,height=500,toolbar=1,resizable=0');</script>

Kendinizi XSS saldırılarına karşı korumak için girdinizi htmlentities() fonksiyonunuzu kullanarak, girdinin görüntülenebileceği her yerde filtreleyin. Unutmayın, alışkanlık haline getirmeniz gereken ilk ipucumuzda, verinin güvenilir verilerle doğrulanmasını gösteriyordu.

Bu sayfanın çok daha güvenli bir sürümü aşağıda gösteriliyor.

Kod Örneği 12: Daha Güvenli bir Form

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head>
<title>XSS örneklendiren sonuçlar</title>
</head>
<body>
<?php
echo("<p>Bunu yazdınız:</p>");
echo("<p>");
echo(htmlentities($_POST['myText']));
echo("</p>");
?>
</body>

Forum gönderilerini doğrulayın
Form sahteciliği, sizin öngörmediğiniz bir yerden sitenizdeki formlardan birine giriş yapılması anlamına gelir. Bir formu kandırmanın en kolay yolu, tüm verileri aktararak formu gönderen bir web sayfası oluşturmaktır. Web uygulamaları tabir-i caizse yersiz yurtsuz olduklarından gönderilen verinin istediğiniz yerden gönderildiğine emin olmanın kesin bir yolu yoktur. IP adreslerinden sunucu adlarına günümüzde her şey artık taklit edilebilr. Kod örneği 13, veri girişi yapabileceğiniz bir formu gösteriyor:

Kod Örneği 13: Metin işleyen bir form

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<title>Form sahteçilik örneği</title>
</head>
<body>
<?php
if ($_POST['submit'] == 'Save') {
echo("<p>Şu metninizi işliyorum: ");
echo($_POST['myText']);
echo("</p>");
}
?>
</body>

Kod örneği 14, Kod Örneği 13'teki forma veri gönderen bir formu gösteriyor. Bunu denemek için 13. kodu web sunucunuza kaydedebilir, 14. kodu ise bir HTML belgesi olarak masaüstünüze kaydedebilirsiniz. Bu formu kaydettikten sonra web tarayıcınız üzerinde açın. Ardından boşlukları doldurabilir ve formu gönderebilirsiniz.

Kod Örneği 14: Verinizi Toplayacak Bir Form

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<title>Collecting your data</title>
</head>
<body>
<form action="veriyiisle.php" method="post">
<select name="answer">
<option value="Evet">Evet</option>
<option value="Hayır">Hayır</option>
</select>
<input type="submit" value="Save" name="submit" />
</form>
</body>

Form sahteciliğinin olası etkisi, gerçekten, eğer formunuz açılır kutlar, seçim düğmeleri, onay kutucukları ya da diğer sınırlandırılmış veri giriş yöntemleri kullanıyor olsun, formun sahte olması durmunda bunların bir değerinin kalmıyor olması. Kod Örneği 15'teki geçersiz veri içeren koda dikkat edin.

Kod Örneği 15: Geçersiz veri içeren bir form

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
<title>Verinizi toplamak</title>
</head>
<body>
<form action="http://path.example.com/veriyiisle.php"
method="post"><input type="text" name="answer"
value="Bunun evet/hayır cevabı için geçerli olmasına imkan yok..." />
<input type="submit" value="Save" name="submit" />
</form>
</body>

Bir düşünün: Eğer kullanıcınin gireceği veriyi sınırlandıran açılır kutunuz ya da seçim düğmeleriniz var ise, girilen veriyi doğrulamanın gerekli olmadığını düşünebilirsiniz. Ne de olsa girdi formunuz kullanıcının sadece belirli bir tip veri girmesini sağlıyor, öyle değil mi? Form sahteciliğini sınırlandırmak için, girilen verinin söylediği şey olup olmadığını kontrol etmeniz gerekir. Kullanabileceğiniz bir teknik, tek kullanımlık bir anahtar oluşturmaktır. Bu yöntem her ne kadar form sahteciliği sorununu kökünden çözmese de, bu işlemi oldukça zorlaştıracaktır. Her bir form oluşturulduğunda şifre değişeceğinden, saldırganın gönderi formunun bir kopyasını alması, şifreyi ayıklaması ve kendi formlarına entegre etmesi gerekir. Bu yöntem bir kişinin tek bir form oluşturarak web uygulamanıza istenmeyen verilerin gönderilmesinin önüne geçer. Kod örneği 16 tek kullanımlık form anahtarı kullanan bir örneği gösteriyor.

Kod Örneği 16: Tek kullanımlık form anahtarı kullanmak

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
session_start();
?>
<html>
<head>
<title>SQL Enjeksiyon Testi</title>
</head>
<body>
<?php
echo 'Oturum Anahtarı=' . $_SESSION['token'];
echo '<br />';
echo 'Formdan Alına Anahtar=' . $_POST['token'];
echo '<br />';
if ($_SESSION['token'] == $_POST['token']) {
/* güzel, çok güzel... bir tane daha oluştur */
} else {
echo '<h1>Defol!</h1>';
}
$token = md5(uniqid(rand(), true));
$_SESSION['token'] = $token;
?>
<form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>"
method="post">
<div><input type="hidden" name="token" value="<?php echo $token; ?>" />
<input type="text" name="myText"
value="<?php echo(isset($_POST['myText']) ? $_POST['myText'] : ''); ?>" />
<input type="submit" value="Save" name="submit" /></div>
</form>
</body>

Çapraz-site istek sahteciliğine (CSRF) karşı koruyun.
Çapraz-site istek sahteciliği (Cross-Site Request Forgeries - CSRF Saldırıları), bir saldırı yürütmek için kullanıc ayrıcalıklarından faydalanan açıkları kullanır. Bir CSRF saldırısında, kullanıcınız şüpheli olmayan suç ortağı haline kolayca dönüşebilir. Kod Örneği 17, benzer bir eylemi içeren örnek bir sayfayı gösteriyor. Bu sayfa, kullanıcı giriş bilgisine çerezler (cookie) üzerinden ulaşıyor. Çerez geçerli olduğu sürece, web sayfası o isteği işleyecektir.

Kod Örneği 17: Bir CSRF Örneği

1
<img src="http://www.example.com/processSomething?id=123456789" />

CSRF saldırılar genellikle <img> etiketleri biçimindedir çünkü tarayıcılar o imajı görüntülemek için belirtilen URL'yi çağırırlar. Ancak imaj kaynağı, kendisine görülen parametreleri içerisine alabilen bir web sayfasının adresi de olabilir. Bu <img> etiketi XSS saldırısına dahil edildiğinde -ki bu durum bugüne kadar belgelenen saldırılarda en sık görülen yöntemdir- kullanıcılar farkında olmadan kendi verilerini kullanarak işlem yapılmasının önünü açabilirler - ki bu bir sahteciliğin bir parçası da olabilir.

Kendinizi CSRF saldırılarına karşı korumak için, formlarınızı doğrulamak için edinmeniz gereken tek kullanımlık anahtar kullanımı alışkanlığını kullanabilirsiniz. Ayrıca $_REQUEST yerine kesin $_POST değişkenini kullanın. Kod örneği 18, veriyi, ister GET isteği ile alan, isterse de verinin kendisine postalanması ile alsın, kötü şekilde kodlanmış bir web sayfası örneğini gösteriyor.

Kod Örneği 18: $_REQUEST üzerinden veriyi almak

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<title>Gönderilerin ve alımların her ikisini de işler</title>
</head>
<body>
<?php
if ($_REQUEST['submit'] == 'Save') {
echo("<p>Şu verinizi işliyorum: ");
echo(htmlentities($_REQUEST['text']));
echo("</p>");
}
?>
</body>

Kod örneği 19 ise sadece POST kullanan formları işleyen, yukarıdaki sayfanın temizlenmiş bir örneğini gösterir.

Kod Örneği 19: Veriyi sadece $_POST üzerinden almak

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<title>Sadece Gönderileri İşler</title>
</head>
<body>
<?php
if ($_POST['submit'] == 'Save') {
echo("<p>Şu verinizi işliyorum: ");
echo(htmlentities($_POST['text']));
echo("</p>");
}
?>
</body>

Sonuç
Daha güvenli PHP Web uygulamaları yazmak için bu 7 alışkanlığı edinmeye başlamak, sizi çeşitli saldırıların kurbanı olmaktan koruyacaktır. Tıpkı diğer alışkanlıklarda olduğu gibi, ilk bakışta biraz garip görünebilirler, ancak zaman geçtikçe size daha doğal görünecektir.

İlk alışkanlığın önemli olduğunu unutmayın: Girdinizi doğrulayın. Girdinizin kötü bir değer içermediğinden emin olduktan sonra dosya sisteminizi, veritabanınızı ve oturumunuzu korumaya başlayabilrsiniz. Son olarak PHP kodunuzun XSS saldırılarına, form sahteciliğine ve CSRF saldırılarına karşı korunmalı olduğundan emin olun. Bu alışkanlıkları hayata geçirecek disiplinli bir yaklaşım, basit saldırıların önüne geçmede size çok büyük yardımı dokunacaktır.

Kaynaklar
Öğren

Ürünleri ve teknolojileri alın

  • IBM trial yazılımını indirererek ya da DVD'sini satın alarak bir sonraki açık kaynak projenizi yaratın.
  • IBM ürün doğrulama sürümlerini indirin ve DB2®, Lotus®, Rational®, Tivoli®, ve WebSphere®'den özel yazılım ürünlerini ve uygulama geliştirme araçlarını kullanmaya başlayın.

Tartışın

Kaynak: IBM
Çeviri: Emrah Ömüriş

/* pinkfloyd yazdı. 04 Ocak 2009 14:14. 9 yorum var */

Yorumlar

Güzel bir yazı olmuş. Çeviri için teşekkürler.
XSS konusunda geçen htmlentities fonksiyonun Türkçe karakterleri desteklemediğini hatırlatayım. htmlentities fonksiyonunun yerine htmlspecialchars fonksiyonunu kullanabilirsiniz.

eğer veritabanı ve sayfanızda utf-8 karakter kodlamasını kullanırsanız htmlentities fonksiyonunda herhangi bir karakter sorunu yaşamazsınız. ben bu şekilde kullanıyorum.
saygılar

/* d.D http://www.habersuzgeci.com */
Yazıyı okuduktan sonra mysql_real_escape_string() fonksiyonunun dökümanına bir daha baktım. Aşağıda listelenen karakterlerin tümü ters bölü ile kaçılıyor;
  • \n
  • \r
  • \
  • '
  • "
  • \x00
  • \x1a
    Dolayısıyla içinde çift tırnak, satır başı gibi karakterler geçen veriler için kullanımı pek uygun görünmüyor. Örneğin, yorum ve makale metinlerini tutan tablo alanları gibi.
    Yukarıdaki listede bulunan son iki karakter ise bir hayli ilginç. Bu karakterleri gerçekten kaçmamız gerektiğini bilmiyordum.

Makaleniz için çok teşekkür ederim. Yorumları güvenli hale getirebilmek için bir Kötü Kelime Süzgecine (badwords.txt) ihtiyacım var. Türkçe bir badwords.txt bulamadım bana yardımcı olur musunuz?

gerçekten güzel bir kaynak. bu güne kadar atladığım bazı ayrıntıları görmemi sağladınız. güzel makale için teşekkür ederim. Ayrıca izin verirseniz, makaleyi kendi siteme de koymak isterim. elbette kaynağı belirtmek şartıyla.

/* Muhtaç olduğun kudret damarlarındaki asil kanda mevcuttur. K.Atatürk */

Süper bir kaynak olmuş çeviren ellerine sağlık, bilgine sağlık

/* http://matasoy.blogcu.com Sigara kullanmam ama Çok Pis QuakeIII Arena Oynarım */

makale için teşekkürler php ye yeni başlamış arkadaşlar için gerekli bilgiler

/* seo | firma ekle */

Sertifikalı IBM Lotus & Domino developer olarak, yazının şu kısmını
"IBM ürün doğrulama sürümlerini indirin ve DB2®, Lotus®, Rational®, Tivoli®, ve WebSphere®'den özel yazılım ürünlerini ve uygulama geliştirme araçlarını kullanmaya başlayın." kısmı biraz atmasyon ve reklam olmuş.

Çünkü yazı başlığı ile bu ürünlerin bir alakası bulunmamakta.

Çok Güzel bir kaynak Teşekkürler

üye olunpillinetwork sitelerine yorum ekleyebilmek ve daha fazlası için, üye olun ya da giriş yapın.

Bu yazıyı rapor et. Kural dışı içeriğe rastladığınızda editörlerimize rapor ederek müdahale edilmesini sağlayabilirsiniz. (Hangi durumlarda rapor edebilirim?)

Bu site

Nokta ve pilli ortak yapımı olan kodaman.org hep birlikte içerik üretip gelirini yazarları ile paylaştığımız kolektif bir kod yazarları blogudur. Siz de katılabilirsiniz.

pilliilan

son yorumlar

arama

pillinetwork