it-swarm-tr.com

SQL enjeksiyon - neden kaçış tırnak artık güvenli değil?

Ham SQL

SQL yazarken - insan girdisini gerçekten alan herhangi bir şey için, enjeksiyondan kaçınmak için birçok şey yapıldı.

SQL enjeksiyonunu duyan herkes bilir ki (PHP örnek olarak kullanacağım) böyle bir şey yapmak güvenli değildir:

$sql = "SELECT * FROM `users` 
.  WHERE `userName` = "{$_POST["username"]}" 
.  AND `pass` = "{$_POST["pass"]}";";

Sihirli

Daha sonra elbette, birisi doğru şekilde sterilize edilmemiş ve kötü uygulamaların bir sonucu olarak doğrudan sql'e konulan program girdisi ile başa çıkmak için "sihirli kaçış alıntıları" kullanma fikriyle ortaya çıktı. Bu, SQL enjeksiyonu ile ilgili sorunu gerçekten çözmedi, ancak tüm kullanıcı girişlerinin karıştığı anlamına geliyordu.

Eğik çizgi ekleme

Yani, bazı insanlar sihirli alıntıları kapattı. Daha sonra, teorik olarak tüm tırnaklardan kaçan ve korsanınız ' OR 1=1 Yapamayan addslashes() aracılığıyla SQL noktasından önce kullanıcı girdisini ayrıştırdılar, ancak addslashes için bile kendi kendine söylediklerini söylediler addslashes kullanmamalısınız, mysql_real_escape_string() gibi veritabanına özgü işlevi kullandığını söylüyor, ancak bunun hala bazıları tarafından yeterli olmadığı söyleniyor.

Veritabanına özel eğik çizgi ekleme

Bu nedenle, DBMS'ye özgü *_real_escape_string Kullanamayız, add slashes Kullanamayız, "sihirli alıntılar" olayı birçok soruna neden oldu ve web gibi kısa ifadeli alıntılarla dolu :

"Özel bir hacker alıntı kaçan döngüler atlamak için bir yol bulacaksınız, sadece DBAL hazırlanan ifadeleri kullanın" - John Q herhangi bir programcı

Tamam, bu yüzden hazırla deyimler ve bir DBAL kullanmak için beni korkuttu. Gerçekten hiçbir şey açıklanmadı, ama kulağa hoş geliyor çünkü çok duydum.

Hazırlanan ifadeler

Şimdi PDO veya bir çerçeveden bir DBAL veya tüm sql'imizi saran ve birisinin sql enjeksiyonunu çalıştıramayacağından emin olan başka bir şey kullanıyoruz.

Sorum temel olarak bir "neden olmasın?", "Ne kullanmalıyım?" Değil. Web, bunu kullanmanızı veya bunu veya ne olursa olsun kullanmanız gerektiğini söyleyen insanlarla doludur, ancak bunların neden olması gerektiğine dair bir açıklama yoktur.

Doğrudan sorular

Sivri sorular (hatırlatma, SQL hakkında soruyorum, PHP SQL etrafında kötü temsilcisi nedeniyle örnek bir dildi, kavramlar evrenseldir):

  1. Neden "sihir" kullanarak tüm kullanıcı girdilerinden kaçamıyoruz?
  2. Addslashes neden "yeterince iyi" değildi?
  3. DB'ye özgü çıkış işlevlerini kullanmanın nesi yanlış ve neden eğik çizgi eklemekten daha iyi?
  4. Neden çerçeveler ve PDO ile hazırlanan ifadeler SQL'in altın standardı olarak selamlanıyor? Neden daha iyi? Neden bunlarla bir SQL enjeksiyonu yapamıyorum, daha önce bahsedilen araçlarla OLABİLİRİM? Bir programcı bir şekilde hala bunu berbat etmeyi başaramaz mı? Neye dikkat etmeliler?
  5. Ortaya koyamadığım başka endişeler var mı?
78
Incognito

Neden "sihir" kullanarak tüm kullanıcı girdilerinden kaçamıyoruz?

Sihir uygulandığında, verinin nerede biteceği bilinmiyor. Yani sihirli tırnaklar, veritabanına kaçmadan yazılmadığı sürece verileri yok ediyor.

Sadece istemciye geri gönderilen HTML yanıtında kullanılabilir. Tamamen doldurulmamış bir form düşünün ve bu nedenle kullanıcıya tekrar gösterilir. Sihirli alıntılarla, ilk denemede girilen veriler artık bir HTML sayfasında anlamsız olan SQL'den kaçacak. Daha da kötüsü: ikinci gönderimde veriler tekrar SQL'den çıkar.

Addslashes neden "yeterince iyi" değildi?

Çok baytlı karakterlerle ilgili sorunları var:

' 27
\ 5c
뼧 bf 5c

Bunlar iki bayt, ancak sadece bir Unicode karakter.

addslashes Unicode hakkında hiçbir şey bilmediğinden, bf 27 ila bf 5c 27. Bu Unicode kullanan bir program tarafından okunursa, 뼧 'olarak görülür. Boom.

Bu konunun http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string adresinde iyi bir açıklama var.

DB'ye özgü çıkış işlevlerini kullanmanın nesi yanlış ve neden eğik çizgi eklemekten daha iyi?

Bunlar daha iyidir çünkü kaçmanın verileri veritabanında olduğu gibi yorumlamasını sağlarlar (son soruya bakın).

Güvenlik açısından, bunları her bir veritabanı girişi için kullanırsanız sorun olmaz. Ama ikisini de bir yerlerde unutabilme riskiniz var.

Düzenleme : Getahobby eklendikçe: Veya, SQL deyimine tırnak işaretleri eklemeden ve gerçek sayıların girdinin uygun veri türüne dönüştürülmesi veya dönüştürülmesi /Düzenle

Yazılım geliştirme açısından bakıldığında kötüdürler çünkü diğer SQL veritabanı sunucu yazılımları için destek eklemeyi çok daha zorlaştırırlar.

Neden çerçeveler ve PDO ile hazırlanan ifadeler SQL'in altın standardı olarak selamlanıyor? Neden daha iyi?

PDO, yazılım tasarımı nedenleriyle çoğunlukla iyi bir şeydir. Diğer veritabanı sunucusu yazılımlarını desteklemeyi çok daha kolay hale getirir. Veritabanına özgü uyumsuzlukların birçoğunu soyutlayan nesne yönelimli bir arayüze sahiptir.

Neden bu [hazırlanmış ifadeler] ile bir SQL enjeksiyonu yapamıyorum, nerede daha önce belirtilen araçlarla OLABİLİRİM?

Hazırlanan ifadelerin " değişken parametreli sabit sorgu " kısmı burada önemli olan şeydir. Veritabanı sürücüsü, geliştirici hakkında düşünmek zorunda kalmadan otomatik olarak tüm parametrelerden kaçacaktır.

Parametreli sorguların, sözdizimsel nedenlerle kaçan parametrelerle normal sorguların okunması genellikle daha kolaydır. Çevreye bağlı olarak, biraz daha hızlı olabilirler.

Hazırlanan ifadeleri her zaman parametrelerle kullanmak, statik kod analiz araçları ile doğrulanabilecek bir şeydir. Xxx_escape_string'e eksik bir çağrı bu kadar kolay ve güvenilir bir şekilde görülmez.

Bir programcı bunu bir şekilde berbat etmeyi başaramaz mı? Neye dikkat etmeliler?

"Hazırlanan ifadeler", sabiti olduğunu gösterir. Dinamik olarak hazırlanmış ifadeler - özellikle kullanıcı girişi ile - tüm enjeksiyon sorunları hala var.

52

[1.] Neden "büyü" kullanarak tüm kullanıcı girdilerinden kaçamıyoruz?

Sihirli alıntılar iki açıdan kırıldığı için:

  1. $ _ (REQUEST/GET/POST) verilerinin tümü DB'ye girmez. Ve herhangi bir anlam ifade edebilmek için, girdiden kurtulmak zorundasınız.
  2. Bunlar addslashes eşdeğeri ([2.] ile ilgili notuma bakın), bu yüzden aslında güvenli değiller.

[2.] Addslashes neden "yeterince iyi" değildi?

