Güvenle veritabanını sorgulamak için hazırlanmış deyimleri kullanarak

5 Cevap php

I versatile in the queries it is allowed to make, but also safe from injection bir fonksiyon yazmaya çalışıyorum. Aşağıdaki kodu olduğu gibi bir hata atar, ama ben yerine 'isim' ile çalıştırırsanız 'tarla' iyi çalışıyor.

$field = "name";
$value = "joe";

function selectquery($field, $value)
  {
  global $dbcon;

  $select = $dbcon->prepare('SELECT * FROM tester1 WHERE :field = :value');
  if($select->execute(array(':field' => $field, ':value' => $value)));
    {
    $row = $select->fetch();
    for ($i=0; $i<3; $i++)
      {
      echo $row[$i]."\n";
      }
    }  
  }

How would I allow the table/fields/values to be changed, without allowing injection attacks? mysql_real_escape_string () geriye tür bir adım gibi görünüyor. Herhangi bir fikir?

5 Cevap

Yanılmış olabilir, ama PDO'de parametre olarak alanları sağlayabilmektedir inanmıyorum.

Neden sadece işleve argüman olarak belirtmez? Kullanıcı tarafından besleniyor verilerin aksine, alanlar, iyi tanımlanmış sonlu ve sık sık değişmez. Gibi

selectquery('name',$value);

ve sorgu olmak var

$field = "name";
$value = "joe";

function selectquery($field, $value)
  {
  global $dbcon;

  $select=$dbcon->prepare("SELECT * FROM tester1 WHERE $field = :value");
  if($select->execute(array(':value' => $value)));
 //etcetera  

Eğer fonksiyonu kendiniz aramak için alan adını temin konum beri SQL enjeksiyonu ile kendinizi saldırı olacak endişeli değilseniz, bu güvenlidir.

Bazı garip nedenle alanın adı kullanıcı girişi geliyor ise, izin verilen alanlarda bir dizi yapabiliriz. Değerler sadece dizi gelebilir, çünkü bu şekilde, size enjeksiyon güvendeyiz. Belki bir API yapıyoruz sürece, alan adı kullanıcı girişi gelen olurdu neden bilmek ve böylece güvenilmeyen olmayın? Diğer akıllı hedefe ulaşmak için daha iyi bir yolu muhtemelen var.

Her neyse, bu tablo adları için bir beyaz liste kullanmak için potansiyel bir çözüm olurdu:

$field = "name";
$value = "joe";

$allowed_fields=array('name','other_name','sandwich');

function selectquery($field_name, $value)
  {
  global $dbcon,$allowed_fields;

  if(!in_array($field_name,$allowed_fields)){ return false; }
  else{ $field=$field_name; }

  $select=$dbcon->prepare("SELECT * FROM tester1 WHERE $field = :value");
  if($select->execute(array(':value' => $value)));
  //etcetera

Veritabanı tanımlayıcılar (sütun adları, tablo adları ve veritabanı adları) değil ve kaçtı olmamalı, bu nedenle sorguları hazırlanmış SQL bunları kullanmayın yapabilirsiniz.

Bazen olsa bu tanımlayıcıları backtick gerekebilir (` MySQL ve " SQLite için kullanılır).

Bir değişkeni Bağlama sorgu sözdizimi değişen özel prevent ona, veri olarak bağlar. Ayrıca, sabit bir sözdizimi sahip motorlar kez hazırlanmış sorguları analiz etmek ve sonra değerleri her set için hızlı bir şekilde çalıştırmanızı sağlar. Eğer, bir preg_replace ('/ \ W /','', $ alan) düşünmek gerekir eğer SQL üstüne bir el tutma tabakası oluşturmak için değil teşvik, ama olur.

Andrew Moore tepki seconding: gitmek için tek yoldur tanımlayıcı alıntı olduğunu ve PDO gerekli yöntem sunmaz. Mdb2 kullanmak yerine, sadece tanımlayıcı alıntı uygulanmasını ödünç almak isteyebilirsiniz. Işlevi, kendi ve hatalar için veteriner onu oldukça kolay yazmak mümkün olmalıdır yeterince basittir.

  1. (Sadece bir tane olabilir) parçaları bir liste halinde . üzerindeki giriş dize bölmek

  2. Her bölüm için:

    1. Tüm ` yerine ``.
    2. Bölüm boş sürece başlangıcına ve sonuna bir ` ekleyin. *
  3. Ile parçaları katılın ..

Bir örnek olarak, quote_identifier("one two.three") olmalıdır `one two`.`three` - oldukça basittir.

Ekstra güvenlik için de dize (özellikle nulls the MySQL docs bakınız) bile kote tanımlayıcılarda yasadışı herhangi bir karakter içeren ama gerçekte MySQL olanlar yakalamak gerekir olmadığını doğrulamak olabilir. MDB2 rahatsız etmiyor.

*, .columnname yasal ve .`columnname` ile alıntı olup ``.`columnname` gerektiği için, bu kontrol gereklidir.