简体   繁体   English

如何在服务器端验证Google reCaptcha?

[英]How to validate google reCaptcha on server side?

I implemented reCaptcha. 我实现了reCaptcha。 After the "I am not a robot" checkbox is clicked, a token is getting generated from google. 单击“我不是机器人”复选框后,就会从Google生成令牌。

Client side (js) 客户端(js)

    function checkCaptchaAndSubscribe(thisContext)
    {
        var captchaResponse = grecaptcha.getResponse();

        if (captchaResponse == "") {
            $captchaRequired.css('display', 'block');
            return false;
        }

        grecaptcha.reset();
        $captchaRequired.css('display', 'none');

        jQuery.ajax({
            url: "/black_newsletter2go/index/verify",
            method: "POST",
            async: "true",
            data: {
                recaptchaResponse: captchaResponse
            },
            success: function(response) {

                $statusContainer.show();

                if (response != "success") {
                    $status.html("<h2 class='nl2go_h2'>Die Captcha Validierung ist fehlgeschlagen!</h2>");
                    return false;
                }

                subscribe(thisContext);
            }
        });
    }

I send the token to my server by using ajax and validate it there like this: 我使用ajax将令牌发送到服务器,并在此进行验证:

Server side (php): 服务器端(php):

    public function verifyAction()
    {
        $captchaResponse = $this->getRequest()->getParam('recaptchaResponse');

        if (!isset($captchaResponse) || empty($captchaResponse)) {
            return "captcha response is empty";
        }

        $secretKey = Mage::Helper("recaptcha")->getSecretKey();

        $url = 'https://www.google.com/recaptcha/api/siteverify';
        $data = array(
            'secret' => $secretKey,
            'response' => $captchaResponse,
        );

        // use key 'http' even if you send the request to https://...
        $options = array(
            'http' => array(
                'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
                'method'  => 'POST',
                'content' => http_build_query($data)
            )
        );

        $context  = stream_context_create($options);

        $result = file_get_contents($url, false, $context);
        $result = json_decode($result);

        //var_dump($result);
        //exit();

        if ($result->success
                && (strpos(Mage::getBaseUrl(), $result->hostname) !== false)) {
            echo "success";
        } else {
            echo "fail";
        }
    }

This is the output of the object $result 这是对象$ result的输出

在此处输入图片说明

It returns success if the checks were successfull, otherwise fail . 它返回success如果检查是全成,否则fail

But is this enough? 但是够了吗? What if the attacker uses a HTTP proxy like burpsuite to change the response to success ? 如果攻击者使用burpsuite这样的HTTP代理更改success响应,该怎么办? Then he can bypass my checks and always get through? 然后他可以绕过我的支票并始终通过? Or am I wrong? 还是我错了?

It uses a key pair to encrypt/decrypt the info. 它使用密钥对来加密/解密信息。 So it's sending the info encrypted. 因此,它以加密方式发送信息。 That's why it can't be tempered with, but of course, that means you must make sure to not get the private key stolen. 这就是为什么不能对其进行调整,但是,当然,这意味着您必须确保不要使私钥被盗。

There the server knows and saves the state in its storage so if the client tries to use it as "success" when it was "fail", the server will know, no matter what. 服务器知道那里的状态并将其保存在其存储中,因此,如果客户端在状态“失败”时尝试将其用作“成功”,则服务器将知道,无论如何。 So for the hacker to change the value for the client is not likely to do much, it will depend on your code, of course. 因此,对于黑客来说,改变客户端的价值的可能性不大,这当然取决于您的代码。 If you are using that reCAPTCHA to log the user in, then obviously that login attempt will fail on the server side if the reCAPTCHA returned "fail". 如果使用该reCAPTCHA登录用户,则很明显,如果reCAPTCHA返回“失败”,则登录尝试将在服务器端失败。 So whether the client is told "success" or not, it still won't be logged in. The client should never be the keeper of such a state since it can't be trusted (it can always have tainted data.) 因此,无论客户端是否被告知“成功”,它仍然不会登录。客户端永远不应该成为这种状态的守护者,因为它不能被信任(它总是会污染数据)。

It works in a way similar to what you'd do between a browser and a server using HTTPS. 它的工作方式类似于您使用HTTPS在浏览器和服务器之间进行的操作。

The communication between your client and your server should also be on HTTPS to avoid some easier man in the middle (MITM) problems. 客户端和服务器之间的通信也应该使用HTTPS,以避免出现一些中间人(MITM)问题。 However, it is always possible to have someone who becomes a proxy, which is how most MITM work, and in that case, whatever you're doing can be changed by the MITM. 但是,总是有可能有人成为代理,这就是大多数MITM的工作方式,在这种情况下,MITM可以更改您所做的任何事情。

The one thing that the MITM can't do is create a valid certificate for the final destination, however. 但是,MITM不能做的一件事就是为最终目的地创建有效的证书。 In that sense, there is a protection, but many people don't verify certificates each time they connect to a website. 从这个意义上说,这是一种保护,但是许多人每次连接到网站时都不会验证证书。 One technique, though, has been for MITM to not give you HTTPS, only him and your server would use HTTPS and the client would remain on HTTP. 但是,MITM的一种技术是不给您HTTPS,只有他和您的服务器将使用HTTPS,而客户端仍将使用HTTP。 Although your code could detect such, obviously the MITM can also change that code. 尽管您的代码可以检测到这种情况,但MITM显然也可以更改该代码。 Similarly, having a cookie set with Http-Only and Secure can enhance the security, but that too can be intercepted by a MITM. 同样,设置具有Http-OnlySecure的cookie可以增强安全性,但是MITM也可以拦截该cookie。

Since the MITM can completely change your scripts, there is pretty much nothing you can do on the client's side that would help detect such a problem and on the server side, you will receive hits that look like what the client sent to you. 由于MITM可以完全更改您的脚本,因此在客户端方面您几乎无能为力,无助于检测到此类问题,而在服务器端,您将收到与客户端发送给您的内容相似的点击。 So again, no real way to detect a MITM. 再次重申,没有检测MITM的真正方法。

There is a post that was asking that very question: could I detect an MITM from the server side? 有一则帖子问了这个问题:我可以从服务器端检测到MITM吗? It's not impossible, but it's rather tricky. 这不是不可能,但是很棘手。 There are solutions being put in place by new implementations/extensions to the normal HTTP solution, but those require an additional application that connects to a different system and there is no reason why such could not also be proxied by a MITM once enough people use such solutions. 新的实现/扩展是对常规HTTP解决方案的解决方案,但是这些解决方案需要连接到不同系统的其他应用程序,并且没有足够的理由,一旦有足够的人使用MITI也无法将其替代解决方案。

The result comes from an URL that is owned by Google. 结果来自Google拥有的URL。 If user tampered with what is being send to your php script - then the google webservice will return a failure and you won't pass such request through. 如果用户篡改了发送到您的PHP脚本的内容-则Google Web服务将返回失败信息,您将不会通过此类请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM