HTTP üzerinden güvenli bir şekilde şifre nasıl gönderilir?


115

Bir oturum açma ekranında kullanıcı, kullanıcı adı ve şifresiyle bir form gönderirse, şifre düz metin olarak gönderilir (POST ile bile, yanılıyorsam düzeltin).

Öyleyse soru, kullanıcıyı ve şifresini, iletişim verilerini gizlice dinleyen üçüncü şahsa karşı korumanın doğru yolu nedir?

HTTPS'nin soruna bir çözüm olduğunun farkındayım, ancak standart HTTP protokolünü (POST isteği) kullanarak en azından bir düzeyde güvenlik sağlamanın bir yolu var mı? (belki bir şekilde javascript kullanarak)

EDIT Bazı önemli şeyleri atlamış olabilirim.

Söz konusu olan bir sayfaydı - bu, elbette bir HTML dosyası olarak HTTP GET isteğinde kullanıcıya gönderilen PHP tarafından oluşturulan oturum açma sayfasıydı. Sunucu ile istemci arasında (@Jeremy Powel) bağlantı kurulmadı, bu yüzden böyle bir anlaşma protokolü oluşturamıyorum. Ve tüm sürecin kullanıcıya şeffaf olmasını istiyorum - kriptografi ile uğraşmak değil, bir şifre göndermek istiyor.

Teşekkürler.


1
İstemci kriptografi kullanmadan bunu muhtemelen başaramazsınız, ancak kullanıcının böyle bir işlemi görmesi gerekmez. Sadece şifresini girer ve PHP'nizin oluşturduğu kod (örneğin javascript) sizin için hepsini işler.
Jeremy Powell

13
Tanımladığınız sorun, HTTPS'nin icat edilme sebebidir. Parolayı şifrelemek için istemciye bir sır gönderirseniz, bir gizli dinleyici dönüş yolculuğunda onu koklayabilir ve şifresini çözebilir.
jnoss

1
Dolayısıyla, önerinizdeki S yalnızca şifre (veya herhangi bir şekilde birleştirilen kullanıcı adı + şifre) olabilir, çünkü bu kullanıcının sahip olduğu tek "sır" dır. Doğrumuyum? Yani çözüm şu şekilde olacaktır: - Sunucu, HTML sayfasına gizli bir R form alanı sağlar - Kullanıcı şifreyi girer ve şifre gönderilmeden önce javascript H (R, S) hesaplar ve sunucuya gönderir, belki AJAX kullanarak bile - Sunucu H (R, S) 'yi hesaplar ve alınanla karşılaştırır ve yetkilendirmenin geçip geçmediğini ajax isteğine bir yanıt gönderir - Javascript tarayıcıyı istenen web sayfasına yönlendirir
Kornelije Petak

2
@jeremy powell - tanımladığınız şey yaygın bir uygulama olsa da, çerezi bir başlıktan koklayabilen ve çerezi yeniden kullanarak kullanıcıyı taklit edebilen bir aracıya karşı da savunmasızdır. HTTPS kullanmadığınız sürece ortadaki adam saldırılarına karşı güvenlik sağlamak zordur
jnoss

1
Gelecekte bu soruyu kim alırsa alsın: Oturum açtıktan SONRA, oturum çerezini de güvenli hale getirmeniz gerekir. (Yani: HTTPS kullanmak gerçekten çok daha kolay.)
Arjan

Yanıtlar:


66

SSL ile HTTP kullanmak hayatınızı çok daha kolay hale getirecek ve rahatça dinlenebilirsiniz çok zeki insanlar (en azından benden daha akıllı!) Bu gizli iletişim yöntemini yıllardır incelediler.


14
... ve "Ama bir SSL sertifikası için ödeme yapmam gerekiyor !!" bu günlerde 30 dolara alabileceğiniz için geçerli bir şikayet değil. Verilerinizin korunması gerçekten 30 dolar değerinde değil mi?
caf

3
Ya abone olduğunuz web barındırıcısı SSL sertifikaları eklemeyi desteklemiyorsa?
Calmarius

89
@Calmarius - o zaman gerçek bir web
barındırıcısına geçersiniz

