【问题标题】:Stop Malicious POST requests停止恶意 POST 请求
【发布时间】:2016-11-18 21:31:49
【问题描述】:

我有一个 AJAX 函数可以调用我网站上的页面。

$(document).on('click', thisIdentity, function() {
    var trigger = $(this);
    var items = trigger.attr('data-values').split('_');
    $.ajax({
        type: "POST",
        url: "/mod/mypage.php",
        data : { pid : item[0], uid : item[1] },
        dataType: "json",
        success: function(data) {
           if(data.job == 1) {
              // do something
           }
        }
    });
});

现在这可以正常工作并按预期进行。但是,如果我使用任何第三方应用程序,例如 POSTMAN 并向 www.xyz.com/mod/mypage.php 发出 POST 请求带有参数 pid : 1 和 uid : 2。它仍然通过并对我的数据库进行更改。

有没有办法检查请求是从我的 仅限域/服务器?

如何在我的域之外阻止此类 POST 请求?

我想到的一件事是在此请求之前生成一个令牌并在 SESSION 中设置,并在 mypage.php 中检查是否设置了令牌。这是一种可行的方法吗?

【问题讨论】:

  • 有一种称为Same-origin policy 的东西。这基本上意味着您的域不会接受任何不是来自您自己的服务器的 POST 数据,除非您特别允许它使用 Cross-origin resource sharing 或简称为 CORS。这就是为什么永远不要信任用户输入数据并在服务器端对其进行验证的一般规则。
  • @icecub 是的,但请求仍在处理中。如果我从具有显式 url 'example.com/mod/mypage.php 的另一台服务器发出 AJAX 请求,那么它会通过同源策略阻止,但如果我从任何 chrome 应用程序(如 POSTMAN)发出 POST 请求,那么它就会通过。这是为什么呢?
  • 那是因为那些应用不会重新发送 POST 数据。相反,他们首先在发送请求之前修改 POST 请求方法。所以 POST 数据仍然来自您的服务器。它只是被修改了。
  • @icecub 有没有办法停止或检查它?而且我注意到,如果我的脚本在处理过程中获取任何 SESSION 变量值,那么当从此类应用程序发出请求时不会获取该值。有什么想法吗?
  • 您必须对每个请求服务器端进行身份验证。永远不要盲目相信用户输入。

标签: javascript php ajax security post


【解决方案1】:

这正是 CSRF 令牌的用途。用户必须先导航到该页面,该页面会生成一个提交令牌,因此不导航到该页面将导致任何 POST 请求无效。

但是,试图阻止某人从 POSTman 之类的实用程序向您的端点发送请求是徒劳的。您必须验证对端点的每个请求,在这种情况下,只需检查照片 ID 是否归提交客户端所有。

OWASP 很好地描述了 CSRF 是什么:

Cross-Site Request Forgery (CSRF) 是一种攻击,它会强制最终用户在当前已通过身份验证的 Web 应用程序上执行不需要的操作。 CSRF 攻击专门针对状态更改请求,而不是窃取数据,因为攻击者无法查看对伪造请求的响应。

示例验证流程

Login.php

<?php

// Establish DB connection, validate

$_SESSION['id'] = $db->getUserId();
$_SESSION['admin'] = $db->getAdminStatus();

删除.php

<?php

if (!$db->isPhotoOwner($_POST['pid'])) {
    exit;
}

// Delete photo flow

Admin.php

<?php

if (!$_SESSION['admin']) {
    die("Not admin.");
}

// Do admin action or whatever

【讨论】:

    【解决方案2】:

    您可以让调用页面使用 $_SERVER['SCRIPT_NAME'] 来标识自己,并将该值写入隐藏的输入字段或 $_POST 并在处理开始时检查它。您选择的任何确认值都可能有效。

    如果他们已经在模仿您的 JSON 数据,那么可能会将其放入 javascript 中,使用 PHP 在页面服务上动态写入代码值。

    【讨论】:

    • 没关系。您可以拥有所有想要的隐藏输入。它们仍然可以在 POST 请求和页面源中看到,并且可以轻松复制/修改。只有用户无法触及的数据才是可信的。例如,就像一个 SESSION。
    • 如果信任是一个问题,那么 AJAX 完全不适合这种情况。已确认的安全状态更改将被同步,而不是 AJAX。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 2020-01-03
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    相关资源
    最近更新 更多