当PHP应用程序建立数据库连接时,它当然通常需要传递登录名和密码.如果我正在为我的应用程序使用单个最小权限登录,那么PHP需要知道某处的登录名和密码.保护密码的最佳方法是什么?看起来只是在PHP代码中编写它并不是一个好主意.
有几个人误以为是关于如何在数据库中存储密码的问题.那是错的.它是关于如何存储允许您访问数据库的密码.
通常的解决方案是将密码从源代码中移出到配置文件中.然后将管理和保护配置文件保留给系统管理员.这样开发人员就不需要了解生产密码,也没有源代码控制中的密码记录.
如果您在其他人的服务器上托管并且无法访问您的webroot,您可以始终将您的密码和/或数据库连接放在一个文件中,然后使用.htaccess锁定该文件:
order allow,deny deny from all
最安全的方法是根本不具备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脚本)都可以通过`ini_get()`读取密码.
Marki555表示,可以运行PHP代码的攻击者也可以调用PHP函数,这显然是正确的,而且无法采取任何措施。我还想补充一点,我不再遵循我自己在此答案中给出的建议,而是使用环境变量。不过,概念很相似:不要将您的凭据存储在代码中,而是以某种方式注入它们。使用`ini_get()`或`getenv()`并不重要。
@DeepBlue如果可以注入ini_get(),也可以注入file_get_contents(anypath)。只要php有办法获取密码,任何恶意代码也会如此。
4> da5id..:将它们存储在Web根目录之外的文件中.
而且,正如其他地方所提到的,在源代码控制之外.
我们可以包括它吗?例如在PHP中我们可以做`include('../ otherDirectory/configfile.conf')`?
5> pdavis..:对于极其安全的系统,我们在配置文件中加密数据库密码(配置文件本身由系统管理员保护).在应用程序/服务器启动时,应用程序然后提示系统管理员提供解密密钥.然后从配置文件中读取数据库密码,解密并存储在内存中以备将来使用.仍然不是100%安全,因为它存储在解密的内存中,但你必须在某些时候称它为"足够安全"!
如果管理员死了怎么办?
@RaduMurzea那太荒谬了.你什么时候听说系统管理员死了?他们就像麦当劳,他们只是突然出现/消失!
@Radu Murzea只有2个或更多的管理员,然后你就像raid阵列一样.一次失败多个驱动器的可能性要低得多.
什么时候服务器重启?唤醒管理员让他们在.etc.etc中输入密码需要多长时间.大声笑
6> Neil McGuiga..:该解决方案是通用的,因为它对于开源和闭源应用都是有用的.
为您的应用程序创建OS用户.请参见http://en.wikipedia.org/wiki/Principle_of_least_privilege
使用密码为该用户创建(非会话)OS环境变量
以该用户身份运行应用程序
好处:
您不会意外地将密码检查到源代码管理中,因为您不能
您不会意外搞砸文件权限.好吧,你可以,但它不会影响这一点.
只能由root或该用户读取.Root无论如何都可以读取所有文件和加密密钥.
如果使用加密,如何安全地存储密钥?
Works x平台
请确保不要将envvar传递给不受信任的子进程
Heroku建议这种方法非常成功.
7> Bob Fanger..:如果可以在存储凭据的同一文件中创建数据库连接.内联connect语句中的凭据.
mysql_connect("localhost", "me", "mypass");否则最好在connect语句之后取消设置凭据,因为无法从内存中读取不在内存中的凭据;)
include("/outside-webroot/db_settings.php"); mysql_connect("localhost", $db_user, $db_pass); unset ($db_user, $db_pass);
如果有人可以访问内存,那么无论如何你都被搞砸了.这是毫无意义的假安全性.在webroot之外(或者至少受.htaccess保护,如果你没有访问webroot上面)是唯一安全的选择.
@uliwitness - 这就像是说因为有人可以用乙炔火炬切断你的网络运营中心的锁意味着门也是假的安全.将敏感信息保持在最严格的范围内总是有意义的.
8> Vagnerr..:您的选择有限,因为您说您需要密码才能访问数据库.一种通用方法是将用户名和密码存储在单独的配置文件中,而不是主脚本中.然后一定要将其存储在主Web树之外.那就是如果有一个Web配置问题,你的php文件只是显示为文本而不是被执行,你没有暴露密码.
除此之外,您使用的是正确的线路,并且对所使用的帐户的访问权限最小.加上那个
不要将用户名/密码的组合用于其他任何事情
将数据库服务器配置为仅接受来自该用户的Web主机的连接(如果数据库位于同一台计算机上,localhost甚至更好)这样即使凭证被公开,除非他们具有对其他人的访问权限,否则它们对任何人都没用.机.
对密码进行模糊处理(即使ROT13会这样做)如果有人能够访问该文件,它也不会提供太多防御,但至少它会阻止随意查看它.
彼得
9> Jim..:如果您使用的是PostgreSQL,那么它会
~/.pgpass
自动查找密码.有关详细信息,请参阅手册.
10> Chris..:将数据库密码放在一个文件中,使其对服务文件的用户只读.
除非你有一些只允许php服务器进程访问数据库的方法,否则这几乎就是你所能做的.
11> Courtney Mil..:以前我们将DB user/pass存储在一个配置文件中,但后来又变成了偏执模式 - 采用了深度防御策略.
如果您的应用程序遭到入侵,则用户将具有对您的配置文件的读取权限,因此有可能让黑客读取此信息.配置文件也可以在版本控制中捕获,或者在服务器周围复制.
我们已经切换到存储用户/传递Apache VirtualHost中设置的环境变量.此配置只能由root读取 - 希望您的Apache用户不以root用户身份运行.
与此相关的是,现在密码是全局PHP变量.
为了降低这种风险,我们采取以下预防措施:
密码已加密.我们扩展PDO类以包括用于解密密码的逻辑.如果有人读取我们建立连接的代码,则使用加密密码而不是密码本身建立连接并不明显.
加密密码从全局变量移动到私有变量应用程序立即执行此操作以减少该值在全局空间中可用的窗口.
phpinfo()
被禁用.PHPInfo是一个简单的目标,可以概述所有内容,包括环境变量.