用户等于不可信。永远不要相信不可信的用户输入。我明白了。但是,我想知道清理输入的最佳时间是什么时候。例如,您是否盲目存储用户输入,然后在访问/使用时对其进行清理,或者您是否立即清理输入,然后存储此“清理”版本?也许除了这些之外还有一些我没有想到的方法。我更倾向于第一种方法,因为来自用户输入的任何数据仍然必须谨慎处理,其中“清理后的”数据可能仍然在不知不觉中或意外地存在危险。不管怎样,人们认为哪种方法最好,出于什么原因?

有帮助吗?

解决方案

我喜欢尽早对其进行清理,这意味着当用户尝试输入无效数据时就会进行清理。如果有一个适合他们年龄的文本框,并且他们输入数字以外的任何内容,我不会让该字母的按键通过。

然后,无论读取数据的是什么(通常是服务器),当我读入数据时,我都会进行健全性检查,只是为了确保不会由于更坚定的用户(例如手动编辑文件,甚至修改数据包)而导致任何内容丢失!)

编辑:总体而言,请尽早进行清理,并在您看不到数据的任何时候(例如,一秒钟)进行清理。文件保存 -> 文件打开)

其他提示

不幸的是,几乎没有一个参与者能够清楚地理解他们在说什么。字面上地。只有@Kibbee 设法让它变得直截了当。

这个主题是关于消毒的。但事实是,像每个人都热衷于谈论的广泛的“通用消毒”这样的事情是 只是不存在。

无数种不同的媒介, 各需要 它有自己独特的数据格式。 而且——甚至 单个特定媒体的各个部分需要不同的格式. 。比如说,HTML 格式对于 HTML 页面中嵌入的 javascript 来说是没有用的。或者,字符串格式化对于 SQL 查询中的数字是没有用的。

事实上,正如大多数赞成答案中所建议的那样,“尽早消毒”只是 不可能的. 。因为人们无法判断数据将在哪一种介质或介质部分中使用。比如说,我们准备防御“sql注入”,逃避一切移动的东西。但是哎呀!- 一些必填字段未填写,我们必须将数据填回到表单而不是数据库中......添加了所有斜杠。

另一方面,我们努力逃避所有“用户输入”......但在 sql 查询中我们没有引号,因为它是一个数字或标识符。没有任何“消毒”对我们有帮助。

第三方面 - 好吧,我们尽了最大努力清理那些可怕的、不值得信任的和蔑视的“用户输入”......但在一些内部过程中,我们使用了这些数据,没有任何格式(因为我们已经尽力了!) - 哎呀!已经获得了二阶注入的所有荣耀。

所以,从现实生活使用的角度来看,唯一正确的方法是

  • 格式化,而不是任何“清理”
  • 就在使用前
  • 按照一定的介质规则
  • 甚至遵循该媒体不同部分所需的子规则。

我像 Radu 一样清理我的用户数据......

  1. 首先使用REGEX的客户端,并使用与事件(例如Onchange或Onblur)相关的JavaScript或jQuery来控制允许的字符对给定的表单字段,例如onChange或onblur,这些事件甚至可以在提交之前删除任何不允许输入。但是,要意识到,这实际上只有让这些用户知道的效果,也将检查服务器端的数据。这比任何实际的保护更是一个警告。

  2. 其次,这些天我很少看到这样做了,服务器端进行的第一个检查是检查表格从何处提交的位置。仅允许您从已指定为有效位置的页面中提交表单,您可以在阅读任何数据之前杀死脚本。诚然,这本身是不够的,因为拥有自己的服务器的好黑客可以“欺骗”域和IP地址,以使其从脚本中显示出来,从而来自有效的表单位置。

  3. 接下来,我什至不必说这个,但总是,我的意思是 总是, ,以污点模式运行脚本。这迫使您不要懒惰,并且要努力第4步。

  4. 使用适合于表单上任何给定字段的数据的合适的回报率尽快消毒用户数据。不要像臭名昭著的捷径'独角兽的魔法角' 来破坏你的污染检查......或者,您不妨关闭污点检查首先要为您的安全性所做的所有好处即可。这就像给精神病患者一把锋利的刀,戴着你的喉咙,并说:“你真的不会伤害我。”

    这是我在第四步中与其他大多数其他人不同的地方,因为我只对我要实际使用的用户数据进行消毒,以可能出现安全风险,例如任何系统调用,对其他变量的作业,或存储数据的任何写作。如果我仅使用用户的数据输入来与我自己存储在系统上存储的数据进行比较(因此,知道自己的数据是安全的),那么我不会像我一样费心对用户数据进行消毒我永远不会向我们介绍自己作为安全问题的方式。例如,以用户名输入为例。我使用用户的用户名输入只是对数据库中的匹配进行检查,如果是的,则我使用数据库中的数据执行所有其他功能,我可能会在脚本中要求它,知道它是安全的在此之后再也不会使用用户数据。

  5. 最后,如今,用机器人(例如Captcha)滤除了机器人的所有尝试的自动提交。如今,这很重要,我花了一些时间编写自己的“人类身份验证”架构,该模式使用照片和“人类”输入来输入他们在图片中看到的内容。我之所以这样做,是因为我发现验证码类型系统真的很烦用户(您可以通过试图破坏扭曲的字母的眼睛看不见的眼睛。通常一遍又一遍地)。这对于使用SendMail或SMTP进行电子邮件的脚本尤其重要,因为这些是您饥饿的垃圾邮件机器人的最爱。

