Ne zaman php eval kötüdür?

17 Cevap php

Ben php gelişmekte olan tüm yıllarda, hep kullanarak eval() kötü olduğunu duydum.

Aşağıdaki kodu göz önüne alındığında, bu ikinci (ve daha şık) seçeneğini kullanmak mantıklı değil mi? Değilse, neden?

// $type is the result of an SQL statement
// e.g. SHOW COLUMNS FROM a_table LIKE 'a_column';
// hence you can be pretty sure about the consistency
// of your string
$type = "enum('a','b','c')";

// possibility one
$type_1 = preg_replace('#^enum\s*\(\s*\'|\'\s*\)\s*$#', '', $type);
$result = preg_split('#\'\s*,\s*\'#', $type_1);

// possibility two
eval('$result = '.preg_replace('#^enum#','array', $type).';');

17 Cevap

I would be cautious in calling eval() pure evil. Dinamik değerlendirme güçlü bir araçtır ve bazen hayat kurtarıcı olabilir. Eval () ile bir (aşağıya bakınız) PHP shortcommings çalışabilirsiniz.

Eval ile ana sorunlar () şunlardır:

  • Potential unsafe input., güvenilmeyen bir parametre aktarımı başarısız bir yoldur. Bu parametre (ya da bunun bir parçası) tam güvenilir olduğundan emin olmak için genellikle önemsiz bir görev değildir.
  • Trickyness. eval () kullanımı takip etmek, bu nedenle daha zor, kod zeki yapar. Brian Kernighan alıntı "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it"

Eval fiili kullanım () ile temel sorun sadece bir tanesidir:

  • yeterince dikkate almadan kullanmak deneyimsiz geliştiriciler.

Genel bir kural olarak, ben bu takip eğilimindedir:

  1. Bazen eval tek / doğru çözümdür.
  2. Çoğu durumda, bir başka bir şey denemelisiniz.
  3. Eğer emin değilseniz, Goto 2.
  4. Else be very, very careful.

eval is evil when there is only the slightest possibility that userinput is included in the evaluated string. When you do eval without content that came from a user, you should be safe.

Yine de en az iki kez eval kullanmadan önce, bu deceivingly basit görünüyor düşünmek gerekir, ancak hata (VBAssassins yorum bakınız) işleme, debuggability vb akılda ile, artık o kadar basit değil.

So as a rule of thumb: Forget about it. When eval is the answer you're propably asking the wrong question! ;-)

Bu durumda, eval sürece keyfi sütunları bir kullanıcı tarafından bir tablo oluşturulmuş olması için onu asla mümkün olduğu gibi, muhtemelen yeterince güvenlidir.

Ama gerçekten daha fazla şık değil. Bu temelde bir metin ayrıştırma sorundur, ve işlemek için PHP'nin ayrıştırıcı kötüye isimli biraz hacky görünüyor. Eğer dil özelliklerini kötüye kullanmak istiyorsanız, neden JSON ayrıştırıcı kötüye değil? En azından JSON çözümleyici, kod enjeksiyonu hiç ihtimali yoktur.

$json = str_replace(array(
	'enum', '(', ')', "'"), array)
	'',     '[', ']', "'"), $type);
$result = json_decode($json);

Bir düzenli ifade muhtemelen en belirgin yoludur. Bu dize tüm değerleri ayıklamak için bir tek normal ifadeyi kullanabilirsiniz:

