Güvenlik kodunun yanında ek flood koruması
19
●2.280
- 19-10-2009, 02:25:46Yanılıyorsunuz

@devturkeli burda haklı
Neden ?
İlk önce session nasıl çalışır onu söyliyeyim
Session ID diye birşey vardır bildiğiniz üzere. Bu ID cookie vasıtası ile kullanıcıya aktarılır ve her istekte bu ID sunucuya tekrar gönderilir. Bu sayafada oturumun(session) kalıcı olmasını sağlar. (Eğer çerezler kapalı ise oturumunuz sürekli değişecektir. Deneyin ve görün).
Bu yüzden curl ile rahatlıkla aşılabilir. Nasıl mı ?
curl ile karşı tarafa istenildiği gibi başlık(header) yollanıyor. Bunun içinde session id bilgiside yollanıyor. Bu yüzden session id, her istekde random olarak bir değer alırsa oturum sürekli değişeceğinden dolayı bu hiç bir işe yaramaz.
Daha iyi ne önerebilirsin ?
IP bazlı kontrol
IP bazlı kontrol aşılabilir mi ?
Evet. Elinizde proxy listeniz var ise buda aşılır.
Umarım açıklayıcı olmuştur. - 19-10-2009, 02:48:21Üyeliği durdurulduah mustafa ben anlatamayacağım bunlara mustafa

