[英]How to secure database passwords in PHP?
當 PHP 應用程序建立數據庫連接時,它當然通常需要傳遞登錄名和密碼。 如果我為我的應用程序使用單一的、最低權限的登錄名,那么 PHP 需要在某處知道該登錄名和密碼。 保護該密碼的最佳方法是什么? 似乎只是在 PHP 代碼中編寫它並不是一個好主意。
一些人將此誤讀為關於如何在數據庫中存儲密碼的問題。 那是錯的。 它是關於如何存儲讓您訪問數據庫的密碼。
通常的解決方案是將密碼從源代碼中移到配置文件中。 然后讓系統管理員負責管理和保護該配置文件。 這樣開發人員不需要知道任何關於生產密碼的信息,並且在你的源代碼控制中沒有密碼記錄。
如果您托管在其他人的服務器上並且在您的 webroot 之外沒有訪問權限,您始終可以將您的密碼和/或數據庫連接放在一個文件中,然后使用 .htaccess 鎖定該文件:
<files mypasswdfile>
order allow,deny
deny from all
</files>
最安全的方法是根本沒有在 PHP 代碼中指定的信息。
如果您使用 Apache,則意味着在 httpd.conf 或虛擬主機文件文件中設置連接詳細信息。 如果這樣做,您可以不帶參數調用 mysql_connect(),這意味着 PHP 永遠不會輸出您的信息。
這是在這些文件中指定這些值的方式:
php_value mysql.default.user myusername
php_value mysql.default.password mypassword
php_value mysql.default.host server
然后你像這樣打開你的 mysql 連接:
<?php
$db = mysqli_connect();
或者像這樣:
<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
ini_get("mysql.default.password"),
ini_get("mysql.default.host"));
將它們存儲在 Web 根目錄之外的文件中。
對於極其安全的系統,我們在配置文件中加密數據庫密碼(它本身由系統管理員保護)。 在應用程序/服務器啟動時,應用程序會提示系統管理員輸入解密密鑰。 然后從配置文件中讀取數據庫密碼,解密並存儲在內存中以備將來使用。 仍然不是 100% 安全,因為它存儲在已解密的內存中,但您必須在某個時候稱其為“足夠安全”!
此解決方案是通用的,因為它對開源和閉源應用程序都很有用。
好處:
這個方法是 Heroku 推薦的,非常成功。
如果可以在存儲憑據的同一文件中創建數據庫連接。 在連接語句中內聯憑據。
mysql_connect("localhost", "me", "mypass");
否則最好在 connect 語句之后取消設置憑據,因為不在內存中的憑據無法從內存中讀取;)
include("/outside-webroot/db_settings.php");
mysql_connect("localhost", $db_user, $db_pass);
unset ($db_user, $db_pass);
以前我們將數據庫用戶/密碼存儲在配置文件中,但此后已進入偏執模式——采用深度防御策略。
如果您的應用程序受到威脅,用戶將擁有對您的配置文件的讀取權限,因此破解者有可能讀取此信息。 配置文件也可能陷入版本控制,或在服務器上復制。
我們已經切換到在 Apache VirtualHost 中設置的環境變量中存儲用戶/密碼。 這個配置只能被 root 讀取——希望你的 Apache 用戶沒有以 root 身份運行。
與此相反的是,現在密碼在全局 PHP 變量中。
為了降低這種風險,我們采取了以下預防措施:
phpinfo()
被禁用。 PHPInfo 是一個簡單的目標,可以了解所有內容,包括環境變量。如果您使用的是 PostgreSQL,那么它會自動在~/.pgpass
查找密碼。 有關更多信息,請參閱手冊。
您的選擇是有限的,因為您說訪問數據庫需要密碼。 一種通用方法是將用戶名和密碼存儲在單獨的配置文件而不是主腳本中。 然后確保將其存儲在主網絡樹之外。 那是如果存在 Web 配置問題,使您的 php 文件僅顯示為文本而不是被執行,則您沒有公開密碼。
除此之外,您處於正確的行上,對正在使用的帳戶的訪問權限最小。 添加到那個
彼得
我們是這樣解決的:
將數據庫密碼放在一個文件中,使其對提供文件的用戶只讀。
除非您有某種方法只允許 php 服務器進程訪問數據庫,否則您幾乎可以做到這一點。
另一個技巧是使用一個 PHP 單獨的配置文件,如下所示:
<?php exit() ?>
[...]
Plain text data including password
這不會阻止您正確設置訪問規則。 但是如果您的網站被黑,“require”或“include”只會在第一行退出腳本,因此獲取數據更加困難。
然而,永遠不要將配置文件放在可以通過 Web 訪問的目錄中。 您應該有一個“Web”文件夾,其中包含您的控制器代碼、css、圖片和 js。 就這樣。 其他任何內容都在脫機文件夾中。
如果您談論的是數據庫密碼,而不是來自瀏覽器的密碼,那么標准做法似乎是將數據庫密碼放在服務器上的 PHP 配置文件中。
您只需要確保包含密碼的 php 文件對其具有適當的權限。 即它應該只能由 Web 服務器和您的用戶帳戶讀取。
通常的做法是將它放入某個配置文件中。 只要確保你:
最好的方法是根本不存儲密碼!
例如,如果您在 Windows 系統上連接到 SQL Server,則可以使用集成身份驗證連接到數據庫,無需密碼,使用當前進程的標識。
如果你需要一個密碼時,先進行加密連接,使用強大的加密(例如,使用AES-256,然后保護加密密鑰,或使用非對稱加密,並有操作系統保護證書),然后將其存儲在一個具有強 ACL 的配置文件(在 web 目錄之外)。
實際上,最佳做法是將數據庫憑據存儲在環境變量中,因為:
如何使用它們?
$_ENV['MYVAR'] = $myvar
echo $_ENV["MYVAR"]
您可以輕松地刪除包含所有環境變量的文件,例如 envvars.php 並執行它( php envvars.php
)並刪除它。 這有點老派,但它仍然有效,並且您在服務器中沒有任何帶有憑據的文件,並且代碼中沒有憑據。 由於它有點費力,框架做得更好。
Symfony 示例(好吧,不僅是 PHP) Symfony 等現代框架建議使用環境變量,並將它們存儲在 .env 未提交文件中或直接存儲在命令行中,這意味着您可以這樣做:
symfony var:set FOO=bar --env-level
文件:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.