How I found the Safari exploit

Introduction

I hope you found my posts on the Safari security holes interesting, in this post I’m going to try and explain how I think and how I managed to work out an exploit for Safari. This post will be unusual for me because generally I try to keep my writing short and sweet, but in this case I thought it would be good learning material and provide a few vendors some insight as well. This post was inspired from a post by Sylvan von Stuppe were he discusses a full disclosure paper edition.

First off, it isn’t instant. It doesn’t happen just like that, although sometimes you can get lucky, most of the time you will spend hours finding/testing/failing. Why bother trying to exploit a browser I here you ask? Well several reasons really: it’s fun, it’s difficult (sometimes), you’ll learn new things and it will improve security for everyone.

I will try and keep the post in simple terms so a newbie can follow but I won’t go in depth explaining Javascript objects etc, so you’ll just have to use Google to find anything that you can’t understand.

How it started

Whenever I hack things, I always start with the simplest possible attack vector and expand from there and if I over complicate the code I start again rather than spend hours fixing javascript errors etc. There are many reasons for this: I keep all the vectors as a reference, the code always improves and I always understand what’s going on. Understanding your own code is important and you have to understand every little detail because the smallest vector maybe needed at a later stage.

So I was messing about with a blank HTML document as I often do when I’m bored and I stumbled upon some strange behavior with the document object, I found that it was possible to create a new object called “document” and store references to the original “document” object. Which works something like this:-

i=document.getElementById;
var document;
document={};

This is bad. Some of you out there will probably say ah but it’s not the actual “document” object, which is correct but I’ve learned over the years that fooling browsers/web sites/web applications is not difficult and this is a vulnerability waiting to happen once I investigate further but anyway….I noticed this behavior in Safari and IE and I thought I wonder if I can fool the browser into thinking that a iframe is actually on the same domain as the target. This is important, I have now set myself a clear single objective and now I can concentrate on that objective.

Fooling the browser

The document object should be protected (Are you listening vendor), enabling anyone to manipulate it is bad. I continued my document exploit and created a domain property, the purpose of this was to fool the browser into thinking the HTML document was part of the Amazon domain.

i=document.getElementById;
var document;
document={};
document.domain='www.amazon.co.uk';

I at least expected the browser to raise an error and stop me from changing a property called document.domain because of it’s dangerous nature. But the browser seemed happy enough and I thought to myself muwhahaha I’m close. I was wrong. I tried the code which looked something like this:-

function attack() {
   alert(document.domain);
}
<iframe src="http://www.amazon.co.uk/" onload="attack();" id="iframe" name="iframe"></iframe>
<script type="text/javascript">
d = document;
w = window.frames;
</script>
<script type="text/javascript">
var document;
document = {};
document.domain = 'www.amazon.co.uk';
var window;
window={};
</script>

Which did indeed work as I expected, it returned the domain I had given it (under IE & Safari), so my next stage was to try and retrieve data from the iframe by crossing domain names and allowing any site to gain access to any other site. It’s worth understanding that I was testing this in IE first and then testing it in Safari because I knew the behavior was the same between browsers I could increase my chances of finding an exploit if I tested both.

I started to improve my attack function to try and gain access to the information:

window.frames = w;
document.getElementById = d.getElementById;
document.getElementsByTagName = d.getElementsByTagName;

By now I’d stored references to getElementById and getElementsByTagName from the original document object and also the window object referencing window.frames. These were my tools to gather my data, I opened up IE and tried my polished attack function….”ACCESS DENIED” πŸ™ I tried it in Safari, a similar error message appeared. Back to square one I thought, maybe it’s not possible, hang on anything is possible I think to myself, how can I improve my code? Hmmmmmm I open up a new window and place the following javascript in the url:

javascript:for(i in document) document.write(i + document[i] + '
')

The code above loops through the document object and all it’s properties/methods, I try it on a local document and then on a external site and I start comparing them. If I just copy the same information from my target site maybe I can fool the browser into thinking it’s on the target domain when it isn’t. I come up with a new and improved fake document object:-

var document;
document = {};
document.domain = 'www.amazon.co.uk';
document.URL = 'http://www.amazon.co.uk';
document.referrer = 'http://www.amazon.co.uk';
document.documentURI = 'http://www.amazon.co.uk';
document.location = 'http://www.amazon.co.uk';
document.protocol = 'HyperText Transfer Protocol';
document.URLEncoded = 'http://www.amazon.co.uk'; 

I try the code again in IE. Nothing. Should I give up it’s getting a bit boring now? Nah lets give Safari a go IE might be comparing the URLS but Safari might not. In my haste I open Safari by clicking the local file instead of running it through the local testing server. I sit back in my chair thinking that it isn’t going to work. Then suddenly up pops an alert box with some HTML code in, eh? It can’t have worked. It must be from the original parent document. No wait…I see Amazon code! It works πŸ™‚ it’s a cool feeling when something like that happens, to know that the hours of coding haven’t gone to waste and you have actually achieved your goal.

Some people get it, some people don’t

I figured out that the exploit I created was a local one and didn’t work on external domains. But to me this didn’t matter because I knew there would be a way to alter the code and get it running on any domain. This is a way of thinking, often I encounter people who say something like “Yeah but it’s only a [local exploit] and only works under these conditions, so I don’t really consider it a serious hole”. What they should be saying is “Ah a local exploit, good find. I better fix this BEFORE it becomes serious”. You’ll never be able to exploit anything if you think like the first one. Your software will ALWAYS contain holes if you think like the first one.

I had this argument with a guy from Apple and he dismissed my report as not serious. Not serious? Are they having a joke I asked myself and told many others. Right ok Apple if you think it isn’t a problem, then just wait…

Evolution of the exploit

I had given myself a new objective, prove this guy wrong. You know that it’s possible, this guy obviously doesn’t understand web security. Lets have some fun. So I started a few experiments to enable the code to run on any domain, my first idea was to create a downloadable file which auto executed. I tried to get it to download but instead the document kept running in the browser under the local web server domain context so it wouldn’t work.

OK so new objective try and get the file to download instead of running in the browser. The reason Safari was doing this is because HTML files are not part of the “safe” (rubbish feature btw) files. In order to get the file to download from the web server I needed to figure out a way to fool the browser into thinking it didn’t contain HTML code.

<body onLoad="alert(window.frames.iframe.document.getElementsByTagName('body')[0].innerHTML);
alert(window.frames.iframe.document.cookie);">
<p>test</p><iframe src="http://www.amazon.co.uk/" id="iframe" name="iframe"></iframe> 
</body>

I named this flaw “This is not a major flaw” which was a sarcastic reference to our “friend” at Apple. This code worked πŸ™‚ it downloaded the file, but it didn’t run automatically πŸ™ the user had to open the document in order to run it. So I had to think of a way to force it to run. (You see how I always have 1 clear objective and ignore the next objective until the first is complete). I thought about this and running local files came to mind, so somehow try and execute a local path by guessing the desktop or download folder. I tried many times out of interest because I thought it would be cool even though it wouldn’t prove my point. It turns out Safari protects the certain paths in such a way that they are (maybe) not accessible.

So I gave up, it was still in the back of my mind though cause this guy had got on my nerves and I wanted to prove him wrong because browsers shouldn’t be able to access external domains from the filesystem. I was again messing about on the computer one day when Apple software update appeared with news of a new beta of Safari. Cool I thought they must have fixed my problem now I have spoken to the guy at Apple. I download it and installed, then opened up my local exploit. It worked! I was mad, why didn’t they fix it? Right ok Apple I’ll show you. I started to look through all of my vectors and thinking to myself how can I execute this code under a local file context from an external domain.

Then it hit me, about:blank, I could use some of the code I had done for the “This is not a major flaw” exploit and inject it into the about:blank document! The rest as they say is history πŸ˜€

Finished exploit

I hope you’ve enjoyed this article, if you have please leave some feedback and I will consider doing articles of this length again and please don’t use any skills gained for bad purposes. Use it to learn.

18 Responses to “How I found the Safari exploit”

  1. Ronald writes:

    Very nice write up πŸ™‚

    And yes you are right about that part that it doesn’t fall out of the sky it requires good knowledge but more important a good imagination: …what if? like of thinking. And yes I can spend tens or even an complete day only trying to bypass a tough protection mechanism. usually I start with the toughest stuff cause that raises the bar, then the rest is a walk in the park πŸ˜‰

    Some browser hackers go look for existing bugs or old bugs and re-open them in a new coat, I don’t like that I never look onto bugzilla or something it spoils all the fun for me. Also many use fuzzers in which I also don’t believe, it can be usefull to find flaws in the javascript engine but that is not what I’m concerned with.

    I just open the source and read every single line. So that is a kind of intelectual approach, when I see for example that they encode certain chars, I try to use unicode in combination with nulls and try to trick the block of code. Many mistakes are made by a bad code architecture.

    I’m building a new attack platform called BrowserFry, interested in contributing? it aims at being a resource of known attacks that can be mashedup quickly to “fry” certain parts, that includes XHR tampering, cookie tampering, Filter Unicode/null fuzzing, heap spraying et al.

    do let me know if you want to join, i think we can create something beautifull here that can save us alot of time. πŸ™‚

  2. Gareth Heyes writes:

    Thanks for the feedback Ronald much appreciated.

    I see many parallels how we both hack things πŸ™‚ I don’t like to reuse old stuff, I like finding new and interesting vectors πŸ˜€

    I read your post about BrowserFry, I will definitely contribute some vectors once you get it going, sounds like a good project to me.

  3. Jani writes:

    How is this PHP related? If I want to read blogs about some browser exploits or Javascript/CSS stuff I use other feeds for that, Planet PHP is not the one you’re looking for..

  4. Gareth Heyes writes:

    Well the tools I write are usually written in PHP so it is relevant. If you think security has nothing to do with PHP I suggest a career change.

    If that’s your opinion I think most of the stuff on Planet PHP should be removed then. I couldn’t care less if people don’t think my stuff is relevant or not, I’m just trying to share my knowledge with the widest possible audience I have, maybe I should reconsider posting at all.

    Thank you for your crappy comment.

  5. David Rodger writes:

    Safari 2.0.4 (419.3) does nothing. No alerts; no content other than Google Ads. Hmmm…

  6. Gareth Heyes writes:

    You did read the URL which says SAFARI ZERO DAY BETA didn’t you?

    You do know 2.0.4 isn’t beta, don’t you?

    You will consider things before you post in future, won’t you?

  7. Gareth Heyes writes:

    WHY DO I BOTHER!

    I try to do something different, educate people in security and most of what I get is wise guys.

  8. Ronald writes:

    @Jani

    Please don’t visit my site, I’m glad I turned of comments. Commenters really think they can say bout anything these days, and you know what? since I turned of comments my traffic increased a 5th fold, and people who are really contructive in commenting do this by email now, you know why? because that takes some effort instead of squirting random rants.

    And I blogged for a long time, the overall ratio is really about 90/9/1:

    90% rants
    9% people who wanna learn and ask.
    1% contributors

  9. Gareth Heyes writes:

    Ronald I was gutted you switched off your comments. Now I can understand why.

  10. Ronald writes:

    Yes indeed, I hoped most commentors were a bit responsible but I was wrong. I know some other high profile bloggers (you know them also) who also were on the brink of shutting it down only because of this stuff. It’s totally disrespectful sometimes. What does planet PHP has anything to do with it, they feed you and not the other way around.
    Many think I shut it down because i can’t handle a couple of corrections, but that isn’t true. if I’m wrong I post it on my blog and tells who told me why I was wrong.

    I had a anonymous reader who really helped me to understand the concept of heap spraying and he corrected my mistakes instead of firing live ammo at me, so that’s what up. I think we put up too much which such commentors, where do they feel the right to fire such rants? I think we make it them too easy to rant, and yes e-mail works fine now I only get constructive information back and zero rants.

    But in the end it is sad when you gave it all, all your time to write some cool post or paper and it gets little or no attention and attracts only flies πŸ˜‰

    But I was lucky that tons of “silent” readers send me long emails when I shut the site down some time ago, that was the reason I came back, otherwise I would have stopped.

  11. Gareth Heyes writes:

    Yep I’m not going to allow future comments from Jani or David Rodger, in fact anyone with stupid comments can now consider themselves censored. In fact stupid commentors just don’t visit my blog.

    I’m going to remove my site from planet php, so these stupid people can have their wish I don’t care.

    It is very sad that a lot of people ruin things for the rest of us. I’m really glad you kept your site going.

  12. buherator writes:

    I translated the article and put it on my blog (with your name and links attached of course). I hope you don’t mind!

    http://buhera.blog.hu/2007/09/05/igy_kell_safarit_hackelni

    Great job, especially because of the explanation of how a hacker thinks. I will recommend it to all the wannabes I’ll meet!

  13. Gareth Heyes writes:

    @buherator

    Thank you very much for the translation and I have no problem with you republishing it. I want to help people learn.

  14. David Coallier writes:

    Well sorry to see you removed your blog from planetPHP, despite some differents, I like reading your blog. Anyways, this article is fun what did the Apple people say after all ? πŸ™‚

  15. Gareth Heyes writes:

    Hi David

    I’ve not heard from the guy at Apple, maybe he’s very busy at the moment πŸ™‚

    Apple just sent me back an official reply, like Thank you for reporting our engineers are looking into it blah blah.

  16. Dhubh writes:

    Thank you for the in depth post explaining not just what you did, but why you did things. I really hope that more security blogger start making posts like this because it adds so much more to the learning value.

  17. Gareth Heyes writes:

    No problem Dhubh I might do a few more posts in future like this. Glad it helped, if you like this sort of thing I’d check out my friend Ronald’s site, he has all sort of exploits on there:-
    Ronalds site

  18. mike writes:

    How can I access data form the iframe in IE8?
    Thanks.