tpug Thu Dec 13 11:23:02 2001 EDT Added files: /phpdoc/tr/chapters security.xml Log: complete translation by Serdar
Index: phpdoc/tr/chapters/security.xml +++ phpdoc/tr/chapters/security.xml <?xml version="1.0" encoding="iso-8859-1"?> <!-- $Revision: 1.1 $ --> <chapter id="security"> <title>Güvenlik</title> <simpara> PHP, hem web sunucusu modülü hem de <acronym>CGI</acronym> uygulaması sürümleri ile, sistemdeki dosyaları okuyabilen, komutları çalıştırabilen ve ağ bağlantıları kurabilen çok güçlü bir dildir. Bu özellikler, güvenlik önlemi alınmamış bir web sunucusunda istenilen her şeyin çalıştırılabilmesini sağlar. PHP, CGI programlarının yazıldığı Perl ve C gibi dillerden daha güvenli bir dil olacak şekilde tasarlanmıştır, derleme sırasında ve çalışma sırasında ayarlanabilen konfigürasyon seçenekleri, ve doğru kodlama teknikleri ile size istediğiniz özgürlük ve güvenlik birleşimini verecektir. </simpara> <simpara> PHP'yi birçok farklı alanlarda kullanabildiğiniz gibi, davranışlarını kontrol ettiğiniz birçok farklı konfigürasyon seçeneği mevcuttur. Geniş bir seçenek yelpazesi PHP'yi çok çeşitli amaçlarla kullanmanıza imkan tanırken, aynı zamanda bu ayarların arasından yapılacak birleşimlerin güvensiz kurulumlarla sonuçlanmasına neden olabilir. </simpara> <simpara> PHP'nin esnek konfigürasyon yapısı, esnek kod yapısı ile aynı güçtedir. PHP büyük sunucu uygulamaları yazarken shell kullanıcısının bütün gücünü kullanma olanağını sağlarken, ufak sunucu taraflı eklentilerle kontrolde tutulan ve ufak risk taşıyan uygulamaların da yazılabilmesini sağlar. Bu ortamın nasıl inşa edildiği, ve ne kadar güvenli olduğu, çok büyük miktarda PHP geliştiricisine bağlıdır. </simpara> <simpara> Bu bölüm bazı genel güvenlik önerilerinden başlayarak, birlikte güvenle kullanılabilecek farklı konfigürasyon seçeneklerini ve durumları açıklayacak, ve farklı güvenlik seviyeleri için kodlama sırasında alınabilecek farklı kararları ele alacaktır. </simpara> <sect1 id="security.general"> <title>Genel Bakış</title> <simpara> Tamamen güvenli bir sistem sanal bir imkansızlıktır, o nedenle güvenlik işine sıklıkla riskin ve kullanılabilirliğin dengelenmesi olarak bakılır. Kullanıcı tarafından gönderilen veri iki farklı biometrik doğrulamadan (retina taraması ve parmak izi gibi) geçiriliyorsa, oldukça yüksek bir maliyet ödeyeceksiniz demektir. Ayrıca karışık sayılabilecek bir formun doldurulması yarım saati bulacak, bu da kullanıcıların güvenlik sistemini aşmak için cesaret bulmasına neden olacaktır. </simpara> <simpara> En iyi güvenlik, kullanıcıların işini engellemeden ve onları gereksiz bir karmaşıklığa sürüklemeden sağlanabilir. Öte yandan, bazı güvenlik saldırıları bu tip normal üstü güvenliğe sahip sistemlerde, zamanla bu sistemlerin zaman aşımına uğraması sonucu gerçekleşmektedir. </simpara> <simpara> Hatırlanmaya değer bir söz: Bir zincir yalnızca en zayıf halkası kadar sağlamdır. Bütün işlemler zaman, yer, işlem tipi vb. gibi ince detaylara kadar kaydedilirken, kullanıcı yalnızca tek bir çerezle doğrulanıyorsa, kaydı tutulan diğer işlemlerin doğruluğu da ciddi biçimde kuşku yaratır. </simpara> <simpara> Sistemi denerken, en basit sayfalar için bile bütün olası testleri yapamayacağınızı aklınızda bulundurun. Sizin aklınıza gelmeyecek bir şey bilinçsiz bir çalışan tarafından, bol bol vakti olan bir cracker tarafından, ya da klavyenin üstünde yürüyen bir kedi tarafından yapılabilir. İşte bu nedenle koda mantık perspektifinden yaklaşmalı, beklenmeyen verinin nereden geleceğini bulmalı, ve buradaki açığın nasıl giderileceği üzerinde çalışmalısınız. </simpara> <simpara> Internet sizin kodunuzu bozarak, sitenizi göçerterek, küfürlü içerik göndererek, ve ilginç bir gün geçirmenize neden olarak kendisine isim yapmak isteyen insanlarla doludur. Küçük ya da büyük bir siteye sahip olmanız önemli değildir, online olarak zaten bir hedef haline gelirsiniz. Birçok saldırı programı boyutu önemsemez, yalnızca geniş IP bloklarını tarayarak kurbanlarını ararlar. Onlardan biri olmamaya çalışın. </simpara> </sect1> <sect1 id="security.cgi-bin"> <title>CGI Kurulum</title> <sect2 id="security.cgi-bin.attacks"> <title>Olası saldırılar</title> <simpara> PHP'nin bir nedenden dolayı sunucu yazılımına (Apache gibi) entegre edilmek istenmediği, ya da PHP'yi farklı tipte CGI okuyucuları kullanarak uygulamalar için güvenli chroot ve setuid ortamlarının yaratılmak istendiği durumlarda PHP'yi <acronym>CGI</acronym> bir seçenek olabilir. Bu kurulum PHP çalıştırılabilir dosyasının web sunucusunun cgi-bin klasörüne kurulmasıyla gerçekleştirilebilir. CERT danışmanı <ulink url="&url.cert;">CA-96.11</ulink> cgi-bin klasörüne hiçbir yorumlayıcının kurulmamasını tavsiye eder. PHP, tek başına okuyucu olarak kullanıldığı takdirde, bu tip kurulumdan kaynaklanan aşağıdaki saldırıları önleyecek biçimde tasarlanmıştır: </simpara> <itemizedlist> <listitem> <simpara> Sistem dosyalarına erişim: <filename role="url">http://my.host/cgi-bin/php?/etc/passwd</filename> </simpara> <simpara> URL içindeki soru işaretinden (?) sonra gelen sorgu bilgisi, CGI arayüzü tarafından okuyucuya komut satırı parametresi olarak aktarılır. Sıklıkla okuyucular komut satırının ilk argümanı olarak belirtilmiş dosyayı açar ve çalıştırırlar. </simpara> <simpara> CGI olarak çalıştırıldığında, PHP komut satırı parametrelerini işlemeyi reddeder. </simpara> </listitem> <listitem> <simpara> Sunucudaki herhangi bir web dokümanına erişim: <filename role="url">http://my.host/cgi-bin/php/secret/doc.html</filename> </simpara> <simpara> URL içindeki PHP çalıştırılabilirinden sonraki yol bilgisi, <filename role="uri">/secret/doc.html</filename>, <acronym>CGI</acronym> arayüzü tarafından programa iletilecek ve program tarafından açılıp yorumlanacak dosyanın ismini belirtir. Bazı web sunucu konfigürasyon direktifleri (Apache: Action) bu tip istekleri <filename role="url">http://my.host/secret/script.php</filename> gibi adreslere yönlendirmek için kullanılır. Bu tip kurulumla, web sunucusu önce <filename role="uri">/secret</filename> klasörüne erişim hakkını gözden geçirir, ve sonra yönlendirilmiş isteği yaratır <filename role="url">http://my.host/cgi-bin/php/secret/script.php</filename>. Ne yazık ki, istek orjinal olarak bu şekilde verildiyse, web sunucusu <filename role="uri">/secret/script.php</filename> dosyasına erişimi kontrol etmeyecek, yalnızca <filename role="uri">/cgi-bin/php</filename> için kontrol yapacaktır. Bu şekilde <filename role="uri">/cgi-bin/php</filename> a erişimi olan herhangi bir kullanıcı, web sunucusu üzerindeki korunan herhangi bir dokümana erişebilir olacaktır. </simpara> <simpara> PHP, bu saldırıları derleme sırasındaki konfigürasyon seçeneği <link linkend="install.configure.enable-force-cgi-redirect">--enable-force-cgi-redirect</link> ve çalışma sırasındaki konfigürasyon direktifi <link linkend="ini.doc-root">doc_root</link> ve <link linkend="ini.user-dir">user_dir</link> ile sunucu doküman ağacı erişim kısıtlaması yapılmış bir klasöre sahipse önleyebilir. Aşağıdaki örneği inceleyerek farklı birleşimler için açıklamalar bulabilirsiniz. </simpara> </listitem> </itemizedlist> </sect2> <sect2 id="security.cgi-bin.default"> <title>Durum 1: yalnızca public dosyaların sunulması</title> <simpara> Sunucunuz parola ile kısıtlanmış bir bölüme sahip değilse ya da IP bazında erişim kontrolü yapılmıyorsa, bu konfigürasyon ayarlarına ihtiyacınız yoktur. Web sunucunuz yönlendirme işlemine izin vermiyorsa, ya da sunucunuzun PHP ile iletişim kurup isteğin güvenli bir yönlendirme isteği olduğunu iletme imkanı yoksa, <link linkend="install.configure.enable-force-cgi-redirect">--enable-force-cgi-redirect</link> seçeneğini kullanarak konfigürasyon yapabilirsiniz. PHP uygulamalarınızın bu uygulamayı başka bir yoldan ya da direk olarak çalıştırabilir olmadığından emin olmalısınız. Bu ne <filename role="php">http://my.host/cgi-bin/php/dir/script.php</filename> olmalıdır, ne de <filename role="php">http://my.host/dir/script.php</filename> olmalıdır. </simpara> <simpara> Yönlendirme Apache içersinden AddHandler ve Action direktifleri kullanılarak yapılabilir (aşağıya bakın). </simpara> </sect2> <sect2 id="security.cgi-bin.force-redirect"> <title>Durum 2: --enable-force-cgi-redirect kullanımı</title> <simpara> Bu derleme sırasında kullanılan komut, PHP'nin <filename role="php">http://my.host/cgi-bin/php/secretdir/script.php</filename> gibi bir url kullanılarak direk olarak çağrılmasını önler. PHP bu modda yalnızca web sunucusu bir yönlendirme kuralı oluşturmuşsa çalışacaktır. </simpara> <simpara> Apache konfigürasyonu içinde yönlendirme aşağıdaki direktifler izlenerek yapılabilir: </simpara> <programlisting role="apache-conf"> <![CDATA[ Action php-script /cgi-bin/php AddHandler php-script .php ]]> </programlisting> <simpara> Bu seçenek yalnızca Apache web sunucusu için test edilmiştir, ve Apache'ın yönlendirmede kullandığı CGI ortam değişkeni <envar>REDIRECT_STATUS</envar> değişkenine bağımlıdır. Web sunucunuz isteğin direk mi yoksa yönlendirme mi olduğunu iletme özelliğine sahip değilse, bu seçeneği kullanamazsınız. Bu durumda burada anlatan diğer CGI kurulumlarından birini denemeniz gereklidir. </simpara> </sect2> <sect2 id="security.cgi-bin.doc-root"> <title>Durum 3: setting doc_root ya da user_dir</title> <simpara> Uygulamalar ve çalıştırılabilirler gibi, web sunucu doküman klasörlerine canlı içerik eklemek için, bazı durumlarda güvensiz işlemler yapmanız gerekir. Bazı konfigürasyon hataları yüzünden, uygulamalar düzgün çalıştırılmaz ve normal HTML dokümanları gibi görüntülenirse, bu durum parolaların ele verilmesi gibi istenmeyen güvenlik açıklarına neden olacaktır. Birçok sistem yöneticisi, yalnızca yorumlayan ve çıktı üretmeyen uygulama dosyaları için yalnızca PHP CGI tarafından erişilebilen farklı bir klasör yapısı yaratmayı tercih etmektedir. </simpara> <simpara> Bir önceki bölümde anlatıldığı gibi, isteklerin yönlendirilmediğini kontrol eden sistem kullanılamaz olduğunda, web sunucusunun kök doküman klasörü haricinde bir doc_root ayarlanması mutlaka gereklidir. </simpara> <simpara> PHP uygulama kök doküman klasörünü isterseniz <link linkend="configuration.file">konfigürasyon dosyası</link> içindeki <link linkend="ini.doc-root">doc_root</link> direktifinden, isterseniz ortam değişkeni olan <envar>PHP_DOCUMENT_ROOT</envar> değerinden değiştirebilirsiniz. Bu değer kullanıldığında, PHP'nin CGI sürümü açılacak dosya ismini <parameter>doc_root</parameter> değeriyle belirtilene göre yaratacak, böylece bu klasörün dışındaki hiçbir uygulama çalıştırılmayacaktır (<parameter>user_dir</parameter> dışındakiler). </simpara> <simpara> Bir diğer kullanışlı seçenek <link linkend="ini.user-dir">user_dir</link> seçeneğidir. user_dir boş olduğunda, açılan dosya yalnızca <parameter>doc_root</parameter> ile kontrol edilir. <filename role="url">http://my.host/~user/doc.php</filename> gibi bir url açılmak istendiğinde, PHP users klasöründeki dosyayı açmak yerine, doc_root altındaki <filename role="uri">~user/doc.php</filename> isimli bir dosyayı açmaya </simpara> <simpara> Örneğin user_dir <filename role="dir">public_php</filename> olarak ayarlanmışsa, <filename role="url">http://my.host/~user/doc.php</filename> gibi bir istek, <filename role="dir">public_php</filename> altındaki aynı isimli dosyaya yönlendirilecektir. Eğer kullanıcının ana klasörü <filename role="dir">/home/user</filename> ise, dosya <filename>/home/user/public_php/doc.php</filename> olarak çalıştırılır. </simpara> <simpara> <parameter>user_dir</parameter> genişlemesi <parameter>doc_root</parameter> ayarından bağımsız olarak gerçekleşir, bu şekilde kök klasör erişimi ile kullanıcı klasörlerine erişim birbirinden ayrı kontrol edilebilir. </simpara> </sect2> <sect2 id="security.cgi-bin.shell"> <title>Durum 4: PHP okuyucusu web ağacının dışında</title> <para> PHP okuyucu dosyasının web ağacı dışında bir yere yerleştirilmesi çok güvenli bir kurulumdur. Dosya örneğin <filename role="dir">/usr/local/bin</filename> klasörüne konulabilir. Bu seçenek tek olumsuz tarafı uygulama dosyalarınızın başına aşağıdakine benzer bir satır koymanızı gerektirmesidir: <informalexample> <programlisting> <![CDATA[ #!/usr/local/bin/php ]]> </programlisting> </informalexample> Bu satır bütün dosyaların ilk satırına yazılmalıdır. Ayrıca bu dosyayı çalıştırılabilir hale getirmeniz gerekir. Bu şekilde, PHP aynı Perl ya da sh ya da diğer bilinen dillerin kullandığı <literal>#!</literal> shell-kaçış mekanizması ile çalıştırılabilir hale gelir. </para> <para> Bu kurulumda PHP'nin <envar>PATH_INFO</envar> ve <envar>PATH_TRANSLATED</envar> değerlerini düzgün biçimde alabilmesi için, php okuyucusu <link linkend="install.configure.enable-discard-path">--enable-discard-path</link> konfigürasyon seçeneği ile derlenmelidir. </para> </sect2> </sect1> <sect1 id="security.apache"> <title>Apache Modülü olarak Kurulum</title> <simpara> PHP Apache modülü olarak kullanıldığında, Apache'in kullanıcı izinlerini alır (genel olarak "nobody" kullanıcısının"). Bunun güvenlik ve doğrulama işlemlerine birkaç etkisi vardır. Örneğin, PHP ile veritabanına erişiyorsanız, veritabanı önyüklü bir erişim kontrolüne sahip olmadığı sürece, veritabanını "nobody" kullanıcısı tarafından erişilebilir halde tutmanız gerekir. Bunun anlamı kötü niyetli bir uygulama kullanıcı ve parola dahi kullanmadan veritabanına erişip üzerinde değişiklik yapabilir demektir. Bir web örümceğinin veritabanındaki bütün yönetici web sayfalarını alması ve veritabanınızı komple yok etmesi mümkündür. Bundan Apache doğrulama sistemini kullanarak korunabilirsiniz, ya da örneğin LDAP kullanarak kendi erişim modelinizi oluşturabilir, .htaccess kullanabilir vb. ve bu kodu kendi PHP uygulamalarınıza ekleyebilirsiniz. </simpara> <simpara> Sıklıkla, bir defa PHP kullanıcısı (bu durumda, apache kullanıcısı) çok az riskle çalışır hale getirildiğinde, PHP kullanıcı klasörlerine yazamaz hale gelir. Ya da belki veritabanlarına erişim ya da işlem yapma hakkını kaybetmiştir. PHP iyi ve kötü dosyalara, iyi ve kötü veritabanı işlemlerine eşit derecede güvenlik uygular. </simpara> <simpara> Bu noktada sıklıkla yapılan bir güvenlik hatası, apache'a root kullanıcı izni vermek, ya da Apache'in sınırlarını farklı bir yolla genişletmektir. </simpara> <simpara> Apache kullanıcısının izinlerini root seviyesine çıkartmak oldukça tehlikelidir ve bütün sistemi etkileyebilir. Bu nedenle sudo, chroot, ve diğer root olarak çalıştırma işlemleri, güvenlik uzmanları tarafından tercih edilmemesi gereken yöntemlerdir. </simpara> <simpara> Daha basit bazı çözümler mevcuttur. <link linkend="ini.open-basedir">open_basedir</link> kullanarak PHP tarafından kullanılabilecek klasörleri kontrol edebilir ve kısıtlayabilirsiniz. Aynı şekilde yalnızca Apache tarafından erişilebilecek alanları ayarlayabilir, böylece bütün web tabanlı aktiviteyi kontrol altına alabilirsiniz. </simpara> </sect1> <sect1 id="security.filesystem"> <title>Dosya Sistemi Güvenliği</title> <simpara> PHP birçok sunucu sisteme kurulu güvenlik sisteminin dosya ve klasör izinlerine uyum gösterir. Bu, size dosya sistemindeki hangi dosyaların okunabileceğini kontrol etme imkanını verir. Herkes tarafından okunabilir dosyaların, dosya sistemine erişimi olan kullanıcılar tarafından güvenle okunabilir olması mutlaka dikkate alınmalıdır. </simpara> <simpara> PHP dosya sistemine kullanıcı seviyesi tabanlı erişim sağlamak üzere tasarlandığından, PHP uygulamalarının /etc/password gibi sistem dosyalarını okumaları, ethernet bağlantıları üzerinde değişiklik yapmaları, yazıcıya ardı ardına görevler yüklemeleri ve benzeri birçok eylemi kolayca yapmaları mümkündür. Bu durum, sizi kullanıcıların hangi dosyalara okuma ve yazma hakları olduğunu denetlemeye zorunlu kılar. </simpara> <simpara> Kullanıcının kendi ana klasöründeki bir dosyayı silmek istediği aşağıdaki uygulamayı ele alalım. PHP web arayüzünün dosya yönetimini sağlamak için kullanıldığını, ve Apache kullanıcısının kullanıcının ana klasöründeki dosyaları silme iznine sahip olduğunu kabul edelim. </simpara> <para> <example> <title>Yetersiz değişken kontrolünün yol açtığı....</title> <programlisting role="php"> <![CDATA[ <?php // kullanıcının ana klasöründen dosya silme $username = $HTTP_POST_VARS['user_submitted_name']; $homedir = "/home/$username"; $file_to_delete = "$userfile"; unlink ($homedir/$userfile); echo "$file_to_delete silindi!"; ?> ]]> </programlisting> </example> username bir kullanıcı formundan gönderilebilir olduğu için, başkasına ait bir kullanıcı adı ve dosya ismi ile, istediği dosyayı silebilir. Bu durumda, bir çeşit kullanıcı doğrulama sistemi kullanmanız gereklidir. Burada gönderilen değerlerin "../etc/" ve "passwd" olduğunda neler olabileceğini düşünün. Kodu bu şekilde okursak: <example> <title>... Bir dosya sistemi saldırısı</title> <programlisting role="php"> <![CDATA[ <?php // PHP kullanıcısının izniyle silinebilecek diskteki bütün dosyalari // siler. PHP kullanıcısı root erişimine sahipse: $username = "../etc/"; $homedir = "/home/../etc/"; $file_to_delete = "passwd"; unlink ("/home/../etc/passwd"); echo "/home/../etc/passwd silindi!"; ?> ]]> </programlisting> </example> Bu durumu önlemenizi gerektiren iki önemli ölçü vardır. <itemizedlist> <listitem> <simpara> PHP web kullanıcısına ait binary dosyasına yalnızca kısıtlı erişim izni ver. </simpara> </listitem> <listitem> <simpara> Gönderilen bütün değerleri kontrol et. </simpara> </listitem> </itemizedlist> İşte geliştirilmiş bir uygulama: <example> <title>Daha güvenli dosya ismi kontrolü</title> <programlisting role="php"> <![CDATA[ <?php // Diskten PHP kullanicisinin silme izni varsa // dosyayı siler. $username = $HTTP_SERVER_VARS['REMOTE_USER']; // dogrulama mekanizmasi $homedir = "/home/$username"; $file_to_delete = basename("$userfile"); // yol ayristiriliyor unlink ($homedir/$file_to_delete); $fp = fopen("/home/logging/filedelete.log","+a"); // silme islemi kaydediliyor $logstring = "$username $homedir $file_to_delete"; fputs ($fp, $logstring); fclose($fp); echo "$file_to_delete silindi!"; ?> ]]> </programlisting> </example> Ancak bu bile istediğimizi tam olarak yapmaz. Doğrulama sisteminiz kullanıcıların kendilerine özel oturum açma hakkını tanıyorsa, ve bir bullanıcı "../etc" olarak login olmayı seçerse, sistem tekrar kırılabilir. Bu nedenle, daha özelleştirilmiş bir kontrol yazmayı tercih etmelisiniz: <example> <title>Daha güvenli dosya ismi kontrolü</title> <programlisting role="php"> <![CDATA[ <?php $username = $HTTP_SERVER_VARS['REMOTE_USER']; // dogrulama mekanizmasi $homedir = "/home/$username"; if (!ereg('^[^./][^/]*$', $userfile)) die('bad filename'); //öl, islem yok if (!ereg('^[^./][^/]*$', $username)) die('bad username'); //öl, islem yok //vb... ?> ]]> </programlisting> </example> </para> <para> İşletim sisteminize bağlı olarak, endişelenmenizi gerektirecek farklı dosyalar bulunur. Bunların arasında aygıt girişleri (/dev/ ya da COM1), konfigürasyon dosyaları (/etc/ dosyaları ve .ini dosyaları), herkesçe bilinen dosya saklama alanları (/home/, Belgelerim), vb. Bu nedenle, öncelikle her şeyi yasaklayıp daha sonra izin verilecek alanları belirlemek, kullanım açısından daha kolaydır. </para> </sect1> <sect1 id="security.errors"> <title>Hata Raporlama</title> <para> PHP güvenliğinde, hataların raporlandığı iki taraf vardır. Birincisi güvenliği arttırmaya yöneliktir, ikincisi ise azaltmaya yönelik. </para> <para> Standart bir saldırı taktiği, sisteme uygunsuz veri girişi yaparak, geri dönen hata mesajlarını incelemektir. Bu, sistemi kırmak isteyen kişiye sunucu hakkında bilgi toplama ve olası zayıflıklar hakkında fikir sahibi olma şansı verir. Örneğin, bir saldırgan form verilerinin işlendiği dosya hakkında yeterli bilgiye sahip olursa, değişkenleri ezmeye ya da onları değiştirmeye çalışabilir: <example> <title>Değişkenlere özelleştirilmiş bir HTML sayfası ile saldırmak</title> <programlisting role="php"> <![CDATA[ <form method="post" action="attacktarget?username=badfoo&password=badfoo"> <input type="hidden" name="username" value="badfoo"> <input type="hidden" name="password" value="badfoo"> </form> ]]> </programlisting> </example> </para> <para> Normal olarak döndürülen PHP hataları, uygulamasındaki hataları ayıklayan bir geliştirici için yardımcıdır. Bu şekilde hatanın yer aldığı dosyayı, sorun yaratan fonksiyonu, hangi satırın problem çıkarttığını tespit edebilir. İşte bütün bu bilgiler aynı zamanda kötü amaçlara alet edilebilir. Bir php geliştiricisinin hata ayıklama sürecinde <function>show_source</function>, <function>highlight_string</function> ya da <function>highlight_file</function> fonksiyonlarını kullanmaları az raslanan bir durum değildir. Ama yayındaki bir sitede, bu durum gizli değişkenleri açığa çıkarabilir, kontrol edilmemiş söz dizimini ele verebilir ve bu listeye daha birçok tehlikeli bilgi dahil edilebilir. Özellikle önyüklü hata ayıklama yöntemlerini ya da bilinen hata ayıklama tekniklerini kullanıyorsanız tehlike altındasınız demektir. Saldırgan hangi genel tekniği kullandığınızı belirlerse, sayfaya çeşitli ayıklama değerleri gönderebilir: <example> <title>Ortak hata ayıklama değişkenleri üzerinden saldırmak</title> <programlisting role="php"> <![CDATA[ <form method="post" action="attacktarget?errors=Y&showerrors=1"&debug=1"> <input type="hidden" name="errors" value="Y"> <input type="hidden" name="showerrors" value="1"> <input type="hidden" name="debug" value="1"> </form> ]]> </programlisting> </example> </para> <para> Hata takibi için kullanılan yöntemden bağımsız olarak, sistem hatalarına sızabilmek, saldırgan için sistem hakkında daha fazla bilgi toplamak anlamına gelir. </para> <para> Örneğin, en çok bilinen PHP hatası, sistemde PHP'nin kullanıldığını ortaya çıkartır. Saldırgan bir .html sayfası arıyorsa, ve geri planda çalışan sistemi analiz etmek istiyorsa (sistemin bilinen zayıflıklarına saldırmak için), hatalı veri göndererek sistemin PHP ile yapıldığını ortaya çıkartabilir. </para> <para> Bir fonksiyon hatası, sistemde hangi veritabanının çalıştığını ortaya çıkartabilir, ya da web sayfasının nasıl programlandığı ya da tasarlandığı hakkında ipucu verebilir. Bu, açık veritabanı portlarına yönelik daha derin araştırmaya yöneltebilir, ya da web sayfasında olabilecek hata veya zayıflıkları incelettirebilir. Farklı hatalı veri parçaları göndererek, bir saldırgan örneğin uygulama içindeki doğrulama sıralamasını bulabilir (hata satırlarından), ya da uygulamanın farklı bölümleri için geçerli olabilecek açıkları tespit edebilir. </para> <para> Bir dosya sistemi ya da genel PHP hatası, web sunucusunun hangi izinlere sahip olduğunu gösterebilir, aynı zamanda web sunucusunun yapısı ve organizasyonu hakkında bilgi verir. Geliştirici tarafından belirlenmiş hata kodu bu sorunu derinleştirebilir, bu şekilde "gizli" bilgiler kolayca açığa çıkartılabilir. </para> <para> Bu duruma ait üç önemli çözüm bulunmaktadır. Birincisi bütün kodun fonksiyonların içine gömülerek, hata mesajlarının yansıtılmamasına çalışmaktır. İkincisi, çalışmakta olan kod içersinden bütün hata raporlama işlemini kapatmaktır. Üçüncüsü, PHP'nin özelleştirilmiş hata kontrol fonksiyonlarını kullanarak kendi hata takip sisteminizi kurmaktır. Güvenlik politikanıza uygun olarak, her üç durumu da kendi sisteminize uygulayabilirsiniz. </para> <para> Bu durumdan korunmanın yollarından birisi, PHP'nin kendi <function>error_reporting</function> fonksiyonunu size kodunuzdaki güvenliği arttırmak ve kullanımı tehlikeli olabilecek değişkenleri bulmakta yardımcı olması amacıyla kullanmaktır. Kodunuzu üretim aşamasına geçmeden önce E_ALL ile test ederek, neredeki değişkenlerin farklı yollarla saldırıya uğrayabileceğini kestirebilirsiniz. Bir defa üretim aşamasına geçmeye hazır olduğunuzda, E_NONE kullanarak, kodunuzu incelemelere kapatmış olursunuz. <example> <title>E_ALL ile tehlikeli değişkenlerin bulunması</title> <programlisting role="php"> <![CDATA[ <?php if ($username) { // Kullanimdan önce kontrol edilmiyor $good_login = 1; } if ($good_login == 1) { // Yukardaki test basarisiz olursa, yaratilmayacak ve denetlenmeyecektir fpassthru ("/highly/sensitive/data/index.html"); } ?> ]]> </programlisting> </example> </para> </sect1> <sect1 id="security.registerglobals"> <title>Register Globals Kullanımı</title> <para> PHP'nin bir özelliği, <link linkend="ini.register-globals">register_globals</link> = off ile konfigüre edilerek güvenliğin arttırılabilmesidir. Bu özelliğin kapatılması, PHP içine direk olarak hiçbir değerin girmemesini sağlamak anlamına gelir. Bu şekilde, potansiyel bir saldırgan tarafından yapılabilecek değişken saldırılarını azaltmış olursunuz. Değişkenlere saldırmaya çalışmak onlara fazladan zamana mal olacak, ve iç değişkenler kullanıcı tarafından gönderilen verilerden verimli bir şekilde izole edilmiş olacaktır. </para> <para> Bu durum PHP ile çalışırken harcanması gereken zamanı arttırsa da, faydaları kaybettiğiniz zamana kıyasla çok daha fazladır. <example> <title>register_globals=off olmadan çalışmak</title> <programlisting role="php"> <![CDATA[ <?php if ($username) { // get/post/cookies ile kullanıcı tarafından değiştirilebilir $good_login = 1; } if ($good_login == 1) { // get/post/cookies ile kullanıcı tarafından değiştirilebilir fpassthru ("/highly/sensitive/data/index.html"); } ?> ]]> </programlisting> </example> <example> <title>register_globals = off olarak çalışmak</title> <programlisting role="php"> <![CDATA[ <?php if($HTTP_COOKIE_VARS['username']){ // yalnızca çerezden gelebilir $good_login = 1; fpassthru ("/highly/sensitive/data/index.html"); } ?> ]]> </programlisting> </example> Bunu akıllıca kullanarak, saldırı işlemi gerçekleştiğinde çalışacak bir uyarı mekanizması kurabilirsiniz. Değişkenin gelmesi gerektiği yeri tam olarak biliyorsanız, gönderilen verinin uygunsuz olup olmadığını denetleyebilirsiniz. Bu saldırma amaçlı kullanılan verinin tamamen durdurulabileceğini garanti etmese de, saldırganı doğru saldırı şeklini tahmin etmeye zorlar. <example> <title>Basit değişken saldırısını tespit etmek</title> <programlisting role="php"> <![CDATA[ <?php if ($HTTP_COOKIE_VARS['username'] && !$HTTP_POST_VARS['username'] && !$HTTP_GET_VARS['username'] ) { // Kullaniciyi dogrulamak icin diger yöntemleri uygular... $good_login = 1; fpassthru ("/highly/sensitive/data/index.html"); } else { mail("[EMAIL PROTECTED]", "Olası saldırı denemesi", $HTTP_SERVER_VARS['REMOTE_ADDR']); echo "Güvenlik ihlali, yönetici uyarildi."; exit; } ?> ]]> </programlisting> </example> Elbette, register_globals değerinin basit bir şekilde kapatılması, kodun güvenliğinin sağlandığı anlamına gelmez. Gönderilen her veri parçası için, farklı denetleme işlemlerinin de yapılması gereklidir. </para> </sect1> <sect1 id="security.variables"> <title>Kullanıcı tarafından Gönderilen Veri</title> <para> Birçok PHP programındaki en büyük zayıflık, dilin kendi iç dinamiklerinden değil de, geliştiricinin kodlama sürecinde güvenliği kafasında bulundurmamasından kaynaklanır. Bu nedenle, verilen kod üzerindeki olası durumlar incelenmeli, beklenmedik bir değişken gönderildiğinde oluşabilecek olası hasar tespit edilmeli ve önlenmelidir. <example> <title>Tehlikeli Değişken Kullanımı</title> <programlisting role="php"> <![CDATA[ <?php // kullanıcının... ya da bir başkasının? ana klasöründen dosya // siler unlink ($evil_var); // Erişimi kaydeder... ya da belki bir /etc/password girişi yapar? fputs ($fp, $evil_var); // Bir uygulamayı çalıştırır.. ya da rm -rf * komutunu? system ($evil_var); exec ($evil_var); ?> ]]> </programlisting> </example> Kodunuzu her zaman için web tarayıcısı tarafından gönderilen verilerin yeterli şekilde denetleyecek halde tutmalı, ve kendinize aşağıdaki soruları sormalısınız: <itemizedlist> <listitem> <simpara> Bu uygulama yalnızca istenen dosyaları mı etkiliyor? </simpara> </listitem> <listitem> <simpara> İstenmeyen verilerin kullanımı söz konusu olabilir mi? </simpara> </listitem> <listitem> <simpara> Bu uygulama hesaplanmayan biçimlerde çalıştırılabilir mi? </simpara> </listitem> <listitem> <simpara> Bu uygulama başka uygulamalarla olumsuz anlamda birlik yaratabilir mi? </simpara> </listitem> <listitem> <simpara> Bütün işlemler gerektiği biçimde arşivleniyor mu? </simpara> </listitem> </itemizedlist> Uygulamanızı yazarken bu soruları daha sonra sormak yerine şimdi sorarak, güvenliğinizi arttırmak için kodu yeni baştan yazmak durumunda kalmazsınız. Bu mantıkla yola çıkarak, belki sisteminizdeki güvenliği garantileyemezsiniz, ama geliştirilmesine ciddi olarak katkıda bulunmuş olursunuz. </para> <para> Bunların haricinde register_globals, magic_quotes ve benzeri değerleri kapatarak, değişken doğrulamasında karmaşa yaratabilecek etkilerden korunabilirsiniz. PHP'nin hata raporlaması (E_ALL) modu ile çalışmak, sorun yaratabilecek değişkenleri yaratılmadan ve denetlenmeden önce tespit etmeniz açısından size yardımcı olabilir (böylece uygunsuz verinin işlenmesini önlemiş olursunuz). </para> </sect1> <sect1 id="security.hiding"> <title>PHP'nin Gizlenmesi</title> <para> Bazı basit teknikler PHP'nin gizlenmesine yardımcı olabilir. Bu şekilde sisteminizdeki zayıflıkları bulmak isteyen saldırganları yavaşlatabilirsiniz. php.ini dosyasındaki expose_php = off değerini ayarlayarak, saldırganlara verilecek bilgi miktarını azaltabilirsiniz. </para> <para> Bir diğer taktik, apache gibi web sunucularına farklı tipteki dosyaları PHP'den geçirmesini söylemektir. Bu .htaccess dosyası ile ya da bizzat apache konfigürasyon dosyası ile yapılabilir. Aşağıdaki uzantıları kullanarak yanlış yönlendirmede bulunabilirsiniz: <example> <title>PHP'nin farklı bir dil olarak saklanması</title> <programlisting role="apache-conf"> <![CDATA[ # Make PHP code look like other code types AddType application/x-httpd-php .asp .py .pl ]]> </programlisting> </example> Ya da tamamen saklanması: <example> <title>PHP için bilinmeyen uzantı isimlerinin kullanılması</title> <programlisting role="apache-conf"> <![CDATA[ # Make PHP code look like unknown types AddType application/x-httpd-php .bop .foo .133t ]]> </programlisting> </example> Ya da html kodu gibi saklayın, yalnız bu durum performans düşüşüne neden olabilir çünkü bütün HTML dosyaları PHP motorundan geçirilecektir: <example> <title>PHP uzantıları için html tipinin kullanımı</title> <programlisting role="apache-conf"> <![CDATA[ # Make all PHP code look like html AddType application/x-httpd-php .htm .html ]]> </programlisting> </example> Bunun verimli bir bişimde çalışabilmesi için, PHP dosyalarınızın uzantısını yukardaki uzantılarla değiştirmelisiniz. Bulanıklıkla güvenliğin sağlanması bir yöntemse de, yan etkisi de kendi etkisi de az olan bir uygulamadır. </para> </sect1> <sect1 id="security.current"> <title>Güncel Tutmak</title> <simpara> PHP, diğer bütün büyük sistemler gibi, tutarlı bir gelişim sürecindedir. Her yeni sürüm sıklıkla güvenliği arttırmak ve onarmak, konfigürasyon hatalarını düzeltmek, ve sistem güvenliğinin bütünlüğünü ve kararlılığını bozabilecek hataları düzeltmek için büyük ve küçük değişiklikler içerir. </simpara> <simpara> Diğer bütün sistem seviyesindeki uygulama dilleri ve programlar gibi, en iyi yaklaşım sıklıkla güncellemek, ve son sürüm ve üzerindeki değişikliklerden haberdar olmaktır. </simpara> </sect1> </chapter> <!-- Keep this comment at the end of the file Local variables: mode: sgml sgml-omittag:t sgml-shorttag:t sgml-minimize-attributes:nil sgml-always-quote-attributes:t sgml-indent-step:1 sgml-indent-data:t sgml-parent-document:nil sgml-default-dtd-file:"../../manual.ced" sgml-exposed-tags:nil sgml-local-catalogs:nil sgml-local-ecat-files:nil End: vim600: syn=xml fen fdm=syntax fdl=2 si vim: et tw=78 syn=sgml vi: ts=1 sw=1 -->