addslashes kısıtlamasından kurtulmanın birçok yolu vardır, bu nedenle temelde kusurludur, ancak kullanmaya çalışın.

[3.] DB'ye özel kaçış işlevlerinin kullanımında yanlış olan nedir ve neden eğik çizgi eklemekten daha iyiydi?

Gerçekten hiçbir şey. Bu sadece PDO/hazırlanan neden "daha iyi" mantra. Kodlama da dahil olmak üzere birçok faktöre dikkat ettiklerinden, yoladdslashes 'den daha iyidir. İşte küçük bir sır; PDO bunları dahili olarak kullanır, ancak addslashes...

[4.] Çerçeveler ve PDO ile hazırlanan ifadeler neden SQL'in altın standardı olarak selamlanıyor? Neden daha iyi? Neden bunlarla bir SQL enjeksiyonu yapamıyorum, daha önce bahsedilen araçlarla OLABİLİRİM?

Onlar altın standart değil, onlar "daha fazla" güvenli değil DB'ye özgü işlevlerden daha ve siz SQL enjeksiyonu yapabilirsiniz bunlarla da. Ve hayır, uygun şekilde sterilize edilmiş girişle SQL enjeksiyonu yapamazsınız.

Tüm teknolojilerde olduğu gibi, geliştiriciler de "yeni" bir şey için dini (fanatik?) Eğilimler geliştirme eğilimindedir. Bu yüzden hazırlanmış Zend Certified Engineers ™ 'a hazırlanan ifadelere geçmenizi tavsiye etmiyorsunuz.

Gerçek şu ki, her şey ne yaptığınızı bilmeye bağlı. Bir makaleyi sayısal kimliğine göre yüklüyorsanız, herhangi bir kaçışa, hatta daha az PDO'ya ihtiyacınız yoktur. Sadece kimliğin gerçekten bir tamsayı olduğundan emin olmanız gerekir.

Daha gerçekçi bir perspektiften bakıldığında, genel kural PDO/hazırlanmış ifadeleri kullanmak değil, doğru işlevleri kullanmaktır, yani gerekir yerine mysql_real_escape_string() kullanın addslashes() veya mysql_escape_string().

[5.] Bir programcı bir şekilde bunu berbat etmeyi başaramaz mı? Neye dikkat etmeliler?

Elbette! Ama "neye dikkat etmeli" değil, "ne yaptığını bil".

Gördüğünüz gibi, eval($_GET['code']) * doğru yerde kullanıldığında tamamen yasaldır (local PHP Test Çalıştırıcısı gibi).

Koşullu bir sorguyu çalıştırmak için bir ORM kullanırsanız, kodu doğrudan girersiniz, bu nedenle doğru yapmazsanız SQL enjeksiyonu alma şansı olabilir (söz konusu ORM'ye bağlıdır). (Varsayımsal) Örnek:

// update() sets the value of a column given a condition
//
//                         .--escaping is automatic here
//                         |                           .--hypothetical SQL injection
//                         v                           v
Db()->update('name',$_GET['newname'])->where(' id = '.$_GET['id']);

(* Sadece sayısız profesyonellerin kafalarını bu şekilde vurduğunu hayal edebiliyorum)

13
Christian

Günün sonunda sorgularınızı korumak için giriş kaçması yapılmalıdır SQL Injection. PDO ve ADODB gibi parametreli sorgu kitaplıkları kaçan kullanır, tek yaptıkları bu uygulamayı örtük olarak güvenli bir şekilde uygulamaktır. Buna karşılık magic_quotes_gpc [~ # ~] [~ # ~] değil, bu temelde sorunlu bir yaklaşımdır.

1) Ne yaptığınızı anlamadıysanız kaçmak sorunlu olabilir. Magic_quotes_gpc etkinse bu tür sorunlar hala kullanılabilir.

mysql_query("select * from users where id=".addslashes($_GET[id]));

PoC Sömürüsü: http: //localhost/vuln.php? İd = uyku ( )

yama:

mysql_query("select * from users where id='".addslashes($_GET[id])."'");

Ders: Sql enjeksiyonundan yararlanmak için alıntı işaretlerine ihtiyacınız yok.

2) Sadece alıntı işaretlerinden kaçtığınızı söyleyelim:

