PHP uygulamasında güvenlik uzaktan ve yerel güvenlik endişelerini içerir. PHP geliştiricilerinin her iki karakteristiği de içine alan uygulamalar geliştirebilmeleri için sahip olmaları gereken 7 alışkanlığı bu makalede listelemeye çalışacağım.
Konu güvenliğe geldiğinde, işletim sistemi ve platform güvenlik sorunlarının yanısıra kendi yazdığınız uygulamaların da güvenli olduğuna emin olmanız gerekmektedir. PHP uygulamaları yazarken aşağıdaki 7 maddeyi alışkanlık haline getirirseniz uygulamalarınızın mümkün olan en güvenli şekilde olacağına emin olabillrsiniz.
- Girdiyi doğrulayın
- Dosya sistemini koruyun
- Veritabanını koruyun
- Oturum verinizi koruyun
- Çapraz-site betikleme açıklarına (XSS) karşı koruyun
- Forum gönderilerini doğrulayın
- Çapraz-site istek sahteciliğine (CSRF) karşı koruyun.
Girdiyi doğrulayın
Konu güvenliğe geldiğinde veriyi doğulamak belki de sahip olmanız gereken en önemli alışkanlıklardan biri olmalıdır. Ve konu girdiye geldiğinde ise bu çok basittir: Kullanıcılarınıza güvenmeyin. Kullanıcılarınız muhtemelen iyi insanlardır ve muhtemelen uygulamalarınızı tam istediğiniz gibi kullanacaklardır. Ancak nerede kullanıcının veri girmesine izin verilirse, orada küçük de olsa gerçekten ama gerçekten kötü verilerin girilme ihtimali de mevcuttur. Bir uygulama geliştiricisi olarak uygulamalarınızı kötü girdilere karşı korumanız gerekmektedir. Kullanıcılarınızın girdilerinin nereye gideceğini ve netip veriler girebileceğini ince eleyip sık dokumak, güçlü ve güvenli uygulamalar geliştirmenize önayak olacaktır.
Her ne kadar dosya sistemi ve veritabanı etkileşimi hakkında yazının ilerleyen kesimlerinde konuşacak olsak da, her tür doğrulamayı içine alacak genel doğrulama ipuçları bulunmaktadır:
- Güvenilir değerler (white-listed values) kullanın
- Sınırlı seçimleri (limited selections) daima yeniden doğrulayın
- Bütünleşik kaçış fonksiyonları (escape functions) kullanın
- Doğru veri tipleri için doğrulama uygulayın, numaralar gibi.
Güvenilir değerler, geçerli olan veriler iken, güvenilir olmayan değerler geçersiz verilerdir. Buradaki ayrım, doğrulama yapılırken, muhtemel değerlerin listesi geçersiz değerlerin listesinden genellikle daha küçüktür ve bunlardan bir çoğu bilinmeyen ya da beklenmeyen değerlerdir.
Doğrulama yaparken, tüm bilinmeyen değerlere karşı korunmaya çalışmaktansa, uygulamanın sadece izin verdiklerini doğrulamak ve bunları işler kılmak genellikle daha kolaydır. Örneğin bir alan içerisindeki değerleri tüm rakamlara sınırlamak için girdinin sadece numaralardan oluşup oluşmadığını kontrol etmek daha verimli olacaktır. Nümerik olmayan veriler üzerinde arama yapacak ve bulunması durumunda onları geçersiz olarak işaretleyecek rutinler yazmayın.
Dosya Sisteminizi Koruyun
Temmuz 2000'de bir web sitesi, web sunucusu üzerinde bulunan müşteri verilerini sızdırdı. Web sitesini ziyaret eden bir ziyaretçi URL'yi, bu verileri gösterecek şekilde ayarladı. Her ne kadar dosyalar hatalı bir biçimde yerleştirilmiş olsa da, bu örnek, dosya sisteminizi saldırılara karşı korumanın önemine dikkat çekiyor.
Eğer PHP uygulamanız dosyalar üzerinde herhangi birşey yaparsa ve kullanıcının giriş yapabileceği değişken bir verisi varsa, kullanıcı girdisini temizleyerek onların herhangi bir girdi ile dosya sistemi üzerinde herhangi bir şey yapamayacaklarından emin olun. Aşağıdaki kod örneği 1, isim atanmış bir imajı indiren bir PHP sitesini örneklendiriyor.,
Kod Örneği 1: Dosya İndirmek
|
|
Sizin de görebileceğiniz gibi Kod Örneği 1 üzerindeki görece tehlikeli olan bu betik, web sunucusunun okuma yetkisi olan her dosyayı listeleyebiliyor, bunlar arasında oturum dizininizdeki dosyalar da yer alıyor (aşağıdaki oturm verisini korumak başlıklı yazıyı okuyun) ve hatta /etc/passwd
üzerindeki bazı dosyaları bile listeliyor. Bu örnek, kullanıcının örnekteki gerekçeler için veri girişi yapabileceği bir dosya adı metin kutusunu içeriyor, ancak dosya adının bir sorgu satırından (query string) oluşmaması için hiçbir neden yok.
Kullanıcı girdisi ile dosya sistemi yetkisini ayarlamak tehlikelidir, bu yüzden yapabileceğiniz en iyi şey, uygulamanızı veritabanının yanısıra gizli, oluşturulmuş dosya adları kullanacak şekilde tasarlayarak her ikisinden de kaçınmaktır. Kod örneği iki, dosya adlarını doğrulayan bir örneği içeriyor. Betik, dosya adında sadece geçerli karakterlerin kullanılıp kullanılmadığını kontrol etmek için kurallı ifadeler kullanıyor ve özellikle nokta-nokta karakterlerini kontrol ediyor: ...
Kod Örneği 2: Geçerli Dosya Adı Karakterlerini Kontrol Etmek
|
|
Veritabanınızı Koruyun
Nisan 2008'de bir Birleşik Devletler Eyaleti'nin Islah Bakanlığı, SQL sütun adlarının sorgu satırlarında kullanılmasının sonucunda gizli verilerin sızmasına sebep oldu. Bu sızıntı, şüpheli kullanıcıların görüntülemek istedikleri sütunları seçebilmesinin, sayfayı gönderebilmesinin ve veriyi alabilmesinin önünü açtı. Bu sızıntı, kullanıcıların kendi girdilerinin, geliştiricilerinin önceden göremediği şeyleri nasıl yaptırmayı akıl edebileceklerini örneklendirirken, SQL enjeksiyon saldırılarına karşı önlem alınmasının önemine işaret ediyor.
Kod örneği 3, bir SQL komutunu çalıştıran bir betik örneğini gösteriyor. Bu örnekte, SQL komutu benzer bir saldırıya izin verecek bir dinamik komutu içeriyor. Bu formun sahipleri liste seçimleri için sütun isimlerini limitlendirdikleri için kendilerini güvende hissedebilirler. Ancak, kod, seçimi sadece açılır kutular ile sınırlandırmanın, kullanıcının istediği herhangi bir şeyi içeren (asterisk [*] dahil) form göndermesinin önüne geçmediğini unutuyor.
Kod Örneği 3: SQL komutnu çalıştırmak
|
|
Yukarıdaki örneğin ışığında veritabanınızı korumayı bir alışkanlık haline getirmek için mümkün olduğu kadar dinamik SQL kodlarından kaçının. Eğer dinamik SQL kodu kullanmak zorundaysanız, sütunlar için doğrudan girdileri kullanmayın. Kod örneği 4, basit bir doğrulama limiti kullanılarak nümerik olmayan verilerin önüne geçerken statik sütunların kullanımının gücünü gösteriyor.
Kod Örneği 4: Doğrulamayı Korumak ve mysql_real_escape_string()
|
|
Bu örnek mysql_real_escape_string()
fonksiyonunun kullanımını gösteriyor. Bu fonksiyon girdiyi düzgün bir şekilde temizleyerek geçersiz bir karakter içermesinin önüne geçiyor. Eğer bugüne kadar magic_quotes_gpc
fonksiyonuna sırtınızı yasladıysanız, PHP V6 ile birlikte bu fonksiyonun artık kullanılamayacağını unutmayın. Artık onu kullanmayın ve PHP uygulamalarını onsuz bir şekilde güvenli olarak yazın. Ayrıca eğer bir ISP kullanıyorsanız, magic_quotes_gpc
fonksiyonunun aktif olmama ihtimalini gözden çıkarmayın.
Son olarak, geliştirilmiş örnekte, SQL komutunun ve çıktının dinamik sütun seçimini içermediğini görebilirsiniz. Bu sayede eğer tablonuza daha sonra farklı veriler içeren sütunlar eklerseniz, onların çıktısını alabilirsiniz. Eğer veritabınızla çalışmak için bir framework kullanıyorsanız, o zaman kullandığınız framework'ün sizin için SQL doğrulamasını halihazırda yapıyor olmasını ihtimali vardır. Emin olmak için kullandığınız framework'ün belgelerine bir göz atın; eğer hala emin değilseniz, sadece güvende olmak için err'e doğrulama uygulayın. Veritabanı etkileşimi için bir framework kullanıyor olsanız bile, diğer doğrulamayı yürütmeniz gerektiğini unutmayın.
Oturumunuzu Koruyun
Varsayılan olarak PHP'de oturum (session) bilgileri geçici bir dizin üzerine yazılır. Kod Örneği 5'te bulunan ve kullanıcının ID'si ile hesap numarasını oturumda depolayan forma dikkat edin.
Kod Örneği 5: Veriyi Oturumda Depolamak
|
|
Kod Örneği 6, /tmp dizininin içeriğini gösteriyor.
Kod Örneği 6: /tmp dizinindeki oturm dosyaları
|
|
Sizin de gördüğünüz üzere, oturm dosyası, yazdırıldığı zaman (Kod Örneği 7'ye bakın), veriyi neredeyse okunması imkansız bir biçimde içeriyor. Dosyanın web sunucu kullanıcısı tarafından hem okunabilir hem de yazılabilir olması gerektiğinden paylaşımlı sunucular üzerinde bulunanlar için oturum dosyaları sorun oluşturabilir. Sizin dışınızda birisi bir betik yazarak bu verileri okuyabilir ve bu sayede oturumdan istedikleri değerleri çekip alabilirler.
Kod Örneği 7: Oturum Dosyasının İçeriği
|
|
Oturum verinizi korumak için iki şey yapabilirsiniz. Bunlardan ilki, oturuma dahil ettiğiniz her şeyi şifrelemektir (encrypt). Ancak verinizi sadece şifrelemek, onun güvenli olduğu anlamına gelmez o yüzden oturum verilerinizi güvence altına almak için sadece bu yönteme sırtınızı yaslamayın. Bir diğer alternatif ise oturum verilerinizi farklı bir yerde depolamaktır, örneğin veritabanı gibi. Buna rağmen veritabanınızı kilitlemeyi unutmamalısınız, ancak bu yaklaşım iki problemi çözüyor: İlk, verinizi paylaşımlı bir dosya sisteminden ziyade daha güvenli bir yerde depolaması; ikincisi, uygulamanızın birden fazla web sunucusu üzerinde aynı anda çalışabilmesini sağlaması.
Kendi oturum izinizi uygulamanıza dahil etmek için PHP'deki session_set_save_handler()
fonksiyonuna bir göz atın. Bununla oturum bilgilerini veritabanında depolayabilir ya da tüm verilerinizi şifrelemek ve deşifrelemek için bir işleyici (handler) geliştirebilirsiniz. Kod örneği 8 bu fonksiyonun kullanıldığı bir örneği ve bunun dahil edilebilmesi için bir fonksiyonlar iskeletini gösteriyor. Dilerseniz buna benzer diğer örnekleri yazının devamındaki Kaynaklar bölümünde görebilirsiniz.
Kod Örneği 8: session_set_save_handler()
fonksiyon örneği
|
|
Çapraz-site betikleme açıklarına (XSS) karşı koruyun
XSS açıkları 2007 yılındaki web site açıklarının büyük bir kısmını oluşturuyor. Bir XSS açığı, kullanıcının web sitenize HTML kodu enjekte edebilmesi durumunda ortaya çıkıyor. HTML kodu script etiketleri içerisinde bir JavaScript kodu içerebilir ve JavaScript'e izin vermek sayfanın görüntülendiği her zaman kod çalıştırmaya izin vermek anlamına gelir. Kod Örneği 9'daki form bir forumu, wikiyi, sosyal ağı ya da metin girmenin normal olduğu herhangi bir sitede görülebilir.
|
|
Kod örneği 10, bu formun sonuçları nasıl yazdırabileceğini ve bu sayede XSS saldırılarına izin verebileceğini gösteriyor.
Kod Örneği 10: showResults.php
|
|
Kod örneği 11 Google ana sayfasını yeni pencerede açabilen bir örneği gösteriyor. Eğer web uygulamanız XSS saldırılarına karşı korunmalı değil ise, verilebilecek zararın büyüklüğü tamamen saldırganın hayalgücü ile sınırlıdır. Örneğin birisi sitenin tarzını yansıtan ve sazan avlama (phishing) olarak bilinen sitelere yönlendiren bir bağlantıyı sisteminize dahil edebilir.
Kod Örneği 11: Şüpheli metin girişi örneği
|
|
Kendinizi XSS saldırılarına karşı korumak için girdinizi htmlentities()
fonksiyonunuzu kullanarak, girdinin görüntülenebileceği her yerde filtreleyin. Unutmayın, alışkanlık haline getirmeniz gereken ilk ipucumuzda, verinin güvenilir verilerle doğrulanmasını gösteriyordu.
Bu sayfanın çok daha güvenli bir sürümü aşağıda gösteriliyor.
Kod Örneği 12: Daha Güvenli bir Form
|
|
Forum gönderilerini doğrulayın
Form sahteciliği, sizin öngörmediğiniz bir yerden sitenizdeki formlardan birine giriş yapılması anlamına gelir. Bir formu kandırmanın en kolay yolu, tüm verileri aktararak formu gönderen bir web sayfası oluşturmaktır. Web uygulamaları tabir-i caizse yersiz yurtsuz olduklarından gönderilen verinin istediğiniz yerden gönderildiğine emin olmanın kesin bir yolu yoktur. IP adreslerinden sunucu adlarına günümüzde her şey artık taklit edilebilr. Kod örneği 13, veri girişi yapabileceğiniz bir formu gösteriyor:
Kod Örneği 13: Metin işleyen bir form
|
|
Kod örneği 14, Kod Örneği 13'teki forma veri gönderen bir formu gösteriyor. Bunu denemek için 13. kodu web sunucunuza kaydedebilir, 14. kodu ise bir HTML belgesi olarak masaüstünüze kaydedebilirsiniz. Bu formu kaydettikten sonra web tarayıcınız üzerinde açın. Ardından boşlukları doldurabilir ve formu gönderebilirsiniz.
Kod Örneği 14: Verinizi Toplayacak Bir Form
|
|
Form sahteciliğinin olası etkisi, gerçekten, eğer formunuz açılır kutlar, seçim düğmeleri, onay kutucukları ya da diğer sınırlandırılmış veri giriş yöntemleri kullanıyor olsun, formun sahte olması durmunda bunların bir değerinin kalmıyor olması. Kod Örneği 15'teki geçersiz veri içeren koda dikkat edin.
Kod Örneği 15: Geçersiz veri içeren bir form
|
|
Bir düşünün: Eğer kullanıcınin gireceği veriyi sınırlandıran açılır kutunuz ya da seçim düğmeleriniz var ise, girilen veriyi doğrulamanın gerekli olmadığını düşünebilirsiniz. Ne de olsa girdi formunuz kullanıcının sadece belirli bir tip veri girmesini sağlıyor, öyle değil mi? Form sahteciliğini sınırlandırmak için, girilen verinin söylediği şey olup olmadığını kontrol etmeniz gerekir. Kullanabileceğiniz bir teknik, tek kullanımlık bir anahtar oluşturmaktır. Bu yöntem her ne kadar form sahteciliği sorununu kökünden çözmese de, bu işlemi oldukça zorlaştıracaktır. Her bir form oluşturulduğunda şifre değişeceğinden, saldırganın gönderi formunun bir kopyasını alması, şifreyi ayıklaması ve kendi formlarına entegre etmesi gerekir. Bu yöntem bir kişinin tek bir form oluşturarak web uygulamanıza istenmeyen verilerin gönderilmesinin önüne geçer. Kod örneği 16 tek kullanımlık form anahtarı kullanan bir örneği gösteriyor.
Kod Örneği 16: Tek kullanımlık form anahtarı kullanmak
|
|
Çapraz-site istek sahteciliğine (CSRF) karşı koruyun.
Çapraz-site istek sahteciliği (Cross-Site Request Forgeries - CSRF Saldırıları), bir saldırı yürütmek için kullanıc ayrıcalıklarından faydalanan açıkları kullanır. Bir CSRF saldırısında, kullanıcınız şüpheli olmayan suç ortağı haline kolayca dönüşebilir. Kod Örneği 17, benzer bir eylemi içeren örnek bir sayfayı gösteriyor. Bu sayfa, kullanıcı giriş bilgisine çerezler (cookie) üzerinden ulaşıyor. Çerez geçerli olduğu sürece, web sayfası o isteği işleyecektir.
Kod Örneği 17: Bir CSRF Örneği
|
|
CSRF saldırılar genellikle
etiketleri biçimindedir çünkü tarayıcılar o imajı görüntülemek için belirtilen URL'yi çağırırlar. Ancak imaj kaynağı, kendisine görülen parametreleri içerisine alabilen bir web sayfasının adresi de olabilir. Bu
etiketi XSS saldırısına dahil edildiğinde -ki bu durum bugüne kadar belgelenen saldırılarda en sık görülen yöntemdir- kullanıcılar farkında olmadan kendi verilerini kullanarak işlem yapılmasının önünü açabilirler - ki bu bir sahteciliğin bir parçası da olabilir.
Kendinizi CSRF saldırılarına karşı korumak için, formlarınızı doğrulamak için edinmeniz gereken tek kullanımlık anahtar kullanımı alışkanlığını kullanabilirsiniz. Ayrıca $_REQUEST
yerine kesin $_POST
değişkenini kullanın. Kod örneği 18, veriyi, ister GET
isteği ile alan, isterse de verinin kendisine postalanması ile alsın, kötü şekilde kodlanmış bir web sayfası örneğini gösteriyor.
Kod Örneği 18: $_REQUEST
üzerinden veriyi almak
|
|
Kod örneği 19 ise sadece POST
kullanan formları işleyen, yukarıdaki sayfanın temizlenmiş bir örneğini gösterir.
Kod Örneği 19: Veriyi sadece $_POST
üzerinden almak
|
|
Sonuç
Daha güvenli PHP Web uygulamaları yazmak için bu 7 alışkanlığı edinmeye başlamak, sizi çeşitli saldırıların kurbanı olmaktan koruyacaktır. Tıpkı diğer alışkanlıklarda olduğu gibi, ilk bakışta biraz garip görünebilirler, ancak zaman geçtikçe size daha doğal görünecektir.
İlk alışkanlığın önemli olduğunu unutmayın: Girdinizi doğrulayın. Girdinizin kötü bir değer içermediğinden emin olduktan sonra dosya sisteminizi, veritabanınızı ve oturumunuzu korumaya başlayabilrsiniz. Son olarak PHP kodunuzun XSS saldırılarına, form sahteciliğine ve CSRF saldırılarına karşı korunmalı olduğundan emin olun. Bu alışkanlıkları hayata geçirecek disiplinli bir yaklaşım, basit saldırıların önüne geçmede size çok büyük yardımı dokunacaktır.
Kaynaklar
Öğren
- Bir developerWorks dersi olan "PHP uygulamalarınızı kilitlemek" makalesini okuyarak geliştiricilerin gözden kaçırmaması gereken dört önemli güvenlik kuralını öğrenin.
- "Sıradan İnsan İçin PHP Şifrelemesi"'ni okuyarak PHP uygulamalarındaki veriyi nasıl güvence altına alabileceğinizi öğrenin.
- "PHP Güvenlik Konsorsiyumu"nu ziyaretederek PHP güvenliği hakkında daha fazla bilgi alın.
- Resmi PHP Web Sitesi üzerinde bulunan "PHP Güvenlik Sitesi"ni ziyaret ederek güvenlik ipuçlarına ulaşın.
- Resmi PHP Web Sitesi üzerinde bulunan "
session_set_save_handler
" girdisini okuyarak özel oturum işleyicileri hakkında daha fazla bilgi alın. - Wikipedia üzerinde bulunan mükemmel XSS girdisini okuyun.
- Chris Shiflett'in "Esaslı PHP Güvenliği" makalesini okuyun.
- PHP geliştiricilerinin ortak buluşma noktası PHP.net'i unutmayın.
- "Önerilen PHP makaleleri listesi"ne bir göz atın.
- developerWorks üzerindeki tüm "PHP İçeriğine" bir göz atın.
- IBM developerWorks'ün "PHP proje kaynakları"nı inceleyerek PHP yeteneklerinizi arttırın.
- Yazılım geliştiricileri ile yapılan ilgi çekici röportajlara ve sohbetlere ulaşmak için developerWorks podcastlerini kontrol edin.
- PHP ile veritabanı mı kullanıyorsunuz? IBM DB2 V9'u destekleyen kurulumu kolay PHP gelişimi ve üretim ortamı olan IBM İçin Zend Core ile tanışın.
- developerWorks'ün Teknik etkinlikler ve webcastleri ile gündemi takip edin.
- Önümüzdeki dönemde düzenlenecek olan konferansları, fuarları, webcastleri ve IBM açık kayna geliştiricilerini ilgilendiren diğer Etkinlikleri takip edin.
- Zengin nasıl-yapılır bilgisi, araçlar ve IBM ürünleri ile kullanacağınız açık kaynak teknojilerini geliştirebilmenize yardımcı olacak güncel proje haberleri için Açık kaynak bölgesini ziyaret edin.
- Ücretsiz developerWorks'ün istediğiniz an izleyebileceğiniz demoları ile IBM ve açık kaynak teknolojileri ve ürün özellikleri hakkında bilgi edinin.
Ürünleri ve teknolojileri alın
- IBM trial yazılımını indirererek ya da DVD'sini satın alarak bir sonraki açık kaynak projenizi yaratın.
- IBM ürün doğrulama sürümlerini indirin ve DB2®, Lotus®, Rational®, Tivoli®, ve WebSphere®'den özel yazılım ürünlerini ve uygulama geliştirme araçlarını kullanmaya başlayın.
Tartışın
- developerWorks bloglarına katılın ve developerWorks komünitesine dahil olun.
- developerWorks PHP Forumu: IBM Bilgi Yönetim Ürünleri (DB2, IDS) ile PHP Uygulamaları Geliştirmek forumuna katılın.
Kaynak: IBM
Çeviri: Emrah Ömüriş
Hiç yorum yok:
Yorum Gönder