Sunucu Güvenliği: CSRF – Cross Site Request Forgery

Türkçesi siteler arasında talep sahteciliğidir. XSRF olarak da kısaltılır. Çok basit anlamıyla sitenize istek gerçekten sitenizden mi geliyor sorusuna net cevap veremiyorsanız CSRF açığınız olabilir. İlk örnek olarak bir kullanıcı giriş formunun gerçekten acemi bir yazılımcının elinde GET sorgusu ile yapıldığını düşünelim. Form yaklaşık şöyle olsun.

Bu form gonderildiginde

gibi bir ürl oluşturacaktır. Peki bu ÜRL gerçekten bizim sitemizdeki giriş formu ile mi oluşturuluyor ? Yoksa başka bir websitesinden ya da client ile sitemizde çeşitli kullanıcı adı ve şifre kombinasyonlarını denemek üzere sorgu üretmek için mi gönderildi ? Haliyle beklentimiz, olması gereken formun bizim siteden gönderilmiş olması. buna emin olabilmemiz. Bunun ile ilgili alınabilecek ilk tedbir madem GET metodu ile gönderilen formlarda böyle bir risk oluşuyor, biz de POST methödü ile formu göndeririz olabilir. Bu oldukça basit, basit olduğu kadar da geçersiz bir tedbir maalesef. Zira linux terminalden curl ile bir POST yapmak şu kadar basittir:

Demek ki POST yeterli değil. Fakat gereksiz de değil tabi ki. Zira aynı browser programını kullanan iki farklı kullanıcının birbirinin parolasını görmesini de istemeyiz. Peki başka ne yapabiliriz? Giriş formları için her formda benzersiz olacak şekilde biletler oluşturabiliriz. Formdan veri geldiği zaman da bu biletleri bizim o oturum için kaydettiğimiz bilet mi değil mi kontrol ederek giriş işlemlerine devam edebiliriz. Örneğin;

Bu gizli form elemanı ile oluşturduğumuz bilet kodumuzu giriş taleplerinde değerlendirmek üzere session değişkeni olarak kaydediyoruz. Giriş talebi geldiği zaman bakalım bu kod ile bizim kaydettiğimiz aynı anlamayı deniyoruz.

Peki bu şekilde token oluşturmamız ve session ile kullanmamız güvenli mi? Hayır ama GET değerini POST yapmaktan daha ciddi bir adım attığımız kesin. Peki neden güvenli değil ? Çünkü session anahtarınız bir şekilde XSS açıkları ile veya başka bir şekilde çalınırsa sizin formunuz için üretilmiş bir bilet kodu da saldırganın eline geçmiş olur ve sistemde geçerli olur. Peki bu durumda daha fazla güvenlik için ne yapılıyor ?

İşte artık pek çok sitede gördüğünüz insan miyiz ? sorusuna geldik yani captcha ! Bu aşamaya kadar yaptığımız her şeyi koruyoruz ve artık kullanıcıların sitemizden POST methödü ile giriş yaptığını biliyor, form gönderilerinde bilet kodumuzu kontrol ediyor ve aynı zamanda sitemizde bilet kodu ile birlikte giriş denemesi ile eşleştirilen bir bilgi daha kullanıyoruz. Resim içerisinde insanların okuyabileceği şekilde yazılmış rasgele 3-6 karakter gibi. Örnek verelim;

Bu kisimda giris formu;

Artık kullanıcı oluşturduğumuz bu resmi okuyarak onayını bir form elemanına yazıyor. Bu sayede artık sitemizde her yeni istek yapmak isteyen saldırganın bilet kodumuzu çalsa da captcha yazması gerekiyor. Saldırganı biraz daha yavaşlattık. Artık bilet koduna gerçekten ihtiyacımız yok çünkü kullanıcı çaptcha ile kodu zaten yazmış oluyor. Ama method olarak POST kullanmaya devam ediyoruz.

