Monday, February 11, 2008

Follow-up to hackable hacking contest...

It has been a few days since I posted about the hackable hacking contest.  I wanted to give you guys a few days to play around to see if you could find the bug.  In this post I am going to go through the bug and how it works.  I am also going to touch on ways that they could have coded it so this wouldn't have happened (there is a small satisfaction in finding these issues, but creating a proper fix is much more fun in my opinion). 

Scenario:  
This hacking contest checks to see how proficient you are at XSS.  It then looks for a specific value to see if you successfully found the bug.  

Initial Investigation: 
When first going to the site I did the first step just to see how the application normally worked.  No big deal.  However, when you look at the HTML you will see that there is a javascript file called "script.js".  What does script.js look like?


eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('e=7.4;6=0;f g(a){7.4=e;8(a==5.h){8(6==0)6=1;4(a);7.u(\'j()\',v)}k{4(a);4("w x 5.h!!")}}7.4=g;f j(){8(6==1){6=2;3="";o=z(5.9("A").B);C(l i=0;i< o.d;i++){l y="o.E(i);3+=F.G(y-1)}3=H(3);8(3=="I"){m="\\J\\K";5.9("c").n="< b" p="\'q\'">r!! &d; "+"L M. &d;T U."}k{5.9("c").n="r!! &d; "+"V W "+3+"."}5.9("c").X.Y=""}}',61,61,'|||ty|alert|document|ok|window|if|all||span|msg|nbsp|orgAlert|function|newAlert|domain||nextstg|else|var|sj|innerHTML||id|h3|Congratulations|href|x6e|setInterval|500|Please|use||unescape|key|value|for|length|charCodeAt|String|fromCharCode|escape|ending|061|071|The|End|x52|x61|x6b|x49|x67|php|show|ranking|Next|stage|style|display'.split('|'),0,{}))

Pretty ugly, eh?

By looking at the code we see that it is obfuscated by using a packer function. An easy way to get around this is to replace the eval call with alert. You can simply do that by putting javascript: in your browser pasting in this long string of javascript and replacing eval with alert. It would look something like the below screen shot.

You will then get an alert box.  While the alert box is up hit ctrl  + c (or splat + c if you are on a mac) so we can get the javascript on to the clipboard.  It is a bit ugly still so use a JavaScript beautifier and then we can start reading.  

orgAlert = window.alert;
ok = 0;
function newAlert(a) {
window.alert = orgAlert;
if (a == document.domain) {
if (ok == 0) ok = 1;
alert(a);
window.setInterval('nextstg()', 500)
} else {
alert(a);
alert("Please use document.domain!!")
}
}
window.alert = newAlert;
function nextstg() {
if (ok == 1) {
ok = 2;
ty = "";
o = unescape(document.all("key").value);
for (var i = 0; i < y =" o.charCodeAt(i);" ty =" escape(ty);" ty ="=" sj = "\061\071" innerhtml = "Congratulations!!   " the="">show ranking."
} else {
document.all("msg").innerHTML = "< span id='h3'>Congratulations!!   " + "Next stage " + ty + "."
}
document.all("msg").style.display = ""
}
}

Ahh much better!

Hmm, now this code looks interesting. Lets figure out what it is doing. The first line of code holds the original alert method call in a variable and then a few lines down we see they are overriding the original alert with their own function "window.alert = newAlert;." For those new to JavaScript might be a little confused. But the beauty and curse of JavaScript is that it is possible to overwrite any method or class with your own. 

The newAlert function is where things go south. This method is called whenever a page gets an alert and then checks to see if the text for the alert is "document.domain" if so it will call the nextstg method which will display a link to the next stage so a user can advance. 

The Attack:
What happens if we let the page load and then manually execute some JavaScript? Oh look we pass the stage. All we have to do is put the following string "javascript:alert(document.domain)" into the address bar after the page loaded. That is it we are done and we can now look like we are all l33t without actually knowing anything :).

Some other interesting tidbits about this contest:
1) Every page they name it differently so a person can't just guess the page name.
2) They use lame obfuscation to store the next page name in the "key" hidden form field.

General Testing Strategies Used:
1) We used the site briefly to see how it is supposed to operate under normal usage.
2) We looked at the client-side code and the public interface exposed to people via the browser.
3) Seeing that there was some JavaScript we should exercise. We used the javascript protocol handler in the browser to execute the JavaScript on the current page to see what would happen.

Possible Fix:
A proposed fix that I would do is since this is a controlled environment and the contest is looking for a specific test. We could hold in a database or in a file that was not directly accessible via the web of the patterns we are expecting for each stage. This would allow for the contest to continue but make it much harder to attack. The only hard part is if someone knew a different pattern that allowed for the same attack to happen. This might happen. But one would hope that if you are writing this contest you know the majority of the variants :).

Labels: ,

0 Comments:

Post a Comment

<< Home