PHP'de veritabanı şifreleri nasıl güvenli hale getirilir?


404

Bir PHP uygulaması bir veritabanı bağlantısı yaptığında, elbette genellikle bir kullanıcı adı ve şifre geçirmesi gerekir. Uygulamam için tek bir minimum izinli giriş kullanıyorsanız, PHP'nin bu giriş ve şifreyi bir yerde bilmesi gerekir. Bu şifreyi korumanın en iyi yolu nedir? Sadece PHP kodunda yazmak iyi bir fikir değil gibi görünüyor.


1
Tamamen güvenli olmak için bir ssl bağlantısı kurmanız gerekir, aksi takdirde ağınızdaki herkes yazdığınız şifreyi koklayabilir.
Charles Ma

1
Bağlantı dizesinde kullanılan kullanıcı şifrelerini mi yoksa veritabanı şifresini mi kastediyorsunuz?
Ozgur Ozcitak

4
Bağlantı dizesinde kullanılan veritabanı şifresi. Teşekkürler!
user18359

Yanıtlar:


238

Birkaç kişi şifreleri bir veritabanında nasıl saklayacağına dair bir soru olarak yanlış anlıyor . Bu yanlış. Bu, erişmenizi sağlayan şifreyi nasıl saklayacağınızla ilgilidir . veritabanı.

Genel çözüm, parolayı kaynak kodun dışına bir yapılandırma dosyasına taşımaktır. Ardından yönetimi bırakın ve bu yapılandırma dosyasını sistem yöneticilerinize kadar güvenli hale getirin. Bu şekilde geliştiricilerin üretim parolaları hakkında hiçbir şey bilmelerine gerek kalmaz ve parolanızın kaynak denetiminizde kaydı yoktur.


8
Teşekkürler. Bunu doğru anlarsam, php dosyası yapılandırma dosyasına bir şifre ekleyerek parolayı kullanmasına izin verir. örneğin, 'app1_db_cfg.php' adlı bir dosyayı, giriş, şifre ve db adını saklayan bir dosya oluşturuyorum. Sonra application.php sayfam 'app1_db_cfg.php' içeriyor ve ben işteyim!
user18359

28
Yapılandırmanın düzgün bir şekilde korunması gerektiğini kabul ediyorum. Ancak bunun nasıl yapılacağını bilmek, geliştiricilerin değil sistem yöneticilerinin işi. Bu durumda güçlü şifrelemenin değerine katılmıyorum. Yapılandırma dosyanızı koruyamazsanız, anahtarlarınızı koruyabileceğinizi düşündüren nedir?
user11318

10
Sadece web sunucusundan veritabanına erişmesine izin verilen bir veritabanı hesabı kullanmayı tercih ederim. Ve sonra yapılandırmayı şifrelemekle uğraşmıyorum, sadece web kökünün dışında saklıyorum.
gnud

11
Dosya yolu bile kaynak kodunda bilinmeyecek şekilde yolu ayarlamak için bir apache ortam değişkeni kullanın. Bu ayrıca, Apache ayarlarının sunucuda ne olduğuna bağlı olarak geliştirme ve üretim için farklı bir parolaya sahip olmanızı sağlar
geedew

15
Lütfen web erişilebilir dizinin dışında saklanan dosyaların bile bunları kullanan komut dosyası tarafından okunması gerektiğini unutmayın. Birisi bu dosyayı içeriyorsa, verileri dosyadan atarsa, şifreyi görür.
Rick Mac Gillis

104

Başka birinin sunucusunda barınıyorsanız ve web kökünüz dışında erişime sahip değilseniz, parolanızı ve / veya veritabanı bağlantınızı her zaman bir dosyaya koyabilir ve daha sonra .htaccess kullanarak dosyayı kilitleyebilirsiniz:

<files mypasswdfile>
order allow,deny
deny from all
</files>

3
Teşekkürler, tam da aradığım şey buydu.
David Gladfelter

28
Kesinlikle, ancak birisinin kabuk erişimi varsa, tüm hesabınız yine de tehlikeye atılmıştır.
kellen

4
Bu kötü bir uygulamadır çünkü kimlik bilgilerinizi yanlışlıkla bir havuza verebilirsiniz.
Porlune

2
@Ankit: Dostu olmayan bir kullanıcının sunucuya dosya yüklemesi ve yürütmesi mümkünse, sunucu düzgün yapılandırılmamış demektir.
kellen

