On Dev
Programming: tools and languages
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.
- Get the given URL via HTTP (for example http://scr.im/test), saving the contents and cookies that are returned.
- Find the value of the CAPTCHA in the given image. Here, we just guess one of the nine possibilities that are returned.
- 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.
- token: a value copied verbatim from the response.
- action: always “view”
- captcha: the value of the CAPTCHA in the given image
- ajax: always “y”
- 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(/"[^"]*"/) do |x|
captcha_value.push(CGI.unescape(x[1..-2]));
end
# 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.
From a web developer’s perspective, I’d like to see a few changes to the HyperText Transfer Protocol. When thinking about some areas of the protocol, I’d love to just start with a new protocol from scratch. But since it’s been around for so long I don’t think we’re going to get rid of it that easily (just like Java).
What could be improved in HTTP?
The first rule in Yahoo’s “Best Practices for Speeding Up Your Web Site” is to minimize the number of HTTP requests your web site requires. This means combining all your CSS into one file, all your JS into one file, etc. We can take this further:
Most front end developers probably know about CSS sprites. CSS sprites are a way to reduce the number of image files downloaded from a server by packaging multiple images in one image file. Using CSS to place the images, you can specify which part of the combined image you want to show in certain parts of the page. This has advantages and disadvantages.
By combining media types into one file, performance is improved server side and in terms of bandwidth because only one response needs to be sent (for that group of images). However, complexity increases: the developer has to do extra work to support this by combining JS and CSS and by creating sprites and writing the CSS to place them correctly on the page (there are tools to help with this).
Is it possible to build this type of functionality into the protocol? Can the user make one request and get all the data it needs from the server for that request in one response?
When a client makes a request to an HTTP server for HTML (whether it is dynamic or static), the server could know what else the client needs in terms of CSS, JS and media by processing the response its going to send. For example, it could parse the HTML and look for image tags, stylesheets and JS files. Or the related files could be specified in a configuration file. The server could then start sending related media files immediately after the requested file is sent.
There are a few approaches one could take:
- A design like Mutltipart messages could be used. Many files are sent at once under one content-type. (an ugly solution in my opinion)
- Many files can be sent sequentially as if they were requested in a persistent connection.
- An archive of all the necessary files could be sent as one file.
Approach (2) seems the most efficient because the browser can start parsing the HTML first and then apply the related files as they come in from the wire.
But what if the client only needs a single file within that archive because they have the rest of it cached? In both of these approaches, it would be complex to specify which files are needed by the client when only some of the files are needed. What if the user clicks on a link on the first page that goes to a very similar page on the same server? How does the client request only the files it needs? There is no easy solution to this problem.
For this post, I’ve focused on one way the protocol could be improved in terms of performance. Is it smart to focus on performance when improving the HTTP protocol? What other areas in the protocol need to be improved? Functionality, security, caching? If you were designing a new protocol, how would you improve the web? How do you imagine the web working in 20 years? Leave a comment…
Let’s take a few things from this blog post on “Code Monkeyism” and discuss:
“Searching for java is dead with Google, one gets
Results 1 – 10 of about 8,620,000 for java is dead.
Dead indeed. Or at least lots of people think it is or will die 2009.”
OK, so, let’s see what other things we can search for on google and get more results than that:
- “ruby is dead” – 9,500,000
- “c is dead” – 207,000,000
- “obama is dead” – 113,000,000
- “free range chickens” – 37,500,000
If that was supposed to convince me of something you are sadly mistaken.
He then tries to define “dead”:
“What does it mean to be dead for a programming language? Perhaps that it is no longer the default choice for projects?”
He goes on to describe how many startups don’t use Java for new applications, and doesn’t say anything about new projects from other types of organizations.
The only large – and lets say profitable and growing – startup that uses Java is LinkedIn.
Apparently this guy knows the technology behind every startup in the world. How am I supposed to trust anything you say when there are statements like this throughout your post?
Later, he states that “Java is not dead”. But then, one paragraph later:
“But just because Java is not dead doesn’t mean it has a future.”
What’s the difference? On what time scale? 5 years? 25 years?
“Java is a none-hype.”
What does that mean? It makes it hard for me to take this post seriously when there are meaningless things written throughout it.
Java is not going anywhere anytime soon. It is used in thousands of applications globally. The development tools available to Java developers are unmatched in quality by any other language. To claim it is dead is just trying to provoke an argument.
I use Java every day at work. I’m not saying it’s the best language out there (far from it), just that its not going anywhere.
Anyways – do me a favor, blogosphere: make sense when you try to discuss these things.