it-swarm-tr.com

URL parametre şifrelemesinden daha iyi teknikler

Ben tek seçenek/vs/son tarih url parametre değerleri üzerinde simetrik şifreleme uygulamak olduğu bir uygulama üzerinde çalışan bir programcıyım. Veriler doğası gereği duyarsızdır, ancak satış temsilcilerinin birbirlerinin ipuçlarını incelemelerini önlememiz gerekiyordu. (Anahtarlar oturum oluşturulduğunda oluşturulur ve kriptografik olarak güçlüdür.) Oturumların sık sık bitmesi bekleniyor.

Rol hiyerarşisi Manager--> Supervisor--> Agents. Veri yapıları şu anda bu rolleri kimin neyi görebileceğini kesin olarak uygulayacak şekilde açıklamamaktadır. Veritabanından bu bilgileri almak kolay bir yere yakın değildi. (Özyinelemeli Veritabanı.)

Bu tekniğin parametre manipülasyonuna karşı bir savunma olarak listede aşağı olduğunu biliyorum. Daha iyi bir teknik ne olurdu?

Kısıtlamalar:
Rol tabanlı kontrol bir seçenek değil.

[Ek bilgi] Herhangi bir değişiklik yapmadan önce istemciye gönderilen ve gönderilen URL'ler şöyle görünüyordu:

https://www.example.com/agent/?producerId=12345

Buradaki belirli tehdit yüzeyi ?agentId=12345. Ajan kimlikleri her bir ajana benzersiz olarak atanır. Ajan A'nın A istatistiklerine bakmak isterse, o acentenin kotasyonlarına ve mevcut satış istatistiklerine bakmak için agentId = 22222 girebilirdi.

Yine, Role Dayalı kontrol benim için bir seçenek değildi: OR kalıcılık katmanı veritabanında değişiklik yapamadım.