$extract_regex = '/
	(?<=,|enum\()	# Match strings that follow either a comma, or the string "enum("...
	\'		# ...then the opening quote mark...
	(.*?)		# ...and capture anything...
	\'		# ...up to the closing quote mark...
	/x';
preg_match_all($extract_regex, $type, $matches);
$result = $matches[1];

Eğer eval içinde (örneğin, kullanıcı girişi gibi) yabancı verileri kullanılarak zaman.

Yukarıdaki örnekte, bu bir sorun değildir.

eval() is equally evil at all times.

"Ne zaman) kötü değildir (eval mi?" Bu eval kullanarak sakıncaları () sihirli bazı bağlamlarda yok ima görünüyor çünkü bence soran yanlış bir sorudur.

Kodun okunabilirliği, çalışma zamanında önce kod yolu (ve olası güvenlik uygulamalarını) tahmin etmek için yeteneği ve dolayısıyla hata ayıklama kodu yeteneği azalır çünkü eval () kullanımı genellikle kötü bir fikirdir. PHP olmadan tam işlevsel bir programlama dilidir - Ayrıca, () eval kullanmak kesinlikle gerekli olduğu bir durum yok.

Aslında kötülüklerin olarak görebilirsiniz ya da kişisel bazı durumlarda eval () kullanarak haklı olup olmadığını size kalmış. Bazılarına göre, kötülükler hiç bunu haklı çıkarmak için çok büyük, ve diğerleri, eval () kullanışlı bir kısayol.

Eğer kötülük olarak () eval görmek Ancak, bu her zaman kötü. Bu sihirli bağlamda bağlı olarak onun kötülüğünü kaybetmez.

Ben pervasızca burada içeriğini çalmak olacak:

  1. Doğası gereği Eval hep bir güvenlik sorunu olacak.

  2. Güvenlik kaygıları dışında eval da inanılmaz yavaş olma sorunu var. PHP 5.1 beta1 üzerindeki 10 kat normal kod sonra yavaş ve 28 kat daha yavaş PHP 4.3.10 benim test.

blog.joshuaeichorn.com: using-eval-in-php

Şahsen, ben bunu ne yaptığını yorumlama değil çünkü bu kod hala çok kötü olduğunu düşünüyorum. O da çok kırılgan hale geçerliliği için girdilerini test değil.

Eval kullanımları% 95 (veya daha fazla) aktif tehlikeli olduğundan ben de hissediyorum, küçük potansiyel zaman diğer durumlarda sağlayabilir olduğunu kaydederek bunu kullanarak kötü uygulama düşkünlük değer değildir. Ayrıca, daha sonra eval kullanımınız iyi olduğunu ve Psikofarmakolojik kötü neden kölelerinin açıklamak gerekecek.

Ve, elbette, PHP Perl gibi bakıyor biter ;)

(Bir "enjeksiyon saldırısı" senaryosu gibi) eval iki ana problem () vardır:

1) It may cause harm 2) It may simply crash

ve daha-sosyal-daha-teknik biri:

3) İnsanların başka bir kısayol olarak uygunsuz kullanmak özendirmek gerekir

