PHP mysql_real_escape_string () veritabanı adını korur?

7 Cevap php

I know that mysql_real_escape_string()
prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a

Ben bu bir yerde yan tümcesinde bir değişken gibi bir şey içine enjeksiyon bir sorgu nasıl koruduğunu biliyorum. Ama burada ben emin değilim bir senaryo:

$query = "SELECT * FROM $db WHERE 1";

If $db is taken from a user input, then the user could insert something like:
$db = 'RealDatabase WHERE 1; DELETE FROM RealDatabase WHERE 1; SELECT FROM RealDatabase';

From my understanding, mysql_real_escape_string() would not affect this string, making the final query: $query = "SELECT * FROM RealDatabase WHERE 1; DELETE FROM RealDatabase WHERE 1; SELECT FROM RealDatabase WHERE 1";

veritabanını silin hangi. Ben habersiz başka bir koruma seviyesi var mı?

7 Cevap

Aradığınız koruma seviyesi ile sağlanır backticks:

"SELECT * FROM `$db` WHERE 1";

Backticks için kullanılan qualify identifiers aksi takdirde belirsiz olabilir (yani MySQL reserved words) ve kullanıcı girişi kabul eden veya değişken-adlandırılmış sütunları veya veritabanları var ise, kesinlikle backticks kullanmalısınız, ya da ben size ileride sorun haline çalıştırırsanız söz verebilirim. Örneğin, ne geçici bir alan adı bazı kullanıcı girişi ile oluşturulmuş bir sistem olsaydı, sadece sona erdi adlı varlık update? Alanını çıktı

"SELECT field1,field2,update FROM table;"

Bu sefil başarısız olur. Ancak;

"SELECT `field`,`field2`,`update` FROM table"

gayet güzel çalışıyor. (Bu aslında bu sorunu vardı ben bir kaç yıl önce üzerinde çalıştığı bir sistemden gerçek bir örnektir).

Bu kötü SQL koyarak açısından sorunu çözer. Örneğin, aşağıdaki sorgu sadece bir "bilinmeyen sütun" hata dönmek, nerede test; DROP TABLE test enjekte saldırı kodu:

"SELECT * FROM `test; DROP TABLE test`;"

Be careful though: SQL Injection is still possible with backticks!

Örneğin, $db değişken had a backtick in it, hala normal bir şekilde bazı SQL enjekte edebilir bu verileri içeriyorsa. Veritabanı ve alan adları için değişken verileri kullanarak yapıyorsanız, sizin deyimi içine koyarak, ve sonra bir kez içinde ters tırnakların ile eleme önce tüm ters tırnakların soymak gerekir.

$db = str_replace('`','',$db);
$sql = "SELECT * FROM `$db` WHERE 1";

Ben veri sanitasyon ve veritabanı tanımlayıcılarını hijyen için ayrı işlevlere sahip bir veritabanı sarıcı kullanmak, ve bu son yaptığı budur :)

Eğer gerçekten SQL sorguları bağlayıcı içine bakmak gerekir.

Bu temelde all SQL enjeksiyon sizi koruyacaktır. Bu aşağı kaynar:

(PHP.net alınan)

$stmt = mssql_init('NewUserRecord');

// Bind the field names
mssql_bind($stmt, '@username',  'Kalle',  SQLVARCHAR,  false,  false,  60);

// Execute
mssql_execute($stmt);

Ve PHP temelde tüm veritabanları üzerinde binded sorguları desteği vardır. Oh ve tabii ki hala tüm girdileri ve olmalıdır çıkışı (ekran).

More info: - http://php.net/manual/en/function.mssql-bind.php

Hayır, mysql_real_escape_string burada size yardım edecek değildir. Fonksiyonu bağlam-duyarlı (herhangi bir içeriği yoktur, çünkü olamaz) değildir ve bu tamamen farklı bir tehdittir modelidir.