mysql_query("select * from users where name='".htmlspecialchars($_GET[name],ENT_QUOTES)."' and id='".htmlspecialchars($_GET[id],ENT_QUOTES)."'");

PoC Sömürü: http: //localhost/vuln.php? Name = \& id = + veya + uyku (30)/*

Yama:

mysql_query("select * from users where name='".addslashes($_GET[name])."' and id='".addslashes($_GET[id])."'");

Ders : Ters eğik çizgiler, alıntı işaretleri kadar tehlikelidir .

3) Peki ya dil kodlaması?

mysql_query("SET CHARACTER SET 'gbk'");
mysql_query("select * from user where name='".addslashes($_GET[name])."'");

PoC Sömürü: http: //localhost/vuln.php? Name =% bf% 27 = uyku (30)/*

Yama:

mysql_query("SET CHARACTER SET 'gbk'");
mysql_query("select * from user where name='".mysql_real_escape_string($_GET[name])."'");

Sonuç:

Bir uygulamada sql enjeksiyonunu önlemek için kaçmak kesinlikle gereklidir. In PHP PDO ve ADOB kullanıcı giriş kaçan zorlayan büyük parametreli sorgu kütüphaneleridir.Sorun birçok programcı kaçan ne olduğunu anlamıyor. en iyi savunma yöntemidir, çünkü kaçan kuralları anlamanız gerekmez.

9
rook

DB'ye özel çıkış işlevleri hakkında. Mysql_real_escape_string () kullanılmasına rağmen SQL enjeksiyonunun gerçekleşebileceği birçok senaryo vardır. LIMIT ve ORDER BY gerçekten zor!

Bu örnekler SQL enjeksiyonuna karşı savunmasızdır:

$offset = isset($_GET['o']) ? $_GET['o'] : 0;
$offset = mysql_real_escape_string($offset);
$sql = "SELECT userid, username FROM sql_injection_test LIMIT $offset, 10";

veya

$order = isset($_GET['o']) ? $_GET['o'] : 'userid';
$order = mysql_real_escape_string($order);
$sql = "SELECT userid, username FROM sql_injection_test ORDER BY `$order`";

Her iki durumda da 'kapsüllemeyi korumak için kullanamazsınız.

kaynak : Beklenmeyen SQL Enjeksiyonu (Kaçış Yetmediğinde) <- Bunu okuyun

5
Cut Copy

Filtreler atlanabilir ve SQL deyimlerine giren veriler yalnızca kullanıcı girdisinden daha fazla yerden gelebilir. SQL'den etkilenen bir kaynağa/lavaboya giriş noktaları bir örnek olarak saklanabilir (daha yüksek dereceli), ancak açıkça HTTP GET parametreleri ve POST HTML formlarındaki parametreler tek kullanıcı yolu değildir) giriş.

Parametrelenmiş sorgular, SQL deyimlerinizi enjeksiyonlardan arındırmaz. Ayrıca değişken bağlama, dizi işlemlerinin/birleştirmenin kaldırılması ve çok çeşitli SQL yan tümcelerinde belirli güvenlik sorunlarının önlenmesi gerekir.

Çoğu geliştirici, üçüncü taraf bileşenlerini ve SQL enjeksiyon sorunları için diğer bağımlılıklarını da kontrol etmeyi unutur ve bazen bu eklemelerin kendi kodlarını savunmasız hale getirebileceğini fark etmez.

Yapılacak en iyi şey, uygulamalarınızı üretime hazır hale getirmek için bir uygulama güvenlik danışmanlığı şirketi kiralamak ve appdev ekip (ler) inizi uygulama güvenlik kontrollerini süreç ve geliştirme teknolojilerine dönüştürmek üzere eğitmektir.

4
atdre

Hendrick'in cevabını genişletmek için. Gerçek olmadığında real_escape_string'i sihirli bir mermi olarak düşünmek kolaydır. İnsanların intval kullanmak veya girdiyi bir tamsayıya dökmek istediklerinde kullandıklarını gördüm. Kaçış dizesini yanlış bağlamda kullanırsanız yine de enjekte edilebilir.

3
getahobby