Birinci durumda, keyfi kod yürütme (tabii ki, bilinen bir dize eval'ing yapıyorsanız değil) riski vardır. Sizin girişler olsa da, düşünmek gibi sabit olarak bilinen ya da olmayabilir.

(Bu durumda) daha büyük olasılıkla sadece kaza gerekir, ve dize bir isteğiniz karanlık bir hata mesajı ile sona erecektir. IMHO, tüm kod (hata en kullanılabilen, biçimi olarak) bir istisna hangi başarısız, mümkün olduğunca düzgün başarısız gerekir.

Ben bu örnekte, yerine davranışa kodlama daha tesadüf kodlama konum, öneririm. Evet, SQL enum ifadesi (ve bu alanın numaralama eminiz -?? Veritabanının doğru sürümü sağ tablosunun sağ alan aradın aslında cevap verdiniz), PHP dizi beyanı sözdizimi gibi bakmak olur ama gerçekten ne yapmak istediğinizi öneririm girişten çıkışa kadar kısa yolu bulmak değil, belirtilen görevi mücadele değildir:

  • Eğer bir enum sahip olduğunu tespit
  • Iç listesini çıkarmak
  • Liste değerlerini ambalajından

Lütfen seçenek bir yapar kabaca ne olduğunu, ama bazı sarmak istiyorum hangi ise ait ve netlik ve güvenliği (örneğin, ilk maç eşleşmezse atmak, istisna veya set boş sonuç) için etrafında yorumlar.

Orada kaçan virgül veya tırnak ile olası bazı sorunlar hala var ve muhtemelen daha sonra de-alıntı verileri açmak gerekir, ama oldukça kodu olarak değil, veri olarak en azından tedavi veri yok.

Preg_version ile kötü sonuç, $ result = null olması muhtemeldir eval sürümü ile kötü bilinmiyor, ama en azından bir kaza.

eval() yavaş, ama ben kötü demezdim.

Bu code injection yol ve kötü olabilir biz bunu yapmak kötü kullanımı var.

Basit bir örnek:

$_GET = 'echo 5 + 5 * 2;';
eval($_GET); // 15

A harmlful örnek:

$_GET = 'system("reboot");';
eval($_GET); // oops

Sana eval() kullanmak için tavsiye ancak bunu yaparsanız, tüm giriş / beyaz liste doğrulamak emin olur.

Ben de kodu muhafaza insanlar için bazı dikkate ödemek istiyorum.

eval () sadece bakmak ve gerçekleşmesi gerekiyordu bilmek easiet değil, sizin örnek o kadar kötü değil, ama başka yerlerde bu doğru bir kabus olabilir.

eval kod olarak bir dize değerlendirir, bunda sorun dize herhangi bir şekilde ise "kusurlu" o büyük güvenlik tehditleri açığa gelebilir. Normalde sorun kullanıcı girişi kullanıcı giriş kodu (örneğin php veya SSI) sonra eval içinde çalıştırılan verebilecek birçok durumda dize değerlendirilir bir durumda olduğunu, bu php dosyası olarak aynı izinleri ile çalışır ve olabilir ediyorum sunucuya bilgi / erişmek için kullanılabilir. Kesinlikle kullanıcı girişi düzgün eval uzatırken önce temizlenir yapmak oldukça zor olabilir. Tartışmalıdır, bazıları başka problemler vardır ...

eval() always kötülüktür.

  • Güvenlik nedenleriyle
  • performans nedenleriyle
  • okunabilirlik / tekrar kullanılabilirliği nedenlerle
  • IDE / aracı nedenlerle
  • hata ayıklama için
  • daha iyi bir yolu her zaman vardır

PHP bunu call_user_func yoluyla yürütme yerine açık evals yapıyor olabilir böyle bir şekilde kod yazmak önerir.

Diğer nedeni eval kötülüktür bu eAccelertor veya ACP gibi PHP baytkodu tarafından önbelleğe olamazdı olmasıdır.

Bu eval () kötülük değil, işlev yapan kötü programlama bulunuyor. Birden sitelerinde dinamik programlama etrafında alınamıyor gibi, bazen kullanmak. İstediğim şeyleri almazsınız gibi, PHP bir sitede ayrıştırıldı olamaz. Ben sadece bir sonuç alacak! Bu benim hayat çok daha kolay yapar gibi, var eval () gibi bir işlev mutluyum. Kullanıcı girişi? Sadece kötü programcılar hackerlar tarafından bağladım olsun. Ben bu konuda endişelenmeyin.

Bu eval () kötülük değil, işlev yapan kötü programlama bulunuyor. Birden sitelerinde dinamik programlama etrafında alınamıyor gibi, bazen kullanmak. İstediğim şeyleri almazsınız gibi, PHP bir sitede ayrıştırıldı olamaz. Ben sadece bir sonuç alacak! Bu benim hayat çok daha kolay yapar gibi, var eval () gibi bir işlev mutluyum. Kullanıcı girişi? Sadece kötü programcılar hackerlar tarafından bağladım olsun. Ben bu konuda endişelenmeyin.

Ben yakında ciddi sorunlar olacak tahmin ...

Tüm dürüstlük, PHP gibi yorumlanmış bir dil gibi eval gibi fahiş bir işlev için iyi kullanmak, kesinlikle yoktur. Ben eval daha güvenli başka yolları kullanarak idam olamazdı program fonksiyonları yerine görmemiştim ...

Eval tüm kötülüklerin köküdür, ben yürekten test kullanıcı girişi yardımcı olacağını düşünüyorum tüm insanlara katılıyorum. Iki kere düşünün, kullanıcı girişi çok farklı şekillerde gelebilir ve biz hackerlar bu işlevi istismar konuşmak gibi hakkında yeterli umursamadı. Bence, sadece tamamen eval kaçının.

Ben kendi yaratıcılığınızı aştı eval işlevini kötüye hazırlanmış örneklerini gördük. Bir güvenlik duruş, tüm maliyet kaçınmak ve en azından ziyade bir 'verilmiş' den PHP yapılandırmasında bir seçenek olarak talep olarak ben bile kadar gitmek istiyorum.

I eval () çok kullanmak için kullanılır, ama hile yapmak için eval kullanmak zorunda değilsiniz vakaların çoğunda bulundu. Peki, call_user_func () ve PHP call_user_func_array () var. Bu statik ve dinamik olarak herhangi bir yöntemi çağırmak için yeterince iyi.

Statik bir çağrı dizi ('class_name', 'Method_Name'), ya da 'class_name :: Method_Name' gibi hatta gibi basit dize olarak geri arama inşa gerçekleştirmek için. Dinamik çağrı kullanım dizi ($ nesne, 'yöntem') tarzı arama gerçekleştirmek için.

Eval için tek mantıklı kullanımı () özel bir derleyici yazmak. Ben bir tane yaptım, ama bu hata ayıklama bu çok zor, çünkü eval, hala kötüdür. Kötü şey evaled kodunda ölümcül hata denilen kodunu çöker olduğunu. Ben en azından sözdizimini kontrol etmek Parsekit PECL uzantısı kullanılır, ama hala hiçbir sevinç - bilinmeyen sınıfı ve tüm app çöker başvurmak için çalışın.

Güvenlik kaygıları, eval () dışında, derlenmiş optimize edilmiş veya opcode önbelleğe, böylece daima yavaş olacaktır edilemez - way slower - Normal php kodu daha. O kötülük yapmaz allthough Bu nedenle eval sigara kullanmak performanslısı. (goto kötülük, eval sadece kötü bir uygulamadır / koklamak kodu / çirkin)