6
@Porlune: Geliştiriciler sürüm kontrol sistemlerini parola dosyasını yok saymalı, yani .gitignore kullanarak. Ancak evet, hassas veriler içeren dosyalara dikkat edilmelidir.
kellen

45

En güvenli yol PHP kodunuzda belirtilen bilgilerin hiç olmamasıdır.

Apache kullanıyorsanız, httpd.conf veya sanal hosts dosya dosyanızdaki bağlantı ayrıntılarını ayarlamak anlamına gelir. Bunu yaparsanız, mysql_connect () parametresiz olarak çağırabilirsiniz, bu da PHP'nin bilgilerinizi asla vermeyeceği anlamına gelir.

Bu dosyalarda bu değerleri şu şekilde belirtirsiniz:

php_value mysql.default.user      myusername
php_value mysql.default.password  mypassword
php_value mysql.default.host      server

Sonra mysql bağlantınızı şöyle açın:

<?php
$db = mysqli_connect();

Veya bunun gibi:

<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
                     ini_get("mysql.default.password"),
                     ini_get("mysql.default.host"));

1
Lütfen ini_get'in
Val

4
Evet, ancak herhangi bir kullanıcı (veya kötü yazılmış php betiğini kötüye kullanan bir hacker) parolayı okuyabilir ini_get().
Marki555

1
@ Marki555 Bununla but any user (or a hacker abusing badly written php script) can read the password via ini_get()nasıl başa çıkıyorsunuz ?
tonix

2
Marki555, PHP kodunu çalıştırabilen bir saldırganın PHP işlevlerini de çağırabileceğini söylüyor ki bu da doğru ve bu konuda bir şeyler yapmak imkansız. Ayrıca, bu cevapta verdiğim tavsiyeleri artık kendim takip etmediğimi, bunun yerine ortam değişkenlerini kullandığımı da eklemek isterim. Kavram benzer olsa da: Kimlik bilgilerinizi kodda saklamayın, ancak bir şekilde enjekte edin. ini_get()Veya kullanmanızın bir önemi yok getenv().
Lars Nyström

2
@DeepBlue ini_get () enjekte edebilirseniz, file_get_contents (anypath) de enjekte edebilirsiniz. Php şifre almak için bir yol olduğu sürece, herhangi bir kötü amaçlı kod da olacaktır.
varesa

40

Bunları web kökünün dışındaki bir dosyada saklayın.


29
Ve başka yerlerde de belirtildiği gibi, kaynak kontrolü dışında.
Frank Farmer

6
ekleyebilir miyiz? örneğin PHP'de yapabilir miyiz include('../otherDirectory/configfile.conf')?
mtk

1
Hepiniz kimlik bilgilerini wwwroot dışında saklamanızı öneriyorsunuz. Tamam, güvenlik geçmişini anlıyorum. Peki o zaman sürüm kontrolünde nasıl saklanmalıdır (örnek yapılandırma)? Genellikle wwwroot git repo'nun köküdür, bu yüzden dışarıda bir şey varsa - VC dışında olacaktır. Yeni geliştiricinin geliştirme için yerel bir örnek oluşturmaya çalıştığını düşünün - "bu dosyayı alın, dışarı kopyalayın ve doldurun" gibi büyüyü nasıl bilmesi gerekir?
babası

@TheGodfather Fikir, yeni bir geliştiricinin kendi geliştirme ortamları için kendi kimlik bilgilerine sahip olması gerektiğidir. Her ne kadar kodda nasıl yapılandırmanız gerektiğini (ancak gerçek verileri değil) gösteren talimatları veya yorumları içeren bir benioku olması iyi bir uygulamadır.
PhoneixS

@TheGodfather, benioku dosyası mı?
Pacerier

35

Son derece güvenli sistemler için, veritabanı şifresini bir yapılandırma dosyasında (sistem yöneticisi tarafından güvence altına alınan) şifreleriz. Uygulama / sunucu başlangıcında, uygulama daha sonra sistem yöneticisinden şifre çözme anahtarını ister. Daha sonra veritabanı şifresi yapılandırma dosyasından okunur, şifresi çözülür ve ileride kullanılmak üzere hafızada saklanır. Şifrelenmemiş bellekte saklandığından hala% 100 güvenli değil, ancak bir noktada 'yeterince güvenli' demelisiniz!


85
yönetici ölürse ne olur?
Radu Murzea

