【问题标题】:PHP $_POST & Denying Fake Forms SecurityPHP $_POST & 拒绝虚假表单安全
【发布时间】:2011-07-21 22:42:55
【问题描述】:

我目前正在编写一个使用表单和 PHP $_POST 数据的 Web 应用程序(到目前为止是标准的!:))。但是,(这可能是一个菜鸟查询)我刚刚意识到,理论上,如果有人在他们的计算机上将一个 HTML 文件与一个伪造的表单放在一起,则将该操作作为我网站上使用的脚本之一并用他们自己的随机数据填充此表单,然后他们不能将这些数据提交到表单中并导致问题吗?

我会清理数据等,所以我不会(太)担心 XSS 或注入式攻击,我只是不希望有人能够,例如,将无意义的东西添加到购物车等。

现在,我意识到对于某些脚本我可以编写保护措施,例如只允许可以在数据库中找到的购物车中的东西,但可能存在无法预测的某些情况所有情况。

所以,我的问题是 - 是否有可靠的方法来确保我的 php 脚本只能由我网站上托管的表单调用?也许一些 Http Referrer 检查脚本本身,但我听说这可能不可靠,或者可能是一些 htaccess 巫术?这似乎是一个太大的安全漏洞(尤其是对于客户评论或任何客户输入之类的东西),而不能让它保持开放状态。任何想法将不胜感激。 :) 再次感谢!

【问题讨论】:

  • 您必须在表单中添加某种独特的令牌。

标签: php security forms post


【解决方案1】:
【解决方案2】:

有一个简单的规则:永远不要相信用户输入

所有用户输入,无论是什么情况,都必须由服务器验证。伪造的 POST 请求是执行 SQL 注入攻击或其他类似攻击的标准方法。您不能信任引荐来源标头,因为它也可以伪造。请求中的任何数据都可以被伪造。无法确保数据是从安全来源(例如您自己的表单)提交的,因为任何和所有可能的检查都需要用户提交的数据,而这些数据可能是伪造的。

保护自己的唯一方法是清理所有用户输入。只接受可接受的值。如果一个值(如 ID)引用数据库实体,请确保它存在。永远不要将未经验证的用户输入插入查询等。列表还在继续。

虽然需要经验并识别所有不同的情况,但您应该注意以下最常见的情况:

  1. 切勿将原始用户输入插入查询。要么使用诸如mysql_real_escape_string() 之类的函数对它们进行转义,要么更好的是,通过诸如 PDO 之类的 API 使用准备好的查询。在查询中使用原始用户输入可能会导致 SQL 注入。
  2. 永远不要将用户输入的数据直接输出到浏览器。始终通过 htmlentities() 之类的函数传递它。即使数据来自数据库,您也不应该相信它,因为所有数据的原始来源通常来自用户。不小心将数据输出给用户可能会导致 XSS 攻击。
  3. 如果任何用户提交的数据必须属于一组有限的值,请确保它属于。例如,确保用户提交的任何 ID 都存在于数据库中。如果用户必须从下拉列表中选择值,请确保所选值是可能的选择之一。
  4. 任何和所有输入验证,例如用户名中允许的字母,都必须在服务器端完成。客户端上的任何表单验证,例如 javascript 检查,只是为了方便用户。它们不为您提供任何数据安全性。

【讨论】:

    【解决方案3】:

    看@@nettuts tutorial的话题。

    只是用以前接受的答案 also in the topic 更新我的答案。

    【讨论】:

    • 虽然表单密钥是防止 XSS 帖子的有效方法,但它们对专门伪造的请求无能为力,我相信这是这里的主要问题。 (不要贬低 XSS 保护的重要性,尤其是在购物应用中)
    • @Rinuwise:对不起,这是我的错,因为我没有再读一遍整个教程(我记得它也触及了引用者的东西)
    【解决方案4】:

    您的问题的答案简短而明确:

    是否有可靠的方法来确保我的 php 脚本只能由我网站上托管的表单调用?

    当然不是。

    事实上,您网站上托管的表单不会调用任何脚本。 客户端浏览器中托管的表单调用所有脚本。
    知道这将有助于理解问题。

    不可能预测所有情况。

    相反,它会。
    所有好的网站都这样做。
    不过,这并没有什么难的。

    每个表单包含的参数数量有限。您只需要检查每个参数 - 仅此而已。

    【讨论】:

      【解决方案5】:

      正如您所说,确保产品存在于数据库中是一个好的开始。如果您使用邮政编码或邮政编码获取地址信息,请确保它对所提供的城市有效。将国家和城市设为下拉菜单,并检查该城市是否适用于所提供的国家/地区。

      如果您使用电子邮件地址,请确保它们是有效的电子邮件地址,并且可能会在授权交易之前发送带有链接的确认电子邮件。电话号码也一样(文本中的确认码),但验证电话号码可能很困难。

      永远不要存储信用卡或付款详细信息,如果可以避免的话(我倾向于认为很少有需要存储详细信息的情况)。

      基本上,规则是确保所有输入都符合您的预期。您不会捕捉到所有内容(姓名和地址必须接受几乎任何字符),但应该可以捕捉到大部分内容。

      我认为没有任何方法可以完全确保它们来自您的表单。 HTTP Referrer 和表单中的隐藏字段可能会有所帮助,但它们并不可靠。您所能做的就是尽可能严格地验证所有内容。

      【讨论】:

      • 逃跑不是主要的,也不是防御的
      • 就安全性而言,尽管不是 OP 所要求的,但它至关重要
      • 再次:转义(至少与 SQL 相关)在安全性方面没有任何意义。
      • 感谢 Belinda - 我想这将不得不结合严格验证、表单键和手动协调。无论如何,我们的卡处理都是在场外进行的,但我只需要再调查一下!再次感谢。
      【解决方案6】:

      只要您相信自己的数据清理方式……并且您说您对其进行了清理,我就不会发现问题。

      你知道http://php.net/manual/en/function.strip-tags.phphttp://www.php.net/manual/en/function.htmlentities.phphttp://www.php.net/manual/en/filter.examples.validation.php 对吧?

      【讨论】:

      • 谢谢大家!@FractalizeR - 非常感谢,我会检查一下。 @fabrik,谢谢,我今天早上会读到这个。 @Rinuwise - 谢谢,我确实确保我清理了所有数据,但这主要是我担心的伪造请求。 @Quamis 谢谢,目前我确实对数据进行了清理,这纯粹是关于虚假但不危险的用户输入。 @ Col. Shrapnel - 啊,当然是关于浏览器托管的表单(duh me),感谢您指出这一点。至于预测所有情况,我可以验证存储在数据库中的数据,但我不确定人们是否会为了纯粹的恶作剧而使用有效产品添加无意义的用户详细信息。
      • @user674512 你不会处理任何不属于你的数据库结构的东西,对吗?注意,一次回答所有人是个坏主意。
      • @Col。弹片 - 哎呀,对不起,我是堆栈溢出的新手,我以后会把它们分开。但是不,我不是那个意思,只是处理这些数据会更容易;我将针对 db 结构中未出现的数据进行其他处理
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-23
      相关资源
      最近更新 更多