Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Apakah mysql_real_escape_string() dan mysql_escape_string() cukup untuk keamanan aplikasi?

@Charles sangat benar!

Anda menempatkan diri Anda pada risiko beberapa jenis diketahui Serangan SQL, termasuk, seperti yang Anda sebutkan

  • Injeksi SQL:Ya! Mysql_Escape_String mungkin MASIH membuat Anda rentan terhadap injeksi SQL, tergantung di mana Anda menggunakan variabel PHP dalam kueri Anda.

Pertimbangkan ini:

$sql = "SELECT number FROM PhoneNumbers " .
       "WHERE " . mysql_real_escape_string($field) . " = " . mysql_real_escape_string($value);  

Bisakah itu lolos dengan aman dan akurat dengan cara itu? TIDAK! Mengapa? karena seorang peretas masih bisa melakukan ini:

Ulangi setelah saya:

mysql_real_escape_string() hanya dimaksudkan untuk menghindari data variabel, TIDAK nama tabel, nama kolom, dan terutama bukan LIMIT bidang.

  • SEPERTI eksploitasi:LIKE "$data%" di mana $data bisa menjadi "%" yang akan mengembalikan SEMUA catatan ... yang bisa jadi eksploitasi keamanan... bayangkan saja Pencarian dengan empat digit terakhir kartu kredit... OOP! Sekarang peretas berpotensi menerima setiap nomor kartu kredit di sistem Anda! (BTW:Menyimpan kartu kredit penuh hampir tidak pernah disarankan!)

  • Eksploitasi Charset:Tidak peduli apa yang dikatakan para pembenci, Internet Explorer tetap , pada tahun 2011, rentan terhadap Eksploitasi Kumpulan Karakter, dan itu jika Anda telah mendesain halaman HTML Anda dengan benar, dengan persamaan

    Berikut hasil dari kode ini ketika berbagai input dilewatkan:

    $ php sql_exploits.php url http://www.reddit.com id
    SQL generated: SELECT url FROM GrabbedURLs 
                   WHERE url LIKE 'http://www.reddit.com%'
                   ORDER BY id;
    Returns: Just URLs beginning w/ "http://www.reddit.com"
    
    $ php sql_exploits.php url % id
    SQL generated: SELECT url FROM GrabbedURLs 
                   WHERE url LIKE '%%' 
                   ORDER BY id;
    Results: Returns every result Not what you programmed, ergo an exploit --
    

    $ php sql_exploits.php 1=1'http://www.reddit.com ' id Hasil:Mengembalikan setiap kolom dan setiap hasil.

    Lalu ada eksploitasi LIMIT yang BENAR-BENAR jahat:

    $ php sql_exploits.php url 
    > 'http://www.reddit.com'
    > "UNION SELECT name FROM CachedDomains"
    Generated SQL: SELECT url FROM GrabbedURLs 
                   WHERE url LIKE 'http://reddit.com%' 
                   LIMIT 1 
                   UNION
                   SELECT name FROM CachedDomains;
    Returns:  An entirely unexpected, potentially (probably) unauthorized query
              from another, completely different table. 
    

    Apakah Anda memahami SQL dalam serangan atau tidak, itu tidak relevan. Hal ini menunjukkan bahwa mysql_real_escape_string() dengan mudah dielakkan bahkan oleh peretas yang paling tidak dewasa sekalipun. Itu karena itu adalah mekanisme pertahanan REAKTIF. Ini hanya memperbaiki eksploitasi yang sangat terbatas dan DIKENAL di Database.

    Semua pelarian tidak akan pernah cukup untuk mengamankan database. Faktanya, Anda dapat REAKSI secara eksplisit untuk setiap eksploitasi yang DIKETAHUI dan di masa mendatang, kode Anda kemungkinan besar akan menjadi rentan terhadap serangan yang ditemukan di masa mendatang.

    Pertahanan yang tepat, dan satu-satunya (benar-benar), adalah PROAKTIF:Gunakan Pernyataan yang Disiapkan. Pernyataan yang disiapkan dirancang dengan perhatian khusus sehingga HANYA SQL yang valid dan TERPROGRAM yang dieksekusi. Ini berarti bahwa, jika dilakukan dengan benar, kemungkinan SQL yang tidak diharapkan dapat dieksekusi akan berkurang secara drastis.

    Secara teoritis, pernyataan yang disiapkan yang diimplementasikan dengan sempurna akan tahan terhadap SEMUA serangan, dikenal dan tidak dikenal, karena mereka adalah teknik SISI SERVER, ditangani oleh DATABASE SERVER DIRI SENDIRI dan perpustakaan yang berinteraksi dengan bahasa pemrograman. Oleh karena itu, Anda SELALU dijamin terlindungi dari SETIAP PERETASAN YANG DIKETAHUI, minimal.

    Dan kodenya lebih sedikit:

    $pdo = new PDO($dsn);
    
    $column = 'url';
    $value = 'http://www.stackoverflow.com/';
    $limit = 1;
    
    $validColumns = array('url', 'last_fetched');
    
    // Make sure to validate whether $column is a valid search parameter.
    // Default to 'id' if it's an invalid column.
    if (!in_array($column, $validColumns) { $column = 'id'; }
    
    
    $statement = $pdo->prepare('SELECT url FROM GrabbedURLs ' .
                               'WHERE ' . $column . '=? ' .
                               'LIMIT ' . intval($limit));
    $statement->execute(array($value));
    while (($data = $statement->fetch())) { }
    

    Sekarang tidak begitu sulit bukan? Dan ini kode empat puluh tujuh persen lebih sedikit (195 karakter (PDO) vs 375 karakter (mysql_). Itulah yang saya sebut, "penuh kemenangan".

    EDIT:Untuk mengatasi semua kontroversi yang ditimbulkan oleh jawaban ini, izinkan saya untuk mengulangi apa yang telah saya katakan:

    Menggunakan pernyataan yang disiapkan memungkinkan seseorang untuk memanfaatkan tindakan perlindungan dari server SQL itu sendiri, dan oleh karena itu Anda dilindungi dari hal-hal yang diketahui orang-orang dari server SQL. Karena tingkat perlindungan ekstra ini, Anda jauh lebih aman daripada hanya menggunakan melarikan diri, tidak peduli seberapa telitinya.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dapatkan nilai AUTO_INCREMENT saat ini untuk tabel apa pun

  2. Memeriksa beberapa kolom untuk satu nilai

  3. Bisakah kolom tabel dengan Kunci Asing menjadi NULL?

  4. Bagaimana cara mendapatkan hitungan setiap nilai berbeda dalam kolom?

  5. Bagaimana ClusterControl Mengonfigurasi IP Virtual dan Apa yang Diharapkan Selama Failover