3
@BornToCode Bu, teknik olarak özel bir IP'ye sahip olmanız ve HTTPS'yi kullanmak için sunucu donanımına (veya en azından bir VPS'ye) sahip olmanız gerektiği anlamına gelir. Sunucunun tamamı ana bilgisayar sahibinin sertifikasıyla korunmadığı sürece, paylaşılan web barındırıcılar HTTPS yapamaz.
Calmarius

6
paylaşılan web barındırıcılar kesinlikle en.wikipedia.org/wiki/Server_Name_Indication
Brian Minton

39

Güvenli kimlik doğrulama geniş bir konudur. Özetle, @ jeremy-powell'in bahsettiği gibi, kimlik bilgilerini her zaman HTTP yerine HTTPS üzerinden göndermeyi tercih edin. Güvenlikle ilgili birçok baş ağrısını ortadan kaldıracaktır.

TSL / SSL sertifikaları bugünlerde oldukça ucuz. Aslında hiç para harcamak istemiyorsanız, ücretsiz bir letsencrypt.org - otomatikleştirilmiş Sertifika Yetkilisi var.

Sen bir adım daha ileri gidip kullanabilirsiniz caddyserver.com aramalar arka planda letsencrypt hangi.

Şimdi, HTTPS'yi ortadan kaldırdığımızda ...

POST verisi veya GET parametreleri ile kullanıcı adı ve şifre göndermemelisiniz. Bunun yerine, aşağıdaki gibi oluşturulmuş bir Yetkilendirme başlığı (Temel erişim kimlik doğrulama şeması) kullanın:

  • Kullanıcı adı ve şifre, iki nokta üst üste ile ayrılmış bir dizede birleştirilir, örneğin: kullanıcı adı: şifre
  • Elde edilen dize, 76 karakter / satır ile sınırlı olmamak üzere Base64'ün RFC2045-MIME varyantı kullanılarak kodlanır.
  • Yetkilendirme yöntemi ve bir boşluk, yani "Temel" kodlanmış dizeden önce yerleştirilir.

kaynak: Wikipedia: Yetkilendirme başlığı

Biraz karmaşık görünebilir ama öyle değil. Kutudan çıkar çıkmaz bu işlevselliği size sağlayacak çok sayıda iyi kitaplık var.

Yetkilendirme başlığı kullanmanız için birkaç iyi neden vardır

  1. Bu bir standart
  2. Basit (nasıl kullanılacağını öğrendikten sonra)
  3. URL düzeyinde şu şekilde oturum açmanıza izin verir: https://user:password@your.domain.com/login(Örneğin Chrome, bunu otomatik olarak Authorizationbaşlığa dönüştürür )

ÖNEMLİ:
@zaph'ın aşağıdaki yorumunda işaret ettiği gibi, hassas bilgilerin GET sorgusu olarak gönderilmesi, büyük olasılıkla sunucu günlüklerinde sonuçlanacağından iyi bir fikir değildir.

görüntü açıklamasını buraya girin


11
GET parametreleri olarak kimlik bilgilerinin (parola) gönderilmesiyle ilgili sorun, kullanıcı / parola çiftinin muhtemelen sunucu günlüklerinde yer almasıdır ki bu iyi bir fikir değildir. Bir POST ile kimlik bilgilerini göndermek en iyisidir.
zaph

Ahh ... hiç de değil. Gördüğünüz ekran görüntüsü, bir tarayıcıda neler olduğunu göstermek için değiştirildi. Tarayıcıya gir'e bastığınız an, URL'nizi bir Authorizationbaşlık oluşturacak şekilde dönüştürür . Sadece bir dene. Günlükleri temiz hatırlatacak. Ve tabii ki sunucudan bir arama yapıyorsanız (eğer endişelendiğiniz senaryo buysa) elbette programlı olarak başlık oluşturmalısınız.
FullStackForger

Göremediğinizi günlüğe kaydedemezsiniz. username:password@urltarayıcıdan şu ifadeye çevrilir: url+ Authorizationistek başlığı. GET sorgularına gelince ... dediğim gibi, Authroziation başlığını kullanın. Daha iyi.
FullStackForger

2
Sorunun amacına değinmiyorsunuz: hassas verileri ortadaki adam gizli dinlemeden korumak. Odak noktası, kimlik bilgilerini geçirmek için alternatif ve / veya daha standart bir yol bulmak değil, onları güvenli olmayan bir kanal üzerinden korumaktır.
Lord of the Goo

3
Bu çözümün yalnızca bağlantıyı TLS / SSL ile zaten şifreliyorsanız işe yarayacağı vurgulanmalıdır. base64 şifreleme değildir.
Scot

14

Bir sorgulama yanıt şeması kullanabilirsiniz. İstemcinin ve sunucunun her ikisinin de gizli bir S bildiğini söyleyin. Ardından sunucu, istemcinin parolayı bildiğinden (parolayı vermeden) emin olabilir:

  1. Sunucu istemciye rastgele bir sayı (R) gönderir.
  2. İstemci, H (R, S) 'yi sunucuya geri gönderir (burada H, SHA-256 gibi kriptografik bir hash işlevidir)
  3. Sunucu H (R, S) 'yi hesaplar ve istemcinin yanıtıyla karşılaştırır. Eşleşirlerse, sunucu istemcinin parolayı bildiğini bilir.

Düzenle:

Burada R'nin tazeliğiyle ve HTTP'nin durumsuz olmasıyla ilgili bir sorun var. Bu, sunucunun yalnızca sunucunun bildiği bir sırrı oluşturmasını sağlayarak ele alınabilir . Daha sonra protokol şöyle olur:

  1. Sunucu rastgele R sayısı üretir. Daha sonra istemciye H (R, Q) gönderir (istemci tarafından taklit edilemez).
  2. İstemci R, H (R, Q) gönderir ve H (R, S) hesaplar ve hepsini sunucuya geri gönderir (burada H, SHA-256 gibi bir kriptografik hash işlevidir)
  3. Sunucu H (R, S) 'yi hesaplar ve istemcinin yanıtıyla karşılaştırır. Sonra R alır ve (tekrar) H (R, Q) hesaplar. İstemcinin H (R, Q) ve H (R, S) sürümü sunucunun yeniden hesaplamasıyla eşleşirse, sunucu istemcinin kimliğinin doğrulandığını kabul eder.

H (R, Q) müşteri tarafından taklit edilemeyeceğinden, H (R, Q) bir çerez görevi görür (ve bu nedenle aslında bir çerez olarak uygulanabilir).

Başka Bir Düzenleme:

Protokoldeki önceki düzenleme yanlıştır, çünkü H (R, Q) 'yu gözlemleyen herhangi biri onu doğru hash ile yeniden oynatabilir gibi görünüyor. Sunucu, hangi R'lerin artık taze olmadığını hatırlamak zorundadır. Bu cevabı CW'lıyorum, böylece siz bu konuyu düzeltip iyi bir şeyler yapabilirsiniz.


+1 - istemci tarafında javascript (veya Flash / Silverlight / vb.)
İle

10
Ortadaki insanı veya kimliğe bürünme saldırılarını durdurmaz. Örneğin, wifi aracılığıyla. Görünüşe göre bu yanlış bir güvenlik duygusu verecek, IMO.
Tom Hawtin - tackline

2
Bu pasif saldırılara karşı koruma sağlar, ancak Ortadaki Adam yine de saldırabilir.
Douglas Leeder

7
Ayrıca sunucunun orijinal parolayı bilmesini gerektirir.
Douglas Leeder

3
Kriptoyu yeniden keşfetmeyin! (üretimde)
bryanph

11

Web barındırıcınız izin veriyorsa veya hassas verilerle uğraşmanız gerekecek, o zaman HTTPS'yi kullanın. (Genellikle afaik yasa gereği).

Aksi takdirde, HTTP üzerinden bir şey yapmak istiyorsanız. Böyle bir şey yapardım.

  1. Sunucu, genel anahtarını oturum açma sayfasına yerleştirir.
  2. Müşteri, giriş formunu doldurur ve gönder düğmesine tıklar.
  3. AJAX isteği, sunucudan geçerli zaman damgasını alır.
  4. İstemci tarafı komut dosyası, kimlik bilgilerini, zaman damgasını ve bir tuzu birleştirir (analog verilerden karma hale getirilir, örn. Fare hareketleri, tuşa basma olayları), açık anahtarı kullanarak şifreler.
  5. Ortaya çıkan hash'i gönderir.
  6. Sunucu karmanın şifresini çözer
  7. Zaman damgasının yeterince güncel olup olmadığını kontrol eder (yalnızca 5-10 saniyelik kısa bir pencereye izin verir). Zaman damgası çok eskiyse oturumu reddeder.
  8. Hash'i 20 saniye saklar. Bu aralıkta oturum açma için aynı karmayı reddeder.
  9. Kullanıcının kimliğini doğrular.

Bu şekilde parola korunur ve aynı kimlik doğrulama hashı tekrar oynatılamaz.

Oturum jetonunun güvenliği hakkında. Bu biraz daha zor. Ancak çalınan bir oturum jetonunu yeniden kullanmayı biraz daha zor hale getirmek mümkündür.

  1. Sunucu, rastgele bir dizge içeren fazladan bir oturum tanımlama bilgisi ayarlar.
  2. Tarayıcı, bir sonraki talepte bu çerezi geri gönderir.
  3. Sunucu tanımlama bilgisindeki değeri kontrol eder, eğer farklıysa, oturumu yok eder, aksi takdirde her şey yolundadır.
  4. Sunucu, çerezi farklı bir metinle yeniden ayarlar.

Dolayısıyla, oturum jetonu çalınırsa ve başka biri tarafından bir istek gönderilirse, orijinal kullanıcının bir sonraki isteğinde oturum yok edilir. Dolayısıyla, kullanıcı siteye aktif olarak göz atıyorsa, bağlantılara sık sık tıklarsa, hırsız çalınan jetonla fazla ileri gitmez. Bu şema, hassas işlemler için (hesap silme gibi) başka bir kimlik doğrulaması gerektirerek güçlendirilebilir.

DÜZENLEME: Saldırganın kendi sayfasını farklı bir genel anahtarla kurması ve sunucuya proxy istekleri yapması durumunda, bunun MITM saldırılarını engellemediğini lütfen unutmayın. Buna karşı korunmak için genel anahtar, tarayıcının yerel depolama alanına veya bu tür hileleri algılamak için uygulama içine sabitlenmelidir.

Uygulama hakkında: RSA muhtemelen en bilinen algoritmadır, ancak uzun anahtarlar için oldukça yavaştır. Bir PHP veya Javascript uygulamasının ne kadar hızlı olacağını bilmiyorum. Ama muhtemelen daha hızlı algoritmalar var.


Bu durumda şifre gerçekten korumalı mı? Birisi neyin gönderildiğini bulup genel anahtarı kullanarak şifresini çözüp daha sonra kullandıklarında zaman damgasını güncelleyemez mi? Bir şey mi kaçırıyorum?
michaellindahl

@michaellindahl asimetrik şifreleme, yalnızca özel anahtarın - asla sunucudan ayrılmayan - şeylerin şifresini çözmek için kullanılabileceği anlamına gelir. Genel anahtarlar yalnızca şifrelemek için kullanılabilir.
Dan Pantry

2
Tarayıcı ve sunucu arasındaki bir bilgisayar, oturum açma sayfasındaki ortak anahtarı değiştirebilir.
Antti

Yöntemlerinizi paylaştığınız için teşekkürler, her şeyi çok ilginç buldum. İnanç bilgileri gönderirken eklenen zaman damgası iyi bir yakalama! Değeri rastgele bir dizge olan fazladan oturum tanımlama bilgisini kullanmakla ilgili bir soru: yalnızca sonraki istek için bir belirteç gibi mi?
Victor

4

İnternette iyi bir uygulama görmeme rağmen, AJAX veya çoklu form gönderimiyle sunucu tarafı ve istemci tarafı Diffie-Hellman anahtar değişim sistemi kullanırdım (ilkini öneririm). Bir JS kitaplığının her zaman MITM tarafından bozulabileceğini veya değiştirilebileceğini unutmayın. Yerel depolama, bununla bir dereceye kadar mücadele etmek için kullanılabilir.


4

Güvenli olmayan bir kanal üzerinden güvenli parolalar kullanmak için SRP'yi kullanabilirsiniz. Bunun avantajı, bir saldırgan trafiği koklasa veya sunucuyu tehlikeye atsa bile, parolaları farklı bir sunucuda kullanamamasıdır. https://github.com/alax/jsrp , tarayıcıda veya sunucu tarafında (düğüm yoluyla) HTTP üzerinden güvenli şifreleri destekleyen bir javascript kitaplığıdır.


1

HTTPS çok güçlüdür çünkü asimetrik kriptografi kullanır. Bu tür bir kriptografi yalnızca şifrelenmiş bir tünel oluşturmanıza izin vermekle kalmaz, aynı zamanda bir bilgisayar korsanıyla değil, doğru kişiyle konuştuğunuzu doğrulayabilirsiniz.

İletişim için asimetrik şifreleme RSA'yı (PGP tarafından kullanılan) kullanan Java kaynak kodu: http://www.hushmail.com/services/downloads/



0

Https kullanmak en iyi seçenek burada (sertifikalar günümüzde o kadar pahalı değil). Bununla birlikte, http bir gereklilikse, bazı kodlama kullanabilirsiniz - bunu sunucu tarafında enkript edin ve kullanıcıların tarayıcısında decript (anahtarı ayrı olarak gönderin).

Safevia.net'i uygularken bunu kullandık - şifreleme istemciler (gönderen / alıcı) tarafında yapılır, bu nedenle kullanıcı verileri ağda veya sunucu katmanında mevcut değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.