Javascript Yazılım Kuralları (JS)

24 Aralık 2007

Güvenlik

Javascript açık kodlama dili olarak tasarlanmıştır. Düzgün güvenlik ölçülerinde düşünülmemiştir ve düzgün güvenlik kodlaması yerine kullanılmamalıdır.

Javascript kodlamasının kendine özgü güvenlik modeli vardır. Bu web sitesi sahibini korumak, tarayıcılarla sunucular arasında veri alış verişini sürdürmek için değildir. Güvenlik modeli kullanıcı diğer web sitelerinden korumak içindir. Bu nedenle sayfada katı kurallar uygulanır. Tarayıcıdaki kendi sayfalarında denetimi elinde bulundurur ama yeteneklerinin bittiği yer de burasıdır.
  • Javascript kodlaması kullanıcı bilgisayarındaki dosyaları okuyamaz, dosyalara yazamaz. Sunucuda da dosya yaratamazlar (ama sunucu tarafındaki bir kodlamayı kullanarak onun dosya yaratması bu konunun dışındadır). Kullanıcı bilgisayarına yazabildikleri tek şey çerezlerdir (cookies).
  • Çerçeve düzenindeki başka sayfalarla iletişim kurabilirler. Eğer bu çerçeveler aynı alan adından geliyorsa bu işleme izin verilir. Ama başka web sitelerinden gelirlerse işleme izin verilmez (postMessage yöntemi bu yeteneği güvenle biraz genişletebilir ama burada anlatılmamıştır). Bazı tarayıcılar aynı web sitesindeki farklı port numaralarını ayrı Web siteleri gibi yorumlayabilirler.
  • Javascript dosya girişinde değer ataması için kullanılamaz ve izin olmadan dosyaları yukarıya gönderemez (upload).
  • Javascript 'location' nesnesinden okuyarak kullanıcının hangi siteleri gezdiğini bulamaz ama tarayıcıya geçmiş (tarihçe-history) üzerinden ileri ya da geri gitmeyi emredebilir. Kullanıcının açtığı diğer sayfaları da göremez.
  • Javascript başka sitelere ait çerezleri ve değişkenleri okuyamaz.
  • Kullanıcının başka programlarla ilişkisini de göremez. Tarayıcının başka pencerelerinde olanları da göremez.
  • Kullanıcının görüşünden uzakta pencereler de açamaz. Ya da kullanıcının göremeyeceği kadar küçük sayfalar olamaz.
Javascript güvenliği hakkında bilgisi olan ve şifre kontrolunda sayfalar üreten birçok insan ya da sunuculara kriptolanmış bilgi gönderip alanlar konuyu iyi bilir. Gerçek güvenlik için SSL/TSL (HTTPS) gerekir ve tüm kontrollar sunucu tarafında yapılır. Eğer çok fazla başarısız deneme yapılmışsa, güvenlik kilitlemesi de kullanılır. Burada amaç, ısrarlı şifre kırma girişimini engellemektir. Javascript bu işlevselliğin yerini alamaz. Burada sorun eğer birisi Internet üzerinden sizin gönderdiğinizi okuyabiliyorsa onu yeniden yazabilir. O halde güvenli bir sayfayı şifreyle beslerseniz, onu değiştirebilirler ve siz onlara dolduracakları şifreyi göndermiş olursunuz. Bu nedenle SSL kullanmalısınız ki güvende kalabilesiniz. Buradaki konular Javascript üzerine olduğu için yalnız konuyu ilgilendirenler anlatılır.

Kodlamanızın kaynağını korumak

Buna olanak yoktur. Bunu yapmak için birçok insan anlamsız girişimlerde bulunmuştur ama dürüst olmak gerekirse girişimde bulunmanın bir anlamı yoktur. Program geliştiricilerin incelediğine göre Javascript kodlamada "copyright" yoktur. Kuramsal olarak olanaklı olsa da yoktur. Bir şey tümüyle yeniyse onun için "copyright" sözü edilebilir.Onun da daha önce yapılmamış olması gerekir. Javascript yaratıcı programcılık için tasarlanmamıştır. Siz bir şeyi yeni bir biçimde yazmış olsanız da o hala daha önce yapılmış bir şeyleri yapıyordur ve siz hala birilerini yargıya götürmek isterseniz orada size gülerler...

Gönderdiğinizi korumak konusunda söylenecek en önemli şey Javascript kodlamasının yazı olduğu, ilk derleme sonucu olmadığı bilinmelidir. Her kullanıcıya kaynağı gönderip sonra onu ondan nasıl gizleyebilirsiniz ki?

Eğer javascript kaynak kodu görüntülenen sayfayla birlikteyse, tarayıcıda "kaynağı görüntüle" kodlamayı gösterecektir. Tarayıcının belleğine bakarak başlık dosyalarındaki kodlamaların dosya adlarını da verecektir.

