请原谅一个初学者的问题。欢迎提供建议、链接和进一步阅读。
我关心网页的安全性,并寻找最佳实践。当使用php连接mariadb/mysql数据库时,大多数建议将数据库密码放在php页面(或包含的页面)上。这安全吗?有更好的“最佳实践”吗?
我搜索过docs、stack overflow和关键字为“hash passwords mysql mariadb php7”等的interwebs,但答案都是关于客户端登录网页,而不是php直接与mariadb交互。mysql文档说密码是散列存储的,但是这对我的php文件没有帮助。php文档没有提供太多有用的信息,也没有实际的例子。
所以,我的问题是:
http用户下载我的源文件并查看这些密码的风险有多高(我意识到php解析页面,所以一个典型的用户不会看到原始代码,也无法下载php——而ssh、php、mariadb等的安全性是一个单独的问题。)
我知道我可以散列密码,但这有什么好处,如果密码就在同一页上(或者我遗漏了什么?)
将数据库变量放入文件或使用 include("super-sensitive-info.php")
把变量放在那里?我能(应该)散列或加密该文件或密码,并使其仍然可用吗?我能把这个文件藏起来吗。 .super-sensitive-info.php
),然后使用服务器安全性来限制访问?
而且,使用特殊字符给我带来了麻烦。 $password = "pa$$w@rd";
应该看起来像 $password = "pa\$\$w\@rd";
,根据引用实践中的典型代码?或者我错过了我不应该在sql中使用特殊字符的备忘录?
为了创建一个简单的示例,假设我有两个文件,看起来像这样。有更好的办法吗?还是这样?
超级敏感信息.php
$user = "username"
$password = "password"
// $password = "pa\$\$w\@rd"; // (e.g. if database pw is "pa$$w@rd"?
$database_name = "database_name"
// I can hash it, but this seems only useful for client logins and such,
// unless I can hash this entire file....
// $hashed_password = password_hash($password, PASSWORD_DEFAULT);
索引.php
include("super-sensitive-info.php")
$db = mysqli_connect('localhost',$user,$password,$database_name)
or die('Error connecting to MySQL server: ' . mysqli_connect_error());
$query = "SELECT * FROM episodes";
3条答案
按热度按时间1cosmwyk1#
您缺少了php的一个非常重要的安全性:“binding”或“escaping”参数,这些参数来自用户(或被入侵的url),然后放入sql查询。
阅读“sql注入”。
xlpyo6sf2#
对于一些最佳实践,请查看最常用的框架代码。
简而言之,@chris85提出了最重要的几点。通常有文件夹结构:
添加
config/*.local.php
要忽略git:在
config.php
:在
index.php
:从公用文件夹提供页面:
ukdjmx9f3#
您将身份验证实体(通常是服务器)验证提供给它的密码的方式与需要证明其凭据的实体(通常是客户端)存储其密码的方式混淆。在您的示例中,服务器mysql数据库将密码存储为哈希值,因此即使数据泄漏,也无法确定原始密码是什么。一个重要的特性是,当客户端希望进行身份验证时,它必须提供密码的明文,以便服务器可以重复哈希过程。如果密码在客户机上散列并发送到服务器,那么验证将基于客户机显示的内容和服务器上存储的内容之间的精确匹配。明文的散列已成为密码-这是非常不安全的。
在php/mysql示例中,是的,您的php需要密码的明文,并且需要将其呈现给数据库以进行身份验证。还有其他方法,但这些方法通常只适用于在身份验证的两端控制代码的情况。因此,密码的明文可能比散列密码更容易暴露。
不能存储php用于连接哈希数据库的密码。
在考虑保护明文的方法之前,您应该尽量减少可以使用它的上下文。mysql可以使用x509证书进行身份验证(mysqli在php端支持这一点),但这实际上相当于一个非常大的密码。在mysql中配置帐户是一个好主意,这样它们只能从特定的地址(或者在单个php/mysql节点的情况下是localhost)访问。
..但如果你不控制基础设施就不太方便了。
http用户下载我的源文件的风险有多高
当您知道如何以及由谁管理基础架构时,很难对其进行量化。但您似乎忽略了数据可能通过的其他路径。
至于保护密码。。。。
正如其他人所说,如果您将密码存储在一个文件中,那么最好确保该文件位于文档根目录之外。
将其命名为包含.php扩展名的密码的文件意味着如果Web服务器直接指向该文件,它将尝试执行该文件,而不是将内容返回给http客户端。虽然试图隐藏文件是安全的模糊,因此不是一个好主意,标志张贴密码的存在是不好的做法。
对于apache(和其他一些Web服务器),在文件名前面加“.ht”通常会阻止Web服务器直接访问它
您可以将mysql用户名和密码存储为phpini设置(因此也可以存储在.htaccess文件中)。这是攻击者查找密码的一个相当明显的地方,但在某些情况下可能是合适的。
加密密码只是意味着你需要找一个安全的地方来存储加密密钥,而不是找一个安全的地方来存储密码。
我是否错过了我不应该在sql中使用特殊字符的备忘录?
您的数据库密码通常不会出现在sql语句中(除了
GRANT...IDENTIFIED BY....
). 不管怎样,只要适当转义,就可以使用特殊字符。但是,特殊字符对密码并不重要——一些系统之所以坚持使用这些字符,是因为人类选择的密码很容易猜测。与使用ascii字符集的可打印字符随机生成的密码相比,一个自然语言单词的每个字符的熵约为其一半,因此10个字符的随机密码与基于单词的20个字符的密码一样强大。计算机非常善于记忆大量的数据。在这样的上下文中使用随机密码是一种很好的做法。如果需要记住手动访问数据库的密码,请使用单独的帐户。
有时最好不要将密码保存在文件系统中—这样可以避免密码在上传到版本控制系统和备份时出现的风险。您可以在环境或共享内存中输入密码的其他位置。linux有一个很好的虚拟hsm功能,带有内核密钥存储,但是每次你想要检索密码连接到数据库时,在shell中运行是非常不高效的(afaik没有一个php扩展来桥接api)