Iyi uygulama ve güvenlik sorgulama PHP / SQL Veritabanı

6 Cevap php

Yani biraz terbiyeli php geliştirici yaşıyorum ve 2007 yılından bu yana 'lanet şeyi yapıyorsun' olmuştur; benim uygulamaları güvenliği söz konusu olduğunda, ancak ben hala nispeten n00bish duyuyorum. Ben gerçekten her şeyi bilmiyorum şekilde elimden ve gerek biliyorum.

I Securing PHP Web Applications almış ve yol boyunca şeyleri test yoluma okuyorum. Ben veritabanı sorgulama (özellikle mysql altında) ile ilgili genel SO grubu için bazı sorular var:

Bir veritabanına veri koymak uygulamalar oluştururken yeterli veri girişi üzerinde mysql_real_escape_string ve genel kontrol (is_numeric vb) nedir? Ne sql enjeksiyon farklı saldırıların diğer türleri hakkında.

Birisi biraz daha fazla bilgi ile saklanır usul ve hazırlanmış deyimleri açıklayabilir misiniz - bunları yapmak ve onlara çağrı yapmak. Ben perde arkasında neler olup bittiğini doğrulama, onlar nasıl çalıştığını bilmek istiyorum.

Ben bir php4 bağlı bir ortamda çalışmak ve php5 an için bir seçenek değildir. Başkasının tüm havalı tatlı yeni mysqli arayüzünü kullanırken size güvenli uygulamalar için ne yaptın, önce bu konumda olmuştur?

Insanlar avantajlı bulduk bazı genel iyi uygulamalar, yükseltmeleri ve (php5 için php4 taşımak gibi) olası göçler dayanabilen bir altyapı oluşturmaya önem nelerdir.

Not: Yaklaşık bir arama vardı php-mysql güvenliği vurmak buna benzer bir şey bulamadı.

6 Cevap

Benim öneriler:

  1. lehine mysqli hendek PDO (mysql sürücüsü ile)
  2. PDO hazırlanmış deyimleri paremeterized kullanın

Daha sonra gibi bir şey yapabilirsiniz:

$pdo_obj = new PDO( 'mysql:server=localhost; dbname=mydatabase', 
                    $dbusername, $dbpassword );

$sql = 'SELECT column FROM table WHERE condition=:condition';
$params = array( ':condition' => 1 );

$statement = $pdo_obj->prepare( $sql, 
    array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) );
$statement->execute( $params );
$result = $statement->fetchAll( PDO::FETCH_ASSOC );

PROs:

  1. PDO sizin yerinize yapar beri kaçan Artık manuel!
  2. Bu ani bir veritabanı backend'e geçiş nispeten kolaydır.

CONs:

  • i herhangi düşünemiyorum.

OWASP bağlantı vardır Javier cevabı iyi bir başlangıçtır.

