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

时间:2018-08-07 09:18:00

标签: javascript php magento-1.9 recaptcha

我实现了reCaptcha。单击“我不是机器人”复选框后,就会从Google生成令牌。

客户端(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);
            }
        });
    }

我使用ajax将令牌发送到服务器,并在此进行验证,如下所示:

服务器端(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";
        }
    }

这是对象$ result的输出

enter image description here

如果检查成功,则返回success,否则返回fail

但这足够了吗?如果攻击者使用burpsuite这样的HTTP代理将响应更改为success怎么办?然后他可以绕过我的支票并始终通过?还是我错了?

2 个答案:

答案 0 :(得分:1)

它使用密钥对来加密/解密信息。因此,它以加密方式发送信息。这就是为什么不能对其进行调整,但是,当然,这意味着您必须确保不要使私钥被盗。

服务器在那里知道状态并将状态保存在其存储中,因此,如果客户端在状态为“失败”时尝试将状态用作“成功”,则服务器将知道,无论如何。因此,对于黑客来说,改变客户端的价值的可能性不大,这当然取决于您的代码。如果使用该reCAPTCHA登录用户,则很明显,如果reCAPTCHA返回“失败”,则登录尝试将在服务器端失败。因此,无论客户端是否被告知“成功”,它仍然不会登录。客户端永远不应该是这种状态的守护者,因为它不能被信任(它总是会污染数据)。

它的工作方式类似于您使用HTTPS在浏览器和服务器之间进行的操作。

您的客户端和服务器之间的通信也应该使用HTTPS,以避免出现一些中间人(MITM)问题。但是,总是有可能有人成为代理,这是大多数MITM的工作方式,在这种情况下,MITM可以更改您所做的任何事情。

但是,MITM不能做的一件事就是为最终目的地创建有效的证书。从这个意义上说,这是一种保护,但是许多人每次连接到网站时都不会验证证书。但是,MITM的一种技术是不给您HTTPS,只有他和您的服务器将使用HTTPS,而客户端仍将使用HTTP。尽管您的代码可以检测到这种情况,但MITM显然也可以更改该代码。同样,将Cookie设置为Http-OnlySecure可以提高安全性,但MITM也可以拦截它。

由于MITM可以完全更改您的脚本,因此您在客户端方面几乎无能为力,无法检测到此类问题,而在服务器端,您将收到与客户端发送给您的内容相似的点击。再次重申,没有检测MITM的真正方法。

There is a post在问的一个问题:我可以从服务器端检测到MITM吗?这不是不可能,但是很棘手。新的实现/扩展是对常规HTTP解决方案的解决方案,但是这些解决方案需要连接到不同系统的其他应用程序,并且没有足够的理由,一旦有足够的人使用MITI也无法将其替代解决方案。

答案 1 :(得分:0)

结果来自Google拥有的URL。 如果用户篡改了发送到您的php脚本的内容-则Google网络服务将返回失败信息,并且您不会通过此类请求。