作为安全措施,是否应该验证用户输入在 PHP(服务器端)中的长度?

信息安全 Web应用程序 php
2021-08-14 06:48:26

需要注意的是,此用户输入将使用正则表达式(在 PHP 中的服务器端)进行验证和清理,然后将被插入到数据库中。稍后它将显示给同一网站上的其他用户(例如:在论坛上)。

我指的是我事先知道我应该从用户那里得到什么长度的情况和我不知道的情况,但我可以假设它不超过 100 个字符。

我试图弄清楚检查用户输入长度是否有任何安全优势。

我知道这因语言而异,我使用的是 PHP。有关任何其他语言(如 Java、.NET、Python 等)的信息都可以。

4个回答

作为一般规则,您应该尽可能地限制用户输入,但不要更多。用于保存城镇名称的字段不需要不受限制的长度。但是,如果您将长度限制为 25,认为没有名字可以更长,您会惹恼威尔士人

如果您担心 SQLi 或 XSS 等问题,较短的输入长度意味着有效载荷的空间更少。因此,它可以被视为针对这些攻击的深度防御。但是,如果这是您的第一道防线,那么您就有大麻烦了……专注于获得基本知识,例如准备好的陈述,对。

最后,您决定使用的任何限制都必须在服务器端强制执行,而不是仅在客户端执行,这是正确的。

这取决于您要保护的内容。

您提到您有一个用于验证输入的正则表达式。这可能很好,但最终取决于您的正则表达式是如何形成的。如果您的 RegEx 看起来像这样,您可能会没事:

{\"name\":\"(.+?)\",\ ?\"age\":(\d+?)}

另一方面,如果您的 RegEx 看起来像这样......

({.+})

仅仅说您使用正则表达式并不足以说明它们对各种攻击(如 SQL 注入或跨站点脚本)的安全性。

长度验证确实可以防止某些形式的拒绝服务攻击。例如,一个 HTTP POST 请求的大小可以是几兆字节。如果您只是将收到的内容复制到数据库中,那么攻击者可以迅速用垃圾填满您的数据库并影响您的可用性。

Web 应用程序客户端的任何验证都可以轻松绕过,从安全角度来看,不应依赖该验证。

浏览器开发人员工具包括非常好的 Html/JavaScript 调试器,允许逐步执行客户端代码,修改属性和脚本以绕过安全检查和验证。

即使是平庸的黑客也知道如何利用它。从安全角度来看,有必要重新检查服务器端的验证。

在我的应用程序中,我在服务器端完成大部分前端工作。我使用返回验证消息或确认页面 URL 的 IFRAME 或 XmlHttpClient 提交大多数表单。这对于大多数表单来说更容易开发并且响应迅速。即便如此,我还是编写了很多客户端 JavaScript,但只有在对性能或用户体验产生更大影响时才会这样做。这是一种 80/20 的策略。

作为安全措施?不。

当用户能够将命令(通常以数据库查询的形式)输入到您没有正确转义的变量中时,就会发生通过用户输入的攻击。虽然截断的输入可能会无意中阻止攻击,但它并不能真正解决问题。

在安全方面,您应该验证所有用户输入,并检查输入是否仅以受保护的方式使用,其中一些情况是:

  1. 如果要以 HTML 格式输出值,您需要确保其中没有 HTML 标签 ( strip_tags) 或只有您允许的标签(使用库或DOMDocument为此)。
  2. 如果要在计算中使用该值,请确保它是有效数字。最简单的方法是投射为(int)$foo(float)$foo,但您的需求可能会有所不同。
  3. 如果要将值存储在数据库中,请确保不要以不安全的方式构建查询。保持查询安全的最佳方法是使用准备好的语句,PDO这对它有好处。否则,您需要确保在构建查询之前转义用户输入。

如果您告诉用户只输入字母和数字作为值,那么您应该只接受服务器上的字母和数字。您可以在客户端添加相同的条件,以防止给您的用户带来意外(在发送表单之前给他们一个错误),但服务器是您真正保护自己的地方,因为客户端验证是提供信息的,它不是保护性的(它很容易被绕过)。

在此基础上,如果你只能在一个字段中存储有限数量的字符,那么如果字段太长,你也可以向用户报告。

假设您想要一个长度不超过 128 个字符的电子邮件地址,您可以像这样在各个级别处理它:

数据库(模型)

CREATE TABLE Emails `email` VARCHAR(128) NOT NULL

PHP(控制器)

$email = $_POST['email'];
if ((strlen($email) > 128) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
    // Produce error that input was invalid
    die('ERROR: Invalid e-mail');
}

// Input is valid, store in database (e.g- with PDO)
$stmt = $pdo->prepare('INSERT INTO Emails (email) VALUES (?)');
$stmt->execute([$email]);

HTML(视图)

<input name="email" type="email" maxlength="128" placeholder="E-mail" />

这为您提供了存储效率、正确性、安全性和对用户的反馈的良好组合;如果他们有一个支持 HTML5 的浏览器,如果他们尝试发送一个无效的值,他们会得到早期的错误,但我们还是会检查服务器的安全性(不符合 HTML5 的浏览器,或恶意用户)。