Bir çok geliştirici anlatılan yöntemlerde 'kaynağı göster' seçeneğinin olmaması gerektiğini söylerler ve tarayıcının kaynağı görünlemesinin gizlenmesini önerirler. Bunun bir yolu da içerik menüsünün kaldırılmasıyla sağlanmasıdır. Ama aynı zamanda başarısız bir girişimdir. Tarayıcının yapması gereken o sayfaya geldiğinde kodlamayı kapatmak ya da bir önceki sayfadan korunmalı sayfanın URL adresini bulmaktır. Zaten Opera Mozilla/Firefox ve IE sayfadaki sınırlamaları ortadan kaldıracak kodlama çalıştırılmasına izin vermektedir.

Bazıları sayfanın indirilmesini yalnız istemde bulunanın başlık bilgilerinin doğru olduğu ve kullanıcının doğru sayfadan geldiği bilinmesine bağlamak isterler. Bunu ikin kullanıcı Curl kullanarak çerezleriyle, başlık bilgileriyle form alanlarıyla sayfayı istemenin yolunu bulmuş olurlar.

Bazıları kodlamayı charCodeAt ya da escape ile karıştırmayı düşünmüşlerdir. Fakat çözüm sayfanın içindedir ve basit değişikliklerle kodlamanın yazı içinde görünmesi sağlanmaktadır. Karıştırılmış bir kodlamanın yeniden anlaşılır bir koda dönüştürülmesi pek de zaman almaz.

Kodunuzu korumak isteyebilirsiniz ama bunu yapmak olanaksızdır. Aklına koyan biri onu sizden alır.

Bir dosyayı şifreyle korumak

En iyisi bu işi sunucu tarafındaki kodlamalarla ve şifrelenmiş iletişimle çözmektir. Ama bu bir Javascript açıklaması...

Aşağıdaki örneği ele alalım. Doğru şifreyi giren birinin sayfaya erişmesini istediğinizde, doğru şifre girene sayfa görüntülenir. Sorun sayfanın kaynak kodudur. Kodlama içine şifreyi de koymamaız gerek ki ne yazdıklarını denetlemek mümkün olsun. Örneğin:
if( document.forms[0].elements[0].value == 'mypassword' ) {
  location.href = 'protectedpage.html';
}
Yukarıdaki bölümde söylendiği gibi sayfanın kaynak kodunu koruyamazsınız. Özellikle onu almayı amaçlayan birinden. Bir kez kaynağa erişti mi, şifreyi ve URL adresi okumak kolaydır. Gerisi kodu almaya kalıyor...

Basit güvenlik için aşağıdaki tekniği deneyin. korunacak dosya adı whateverYourPasswordIs.html olsun ve aynı yolda (klasörde) index.html bulunsun. Şimdi aşağıdakini kullanın:
<form action="" onsubmit="location.href = this.elements[0].value + '.html'; return false;">
<input type="text">
<input type="submit" value="Submit">
</form>
Bu teknikteki sorun sayfa içeriğinin Internet üzerinden açık geçmesidir. Eğer biri giden gelen mesajları izliyorsa (izlemek pekçok ülkede suçtur ama suç olması izlenmemesi anlamına gelmez), sayfada istediklerini alabilirler.

Bu tekniğe az tanınmışlıkla (obscurity) güvenlik denmektedir. Diğer bir deyimle güvenlidir çünkü kimse orada olduğunu bilmemektedir. Eğer biri niyetlenirse unutmayın onu da bulabilir.

Daha karmaşık bir çözümde, kendi kriptolama tekniğinizi yaratın ve şifrenizi gizleyin. Dosyanın içeriğini de kriptolayın. Sayfa yüklenince "write.prompt" ile şifre girmelerini isteyin. Sayfayı girilen şifreyle açın. Eğer tekniğiniz yeterince iyiyse hatalı şifre karmaşık sayfa içeriği görüntüleyecektir. Bu teknikle şifre Internet üzerinden açık olarak gitmez ve sayfa da açık gelmez. Bu teknik acı güçle kırılabilir (cracked by brute force). Akla gelebilecek her tür şifreyi nedeyerek ve birileri çalışıncaya dek. Bazı şifreleme algoritmaları daha iyi sonuçlar için yardımcı olabilir.

Bu tekniklerin her ikisi de burada kullanıldı.

Size gelmeden verileri kriptolamak

Normalde yalnız Internet kullanan Javascript'le bu olmaz. Siz yazıyı kullanıcı tarafında kriptolayıp sonra kendi tarafınızda açarsınız. Bunu size telefon ya da postayla bildirirler. Başka bir yol da şifreyi bir sayfaya koymak ve sonra o şifreyi kriptolayacak işlevi aynı şifreyle çalıştırmaktır. Kriptolamış da olsanız onu kırmak izleyen için hiç de zor bir iş değildir. Aslında kripto da acı kuvvete dayalı tekniklerle kırılabilir.