Benim çözümüm, oturum tarafından oluşturulan bir şifreleme anahtarı (Java'nın KeyGenerator sınıfını kullanarak) kullanmak ve istemciye gönderilen giden URL'leri şifrelemekti. Şimdi, url şuna benziyor:

https://www.example.com/agent/?producerId=<ciphertext>

Birisi agentId = 22222'yi denerse, sunucu bunun şifresini çözecektir düşünüyor şifreli metindir ve sonuçta geçersiz bir karakter dizisi oluşturur.

(Bu, mevcut bir ajanın olabilir bulunma olasılığını açık bırakır, ancak saldırıyı yapan kişi ile ilgili olması pek olası değildir.

Bu sorunun optimal güvenlik (kaynak erişimini sağlamak için rol tabanlı kontrol) ve gri bir alanda bazı güvenliği sıkmaya çalışmakla ilgili olmadığını vurgulayacağım.

Buradaki parametre şifreleme çözümü, güvenlik görevlilerimizden biri tarafından bana önerildi. Bu çözüm üzerinde düşünmediğim bir paket var - kırık URL'ler - ve b yanı sıra erişim kurallarını uygulamak için zaman tartışmak için bu çözüm tarafından oluşturulan bakım sorunu kullanacağım daha az stopgap tarzında.

21
avgvstvs

İyi soru! Savunmaya çalıştığınız tehdidi detaylandırdığınız için teşekkür ederiz. Cevabımı buna göre düzenledim.

Özet. Birincil savunmanız erişim kontrolü olmalıdır. Hangi kullanıcıların hangi sayfaları görüntüleyebileceğini sınırlamanız gerekir. Detaylar aşağıda.

Web uygulamalarında erişim kontrolü. Yapmanız gereken şey, kullanıcının bir sayfada göstereceğiniz verilere erişme yetkisine sahip olup olmadığını kontrol etmek, bu verileri görmelerine izin vermeden önce. Bu temel olarak erişim kontrolüne gelir: bir yetkilendirme politikasına dayanarak hangi kullanıcıların hangi verileri görüntüleyebileceğini sınırlayan kontroller istersiniz.

Her ajan için bir sayfa olacak şekilde diziniz var gibi görünüyor:

http://www.example.com/agent/?producerId=12345
http://www.example.com/agent/?producerId=12346
http://www.example.com/agent/?producerId=12347
...

burada üretici kimlikleri (agentIds) potansiyel olarak tahmin edilebilir veya öngörülebilirdir. 12345 aracının http://www.example.com/agent/?producerId=12345 ancak diğer sayfalardan hiçbiri değil. TAMAM.

Bu bir bataklık standart durum ve bataklık standart savunma: erişim kontrolü.

Erişim denetimini uygulamak için web uygulamasını kodlarsınız, böylece her sayfa kullanıcının bu sayfayı görüntülemesine izin vermeden önce kullanıcının o sayfayı görüntüleme yetkisi olup olmadığını kontrol eder. Örneğin, yukarıda listelenen sayfa için, o sayfayı uygulayan mantık, şu anda oturum açmış olan kullanıcının kimliğini kontrol eder. Oturum açan kullanıcının kimliği, sayfa parametresinin manufacturerId ile eşleşiyorsa, onlara bilgileri gösterirsiniz. Kimlik eşleşmezse, onlara bilgileri göstermezsiniz: başka bir kullanıcıysa, onlara bir hata sayfası gösterir (nasıl erişileceği hakkında bilgi ile) veya kullanıcı henüz giriş yapmadıysa, yeniden yönlendirirsiniz giriş sayfasına yönlendirin.

Bu, yer işaretlerini bozmaz. Veritabanında değişiklik, kalıcılık katmanında değişiklik veya rol tabanlı erişim denetimi gerektirmez. Şu anda oturum açmış olan kullanıcının kimliğini aramak ve bunu sağlayıcı kimliğiyle ilişkilendirmek için bir yol bulmanızı gerektirir. Ayrıca, yönetici ve amirlerin diğer tüm aracıların verilerini görmesine izin vermek istiyorsanız, o anda oturum açmış olan kullanıcıyı aramak ve bunların yönetici mi yoksa yönetici mi olduğunu belirlemek için bir yola ihtiyacınız vardır. Yalnızca temsilcinin yöneticisinin/amirinin sayfalarını görüntülemesine izin vermek istiyorsanız (diğer tüm yöneticiler/amirler değil), her acentenin yöneticisini/süpervizörünü belirlemenin bir yoluna ihtiyacınız vardır. Bunlar oldukça basit, minimum gereksinimlerdir; Onlardan nasıl kaçınabileceğinizi görmek zor.

@Symbcbean düzgün bir şekilde işaret ettiği gibi, bu web uygulamalarında sıklıkla bulunan çok yaygın bir hatadır. Tipik bir örnek, bir kaynağı tanımlamak için tahmin edilebilir bir parametre değeri kullanan ve kullanıcının kimliğini doğrulamamış bir site olabilir. Örneğin, siparişlere sıralı bir sipariş numarası atandığını varsayalım:

https://www.example.com/show_order.php?id=1234
https://www.example.com/show_order.php?id=1235
https://www.example.com/show_order.php?id=1236
...

ve URL'yi bilen herkesin siparişi görebildiğini varsayalım. Bu kötü olurdu, çünkü sipariş numarasını bilen (veya tahmin eden) herhangi birinin, yetkilendirilmemiş olsalar bile siparişi görüntüleyebileceği anlamına gelir. Bu OWASP'ın İlk On web uygulaması güvenlik risklerinden biridir: Güvenli Olmayan Doğrudan Nesne Referansları . Daha fazla bilgi için OWASP'ta bulunan kaynakları okumanızı tavsiye ederim. OWASP, web uygulaması güvenliği konusunda birçok harika kaynağa sahiptir.

Diğer yorumlar. Diğerleri SSL kullanılmasını önerdi. Bu, parametre müdahalesini engellemese de, diğer sorunlara karşı savunan genel bir güvenlik uygulamasıdır. SSL kullanmak basittir: web sitenizi http yerine https kullanacak şekilde yapılandırın (ve ideal olarak HSTS'yi etkinleştirin ve tüm çerezlerde secure bitini ayarlayın).

Ayrıca, gizli bilgilerin URL parametrelerinde saklanmasından kaçınmak daha iyidir, diğer her şey eşittir. Gizli bilgileri oturum durumunda veya veritabanında saklayabilirsiniz.

16
D.W.

Kısacası: RL parametrelerini şifrelemeyin, ayrı bir arama kullanın .

Ayrıca, herhangi bir web uygulaması güvenliği ölçüsü istiyorsanız, HTTPS kullanmak temel olarak tartışılamaz. 2015 yılında zorunludur. TLS 1.1+ ile rahat olun.


Geliştiriciler ne yapmak istiyor?

What developers want to do

Geliştiriciler bunun yerine ne yapmalı

enter image description here

7

ancak satış temsilcilerinin birbirlerinin olası satışlarına göz atmasını önlememiz gerekiyordu

Bu, istemcinin bir tarayıcı olduğunu ima eder - anahtarı bir noktada açık metin olarak mı gönderiyorsunuz?

Polinom doğrudur, SSL kullanıyor olmalısınız. Bu, aşağıdaki gibi görünen bir URL'ye bitişik değerler yazarak kullanıcıların sorununu çözmeyecektir:

https://www.example.com/show_order.php?id=1234
https://www.example.com/show_order.php?id=1235
https://www.example.com/show_order.php?id=1236
...

İsteği doğrulamak için sunulması gereken parametrelere dayanarak sunucu tarafında bir kimlik doğrulama belirteci oluşturmak oldukça mümkündür. İdeal olarak bunun için bir mesaj kimlik doğrulama kodu (MAC) kullanırsınız, ancak dikkatli olursanız bir karma da işe yarar. Örneğin. PHP'de ...

 print "<a href='show_order.php?id=" . $id . "&valid=" . md5($id . crypto_key()) . "'>...

Hangi sadece tarafından doğrulanır:

if ($_GET['valid'] != md5($_GET['id'] . crypto_key()) {
   die('not authorized');
}

Burada crypto_key() statik bir şifreleme anahtarı döndürür (örneğin, /dev/urandom 'Dan 128 bit çekip veritabanında saklayarak oluşturun).

Ancak yine de URL'yi oluşturan koda erişimi kontrol etmeniz gerekir.

3
symcbean

İşte benim çözümüm

$id=1234;
$en_id = encrypString( $id);

ve url'yi şöyle oluşturuyorum

https://www.example.com/show_order.php?id=$en_id

uRL şöyle görünecek

https://www.example.com/show_order.php?id=9muEYh4lShFDeCnXqoNpxucs42Fuz5Nexq1IUGWYEffffe88yRbJu

ve diğer tarafta şifresini çözdüm

$en_id= decryptString($_GET['id']);

crypt ve decrypt işlevleri

function encrypString($plaintext) {
         # --- ENCRYPTION ---

        $key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");//change this

        # show key size use either 16, 24 or 32 byte keys for AES-128, 192
        # and 256 respectively
        $key_size =  strlen($key);
        //echo "Key size: " . $key_size . "\n";


        # create a random IV to use with CBC encoding
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);

        # creates a cipher text compatible with AES (Rijndael block size = 128)
        # to keep the text confidential 
        # only suitable for encoded input that never ends with value 00h
        # (because of default zero padding)
        $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
                                     $plaintext, MCRYPT_MODE_CBC, $iv);

        # prepend the IV for it to be available for decryption
        $ciphertext = $iv . $ciphertext;

        # encode the resulting cipher text so it can be represented by a string
        $ciphertext_base64 = base64_encode($ciphertext);

        return  rawurlencode($ciphertext_base64);//important rawurlencode for + symbol in url

    }


decryptString($ciphertext_base64) {
        # --- DECRYPTION ---

        $key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");//change this

        # show key size use either 16, 24 or 32 byte keys for AES-128, 192
        # and 256 respectively
        $key_size =  strlen($key);
        //echo "Key size: " . $key_size . "\n";

        # create a random IV to use with CBC encoding
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);

        $ciphertext_dec = base64_decode($ciphertext_base64);

        # retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
        $iv_dec = substr($ciphertext_dec, 0, $iv_size);

        # retrieves the cipher text (everything except the $iv_size in the front)
        $ciphertext_dec = substr($ciphertext_dec, $iv_size);

        # may remove 00h valued characters from end of plain text
        $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key,
                                    $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

        return rawurldecode($plaintext_dec);
    }
2

Parametre kurcalamasını önlemek için, her zaman düz metin değerleriyle bir karma boyunca gönderdim.

örneğin. korumak istediğiniz bu url'yi alın

https://www.mysite.com/somepage?param1=abc&param2=xyz

Sunucuda, modeliniz tüm URL değerlerini gizli bir tuzla hash eder

string salt = "A1B2C3D4...";
string param1 = "abc";
string param2 = "xyz";
string hash = YourFavoriteHashingAlgorithm(param1 + param2 + salt);
// result hash = "Y83YMB38DX83YUHFIEIGKDHSEUG"

bu karma değerini diğer url değerleriyle birlikte gönderirsiniz

https://www.mysite.com/somepage?param1=abc&param2=xyz&hash=Y83YMB38DX83YUHFIEIGKDHSEUG

Şimdi, bu URL için bir istek aldığınızda, size sunulan parametreleri tekrar alıp aynı algoritma ile hash edersiniz. Yeni oluşturduğunuz karma, size sunulmakta olan karma değerle eşleşmelidir, aksi takdirde 400 "Kötü İstek" sonucu gönderin !.

Güzel olan şey, parametrelerinizin hala insanlar tarafından okunabilmesidir ve mevcut tüm doğrulama mantığınız aynı kalabilir.

1
raterus

kullan kullanıcı girişi yapmayın

(çünkü bunu yapamazsınız güven it)

Bu cevap, kabul edilen mesajını bana çok önemli bir sadeleştirme ile genişletir.

Şimdi, açıklamanızdan ve en iyi anlayışımdan Sales Agent A (Yani 12345) 'un Sales Agent B' A göz atmasını önlemek istediğinizi söylediniz. 'nin verileri (yani 54321).

Basitçe, sorgu dizesinden agentId parametresini öldürün ve oturumdan alın

URL https://example.org/show_order.php Olur

Dahili olarak, uygulama , satış temsilcisi kimliğini oturumda saklanan anaparadan ayıklamalıdır. Ben aşırı derecede paslı PHP bu yüzden sahte kod kullanacağım

SELECT * FROM sales where salesman_id = ?1;
[1 = getPrincipalSalesId()]

Bu sorgu istemciden gelen her şeyi yok sayar. Kalıcılık katmanında değişiklik yapılmasını gerektirmez. RBAC (rol tabanlı erişim kontrolü) uygulanmasını bile gerektirmez, ancak her şey getPrincipalSalesId işleviyle ilgilidir.

Temel olarak URL'yi oluşturmak için kullandığınız kodla aynıdır, ancak bu kez bu değeri sorguya çekerek örtük yaparsınız. .