简而言之,我将像向我妻子解释一样......您的服务器就像一家受欢迎的夜总会,并且您拥有的弹跳量越多,您在夜总会中可能遇到的麻烦越小。我在门外有两名保镖(客户端验证和人工身份验证),门内有一名保镖(检查有效的表单提交位置......“真的是您在此ID上),还有更多靠近门的弹跳器(运行污点模式并使用良好的Regexes检查用户数据)。

我知道这是一篇较旧的帖子,但我觉得它对于任何在我访问这里后可能阅读它的人来说都足够重要,并意识到他们不是'魔法子弹” 当涉及到安全性时,需要所有这些相互配合才能确保用户提供的数据的安全。仅仅使用其中的一两种方法实际上是没有价值的,因为它们的威力只有当它们全部组合在一起时才存在。

或者总而言之,正如我妈妈经常说的那样......“安全总比后悔好”。

更新:

我这些天正在做的另一件事是对我的所有数据进行 Base64 编码,然后对将驻留在我的 SQL 数据库中的 Base64 数据进行加密。以这种方式存储它需要大约三分之一的总字节数,但在我看来,安全优势超过了数据的额外大小。

这取决于您正在进行哪种消毒。

为了防止 SQL 注入,请勿对数据本身执行任何操作。只需使用准备好的语句,这样,您就不必担心弄乱用户输入的数据,并对您的逻辑产生负面影响。您必须进行一些清理,以确保数字是数字,日期是日期,因为所有内容都是来自请求的字符串,但不要尝试进行任何检查来执行块关键字或任何其他操作。

为了防止 XSS 攻击,在存储数据之前修复数据可能会更容易。然而,正如其他人提到的,有时拥有用户输入内容的原始副本是很好的,因为一旦更改它,它就会永远丢失。遗憾的是,没有一种万无一失的方法来确保您的应用程序只输出经过净化的 HTML,而您可以通过使用准备好的查询来确保您不会被 SQL 注入捕获。

最重要的是在逃跑时始终保持一致。意外的双重消毒是蹩脚的,而不消毒是危险的。

对于 SQL,只需确保您的数据库访问库支持自动转义值的绑定变量。任何手动将用户输入连接到 SQL 字符串的人都应该更了解。

对于 HTML,我更喜欢在最后一刻转义。如果您破坏了用户输入,您将永远无法将其恢复,并且如果他们犯了错误,他们可以稍后进行编辑和修复。如果你破坏了他们的原始输入,它就会永远消失。

尽早是好的,绝对是在你尝试解析它之前。稍后要输出的任何内容,或者特别是传递给其他组件(即 shell、SQL 等)的内容都必须经过清理。

但不要太过分 - 例如,密码在存储之前会被散列(对吗?)。哈希函数可以接受任意二进制数据。而且您永远不会打印出密码(对吗?)。所以不要解析密码 - 也不要清理它们。

另外,请确保您正在从受信任的进程进行清理 - JavaScript/任何客户端内容都比无用的安全性/完整性更糟糕。(不过,尽早失败可能会提供更好的用户体验 - 只需在两个地方都这样做即可。)

