什么时候最好对用户input进行清理?
用户等于不可信。 永远不要相信不值得信任的用户的input。 我明白了。 但是,我想知道什么时候最好的时间来消毒input。 例如,是否盲目地存储用户input,然后在访问/使用时对其进行清理,或者是否立即清理input,然后存储此“已清除”的版本? 也许除了这些之外,还有其他一些我没有的方法。 我更倾向于第一种方法,因为任何来自用户input的数据都必须谨慎对待,在那里“清理”的数据可能仍然在不知不觉中或意外地是危险的。 无论哪种方式,人们认为最好的方法是什么,为什么?
我希望尽可能早地进行消毒,这意味着当用户尝试input无效数据时会发生消毒。 如果他们的年龄有一个文本框,并且input了其他任何数字,我不会让这封信的按键通过。
然后,无论是读取数据(通常是服务器),当我读取数据时,我都会做一个合理的检查,只是为了确保没有任何东西因为用户更加确定而滑入(如手动编辑文件,甚至修改数据包!)
编辑:总体而言,提前消毒和消毒任何时候你已经失去了数据的一秒钟(例如文件保存 – >文件打开)
我像Radu一样清理我的用户数据…
-
第一个客户端使用正则expression式和控制允许的字符input到使用javascript或jQuery绑定到给定的表单字段绑定到事件,如onChange或OnBlur,它可以删除任何不允许的input,甚至可以提交之前。 然而,实现这个function的确只是让这些用户知道,也就是说数据也要在服务器端进行检查。 这比任何实际的保护更多的警告。
-
其次,现在我很less再看到这样做,服务器端的第一个检查就是检查表单提交的位置。 通过只允许从您指定为有效位置的页面提交表单,您甚至可以在读取任何数据之前终止脚本。 诚然,这本身是不够的,作为一个好的黑客,他们自己的服务器可以“欺骗”域名和IP地址,使您的脚本显示它来自有效的表单位置。
-
接下来,我甚至不必说这个,但总是,而且我的意思是, 总是在恶意模式下运行你的脚本。 这迫使你不要懒惰,并要努力步骤4。
-
尽可能快地清理用户数据,使用格式正确的正则expression式,这些正则expression式适合于表单上任何给定字段所期望的数据。 不要像臭名昭着的' 独angular兽的魔angular '这样的快捷方式来冲破你的污点检查…或者你可能只是关掉污染检查,为了你的安全,所有的好处。 这就像给精神病患者一把锋利的刀,bearing住你的喉咙,并说:“你真的不会伤害我,你会这样做”。
这里是我在第四步中与其他大多数人不同的地方,因为我只是对可能带来安全风险的用户数据进行清理,比如任何系统调用,对其他variables的赋值,或者任何写入来存储数据。 如果我只使用用户input的数据来比较我自己存储在系统中的数据(因此知道我自己的数据是安全的),那么我不打算消毒用户数据,因为我我永远不会把它看作一个安全问题。 例如,以用户名input为例。 我使用用户input的用户名只检查它匹配我的数据库中的匹配,如果是true,之后我使用数据库中的数据来执行我可能要求在脚本中的所有其他函数,知道它是安全的,之后再也不使用用户数据。
-
最后,就是过滤掉所有这些机器人自动提交的所有尝试,并使用“validation码”系统(如Captcha)。 这些日子已经足够重要,所以我花时间编写了我自己的“人类authentication”模式,使用照片和“人”的input来input他们在图片中看到的内容。 我这样做是因为我发现Captchatypes的系统真的让用户恼火(你可以通过他们眯起的眼睛告诉他们试图破译扭曲的信件…通常是一遍又一遍)。 这对于使用SendMail或SMTP进行电子邮件的脚本尤其重要,因为这些是您的饥饿垃圾邮件机器人的collections夹。
简而言之,我会像我对我的妻子那样解释它,你的服务器就像是一个受欢迎的夜总会,而且你拥有的保镖越多,你在夜总会里可能会遇到的麻烦就越less。 我有两个门外的保安人员(客户端validation和人工authentication),一个保安人员在门内(检查有效的表格提交位置……“这真的是你在这个ID”),另外几个保镖靠近门(运行污染模式并使用正确的正则expression式来检查用户数据)。
我知道这是一个较旧的post,但是我觉得这对于任何在我访问之后可以阅读它的人来说是足够重要的,因为在安全性方面他们不是“ 魔法子弹 ”,并且所有这些都需要相互合作使您的用户提供的数据安全。 仅仅使用这些方法中的一种或两种实际上是毫无价值的,因为它们的力量只有在它们全部团结在一起时才存在。
或者总之,正如我妈妈经常会说的那样:“安全得比对不起”。
更新:
我最近做的还有一件事是Base64对我的所有数据进行编码,然后对驻留在我的SQL数据库上的Base64数据进行encryption。 总共需要大约三分之一的字节来存储,但是在我看来,安全性的好处超过了额外的数据量。
不幸的是,几乎没有一个参与者清楚地理解他们在说什么。 从字面上看。 只有@Kibbee设法使它变直。
这个话题都是关于消毒。 但事实是,大家都这么热衷于谈论的广义“通用消毒”这样的事情是不存在的。
有几十种不同的介质 ,每种都需要自己的,不同的数据格式。 而且,即使是单个特定的介质,也需要不同的格式 。 比如,HTML格式对HTML页面中embedded的JavaScript没有用处。 或者,string格式化对SQL查询中的数字没有用处。
事实上,正如最有争议的答案所暗示的那样,这样的“尽早消毒”是不可能的 。 正如人们无法分辨哪些媒体或媒体部分将使用哪些数据。 比方说,我们正准备从“sql注入”防御,逃避所有移动的东西。 但哎呀! – 一些必填字段没有填写,我们必须填写数据,而不是数据库…所有的斜杠添加。
另一方面,我们努力逃避所有的“用户input”…但在SQL查询中,我们没有引号,因为它是一个数字或标识符。 没有“消毒”对我们有帮助。
第三方面 – 好吧,我们尽最大努力消除了可怕的,不可信的和不被信任的“用户input”……但是在一些内在的过程中,我们没有任何格式地使用这些数据(因为我们已经尽力了!)哎呦! 已经获得了二级注入的荣耀。
所以,从现实生活使用的angular度来看,唯一正确的方法是
- 格式化,而不是“消毒”
- 在使用之前
- 根据一定的媒体规则
- 甚至遵循这个媒体不同部分所需的分则。
这取决于你在做什么样的消毒。
为了防止SQL注入,不要对数据本身做任何事情。 只要使用准备好的语句,那么就不用担心用户input的数据出现混乱,并且会对逻辑产生负面影响。 你必须清理一点,确保数字是数字,date是date,因为一切都是一个string,因为它来自请求,但不要尝试做任何检查,如块关键字或任何东西。
为了防止XSS攻击,在数据存储之前修复数据可能会更容易一些。 但是,正如其他人所提到的,有时用户input一个完整的副本是很好的,因为一旦你改变了它,它就会永远丢失。 这几乎是太糟糕了,没有一种可靠的方法来确保您的应用程序仅仅使用已准备好的查询来确保您不会被SQL注入所捕获,而只是将已消毒的HTML进行清理。
早期是好的,绝对在你尝试parsing它之前。 以后要输出的任何东西,或者特别传递给其他组件(例如,shell,SQL等)都必须进行消毒。
但是不要过分 – 例如,在存储密码之前密码被散列(对吗?)。 哈希函数可以接受任意的二进制数据。 而且你永远不会打印出密码(对吧?)。 所以不要parsing密码 – 也不要对它们进行消毒。
另外,确保你正在从一个可信的进程中进行消毒 – JavaScript /任何客户端比无用的安全/完整性更糟糕。 (尽pipe这可能会提供一个更好的用户体验,但只要这样做就可以了。)
最重要的是在逃跑的时候始终保持一致。 意外的双重消毒是跛脚的,而不是消毒是危险的。
对于SQL,只要确保您的数据库访问库支持自动转义值的绑定variables。 任何手动连接用户input到SQLstring的人应该知道更好。
对于HTML,我宁愿在最后时刻逃脱。 如果您销毁用户input,则永远无法将其还原,如果他们犯了错误,他们可以稍后编辑和修复。 如果你摧毁他们原来的投入,那就永远消失了。
Perl有一个污点选项,它将所有用户input视为“污染”,直到用正则expression式检查为止。 受污染的数据可以被使用和传递,但它会污染接触到的任何数据,直到被污染。 例如,如果用户input被附加到另一个string,则新string也被污染。 基本上,任何包含受污染值的expression式都会输出一个污染的结果。
受污染的数据可以随意丢弃(数据不变),但只要一个影响外部世界的命令使用,perl脚本就会失败。 所以,如果我使用受污染的数据来创build一个文件,构build一个shell命令,更改工作目录等,Perl将失败,并出现安全错误。
我不知道另一种语言有“污点”,但使用它已经非常睁大眼睛。 如果不立即将其污染的话,被感染的数据如何迅速传播,这是惊人的。 对程序员来说,自然而正常的事情,比如根据用户数据设置variables或者打开一个文件,看起来危险而且危险。 因此,完成任务的最佳策略就是一旦从外部获得一些数据就会将其解除。
我怀疑这也是其他语言的最佳方式:马上validation用户数据,以便错误和安全漏洞无法传播太多。 而且,如果潜在漏洞在一个地方,那么审计安全漏洞的代码应该更容易。 而且你永远无法预测哪些数据将被用于以后的目的。
我的意见是消毒用户input尽快客户端和服务器端,我这样做
- (客户端),允许用户只在该字段中input特定的键。
- (客户端),当用户使用onblur转到下一个字段时,testing他input的正则expression式的input,并注意用户是否有不好的情况。
- (服务器端),再次testinginput,如果字段应该是INTEGER检查(在PHP中可以使用is_numeric()),如果字段有一个众所周知的格式检查它对一个正则expression式,所有其他(如文本注释),只是逃避他们。 如果有任何可疑的情况,停止执行脚本,并向用户返回通知,说明他所input的数据无效。
如果真的看起来像一个可行的攻击,脚本发送邮件和短信给我,所以我可以检查和maibe尽快阻止它,我只需要检查我login所有用户input日志,脚本在接受input或拒绝之前所做的步骤。
在存储之前清理数据。 一般来说,你不应该在没有首先清理input的情况下执行任何 SQL操作。 你不想让自己受到SQL注入攻击。
我有点遵循这些基本规则。
- 只能修改SQL操作,比如INSERT,UPDATE,DELETE通过POST。 永远不要GET。
- 逃避一切。
- 如果您希望用户的input是确定的东西,请确认是否是某种东西。 例如,您正在请求一个号码,然后确定它是一个号码。 使用validation。
- 使用filter。 清除不需要的字符。
用户是邪恶的!
也许并不总是,但我的做法是总是立即sanatize,以确保在我的后端附近没有任何风险。
附加的好处是,如果您在input点进行消毒,则可以向用户提供反馈。
假设所有用户都是恶意的。 尽快清理所有input。 句号
在进行任何处理之前,我会对数据进行清理。 我可能需要把第一个和最后一个名称字段连接成第三个字段,插入数据库。 我甚至会在连接之前对input进行清理,所以我没有得到任何types的处理或插入错误。 越快越好。 即使在前端使用Javascript(在网页设置中)也是理想的,因为这将会在没有任何数据传送到服务器的情况下发生。
可怕的是你甚至可能想开始清理数据库中的数据。 最近激增的ASPRox SQL注入攻击是双重致命的,因为它会感染给定数据库中的所有数据库表。 如果您的数据库托pipe在同一个数据库中托pipe多个帐户的地方,那么您的数据就会因为别人的错误而被破坏,但是现在,由于没有您自己的初始错误,您已经join了为访问者托pipe恶意软件的行列。
当然,这可以做很多工作,但是如果数据很关键,那么这是值得的投资。
我发现立即清理它有两个好处。 一,你可以validation它,并提供反馈给用户。 二,您不必担心在其他地方使用数据。
在将应用程序放入应用程序的较低层之前,应始终将用户input视为恶意。 请务必尽快处理消毒input,在检查恶意意图之前不应以任何理由将其存储在数据库中。