Fakat yeterli mi ? Maalesef yine hayır. Çünkü Hindistan’da belirli meblağlar karşılığında bu çaptchaları sizin için okuyan bir takım çeteler var. Evet şaka değil insanlar size tam anlık olmasa da bu verileri okuyup para karşılığı gönderiyor. Bu yüzden kendiniz çaptcha üretmek yerine pek çok sitede gördüğünüz çaptcha servislerini kullanmanızı tavsiye ederim. Zira bu servisler sizin fazladan kod yazmanızı gerektirmeden çaptchayı deneme sayısını arttıran kullanıcı için zorlaştırıyorlar. Örneğin ilk denemesinde sadece çaptcha kutusunu işaretleten servis zamanla resim hatta ses dinleterek çaptcha onay aşamasını uzatıyor. Tabi siz de her denemede çaptcha karakterini uzatabilirdiniz ama bu sefer de başka yerlerde bolca deneme yapmış şüpheli bir kullanıcıya işin başında zor bir çaptcha sunmak için nedeniniz olmayacaktı. İşte bu servisler vpn kullanan, cookie kabul eden, virtual browser kullanan kullanıcıları genel olarak mimleyerek tüm internetin güvenliğine katkıda bulunuyorlar. Servis alternatiflerine bu adresden ulaşabilirsiniz.

Peki işimiz kullanıcı giriş formu ile bitti mi? Maalesef yine hayır. Özellikle XSS açığı bulanan bir websiteniz var ve sitenizde frame kullanımı apaçhe ayarlarınızda açıksa şöyle bir sorununuz daha var demektir. Kullanıcı şifresi değiştirme sorguları. Şöyle ki bir kullanıcınız sitenize giriş yaptı. Bir şekilde saldırgan giriş yapmış bu kullanıcıya kendi sitesini de ziyaret ettirtti. Kendi sitesinden ise daha önce üye olarak sitenizden aldığı parola değiştirme kısmının kodlarını aldı ve JS ile bu kodları masum kullanıcınıza çaktırmadan tetikleyip parolasını kendi belirlediği bir parola ile değiştirdi. Kullanıcımız yazdığınız koda göre logout olabilir ya da oturumu bittiği zaman bir daha siteye giremeyebilir. Çünkü saldırgan çoktan değiştirmiştir şifreyi.

Bu durumda ne yapmalısınız ? Benim önerim ve her zaman yaptığım şey, kullanıcınız yönetici türünde bile olsa profil bilgilerini güncellerken mutlaka şifre sormanız. Bu şekilde parolasını bilmeyen saldırgan parola güncelleme sayfasında işlem yapamayacaktır.

Artık canınız sıkıldı belki ama yine soralım peki bu yeterli mi ? Hayır. Çünkü saldırgan kullanıcı hesabını geçirmekten öte kullanıcı adına çaptcha ya da şifresini oturum sırasında tekrar girmediği yerlerde POST işlemleri yapabilir. Örneğin kullanıcılar arası mesajlaşma imkanı olan bir sitede bir kullanıcıdan diğerine mesaj göndererek spam sayfasına link gönderebilir. Bu durumda en önemli güvenlik tedbiri XSS açıklarını kapattığınıza emin olmaktır. XSS ile ilgili yazım için buraya tıklayabilirsiniz. 

CSRF saldırıları ile ilgili yeni bilgiler edinirsem bu blog kapsamında paylaşmaya devam edeceğim. Herkese iyi çalışmalar…

Sunucu güvenliği: XSS – Cross Site Scripting

Dinamik websitelerindeki güvenlik aciklarindandir. Öğrendiğim kadarıyla GET üzerinden sunucuya gönderilen verinin tamamlayici kodlarla değiştirilerek scriptin çıktılarının manipüle edilmesine dayanıyor. Bu tür açıkları olan siteleri saldırganlar arama motorları üzerinden arayarak bulabiliyor. Bunun için kullandıkları tespit edici arama kelimelerine saldırgan jargonunda dork deniyor.

Örneğin; inurl:sayfa.php?id=1 gibi. Bunun yanına gov vb. domain uzantılarını yazarak belirli türdeki siteleri hedefleyebiliyorlar. Bulunan her sitede açık var diyemeyiz. Buldukları sitelerde XSS açığı olup olmadığını XSS denemesi yaparak anlayabiliyorlar.

Örneğin deneme şekli olarak URL adresine şunun gibi bir şey yazıyorlar;

Ekrana uyarı penceresi gelirse ha evet XSS açığı varmış diyorlar ve farklı XSS scriptleri ile sitenin scriptini farklı şekilde tamamlayarak sitenin sunucu tarafındaki kod ve verilerine erisiyorlar.

