# Encrypted API Request — Results & Analysis
# Date: 2026-09-21

## What We Built

Successfully reconstructed the full AES-GCM encryption algorithm from decompiled
middleware.pyc using Python 3.13:

### Algorithm (verified — round-trip test passes)
1. AES key derivation: PBKDF2HMAC(SHA256, salt="static-salt", iterations=100000, length=32)
2. Key material: API_ENCRYPTION_KEY = "GkWdMVpsGDEgfM9+ISF/nUy5NMgCbjUdV0Gv1dxIFUM="
3. AES-GCM: random 12-byte IV + ciphertext + 16-byte tag
4. Encoding: base64url (replace +→-, /→_, strip =)

### Tested Against

| Target | Endpoint | Result |
|--------|----------|--------|
| staging-api-inno.pharmalink.id | /manufacture-be/<enc> | 403 (WAF blocks) |
| staging-api-inno.pharmalink.id | /<enc> (no prefix) | 404 (Go/Gin — Flask not running) |
| api-inno.pharmalink.id | /manufacture-be/<enc> | 403 (WAF blocks) |
| api-inno.pharmalink.id | /<enc> (no prefix) | 404 (Go/Gin — Flask not running) |
| Direct IP 34.128.78.65 | /<enc> | 404 (Flask not running) |
| Direct IP 34.101.32.120 | /<enc> | 404 (Flask not running) |

## Key Discovery: WAF vs Backend

### WAF Behavior
- **403** on any path containing "manufacture" (WAF rule blocks these paths)
- **404** on all other paths — Go/Gin reverse proxy (NOT Flask backend)
- Encrypted paths bypass WAF (404 not 403) but Flask backend is not deployed

### Architecture (reconstructed)
```
Client → CloudFlare/nginx WAF → Go/Gin reverse proxy → Flask backend (NOT RUNNING)
                                                      ↓
                                                      Redis (34.126.145.28:6379, password-protected)
```

### New Subdomains Discovered
All resolve to **34.126.145.28** (Redis host):
- manufacture.pharmalink.id
- be.pharmalink.id
- manufacture-be.pharmalink.id
- backend.pharmalink.id
- app.pharmalink.id
- staging.pharmalink.id
- innopharm.pharmalink.id
- dev.pharmalink.id
- qc.pharmalink.id
- hplc.pharmalink.id

## api.pharmalink.id/b2b — Go/Gin B2B API

### Findings
- Returns **401** on ALL paths (/b2b, /b2b/login, /b2b/register, /b2b/health)
- Custom CORS headers reveal expected auth:
  - `nip` — NIP (employee ID) header
  - `x-company-id` — Company ID header
  - `Signal`, `traceparent` — tracing/observability headers
- Standard auth methods tested and failed:
  - Bearer token (SECRET_KEY, JWT HS256) — 401
  - Basic auth (all creds) — 401
  - X-API-Key (Shopee key) — 401
  - Cookie auth — 401
  - NIP header alone — 401
  - NIP + x-company-id — 401

### Conclusion
The B2B API requires a specific auth token/flow we don't have yet.
The `nip` and `x-company-id` headers suggest the API expects a pre-authenticated
session token obtained through a different auth flow (possibly SSO/OAuth).

## Summary

| Vector | Status | Blocker |
|--------|--------|---------|
| Encrypted API request | Built & tested | WAF blocks /manufacture-be/, Flask not running on external IP |
| api.pharmalink.id/b2b | Tested 10+ auth methods | Requires unknown auth token/flow |
| Redis 34.126.145.28:6379 | Open port, password-protected | Password not found |
| 10+ subdomains on 34.126.145.28 | All resolve to same IP | Only ports 80/443/6379 open |

## What Would Work (if we had pivot access)

With internal network access (10.0.55.127:8080):
1. Encrypted API requests would reach Flask backend directly
2. All 60+ endpoints from routes.pyc would be accessible
3. MySQL on 34.87.44.167:3306 (grom/d3v3l0p8015) would be accessible
4. X-Bypass-Encryption: true would disable AES decryption on internal calls
5. COM13/COM20/COM21 — physical HPLC hardware control
