Htmlspecialchars ve mysql_real_escape_string enjeksiyon benim PHP kodu güvenli tutmak mı?

5 Cevap php

Bugün erken saatlerde bir soru input validation strategies in web apps ile ilgili istendi.

Üst cevap yazma anda, PHP sadece htmlspecialchars ve mysql_real_escape_string kullanarak göstermektedir.

Benim soru: bu her zaman yeterli mi? Daha biz bilmeli var mı? Bu fonksiyonları Nerede yıkmak mı?

5 Cevap

Bu veritabanı sorguları gelince, her zaman denemek ve hazırlanmış parameterised sorguları kullanın. mysqli ve PDO kütüphaneler bu destek. Bu gibi mysql_real_escape_string gibi kaçış fonksiyonlarını kullanarak daha sonsuz güvenlidir.

Evet, mysql_real_escape_string etkili sadece bir dize kaçan fonksiyonudur. Bu sihirli bir değnek değildir. Bunu yapacak hepsi tek bir sorgu dizesinde kullanmak güvenli olabilmesi için de tehlikeli karakterleri kaçış. Eğer önceden girişleri sterilize yoksa Ancak, o zaman bazı saldırı vektörleri savunmasız olacaktır.

Aşağıdaki SQL düşünün:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

You should be able to see that this is vulnerable to exploit.
Imagine the id parameter contained the common attack vector:

1 OR 1=1

Orada kodlamak için orada hiçbir riskli karakter var, bu yüzden düz kaçan filtreden geçecek. Bizi terk:

SELECT fields FROM table WHERE id= 1 OR 1=1

Which is a lovely SQL injection vector and would allow the attacker to return all the rows. Or

1 or is_admin=1 order by id limit 1

ki üretir

SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1

Hangi saldırganın bu tamamen kurgusal örnekte ilk yöneticinin ayrıntıları dönebilirsiniz.

Bu işlevler yararlı iken, bunlar dikkatle kullanılmalıdır. Tüm web girişler bir dereceye kadar doğrulanmış olduğundan emin olmak gerekir. Bu durumda, biz bir sayı olarak kullandığınız bir değişken, aslında sayısal olup olmadığını kontrol etmedi çünkü biz istismar edilebilir görüyoruz. PHP Yaygın olarak, yüzen, girişler tam sayı olduğu alfanümerik vb kontrol fonksiyonları bir dizi kullanmak Ama SQL geldiğinde, hazır deyimi çoğu değerini dikkate almalıdır. Veritabanı fonksiyonları 1 OR 1=1 geçerli bir hazır olmadığı bilinmektedir olurdu gibi bir hazır deyimi ise Yukarıdaki kod güvenli olurdu.

Htmlspecialchars'dan gelince (). Bu kendi başına bir mayın tarlası bulunuyor.

Farklı html ilgili kaçan fonksiyonların bir bütün seçim var PHP gerçek bir sorun, ve ne yapacağını tam olarak hangi işlevleri üzerinde net bir kılavuz yoktur.

Eğer bir HTML etiketinin içine iseniz Öncelikle, gerçek sorun bulunmaktadır. Bakmak

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

Biz bir HTML etiketinin içine zaten konum, bu yüzden gerek yok < veya> tehlikeli bir şey yapmak. Bizim saldırı vektörü sadece olabilir javascript:alert(document.cookie)

Şimdi çıkan HTML gibi görünüyor

<img src= "javascript:alert(document.cookie)" />

Saldırı düz aracılığıyla alır.

Bu kötüleşiyor. Neden? htmlspecialchars (bu şekilde çağrıldığında) sadece çift tırnak ve tek değil kodlar çünkü. Biz Yani eğer

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

Bizim kötü Saldırgan artık yepyeni parametreleri enjekte edebilir

pic.png' onclick='location.href=xxx' onmouseover='...

bize verir

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

Bu durumda, sihirli bir mermi sadece bir girdiyi kendinizi santise zorunda var. Denemek ve kötü karakterler filtre eğer kesinlikle başarısız olur. Bir beyaz liste yaklaşım ve sadece iyi karakter geçsin. Farklı vektörler olabilir nasıl örnekler için XSS cheat sheet Bak

HTML etiketleri dışında htmlspecialchars ($ string) kullansanız bile, hala çok bayt charset saldırı vektörleri açıktır.

Eğer olabilir en etkili şöyle mb_convert_encoding ve htmlentities bir arada kullanmaktır.

$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');

Hatta bu çünkü UTF kolları şekilde, IE6 savunmasız bırakır. IE6 kullanım düşüyor kadar Ancak, bu tür ISO-8859-1 olarak daha sınırlı bir kodlama, geri düşebilir.

