一尘不染

有效地清理用户输入的文本

mysql

我有一个HTML表单,可以接受用户输入的大小约为1000的文本,并将其提交到php页面,并将其存储在mysql数据库中。我将PDO与准备好的语句一起使用以防止sql注入。但是,要清理用户输入的文本,需要做的最大努力是什么?

我想防止任何脚本注入,xss攻击等。


阅读 229

收藏
2020-05-17

共1个答案

一尘不染

安全是一个有趣的概念,吸引了很多人。不幸的是,这是一个复杂的主题,甚至专业人士也弄错了。我在Google(CSRF),Facebook(更多CSRF),几家主要的在线零售商(主要是SQL注入/
XSS)以及数千个公司和个人小型站点中发现了安全漏洞。

这些是我的建议:

1)使用参数化查询
参数化查询强制将传递给查询的值视为单独的数据,以便DBMS无法将输入值解析为SQL代码。很多人会建议您使用来转义字符串mysql_real_escape_string(),但是与流行的看法相反,这
不是 SQL注入的万能解决方案。以以下查询为例:

SELECT * FROM users WHERE userID = $_GET['userid']

如果$_GET['userid']设置为1 OR 1=1,则没有特殊字符,并且不会被过滤。这将导致返回所有行。甚至更糟的是,如果将其设置为1 OR is_admin = 1

参数化查询可防止发生这种注入。

2)验证您的输入
参数化查询很好,但是有时意外的值可能会导致代码出现问题。确保您正在验证它们是否在范围之内,并且它们不允许当前用户更改他们不应该做的事情。

例如,您可能具有密码更改表单,该表单将POST请求发送到更改其密码的脚本。如果您将其用户ID作为隐藏变量放置在表单中,则他们可以更改它。发送id=123而不是发送id=321可能意味着他们更改了他人的密码。确保在类型,范围和访问权限方面正确验证了所有内容。

3)使用htmlspecialchars逃避显示的用户输入
假设您的用户输入“关于我”的信息是这样的:这样做
</div><script>document.alert('hello!');</script><div>
的问题是您的输出将包含用户输入的标记。试图用黑名单自己过滤掉这是一个坏主意。使用htmlspecialchars过滤掉串,使HTML标签转换为HTML实体。

4)不要使用$ _REQUEST
通过让用户点击一个链接或访问表示一个脚本同名但对它们记录在一个网站的动作URL跨站请求伪造(CSRF)攻击的工作。该$_REQUEST变量是的组合$_GET$_POST并且$_COOKIE,这意味着你不能告诉是在一个POST请求(即通过发送一个变量之间的区别input在窗体标签),或者在你的URL设置为GET的一部分变量(例如page.php?id=1)。

假设用户要向某人发送私人消息。他们可能会发送POST请求sendmessage.php,用tosubjectmessage作为参数。现在,让我们假设有人发送了GET请求:

sendmessage.php?to=someone&subject=SPAM&message=VIAGRA!

如果您使用$_POST,那么您将不会看到任何这些参数,因为它们是在其中设置的$_GET。您的代码将看不到$_POST['to']或任何其他变量,因此它不会发送消息。但是,如果您使用$_REQUEST$_GET$_POST固定在一起,那么攻击者可以将这些参数设置为URL的一部分。当用户访问该URL时,他们无意间发送了该消息。真正令人担忧的部分是用户无需执行任何操作。如果攻击者创建了一个恶意页面,则该页面可能包含iframe指向URL的。例:

<iframe src="http://yoursite.com/sendmessage.php?to=someone&subject=SPAM&message=VIAGRA!">
</iframe>

这导致用户向人们发送消息而从未意识到他们做了任何事情。因此,您应该避免$_REQUEST使用$_POST$_GET代替。

5)将您得到的所有内容都视为可疑(甚至是恶意),
您根本不知道用户向您发送了什么。这可能是合法的。可能是攻击。永远不要相信用户发送给您的任何信息。转换为正确的类型,验证输入,必要时使用白名单进行过滤(避免使用黑名单)。这包括通过什么SENT
$_GET$_POST$_COOKIE$_FILES

如果遵循这些准则,则在安全性方面您将处于合理的位置。

2020-05-17