【问题标题】:What are the ways to secure an AJAX request?保护 AJAX 请求的方法有哪些?
【发布时间】:2014-02-19 15:38:03
【问题描述】:

我有一个客户端进行 AJAX 调用以对 URL 进行分类。它会调用 myserver.php?url=facebook.com 并且服务器会响应 Social。不涉及密码,只有一个 URL 字符串,服务器将为其返回一个类别。

我们已经为 url 类别建立了一个大型数据库,我不希望人们调用这个 API 并窃取数据。有什么方法可以确保我在服务器上收到的请求是我的客户端?在服务器端设置每个 IP 的请求限制会起作用吗?

是否值得使用 SSL(因为不涉及超安全的东西,而且我每分钟收到 1000 个请求)?我是数据安全新手,请在这方面指导我。

【问题讨论】:

  • 基本身份验证(用户名/密码)、SSL、IP 地址限制(如果客户端有静态 IP)
  • 如果你擅长在 php 中保护你的输入,你可以在到达 php 页面后清理你的请求:)
  • 或者干脆在ajax请求中添加一个CSRF token,在服务器上设置,在服务器上查看

标签: php ajax security


【解决方案1】:

最终,您无法保护任何公共资源免遭屏幕报废...Read More,但如果您只想添加一个基本保护层,防止某人编写直接访问您网站 API 的脚本,那么您可以在 AJAX 请求上设置 单次使用 CSRF 令牌,另外一个明智的做法是不使用 GET 而使用 POST。

这是一个简单的示例,在客户端加载页面时,您将一些令牌设置到会话中,并将令牌添加到 AJAX:

<?php 
session_start(); 
$_SESSION['csrf_ajax_key'] = sha1(uniqid());
$_SESSION['csrf_ajax_val'] = sha1(uniqid());
?>
<!DOCTYPE html>
<html>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>

<body>

<span id="result">Ajax response goes here...</span>

<script>
var request = $.ajax({
    type: "POST",
    url: "yourAPI.php",
    data: {"url":"facebook.com", "<?php echo $_SESSION['csrf_ajax_key'];?>":"<?php echo $_SESSION['csrf_ajax_val'];?>"}
});
request.done(function(response) {
    $("#result").html(response);
});
request.fail(function(jqXHR, textStatus, errorThrown) {
    console.log(textStatus, errorThrown);
});
</script>

</body>
</html>

然后在您的 API 上进行一些简单的检查以检查密钥是否已设置,它是一个 xmlhttprequest(AJAX) 并且是一个 POST 请求。然后取消设置会话密钥以停止多个请求或者您可以为后续请求返回新密钥(如果您轮询)。

<?php 
session_start();

if(
    //Check required variables are set
    isset($_SESSION['csrf_ajax_key']) &&
    isset($_SESSION['csrf_ajax_val']) &&
    isset($_POST[$_SESSION['csrf_ajax_key']]) &&
    isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&

    //Check is AJAX
    strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest' &&

    //Check is POST
    $_SERVER['REQUEST_METHOD'] === 'POST' &&

    //Check POST'ed keys match the session keys
    $_SESSION['csrf_ajax_val'] == $_POST[$_SESSION['csrf_ajax_key']]
){
    //good - example
    if(isset($_POST['url']) && $_POST['url']=='facebook.com'){
        echo 'This is the response for facebook.com';
    }

}

//Unset to stop multiple attempts
unset($_SESSION['csrf_ajax_val'], $_SESSION['csrf_ajax_key']);
?>

虽然不是 100%,但大部分都会停止。

【讨论】:

  • 这取决于发出 AJAX 请求的页面是否公开(也许@Bryan 可以澄清一下)。如果是这样,攻击者可以简单地先请求 HTML 页面,抓取令牌,然后发出 AJAX 请求。
  • 是的,你说得对,我本来打算添加的,但我在底部添加了语句。没有 100% 的方法可以保护公共资源。最终,如果浏览器可以访问它,唯一的选择是通过默默无闻的安全性。尽管可以说任何使用 CSRF 类型令牌的形式,都可以先刮掉它,但这是否意味着它不值得添加额外的层...
【解决方案2】:

你可以看看这个领域的一些大玩家。要访问来自 Google 等的服务,您需要一个 API 密钥,作为一种简单的身份验证形式。这可以作为参数或 HTTP 标头传输。

SSL 有助于防止对 API 密钥的窃听。

请记住,不建议使用 GET 获取此类信息,否则 API 密钥将在代理日志等中可读。

【讨论】:

    【解决方案3】:

    您应该验证传入的 URL。您可以执行以下操作:

    • 验证提供的 URL 是有效的 URL
    • 禁止某些 URL,如 IP 地址(仅当这些 URL 未分类时)
    • 如果可以,要求客户使用帐户进行身份验证,如果发出一些无效请求,您可以自动禁止该帐户。 在这种情况下,您需要 SSL。
    • 限制每个客户端每秒的请求数,以防止拒绝服务和不合理的资源消耗

    【讨论】:

    • 检查 SQL 语句是个坏主意,因为总会遗漏一些东西 - 推荐的方法是使用参数化查询。
    • @SilverlightFox 感谢您的更正。我会删除那部分。
    猜你喜欢
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 2014-09-06
    • 2013-03-20
    • 1970-01-01
    • 2010-10-25
    • 2017-03-13
    相关资源
    最近更新 更多