XSS Saldırı Türleri

Stored XSS

Bu saldırı turu XSS ile sunucuya gönderilen kodun tüm kullanıcıları etkilemesi söz konusu. Yani kullanıcıların şifreleri dahil bilgileri çalınabilir.  Ornegin kullanıcı giriş sayfasında çalışan bir veritabanı sorgusu mevcutsa, bu sorgunun çıktısı ile kullanıcı giriş formu değiştirilip, kullanıcının giriş yapmak için yazdığı bilgiler farklı sunuculara gönderilerek depolanabilir. Kullanıcılar her sitede benzer ya da aynı şifreleri kullandığı için epostalari ve diğer sosyal medya hesapları da tehlikeye girmiş olur. Sadece veritabanına erişim sağlandığı durumlarda kullanılan saldırı şekli bu olmakta.

Reflected XSS

Bu saldırı veritabaninda duran kodlar yerine URL içerisinden gönderilen GET değişkenleri yapılabiliyor. Saldırı turu ziyaretçilere direkt olarak yansımıyor. Fakat üye olduğu bilinen bir epostaya gönderilen örneğin bir şifre hatırlatma URL adresi ile yine kullanıcının bilgileri tehlikeye atılmış olur. Bu tur saldırıda veritabanı veya kodlara saldırgan erisememis olabilir. Fakat bu acemi internet kullanıcıları için tehlikeyi bertaraf etmiş olmuyor.

DOM XSS

Bu noktada sitenin kodlarına da artık erişim sağlanmış oluyor. Sitenin içerisine javascript kodları ile normalde olmaması gereken, kullanıcıya gösterilmeyen bir takım kodlar eklenerek kullanıcı verileri calinabiliyor.

XSS ataklarından korunmak

GET ile gönderilen page veya id gibi değerlerin HTML, JS vb. kodlardan temizlenmesi gerekiyor. Bunun en ilkel yollarından biri PHP için htmlspecialchars kullanarak kodlarin htmlden dönüştürülmesi. Bu konu iyi bir framework ile aşılabilir. Örneğin kullandığım Symfony framework HTTPComponent ile bu tur şeyleri önlüyor. Ayrıca route tanımlarına değişkenlerin içerebileceği karakterler sinirlanarak sadece sayı veya metin olabilir gibi regex ifadeleri de eklenebiliyor. Fakat Symfony gibi bir framework kullanmak öğrenmesi ciddi zaman alan ve uygulama yapması da o kadar çabuk olmayan bir yapı ve büyük siteler için kullanılır. Bu yüzden apache düzeyindeki tedbirler hem sistemciler hem geliştiriciler için daha basit ve kapsam olarak da geniş diyebilirim.

Apache için XSS tedbirleri

Fakat bu oldukça ilkel şekilde yazılmış bir websitesi için alınabilecek bir tedbir. Eğer sunucunuz linux ise veya .htaccess dosyaları web alaninizda çalışacak şekilde ayarlanmissa apache sunucusu için farklı ve genel bir tedbir daha var. Bunu yapmak için sunucuda apache mod_headers aktif olmalı.

XSS ataklarını engellerken bir ayar daha var. Bu da x-frame ayarı. Bu aşağıdaki satır sitenizde açılabilecek frame ve iframelerin sadece yine sizin sitenizden olmasını gerektiriyor. Bu sayede farklı saldırgan adresleri kullanicilarinizin verilerine talip olamıyor. SAMEORIGIN degerini DENY yaparsanız kendi sitenizden bile frame açılmıyor.

Özellikle izin vermek istediniz frame URL adresleri olması durumunda ALLOW FROM uri kullanabilirsiniz.

Bir başka nokta ise XSS atağının upload edilmiş bir dosyanın içeriğinin değiştirilerek yapılabilir olması. Yani bir resim dosyası upload etmesini beklediğiniz kullanıcı resim dosyasının sadece header bilgilerini kullanıp devamında sunucunuzda çalıştırmak istediği kodları eklemiş olabiliir. Bunu için X-Content-Type koruması kullanılıyor. Buradaki mantık siteye JPG uzantılı bir dosya gönderilmesine rağmen aslında html ve js içerikli bir dosyanın gönderilmiş olması. Mime-Type kontrolü yapmayan bir upload işleminden bu geçebilir. Kullanıcı browser ise dosya açıldığında uzantısı JPG olmasına rağmen mime-type html/text olduğu için bu resim dosyasını siteymis gibi calistirabilir. Bu veritabanı yerine dosya olarak depolanmış bir XSS açığı demek oluyor. Bunu için .htaccess dosyanizda ya da virtualhost taniminizda aşağıdaki satırı kullanmanız gerekiyor. Bu sayede dosya tipine browser karar vermiyor, sunucunuzdaki dosya uzantısı geçerli oluyor.

