Node.js'de SQL enjeksiyonunu önleme


88

Node.js'de (tercihen bir modülle) SQL enjeksiyonlarını, PHP'nin bunlara karşı korunan Hazırlanmış İfadeler yaptığı gibi önlemek mümkün müdür?

Öyleyse nasıl? Değilse, verdiğim kodu atlayabilecek bazı örnekler nelerdir (aşağıya bakın).


Bazı Bağlamlar:

Node-mysql modülünü kullanarak Node.js + MySql'den oluşan arka uç yığınına sahip bir web uygulaması yapıyorum . Kullanılabilirlik açısından, modül harika, ancak henüz PHP'nin Hazırlanmış İfadelerine benzer bir şey uygulamadı (yine de yapılacak işin üzerinde olduğunun farkındayım ).

Anladığım kadarıyla, PHP'nin hazırlanmış ifadeleri uygulaması, diğer şeylerin yanı sıra, SQL enjeksiyonlarının önlenmesine büyük ölçüde yardımcı oldu . Yine de, node.js uygulamamın, varsayılan olarak sağlanan dizge kaçışıyla bile (aşağıdaki kod parçacığında olduğu gibi) benzer saldırılara açık olabileceğinden endişeleniyorum .

node-mysql, node.js için en popüler mysql bağlayıcısı gibi görünüyor, bu yüzden başkalarının bu sorunu hesaba katmak için (varsa) ne yaptığını merak ediyordum - ya da başlamak için node.js ile ilgili bir sorun olup olmadığını merak ediyordum. (kullanıcı / istemci tarafı girişi dahil olduğundan bunun nasıl olmayacağından emin değilim).

Ben geçiş Should düğüm-mysql-yerli hazırladığı ifadeleri sağlamaz, çünkü zaman varlık için? Bunu yapmakta tereddüt ediyorum, çünkü node-mysql kadar aktif görünmüyor (ancak bu sadece tamamlandığı anlamına gelebilir).

Sırasıyla siteler arası komut dosyası yazmayı ve sql enjeksiyonlarını önlemek için node-mysql'nin hazırlanmış deyim benzeri sözdizimi (yukarıda bahsettiğim gibi karakter kaçması yapar) ile birlikte dezenfektan modülünü kullanan bir kullanıcı kayıt kodu pasajı :

// Prevent xss
var clean_user = sanitizer.sanitize(username);

// assume password is hashed already
var post = {Username: clean_user, Password: hash};

// This just uses connection.escape() underneath
var query = connection.query('INSERT INTO users SET ?', post,
   function(err, results)
   {
       // Can a Sql injection happen here?
   });

Yanıtlar:


60

node-mysqlKütüphane otomatik zaten yapıyoruz olarak kullanıldığında kaçan gerçekleştirir. Bkz. Https://github.com/felixge/node-mysql#escaping-query-values


3
Gönderimde belirtildiği gibi, kütüphanenin karakterlerden kaçtığının farkındayım, ancak hazırlanmış ifadeler uygulayan bir kütüphaneye geçmezsem güvenlik açısından daha çok endişeleniyorum, yani bir SQL enjeksiyonu Şu anda yapıyorum?
funseiki

2
Kaçan karakterler SQL enjeksiyonunu engeller. Enjeksiyonlar, karakterler kaçmadığında meydana gelir ve kötü niyetli kullanıcılar, sorguyu kapatmak ve örneğin bir tabloyu düşürmek veya sahte bir kayıt eklemek için yeni bir tane başlatmak için bunu kullanabilir. Kaçan karakterlerle bu mümkün değildir. Wikipedia , SQL Enjeksiyonu hakkında bazı ek bilgilere sahiptir.
Michael Pratt

4
Ancak tüm SQL enjeksiyonlarını engelliyor mu? Bu cevap önermiyor (en azından PHP + MySQL için) ve PHP'nin Hazırlanmış İfadelerinin işe yaradığını ima ediyor. Yine, bu PHP bağlamında.
funseiki

1
Bağlantınıza göre, bu yalnızca MySQL'in güncel olmayan sürümlerinde çalışır. Bu saldırının Düğüm üzerinde çalışıp çalışmadığını bilmiyorum, ancak çok özel PHP güvenlik açıklarıyla ilgisi varmış gibi görünüyor, bu yüzden içgüdülerim hayır. Node-mysql'de kesinlikle hiçbir güvenlik açığı olmadığını söylemiyorum, ancak zaten çok sayıda üretim ortamında kullanılıyor. Hala SQL enjeksiyonu konusunda endişeliyseniz, mermiyi ısırmanızı ve MongoDB gibi bir şey denemenizi öneririm - SQL kullanmıyorsanız SQL enjeksiyonu yapamazsınız.
Michael Pratt

1
Öyle görünüyordu ve MongoDB rotası iyi bir nokta - ancak mevcut tasarım ilişkisel bir şemaya iyi bir şekilde katkıda bulunacaktı. Konsensus sadece düğüm-mysql ile yapışmasını doğru gibi aksi, öyle görünüyor - Ben başkasının güvenlik açıkları üzerinde fikir olup olmadığını görmek için bekleyeceğim
funseiki

