MySQL için php kaçan tırnak. PHP'deki en yaygın SQL enjeksiyon modeli işe yaramaz karakter kaçışıdır.

(PHP 4> = 4.3.0, PHP 5)

mysql_real_escape_string - SQL deyiminde kullanılmak üzere bir dizedeki özel karakterlerden kaçar

Açıklama

mysql_real_escape_string (string $ unescaped_string [, kaynak $ link_identifier = NULL]): sicim

Bağlantının geçerli karakter kümesini hesaba katarak unescaped_string içindeki özel karakterlerden kaçar, böylece onu bir dizi içine yerleştirmek güvenli olur. mysql_query ()... Eğer ikili veri eklenecekse bu fonksiyon kullanılmalıdır.

mysql_real_escape_string() MySQL'in aşağıdaki karakterlere ters eğik çizgi ekleyen mysql_real_escape_string kitaplık işlevini çağırır: \ x00, \ n, \ r, \ , " , " ve \ x1a.

MySQL'e bir sorgu göndermeden önce verileri güvenli hale getirmek için bu işlev her zaman (birkaç istisna dışında) kullanılmalıdır.

Dikkat

Güvenlik: varsayılan karakter seti

Karakter seti, ya sunucu düzeyinde ya da API işleviyle ayarlanmalıdır. mysql_set_charset() etkilemesi için mysql_real_escape_string() ... Daha fazla bilgi için karakter kümeleriyle ilgili kavramlar bölümüne bakın.

parametreler

unescaped_string

Kaçınılması gereken dize.

Link_identifier

MySQL bağlantısı. Bağlantı tanımlayıcısı belirtilmemişse, tarafından açılan son bağlantı mysql_connect () varsayılır. Böyle bir bağlantı bulunamazsa, sanki bir tane oluşturmaya çalışacaktır. mysql_connect () hiçbir argüman olmadan çağrılmıştı. Herhangi bir bağlantı bulunamazsa veya kurulmazsa, bir E_UYARI seviye hatası üretilir.

Dönüş değerleri

Kaçan dizeyi döndürür veya YANLIŞ hata üzerine.

Hatalar / İstisnalar

Bu işlevi bir MySQL bağlantısı olmadan yürütmek de E_UYARI seviye PHP hataları. Bu işlevi yalnızca geçerli bir MySQL bağlantısı varken yürütün.

Örnekler

Örnek # 1 Basit mysql_real_escape_string() örnek

// Bağlamak
$ link = mysql_connect ("mysql_host", "mysql_user", "mysql_password")
VEYA die (mysql_error());

// Sorgu
$ sorgu = sprintf ( "SELECT * FROM users WHERE user ="% s "VE password ="% s "",
mysql_real_escape_string ($ kullanıcı),
mysql_real_escape_string ($ şifre));
?>

Örnek # 2 mysql_real_escape_string() bir bağlantı örneği gerektirir

Bu örnek, bu işlev çağrılırken bir MySQL bağlantısı yoksa ne olacağını gösterir.

Yukarıdaki örnek şuna benzer bir çıktı verecektir:

Uyarı: mysql_real_escape_string (): 5. satırda /this/test/script.php içinde böyle bir dosya veya dizin yok Uyarı: mysql_real_escape_string (): 5. satırda /this/test/script.php içinde sunucuya bir bağlantı kurulamadı bool (yanlış) dize (41) "SELECT * FROM aktörlerden WHERE last_name =" ""

Örnek # 3 Örnek bir SQL Enjeksiyon Saldırısı

// $ _POST [" şifre "] kontrol etmedik, kullanıcının istediği herhangi bir şey olabilir! Örneğin:
$ _POST ["kullanıcı adı"] = "aidan";
$ _POST ["şifre"] = "" VEYA "" = "";

// Herhangi bir eşleşen kullanıcı olup olmadığını kontrol etmek için veritabanını sorgula
$ sorgu = ($ _POST ["kullanıcı adı"]) "VE şifre =" ($ _POST ["şifre"]) "";
mysql_query ($ sorgu);

// Bu, MySQL'e gönderilen sorgunun şöyle olacağı anlamına gelir:
yankı $ sorgusu;
?>

MySQL'e gönderilen sorgu:

Bu, herkesin geçerli bir şifre olmadan oturum açmasına izin verir.

Notlar

Kullanmadan önce bir MySQL bağlantısı gereklidir mysql_real_escape_string() aksi halde seviye hatası E_UYARI oluşturulur ve YANLIŞ Geri döndü. link_identifier "t tanımlı değilse, son MySQL bağlantısı kullanılır.

Not: mysql_real_escape_string() kaçmaz % ve _ ... Bunlar, birleştirilirse MySQL'deki joker karakterlerdir. SEVMEK, HİBE, veya GERİ ÇEKMEK.

8 yıl önce

Orijinal mysql_real_escape_string'i taklit eden ancak aktif bir mysql bağlantısına ihtiyaç duymayan küçük bir fonksiyon. Bir veritabanı sınıfında statik bir fonksiyon olarak uygulanabilir. Umarım birisine yardımcı olur.

function mysql_escape_mimic ($ giriş) (
if (is_array ($ inp))
dizi_haritasını döndür (__METHOD__, $inp);

If (! Boş ($ giriş) && is_string ($ giriş)) (
return str_replace (dizi ("\\", "\ 0", "\ n", "\ r", "" "," "", "\ x1a"), dizi ("\\\\", "\ \ 0 "," \\ n "," \\ r "," \\ "", "\\" "," \\ Z "), $ inp);
}

$ girişini döndür;
}
?>

13 yıl önce