Diğer bir XSS açığı konusu httpOnly ile cookie koruması sağlayarak PHP ile oluşturulmuş bir cookieye JS ile erisilip kullanıcının bilgilerinin başka yerlere gönderilmesinin önüne geçmektir. PHP SessionId gibi bir cookie değeri browser içine saldırgan tarafından koyularak açılmış oturum anahtarı kullanılıp oturuma ortak olunabilir. Bunu için bu satırı .htaccess veya apache virtualhost için kullanıyoruz.

Bir başka XSS tedbiri  TraceEnable değerini kapatıp off yapmaktir.

Bunun dışında CSP ile daha detaylı CSS ve JS çağrıları yaparak farklı sitelerden yapılacak css ve js dosyalarının sitenize çalışmasını önleyebilirsiniz. Bu adreste CSP hakkında cidden detaylı bir kaynak var. Kısaca ilgili satır şöyle oluyor;

Genel olarak toparlarsak .htaccess dosyamız ya da virtualhost ek satırlarımız şöyle oluyor;

Burada sadece XSS ile ilgili bir takım tedbirlerden söz ettim. Bunlar hem diğer ataklar için yeterli değil hem de XSS için yeterli olmayabilir. Daha farklı bilgilerle güvenliğinizi arttırabilirsiniz. Yeni XSS tedbirleri bulursam bu blog icinde tekrar paylaşacağım.

Yeni satirlar (12 Ekim 2017)

X-Frame-Options ayarimizi SAMEORIGIN ya da DENY olmasi, bir baska siteden frame acarak sitemizin gorunmesini engelliyor. Fakat baska bir sitede acilmis frame icindeki form bizim sitemize hala POST yapabilir. Islem sonunda bir veri ekrana cikacaksa da cikmiyor.

PHP calisma modu ve XSS (19 Ekim 2017)

PHP calışma modundan dolayı cPanel/centos sıstemlerde apache security modul için bazen .htaccess dosyasında headers satırlarını tetiklemiyor. Bunun nedeni anladığım kadarı ile php dosyalara apache üstünden değil direkt olarak php’nin cevap verecek şekilde ayarlanması. Bu durumda header tanımlarını PHP header olarak yazmanız gerekiyor. Tum dosyalarda include edilen veritabanı bağlantisi içeren bir dosya içinde bunu yaparsanız XSS vb header bilgilerini görebiliyorsunuz.

Yeni Başlayan Programcılara Tavsiyeler

Yıllardır program yazan birisi olarak bazı tecrübelerimi paylaşmak istedim. Kısa vadeli hızla para kazanmak gibi hedefleriniz varsa bunları okuyarak zaman kaybetmemenizi tavsiye ederim. Mesleğini sevip, amatör ruh taşıyan biriyseniz, umarım bunlardan fayda görürsünüz.

Her Gün İngilizcenizi Geliştirin
İngilizce öğrenin demiyorum. Her gün İngilizcenizi geliştirin. Eski bildiklerinizi tekrar edin. Yeni teknik terimleri mutlaka ingilizcesi ile de öğrenin. Eğer hiç ingilizce bilmiyorsanız sakın oturup bir programlama dili öğrenmeyin. Mutlaka önce ingilizceyi okduğunuzu anlayacak kadar öğrenin. Evrensel anlamda meslek sahibi olmak ve belki de bir gün literatüre katkıda bulunmak için bu mutlaka şarttır.

Önce Teoriyi Öğrenin

