安全性

请记住,互联网是由不希望我们拥有任何秘密的人创建的。同时,还要记住,很多人被雇佣来学习我们的秘密并将其记录在某个地方。

偏执是一种智慧的表现。


连接参数

有时,连接参数(包括用户名和密码)会存储在纯文本文件中,例如 .ini 文件。这是非常不安全的:如果某个用户猜到文件名,他可以读取文件。如果文件位于 Web 服务器的 WWW 目录之外,则稍微安全一些,但更好的做法是将其作为常量存储在程序文件中。

总有可能某个用户能够获取你的 FTP 密码或其他密码。因此,连接 MySQL 使用的用户名和密码应该与其他服务的用户名/密码不同。

MySQL 密码必须是安全的。你不需要记住它们。密码应该包含小写字母、大写字母、数字和符号(如‘_’);它们不应包含已有的单词或你的出生日期;它们不应通过电子邮件发送(如果发送了,必须有修改它们的办法);它们不应存储在不必要的地方。


SQL 注入

什么是 SQL 注入?

在一个理想的世界里,你应该知道,$_POST 中包含的值是你可以插入到 SQL 语句中的值。但是在现实世界里,由于贫困和专有软件的存在,情况并非如此。这些值可能包含被称为“SQL 注入”的攻击。当你期望像 "'42'" 这样的值时,你可能会遇到像 "'42' OR 1" 这样的值。因此,当你尝试执行如下语句时:

DELETE FROM `articles` WHERE `id`=42

你实际上可能创建出这样的语句:

DELETE FROM `articles` WHERE `id`=42 OR 1

这将删除所有记录。

此外,在某些情况下,你可能尝试执行如下查询

SELECT * FROM `my_nice_table` WHERE title='bla bla'

而用户可以将其修改为:

SELECT * FROM `my_nice_table` WHERE title='bla bla'; TRUNCATE TABLE `my_nice_table`

这些只是示例。如果所有记录从你的表中消失,你很容易发现。如果表格已被正确备份,你可以恢复数据。但有更糟糕的情况。如果用户学会了如何操纵你的数据库,他可以为自己创建管理员账户,或者他可以对你的网站内容进行修改,而你永远也看不到,甚至可以注册自己没有支付的款项。


如何防止 SQL 注入

简单来说,必须代表值的输入如果包含其他内容,则不应被接受。

  1. 字符串值
    字符串值用单引号 ' 括起来。每个字符串中的引号应转换为 ''\'PHP 推荐使用 mysql_real_escape_string 来替换这些特殊字符。

  2. 数字(整数、浮动数)
    它们必须是数字。如果它们包含 OR 或空格,则不是数字。

  3. 日期
    日期应用单引号括起来,并像字符串一样处理。

  4. NULL / UNKNOWN / TRUE / FALSE
    这些值不应由用户输入,而应通过程序生成。

  5. SQL 名称
    在某些情况下,SQL 名称可能包含在用户输入中。常见的情况是用来排序的列名,这些列名可能来自 $_GET。将它们用反引号 括起来,并将每个反引号替换为两个反引号 ` 。通常,如果 SQL 名称仅用于 ORDER BY` 子句,这是一种可以接受的做法。

  6. 注释
    用户输入不应直接插入 SQL 注释中。

  7. 密码
    当密码存储在数据库中时,它们通常应该是加密的。加密应由脚本完成,而不是 MySQL。如果通过 SQL 执行加密,密码将作为明文写入语句中。这意味着密码可能通过以下方式暴露:

    • 可能通过系统日志,如果与数据库的通信是通过网络且没有加密
    • MySQL 日志
    • SHOW PROCESSLIST

    因此,永远不要发送如下查询

    SELECT 1 FROM `users` WHERE `password`=MD5('abraxas')
    

    PHP 中,你应该这样写:

    $sql = "SELECT 1 FROM `users` WHERE `password`=MD5('".md5('abraxas')."')";
    

    永远不要使用不安全的加密函数,如 PASSWORD()。另外,不应使用双向加密。只有像 SHA256 这样的加密散列是安全的,避免使用过时的散列算法,如 MD5。

    即使密码已经安全地加密,也不应通过 SELECT 查询来获取它们。这是不安全的,且单向加密并不需要这样做。


SSL

如果数据库中的所有内容都是公开的,那么没有理由使用加密通信。但通常情况并非如此。即使如此,可能仍然有一小部分用户被授权提交新内容,这就需要使用密码。

因此,使用 SSL 加密通常是一个好的选择。请参阅你驱动程序的文档,了解如何实现这一点(通常只是一个简单的连接选项)。

SSL 不仅加密包含用户密码的网络流量,而且通过证书验证用户所访问的网站是否是正确的。一个可能的攻击方式是创建一个伪造网站,试图诱使你提交用户名和密码。

Last modified: Friday, 17 January 2025, 7:37 PM