Post

Authentication Is Not Authorisation: Walking Into an Internal Engineering Environment Through SSO

TL;DR An internal engineering environment at a top US-based HR company sat behind a login page with nothing behind the page. The SSO flow accepted any identity, including a personal Google account with no invitation. That session gave me read access to their bug bounty tickets, security fixes and internal engineering discussions.

Background

The target is a large US-based HR and workforce management company. Big attack surface, active responsible disclosure program.

My process is simple. Enumerate subdomains, filter live hosts with httpx, then test by hand. I look for hosts that should not be on the internet. Internal tools are built for trusted users, so their access control is usually the weakest part.

How I found it

Enumeration turned up an engineering subdomain, mechtopus.company.com. It returned a login page and nothing on the public site linked to it. A login page with no obvious purpose is worth a closer look.

The page was SSO only. No registration, no password field.

The Auth0 login page for the Mechtopus tenant. Google is the only way in.

One button, one provider, and no hint that it was meant to be employees only.

Instead of clicking the SSO button, I looked at what the page could do. I fed the JavaScript bundles to a route finding browser extension by LostSec, which extracts endpoints out of JS files. That gave me the real auth route: /users/auth/<provider>.

The flaw

The app treated “this person authenticated with an identity provider” as “this person works here”.

Question Who answers it What happened
Is this a real, valid identity? The identity provider Answered correctly
Is this identity an employee of this company? The identity provider (domain or group claim) Never enforced
Is this identity allowed into this application? The application, server-side Never asked

Vulnerability class: Broken Access Control / Missing Authorization (OWASP A01, OWASP API #1, CWE-862), plus Improper Authentication (CWE-287).

Reproduction

  1. Open mechtopus.company.com. You get a login screen.
  2. Go straight to /users/auth/<provider>, skipping the page.
  3. Log in with a personal Google account. No company email, no invite, no account provisioned for me.
  4. The callback issues a session with access to the internal workspace.

No payload, no tampering. The flow did exactly what it was configured to do. Nothing downstream checked whether I was allowed in.

I logged out right away and did not open, comment on, download or list anything. I did not need to. The session existing was the proof.

Root cause

No access control behind the SSO. The app created a session as soon as the identity provider returned a valid assertion. It never checked an email domain allowlist, an IdP group claim, or a user allowlist.

The Google connection was not tied to the company. That login page offers one way in: a Google account. The connection behind it was not restricted to the company’s Workspace domain, so any Google account completed the flow. A social Google connection and a Workspace connection with no domain rule both produce that result. The screenshot above is the whole configuration surface, and nothing on it says “employees only”.

The login page was cosmetic. It showed an SSO only experience and implied employees only. Nothing enforced that. The route that starts the handshake was reachable directly.

I never saw the source code. The first and third points are behaviour I observed. The second is my read of the tenant configuration, and it is the most likely explanation.

What I saw

The workspace was their engineering environment. Bug bounty tickets, security fixes, patch discussions, internal notes on issues that were not fixed yet.

That is the part worth pausing on. Those tickets are a list of known weaknesses, written by the people trying to close them.

Impact

Engineering tickets hold more than roadmaps. They hold stack traces, CI logs, internal hostnames, sample keys, connection strings, employee names and roles. Read access to that is read access to a map.

Security tickets are the sharp edge. A researcher’s unreported finding, a patch that has not shipped, a known flaw with no fix. Anyone reading those knows where to look next.

If tickets reference customer data, employee PII or payment context, this becomes a reportable breach with the audit and notification work that follows.

Severity is critical. The only prerequisite was a free email account.

Fix

  • Check membership server side, in the callback, before issuing any session. Email domain allowlist, IdP group claim, or user allowlist. Deny by default.
  • Remove social connections from internal apps. Corporate connection only. Enforce the same at the IdP so an unapproved identity cannot finish the flow.
  • Add provisioning with an allowlist, plus SCIM deprovisioning so leavers lose access.
  • Do not rely on a hidden subdomain. Put internal tools behind an identity aware proxy (Cloudflare Access, Teleport, Google IAP) or take them off the internet.
  • Alert on authentications to internal apps from consumer identity providers, on first seen identities, and on new geographies. Any one of those turns this into a same day detection.

Takeaways

Authentication is an input. Authorisation is the decision. Every SSO bug of this shape is a valid token treated as permission.

A login wall is not an access control. If a page says “sign in” and nothing else, check what happens after sign in succeeds.

Read only internal access is not low impact. A tracker is a map of a company’s weaknesses, and it is usually judged less harshly than it deserves.

Report discipline is part of the finding. Log out, do not enumerate, capture the minimum, and separate what you observed from what you inferred.

Disclosure

I reported this through the company’s disclosure program with the minimum proof: the route, the steps to reach it, and a screenshot of an authenticated session. No customer data, no ticket contents, no screenshots of anything inside the workspace.

They confirmed the issue and closed the gap. The environment is no longer reachable the way I reached it, and the report was rewarded with a bounty. Credit to the team for how quickly they handled it. A readable report with a short, precise reproduction is usually the difference between a triage argument and a fix.


Reported privately through the company’s disclosure program, fixed, and rewarded with a bounty. Company name, hostnames, ticket contents, employee identifiers and customer data have been removed. company.com and mechtopus are placeholders.

~ cybershaykh

This post is licensed under CC BY 4.0 by the author.