在Web开发期间,我有多少时间会花在用户输入验证上?

时间:2020-03-06 14:30:07  来源:igfitidea点击:

我是开发网络事物的新手。到目前为止,我花费大量时间(大约50%)来尝试防止不良用户将sql注入之类的内容放入我的输入表单并在服务器端对其进行验证。这正常吗?

解决方案

不,这是不正常的。也许我们需要:

  • 使用权限组件避免SQL注入(Java中的PreparedStatements)
  • 创建一个组件来"过滤"来自用户的消息(Java中的Servlet过滤器)。

任何现代语言都支持这两种方式。

亲切的问候

很高兴我们能保护自己。太多没有。

但是,正如其他人所说的那样,更好的体系结构选择将使问题消除。使用准备好的语句(大多数语言应对此提供支持)将使SQL注入攻击消失。加上许多数据库,它们将显着提高性能。处理跨站点脚本攻击更为棘手。但是基本策略必须是确定如何逃避用户输入,确定在何处逃避输入,并始终在同一位置进行操作。不要陷入认为多多益善的陷阱!在一个地方以一种方式始终如一地执行此操作就足够了,并且可以避免我们不得不找出多个转义级别中的哪个导致了特定的错误。

或者通过学习如何创建和维护合理的体系结构来学习经验。而且,它需要反思不良经历。因此,请注意当前的痛点(看起来很像),并考虑可以采取不同的措施来避免这些痛点。如果我们有导师,请与导师交谈。在这个项目中,这并不总是能为我们提供太多帮助,但在下一个项目中,它将有所帮助。

为了防止sql注入攻击,只需使用准备好的语句进行查询(确切的方法将取决于平台)。一旦这样做,我们就不必再为这个特定方面而烦恼了。我们只需要在任何地方使用它。

至于一般的输入验证,最好依靠一个通用的基础来测试必填字段,数字等。例如,ASP.Net的验证器非常易于使用。我们应该遵循的一条经验法则是不要轻易信任客户端(javascript)为我们执行此操作,因为它很容易解决。始终首先在服务器端执行此操作。

当我们允许引入可能包含html / javascript的丰富内容时,一个特殊的情况要引起注意。这可能允许恶意用户向数据中注入JavaScript,从而触发我们在呈现时不受控制的代码。不要尝试滚动自己的验证代码。在网络上搜索免费的,经过测试的,可维护的代码,这些代码将为我们完成任务。 Jeff在其中一个播客中提供了一些有关这方面的建议。

一旦我们使输入验证代码自动化,花在代码上的时间就应该与业务规则的复杂性直接相关。因此,一般规则是:保持简单。

@Jeremy一些PHP细节

对于数据库查询,请始终尝试使用准备好的参数化查询。 mysqli和PDO库支持此功能。这比使用转义函数(例如mysql_real_escape_string)更加安全。

是的,mysql_real_escape_string实际上只是一个字符串转义函数。这不是灵丹妙药。它所要做的就是逃避危险字符,以便可以安全地在单个查询字符串中使用它们。但是,如果我们不事先清理输入内容,那么我们将容易受到某些攻击媒介的攻击。

想象下面的SQL:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

我们应该能够看到这很容易被利用。
假设id参数包含公共攻击向量:

1 OR 1=1

它们没有危险的字符进行编码,因此它将直接通过转义过滤器。离开我们:

SELECT fields FROM table WHERE id = 1 OR 1=1

这是一个可爱的SQL注入向量。

这些功能虽然有用,但必须谨慎使用。我们需要确保所有Web输入都经过一定程度的验证。在这种情况下,我们发现我们可以被利用,因为我们没有检查用作数字的变量实际上是数字。在PHP中,我们应该广泛使用一组函数来检查输入是否为整数,浮点数,字母数字等。但是对于SQL,请注意准备好的语句的大部分值。如果上面的代码是预准备的语句,则上面的代码将是安全的,因为数据库函数会知道" 1 OR 1 = 1"不是有效的文字。