Bir programlama dilinin komutlarını, söz dizimini öğrenmek sizi kesinlikle programcı yapmaz. Sadece bir kodlayıcı olursunuz. Ayrıca iyisinden bir kodlayıcı ( coder ) da olamazsınız. Bu yüzden Programcı olmaya çalışın. Yani işin analiz, test, gerçekleştirme ve değerlendirme aşamaları gibi teorik kısımlarını, bunlar içerisinde analiz teknikleri, tasarım kalıpları gibi bir takım alt teorik disiplinleri mutlaka öğrenin. Yani yazdığınız kodun ne dediğini bilmek ve bunu bazen uzun bazen kısa ama doğru şekilde söylemek için bunlara ihtiyacınız var. Bu sayede programlama dili içinde ya da programlama dilleri arasında çekiçle çivi çakmak dışında iş yapmamanız gerektiğini de keşfedecek, her aracı doğru yerde kullanarak en çokta kendinizi yıpratmaktan ve hayatınızı kısır döngülere sokmaktan kurtulacaksınız.

Algoritma öğrenin. Algoritma size düşünmeyi ve küçük hataların ya da öngörüsüzlüğün programcılık dünyasında ne kadar büyük sorunlar ortaya çıkartabileceğiniz gösterecektir. Düşünmeden iş yapmamak için algoritma öğrenmeniz gerekir.

Bir programlama dili öğrenmeden önce değişken, fonksiyon, sınıf, aduzayı, soyut sınıflar, bağımlılık enjeksiyonu, annotations öğrenmeniz o dili öğrenirken sadece zaten programlama işlerinin o dilde nasıl ifade edildiğini anlamanız demek olacaktır.

Yaklaşım öğrenin. Dünya bugün pek çok programcının iddia ettiği üzere sadece nesne yönelimli olarak üretilmiş programlar kullanmıyor. Fonksiyonel, prosedürel, cephe yönelimli ya da nesne yönelimli yaklaşımların her birinin farklı büyüklükteki programlarda, farklı şartlar ve imkanlar dahilinde verimli olacağını bilin. Kısa olmayan bir zaman sonra hangisini neden ve nerede kullanmanız gerektiğini çok daha iyi anlayacaksınız.

Proje yönetimi öğrenin. Bu sizi çok daha iyi bir programcı yapacaktır. Hangi proje yönetiminde hangi aşamalar nasıl diziliyor anladığınızda elinizdeki veriler ve imkanlar doğrultusunda amaçlarınıza nasıl daha hızlı ve verimli ulaşacağınızı anlayacaksınız. Öngörüleriniz ve pazara bakış açınız doğru kriterleri kullanan anlamlı bir şekil alacaktır. Bu sayede bilgili ve bilgisiz insanları daha hızlı ayırt edip, olmayacak duaya amin diyen pek çok kişiyi ve projeyi başından öngörecek ve zaman kaybetmeyeceksiniz. CPM-pert ya da agile kullanacağınız projeler MVC, MVVM ya da DCI kullanacağınız projeler ayrıdır. Bunların ayrı olma sebeplerini sahip olduğunuz imkanlar ve hedefleriniz doğrultusunda avantaj ve dezavantajları ile ilişkilendirdiğinizde kendinizi daha güvende hissedeceksiniz.

Dataya Yakın Olun

Bunun anlamı işleyeceğiniz veri ile aranıza koyabildiğiniz kadar az araç, arayüz yani daha az kod koymanızdır. İlla veriye erişim bir takım programlar yani kodlar üstünden olacaksa bu kodların açık kaynak olmasına çalışın.

Sözgelimi SQL komutlarını bir takım arayüzlerle vermeye çalışmayın. Mesela MySQL kullanıyorsanız komut satırında iş yapın. Gerçekten gerekmedikçe araya bir Workbench koymayın, benzeri araçları kullanmayın.

Kullandığınız IDE’ler gereksiz dosyalar oluşturmasın ve mümkünse bazı karakterleri gizlemesinler. Mesela VIM ya da Emacs kullanın ve gerçekten gerekmedikçe eclipse, netbeans, sublime text gibi editörler kullanmayın.

İşletim sistemi olarak mutlaka unix türevi bir sistem tercih etmeye çalışın. Hatta linux tercih edin. Linux üstünde arayüzler, browserlar kullanmak tabi ki zorundasınız. Fakat çok iyi bir terminal kullanıcısı olmayı sakın es geçmeyin.

Versiyon yönetim araçları kullanıyorsanız GIT kullanın. CVS ve SVN gerekmedikçe artık kullanmanızı tavsiye etmediğim eski teknolojilerdir. Bu araçları da mutlaka komut satırında olabildiğince orjinal komutları ile fazla alias yazmadan kullanın.