Cheekysoft mükemmel cevap ek olarak:

  • Evet, onlar güvende tutmak, ama onlar alışık Yalnızca kesinlikle doğru olacaktır. Yanlış onları kullanın ve hala savunmasız olacaktır, ve (örneğin veri bozulması için) başka sorunlar olabilir
  • (Yukarıda belirtildiği gibi) yerine Parametrelenmiş sorguları kullanın. Sen mesela aracılığıyla kullanabilirsiniz PDO veya PEAR DB gibi bir sargı vasıtasıyla
  • Magic_quotes_gpc ve magic_quotes_runtime her zaman kapalı ve yanlışlıkla bile kısa, açık olsun asla emin olun. Bu güvenlik sorunları önlemek için PHP geliştiricileri tarafından erken ve derin yanlış girişim vardır (veri yok eder)

Orada HTML enjeksiyon (örneğin, cross site scripting) önlenmesi için bir gümüş kurşun değil gerçekten, ama sen HTML çıktısı için bir kütüphane ya da çiftleşmiş sistemi kullanıyorsanız eğer daha kolay elde etmek mümkün olabilir. Uygun şeyler kaçmak için nasıl bunun için belgeleri okuyun.

HTML, işler bağlamında bağlı olarak farklı kaçtı gerekir. Bu Javascript içine konuyor dizeleri özellikle doğrudur.

Ben kesinlikle yukarıdaki mesajlar ile kabul edeceğini, ama özellikle, Cheekysoft cevabı için cevapta eklemek için küçük bir şey var:

When it comes to database queries, always try and use prepared parameterised queries. The mysqli and PDO libraries support this. This is infinitely safer than using escaping functions such as mysql_real_escape_string.

Yes, mysql_real_escape_string is effectively just a string escaping function. It is not a magic bullet. All it will do is escape dangerous characters in order that they can be safe to use in a single query string. However, if you do not sanitise your inputs beforehand, then you will be vulnerable to certain attack vectors.

Aşağıdaki SQL düşünün:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

You should be able to see that this is vulnerable to exploit. Imagine the id parameter contained the common attack vector:

1 OR 1 = 1

There's no risky chars in there to encode, so it will pass straight through the escaping filter. Leaving us:

SELECT fields FROM table WHERE id = 1 OR 1=1

Ben bir sayı değil bir şey çıkarmaz benim veritabanı sınıfının koymak hızlı bir küçük işlevini kodlanmış. Bu preg_replace kullanır, bu yüzden biraz daha optimize fonksiyon bozuklukları var, ama bir çimdik çalışır ...

function Numbers($input) {
  $input = preg_replace("/[^0-9]/","", $input);
  if($input == '') $input = 0;
  return $input;
}

Bunun yerine kullanarak

$result = "SELECT fields FROM table WHERE id = ".mysqlrealescapestring("1 OR 1 = 1");

Ben kullanmak istiyorum

$result = "SELECT fields FROM table WHERE id = ".Numbers("1 OR 1 = 1");

ve güvenli bir şekilde sorguyu çalıştırmak istiyorum

Id = 111 tabloda SELECT alanlar

Tabii, bu sadece doğru satır görüntülenmesini durdu, ama o ;) sitenize sql enjekte çalışıyor herkes için büyük bir sorun olduğunu sanmıyorum

Bu bulmacanın önemli bir parçası bağlamlarda. Eğer sorgudaki her argümanı alıntı eğer kimliği olarak "1 OR = 1 1" gönderme Birisi bir sorun değildir:

SELECT fields FROM table WHERE id='".mysql_real_escape_string($_GET['id'])."'"

Hangi sonuçlar:

SELECT fields FROM table WHERE id='1 OR 1=1'

hangi faydasızdır. Eğer dize kaçıyorlar yana, giriş dizesi bağlamda patlak olamaz. Ben MySQL versiyonu 5.0.45 kadarıyla bu test ettik, ve bir tamsayı sütun için bir dize bağlamı kullanarak herhangi bir sorun yaratmaz.

$result = "SELECT fields FROM table WHERE id = ".(INT) $_GET['id'];

Daha iyi 64 bit sistemlerde, iyi çalışır. Gerçi çok sayıda adresleme üzerinde sistem sınırlamalar dikkat, ancak veritabanı kimlikleri için bu zaman büyük% 99 çalışır.

Siz de kendi değerlerini temizlemek için tek bir işlev / yöntem kullanılarak yapılmalıdır. Bu fonksiyon mysql_real_escape_string için sadece bir sarıcı (olsa bile). Neden? Bir gün olduğunda bir veriyi temizleme tercih ettiğiniz yöntemi istismar bulundu çünkü sadece o değil, bir sistem çapında bulmak ve değiştirmek fazla yer, güncelleme var.