mysql_real_escape_string'in belgelerde belirtildiği gibi "\ x00, \ n, \ r ve ve \ x1a'ya ters eğik çizgi eklemediğini, ancak karakteri sorgular için MySQL tarafından kabul edilebilir bir temsille değiştirdiğini unutmayın (örn. \ n, "\ ile değiştirilir" (\," ve "belgelendiği gibi kaçarlar) Bu, bu işlevi nasıl kullanmanız gerektiğini değiştirmez, ama bence bilmek güzel.

6 yıl önce

Herkese, yorumlanmış kod oluşturmak için temelde asla harici girdi kullanmamanız gerektiğini söylemeden, kaçış tartışması tamamlanmış sayılmaz. Bu, SQL ifadeleri veya herhangi bir tür "değerlendirme" işlevini çağıracağınız herhangi bir şey için geçerlidir.

Bu nedenle, bu çok bozuk işlevi kullanmak yerine, bunun yerine parametrik olarak hazırlanmış ifadeleri kullanın.

Dürüst olmak gerekirse, SQL ifadeleri oluşturmak için kullanıcı tarafından sağlanan verileri kullanmak profesyonel ihmal olarak düşünülmeli ve parametrik olarak hazırlanmış ifadeleri kullanmadığınız için işvereniniz veya müşteriniz tarafından sorumlu tutulmalısınız.

Bu ne anlama geliyor?

Bunun gibi bir SQL ifadesi oluşturmak yerine şu anlama gelir:

"X (A) DEĞERLERİNE EKLE (". $ _ POST ["a"]. ")"

Şuna benzeyen bir ifadeyi yürütmek için mysqli "s ready() function () işlevini kullanmalısınız:

"X (A) DEĞERLERİNE (?) EKLE"

Not: Bu, asla dinamik SQL ifadeleri oluşturmamanız gerektiği anlamına gelmez. Bunun anlamı, bu ifadeleri oluşturmak için asla kullanıcı tarafından sağlanan verileri kullanmamanız gerektiğidir. Kullanıcı tarafından sağlanan tüm veriler, ifade edildikten sonra ifadeye parametre olarak iletilmelidir. hazırlanmıştır.

Bu nedenle, örneğin, küçük bir çerçeve oluşturuyorsanız ve istek URI'sine dayalı bir tabloya ekleme yapmak istiyorsanız, $ _SERVER [" REQUEST_URI "] değerini (veya herhangi bir parçası) ve bunu doğrudan sorgunuzla birleştirin.Bunun yerine, $ _SERVER ["REQUEST_URI"] değerinin istediğiniz kısmını ayrıştırmalı ve bunu bir tür işlev veya ilişkisel dizi aracılığıyla kullanıcı olmayan bir diziyle eşleştirmelisiniz. Sağlanan değer Eşleme herhangi bir değer üretmiyorsa, kullanıcı tarafından sağlanan verilerde bir sorun olduğunu bilirsiniz.

Bunu takip etmemek, parametrik olarak hazırlanmış ifadeler kullanmasına rağmen, Ruby On Rails çerçevesinde bir takım SQL enjeksiyon problemlerinin nedeni olmuştur. GitHub bir noktada bu şekilde saldırıya uğradı. Bu nedenle, hiçbir dil bu soruna karşı bağışık değildir. Bu nedenle, bu genel bir en iyi uygulamadır ve PHP'ye özgü bir şey değildir ve neden onu GERÇEKTEN benimsemeniz gerekir.

Ayrıca, parametrik olarak hazırlanmış ifadeler kullanırken bile, kullanıcılar tarafından sağlanan verilerin bir tür doğrulamasını yapmalısınız. Bunun nedeni, kullanıcı tarafından sağlanan verilerin genellikle oluşturulan bazı HTML'nin bir parçası haline gelmesi ve kullanıcı tarafından sağlanan verilerin tarayıcıda güvenlik sorunlarına neden olmayacağından emin olmak istemenizdir.

9 yıl önce

Örnek # 2'de SQL enjeksiyonu ile ilgili ilginç bir tuhaflık var: AND, OR'a göre önceliklidir, bu nedenle enjekte edilen sorgu aslında WHERE (user =" aidan "AND password =" ") OR" "=" " olarak yürütülür. rasgele bir kullanıcı adına karşılık gelen bir veritabanı kaydı döndürmek (bu durumda "aidan"), aslında TÜM veritabanı kayıtlarını döndürür.Belirli bir sırayla. Bu nedenle, bir saldırgan herhangi bir hesapla oturum açabilir, ancak herhangi bir hesapla oturum açması gerekmez. hangi hesap üzerinde kontrol.

Elbette, potansiyel bir saldırgan, ilgili belirli kullanıcıları hedeflemek için parametrelerini değiştirebilir:

// Örneğin. saldırganın değerleri
$ _POST ["kullanıcı adı"] = "";
$ _POST ["şifre"] = "" VEYA kullanıcı = "yönetici" VE "" = "";

// Hatalı biçimlendirilmiş sorgu
$ sorgu = "SEÇ * KULLANICILARDAN NEREDE kullanıcı ="$ _POST [kullanıcı adı] "VE şifre =" $ _POST [şifre] "";

yankı $ sorgusu;

// MySQL'e gönderilen sorgu şunu okur:
// SELECT * FROM users WHERE user = "" AND password = "" VEYA user = "yönetici" AND "" = "";
// herkesin "yönetici" adlı hesaba erişmesine izin verecek

?>

1 yıl önce

@feedr
Notunu şu şekilde detaylandırdım:
$ string = "asda \ 0sd \ x1aas \\\\\\\\ dasd \" asdasd \ na \ "\" sdasdad ";
$ dizi1 = dizi ("\\\\\\\\", "\ 0", "\ n", "\ r", "" "," "", "\ x1a");
$ dizi2 = dizi ("\\\\\\\\\\\\\\\\", "\\\ 0", "\\\ n", "\\\ r", "\\\" "," \\\ "", "\\\ Z");
yankı ($ dize);
yankı (PHP_EOL);
için ($ ben = 0; $ ben eğer ($ ben == 0)
$p = "/ (?Başka
$p = "/ (?yankı ($ ben);
yankı ($p);
yankı ($ dizi2 [$ ben]);
$ dize = preg_replace ($ p, $ dizi2 [$ i], $ dize);
yankı ("\ t");
yankı ($ dize);
yankı (PHP_EOL);
}
yankı (PHP_EOL);
yankı ($ dize);

2 yıl önce

Numb Safari'de Sam'den Alıntı Yapmak

["Hiçbir kaçış tartışması, herkese yorumlanmış kod oluşturmak için temelde asla harici girdi kullanmamanız gerektiğini söylemeden tamamlanmış sayılmaz. Bu, SQL ifadeleri veya herhangi bir "değerlendirme" işlevini çağıracağınız herhangi bir şey için geçerlidir.

Bu nedenle, bu çok bozuk işlevi kullanmak yerine, bunun yerine parametrik olarak hazırlanmış ifadeleri kullanın.

Dürüst olmak gerekirse, SQL ifadeleri oluşturmak için kullanıcı tarafından sağlanan verileri kullanmak profesyonel ihmal olarak kabul edilmeli ve parametrik olarak hazırlanmış ifadeleri kullanmadığınız için işvereniniz veya müşteriniz tarafından sorumlu tutulmalısınız. "]

Selim haklı ........

Bununla birlikte, tüm sterilize etmeyi durdurmanın ve görevi sadece parametrik olarak hazırlanmış ifadelere aktarmanın mantıklı olduğunu düşünmüyorum.

Belirli bir durumda çalışan belirli bir geliştirici, geçerli girdi hakkında her zaman daha fazla bilgi sahibi olacaktır (bu bağlama özel).

Bir kullanıcıdan, daha önce vermiş olduğunuz bir değeri iletmesini isterseniz ve tüm bu değerlerin AB ****** ile başladığını ve dizenin 7 veya 11 uzunluğunda olması gerektiğini, ancak asla başka bir uzunlukta olmaması gerektiğini bilirsiniz. iyi bir ön temizleyicinin temeli - bir dizenin izin verilen farklı uzunlukları eski verileri gösterebilir.

Kötü niyetli bir kullanıcının bir form aracılığıyla geçirmiş olabileceği çöpleri asla parametrik hazırlanmış ifadelere iletmek istemem, her zaman önce kendi akıl sağlığı kontrollerimi yapmak isterim ve bazı durumlarda bunlar dikkatli ve yanlış olabilir. sadece Veritabanı işlemini tamamen iptal etmeyi seçin.

Bu şekilde DB'm güvenli hale getirilmiş güvenli olmayan ifadelerle tıkanmaz - daha iyi olan tıkanmaz.

Katmanlarda güvenlik - temizlik ve doğrulama, hazırlanan ifadeleri kullanmadan ÖNCE her durumda dikkate alınmalıdır.

Ek olarak, resmi belgeyi okuyabildiğim kadarıyla
==============================================

"Kaçış ve SQL enjeksiyonu

Bağlı değişkenler, sorgudan ayrı olarak sunucuya gönderilir ve bu nedenle sorguya müdahale edemez. Sunucu, deyim şablonu ayrıştırıldıktan sonra bu değerleri doğrudan yürütme noktasında kullanır. Sorgu dizesinde hiçbir zaman doğrudan değiştirilmedikleri için bağlı parametrelerden çıkış yapılmasına gerek yoktur "

Bu bana, geçersiz kılmayla değil, alternatif ele alma yoluyla içsel tehlikelerden kaçınıldığını gösteriyor.

Bu, hazırlanmış ifadelere tamamlanmamış dönüşüme sahip büyük bir projenin, bir organizasyonun farklı bölümlerindeki eski kodun veya birbiriyle konuşan sunucuların, kötü haberi bağışık bir konumdan veya durumdan bağışık olmayan bir duruma geçirebileceği anlamına gelir.

Sanitasyon, ek risklere maruz kalmadan yetkin bir şekilde gerçekleştirildiği sürece, kişisel olarak belirli temizlik katmanlarına bağlı kalır ve ardından hazırlanan ifadeleri çağırırdım.


İlk olarak, bu eğik çizgilere neden ihtiyaç duyulduğu hakkında biraz.
Sorgudaki herhangi bir veriyi değiştirirsek, bu verileri SQL komutlarından ayırt etmek için tırnak içine alınmalıdır.
Örneğin, yazarsanız
SEÇ * NEREDE tablodan isim = Fatura
daha sonra baz, Bill'in başka bir alanın adı olduğuna karar verecek, onu bulamayacak ve bir hata verecektir. Bu nedenle, değiştirilen veriler (bu durumda, Fatura adı) tırnak işaretleri içine alınmalıdır - o zaman taban, değeri ad alanına atanması gereken bir dize olarak kabul eder:
SEÇ * NEREDE tablodan isim = "Fatura"
Bununla birlikte, alıntılar verilerin kendisinde de bulunabilir. Örneğin,
SEÇ * NEREDE tablodan isim = "D" Artagnan "
Burada veritabanı "D" nin veri olduğuna karar verecek ve Artagnan bilmediği bir komuttur ve ayrıca bir hata verecektir. Bu nedenle, veri tabanında bulunan tırnakların (ve diğer bazı özel karakterlerin) verilere atıfta bulunduğunu veritabanına açıklamak için tüm verileri geçmek gerekir.
Sonuç olarak, hatalara neden olmayacak doğru bir istek alacağız:
SEÇ * NEREDE tablodan isim = "D \" Artagnan "

Böylece, bir sorguya veri koyarken iki kurala uymanız gerektiğini öğrendik:
- sorguya eklenen tüm veriler tırnak içine alınmalıdır (tek veya çift, ancak tek daha uygun ve daha sık kullanılır).
- tüm dize değişkenlerinde özel karakterlerden eğik çizgi ile çıkılmalıdır.

Özel olarak not edilmelidir: eklenen eğik çizgiler tabana GİRMEZ. Bunlara yalnızca istekte ihtiyaç duyulur. Veritabanına girerken, eğik çizgiler atılır. Buna göre, bir veritabanından veri alınırken şerit çizgileri kullanmak yaygın bir hatadır.

Aslında, yukarıdakilerin tümü dize verileri ve tarihleri ​​için geçerlidir. Rakamlar, yanıp sönmeden ve tırnak içine alınmadan eklenebilir. Eğer bunu yaparsan GEREKLİ! sorguya eklemeden önce verileri istenen türe zorlayın, örneğin:
$ kimlik = iç değer ($ kimlik);
Bununla birlikte, basitlik (ve güvenilirlik) için, dizelerde olduğu gibi sayılarla da çalışabilirsiniz (çünkü mysql onları doğru türe dönüştürmeye devam edecektir). Buna göre, talebe eklenen tüm verileri izleyecek ve ekleyeceğiz.

Ayrıca, bir kural daha var - isteğe bağlı, ancak hatalardan kaçınmak için buna uyulmalıdır:
Alanların ve tabloların adları tek tırnak içine alınmalıdır - "` "(bu karaktere sahip tuş, standart klavyede" 1 "tuşunun solunda bulunur) Sonuçta, alan adı mysql ile çakışabilir anahtar kelimeler, ancak geri alıntıyı kullanırsak, MySQL her şeyin doğru olduğunu anlayacaktır:
'tablodan' NEREDE' tarih'ten * SEÇİN = "2006-04-04"
Bu tırnak işaretleri arasında ayrım yapmak ve birini diğeriyle karıştırmamak gerekir. Ayrıca backticks'in eğik çizgi ile kaçmadığı da unutulmamalıdır.

Böylece, veriyi talebe nasıl doğru bir şekilde yerleştireceğimizi öğrendik.
ANCAK! Dinamik sorgu oluşturma, veri değiştirme ile sınırlı değildir. Sıklıkla SQL komutlarını ve alan adlarını sorguda değiştirmemiz gerekir. Ve burada zaten güvenlik konusuna geçiyoruz:

SQL Injection, komut dosyasına iletilen veriler, bu komut dosyasında oluşturulan sorgunun amaçlanandan tamamen farklı bir şekilde yürütülmeye başlayacağı şekilde değiştirildiğinde bir bilgisayar korsanı saldırısıdır.
Bu tür saldırılara karşı korunma kuralları iki noktaya ayrılabilir:
1. Verilerle çalışma.
2. İsteğin kontrol öğeleriyle çalışma.

İlk noktayı yukarıda ayrıntılı olarak ele aldık. O, denebilir ki, aslında, koruma değildir. Sorguya veri ekleme kurallarına uygunluk, her şeyden önce SQL SYNTAX gereksinimleri tarafından belirlenir. Ve bir yan etki olarak, bilgisayar korsanlığına karşı korumamız da var.

İkinci nokta çok daha karmaşıktır, çünkü veri için böyle bir evrensel kural yoktur - bir geri tepme, alan adını bir bilgisayar korsanı tarafından değiştirilmesinden hiçbir şekilde korumayacaktır. Tablo adlarını, SQL deyimlerini, LIMIT komut parametrelerini ve diğer deyimleri tırnak içinde alıntılamak mümkün değildir.
Bu nedenle, bir sorguda kontrolleri değiştirirken temel kural şudur:
SQL ifadelerini veya alan adlarını, veritabanlarını, tabloları bir sorguda dinamik olarak değiştirmeniz gerekiyorsa, bunlar hiçbir koşulda doğrudan sorguya eklenmemelidir.
Bu tür eklemeler için tüm seçenekler, komut dosyanızda GELİŞMİŞ olarak yazılmalı ve kullanıcının girdiğine göre seçilmelidir.
Örneğin, bir alanın adını operatöre göre siparişe iletmeniz gerekiyorsa, hiçbir durumda doğrudan değiştirmemelisiniz. Önce kontrol etmeliyiz. Örneğin, bir geçerli değerler dizisi oluşturun ve bunu yalnızca iletilen parametre bu dizide mevcutsa istekte değiştirin:
$ siparişler = dizi ("isim", "fiyat", "adet");
$ anahtar = array_search ($ _GET ["sıralama"], $ siparişler));
$ sipariş = $ sipariş [$ anahtarı];
$ sorgu = "SEÇ * `tablodan` SİPARİŞLE $ orderby";
Kullanıcı tarafından daha önce açıklanan seçenekler dizisinde girilen bir kelimeyi ararız ve bulursak dizinin karşılık gelen öğesini seçeriz. Eğer eşleşme bulunamazsa dizinin ilk elemanı seçilir.
Böylece, kullanıcının girdiği değil, komut dosyamızda yazılanlar istekte değiştirilir.
Diğer tüm durumlarda da aynısını yapmalısınız.
Örneğin, WHERE yan tümcesi dinamik olarak oluşturulmuşsa:
if (! boş ($ _ GET ["fiyat"])) $ nerede. = "fiyat =" ".mysql_real_escape_string ($ _GET [" fiyat "])." "";
$ sorgu = "SELECT * FROM` tablosundan` NEREDE $ nerede ";
Tablo adının sorguda dinamik olarak değiştirilebileceği bir durumu hayal etmek benim için zor, ancak bu olursa, ad yalnızca komut dosyasında önceden yazılmış kümeden de eklenmelidir.
LIMIT operatörünün parametreleri, aritmetik işlemler veya intval () işlevi kullanılarak bir tamsayı türüne zorlanmalıdır.
Burada listelenen örneklerin dinamik sorgu oluşturmaya yönelik tüm seçenekleri tükettiğini düşünmeyin. Sadece prensibi anlamanız ve bu gibi tüm durumlarda uygulamanız gerekir.

LIKE operatörü ile çalışmanın özellikleri
Tamamen ayrı bir durum LIKE operatörüdür.
İlk olarak, normal eğik çizgilere ek olarak, LIKE ile değiştirilen değişkenlerde eğik çizgiler iki katına çıkarılmalıdır. Diğer bir deyişle, değişken \ karakterini içeriyorsa, iki katına çıkarılmalı ve ardından mysql_real_escape_string aracılığıyla olağan akışı gerçekleştirilmelidir.
Örneğin, dizeyi arıyorsak
\'ye "ters eğik çizgi" denir ve tam bir eşleşmeye ihtiyacımız var, o zaman sadece mysql_real_escape_string kullanıyoruz ve sorgu standart:
SELECT * FROM test WHERE alanı = "karakter \\ denir \" ters eğik çizgi \ "" Bu dizgiyi LIKE'da değiştirmek istiyorsak, önce her eğik çizgiyi iki ile değiştirmemiz ve ardından mysql_real_escape_string uygulamamız gerekiyor. Sonuç olacak
SELECT * FROM tablo NEREDE "% karakter \\\\ GİBİ alan \" ters eğik çizgi \ "%" olarak adlandırılır
İkinci olarak, eğik çizgi ekleme işlevlerinin hiçbirinin LIKE operatöründe kullanılan "%" ve "_" arama meta karakterlerine eğik çizgi eklemediğini unutmayın. Bu nedenle, bu operatörü kullanıyorsanız ve _ ve % sembollerinin maske olarak kullanılmasını istemiyorsanız, eğik çizgileri manuel olarak ekleyin. Bu komutla yapılabilir
$ data = addCslashes ($ data, "% _"); Dikkat - bu lashes değil! Bu işlevin adında ek bir "c" vardır.

Böylece LIKE operatöründe kullanılan değişkenleri ayrı ayrı işlememiz gerektiği ortaya çıkıyor.
önce aşağıdaki kodu kullanarak bir eğik çizgiyi iki ile değiştirin:
$ var = str_replace ("\\", "\\\\", $ var); sonra (talebe giren diğer tüm verilerle birlikte yapabilirsiniz), şunu keseriz:
$ var = mysql_real_escape_string ($ var); ve sonra, _ ve %'nin tam olarak kendileriyle eşleşmesini istiyorsak,
$ var = addCslashes ($ var, "_%");
Sonuç olarak, örneğin böyle bir dize ararsak
\ "ters eğik çizgi" olarak adlandırılır ve _ karakteri "alt çizgi" olarak adlandırılır daha sonra işlendikten sonra, istekte şöyle görünmelidir:
"% karakteri \\\\, \" ters eğik çizgi \ "olarak adlandırılır ve \ _, \" alt çizgi \ " olarak adlandırılır Yani, başlangıçta satırdaki eğik çizgi dört katına çıktı. Karakterlerin geri kalanı her zamanki gibi çıktı. Artı - alt çizgi karakteri parladı.

Eğik çizgiler hakkında. Onlardan nasıl kurtulurum
İngilizce ters eğik çizgiden eğik çizgi veya ters eğik çizgi, anlaşılmaz bir şekilde değişkenlerinizde aniden kendiliğinden görünen bir ters eğik çizgidir ("\"). Bazı özel karakterlere eklenir, ancak çoğunlukla alıntılardan dolayı fark edilir.
Bu, genellikle barındırmada varsayılan olarak etkinleştirilen özel PHP ayarları nedeniyle olur. Teorik olarak, bu ayarlar veritabanıyla çalışan komut dosyalarının güvenliğini artırabilir. Pratikte, eğik çizgilerin otomatik olarak eklenmesi, hem bir veritabanıyla çalışırken hem de yokluğunda genellikle kafa karışıklığına ve uygunsuzluğa neden olur.
Aşağıda bu iki durumu ayrıntılı olarak tartışacağız.

Toplu olarak "sihirli alıntılar" olarak adlandırılan php.ini yönergeleri, eğik çizgilerin otomatik olarak eklenmesinden sorumludur:
magic_quotes_gpc ve magic_quotes_runtime Birincisi etkinleştirilirse, PHP, kullanıcıdan alınan verilere - POST, GET istekleri ve tanımlama bilgilerinin yanı sıra (HTTP Yetkilendirmesi yoluyla alınan oturum açma adı ve parolaya) otomatik olarak eğik çizgi ekler.
İkincisi ise, komut dosyasının yürütülmesi sırasında elde edilen verilere eğik çizgiler eklenir - örneğin, bir dosya veya veritabanından.

Veritabanı olmadan çalışıyorsanız veya bir veritabanı ile doğru çalışıyorsanız (aşağıda anlatılacaktır), fazladan eğik çizgiler sadece sizi rahatsız eder ve bunlardan kurtulmanız gerekir. Otomatik eklemeyi devre dışı bırakmanın en kolay ve en doğru yolu PHP ayarlarındadır.
Bu, erişiminiz varsa php.ini'deki ilgili yönergeleri düzelterek veya sitenin son dizininde bir .htaccess dosyası oluşturup satırları ekleyerek yapılabilir.
php_flag magic_quotes_gpc 0
php_flag magic_quotes_runtime 0

Bu şekilde devre dışı bırakamazsanız, gelen verileri eğik çizgilerden temizlemek için değişen derecelerde karmaşıklıkta kod yazmanız gerekecektir. (Ancak, PHP ayarlarına bağlı olmayan taşınabilir bir uygulama yazmak istiyorsanız, yine de yazmanız gerekir. Ve scriptlerinizin başında ayrı bir bloğa ekleyin).

Çalışma sırasında elde edilen veriler, ele alınması en kolay olanıdır: betiğin başına yazmak yeterlidir.
set_magic_quotes_runtime (0); Kullanıcıdan alınan veriler için her şey çok daha karmaşıktır. Bu kod için iki fonksiyona ihtiyacımız var:

  • get_magic_quotes_gpc işlevini kullanarak PHP'nin eklenip eklenmediğini kontrol edebilirsiniz.
  • stripslashes eğik çizgileri kaldırır.
    Buna göre, ilkinin yardımıyla kontrol etmeniz gerekir ve eğer PHP onu eklediyse, gelen tüm değişkenleri yineleyin ve ikincisinin yardımıyla temizleyin.
    register_globals = off ile düzgün çalışıyorsanız, tarayıcıdan gelen verileri içeren tüm dizilere şerit çizgileri uygulamak yeterlidir.
    Örneğin, tüm site komut dosyalarına aşağıdaki kodu ekleyebilirsiniz:
    fonksiyon şeritleri (& $ el) (
    if (is_array ($ el))
    foreach ($ el as $ k => $ v)
    şeritler ($el [$ k]);
    else $ el = eğik çizgiler ($ el);
    }
    if (get_magic_quotes_gpc()) (
    şeritler ($ _GET);
    şeritler ($ _POST);
    şeritler ($ _COOKIE);
    şeritler ($ _REQUEST);
    if (isset ($ _ SERVER ["PHP_AUTH_USER"])) şeritler ($ _SERVER ["PHP_AUTH_USER"]);
    if (isset ($ _ SERVER ["PHP_AUTH_PW"])) şeritler ($ _SERVER ["PHP_AUTH_PW"]);
    }
    Yanlış register_globals ayarları durumunda, kabul edilebilir bir çözüm bulmak hiç de zor olacaktır, bu yüzden - tekrar ediyorum - hemen doğru ayarlarla çalışmak daha iyidir.

    Uyarılar

    • "Sihirli alıntılara" güvenmemenizin nedenleri arasında bir tane daha var. Pek olası değil ama yine de. "Sihirli alıntılar" aslında iki yönerge değil, üç yönergedir. Üçüncüsü magic_quotes_sybase'dir. Eğik çizgi yerine tırnak işareti eklemekle kalmaz, aynı zamanda magic_quotes_gpc'nin etkisini de iptal eder. Eğer bir mucize eseri bu direktiflerin her ikisi de "on" statüsüne sahipse, o zaman sonuncusu çalışmayacak! Yani, "sihirli alıntılara" güvenerek, bu durumda, yanlış oluşturulmuş sorguların tüm zevklerini alacağız. Genel olarak, tamamen teorik olarak, bu yönergenin mevcudiyeti dikkate alınmalıdır, çünkü aynı zamanda böyle bir sürpriz de getiriyor ... slashes ve stripslashes işlevlerinin davranışını değiştirmek! magic_quotes_sybase = açıksa, bu işlevler sırasıyla eğik çizgi yerine tek bir alıntı eklemeye ve kaldırmaya başlar.
    • Verilen tüm örnekler sadece Mysql veritabanı içindir. Sorgu oluşturmaya yönelik özel kurallar, diğer VTYS'ler için farklılık gösterebilir, ancak genel ilke aynı kalır:
      • veritabanı veya bir üçüncü taraf kitaplığı ile çalışmak için API sağlarsa sorgu oluşturmak için özel işlevler, ve bunları kullanma olasılığı vardır, o zaman her şeyden önce bunları kullanmak gerekir.
      • böyle bir işlev yoksa, bu DBMS için özel karakterlerden kaçma işlevi için belgelere bakmalısınız.
    Not: formlar
    Formların giriş etiketlerinde değer çıktısı alırken, eğik çizgiler yardımcı olmaz.
    Tüm metni böyle bir alanda görüntülemek için, değer tırnak içine alınmalıdır, ve çıkış verilerine htmlspecialchars () işlevini uygula
    Örnek:

    Ayrıca (bunun tırnaklar ve eğik çizgilerle hiçbir ilgisi olmamasına rağmen), tarayıcıya genel olarak doğrulanmamış bir kullanıcıdan alınan tüm veriler görüntülenirken htmlspecialchars işlevinin uygulanması gerektiğine dikkat edilmelidir. Bu neden yapılmalı, istek üzerine Google'da XSS güvenlik açığının ne olduğunu okuyabilirsiniz.
    phpfaq.ru tarafından
  • tırnak işaretleri dizisi (11)

    Sorgu yazmanın en iyi yolunu bulmaya çalışıyorum. Tutarlı olmanın önemini de anlıyorum. Şimdiye kadar, gerçek bir düşünce olmadan yanlışlıkla tek tırnak, çift tırnak ve ters tik kullandım.

    $ sorgu = "INSERT INTO tablosu (id, sütun1, sütun2) DEĞERLER (BOŞ, değer1, değer2)";

    Ayrıca, yukarıdaki örnekte, "tablo", "sütun [n]" ve "val [n]" değişkenlerinin olabileceğini göz önünde bulundurun.

    Bunun standardı nedir? Ne yapıyorsun?

    Yaklaşık 20 dakikadır benzer soruların cevaplarını okuyorum ama bu sorunun kesin bir cevabı yok gibi.

    Yanıtlar

    Şimdi, MySQL sorgunuzda doğrudan gönderi değişkenini kullandığınızı varsayalım, ardından bunu şu şekilde kullanın:

    $ sorgu = "INSERT INTO` tablo` (`kimlik`,` isim`, `email`) DEĞERLER (" ". $ _ POST [" id "]." "," ". $ _ POST [" isim "] ." "," ". $ _ POST [" e-posta "]." ")";

    Bu, MySQL'de PHP değişkenlerini kullanmak için en iyi uygulamadır.

    Çoğunlukla Mysql'de bu tür tanımlayıcılar `,", "ve () sorgularında kullanılır.

      "veya", dizeyi "01-26-2014 00:00:00" veya "01-26-2014 00:00:00" değeri olarak dahil etmek için kullanın. Bu tanımlayıcı yalnızca "26-01-2014 00:00:00" satır işlevi için kullanılır, örneğin şimdi () veya toplam, maks.

      `bir tablo veya tablo tablosu eklemek için kullanın, örneğin tablo_adı'ndan sütun_adı seçin burada id =" 2 "

      () yalnızca bir sorgunun bölümlerini basitçe içine almak için kullanılır, örneğin tablo_adı'ndan sütun_adı seçin burada (id = "2" ve cinsiyet = "erkek") veya name = "rakesh.

    Tüm (iyi açıklanmış) yanıtların dışında, aşağıda belirtilenlerden hiçbiri yoktu ve bu Soru-Cevap'a sık sık katkıda bulunuyorum.

    Kısaca; MySQL matematik yapmak istediğini düşünüyor kendi tablonuza / sütununuza yerleştirin ve "e-posta" gibi kısa çizgileri e-posta olarak yorumlayın.

    Sorumluluk reddi. Bu yüzden, veritabanlarıyla çalışmaya tamamen yeni olanlar ve daha önce açıklanan teknik terimleri anlayamayanlar için bunu bir “Bilginize” yanıtı olarak ekleyeceğimi düşündüm.

    (Yukarıda SQL sorunuzun doğasıyla ilgili iyi cevaplar var, ancak bu, PHP'de yeniyseniz de alakalı olabilir.)

    PHP'nin tek ve çift tırnakları farklı şekilde ele aldığını belirtmek önemli olabilir ...

    Tek tırnaklı dizeler "değişmez değerlerdir" ve epeyce WYSIWYG dizesini temsil eder. Çift tırnaklı dizeler olası değişken ikamesi için PHP tarafından yorumlanır (PHP'deki geri referanslar tam olarak dizeler değildir, kabukta bir komut yürütür ve sonucu döndürür).

    $foo = "bar"; echo "bir $ foo var"; // Bir $ foo yankısı var "bir $ foo var"; // Bir çubuk var echo `ls -l`; // ... bir dizin listesi

    Tablolar sütunlar ve değerler değişken ise, iki yol vardır:

    Çift tırnak "" ile tam sorgu:

    $ sorgu = "INSERT INTO $ tablo_adı (id, $ sütun1, $ sütun2) DEĞERLER (BOŞ," $ değer1 "," $ değer2 ")";

    $ sorgu = "GİRİŞE GİR". $ tablo_adı. "(id,". $ sütun1. ",". $ sütun2. ") DEĞERLER (BOŞ," ". $ değer1." "," ". $ değer2." " )";

    Tek tırnak "" ile:

    $ sorgu = "GİRİŞE GİR". $ tablo_adı. "(id,". $ sütun1. ",". $ sütun2. ") DEĞERLER (NULL,". $ değer1. ",". $ değer2. ")";

    Sütun / değer adı MySQL'e ayrılmış bir anahtar kelime gibi göründüğünde geri keneleri kullanın.

    Not. Tablo adıyla bir sütun adı belirtiyorsanız, aşağıdaki gibi geri tikler kullanın:

    "tablo_adı". "sütun_adı"<- Примечание: исключить. из задних клещей.

    Geri dönüş işaretleri, tablo ve sütun tanımlayıcıları için kullanılmalıdır, ancak yalnızca tanımlayıcı, MySQL'e ayrılmış bir anahtar kelime olduğunda veya tanımlayıcı, sınırlı kümenin dışında boşluklar veya karakterler içerdiğinde gereklidir (aşağıya bakın). Tırnak işaretleri sorununu önlemek için mümkünse sütun veya tablo tanımlayıcıları olarak ayrılmış anahtar kelimeleri kullanmaktan kaçınmak genellikle iyi bir fikirdir.

    Dize değerleri için, örneğin DEĞERLER () listesinde tek tırnak kullanılmalıdır. Çift tırnaklar MySQL tarafından dize değerleri için de desteklenir, ancak tek tırnaklar diğer RDBMS'ler tarafından daha yaygın olarak kabul edilir, bu nedenle çift tırnak yerine tek tırnak kullanmak iyi bir fikirdir.

    MySQL ayrıca DATE ve DATETIME değişmez değerlerinin "2001-01-01 00:00:00" gibi dizeler olarak tek tırnaklara sahip olmasını bekler. Daha fazla bilgi için, özellikle tarih dizelerinde segment ayırıcı olarak kısa çizgi kullanmanın alternatifleri için tarih ve saat literatür belgelerine bakın.

    Bu nedenle, örneğinizi kullanarak, PHP dizesini iki kez yayınlar ve "val1", "val2" değerleri için tek tırnak kullanırdım. NULL, MySQL anahtar sözcüğüdür ve özel (olmayan) bir değerdir ve bu nedenle kullanılmaz.

    Bu tablo veya sütun kimliklerinin hiçbiri ayrılmış kelimeler değildir veya alıntı yapılacak karakterleri kullanmaz, ancak yine de onları geriye doğru alıntıladım (daha sonraları ...).

    RDBMS ile ilgili işlevler (MySQL'deki NOW () gibi), argümanları daha önce bahsedilen aynı alıntı veya alıntı kurallarına uysa da alıntı yapılmamalıdır.

    Backtick (`) tablo ve sütunu ┬──┬───────┐ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ $ sorgu = " INSERT INTO "table" (` id`, `col1`,` col2`, `date`,` update`) DEĞERLER (BOŞ, "değer1", "değer2", "2001-01-01", ŞİMDİ ())"; Alıntılanmayan anahtar kelime ─────┴┴┴┘ │ │ │ │ │ │ │││││ Tek tırnaklı (") karakter dizileri ──────────┴────── ┴────┘ │ │ │││││ Tek tırnaklı (") TARİH ───────────────────────── ─ ───────┘ │││││ Alıntılanmamış işlev ───────────────────────────── ─────┴┴┴┴┘

    Değişken enterpolasyon

    Değişkenler için alıntılama kalıpları değişmez, ancak değişkenleri doğrudan bir dizgede enterpolasyon yapmak istiyorsanız, PHP'de çift tırnak içine alınmalıdır. SQL'de doğru şekilde kullanmak için değişkenlerden kaçındığınızdan emin olun. (Bunun yerine SQL enjeksiyonuna karşı bir savunma olarak hazırlanmış deyimleri destekleyen bir API kullanılması önerilir.)

    // Bazı değişken değiştirmelerle aynı şey // Burada, bir değişken tablo adı $ tablosu ters tırnaklı ve DEĞERLER listesindeki değişkenler // tek tırnaklı $ sorgu = "INSERT INTO `$ tablo`(`id`,` sütun1`, `sütun2`,` tarih`) DEĞERLER (BOŞ, "$ val1", "$ val2", "$ tarih")";

    Hazırlanan ifadeler

    Hazırlanan ifadelerle çalışırken, dolgu ifadelerinin dahil edilip edilmeyeceğini belirlemek için belgelere bakın. PHP, PDO ve MySQLi'de bulunan en popüler API'ler yetkisiz diğer dillerdeki çoğu hazırlanmış API ifadeleri gibi yer tutucular:

    // Adlandırılmış parametrelere sahip PDO örneği, tırnak içine alınmamış $ sorgu = "INSERT INTO` tablo` (`id`,` sütun1`, `sütun2`,` tarih`) DEĞERLER (: id,: sütun1,: sütun2,: tarih) " ; // MySQLi örneği ile? parametreler, tırnaksız $ sorgu = "INSERT INTO` tablo` (`id`,` sütun1`, `sütun2`,` tarih`) DEĞERLER (?,?,?,?) ";

    Tanımlayıcılarda geri başvuru döndüren semboller:

    Örneğin:

    Aynısı tablo adları ve alan adları için de yapılabilir. Bu çok iyi alışkanlık, veritabanı kimliğinizi arka pencerelerle bağlarsanız.

    Geri izleme hakkında daha fazla bilgi edinmek için bu yanıta göz atın.

    Şimdi Çift tırnak ve Tek Tırnak hakkında (Michael bundan daha önce bahsetmişti).

    Ancak değeri tanımlamak için tek veya çift tırnak kullanmanız gerekir. Başka bir örnek görelim.

    INSERT INTO `tablename` (` id, `title`) DEĞERLER (NULL, title1);

    Burada başlık1'i tırnak içine almayı kasten unuttum. Sunucu şimdi başlık1'i sütun adı (yani kimlik) olarak kabul edecektir. Bu nedenle, bunun bir değer olduğunu belirtmek için çift veya tek tırnak kullanmanız gerekir.

    INSERT INTO `tablename` (` id, `title`) DEĞERLER (NULL," title1 ");

    Şimdi, PHP ile birleştirildiğinde, çift tırnak ve tek tırnak, sorgunuzu yazmayı çok daha kolay hale getiriyor. Sorunuzdaki sorgunun değiştirilmiş versiyonuna bir göz atalım.

    $ sorgu = "INSERT INTO` tablo` (`id`,` sütun1`, `sütun2`) DEĞERLER (BOŞ," $ değer1 "," $ değer2 ")";

    Şimdi, PHP'de çift tırnak kullanarak, $ val1 ve $ val2 değişkenlerini değerlerini kullanacak şekilde yapacaksınız, böylece geçerli bir sorgu oluşturacaksınız. sevmek

    $ val1 = "benim değerim 1"; $ val2 = "benim değerim 2"; $ sorgu = "INSERT INTO` tablo` (`id`,` sütun1`, `sütun2`) DEĞERLER (BOŞ," $ değer1 "," $ değer2 ")";

    INSERT INTO `table` (` id`, `col1`,` col2`) DEĞERLER (NULL, "benim değerim 1", "değerim 2")

    Burada, genellikle iki noktada son bulan pek çok yardımcı cevap var.

    1. BACKTICKS (`) tanımlayıcı adları etrafında kullanılır.
    2. ONE QUOTES (") değerlerin etrafında kullanılır.

    Ve @MichaelBerkowski'nin dediği gibi

    Geri dönüş işaretleri, tablo ve sütun tanımlayıcıları için kullanılmalıdır, ancak yalnızca tanımlayıcı, MySQL'e ayrılmış bir anahtar kelime olduğunda veya tanımlayıcı, sınırlı kümenin dışında boşluklar veya karakterler içerdiğinde gereklidir (aşağıya bakın). Tırnak işaretleri sorununu önlemek için mümkünse sütun veya tablo tanımlayıcıları olarak ayrılmış anahtar kelimeleri kullanmaktan kaçınmak genellikle iyi bir fikirdir.

    Tanımlayıcının bulunamadığı bir durum var ayrılmış anahtar kelime veya içerir boşluk karakterleri veya sınırlı kümenin dışındaki karakterler, ama kesinlikle etraflarında geri bağlantı gerektirir.

    123E10 geçerli bir tanımlayıcı adıdır, ancak aynı zamanda geçerli bir INTEGER değişmezidir.

    [Ayrıntılara girmeden, böyle bir tanımlayıcı adı nasıl elde edersiniz], Diyelim ki 123456e6 adında geçici bir tablo oluşturmak istiyorum.

    Geri tepmelerde HATA yoktur.

    DB> geçici tablo `123456e6` (` id` char (8)); Sorgu Tamam, 0 satır etkilendi (0,03 sn)

    Geri arama kullanmıyorsanız HATA.

    DB> 123451e6 geçici tablosunu oluştur (`id` karakter (8)); HATA 1064 (42000): SQL sözdiziminizde bir hata var; 1. satırda "123456e6 (` id` char (8))) " yakınında kullanılacak doğru sözdizimi için MariaDB sunucu sürümünüze karşılık gelen kılavuza bakın

    Ancak, 123451a6 iyi bir tanımlayıcı adıdır (geri tik yok).

    DB> geçici tablo 123451a6 (`id` char (8)); Sorgu Tamam, 0 satır etkilendi (0,03 sn)

    Bunun nedeni, 1234156e6'nın da üstel bir sayı olmasıdır.

    Dize değerleri için, örneğin DEĞERLER () listesinde tek tırnak kullanılmalıdır.

    Backtick'ler genellikle bir tanımlayıcıyı belirtmek için kullanılır ve ayrıca ayrılmış anahtar kelimelerin yanlışlıkla kullanılması nedeniyle güvenli olabilir.

    PHP ve MySQL birleştirildiğinde, çift tırnak ve tek tırnak, sorgu yazma süresini büyük ölçüde basitleştirir.

    MySQL'de iki tür alıntı vardır:

    1. "dize değişmezlerini dahil etmek için
    2. `tablo ve sütun adları gibi tanımlayıcıları dahil etmek için

    Ve sonra "bu özel bir durum. bir sql_mode sunucusunun sql_mode'una bağlı olarak bir seferde yukarıdaki hedeflerden:

    1. Varsayılan"karakter", dize değişmezlerini iç içe geçirmek için kullanılabilir "
    2. ANSI_QUOTES modunda, tanımlayıcıları dahil etmek için bir karakter kullanılabilir, ANSI_QUOTES

    Aşağıdaki sorgu, SQL moduna bağlı olarak farklı sonuçlar (veya hatalar) üretecektir:

    WHERE foo = "bar" tablosundan "sütun" SEÇİN

    ANSI_QUOTES devre dışı bırakıldı

    Sorgu, foo sütununun "bar" dizesine eşit olduğu değişmez "sütun" dizesini seçecektir.

    ANSI_QUOTES etkinleştirildi

    Sorgu, foo'nun sütuna eşit olduğu sütun sütununu seçecektir.

    Ne zaman kullanılır

    • Kodunuzun SQL modlarına bağlı olmaması için "kullanmaktan kaçınmanızı öneririm.
    • Her zaman kimlikleri ekleyin, çünkü bu iyi bir uygulamadır (SO hakkında birkaç soru bunu tartışır)

    "" ve "" kullanımı arasında açık bir ayrım vardır.

    Boyunca "" kullanıldığında, "dönüşüm veya çeviri" yoktur. Olduğu gibi yazdırır.

    "" ile ne çevrilirse çevrilsin kendi değerine "çevrilir veya dönüştürülür".

    Çeviri/dönüştürme ile şunu kastediyorum: tek tırnak içinde yer alan hiçbir şey değerlerine "çevrilmeyecek". Tırnak içinde oldukları için kabul edilecektir. Örnek: a = 23, ardından echo "$ a" standart çıktıda $ a üretecektir. Oysa echo "$ a" standart çıktıda 23 üretecektir.

    İşimin doğası gereği, web uygulamalarının kaynak kodunun güvenlik denetimlerini yapmak zorundayım.
    Çok sayıda web uygulaması ve çok sayıda kod...

    SQL enjeksiyonlarının en yaygın sunucu tarafı web uygulaması güvenlik açığı olduğu bir sır değil. Bu tür şeylerin neredeyse tamamen hariç tutulduğu platformlar ve çerçeveler vardır, örneğin, ORM "ohm ve diğerleri. Ancak istatistikler bize ısrarla basit birleştirilmiş SQL sorgularıyla İnternet'teki web uygulamalarının mutlak yaygınlığını söyler. ORM, örneğin, yalnızca ifade parametrelerinin değil, aynı zamanda operatör düzeyinde sorgu mantığının kendisinin de kullanıcı verilerine bağlı olması gerektiğinde genel olarak uygulanabilir.

    Öyleyse başlayalım.

    Yararsız karakter kaçıyor
    PHP web uygulamalarının %83'ünde SQL enjeksiyonuna karşı savunmasız bulundu
    gibi karakter çıkış işlevlerini uygulama
    mysql_escape_string
    mysql_real_escape_string
    ekler
    tırnak işaretleri olmadan. Çoğu zaman kendini sayısal parametrelerde gösterir (her türlü * _id).
    Örnek
    $ sql = "Kullanıcıyı NEREDE kullanıcı listesinden SEÇ kullanıcı kimliği =". mysql_real_escape_string ($ _ GET ["uid"]);

    Görünüşte güvenli kod, ancak yalnızca görünüşte. Uygulamamda PHP'de en sık görülen SQL enjeksiyon modelinin içeri girdiği yer burasıdır. Bu güvenlik açığına saldırmak için, bir saldırganın saldırı vektöründe "" \ x00 \ r \ n \ x1a karakterlerini kullanmaması yeterlidir.
    Örneğin:
    /index.php?uid=-777 UNION şifreyi kullanıcı listesinden SEÇ

    Kodda ara
    Dilin semantiği ile karmaşıktır. Basit bir arama için egrep kullanılabilir:
    egrep -Rin "(seçin | güncelle | ekle | sil | değiştir). * ('den | ayarla | içine). * (mysql_escape_string | mysql_real_escape_string | lashes)". | grep -v "[\" "] [" \ "]"

    Arama ifadesinin mantığı şu şekildedir - filtreleme işlevlerinin solunda tırnak işareti ("", "", "", "") olmayan tüm dizeleri bulun. Yöntem elbette %100'den uzaktır, ancak anlamsal analiz yapmak için düzenli ifadeyi zorunlu kılmak imkansızdır.
    Bilgileri görüntüleme kolaylığı için, konsolda işlevi renkli olarak vurgulayabilirsiniz:
    egrep -Rin "(seçin | güncelle | ekle | sil | değiştir). * ('den | ayarla | içine). * (mysql_escape_string | mysql_real_escape_string | lashes)". | grep -v "[\" "] [" \ "]" | egrep --color "(mysql_escape_string | mysql_real_escape_string | lashes)"

    Bu standart güvenlik açığına karşı korunmak için, tipe göre tahmin kullanmak en iyisidir.
    Her türlü filtreleme ve taramadan her zaman daha hızlı ve daha güvenilir çalışır.
    Yukarıdaki örnek için yama şu şekilde olabilir:
    $ sql = "userlist FROM kullanıcı listesinden WHERE userid =". intval ($ _ GET ["uid"]);

    Bu, kısa taslağı tamamlar. Tüm web geliştiricilerini bu tür yapılar için kaynaklarını temizlemeye teşvik ediyorum. Daha da iyisi, yukarıdaki arama komut dosyasını insanlar için genişletin.