提问人:Moritz 提问时间:9/13/2019 最后编辑:Moritz 更新时间:9/13/2019 访问量:965
何时(以及为什么何时)以及如何在 php 中清理来自 POST JSON 的数据(以便输出可在 Swift 和 HTML 中使用)
When (and why the when) and how should I sanitize data from POST JSON in php (such that output usable in Swift AND HTML)
问:
在过去的几天里,我阅读了很多关于使用 PHP 清理输入和输出数据以防止(最突出的)XSS 和 SQL 注入的资源,即一堆关于 SO 的问题。然而,在这一点上,我觉得我对我应该做什么和不应该做什么更加困惑和不安全,部分原因是一些相反的信息,例如,我已经读过很多次,如果我使用准备好的语句,我不需要使用或任何其他形式的输入清理, 其他消息来源说我无论如何都应该使用它,甚至我应该像这样对它进行消毒;苹果的这个页面相当粗略地(?)介绍了这个话题;等。因此,我真的很想澄清我应该做什么 - 最好但不一定,由在该领域(服务器端安全)有一定经验的人,例如在这个领域工作,做过很多研究,甚至可能站在攻击者一边(?mysqli_real_escape_string
为了更好地理解我的情况,我将尽可能简明扼要地回顾一下:
我目前正在使用 Swift (iOS) 编写一个应用程序,需要将一些数据发送到我的服务器,在那里它使用 SQL 保存在表格中,并且可以由其他用户检索(例如用于博客)。
为此,我通过编码为JSON的POST将数据发送到我的服务器(“myphp.php”;使用Alamofire,不过这应该不是很重要),并在那里对其进行解码。这是我不确定我是否应该以某种方式清理我的数据的第一个地方(参考我上面链接的问题)。无论如何,然后我继续使用准备好的语句将其插入表中(MySQL,因此没有模拟任何内容)。此外,我还希望我输出的数据可以在 html 中使用,或者更确切地说,整个 PHP 也可用于 AJAX。
这是我的意思的一个例子:
// SWIFT
// set parameters for request
let parameters: Parameters = [
“key”: “value”,
...
]
// request with json encoded parameters
Alamofire.request(“myphp.php”, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.validate().responseJSON(completionHandler: { (response) in
// do things with data (e.g. show blog post)
// PHP
header('Content-Type: application/json');
$decodedPost = json_decode(file_get_contents('php://input'), true);
// what to do with input...?
// PREPARED STATEMENTS: insert, select, etc.
// what to do with output...?
// echo response - json-encoded so that
// json completion handler in swift can work with it
echo json_encode($output, JSON_NUMERIC_CHECK);
我曾向一位朋友请教过一些建议,他告诉我他总是做以下事情(这也是他发给我的一个函数)——无论数据是输入还是输出:xss_clean()
$key = xss_clean(mysqli_real_escape_string($db, trim(htmlspecialchars($data))));
// e.g. $data = decodedPost["key"]
然而,不仅我的研究告诉我这可能没有必要,而且他还告诉我这有其局限性,最明显的是,当数据应该再次从服务器检索并再次显示给例如另一个用户时 - 尽可能接近原始输入。
正如你所看到的,我真的很困惑。我想尽可能地保护发送到服务器的用户数据,所以这对我来说是一个非常重要的话题。我希望这个问题不要太宽泛,但许多其他问题,就像我说的,至少部分是矛盾的,或者非常古老的,例如仍然使用简单的扩展而没有准备好的陈述。
如果您需要更多信息,请随时询问。非常感谢对官方文件(以支持答案)的引用。谢谢!mysql
答:
输入清理是一个误导性术语,表示您可以对所有数据挥舞魔杖并使其成为“安全数据”。问题在于,当数据被不同的软件解释时,“安全”的定义会发生变化,编码要求也会发生变化。同样,“有效”数据的概念因上下文而异 - 您的数据可能需要特殊字符(',“,&,<) - 请注意,SO 允许所有这些作为数据。
嵌入到 SQL 查询中的输出可能是安全的,嵌入到 HTML 中可能并不安全。或者斯威夫特。或者 JSON。或者 shell 命令。或 CSV。剥离(或完全拒绝)值,以便它们可以安全地嵌入到所有这些上下文(以及许多其他上下文)中,这太严格了。
那么我们该怎么办呢?确保数据永远不会造成伤害。实现这一点的最好方法是首先避免对数据进行解释。参数化 SQL 查询就是一个很好的例子;这些参数永远不会被解释为 SQL,它们只是作为数据放入数据库中。
相同的数据可用于其他格式,例如 HTML。在这种情况下,数据应该在嵌入时针对该特定语言进行编码/转义。因此,为了防止 XSS,数据在放入输出时应该是 HTML 转义的(或者 javascript 或 URL 转义的)。不在输入时。这同样适用于其他嵌入情况。
那么,我们是否应该将我们得到的任何内容直接传递给数据库?
否 - 您肯定可以检查有关用户输入的内容,但这与上下文高度相关。我们称之为 - 验证。确保在服务器上完成此操作。一些例子:
- 如果字段应该是整数,您当然可以验证此字段以确保它包含整数(或者可能是 NULL)。
- 您通常可以检查特定值是否为一组已知值之一(白名单验证)
- 您可以要求大多数字段具有最小和最大长度。
- 您通常应该验证任何字符串是否仅包含其编码的有效字符(例如,没有无效的 UTF-8 序列)
正如你所看到的,这些检查非常依赖于上下文。所有这些都是为了帮助增加您最终获得有意义的数据的几率。它们不应该是保护应用程序免受恶意输入(SQL 注入、XSS、命令注入等)攻击的唯一防御措施,因为这不是执行此操作的地方。
评论