kaydet test.php
<?php session_start(); $sid = session_id(); if ($_POST['sid'] == $sid) { if (!$_SESSION['hede']) { fwrite(fopen("a.txt", "a"), "hede\n"); echo 'Yazı Eklendi.'; } else { echo 'Flood girişimi!'; } } $_SESSION['hede'] = 'hede'; ?>kaydet flood.php
<?php function getir($site) { $fakeSID=md5(mt_rand(1,9999)); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $site); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_COOKIE, "PHPSESSID=$fakeSID"); curl_setopt($ch,CURLOPT_POST, true); curl_setopt($ch,CURLOPT_POSTFIELDS,"sid=$fakeSID"); $data = curl_exec($ch); curl_close($ch); return $data; } echo getir('http://p/test.php'); ?>İlk önce normal browserden session kontrollü ve session korumalı(?) test.php yi çalıştırın. a.txt dosyası yazıldıktan sonra session hafızaya kaydedildiği için, session kontrolü sayesinde 2. bir işleme izin vermeyecek ve ekrana Flood girişimi! yazacaktır.
Şimdi flood.php yi çalıştırın seri bir şekilde sayfanızı sürekli yenileyin. a.txt dosyanızı açın bir yığın hede yazısını görürsünüz.
Anlatmak istediğim sessionid kontrol falan tıraş. Curl ile fake sessionid oluşturuluyor hafızaya alınıyor test.php deki session kontrolüde, curlun kaydettiği fakesessionid ile yine post ile yolladıgım aynı fakesessionid i eşleştiriyor, eşit oldugu için dediğiniz güvenlik tırt kalıyor. - 19-10-2009, 10:35:13Üyeliği durduruldudevturkeli nin uygulama mantigi aynen gecerli. sessionda token gibi bir paremetre tutmuyorsaniz session id olmasinin bir engelleyici etkisi olmaz.devturkeli adlı üyeden alıntı: mesajı görüntüle
php güvenliği ile ilgili video serisi yapiyorum
inş bitince hepsini anlatcam
- 20-10-2009, 22:03:32Curl ile session kontrolünü çok rahat aşarsın..BHCoder adlı üyeden alıntı: mesajı görüntüle
devturkeli, 2 üstteki son mesajın ve zone.org ile alakalı verdiğin linkte ancak kokulusilginin verdiği kodu aşarsın, en altta Yns de demiş ki; "yine curl ve regexp yardimiyla sayfaya istek yapilip hidden input'un degeri alinip, ondan sonra sayfaya post edilirse senin korumada caresiz kaliyor", demiş, ama maalesef yanılmış.
Üyelik kontrollü bir sistemde flood kontrolü basit bir şekilde engellenebilir fakat direk ziyaretçiden alınacak veriler en iyi IP kontrolü ile engellenebilir, bunun harici diğer yöntemlerle engelleme yapılırsa curl ile aşılabilir, fakat IP bazlı bir engelleme yapılırsa ancak dnmtnk'nin de dediği gibi ya random proxy kullanacaksınız ya da modeme reset atacaksınız
Az sonra bunun ile ilgili bir betik yazıp paylaşacağım, token kontrollü olsun istediğiniz gibi, o betiği aşacak kodu paylaşırsanız fazla söze gerek kalmamış olur böylece
- 20-10-2009, 22:55:25Evet kodumuz aşağıdaki gibi, güvenlik kodu yok, 30 saniye içinde yada sizin belirleyeceğiniz bir süre kadar yeniden mesaj yazılmasını engeller, bu engeli ancak curl ile random proxy kullanarak ya da modeminiz 30 saniye içinde yeni bir ip alıyorsa resetleyip öyle aşabilirsiniz (benim modem 20 saniyede yeni ip alıyor mesela), ayrıca dışarıdan direk post gönderimini engellemek için gizli bir hidden input ile key gönderiyoruz, buna CSRF koruması da deniyor, kıracak olan varsa buyursun kırsın, bizde yeni birşey öğrenmiş oluruz.
(Ufak tefek hatalar olabilir, inceden inceye kontrol etmedim.)
Tablo:
CREATE TABLE messages ( id int(11) NOT NULL auto_increment, message text NOT NULL, name varchar(25) NOT NULL, ip varchar(15) NOT NULL, time timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, PRIMARY KEY (id) );
Dosya (herhangi bir isimle kaydedin)
<?php session_start(); @setlocale(LC_ALL, 'turkish'); // connect mysql_connect('localhost','root','0000') or die (mysql_error()); mysql_select_db('flood') or die (mysql_error()); // settings $floodtime = 30; $charlimit = 100; ################################################################################################### if(empty($_REQUEST['flood'])) { $ip = $_SERVER['REMOTE_ADDR']; $_SESSION['ip'] = $ip; $time = time(); $key = md5($ip).md5(microtime()); if(!isset($_SESSION['key'])){ $_SESSION['key'] = $key; } echo ' <h4>Flood Koruması</h4> <form method="POST" action="'.$_SERVER['PHP_SELF'].'?flood=message"> İsim : <input type="text" name="name"><br /> Mesaj : <textarea name="message" rows="10" cols="30"></textarea> <input type="hidden" name="key" value="'.$key.'"><br /><hr /> * Mesajınız en çok '.$charlimit.' karakter olabilir.<br /> * Yeniden mesaj gönderme süresi : '.$floodtime.' sn.<br /><hr /> <input type="submit" value="Send Message"> </form> '; } ################################################################################################### if($_REQUEST['flood']=='message') { if(empty($_POST['key']) || empty($_SESSION['key']) || $_POST['key'] != $_SESSION['key']) { die ('<a href="'.$_SERVER['PHP_SELF'].'">Yeni flood denemesi yap!</a>'); } elseif(empty($_POST['name']) || empty($_POST['message'])) { header('Refresh:3 url='.$_SERVER['PHP_SELF']); die ('Lütfen boş alan bırakmayınız !'); } elseif($charlimit < strlen($_POST['message'])) { header('Refresh:3 url='.$_SERVER['PHP_SELF']); die ('Mesajınız en çok '.$charlimit.' karakter olabilir.'); } else { $sql = mysql_query("SELECT * FROM messages WHERE ip = '$_SESSION[ip]' ORDER BY time DESC LIMIT 1") or die (mysql_error()); $res = @mysql_fetch_row($sql); $dbtime = strtotime($res['4']); $nowtime = time(); if(($nowtime - $dbtime) < $floodtime) { header('Refresh:3 url='.$_SERVER['PHP_SELF']); die ('Yeniden mesaj gönderebilmek için '.($floodtime - ($nowtime - $dbtime)).' saniye beklemelisiniz !'); } else { header('Refresh:3 url='.$_SERVER['PHP_SELF']); $message = mysql_real_escape_string(strip_tags(trim($_POST['message']))); $name = mysql_real_escape_string(strip_tags(trim($_POST['name']))); mysql_query("INSERT INTO messages (message,name,ip,time) VALUES ('$message','$name','$_SESSION[ip]',NOW())") or die ('Bir problem oldu, daha sonra tekrar deneyiniz.'); echo 'Mesajınınız eklendi..<br /><a href="'.$_SERVER['PHP_SELF'].'">Başka mesaj ekle!</a>'; } } } ?> - 21-10-2009, 00:25:55Kimlik doğrulama veya yönetimden onay bekliyor.Kodun oldukça güvenli fakat bir kaç eksik var.Enigmatic adlı üyeden alıntı: mesajı görüntüle
$_SERVER['PHP_SELF']
xss açığı oluşturur.
bknz. Temizlemek lazım kullanmadan önce.
xss açığı olunca sayfadaki key değeri çok rahat alınabilinir ve kullanıcının haberi olmadan veri postlanabilinir.
CSRF için key yerine referrer kontrolü yapmak daha iyi olur, çünkü javascript ile sahte referrer gönderilemez. - 21-10-2009, 16:50:03Kodu genel kullanım için vermedim zaten, herkesin kendine göre çeşitli güvenlik fonksiyonları var, kullanmak isteyen elbette güvenlik önlemlerini alacak.S4l1h adlı üyeden alıntı: mesajı görüntüle
Key değeri elbette çok basitçe alınabilir, buradaki key değerinin amacı adres satırına direk POST yapılmasını engellemek içindir, yani saldırgan önce ilk önce formu mutlaka ziyaret etmelidir, CURL ile rahatça key değeri alınıp POST gönderilebilir ama tek sefer, ard arda gönderim belirlenen süre kadar yapılamaz, yapılabilmesi için mutlaka ip değişilmesi gerekir.
Birde şu cümleyi hiç anlamadım;
CURL ile referer kontrolü basitçe aşılabiliyor biliyorsunuz, javascriptin konuyla alakasını anlamadım ?Alıntı