Daha yapabileceğiniz birkaç şey daha vardır:

  1. SQL enjeksiyon saldırıları ile ilgili olarak, "BIRAKMA" veya "DELETE *", bu benzeri gibi girişten yaygın SQL ifadeleri kaldıracak bir fonksiyon yazabiliriz:

    * $ Sqlarray = array ("kullanıcılar" FROM "DAMLA", "ya = 1 1", "sendika seçme", "SELECT * FROM", "ana seçmek", "tablo oluşturmak", "kullanıcılar"); *

    Sonra bu diziden karşı girişini kontrol edecek fonksiyon yazmak. $ Sqlarray içindeki herhangi bir madde kullanıcılardan yaygın girdi olmayacaktır emin olun. (Teşekkürler lou, bu konuda strtolower kullanmayı unutmayın).

  2. Ben memcache PHP 4 ile çalışır ama sadece Y dönemde kez process.php sayfası X miktarı belli bir uzak IP erişimi sağlayarak yerinde memcache ile bazı spam koruması koyabilirsiniz emin değilim.

  3. Ayrıcalıklar önemlidir. (Diyelim ki sipariş işleme) ayrıcalıklar eklemek sadece gerekiyorsa, o zaman sadece eklemek ve belki ayrıcalıkları seçin sahip bir kullanıcı ile sipariş süreci sayfasında veritabanına giriş yapmalıdır. Bu, bir SQL enjeksiyon ile var olsa bile, sadece silebilir ya da yeniden yapılandırma INSERT / SELECT sorguları gerçekleştirmek ve olamazdı anlamına gelir.

  4. Bir dizinde önemli bir php işleme dosyaları koyun gibi / bulunmaktadır. Sonra bu bütün IP'leri erişimine izin vermemek / dizini bulunmaktadır.

  5. Kullanıcının oturumunda kullanıcının ajan + remoteip + senin tuz ile tuzlu MD5 koymak ve doğru MD5 kendi çerez olduğunu her sayfa yük doğrulamak olun.

  6. Bazı başlıkları Disallow (http://www.owasp.org/index.php/Testing_for_HTTP_Methods_and_XST). (Eğer dosya yükleme ihtiyacım yoksa) PUT Disallow / İZ / CONNECT / başlıkları SİL.

Ben genellikle bu yüzden özellikle sizin ihtiyaçlarına hedeflenen öneriler sağlayamaz PHP ile çalışmak yok, ama OWASP sayfasına bir göz, özellikle ilk 10 açıklarını rapor almanızı öneririz: http://www.owasp.org/index.php/Top_10_2007

Bu sayfa, her güvenlik açığı için size farklı platformlarda sorunu önlemek için yapabileceğiniz şeylerin bir listesini almak (. Net, Java, PHP, vb)

Hazırlanan tablolar ile ilgili, onlar motoru gerçek parametresinin parçası olarak değil ayrıştırıldı gereken bir şey vardır hangi karakterleri anlayabilir bu bilgileri kullanarak, kaç tane parametre ve belirli bir sorgu sırasında beklemek ne tipleri veritabanı motoru bildirerek çalışmak bir dize sınırlayıcı olarak bir 'yerine bir veri parçası olarak (kesme işareti)' gibi SQL. Üzgünüm PHP hedefleyen daha fazla bilgi sağlamak, ama bu yardımcı olur umarım olamaz.

AFAIK, PHP / MySQL genellikle parametreli sorgular yoktur.

sprintf() mysql_real_escape_string() oldukça iyi çalışması gerektiğini ile kullanma. Eğer sprintf() (tamsayılar için örneğin "% d") uygun biçim dizeleri kullanırsanız, oldukça güvenli olmalıdır.

Ben yanlış olabilir, ama kullanıcı sağlanan verilere mysql_real_escape_string kullanmak için yeterli olmamalı?

Onlar ctype_digit yerine örneğin kullanarak olduklarından emin gerçek sayı olan yapmak gerekir, bu durumda sayı olduğunda sürece or is_numeric or sprintf {[(3)] } veya %u), bir dizi girdi zorlamak için.

Ayrıca, bir serarate mysql Sadece SEC edebilirsiniz php komut için kullanıcıyı, INSERT, UPDATE ve DELETE sahip muhtemelen iyi bir fikir ...


Example from php.net

Örnek 3 A "En İyi Uygulama" sorgusu

Her bir değişken etrafında mysql_real_escape_string () kullanarak SQL Injection önler. Bu örnek ayar Parite Magic bağımsız, bir veritabanını sorgulamak için "en iyi uygulama" yöntemi gösterir.

Sorgu doğru olarak işletilecek, ve SQL Injection saldırıları çalışmaz.

   <?php
    if (isset($_POST['product_name']) && isset($_POST['product_description']) && isset($_POST['user_id'])) {
        // Connect

        $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password');

        if(!is_resource($link)) {

            echo "Failed to connect to the server\n";
            // ... log the error properly

        } else {

            // Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON.

            if(get_magic_quotes_gpc()) {
                $product_name        = stripslashes($_POST['product_name']);
                $product_description = stripslashes($_POST['product_description']);
            } else {
                $product_name        = $_POST['product_name'];
                $product_description = $_POST['product_description'];
            }

            // Make a safe query
            $query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)",
                        mysql_real_escape_string($product_name, $link),
                        mysql_real_escape_string($product_description, $link),
                        $_POST['user_id']);

            mysql_query($query, $link);

            if (mysql_affected_rows($link) > 0) {
                echo "Product inserted\n";
            }
        }
    } else {
        echo "Fill the form properly\n";
    }

DB Yazi Becerisi I içeren herhangi bir faaliyet için saklı yordamlar kullanın ve tüm seçtiği için bağlama parametrelerini kullanın.