En iyi ve uygun teknik simetrik kriptolama tekniği olan ikiz anahtar kullanmaktır (halka açık/gizli anahtarlar). Diffie-Hellman ya da SSL'de olduğu gibi. Ya da asimetrik ikili anahtar kullanarak (PGP ya da RSA için kullanıldığı gibi) kriptolama yapılabilir. Kaba kuvvet kırılımları önlemek için tarayıcı bu tekniklerde 2 üzeri 10600 gibi büyük sayıları tutar. Javascript bu kadar büyük sayılarla uğraşacak kadar işlem yeteneği olan bir kodlama biçimi değildir. Bu nedenle belirtilen şifreleme tekniklerinin kullanımı çok kolay değildir. Aslında http://shop-js.sourceforge.net/ çok büyük sayıların benzetimini yapmaktadır ve örnek olarak Javascript ile RSA anlatılmıştır. Birkaç saniyede işlem yapabilmektedir (o sayfadaki crypto.js kaynak koduna bakınız).

Böyle de olsa, RSA kodlamasının (ya da benzerinin) eşitini de yapsanız, kullanıcının sizin tanımınızı SSL sertifikası olarak onaylayamaz. O zaman üçüncü kişilerin kendi kodlarını araya ekleyerek bilginin kendilerine ulaşması olasılığı vardır. En iyi güvenlik için SSL kodlamasına bağlı kalın...

e-posta adresinizi korumak

Bu javascript kodlamasının yapabildiği en güzel işlerden biridir. Bilmeyenlere kısa bir özet olarak konu şöyle anlatılabilir: Arama motorları Interneti karıştırır, sayfalardaki bağları kullanarak yeni sayfalardan arama motoru veri tabanına bilgi toplarlar. Aynı yöntemi kullanan "spamcılar" da Interneti kurcalar ve sayfalardaki açık e-posta adreslerini toplarlar (mailto: anahtar sözcüğünü kullanarak). Başka anlamlarda çok iyi olan yöntemleri bu haramcılar kötü amaçlarına kullanırlar.

Kısacası bir web sayfasında e-posta adresinizi yazmış olmakla birçok spam türü e-posta almanızı sağlamış olursunuz (isimsiz ve anlamsız birçok e-posta). Birçok kimse tuzağa düşüp e-posta listelerinden çıkarılmalarını isteyen yanıtlar da verirler. Aslında bu davranış size e-posta gönderenlerin çok işine yarar. Çünkü yanır verdiğiniz için veri tabanında sakladıkları e-posta adresi gerçek bir adrestir ve satılınca iyi para eder... Bu tür mesajlar gelmeden sorunu çözecek bir kaç yol vardır:
  • haber gruplarıyla postalaşırken, misafir defterini imzalarken ya da web sayfanızda belirtirken yahoo ya da hotmail türü bir hesap kullanın. Sonra sorun olduğunda bu hesabı kolayca alabilirsiniz. Çok fazla spam posta mı aldınız, hemen o adresi boşaltın ve yerine yenisini alın.
  • Eğer yapabilirseniz e-posta istemci (client) programınızın otomatik yanıt vermesini (yanıt isteyen e-postalar için) kaldırın. Bu biçimiyle e-posta istemci programları otomatik olarak e-posta adresinizi onaylamamış olur.
  • Otomatik yanıtlar verirken çok dikkatli olun.
  • e-posta adresinizi gönderirken, onu adim@BURAYI_SILmydomain.com ya da myName(burayı @ işaretiyle değiştir)mydomain.com biçiminde yazın ve umun ki alan posta adresinizi doğru algılamış olsun. Sorun da anlaması gerekenin anlamaması ve neden e-posta adresinin çalışmadığının bilinmemesidir. O zaman bir sonraki olasılığı denemek gerekir.
  • JavaScript kullanın.

e-posta adreslerinizi yazmaz için Javascript kullanmak

Hiçbir e-posta adresi harmanlayıcısı Javascript kodunu çözecek kadar becerikli değildir. Eğer e-posta adresinizi Javascript ile yazarsanız onu okuyamazlar (e-posta adresi olarak). Tabi Javascript içinde bile e-posta adresinizi bir kelime olarak yazarsanız onu okuyabilirler. Doğru olanı onu parçalara ayırmaktır.
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( 'Benim e-posta adresim ' + theName + '@' + theDomain );
Bunun çıktısı: Benim e-posta adresim myEmailName@myEmailDomain.com

mailto: bağı da kullanabilirsiniz.
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( '<a href="mailto:' + theName + '@' +
                theDomain + '">Bana erişin<\/a>' );
Bunun çıktısı: Bana erişin

Her ikisinin karışımını da kullanabilirsiniz:
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( '<a href="mailto:' + theName + '@' +
                theDomain + '">' + theName + '@' +
                theDomain + '<\/a>' );
Bunun çıktısı: myEmailName@myEmailDomain.com

Bu yaklaşımın bir sorunu var. Kullanıcıların Javascript kodu açık olmalıdır. Tüm herşey ona dayanmaktadır. Bu nedenle iki yöntemin karışımını kullanmak iyidir.
<script type="text/javascript">
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( '<p><a href="mailto:' + theName + '@' +
                theDomain + '">' + theName + '@' +
                theDomain + '<\/a><\/p>' );
</script>
<noscript>
  <p><a href="mailto:myEmailName(replace with @ symbol)myEmailDomain.com">
  myEmailName(burayı @ işaretiyle değiştirin)myEmailDomain.com</a></p>
</noscript>