chandevel / Clover

Clover - imageboard browser for Android (moved from Floens/Clover)
https://chandevel.github.io/Clover/
GNU General Public License v3.0
788 stars 260 forks source link

A fix for the captcha. #58

Closed nin9tyfour closed 9 years ago

nin9tyfour commented 9 years ago

Intro

As you're probably well aware, the new recatpcha cannot be implemented with native UI objects, with the exception of a web view (this is the case for iOS, at least). I experiemented a bit with the new style captcha yesterday after seeing how bad the no script ones have become. I'm going to detail how I did it as a courtesy, since I believe Clover is a great resource for developers of 4chan clients and the like.

With my implementation I am able to tick the captcha box and it may present me with a very simple captcha or an interactive style-captcha. The latter of which makes this particularly hard to port out of a web view, so at this point, web view seems to offer the best compatibility. Thankfully this solution doesn't even require using your server to host the captcha, it's all between the device and Google.

Overview

You're going to need a web view.

Here is the HTML I load into mine, bear in mind I have very little knowledge of HTML and CSS.

<head>
    <script type="text/javascript">
        var onloadCallback = function() {
            grecaptcha.render('html_element', {
                              'sitekey' : '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc',
                              'callback' : dataCallback,
                              'theme' : '%%NIFRecaptchaColourScheme%%'
                              });
        };
    </script>
    <script type="text/javascript">
        var dataCallback = function(authResult) {
            document.forms["myform"].submit();
        };
    </script>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"></script>

<body>
</head>
<form name="myform" action="" method="post">
<div style="
    display: table;
    ">
    <div style="width: 304px; height: 78px;">
        <div id="html_element"></div>
    </div>
</form>
</body>

%%NIFRecaptchaColourScheme%% is replaced with light or dark depending on the application's current theme.

I've actually tried to do this in the past but kind of gave up since the entire idea of it seemed kind of ridiculous. Regardless, the trick here is to set the referer to 4chan.org, or some variant of that fortune.4chan.org, clover.4chan.org, etc, it doesn't matter.

My web view has a delegate setup to the view controller, so every request that is performed, I query "grecaptcha.getResponse();" in the web view. This is actually a function supported by Google, so I imagine it is very future proof, unless they decide to rename it, like g-recaptcha-response... grecaptcha.getResponse(); will return an empty string if there is no response, it wasn't nil in my case but instead empty, so be aware of that. Once your delegate determines that the response was not in fact empty, basically any response, that (a) isn't nil and (b) is longer than 0 characters means the response was valid.

For the sake of simplicity this should work, JavaScript is obviously important, as an aside it can't even be disabled in web views on iOS:

webview.getSettings().setJavaScriptEnabled(true);
webview.loadDataWithBaseURL("http://clover.4chan.org", the\_html\_file, "text/html", "UTF-8", "");

Anyway, good luck, let me know if it works and if you want to give credit, it'd be very welcome!

floens commented 9 years ago

Hey nin9tyfour,

This is very informative, thank you.

As reCAPTCHA support has told me at https://groups.google.com/forum/#!topic/recaptcha/fws1H43_igo the widget should be hosted on the site itself, so I tried that first. But like you said, loading it with loadDataWithBaseUrl also seems to work just fine. I guess the captcha does not know the difference between it being loaded on the website, and loaded with this fake origin. I wonder if this has any security problems.

I hope this method if future proof. I think this is better than requiring 4chan to create a html page for now.

nin9tyfour commented 9 years ago

Fortunately loading a string into the web view and setting the base URL also sets the Referer header. The Referer is what is solely responsible for determining the site origin. Unless there is some JavaScript function that Google could use to double check the Referer, then there may be an issue, but I'm hoping not as this solution seems quite good. Otherwise there's always the chance of getting 4chan to host a captcha, but for the moment this solution is sufficient and doesn't impose any stress on their end.

Regards

On 1 Apr 2015, at 04:42, Floens notifications@github.com wrote:

Hey nin9tyfour,

This is very informative, thank you.

As reCAPTCHA support has told me at https://groups.google.com/forum/#!topic/recaptcha/fws1H43_igo the widget should be hosted on the site itself, so I tried that first. But like you said, loading it with loadDataWithBaseUrl also seems to work just fine. I guess the captcha does not know the difference between it being loaded on the website, and loaded with this fake origin. I wonder if this has any security problems.

I hope this method if future proof. I think this is better than requiring 4chan to create a html page for now.

— Reply to this email directly or view it on GitHub.

yate commented 9 years ago

Awesome find, thank you!