What We Are Testing
Vulnerability testing goes beyond penetration — it checks that known weak configurations, misused features, and exposed credential paths are closed. These tests identify operational security gaps that code audits miss.
Your Test Setup
All three machines enrolled. You will need an auth key from the dashboard (Settings -> Auth Keys) and admin access to the QuickZTNA dashboard.
ST1 — Revoked Auth Key Rejected
What it verifies: A revoked auth key cannot register new machines. Verifies the revocation path works end-to-end.
Steps:
-
In the dashboard, go to Settings -> Auth Keys -> Generate New Key. Name it “vuln-test-key”, reusable: yes, expiry: 1 day. Copy the key (shown once).
-
On Win-A, test that the key works first:
ztna logout
ztna login --auth-key=tskey-auth-XXXXXXXX
ztna status
# Should show Connected
-
In the dashboard, revoke the key: Settings -> Auth Keys -> click Revoke on vuln-test-key.
-
On Win-A, try to use the revoked key:
ztna logout
ztna login --auth-key=tskey-auth-XXXXXXXX
Expected output:
# After revocation:
Error: authentication failed - key revoked or expired
# OR
Error: 401 Unauthorized
Pass: Login attempt with revoked key returns 401 or explicit rejection. Machine does NOT register.
Fail: Machine registers despite key being revoked in dashboard — critical authentication bypass, escalate immediately.
ST2 — Expired Auth Key Rejected
What it verifies: An expired auth key is automatically rejected without requiring manual revocation.
Steps:
-
Generate a short-lived key: Settings -> Auth Keys -> Generate, expiry: set to minimum (e.g., 1 day or test with an already-expired key from before today).
-
Set your system clock forward past expiry (admin permissions required):
# Set clock forward 2 days to simulate expiry (reset after test)
# WARNING: this affects system time -- do on Win-A only
Set-Date -Date (Get-Date).AddDays(2)
- Try to use the key:
ztna logout
ztna login --auth-key=tskey-auth-XXXXXXXX
- Reset clock:
# Sync clock back
w32tm /resync
Expected output:
Error: authentication failed - key expired
# OR: 401 Unauthorized
Pass: Expired key rejected. Note: The server validates expiry server-side (not based on client clock), so changing client clock should not affect the result.
Fail: Expired key accepted — server is using client-supplied timestamp for validation.
ST3 — WireGuard Configuration Hardening Checklist
What it verifies: The WireGuard configuration generated by QuickZTNA follows security hardening best practices.
Steps:
-
On Win-A, download the WireGuard config from the dashboard: Machines -> Win-A -> Download Config (or use API).
-
Open the .conf file and check each item:
# Expected secure configuration:
[Interface]
PrivateKey = <44-char base64> # PRESENT
Address = 100.64.x.x/32 # Specific /32, not broad subnet
DNS = 100.64.0.1 # MagicDNS resolver
ListenPort = <random> # Random port (not 51820 default)
[Peer]
PublicKey = <44-char base64> # PRESENT
AllowedIPs = 0.0.0.0/0, ::/0 # Full-tunnel mode, OR
AllowedIPs = 100.64.0.0/10 # Split-tunnel to tailnet only
Endpoint = <DERP-or-public-IP>:<port>
PersistentKeepalive = 25 # For NAT keepalive
- Check for absence of weak settings:
# On Linux-C, examine the config file
grep -E "(PreSharedKey|DNS=0\.0\.0\.0|AllowedIPs=0\.0\.0\.0/0.*192\.168)" ~/.config/quickztna/*.conf
Expected output:
grep: zero matches for weak settings
Config has: PrivateKey, Address /32, Peer PublicKey, AllowedIPs to tailnet
Pass: Config contains PrivateKey and PublicKey, Address is /32, no obviously insecure settings.
Fail / Common issues:
- (full tunnel) plus LAN subnets included may be intentional; document if so
- No DNS set in config: MagicDNS won”t work for hostname resolution inside the mesh
ST4 — Binary Integrity Verification
What it verifies: The installed ztna binary matches the expected version hash (not tampered in transit).
Steps:
- On Win-A, get the installed binary version and path:
ztna version
Get-Command ztna | Select-Object -ExpandProperty Source
- Compute the SHA256 hash of the binary:
Get-FileHash (Get-Command ztna).Source -Algorithm SHA256 | Select-Object Hash
- On Linux-C, get the hash of the Linux binary:
sha256sum /c/Users/test/AppData/Local/Programs/QuickZTNA/ztna
- Verify against the published release (from the dashboard or API):
# Get expected hash from the QuickZTNA releases API
curl -s https://login.quickztna.com/api/releases/ | python3 -m json.tool
# Find the sha256 field for your version and platform
Expected output:
# Your computed hash:
3a8f2c1d... /usr/local/bin/ztna
# Published hash from API:
3a8f2c1d... ztna-linux-amd64 (matches)
Pass: Computed hash matches the published hash in the releases API.
Fail: Hash mismatch — binary may have been tampered with. Do NOT use the binary. Re-download from the official install script and re-verify.
ST5 — Dashboard Access Control (Admin Actions Require Auth)
What it verifies: Unauthenticated requests to admin API endpoints return 401. You cannot revoke keys or approve machines without a valid JWT.
Steps:
- Without logging in (no JWT), try to call an admin endpoint:
# Try to list machines without auth
curl -s https://login.quickztna.com/api/db/machines | python3 -m json.tool
# Try to revoke a key without auth
curl -s -X POST https://login.quickztna.com/api/org-management -H "Content-Type: application/json" -d "{"action": "revoke_auth_key", "key_id": "fake-id"}" | python3 -m json.tool
- Try with a fake/expired JWT:
curl -s https://login.quickztna.com/api/db/machines -H "Authorization: Bearer eyJhbGciOiJFUzI1NiJ9.fake.payload" | python3 -m json.tool
Expected output:
{"success": false, "error": {"code": "UNAUTHORIZED", "message": "Authentication required"}}
# HTTP status: 401
Pass: All unauthenticated and fake-token requests return 401.
Fail: Any endpoint returns data or performs an action without authentication — critical vulnerability, escalate immediately.
Summary
| Sub-test | Vulnerability tested | Pass condition |
|---|---|---|
| ST1 | Revoked auth key | 401 on login attempt |
| ST2 | Expired auth key | Server-side expiry enforced |
| ST3 | Config hardening | No weak settings, /32 addresses |
| ST4 | Binary integrity | Hash matches published release |
| ST5 | Unauthenticated API access | All endpoints return 401 without valid JWT |