0

我希望这不是太难,所以这里有一个故事,我创建了一个简单的过程,它在请求时作为 JSON 对象发送,但出于安全原因,真的想保护(403)文件的内容,如果通过在浏览器中放置一个完整的 URL 来访问它。

这是我的 ajax.php 中的一个脚本

<?php
$image = array(
"/trial/images/1.png",
"/trial/images/2.png",
"/trial/images/3.png",
"/trial/images/4.png"
);
  $msg = array(
    'status' => 1,
    'message' => 'Remember to +1',
    'html' => '<p>Thank you for downloading our software <img src="'. $image[array_rand($image)] .'" width="80" height="80" alt="Thank You"></p>'
  );
  echo json_encode($msg);
?>

这是我使用 ajax POST 到该文件以获取 JSON 对象的函数的脚本。

function custom_reminder(aElem){
    theLink=$(aElem).attr("href");
    $.ajax({
        type:"POST",
        url:"/includes/ajax.php",
        data:"action=reminder&thepath="+theLink,
        dataType:"json",
        error:function(){window.location=theLink;},
        success:function(msg){
            if(msg.status == 1) {
                display_reminder(msg.html,theLink);
            }else{
                custom_message(msg.message,"error");
                }
        }
    });
}

请帮忙

4

3 回答 3

4

这个故事应该防止带有 AJAX 请求的 CSRF(跨站点请求原谅攻击)。

  1. 您可以放置​​一些标头数据并检查客户端是否请求它。
  2. 使用会话检查来自客户端的数据,并将其与服务器上的会话进行比较以访问 ajax 请求。
  3. 添加代码strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')以确保 xmlhttprequested 来自 ajax
  4. 如果您从服务器发送敏感数据并将其存储在有时间限制的客户端上,则生成一些令牌

令牌使用示例:

function checkToken( $userId, $eventIdentificator, $token){

       if( $token == sha1( $some_value_grabbed_from_time )){
       return true;
       }
    }
    return false;
}

5. 添加时间限制用户以使用某些生成的密钥请求数据,以便将来不能在 GET 中使用此哈希密钥并防止对其进行攻击。

生成令牌示例:

protected static function _generateToken()
{
    $token = sha1(mt_rand(0, 1000000));
    $_SESSION[$token] = time();
    return $token;
}

并将其验证为:

     if ($_SESSION[$token] >= time() - 7200) {
        $valid = true;
     }

6. 您可以将 COOKIE 添加到 ajax 中,如 IT 安全性所示:https ://security.stackexchange.com/questions/20015/protecting-against-csrf-when-a-form-is-being-submitted-via-an- ajax 调用

7. 查看 Github 上的示例,如简单类所示:https ://github.com/foxbunny/CSRF4PHP

或者 ...

public function generateToken() {
    // Create or overwrite the csrf entry in the seesion
    $_SESSION['csrf'] = array();
    $_SESSION['csrf']['time'] = time();
    $_SESSION['csrf']['salt'] = $this->randomString(32);
    $_SESSION['csrf']['sessid'] = session_id();
    $_SESSION['csrf']['ip'] = $_SERVER['REMOTE_ADDR'];
    // Generate the SHA1 hash
    $hash = $this->calculateHash();
    // Generate and return the token
    return base64_encode($hash);
}

protected function checkTimeout($timeout=NULL) {
    if (!$timeout) {
        $timeout = $this->timeout;
    }
    return ($_SERVER['REQUEST_TIME'] - $_SESSION['csrf']['time']) < $timeout;
}

public function checkToken($timeout=NULL) {
    // Default timeout is 300 seconds (5 minutes)

    // First check if csrf information is present in the session
    if (isset($_SESSION['csrf'])) {

        // Check the timeliness of the request
        if (!$this->checkTimeout($timeout)) {
            return FALSE;
        }

        // Check if there is a session id
        if (session_id()) {
            // Check if response contains a usable csrf token
            $isCsrfGet = isset($_GET['csrf']);
            $isCsrfPost = isset($_POST['csrf']);
            if (($this->acceptGet and $isCsrfGet) or $isCsrfPost) {
                // Decode the received token hash
                $tokenHash = base64_decode($_REQUEST['csrf']);
                // Generate a new hash from the data we have
                $generatedHash = $this->calculateHash();
                // Compare and return the result
                if ($tokenHash and $generatedHash) {
                    return $tokenHash == $generatedHash;
                }
            }
        }
    }

    // In all other cases return FALSE
    return FALSE;
}

}