Yazılım Hem Bilim Hem de Sanattır

Bu iki sebepten dolayı yazılım dünyasında evrensel olarak anlam taşımayan hedeflerden uzak durun. Söz gelimi milliyetçi ruhunuza yenik düşerek yerli bir işletim sistemi yapmaya kendinizi adamak yerine, herkesin katkıda bulunabileceği ve bunun sistematikleştirildiği açık kaynak dünyasına katkıda bulunun. Bu şekilde kodunuz değil, bilginizin ne kadar hızlı arttığını görecek, bilmediğiniz şeyleri öğrenmek bir yana belki de bulunduğunuz ülkede henüz farkedilmemiş bilgilere , misyona ve vizyona erişebileceksiniz. Çevrenizde sizden çok daha zeki ve tecrübeli insanların artması bu anlamda güzel bir emaredir. Aynı zamanda çok şanslı olduğunuzu gösterir.

Bu anlamda mümkünse yerel projelere katılmak yerine yerelleştirme projelerine katılmanız çok daha iyi olacaktır. Açık kaynaklı bir programı Türkçe dili eklemek ya da ona bir dil sistemi eklemek bile sadece Türkçe dökümanı olan ve Türkçe bilmeyenlerin anlayamayacağı, geliştirmeye katılamayacağı/katılmayacağı bir sistem geliştirmekten çok daha iyidir.

Esinlenin

Bunu farklı programların muadilini yapmak adına o programlardan özellik ya da kod alın anlamında kullanmıyorum. Fakat bu dediğim de yanlış değil. Eğer açık kaynak ya da kapalı kaynak yazılım yazılım geliştiriyor ve ilgili lisansın ( GNU, BSD, MIT ) kapsamı dışına çıkmıyorsanız kodda alabilir, kütüphanede kullanabilirsiniz tabi ki.

Asıl kastettiğim konu ise farklı disiplinlerden esinlenmeniz. Örneğin bir antivirüs yazılımı yazıyorsanız biyolojik virüslerin nasıl yok edildiğini araştırın. Bu anlamda bir yazılım güvenliği işi yapıyorsanız, bir doktorun nasıl muayene ettiğini, neyi gözönüne aldığını düşünün. Yazılım bilimleri yoğun matematiğe dayansa bile unutmayın ki disiplin olarak pek çok bilim dalından daha genç. Somut ürünler ortaya çıkartan fizik, kimya, tıp gibi alanlar eğer düşündüğünüz üretim senaryoları ya da algoritmalar ile ilgili paralel bir çözüm havuzuna sahipse bunları inceleyin. Özellikle oyun yazıyorsanız oyun teorisini kurmak için masa oyunlarının tavla, satranç hatta monopoly’nin kazanç-rakip ve başarı-başarısızlık gibi kurguları nasıl sistematikleştirdiğini iyi anlayın. Sizin oluşturacağınız teorilerde önünüze ışık tutacak veriler ve düşünüş şekilleri elde edebilirsiniz.

Son Söz

Burada halkımızın pek alışık olmadığı belki de on yıldan fazla sürenizi alacak ciddi uzun bir süreçten bahsetmeye çalıştım. Herhangi bir alanda da on yıldan az uğraşmış birisinin uzman ya da profesyonel olduğunu iddia etmesini pek haklı görmediğimi belirteyim. Bu yüzden mesleğinize sadakat ve vefanız konusunda yanlış yapmamanızı salık vererek, sıra ile takip etmeniz gerektiğini düşündüğüm tavsiyeler halinde verdim. Bu anlattıklarımın Türkiye’de çalışan ve iş yapanların sadece binde birine hitap ettiğini düşündüğümü de belirteyim. Yani bu anlattıklarım işinizi gerçekten sevmiyorsanız ve onunla evli değilseniz sizi mutlu etmeyebilir. Sizi para kazanmak mutlu edecekse lütfen programcı olmayın. Bu işten kısa vadede para kazanmanız çok imkan dahilinde değil. Bunun yerine borsa, emlak ya da taşımacılık sektörlerini denemenizi tavsiye ederim. Emin olun çok daha kolay ve hızlı para kazanacaksınız.

Sürç-i lisan ettiysek affola…