Sen git ve sunucusuna doğrudan kullanıcı girilen tablo adını göndererek olmadan, tablo var olduğunu doğrulamak gerekir. En iyi çözüm use a server-side array/look-up table containing the table names they are allowed to use etmektir. Onlar orada değil bir şey kullanmaya çalışırsanız, o zaman onlara izin vermeyin.

Eğer gerçekten tablo TÜM gerekiyorsa, o zaman sadece "ne tablolar var?" Sunucu sorabilirsiniz ama şans, sonunda size daha sonra etrafında karıştırmak istemiyorum bir tablo olacak, ve size gereken - ve onun çıkış (isteğe bağlı, her zaman sunucu isteyen önlemek için belli bir süre için önbelleğe alma) ile çalıştırmak Neyse dizi şeyi kullanmak çok ileriye gitmek ve bunu.

Bunun yerine get sorguda veritabanı adı ekleme veritabanı isimleri ve kimlikleri ayrı bir tablo yapabilirsiniz. Sonra sorguya sadece id append. Sonra o kimliği için gelen veritabanı adını aramak ve kullanabilirsiniz. Daha sonra alınan id (is_numeric) sayısal ve ayrıca kullanıcı sadece listenizde olan veritabanlarından seçebilirsiniz emin olabilirsiniz emin olabilirsiniz.

(Ayrıca bu veritabanlarının isimlerini bulmaya ve muhtemelen başka sitenizde bir SQL enjeksiyonu bunları kullanmak açmalarını önler.)

Ilk yöntemi kullanarak size sorguda kullanmadan önce veritabanı adı ayrıştırmak ve hiçbir boşluk içerdiğinden emin olun.

Tablo adları boşluk karakterleri kabul etmiyoruz, sadece onları şerit. Yani yukarıdaki $ DB RealDatabaseWHERE1;DELETEFROMRealDatabase.... olur. Bu tür sorgu geçersiz, fakat kusur önleyecektir.

Eğer 'hackish' şeyler bu tür, sadece bunu önlemek istiyorsanız explode(' ', $db) o olsun sonuç dizinin [0]. Bu ilk bölümü (RealDatabase) ve başka bir şey olsun istiyorum.

Eğer şüpheli veri kullanılan herhangi bir zaman kullanmak onun sadece iyi. Eğer tablo kendinizi belirterek ve kurcalama için oda varsa, onu kaçmak için gerek yoktur. Kullanıcıların potansiyel bir sorgu olarak çalıştırmak alabilir şey karar varsa, o kaçış.

Eğer gerçekten sizin veritabanı için kullanıcı (kötü kötü kötü) bir get kullanmanız gerekiyorsa, o kodlama aşağıdaki stil kullanabilirsiniz ...

$realname = '';
switch ($_GET['dbname']){
    case 'sometoken' : $realname = 'real_name'; break;
    case 'sometoken1' : $realname = 'real_name1'; break;
    case 'sometoken2' : $realname = 'real_name2'; break;
    case 'sometoken3' : $realname = 'real_name3'; break;
    case 'sometoken4' : $realname = 'real_name4'; break;
    case default : die ('Cheeky!!!');
}

$query = "SELECT * FROM `{$realname}` WHERE 1";

ya da seçenek olarak ...

$realname = $tablenames[$_GET['dbname']];

if (!$realname)
    die ('Cheeky!!!');

Bu 2 yol veya benzer bazı kodlama kullanarak beklenmedik değerlerden girişinizi koruyacaktır.

Ayrıca kullanıcının, bilgi anlaması mümkün olabilir, gerçek tablo veya veri tabanı adlarını görmek geçmez demektir.

Emin aksi uyarılar ihraç edilecek ilk geçerli bulunuyor yapmak için $ _GET ['dbname'] içeriğini kontrol emin olun.

Ben hala bu çok kötü bir tasarım olduğunu söylemek, kullanıcıların bir dosya sağlamak için izin ve onay olmadan I / O fonksiyonları aracılığıyla o geçen anımsatır. Bu sadece çok güvensiz düşünün.

Güvenlik tembellik kural izin için çok önemlidir.