我有一个html表单,接受用户输入的大小约为1000的文本,并提交到一个php页面,它将存储在mysql数据库中.我使用PDO与预准备语句来防止SQL注入.但要清理用户输入的文本,需要做的最好的努力是什么?
我想阻止任何脚本注入,xss攻击等.
安全是一个有趣的概念,吸引了很多人.不幸的是,这是一个复杂的主题,甚至专业人士也错了.我在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来转义显示的用户输入
让我们说你的用户输入他们的"关于我",如下所示:
htmlspecialchars
过滤掉串,使HTML标签转换为HTML实体.
4)不要使用$ _REQUEST
跨站请求伪造(CSRF)通过让用户点击一个链接或访问,表示同名但对它们记录在一个网站的动作脚本的URL攻击的工作.该$_REQUEST
变量是的组合$_GET
,$_POST
并且$_COOKIE
,这意味着你不能告诉是在一个POST请求(即通过发送一个变量之间的区别input
在窗体标签),或者在你的URL设置为GET的一部分变量(例如page.php?id=1
).
假设用户想要向某人发送私人消息.他们可能会发送POST请求sendmessage.php
,用to
,subject
并message
作为参数.现在让我们假设某人发送了一个GET请求:
sendmessage.php?to=someone&subject=SPAM&message=VIAGRA!
如果您正在使用$_POST
,则不会看到任何这些参数,因为它们是设置的$_GET
.您的代码将看不到$_POST['to']
或任何其他变量,因此它不会发送消息.但是,如果您正在使用$_REQUEST
,$_GET
并且$_POST
卡在一起,那么攻击者可以将这些参数设置为URL的一部分.当用户访问该URL时,他们无意中发送了该消息.真正令人担忧的部分是用户无需做任何事情.如果攻击者创建了恶意页面,则可能包含iframe
指向URL 的恶意页面.例:
这导致用户在没有意识到他们做任何事情的情况下向人们发送消息.出于这个原因,你应该避免$_REQUEST
和使用$_POST
而$_GET
不是.
5)将您提供的所有内容视为可疑(甚至是恶意)
您不知道用户向您发送了什么.这可能是合法的.这可能是一次袭击.永远不要相信用户发送给您的任何信息.转换为正确的类型,验证输入,使用白名单在必要时进行过滤(避免黑名单).这包括通过发送任何东西$_GET
,$_POST
,$_COOKIE
和$_FILES
.
如果您遵循这些指导原则,那么您在安全性方面具有合理的地位.