Friday, September 13, 2013

Bitsquatting at DEFCON21 and More

I was very excited to see that several researchers are investigating bitsquatting and writing about it. There were two presentations about bitsquatting at DEFCON 21, a presentation at ICANN 47, and a research paper presented at WWW2013.

Jaeson Schultz - DEFCON 21 - Examining the Bitsquatting Attack Surface
Jaeson presented some excellent ways to exploit bitsquatting that I did not think of -- such as using bitsquats in URL delimeters to target otherwise unexploitable domains. As an example taken from the paper, ecampus.phoenix.edu can become ecampus.ph/enix.edu/.

Additionally Jaeson presents a great mitigation that can be implemented at the local level -- Response Policy Zones. From the paper:
An RPZ is a local zone file which allows the DNS resolver to respond to specific DNS requests by saying that the domain name does not exist (NXDOMAIN), or redirecting the user
to a walled garden, or other possibilities. To mitigate the effects of single bit errors for users of a DNS resolver the resolver administrator can create a Response Policy Zone that protects against bitsquats of frequently resolved, or internal-only domain names.  
 

Robert Stucke - DEFCON 21 - DNS Has Been Found To Be Hazardous To Your Health
Robert demonstrated some new vectors for bitsquatting, such as web applications and hosted email providers. Speifically, he bitsquatted gstatic.com (a site that serves static content for Google properties). Not only was he able to return arbitrary content to people using Google's search services, he could also affect web applications, such as feed readers, that rely on correct resolution of gstatic.com. Robert also bitsquatted psmtp.com, a hosted email provider. This allowed him to potentially receive other people's email.

Nigel Roberts - ICANN 47 - Bitsquatting
Nigel (who runs .gg) presented about bitsquatting to ICANN. Hopefully this will result in more research at the ccTLD level. 

Nick Nikiforakis, et al. - WWW2013 - Bitsquatting: Exploiting Bit-flips for Fun, or Profit?
Nick and his coauthors did a measurement study about the prevalence of bitsquatting and what content appears on bitsquatted domains. They identified several that are used for adverstising, affiliate programs, and malware distribution.  There is also a great graph in the paper where you can see a huge spike in bitsquat domain registration after my Blackhat presentation :).

Thursday, August 1, 2013

Introducing Binfuzz.js

Tomorrow morning I will be giving a demonstration of Binfuzz.js at Blackhat Arsenal 2013. Please stop by the Arsenal area from 10:00 - 12:30. The slides are already available on the Blackhat website.

The Binfuzz.js page on dinaburg.org is now live, and all the code is uploaded to Github.

What is Binfuzz.js?


Binfuzz.js is a library for fuzzing structured binary data in JavaScript. Structured binary data is data that can be easily represented by one or more C structures. Binfuzz.js uses the definition of a structure to create instances of the structure with invalid or edge-case values. Supported structure features include nested structures, counted arrays, file offset fields, and length fields. The live example uses Binfuzz.js to generate Windows ICO files (a surprisingly complex format) to stress your browser's icon parsing and display code.

Features


