2010-09-24 23 views
20

Bazı çok baytlı karakter kümeleri verildiğinde, aşağıdakilerin yapmak istediği şeyi yapmadığını varsayarak düzeltebilir miyim? Özelliklestr_replace() tehlikeli midir?

$string = str_replace('"', '\\"', $string); 

, giriş 0xbf5c gibi geçerli bir karaktere sahip olabilecek bir karakter kümesinde, bu yüzden bir saldırganın bir tırnaksız çift tırnak ardından geçerli bir karakter bırakarak 0xbf5c22 almak için 0xbf22 enjekte eğer (") .

bu sorunu hafifletmek için kolay bir yol var mı, yoksa (benim durumumda, dize bir HTML girdi etiketinin değeri özniteliği girecek

ilk etapta sorunu yanlış anlama am:? yankı 'giriş türü = "metin" değeri = "'. $ dize. '">';)

DÜZENLEME: Bu konuda, preg_quote() gibi bir işlevden ne haber? Bunun için bir karakter argümanı yok, bu yüzden bu senaryoda tamamen işe yaramaz gibi görünüyor. UTF-8 karakter kümesini sınırlandırma seçeneğiniz olmadığında (evet, bu güzel olurdu), gerçekten engelli gibi görünüyorsunuz. Bu durumda ne değiştirme ve alıntılama işlevleri mevcut?

+0

Bkz. [Yalnızca argümanlar olarak geçerli UTF-8 kodlanmış dizeleri verildiğinde str_replace UTF-8 kodlu dizede güvenle kullanılabilir mi?] (Http://stackoverflow.com/questions/2652193/can-str-replace- mb_str_replace'a neden ihtiyaç duyulmadığını okumak için güvenli bir şekilde kullanılan-on-a-utf-8-kodlanmış-dizgi-sadece-verilen-geçerli-geçerli). – Lode

cevap

25

Hayır, haklısın: beklenmeyen bir sonuç neden olabilir baytlı dizgeye bir Tek baytlık dize işlevini kullanma. Parametrelerin kombinasyonu ile ilgili olarak, bu

function mb_replace($search, $replace, $subject, &$count=0) { 
    if (!is_array($search) && is_array($replace)) { 
     return false; 
    } 
    if (is_array($subject)) { 
     // call mb_replace for each single string in $subject 
     foreach ($subject as &$string) { 
      $string = &mb_replace($search, $replace, $string, $c); 
      $count += $c; 
     } 
    } elseif (is_array($search)) { 
     if (!is_array($replace)) { 
      foreach ($search as &$string) { 
       $subject = mb_replace($string, $replace, $subject, $c); 
       $count += $c; 
      } 
     } else { 
      $n = max(count($search), count($replace)); 
      while ($n--) { 
       $subject = mb_replace(current($search), current($replace), $subject, $c); 
       $count += $c; 
       next($search); 
       next($replace); 
      } 
     } 
    } else { 
     $parts = mb_split(preg_quote($search), $subject); 
     $count = count($parts)-1; 
     $subject = implode($replace, $parts); 
    } 
    return $subject; 
} 

: Örneğin mb_ereg_replace veya mb_split için yerine multibyte string functions kullanın:

$string = mb_ereg_replace('"', '\\"', $string); 
$string = implode('\\"', mb_split('"', $string)); 

Düzenleme İşte kullanılarak mb_replace uygulama var varyantı bölünmüş katılmak işlev, str_replace tek bayt gibi davranmalıdır.

+0

PHP'de mb_str_replace yok –

+1

mb_ereg_replace() için sözdizimi yanlış - düzenli bir ifade gerektirir. Bu tür bir işlevin gerektirdiği daha ağır işlemelerden kaçınmayı umuyordum, ama sanırım şansım yok. Bunu HER ŞEY için kullanmalıyım - hatta preg_quote() gibi bir şey bile, değil mi? PHP5.3'teki normal ereg_ * işlevlerine rağmen, aynı mb_ereg_ * işlevleri için geçerli değil mi? – user456885

+1

@ user456885: '' 'karakteri tanımlayan geçerli bir normal ifade ''' (bunun PCRE olmadığını unutmayın). Ama neden ikinci ayrıştırma varyantını kullanmıyorsunuz? – Gumbo

3

Önce mb_regex_encoding() ile charset belirterek ya mb_ereg_replace kullanabilirsiniz. Alternatif olarak, UTF-8'i kullanırsanız, u değiştiricisiyle preg_replace'u kullanabilirsiniz. Anladığım kadarıyla, dize enjeksiyonun bu türden çok fazla mysql_real_escape_string çözülür Dan

+0

Maalesef bu sorunu çözeceğini düşündüğüm UTF-8'i sınırlayamıyorum. Ben mb_ereg_replace() orada tek çözüm (?) Olduğunu düşünüyorum ... ama basit bir str_replace() için verimsiz görünüyor. Bunu preg_quote() için de yedek olarak çağırmalıyım, ha? ... Ayrıca, ereg_ * işlevlerinin artık kullanımdan kaldırıldığını biliyorum - bunlar mb_ereg_ * işlevlerini de içeriyor mu? – user456885

+0

Kod parçacıkları cümlelerden daha iyidir IMPO – Trix

-3
+6

Bu, belirli bir veritabanı sürücüsüne bağlı bir işlevdir. Veritabanına bile gitmeyen veriden kaçmak için bazı veritabanı sürücüsünün kurallarına güvenmek istemiyorum. Kodun bir veritabanını ilk sırada kullanmaması durumunda bir veritabanı sürücüsünün kullanılmasını da istemiyorum. Özellikle çok popüler veri madenciliği konusu için – user456885

6

kod Aksine bütün geçmekte daha vb Shift_JIS, GB *, gibi kırık olanlarla mükemmel UTF-8 ve EUC-TW gibi aklı başında baytlı-kodlamaları ile güvenli ama tehlikelidir Bu eski kodlamalar ile güvende olmak için baş ağrısı ve ek yükü, sadece UTF-8'i desteklemenizi tavsiye ederim.

+1

her zaman mümkün değildir. –

+0

@TimoHuovinen: UTF-8 olmayan kodlamalarda veri ile uğraşmak zorunda olduğunuz bu tür uygulamalar için, en basit çözüm, giriş aşaması sırasında yeniden kodlanır, böylece işlediğiniz zaman UTF-8'de olur. –

+1

daha kolay yapıldığını söyledi :) Örneğin bu şekilde desteklenmeyenlerin bir listesini [tarayıcı destekli karakterler] keşfettim (http://stackoverflow.com/questions/3565713/how-can-i-convert-html-character-references- x5e3-to-düzenli-utf-8/3566055 # 3566055). UTF-8 ile DOMDocument kullanarak sorunları. Buna yeni gelen için yaşayan bir kabus yaratacak birçok konu var. [Bunun gibi] (http://stackoverflow.com/questions/9210473/how-to-convert-text-with-html-entites-and-invalid-characters-to-its-utf-8-equi) –