如何使用PHP和jQuery发送安全的AJAX请求 [英] How to send secure AJAX requests with PHP and jQuery

查看:160
本文介绍了如何使用PHP和jQuery发送安全的AJAX请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题



所以有一段时间我一直在尝试使用不同的AJAX方法将数据发送到服务器,该服务器将被处理并存储在MySQL数据库中。



AJAX请求命中的页面 api.php ,使用PHP的PDO预处理语句来保存数据,所以MySQL注入并不是真正的问题,需要加密的密码或数据也由 api.php 处理,这不是我在这里要求的。我的问题更多地涉及如何确保数据在从客户端传输到服务器时是安全的。



方法



我目前有(对于我在下面列出的登录示例):




  • 域上运行的SSL证书/ HTTPS。 / li>
  • 某些AJAX请求(显然不是此登录请求示例,因为没有会话开始)仅在PHP会话在整个站点上有效时使用(在 login.php 和 api.php 在此示例中。)

  • <$ c的速率限制访问函数时$ c> api.php 。

  • PHP PDO准备语句与 api.php

  • 加密 api.php 内的敏感数据(与问题无关)。



问题



最后,我的问题是:


  1. 这种方法是使用异步HTTP( Ajax)请求足够安全而不是仅仅将数据提交到PHP页面并向前重定向? (这样可以改善用户的体验)。

  2. 如何检查用户发送的数据是否未被篡改?

  3. 我是否合理地保护了我的用户数据,如果没有,我还能做什么?



示例