Binfuzz.js includes support for:

  • Several predefined elementary types: Int8, Int16, Int32 and Blob.
  • Nested structures
  • Arrays
  • Counter Fields (e.g. field A = number of elements in Array B)
  • Length Fields (e.g. field A = length of Blob B)
  • File Offsets (e.g. field A = how far from the start of the file is Blob B?
  • Custom population functions (e.g. field A = fieldB.length + fieldC.length)

The ICO fuzzing example includes uses of all of these because I needed them to implement ICO file generation.

Combinatorics


Binfuzz.js calculates the total number of combinations based on how many possible combinations there are for each individual field. It is then possible to generate a structured data instance corresponding to a specific combination number. It is not necessary to generate prior combinations. This way random combinations can be selected when fuzzing run time is limited.

Why?


The best way to learn is by doing, and I wanted to learn JavaScript. So I decided to create an ICO file fuzzer in JavaScript. I chose ICO files because of favicon.ico, a file browsers automatically request when navigating to a new page. After starting the project, I realized I got a lot more than I bargained for. Icons are a surprisingly complex format that has evolved over time. There are several images in one file, each image has corresponding metadata, there are internal fields that refer to offsets in the file, and the size of the icon data for each image depends the metadata. All of these interlinked reationships need to be described and processed by Binfuzz.js.

Monday, July 29, 2013

A Travel Story

I travel frequently, and not just to the usual tourist destinations. I've gone to places like Singapore, Japan, Ukraine, and India. This is a story of trying desperately to get home from a recent trip.

Be Aware of You Surroundings


The first sign of trouble was when the roof started leaking. The storm outside had only been raging for half an hour before the two droplets landed on my head. The buckets and signs on the floor captured most of the leaks, but there were numerous unmarked drips. You don't want this kind of water in your hair or food. Always be aware of your surroundings.

I arrived at my gate to find a delayed flight. At least there was now time to eat, since all the good food options were in the international terminal. Casually I trekked over, scarfed down some ethnic food and began meandering back to the gate.

An Ominous Sign


The blaring alarm noises and the flashing emergency lights of the fire alarm told me something was wrong. Neither the airport staff, nor security, nor the airline staff knew what was happening. Just that there wasn't a fire. Maybe. There was no smoke, no firemen, and everyone was calm. Carefully and slowly, I continued towards the gate. Then the power went out.

It was still daytime, and the sunlight and fire alarm (probably on backup power) provided enough lights to get by. The gate was in complete chaos. None of the computers worked, and the staff tried their best to assuage angry passengers. Some were just grumpy, others in tears, but all wanted some answers. There were no answers, no air conditioning, and it was getting hot.

The darkened terminal was like an impoverished refugee camp. Uniformed staff handing out bottles of water to angry men, crying women and screaming children. Mobs of people begged staff for answers. It was dark, hot, loud, and no one knew what was going on. This went on for two hours.

Then the plane arrived, but we couldn't board. The jetbridges were electric and wouldn't extend. Other parts of the airport had power, but the airline couldn't or wouldn't use the working jetbridges. The flight was cancelled, but we weren't rebooked to a new flight because there was no power. We had to call the central reservation office. This was never announced, of course. I happened to overhear another passenger talk with the gate agent.

So I called. After 30 minutes, a man with an accent answered. He sounded legitimately concerned, but all the flights for the day were sold out. I asked if he could rebook me on a competing airline; he typed something on a keyboard and then told me that all flights on all airlines to my destination were sold out. No inventory; The earliest possibility was the next night. Begrudgingly, I agreed. I asked about hotel vouchers. "Of course, the gate agents can print them for you", he replied. The power was still out.

Perseverance


I wasn't about to spend another night in this place. There was still one flight on a competing airline, and it was leaving soon. Sure I was told there were no seats, but one can't blindly trust a company to do something that lowers profit. And besides, maybe someone wouldn't show up. The competing airline was naturally in the furthest possible terminal from where I was. It was a long walk, but they probably power.

Turns out there were seats on the flight. There would be a cost, but I would get home, today. Life was also better in this part of the airport. There were no leaks in the roof and the air conditioning was on. Nobody was crying. I sat down near the new gate.

There was a current flight there, delayed indefinitely. Must be weather, I figured. That assumption was shattered when I heard two airline employees talking next to the gate entrance. Turns out the plane needed fuel. They sent for a fuel truck, but it arrived without fuel. For the past half hour they were trying to find either fuel, a new fuel truck, or whomever got them into the boondoggle. No one was answering. After 15 more minutes, they found a new truck. Two hours later my plane arrived.

Don't Count Your Chickens...


As we boarded, I realized there were plenty of seats. The flight was only half full. So much for "no seats available." As we taxied to the runway, I was thankful to finally be out of this wretched place.

My enthusiasm was premature. Literally as we were next in line to depart, our plane was directed to stop. After an hour on the tarmac, the full story unfolded. The original flight path had unexpected weather. We had an approved alternate flight path, but in the time it took us to taxi (about 30 min in the rain at this airport), the alternate flight path also had unexpected weather. It was 30 more minutes before we moved again.

Departure At Last


This time, it was for real. Our wheels touched off the ground and we ascended into the stormy sky. The plane shook violently as we passed through the rain, wind, and lightning. I clutched my seat and thought about this abhorrent place: the fire alarm, the crying passengers, the hot, dark, sweaty terminal, helpless staff, the leaky roof and fuel-less fuel trucks. I just wanted to go home and to never again fly into Philadelphia International Airport.

Sunday, July 21, 2013

Readability Improvements

In preparation for new content relating to my Blackhat 2013 Arsenal presentation, I made some readability improvements to the blog and to dinaburg.org in general.

The layout is wider and the font size for text is now 16 pixels.

Please let me know what you think.

Friday, July 12, 2013

Git Fails On Large Files

Turns out git fails spectacularly when working with large files. I was surprised, but the behavior is pretty well documented. In typical git fashion, there is an obscure error message and an equally obscure command to fix it.

The Problem


A real-life example (with repository names changed):

artem@MBP:~/git$ git clone git@gitlab:has_a_large_file.git
Cloning into 'has_a_large_file'...
Identity added: /Users/artem/.ssh/devkey (/Users/artem/.ssh/devkey)
remote: Counting objects: 6, done.
error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the remote side.
remote: Compressing objects: 100% (5/5), done.
remote: fatal: Out of memory, malloc failed (tried to allocate 1857915877 bytes)
remote: aborting due to possible repository corruption on the remote side.
fatal: early EOF
fatal: index-pack failed

I pushed the large file without issues, but couldn't pull it again because the remote was dying. The astute reader will notice the remote was running gitlab. The push also broke the gitlab web interface for the repository.

From my Googling, the problem is that the remote side is running out of memory when compressing a large file (read more about git packfiles here). Judging by the error, git attempts to malloc(size_of_large_file) and the malloc fails.

This situation raises conundrums that may only be answered by Master Git:
  • Why was I able to push a large file, but not pull it?
  • Why would one malloc(size_of_large_file) ?
  • What happens when you push a >4Gb file to a 32-bit remote?

I was curious enough about the last one to look at the code: it will likely die gracefully (see line 49 of wrapper.c). Integer overflow likely avoided; would need to read more code much more carefully to be sure.

The Solution


In theory, the solution is to re-pack the remote with a smaller pack size limit. That requires ssh access to the remote repository, which I don't have. So the following fix is untested, and taken from http://www.kevinblake.co.uk/development/git-repack/. The obscure command in question (must be run on the remote):

git repack -a -f -d

Of course, repacking the remote but having non-repacked local repositories around may cause other problems.

Just For Fun


Here is another large file fail:

artem@MBP:~/temp/largerandomfile$ dd if=/dev/urandom of=./random_big_file bs=4096 count=1048577
1048577+0 records in
1048577+0 records out
4294971392 bytes transferred in 437.836959 secs (9809522 bytes/sec)

artem@MBP:~/temp/largerandomfile$ git add random_big_file
artem@MBP:~/temp/largerandomfile$ git commit -m "Added a big random file"
[master 377db57] Added a big random file
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 random_big_file

artem@MBP:~/temp/largerandomfile$ git push origin master
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
error: RPC failed; result=22, HTTP code = 413 KiB/s
fatal: The remote end hung up unexpectedly
Writing objects: 100% (3/3), 4.00 GiB | 18.74 MiB/s, done.
Total 3 (delta 0), reused 1 (delta 0)
fatal: recursion detected in die handler
Everything up-to-date

Everything up-to-date, indeed.

Sunday, June 16, 2013

OptimizeVM: Fast Windows Guests for VMware

Do you make Windows VMs? Are they slow? OptimizeVM will make them fast(er).

I got tired of re-googling and re-typing the same commands over and over make my Windows VMs fast, so I collected them on Github: https://github.com/artemdinaburg/OptimizeVM.

OptimizeVM is based on the commands provided in the official VMware View Optimization Guide.

The goal of OptimizeVM is to minimize disk access and remove fancy graphical effects. Certain Windows features, such as Windows Search, System Restore, Windows Updates, and Registry Backup will cause constant background disk access. The disk access makes your VM slow and increases virtual disk size. These features are also unnecessary for VMs that get reverted to a clean snapshot every couple of days.

The script also removes some annoyances like the Action Center, Network Location Wizard, hidden file extensions, and so on.

The disabling of some features, such as Windows Firewall, Windows Defender, and Windows Update do lower the security of your system. If you are very worried, turn them back on. I leave them off since in my workflow VMs get reverted to a clean state every few days.

If you want to speed up your Windows VMs, here are a few more useful links:



Tuesday, April 30, 2013

JavaScript Frustrations and Solutions

Since there's no better way to learn than by doing, I've been teaching myself JavaScript by writing a structured binary data fuzzer. The fuzzer currently generates Windows ICO files, and will soon be released. In the meantime, I wanted to describe some frustrating experiences learning JavaScript and include solutions to them.

Object Orientation in JS is Confusing 


Some of this may be because I am used to class-ical inheritance, but considering the number of JavaScript OOP libraries (e.g. oolib, dejavu, Klass, selfish), I'm not alone.

The first confusing thing is that objects are functions declared via the function keyword and instantiated via the new operator. The overloaded use of function doesn't let you know right away if the code you are reading is an object a traditional function. The use of the new operator gives a false impression of class-ical inheritance and has other deficiencies. For instance, until the introduction of Object.create it was impossible to validate arguments to an object's constructor. The deficiency is shown in the following example.

In this motivating example, we want to create an object to encapsulate integers and validate certain properties in the object's constructor. The initial code could look something like this:

function Int(arg) {
    console.log("Int constructor");
    this.name = arg['name'];
    if(this.name === undefined)
    {
        alert('a name is required!');
    }
    this.size = arg['size'];
};
Int.prototype.getName = function() {
    console.log("Int: " + this.name);
};
var i = new Int({'name': 'generic int'});
i.getName();

Running this code would print:

Int constructor
Int: generic int

But now lets say I want to write something to deal specifically with 4-byte integers. The initial code to inherit from the Int object would look similar to the following:

function Int4(arg) {
    arg['size'] = 4;
    Int.call(this, arg);
    console.log("Int4 constructor");
};
Int4.prototype = new Int({});
Int4.prototype.constructor = Int4;
Int4.prototype.getName = function() {
    console.log("Int4: " + this.name);
};
var i4 = new Int4({'name': '4-byte int'});
i4.getName();

This code will alert with 'a name is required'! To set Int4's prototype chain we need to create a new Int object. Arguments to the constructor cannot be validated since they are not known when new Int({}) is called. Luckily this has been fixed by use of Object.create:

function Int4(arg) {
    arg['size'] = 4;
    Int.call(this, arg);
    console.log("Int4 constructor");
};
Int4.prototype = Object.create(Int.prototype);
Int4.prototype.constructor = Int4;
Int4.prototype.getName = function() {
    console.log("Int4: " + this.name);
};
var i4 = new Int4({'name': '4-byte int'});
i4.getName();

All Functions are Function Objects and all Objects are Associative Arrays.


All functions are actually Function objects, all objects are associative arrays. There are also Arrays, which are not functions and but are also associative and also objects. Sometimes you want Arrays to be arrays, and sometimes you actually want Objects to be arrays. Confused yet?

Scoping Rules and Variable Definition Rules that Lead to Subtle Bugs


Scoping rules are a bit confusing, since there is at least three ways to declare variables: assignment, var, and let. Of course, all of these have different semantics. The biggest problem for me was that creating a variable by assignment adds it to the global scope, but using var will keep it in function scope. And when using identically named variables, a missing var in one function will make that function use the global variable instead of the local. Using the wrong variable will lead to lots of frustrating errors.

The solution is to always "use strict" to force variable definitions. Of course, doing this globally will break some existing libraries you are using. Such is life.

Type Coercion With the Equality Operator (==)


Its amazing what is considered equal in JavaScript via ==. Instead of restating all these absurdities, I'll just link to someone else who has:
http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/

When I started my project, I didn't realize that the Strict Equality (===) existed. It should be used anywhere you would expect == to work. It seems more sane to have == be Strict Equality, and another Coercive Equality operator (something like ~= or ~~), but what is done is done.

Problems Modularizing and Importing Code


C/C++ has #include, Python has import, JavaScript has... terrible hacks. There is sadly no standard way to import new code in a .js file, making modularization of your code difficult. I resorted to simply including prerequisite scripts in the HTML where they will be used, but I wish there was a way to include JavaScript from JavaScript.

Browser Compatibility Issues


Not all browsers have Object.create. Not all browsers have console.log in all situations. Not all browsers support "use strict". Turns out every browser is slightly different in a way that will subtly break your code, but of course the main culprit is usually IE.