我正在清理联系表单字符串:
$note = filter_var($_POST["note"], FILTER_SANITIZE_STRING);
这很好用,除非人们用英寸(")和英尺(')写。 所以I'm interested in 5" 8" 10" & 1'
出现为I'm interested in 5" 8" 10" & 1'
这有点乱七八糟。
我可以消毒但保持我的 5'9" 吗?
计算机数据本身既无害也无害。它只是一条信息,以后可以用于给定目的。
有时,数据被用作计算机源代码,这些代码最终会导致物理操作(磁盘旋转,LED闪烁,图片上传到远程计算机,恒温器关闭锅炉......那时(也只有那时)数据才会变得有害;由于软件错误,我们甚至时不时地失去昂贵的太空飞船。
你自己编写的代码可能与你的能力或善意所要求的一样有害或无害。当您的应用程序存在允许执行不受信任的第三方代码的漏洞时,就会出现大问题。这在连接到开放互联网的Web应用程序中尤其严重,并且期望从世界任何地方接收数据。但是,这在物理上怎么可能?有几种方法,但最典型的情况是由于动态生成的代码,这在现代 www 中一直发生。你使用PHP来生成SQL,HTML,JavaScript...如果您选择不受信任的任意数据(例如URL参数或表单字段)并使用它来编写稍后将执行的代码(由您的服务器或访问者的浏览器执行),则可能会有人被黑客入侵(您或您的用户)。
你每天都会在Stack Overflow上看到这一点:
$username = $_POST["username"];
$row = mysql_fetch_array(mysql_query("select * from users where username='$username'"));
<td><?php echo $row["title"]; ?></td>
var id = "<?php echo $_GET["id"]; ?>";
面对这个问题,有人声称:让我们消毒吧!很明显,有些角色是邪恶的,所以我们会将它们全部删除,我们就完成了,对吧?然后我们看到这样的东西:
$username = $_POST["username"];
$username = strip_tags($username);
$username = htmlentities($username);
$username = stripslashes($username);
$row = mysql_fetch_array(mysql_query("select * from users where username='$username'"));
这是一个令人惊讶的普遍误解,甚至被一些专业人士所采用。您到处都能看到症状:您的评论首先被肢解<
符号,您在注册时收到"您的密码不能包含空格",并且您阅读了为什么我不能使用某些词(如"drop")作为我的安全问题答案的一部分?在常见问题中。它甚至在计算机语言中:每当你读到"消毒"、"逃脱"时......在函数名称(没有进一步的上下文)中,您有一个很好的提示,表明这可能是一个误导性的努力。
这一切都是为了建立数据和代码的明确分离:用户提供数据,但只有你提供代码。而且没有一个通用的通用解决方案,因为每种计算机语言都有自己的语法和规则。 DROP TABLE users;
在SQL中可能非常危险:
mysql> DROP TABLE users;
Query OK, 56020 rows affected (0.52 sec)
(哎呀!...但它在例如JavaScript中并没有那么糟糕。看,它甚至没有运行:
C:'>node
> DROP TABLE users;
SyntaxError: Unexpected identifier
at Object.exports.createScript (vm.js:24:10)
at REPLServer.defaultEval (repl.js:235:25)
at bound (domain.js:287:14)
at REPLServer.runBound [as eval] (domain.js:300:12)
at REPLServer.<anonymous> (repl.js:427:12)
at emitOne (events.js:95:20)
at REPLServer.emit (events.js:182:7)
at REPLServer.Interface._onLine (readline.js:211:10)
at REPLServer.Interface._line (readline.js:550:8)
at REPLServer.Interface._ttyWrite (readline.js:827:14)
>
最后一个例子还说明了它不仅仅是一个安全问题。即使你没有被黑客入侵,从随机输入生成代码也会让你的应用崩溃:
SELECT * FROM customers WHERE last_name='O'Brian';
您的SQL语法有误;请查看与您的MySQL服务器版本相对应的手册,了解在"Brian"附近使用的正确语法
那么,如果没有一个普遍的解决方案,该怎么办呢?
了解问题:
如果不正确地注入原始文本数据,它可能会成为代码(有时是无效代码)。
使用每种技术的特定机制:
如果目标语言需要转义:
<p><3 to code</p>
→<p><3 to code</p>
。在源语言中查找要转义的特定工具:
echo '<p>' . htmlspecialchars($motto) . '</p>';
如果语言/框架/技术允许在单独的通道中发送数据,请执行此操作:
$sql = 'SELECT password_hash FROM user WHERE username=:username'; $params = array( 'username' => $username, );