我知道每个人都有不同的方法来处理他们的网站数据和传输数据。我也明白,无论你做什么,你都永远不会受到100%的保护,因为你的系统可能存在一些你无法解释的漏洞和方法。我正在寻找有关安全发送数据的一般方法的反馈/改进,而不是批评下面的具体代码,因为它只是一个例子。但欢迎任何建设性的答案。感谢您花时间阅读/回答。

  function loginUser(){
var process =loginUser;
var data = $(form)。serializeArray();
data [1] .value = SHA512(data [1] .value); // sha然后在api.php页面加密
data = JSON.stringify(data);

$(#loginButton)。html('< i class =fa fa-spinner fa-pulse fa-lg fa-fw>< / i> Login');
$ .ajax({
类型:POST,
url:api.php,
data:{process:process,data:data} ,
成功:函数(数据){
if(data.response.state ==success){
//如果api.php返回成功,则重定向到主页
} else {
//如果api.php返回失败,显示错误
}
},
错误:函数(jqXHR,textStatus,errorThrown,data){
//错误处理
},
dataType:json
});
}


解决方案

1。检查ORIGIN标题



作为


The problem

So for a while now I've been experimenting with different AJAX approaches in sending data to a server that will be processed and stored inside a MySQL database.

The page that the AJAX request hits api.php, uses PHP's PDO prepared statements to save the data, so MySQL injections aren't really a problem and the passwords or data that needs to be encrypted are also handled by api.php which isn't what I'm asking here. My question relates more to how to ensure the data is secure when being transferred from the client to the server.

The approaches

I currently have (for the login example I have included below):

  • SSL Cert/HTTPS running on the domain.
  • Certain AJAX request (obviously not this login request example as there is no session to begin with) will only work if the PHP Session is valid across the site (used on both login.php and api.php in this example).
  • Rate limiting on api.php when accessing functions.
  • PHP PDO prepared statements when interacting with the database inside api.php.
  • Encrypts sensitive data inside api.php (not relevant to the question).

The questions

Finally, my questions are:

  1. Is this approach to using asynchronous HTTP (Ajax) requests safe enough to use rather than just submitting data to a PHP page and redirecting onwards? (As this way improves the user's experience).
  2. How can I check to know that the data my user's are sending hasn't been tampered with?
  3. Am I reasonably doing enough to protect my user's data, if not, what else can I do?

The example

I understand everyone has different approaches to handling their site's data and transporting that data. I also understand that no matter what you do, you can never be 100% protected, as there may be vulnerabilities and ways around your system that you can't account for. I'm looking for feedback/improvements on my general approach in sending data securely rather than criticism of the specific code below as it is only an example. But any constructive answers are welcome. Thanks for taking the time to read/answer.

function loginUser() {
    var process = "loginUser";
    var data = $("form").serializeArray();
    data[1].value = SHA512(data[1].value); // sha then encrypt on api.php page 
    data = JSON.stringify(data);

    $("#loginButton").html('<i class="fa fa-spinner fa-pulse fa-lg fa-fw"></i> Login');
    $.ajax({
        type: "POST",
        url: "api.php",
        data: {"process": process, "data": data},
        success: function(data) {
            if (data.response.state == "success") {
                // if api.php returns success, redirect to homepage
            } else {
                // if api.php returns failure, display error
            }  
        },
        error: function(jqXHR, textStatus, errorThrown, data) {
            // error handling
        },
        dataType: "json"
    });
}

解决方案

1. Check the ORIGIN header

As specified by OWASP, this is not enough but recommended :

Although it is trivial to spoof any header from your own browser, it is generally impossible to do so in a CSRF attack, except via an XSS vulnerability. That's why checking headers is a reasonable first step in your CSRF defense, but since they aren't always present, its generally not considered a sufficient defense on its own.

And by Mozilla :

The Origin header is considered helpful against JSON data theft and CSRF attacks. The information provided by Origin--a bit of contextual request-creation information--should provide hints to web servers about trustworthiness of requests [...]

Checking the HTTP_ORIGIN header could be written as :

header('Content-Type: application/json');

if (isset($_SERVER['HTTP_ORIGIN'])) {
    $address = 'http://' . $_SERVER['SERVER_NAME'];
    if (strpos($address, $_SERVER['HTTP_ORIGIN']) !== 0) {
        exit(json_encode([
            'error' => 'Invalid Origin header: ' . $_SERVER['HTTP_ORIGIN']
        ]));
    }
} else {
    exit(json_encode(['error' => 'No Origin header']));
}

1. (bis) Check the REFERER header

Again from OWASP :

If the Origin header is not present, verify the hostname in the Referer header matches the site's origin. Checking the referer is a commonly used method of preventing CSRF on embedded network devices because it does not require a per-user state.. This method of CSRF mitigation is also commonly used with unauthenticated requests [...]

Checking the HTTP_REFERER is also quite simple in PHP with $_SERVER['HTTP_REFERER'], you can just update the above code with it.


BE CAREFUL with the checking which always need to be really specific : do no check just example.com or api.example.com but the full https://example.com. Why ? Because you could spoof this check with an origin like api.example.com.hacker.com.


2. Generate CSRF tokens

A well-explained answer specific to PHP has been given there, in short :

  1. Generate the token :

    session_start();
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    

  2. Add it in your generated views via a meta (like Github) :

    <meta name="csrf-token" content="<?= $_SESSION['csrf_token'] ?>">
    

  3. Setup jQuery ajax calls to include this token :

    $.ajaxSetup({
        headers : {
            'CsrfToken': $('meta[name="csrf-token"]').attr('content')
        }
    });
    

  4. Server-side check your AJAX requests :

    session_start();
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    
    header('Content-Type: application/json');
    
    $headers = apache_request_headers();
    if (isset($headers['CsrfToken'])) {
        if ($headers['CsrfToken'] !== $_SESSION['csrf_token']) {
            exit(json_encode(['error' => 'Wrong CSRF token.']));
        }
    } else {
        exit(json_encode(['error' => 'No CSRF token.']));
    }
    

Most PHP frameworks have their own CSRF implementation, which more or less lay upon the same principle.


3. Sanitize validate user input.

You always must filter espace inputs and validate them.


4. Protect your server


5. Never trust user input

As @blue112 said, it is one of the most elementary security principles.

这篇关于如何使用PHP和jQuery发送安全的AJAX请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