12

Kitaplığın benioku dosyasında kaçışla ilgili bir bölümü vardır. Javascript-native, bu yüzden node-mysql-native'ye geçmeyi önermiyorum . Belgeler, çıkış için şu yönergeleri belirtir:

Düzenleme: node-mysql-native aynı zamanda saf bir Javascript çözümüdür.

  • Numaralar dokunulmadan bırakılır
  • Boole'ler true/ falsedizelere dönüştürülür
  • Tarih nesnelerinin dönüştürüldüğü YYYY-mm-dd HH:ii:ss dizelere
  • Tamponlar onaltılık dizelere dönüştürülür, örn. X'0fa5'
  • Dizelerden güvenli bir şekilde kaçılır
  • Diziler örneğin, listeye dönüşüyor ['a', 'b']içine döner'a', 'b'
  • İç içe diziler, (kütle parçaları için) gruplandırılmış listeler halinde, örneğin getirilir [['a', 'b'], ['c', 'd']]içine döner('a', 'b'), ('c', 'd')
  • Nesneler key = 'val'çiftlere dönüştürülür . İç içe geçmiş nesneler dizelere dönüştürülür.
  • undefined/ nulldönüştürülürNULL
  • NaN/ Infinityolduğu gibi bırakılır. MySQL bunları desteklemez ve bunları değerler olarak eklemeye çalışmak, destek uygulayana kadar MySQL hatalarını tetikleyecektir.

Bu, aşağıdaki gibi şeyler yapmanızı sağlar:

var userId = 5;
var query = connection.query('SELECT * FROM users WHERE id = ?', [userId], function(err, results) {
  //query.sql returns SELECT * FROM users WHERE id = '5'
});

Bunun kadar iyi:

var post  = {id: 1, title: 'Hello MySQL'};
var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) {
  //query.sql returns INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
});

Bu işlevlerin yanı sıra, kaçış işlevlerini de kullanabilirsiniz:

connection.escape(query);
mysql.escape(query);

Sorgu tanımlayıcılarından çıkmak için:

mysql.escapeId(identifier);

Hazırlanan ifadeler hakkındaki yorumunuza yanıt olarak:

Kullanılabilirlik açısından, modül harika, ancak henüz PHP'nin Hazırlanmış İfadelerine benzer bir şey uygulamadı.

Hazırlanan ifadeler bu bağlayıcı için yapılacaklar listesindedir, ancak bu modül en azından hazırlanan ifadelere çok benzeyen özel formatlar belirlemenize izin verir. Benioku dosyasından bir örnek:

connection.config.queryFormat = function (query, values) {
  if (!values) return query;
  return query.replace(/\:(\w+)/g, function (txt, key) {
    if (values.hasOwnProperty(key)) {
      return this.escape(values[key]);
    }
    return txt;
  }.bind(this));
};

Bu, bağlantının sorgu biçimini değiştirir, böylece aşağıdaki gibi sorguları kullanabilirsiniz:

connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });
//equivalent to
connection.query("UPDATE posts SET title = " + mysql.escape("Hello MySQL");

Cevabınız için teşekkür ederim - hazırlanmış tarzın farkındayım. Altında, yine de, karakterler kaçıyor. Bakınız: "Ancak, gerçekten sadece aynı connection.escape () 'i kullanıyor" . Node-mysql-native kullanmama konusunda: Mücadele ettiğim şey bu. Node-mysql-native, hazırlanmış ifadeleri uygularsa ve uygulamaları SQL enjeksiyonlarını engelliyorsa, node-mysql bunları alana kadar geçiş yapmam gerekmez mi?
funseiki

Bu bir çeşit tavuk ve yumurta sorusu. Sürücümü aktif olarak geliştirmiyorum çünkü çoğu insan @ felixge kullanıyor. Muhtemelen hazırlanmış ifadeleri node-mysql'e taşımak için biraz zaman bulmaya çalışacağım çünkü bu gerçekten bazı performans faydaları sağlıyor (ve potansiyel olarak sql enjeksiyonlarını zorlaştırıyor). Denemeye karar verirseniz yorum yapmaktan / yayınlamaktan çekinmeyin
Andrey Sidorov

1
@funseiki Hazırlanan ifadelerin en iyi çözüm olacağına eminim, ancak kaçmanın SQL enjeksiyonlarını engelleyeceğinden eminim. Modülün kendisi Joyent tarafından desteklendiği için, modül aktiftir ve açıkça iyice kontrol edilir. Bu modül üretime hazır olmasaydı, modülün geçen ay ortalama 1000 indirme / gün olacağını düşünmüyorum. Node-mysql-native, son geliştirilmesinden bu yana 6 aydır ve node-mysql çok aktiftir ve üzerinde birden fazla kişi çalışmaktadır.
hekzasiyanür

@AndreySidorov Yorumunuz için teşekkürler - bunun üstesinden gelmeye çalışırsam, bir güncelleme göndereceğim. Yakın zamanda olacağını sanmıyorum, çünkü başa çıkması kolay bir canavar gibi görünmüyor (şu anda sahip olduğumdan daha fazla araştırma gerektirecek). Ayrıca bu sürücüyü yaptığınız için teşekkürler - siz çocuklar
Node.js'nin

@hexacyanide node-mysql çok popüler olduğu için, topluluk üyelerinden karşılaşmış olabilecekleri (veya engelledikleri) güvenlik sorunları hakkında bir yanıt alabileceğimi ve mevcut karakter kaçış yaklaşımının neden güvenli olduğuna dair ikna edici bir argüman alabileceğimi umuyordum. kodları için yeterli.
funseiki

12

Bunun daha eski bir gönderi olduğunun farkındayım ama öyle görünüyor ki bir cevap asla işaretlenmedi, bu yüzden bunu oraya atacağım.

Kullandığınız bir modülün güvenli olup olmadığını test etmekle ilgili olarak, alabileceğiniz birkaç yol vardır. Her birinin artılarına / eksilerine değineceğim, böylece daha bilinçli bir karar verebilirsiniz.

Şu anda kullandığınız modül için herhangi bir güvenlik açığı bulunmamakla birlikte, bu genellikle kullanmakta olduğunuz modül / yazılım paketini kullanan bir güvenlik açığı olabileceğinden ve uyarılmayacağınızdan, genellikle yanlış bir güvenlik hissine yol açabilir. satıcı bir düzeltme / yama uygulayana kadar bir soruna.

  1. Güvenlik açıklarından haberdar olmak için posta listelerini, forumları, IRC'yi ve diğer bilgisayar korsanlığı ile ilgili tartışmaları takip etmeniz gerekecektir. PRO: Çoğu zaman, bir satıcı uyarılmadan veya yazılımlarına yönelik olası saldırı yolunu düzeltmek için bir düzeltme / yama yayınlamadan önce bir kitaplıktaki olası sorunların farkına varabilirsiniz. CON: Bu çok zaman alıcı ve kaynak yoğun olabilir. Bu rotaya, RSS beslemelerini, günlük ayrıştırmayı (IRC sohbet günlükleri) ve veya anahtar sözcükleri (bu durumda node-mysql-native) kullanan bir web sıyırıcısı kullanan bir bota giderseniz ve bildirimler, bu kaynakları taramak için harcanan zamanı azaltmaya yardımcı olabilir.

  2. Satıcının aramamış olabileceği sorunları test etmeye yardımcı olması için bir fuzzer oluşturun, bir fuzzer veya metasploit , sqlMap vb. Gibi başka bir güvenlik açığı çerçevesi kullanın . PRO: Bu, uyguladığınız modül / yazılımın halka açık erişim için güvenli olup olmadığına bakılmaksızın kabul edilebilir bir seviyeye kadar emin olmanın kesin bir yöntem olduğunu kanıtlayabilir. CON: Bu aynı zamanda zaman alıcı ve maliyetli hale gelir. Diğer sorun, yanlış pozitiflerin yanı sıra bir sorunun bulunduğu ancak fark edilmediği sonuçların eğitimsiz bir şekilde incelenmesinden kaynaklanacaktır.

Gerçekten güvenlik ve genel olarak uygulama güvenliği çok zaman alıcı ve kaynak yoğun olabilir. Yöneticilerin her zaman kullanacağı bir şey, yukarıdaki iki seçeneği gerçekleştirmenin maliyet etkinliğini (insan gücü, kaynaklar, zaman, ücret vb.) Belirlemek için bir formüldür.

Her neyse, bunun umulan bir 'evet' veya 'hayır' cevabı olmadığını anlıyorum, ancak söz konusu yazılımın bir analizini yapana kadar kimsenin bunu size verebileceğini sanmıyorum.


3

Bu sorunun eski olduğunu biliyorum, ancak ilgilenen herkes için Mysql-native modası geçmiş, bu yüzden orijinal MySQL modülünün ekibinin yardımıyla oluşturulan yeni bir modül olan MySQL2 oldu . Bu modülde daha fazla özellik var ve sanırım daha fazla güvenlik için PHP'deki gibi (kullanarak.execute () kullanarak) ifadeler hazırladığı için istediğiniz şeye sahip.

Aynı zamanda çok aktif (son değişiklik 2-1 gün arasındaydı) Daha önce denemedim ama bence istediğin şey bu ve daha fazlası.


-1

En kolay yol, tüm veritabanı etkileşimlerinizi rotalarınıza aktardığınız kendi modülünde işlemektir. Rotanızın veritabanı bağlamı yoksa SQL yine de ona dokunamaz.


Bu, OP'nin nasıl sterilize edileceği sorusuna gerçekten cevap vermiyor.
Christopher
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.