36
@RaduMurzea bu çok saçma. Sys Admins'in öldüğünü ne zaman duydunuz? McDonalds gibiler, sadece hiçbir yerden ortaya çıkıyorlar / yok oluyorlar!
ILikeTacos

13
@Radu Murzea Sadece 2 veya daha fazla yöneticiniz var, o zaman bir baskın dizisi gibi pariteniz var. Bir seferde birden fazla sürücünün arızalanması olasılığı çok daha düşüktür.
element11

5
sunucular yeniden başlatıldığında ne olacak? Yöneticiyi, şifreyi ..etc.etc olarak yazmaları için uyandırmak için geçen süreye ne dersiniz? lol
John Hunt

1
'Bellekte saklanan' ile ne demek istediğinizden emin değilim. PHP web uygulamaları, genellikle bir sayfayı görme isteğine yanıt vermek için gereken süreden daha uzun süre bellekte hiçbir şey depolamaz.
bdsl

15

Bu çözüm geneldir, çünkü hem açık hem de kapalı kaynak uygulamaları için yararlıdır.

  1. Uygulamanız için bir işletim sistemi kullanıcısı oluşturun. Bkz. Http://en.wikipedia.org/wiki/Least_privilege
  2. Parola ile o kullanıcı için (oturum olmayan) bir OS ortam değişkeni oluşturun
  3. Uygulamayı bu kullanıcı olarak çalıştırın

Avantajları:

  1. Parolalarınızı yanlışlıkla kaynak denetiminde kontrol edemezsiniz, çünkü yapamazsınız
  2. Yanlışlıkla dosya izinlerini bozmazsınız. Evet, ama bunu etkilemez.
  3. Sadece root veya o kullanıcı tarafından okunabilir. Kök zaten tüm dosyalarınızı ve şifreleme anahtarlarını okuyabilir.
  4. Şifreleme kullanıyorsanız, anahtarı nasıl güvenli bir şekilde saklıyorsunuz?
  5. X platformu çalışır
  6. Envvar'ı güvenilmeyen çocuk süreçlerine geçirmediğinizden emin olun

Bu yöntem çok başarılı olan Heroku tarafından önerilmektedir.


11

veritabanı bağlantısının, kimlik bilgilerinin depolandığı dosyada oluşturulması mümkünse. Connect deyimindeki kimlik bilgilerini satır içinde.

mysql_connect("localhost", "me", "mypass");

Aksi takdirde, bağlantı deyiminden sonra kimlik bilgilerini ayarlamak en iyisidir, çünkü bellekte olmayan kimlik bilgileri bellekten okunamaz ;)

include("/outside-webroot/db_settings.php");  
mysql_connect("localhost", $db_user, $db_pass);  
unset ($db_user, $db_pass);  

9
Birisinin belleğe erişimi varsa, yine de mahvoldunuz. Bu anlamsız sahte güvenlik. Web kökünün dışında (veya web kökünüzün üzerinde erişiminiz yoksa en azından bir .htaccess tarafından korunan) tek güvenli seçenektir.
uliwitness

2
@uliwitness - Bu, birisinin ağ operasyon merkezinizin kilidini asetilen meşale ile kesebilmesi nedeniyle kapının da sahte güvenlik olduğu anlamına geliyor. Hassas bilgileri mümkün olan en dar kapsama bağlı tutmak her zaman mantıklıdır.
Luke A. Leber

1
Echo $ db_user veya $ db_pass yazdırmaya ne dersiniz? Aynı ekipteki geliştiriciler bile üretim kimlik bilgilerini bulamamalıdır. Kod, giriş bilgileri hakkında yazdırılabilir hiçbir şey içermemelidir.
Mohammed Joraid

8

Veritabanınıza erişmek için parolaya ihtiyacınız olduğunu söylediğiniz gibi, seçenekleriniz biraz sınırlıdır. Genel bir yaklaşım, kullanıcı adı ve parolayı ana komut dosyası yerine ayrı bir yapılandırma dosyasında saklamaktır. Ardından bunu ana web ağacının dışında sakladığınızdan emin olun. Php dosyalarınızı yürütülür yerine sadece metin olarak görüntülenmesini bırakan bir web yapılandırma sorunu varsa, bu şifre maruz değil.

