【问题标题】:Protect PHP endpoints called by AJAX保护由 AJAX 调用的 PHP 端点
【发布时间】:2016-02-21 20:49:41
【问题描述】:

我的应用程序包含几个可通过 AJAX 访问的 PHP 端点。问题是它们也可以通过向同一端点发出 HTTP 请求的任何人访问。我可以按照this answer 的规定添加对HTTP_X_REQUESTED_WITHHTTP_REFERER 的检查,但这些检查可能会被欺骗。我可以添加一个需要与请求一起发布的密钥,但是任何查看 javascript 和/或控制台的人都可以看到这个密钥。这里的解决方案是什么?

【问题讨论】:

  • 你在担心什么? CSRF?如果是这样,一个令牌就是答案。不过,它是否是 Ajax 并不重要。
  • 不,我只是不希望(例如)恶意人员/工具调用诸如“deleteJob”之类的端点,只能由端点所在服务器上的实际网站调用。
  • 如果端点是公共的,任何人都可以调用它,不管是不是 Ajax。您需要进行身份验证。
  • 是的,我想我的问题是:当每个人都能够看到客户端传递的用户名/密码(例如通过查看控制台)时,客户端身份验证如何工作?

标签: javascript php ajax security endpoint


【解决方案1】:

人们通常认为因为他们使用 Ajax 请求,所以常规的 sessions 不起作用。他们是这样。 如果您有一个端点可以从源代码中可见的数据库中删除某些内容,例如:

example.com/user/1/delete

您可以像在浏览器中使用非 Ajax HTTP 请求一样保护该请求免受未经身份验证的用户的访问。使用sessions。如果用户有权限删除用户,则该路由有效,否则返回错误(或不执行任何操作)。

您还可以使用 OAuth 保护 API。这里有一个很好的文档来解释它是如何工作的:http://tatiyants.com/using-oauth-to-protect-internal-rest-api/

【讨论】:

  • 会话不能跨域工作。例如,如果您的应用程序在 app.example.com 上运行,而您的 API 在 api.example.com 上运行,您将没有可用的会话。
【解决方案2】:

如果您的应用程序和 api 位于不同的域(例如 app.example.comapi.example.com)上,大多数答案都没有帮助 - 在这种情况下会话将无法正常工作,您将不得不转向 OAuth,这非常这么简单的问题的大锤。

我会这样做:

我假设您在数据库中有用户和一个唯一标识符,例如 user_id=12345。我还假设您的工作在数据库中,并且它们也具有唯一 ID,例如 job_id=6789

首先在 app.example.com 上,您使用 Blowfish 等快速简便的方法加密两个 ID:

$secret_uid = mcrypt_encrypt(MCRYPT_BLOWFISH, "your_secret", strval($user_id));
$secret_jid = mcrypt_encrypt(MCRYPT_BLOWFISH, "your_secret", strval($job_id));

我假设您的端点会像这样工作:

api.example.com/jobs/delete/<job_id>/<user_id>

所以现在从 Ajax 调用该端点,而不是使用普通 ID 调用

api.example.com/jobs/delete/6789/12345

您使用加密的 ID 调用它:

api.example.com/jobs/delete/6A73D5B557C622B3/57F064C07F83644F

在软件的 API 端解密参数:

$jid = mcrypt_decrypt(MCRYPT_BLOWFISH, "your_secret", <param_1>);
$uid = mcrypt_decrypt(MCRYPT_BLOWFISH, "your_secret", <param_2>);

现在您可以在您的数据库中搜索uidjid 并执行您计划执行的任何任务。确保用户当然只能删除他自己的作业。

我承认这不是 100% 的解决方案,但它给攻击者留下了很多猜测工作 - 他必须猜测 user_id 和匹配的 job_id、加密算法和你的秘密。它不能防止运行数百万次暴力尝试来猜测匹配对,但它使您更有可能(而且您应该对端点进行某种配额限制保护)。

祝你好运!

【讨论】:

    【解决方案3】:

    没有。如果你给某人一些数据,那么他们可以以任何他们喜欢的方式处理它。您无法控制它离开服务器后会发生什么。

    同样,您无法控制它们发送到端点的数据。

    【讨论】:

    • 没错。任何有头脑的攻击者都可以使用、修改和操纵您向浏览器提供/从浏览器提供的任何内容。
    • 假设我有一个名为“deleteJob”的端点,我希望前端/客户端可以访问它,那么 没有办法 保护它吗?
    • 有,通过身份验证,然后可能是授权规则。身份验证可以通过客户端需要发送的存储在客户端上的 cookie 或令牌来完成。
    • @GluePear — 用户名和密码或任何其他类型的 auth/authz,您可以限制给定用户可以删除的作业。
    • @Quentin - 但是任何查看客户端代码的人都可以看到这些,不是吗?
    【解决方案4】:

    对开发人员来说,为 API 或 Web 服务进行身份验证非常重要。 dhackeBugHunterUK 给出了完美的答案,我只想向您展示我用来制作的简单代码易于使用的身份验证。

    为身份验证添加会话

    您可以为您的 API 添加会话和会话超时,因此只有您的应用可以使用它,您可以在加载应用的首页时启动会话,您可以设置超时并通过以下方式限制不同用户的不同服务会议。

    一般想法如何做到这一点

    <?php
    if(!empty($_SESSION['api_session']) && $_SESSION['api_session'] == 'usertype'){
     //usertype comprise of what access you want to give 
     //guest, registered user, stack holder, admin etc. 
    ...
    header('Content-Type:application/json;');
    echo json_encode($output);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-30
      • 1970-01-01
      • 2015-05-12
      • 1970-01-01
      • 2016-09-13
      相关资源
      最近更新 更多