0

请原谅初学者的问题。欢迎提出建议、链接和进一步阅读。

我担心网页的安全性并寻找最佳实践。当使用 PHP 连接到 MariaDB/MySQL 数据库时,大多数建议将数据库密码放在 PHP 页面(或包含的页面)上。这安全吗?有更好的“最佳实践”吗?

我用“哈希密码 MySQL MariaDB PHP7”等关键字搜索了文档、Stack Overflow 和互联网,但答案都是关于客户端登录到网页,而不是 PHP 直接与 MariaDB 交互。MySQL Docs说密码是为了存储而散列的,但这对我的 PHP 文件没有帮助。PHP 文档没有提供太多有用的信息,也没有实际示例。

所以,我的问题:

  1. HTTP 用户下载我的源文件并查看这些密码的风险有多高?(我意识到 PHP 会解析页面,因此一般用户不会看到原始代码或能够下载 PHP——而 ssh、PHP、MariaDB 等的安全性是一个单独的问题。)

  2. 我知道我可以散列密码,但是如果密码就在同一页面上,这有什么用?(或者我错过了什么?)

  3. 将数据库变量放在文件中,还是使用 include("super-sensitive-info.php")并将变量放在那里更好/更安全?我可以(应该)散列或加密那个文件或密码,并且仍然可以使用吗?我可以(我应该)隐藏这个文件,例如.super-sensitive-info.php),然后使用服务器安全来限制访问吗?

  4. 而且,使用特殊字符给我带来了麻烦,例如,按照典型的代码在引号中的做法,$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";
4

3 回答 3

0

您缺少 PHP 的一个非常重要的安全性:来自用户(或被黑 url)然后放入 SQL 查询的“绑定”或“转义”参数。

阅读“SQL 注入”。

于 2018-05-08T03:43:57.970 回答
0

对于一些最佳实践,请查看最常用的框架代码。

简而言之,@chris85 提出了最重要的几点。通常它具有文件夹结构:

config/config.local.php
public/index.php

添加config/*.local.php到 git 忽略:

$ echo "config/*.local.php">>.gitignore

config.php

return [
  'db' => [
    'username' => '...',
    ...
  ]
];

index.php

$config = require '../config.php';
$db = DbConnect($config['db']);
echo json_encode($db->getAllEpisodes());

从公共文件夹提供您的页面:

$ php -S localhost:8000 -t ./public/
于 2018-04-18T21:18:24.390 回答
0

您将身份验证实体(通常是服务器)验证提供给它的密码的方式与需要证明其凭据的实体(通常是客户端)存储其密码的方式混淆了。服务器,在您的示例中,mysql 数据库将密码存储为哈希值 - 因此即使数据泄露,也无法确定原始密码是什么。一个重要的特性是,当客户端希望进行身份验证时,它必须显示密码的明文,以便服务器可以重复散列过程。如果密码在客户端上经过哈希处理并发送到服务器,则验证将基于客户端提供的内容与服务器上存储的内容之间的精确匹配。明文的哈希变成了密码——这很不安全.

在 PHP/MySQL 实例的情况下,是的,您的 PHP 需要密码的明文,并且需要将其提供给数据库以进行身份​​验证。还有其他方法,但这些通常仅适用于您在身份验证两端控制代码的情况。因此,密码的明文可能比散列密码更容易暴露。

您不能存储 PHP 用来连接到散列的数据库的密码。

在考虑保护明文的方法之前,您应该尽量减少可以使用明文的上下文。MySQL 可以使用 x509 证书进行身份验证(这在 PHP端由 mysqli支持),但这实际上只是一个非常大的密码。最好在 mysql 中配置帐户,使其只能从特定地址(或单个 PHP/mysql 节点的 localhost)访问。

GRANT ALL ON yourdb.* TO 'phpuser'@'192.168.0.%';

..但如果您不控制基础设施,则不是很方便。

HTTP 用户下载我的源文件的风险有多高

当您知道如何以及由谁管理基础架构时,这很难量化。但是您似乎忽略了可能泄露数据的其他途径。

至于保护密码......

  • 正如其他人所说,如果您将密码存储在文件中,那么确保该文件位于文档根目录之外是个好主意。

  • 将其命名为包含带有 .php 扩展名的密码的文件应该意味着如果网络服务器确实直接指向该文件,它将尝试执行它,而不是将内容返回给 http 客户端。虽然试图隐藏文件是隐蔽的安全性,因此不是一个好主意,但标记密码的存在并不是一个好习惯。

  • 在 Apache(和其他一些网络服务器)的情况下,在文件名前加上“.ht”通常会阻止网络服务器直接访问它

  • 您可以将 mysql 用户名和密码存储为 PHP ini 设置(因此也可以存储在 .htaccess 文件中)。这是攻击者寻找密码的一个相当明显的地方——但在某些情况下可能是合适的。

加密密码只是意味着您需要找到安全的地方来存储加密密钥,而不是安全的地方来存储密码。

我是否错过了我不应该在 SQL 中使用特殊字符的备忘录?

您的数据库密码通常不会出现在 SQL 语句中(from 除外GRANT...IDENTIFIED BY....)。无论如何,只要对特殊字符进行了适当的转义,您就可以使用它们。但是特殊字符对于密码来说并不重要——一些系统坚持使用它们的原因是因为人类选择了容易猜到的密码。与使用 ASCII 字符集中的可打印字符随机生成的密码相比,自然语言单词的每个字符的熵大约只有一半 - 因此,10 个字符的随机密码与基于单词的 20 个字符的密码一样强。计算机非常擅长记住大量数据。在这样的上下文中使用随机密码是一种很好的做法。

如果您需要记住手动访问数据库的密码,请为此使用单独的帐户。

有时最好不要在文件系统上保留密码——这可以避免密码出现在上传到版本控制系统和备份中的风险。其他可以放密码的地方是环境,或者共享内存。Linux 有一个很好的虚拟 HSM 功能和内核密钥存储,但是每次你想检索密码以连接到数据库时都在 shell 中运行是相当低效的(AFAIK 没有桥接 API 的 PHP 扩展)

于 2018-04-18T22:24:44.637 回答