至于htmlspecialchars()。那是它自己的雷区。

PHP中存在一个真正的问题,因为它具有与html相关的各种转义功能的全部选择,而对于确切的功能没有明确的指导。

首先,如果我们位于HTML标记内,则确实会遇到麻烦。看着

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

我们已经在HTML标记中,因此我们不需要<或者>做任何危险的事情。我们的攻击媒介可能就是javascript:alert(document.cookie)

现在结果HTML看起来像

<img src= "javascript:alert(document.cookie)" />

攻击直截了当。

情况变得更糟。为什么?因为htmlspecialchars仅编码双引号而不是单引号。所以如果我们有

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

我们的邪恶攻击者现在可以注入全新的参数

pic.png' onclick='location.href=xxx' onmouseover='...

给我们

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

在这些情况下,没有魔术的子弹,我们只需要自己修改输入即可。如果我们尝试滤除不良字符,我们肯定会失败。采取白名单方法,只允许通过一些好的字符。查看XSS备忘单,了解有关如何实现多种向量的示例

即使我们在HTML标记之外使用htmlspecialchars($ string),我们仍然容易受到多字节字符集攻击向量的攻击。

我们可能最有效的方法是使用mb_convert_encoding和htmlentities的组合,如下所示。

$str = mb_convert_encoding($str, ‘UTF-8′, ‘UTF-8′);
$str = htmlentities($str, ENT_QUOTES, ‘UTF-8′);

即使这样,由于IE6处理UTF的方式,它也容易受到攻击。但是,在IE6的使用率下降之前,我们可以使用更有限的编码,例如ISO-8859-1.

只是关于准备好的声明的注释。首先,如果可以的话,应该尝试使用存储过程...在大多数情况下,它们可能是更好的解决方案。

其次,只有当我们不使用动态SQL(即编写更多SQL然后执行它的SQL)时,它们都可以保护我们免受SQL注入。在这种情况下,它们将无效-存储过程也将无效。

关于我们花费的时间百分比:验证非常重要,即使没有时间,也需要一些思考。但是百分比取决于应用程序的大小,不是吗?在一个很小的应用程序中,例如,只有新闻通讯注册,验证很有可能会花费我们大量的时间。

在较大的应用程序中,即我们有很多非表示代码的地方,这是不正常的。

我明白你的问题了。看起来保护逻辑遍布整个代码库。而且,每次编写潜在危险的代码时,都必须小心包括所有保护措施。而且,每当出现新威胁时,我们都必须仔细阅读所有这些声明,并验证它们的安全性。

我们无法通过这种方式实现真正的安全性。

我们应该有一些包装器,即使不是没有可能,这也会使生成不安全的代码变得困难。例如,准备好的语句。但是我们可能想要使用ORM,例如Ruby on Rails的ActiveRecord,或者框架中的等效项。

对于输出和XSS保护,请确保默认情况下输出是HTML转义的。然后,如果我们确实需要将生成的HTML输出给用户,则可以明确地执行此操作,这样将更易于验证。

对于CSRF保护,请尝试查找通用解决方案。通常,它应该自动执行其职责,而无需我们显式创建验证令牌,手动验证,丢弃它或者拒绝请求。

我们面临的问题只能通过概括来解决。

尝试确定所需的常见输入验证类型

  • 数字/字符串值/正则表达式验证
  • 范围/长度
  • 转义特殊字符
  • 在黑名单中检查我们在特定上下文中不需要的常见关键字("脚本","选择","删除" ...)

并在处理数据之前系统地调用它们。

所有数据库访问都必须使用准备好的语句完成,并且不要连接查询字符串。

所有输出都必须转义,因为我们不想将所有转义的内容存储在数据库中。

一个好的带外/社交方法是:尽最大可能确定用户。被识别的机会越高,他们越会欺骗系统。获取他们的手机号码以发送代码,检查他们的信用卡等。