此源代码显示为防止对侧 Ajax 请求进行 CSRF 攻击的最佳实践。它将检查从表单发送的生成数据的获取/发布,并与作为静态变量 ( _generateToken())放在 PHP 对象上的哈希值进行比较

8. OWASP来自 Web 应用程序项目的展示展示了如何通过 X/CSRF 进行攻击的可用示例以及如何防止它们的可用示例。

链接:https ://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet

大多数情况下,通常是原则上:“双重提交 cookie”,当脚本在每个请求上发送随机生成的 ID 并将其与先前发送的和新发送的 vars 进行比较时。

9. 编写您自己的 SCRIPT 以测试随机字符串攻击,使用 SHA512 进行更难的攻击,或仅使用下载进行测试:https ://www.owasp.org/index.php/Category:OWASP_CSRFTester_Project

10. 添加一些带有圆形示例 time() 的 HTTP HEADER 虚拟数据并比较示例是今天 ODD 或 EVEN 日或 ODD/EVEN 小时/分钟....

11. 如果在某个时间段(例如 3 分钟)内经常从一个 IP 地址受到攻击,则向管理员发出警报……或阻止临时远程主机……

12. 如果您仍然不知道 X/CSRF 的工作原理,请查看 YT 上的一些视频示例:http ://www.youtube.com/watch?v=pDXTDR6xew8

13. 如果您想知道如何使用crypt()和一些 OLD SCHOOL CSRF 预防使用示例: http: //phpmaster.com/preventing-cross-site-request-forgeries/

或简单的代码:

session_start();

switch($_GET["action"]) {
    case "login":
    if ($_SERVER["REQUEST_METHOD"] == "POST") {
        $user = (isset($_POST["user"]) &&
            ctype_alnum($_POST["user"]) ? $_POST["user"] : null;
        $pass = (isset($_POST["pass"])) ? $_POST["pass"] : null;
        $salt = '$2a$07$my.s3cr3t.SalTY.str1nG$';

        if (isset($user, $pass) && (crypt($user . $pass, $salt) ==
            crypt("admintest", $salt))) {
            $_SESSION["user"] = $_POST["user"];
        }
    }
    break;

    case "logout":
    $_SESSION = array();
    session_destroy();
    break;
}

header("Location: login.php");

14. 对于 CODEIGNITER/KOHANA 用户可以通过 HOOKS 简单地使用(在所有类之前作为类加载),并带有注入代码示例:http: //net.tutsplus.com/tutorials/php/protect-a-codeigniter-application-against -csrf/

  1. 防止通过 JAVASCRIPT 注入代码:

    $output = preg_replace('/(<(form|FORM)[^>]*(method|METHOD)="(post|POST)"[^>]*>)/',  
                     '$0<input type="hidden" name="' . self::$token_name . '" value="' . self::$token . '">', $output);  
    
  2. 当您使用 JSON 数据发送或接收数据时进行 put SSL 数据传输,以防止嗅探或查看数据。

  3. 根据内容将哈希等数字签名放入标头中。例如,散列您的内容并放入头文件“Digital-Sign:md5-data”。内容应该被散列并作为数字签名的新变量放入标题中。客户端检查数据并使用哈希进行比较以进行检查是真的。您可以将盐与发送数据的时间戳结合使用。md5($timestasmp.$content)

于 2013-03-08T12:32:36.623 回答
1

你可以查一下推荐人。如果它来自同一主机,则提供 JSON 文件。否则显示 403。

其他选项可能是基于不同值的散列的秘密。将它们与 AJAX 请求一起发送并在您的 PHP 文件中检查它们。

于 2013-03-08T12:19:27.483 回答
0

使用会话:

$_SESSION['key'] = 'randomcode';

将此密钥的加密版本发送到您的 AJAX 调用。

让 AJAX 脚本将接收到的密钥与会话匹配。如果匹配,您就知道该请求来自访问过您下载页面的人。

于 2013-03-08T12:27:25.550 回答