[Owasp-turkey] mysql escape sorunsali - 2 defa alanlar kusura bakmasin

Hakan Can gogreenbecool at gmail.com
Fri Jan 25 00:55:16 UTC 2013


Gördüğüm kadarıyla arkadaşların kafası haklı olarak karışmış.
Öncelikle kavramları yerine oturtalım.
1- string : içinde sql dili ile ilgili her hangi bir tanımlayıcı ad, method
yada komut barındırmayan sadece karakter ve özel-karakterden oluşan dizi.

2- Özel-karakter Literal Characters(mysql):
  NUL (0x00) --> \0
  BS  (0x08) --> \b
  TAB (0x09) --> \t
  LF  (0x0a) --> \n
  CR  (0x0d) --> \r
  SUB (0x1a) --> \Z
  "   (0x22) --> \"
  %   (0x25) --> \%
  '   (0x27) --> \'
  \   (0x5c) --> \\
  _   (0x5f) --> \_


mysql'deki ana ayıraçlar
#1 `  	Opening single quote (0x60)
#2 '	Closing single quote (apostrophe)  (0x27)
#3 "	Quotation mark (0x22)

  şimdi tek tek kafa karıştıran noktalara ışık tutabiliriz.
Normal MySQL mode seçildiğinde #2 ve #3  string tanımlama ayracı olarak
kullanılabilir, #1 string tanımlamadığı gibi özel karakterleri de
işlevsizleştirir. #1 ayıracı database table ve column adlarını korumak 
ve tanımlamak için kullanılabilir.

ör (select `check-in`,`check-out` from rooms where location='alanya' and 
city="antalya")

normalde (-) yani tire column adı içinde hata verirken #1 ile ayıraç 
içine alınca
sorunsuz çalışır.
Fakat ANSI_QUOTES SQL mode seçildiğinde  #3 ayracını #1 e çevirir
(Burası tüm karışıklığın çıktığı nokta) #2 ye değil.
yukarıdaki örneğe bakarsak "antalya" => `antalya` ya dönüştürülür ve mysql
antalya adında bir column bulunamadı diye hata verir.
Kısaca sadece #2 string tanımlar #1 ve #2 database table ve column adlarını
tanımlamakta kullanılabilir.
Burası çok önemli ANSI ve Mysql mode değişimi sadece string tanımlama 
tarzını
değiştirir. String içindeki Literal Characterlerin nasıl escape edileceğini
değiştirmez.
Her iki durumda da geçerli bir şekilde tüm özel karakterler(kendisi dahil)
\ backslash ile escape edilebilir

 >Ancak benim gordügüm bu deil. Yani her durumda;
 >
 >    single tick, extra single tick ile escape edilebiliyor VE
 >    single tick, \ karakteriyle  de escape edilebiliyor.
 >
 >Sadece aşağıdaki komut çalıştırılırsa
 >
 >set sql_mode NO_BACKSLASH_ESCAPE

 >işte bu durumda yukarıdaki ikinci madde çalışmıyor.

normal sql modun da  '"test"' ve "'test'"  escape edilmeden çalışır
fakat ''test'' ve ""test"" hata verir  fakat escape edilirse
	'\'test\'' ve "\"test\"" normal çalışır
yukarıdaki durumlarda quote() fonksiyonu tercih edilmelidir.

teknik olarak ANSI mode da  (") ayıracı kullanılamayacağı için ve 
dönüştürüldüğü için manuel olarak escape edilmezse hata vermeli. Ama bu 
mantıken olması gereken.
Test edilip doğrulanması gerekir.

not:Mysql fonksiyonları (%) ve (_) özel karakterlerini escape etmez 
çünkü bunlar
like ile genel arama yapmak için kullanılır  (location like '%köy')

mysql_real_escape_string fonksiyonu aşağıdaki karakterleri escape eder
\x00, \n, \r, \, ', " ve \x1a.(control Z)
#1 \x60 ayıracı mysql fonksiyonları tarafından escape edilmez.
Manüel olarak escape edilmez ise hata verir.

OWASP sitesine gelirsek evet bu kafa karıştırıcı.
Mysql yardım metinleri ile çelişiyor ve düzeltilmesi gerekir.
Okadar da önemli değil sonuçta ansi kullananımından caydırmak dışında 
bir yan etkisi yok :)

Hakan Can.

http://dev.mysql.com/doc/refman/5.0/en/string-literals.html
mysql yardım metini sayfasından alıntı:
 >If the ANSI_QUOTES SQL mode is enabled, string literals can be quoted 
only
within single quotation marks because a string quoted within double 
quotation
marks is interpreted as an identifier.

https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#MySQL_Escaping
sayfasından alıntı

 >MySQL Escaping
 >
 >MySQL supports two escaping modes:
 >
 >    ANSI_QUOTES SQL mode, and a mode with this off, which we call
 >    MySQL mode.
 >
 >ANSI SQL mode: Simply encode all ' (single tick) characters with '' 
(two single ticks)


More information about the Owasp-turkey mailing list