Bunun dışında, kullanılan hesap için minimum erişime sahip doğru satırlardasınız. Buna ekle

  • Kullanıcı adı / şifre kombinasyonunu başka hiçbir şey için kullanmayın
  • Veritabanı sunucusunu bu kullanıcı için yalnızca web ana bilgisayarından bağlantıları kabul edecek şekilde yapılandırın (DB aynı makinede ise localhost daha da iyidir) Bu şekilde, kimlik bilgileri açık olsa bile, makinesi.
  • Şifreyi gizleyin (ROT13 bile yapacaktır), bazıları dosyaya erişirse çok fazla savunma yapmaz, ancak en azından rahat bir şekilde görüntülenmesini önler.

Peter


8

PostgreSQL kullanıyorsanız, ~/.pgpassşifreleri otomatik olarak arar . Daha fazla bilgi için kılavuza bakınız .


8

Daha önce DB kullanıcısını / parolasını bir yapılandırma dosyasında depoladık, ancak o zamandan beri paranoyak moda geçtik - Derinlikte Savunma politikası benimsemiştik .

Uygulamanızın güvenliği ihlal edilirse, kullanıcının yapılandırma dosyanıza okuma erişimi olur ve bu nedenle bir krakerin bu bilgileri okuma olasılığı vardır. Yapılandırma dosyaları sürüm kontrolüne takılabilir veya sunucuların etrafına kopyalanabilir.

Kullanıcı / geçişin Apache VirtualHost'ta ayarlanan ortam değişkenlerinde depolanmasına geçtik. Bu yapılandırma yalnızca kök tarafından okunabilir - umarım Apache kullanıcınız kök olarak çalışmaz.

Bununla con, şimdi şifrenin Global PHP değişkeninde olmasıdır.

Bu riski azaltmak için aşağıdaki önlemlere sahibiz:

  • Parola şifreli.PDO sınıfını, şifrenin şifresini çözmek için mantığı içerecek şekilde genişletiyoruz. Birisi bağlantı kurduğumuz kodu okursa, bağlantının şifrenin kendisiyle değil şifreli bir şifreyle kurulduğu açıkça görülmez.
  • Şifrelenmiş parola genel değişkenlerden özel bir değişkene taşınır Uygulama, değerin genel alanda kullanılabileceği pencereyi azaltmak için bunu hemen yapar.
  • phpinfo()devre dışı. PHPInfo, ortam değişkenleri de dahil olmak üzere her şeye genel bir bakış elde etmek için kolay bir hedeftir.

6

Veritabanı parolasını bir dosyaya koyun, dosyaları sunan kullanıcıya salt okunur yapın.

Sadece php sunucu işleminin veritabanına erişmesine izin vermenin bazı yolları yoksa, bu hemen hemen tüm yapabilirsiniz.


5

Veritabanı parolası hakkında konuşuyorsanız, bir tarayıcıdan gelen parola yerine, standart uygulama, veritabanı parolasını sunucudaki bir PHP yapılandırma dosyasına koymak gibi görünüyor.

Parolayı içeren php dosyasının üzerinde uygun izinlere sahip olduğundan emin olmanız gerekir. Yani sadece web sunucusu ve kullanıcı hesabınız tarafından okunabilir olmalıdır.


1
Ne yazık ki PHP yapılandırma dosyası phpinfo () tarafından okunabilir ve birisi şanslı bir saldırganın arkasında bazı test komut dosyası bırakırsa şifreyi okuyabilecektir. Bağlantı parolasını web sunucusu kökünün dışındaki bir dosyada bırakmak muhtemelen en iyisidir. O zaman ona erişmenin tek yolu ya bir kabukla ya da rastgele kod yürütmektir, ancak bu senaryoda tüm güvenlik yine de kaybolur.
MarioVilas

5

Sadece bir yerde bir yapılandırma dosyasına koymak genellikle böyle yapılır. Sadece şunlardan emin olun:

  1. ağınız dışındaki herhangi bir sunucudan veritabanı erişimine izin verme,
  2. şifreyi yanlışlıkla kullanıcılara göstermemeye dikkat edin (bir hata iletisinde veya yanlışlıkla HTML, vb. olarak sunulan PHP dosyaları aracılığıyla).

5

Bunu şu şekilde çözdük:

  1. Diğer şifre sunucusundan açık bağlantı ile sunucuda memcache kullanın.
  2. Parolayı (hatta şifrelenmiş tüm password.php dosyasını) artı şifresini çözmek için kaydedin.
  3. Web sitesi, şifre dosyası parolasını tutan memcache anahtarını çağırır ve tüm şifrelerin belleğinde şifresini çözer.
  4. Parola sunucusu her 5 dakikada bir yeni bir şifrelenmiş parola dosyası gönderir.
  5. Projenizde şifreli password.php kullanıyorsanız, bu dosyanın harici olarak dokunulup dokunulmadığını veya görüntülenip görüntülenmediğini kontrol eden bir denetim yaparsınız. Bu durumda, belleği otomatik olarak temizleyebilir ve sunucuyu erişim için kapatabilirsiniz.