Perl 有一个污点选项,它认为所有用户输入都“被污染”,直到使用正则表达式进行检查。受污染的数据可以被使用和传递,但它会污染它接触到的任何数据,直到未被污染为止。例如,如果用户输入附加到另一个字符串,则新字符串也会受到污染。基本上,任何包含受污染值的表达式都会输出受污染的结果。

受污染的数据可以随意丢弃(污染数据),但一旦它被对外界有影响的命令使用,perl 脚本就会失败。因此,如果我使用受污染的数据创建文件、构造 shell 命令、更改工作目录等,Perl 将失败并出现安全错误。

我不知道还有哪种语言有类似“污点”的东西,但使用它让人大开眼界。如果您不立即清除受污染的数据,其传播速度将令人惊讶。对于程序员来说,自然而正常的事情,例如根据用户数据设置变量或打开文件,在打开污染后看起来很危险且有风险。因此,完成任务的最佳策略是在从外部获取一些数据后立即清除污染。

我怀疑这也是其他语言的最佳方式:立即验证用户数据,以便错误和安全漏洞不会传播得太远。此外,如果潜在漏洞位于一处,那么审核代码是否存在安全漏洞应该会更容易。而且您永远无法预测哪些数据稍后将用于什么目的。

我的意见是尽快清理客户端和服务器端的用户输入,我这样做

  1. (客户端),允许用户仅在字段中输入特定键。
  2. (客户端),当用户使用OnBlur进入下一个字段时,请测试他针对RegexP输入的输入,并注意用户如果某些内容不好,则会注意用户。
  3. (服务器端),再次测试输入,如果要进行整数检查(在PHP中,您可以使用is_numeric()),如果字段具有众所周知的格式,请使用REGEXP检查一下,所有其他(如文本注释),只是逃脱他们。如果有任何可疑之处,请停止脚本执行并向用户返回一个通知,表明他输入的数据无效。

如果某些事情确实看起来像是可能的攻击,脚本会向我发送一封邮件和一条短信,这样我就可以检查并尽快阻止它,我只需要检查我记录所有用户输入的日志,然后脚本在接受或拒绝输入之前执行的步骤。

存储数据之前先清理数据。一般来说你不应该表演 任何 SQL 操作无需先清理输入。您不想让自己遭受 SQL 注入攻击。

我有点遵循这些基本规则。

  1. 仅执行修改 SQL 操作,例如通过 POST 进行 INSERT、UPDATE、DELETE。永远不要得到。
  2. 逃避一切。
  3. 如果您期望用户输入某种内容,请确保检查它是否是某种内容。例如,您正在请求一个号码,然后确保它是一个号码。使用验证。
  4. 使用过滤器。清理不需要的字符。

用户是邪恶的!

好吧,也许并不总是如此,但我的方法是始终立即进行清理,以确保我的后端附近没有任何有风险的地方。

额外的好处是,如果您在输入点进行清理,您可以向用户提供反馈。

假设所有用户都是恶意的。尽快清理所有输入。句号。

在对数据进行任何处理之前,我会先对其进行清理。我可能需要获取名字和姓氏字段并将它们连接到插入数据库的第三个字段。我将在进行串联之前对输入进行清理,这样我就不会出现任何类型的处理或插入错误。越早越好。即使在前端(在 Web 设置中)使用 Javascript 也是理想的选择,因为这将在没有任何数据进入服务器的情况下发生。

可怕的是,您甚至可能还想开始清理来自数据库的数据。最近激增的 ASPRox SQL 注入攻击具有双重致命性,因为它会感染给定数据库中的所有数据库表。如果您的数据库托管在同一个数据库中托管多个帐户的地方,那么您的数据会因为其他人的错误而被损坏,但现在您已经加入了向访问者托管恶意软件的行列,而这并不是您自己的最初错误。

当然,这需要预先做大量的工作,但如果数据很关键,那么这是一项值得的投资。

我发现立即清洁它有两个优点。第一,您可以对其进行验证并向用户提供反馈。第二,您不必担心在其他地方消耗数据。

在将用户输入放入应用程序的较低层之前,应始终将其视为恶意输入。始终尽快处理清理输入,并且在检查恶意意图之前不应以任何原因将其存储在数据库中。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top