4

Ek bir hile, şöyle görünen bir PHP ayrı yapılandırma dosyası kullanmaktır:

<?php exit() ?>

[...]

Plain text data including password

Bu, erişim kurallarını düzgün bir şekilde ayarlamanıza engel olmaz. Ancak web sitenizin saldırıya uğraması durumunda, bir "gereksinim" veya "içerme" ilk satırdaki komut dosyasından çıkacaktır, böylece verileri almak daha da zorlaşacaktır.

Yine de, bir dizindeki yapılandırma dosyalarının web üzerinden erişilmesine izin vermeyin. Denetleyici kodunuzu, css, resim ve js içeren bir "Web" klasörünüz olmalıdır. Bu kadar. Başka her şey çevrimdışı klasörlere gider.


ama sonra php betiği dosyada saklanan kimlik bilgilerini nasıl okuyor?
Christopher Mahan

3
Normal bir metin dosyası gibi fopen () yöntemini kullanırsınız.
e-satis

2
@ e-satis ok hacker'ın yapmasını engelleyecek require/ includeama nasıl önlenecek fopen?
dmnc

"Bu, erişim kurallarını düzgün bir şekilde belirlemenizi engellemez"
e-satis

@ e-satis, bu oldukça zekice. merak ediyorum neden kimse bunu düşünmedi. Ancak , editör kopyalama sorununa hala açıktır. feross.org/cmsploit
Pacerier

4

En iyi yol şifreyi hiç saklamamaktır!
Örneğin, bir Windows sistemindeyseniz ve SQL Server'a bağlanıyorsanız, geçerli işlemin kimliğini kullanarak veritabanına parola olmadan bağlanmak için Tümleşik Kimlik Doğrulama'yı kullanabilirsiniz.

Eğer bir şifre birinci bağlantı kurmak gereğini yaparsanız şifrelemek onu, (örneğin AES-256 kullanılarak ve ardından şifreleme anahtarını koruyabilir veya sertifika korumak OS asimetrik şifreleme kullanılarak ve var) güçlü şifreleme kullanarak ve ardından a depolar güçlü ACL'lere sahip yapılandırma dosyası (web dizininin dışında) .


3
Şifreyi tekrar şifrelemenin bir anlamı yok . Şifrelenmemiş parolaya erişebilen biri, parolanın şifresini çözmek için gereken parolayı da alabilir. Ancak, ACL ve .htaccess kullanmak iyi bir fikirdir.
uliwitness

2
@uliwitness Sanırım yanlış anlamış olabilirsiniz - " tekrar şifrelemek" ile ne demek istiyorsun ? Sadece bir şifreleme. Ve şifrelemek için parolaları (insan kullanımı için tasarlanmıştır) kullanmak istemezsiniz, oldukça basit bir anahtar yönetimi, örneğin işletim sistemi tarafından korunan, dosya sistemine erişmenin anahtara erişim izni vermeyeceği şekilde.
AviD

3
Şifreleme sihir değildir - AES anahtarını ACL'lerle korumak yerine şifreyi orada saklayabilirsiniz. AES anahtarına veya şifresi çözülmüş parolaya erişim arasında bir fark yoktur, bu bağlamda şifreleme sadece yılan yağıdır.
MarioVilas

@MarioVilas whaat? Parola şifrelenmişse, işletim sistemi tarafından korunan şifreleme anahtarı ile nasıl bir fark yoktur? Şifreleme sihir değildir - tüm gizliliği daha küçük şifreleme anahtarına sıkıştırır. Sadece edilir Zor bu bağlamda, snakeoil hareketli tüm işletim sistemi içine gizlilik söyledi.
AviD

6
@AviD nasıl işletim sistemi anahtarı koruyabilir ama verilerin kendisini değil? Cevap: her ikisini de koruyabilir, bu nedenle şifreleme gerçekten yardımcı olmaz. Yalnızca verilerin depolanması ve şifreleme anahtarının örneğin bir kullanıcı tarafından yazılması gereken bir paroladan türetilmesi farklı olurdu .
MarioVilas
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.