forked from username/flaskpaste
docs: add comprehensive threat model
STRIDE analysis covering: - System architecture and trust boundaries - Attack surface analysis (10 entry points) - Threat actors (anonymous, authenticated, operator, sophisticated) - 20+ threats with mitigations across STRIDE categories - Security controls matrix - MIME polyglot attack mitigations - Cryptographic controls - Residual risks and known limitations - Incident response guidance
This commit is contained in:
@@ -203,7 +203,7 @@ Not tested (no signature defined):
|
||||
```
|
||||
[ ] Add remaining MIME test results to security assessment
|
||||
[ ] Document rate limiting behavior under attack
|
||||
[ ] Create threat model diagram
|
||||
[x] Create threat model diagram (documentation/threat-model.md)
|
||||
[x] Add security headers audit to CI pipeline
|
||||
```
|
||||
|
||||
|
||||
287
documentation/threat-model.md
Normal file
287
documentation/threat-model.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# FlaskPaste Threat Model
|
||||
|
||||
Security architecture, attack surfaces, and mitigations for FlaskPaste.
|
||||
|
||||
---
|
||||
|
||||
## System Architecture
|
||||
|
||||
```
|
||||
INTERNET
|
||||
|
|
||||
+-----------+-----------+
|
||||
| HAProxy/nginx |
|
||||
| (TLS termination) |
|
||||
+-----------+-----------+
|
||||
|
|
||||
+-----------+-----------+
|
||||
| FlaskPaste |
|
||||
| (Flask + Gunicorn) |
|
||||
+-----------+-----------+
|
||||
|
|
||||
+-----------+-----------+
|
||||
| SQLite DB |
|
||||
| (paste storage) |
|
||||
+-----------------------+
|
||||
```
|
||||
|
||||
### Trust Boundaries
|
||||
|
||||
```
|
||||
+----------------------------------------------------------------+
|
||||
| UNTRUSTED ZONE |
|
||||
| - Anonymous users |
|
||||
| - Public internet |
|
||||
+----------------------------------------------------------------+
|
||||
|
|
||||
[TLS + PoW Challenge]
|
||||
|
|
||||
+----------------------------------------------------------------+
|
||||
| SEMI-TRUSTED ZONE |
|
||||
| - HAProxy/nginx reverse proxy |
|
||||
| - Rate limiting enforcement |
|
||||
+----------------------------------------------------------------+
|
||||
|
|
||||
[X-Proxy-Secret validation]
|
||||
|
|
||||
+----------------------------------------------------------------+
|
||||
| TRUSTED ZONE |
|
||||
| - Flask application |
|
||||
| - SQLite database |
|
||||
| - PKI CA (if enabled) |
|
||||
+----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Attack Surface Analysis
|
||||
|
||||
### Entry Points
|
||||
|
||||
| Entry Point | Protocol | Auth | Rate Limited | Description |
|
||||
|-------------|----------|------|--------------|-------------|
|
||||
| POST / | HTTPS | Optional | Yes | Create paste |
|
||||
| GET /{id} | HTTPS | Optional | Yes | View paste metadata |
|
||||
| GET /{id}/raw | HTTPS | Optional | Yes | View raw content |
|
||||
| HEAD /{id} | HTTPS | None | Yes | Check existence |
|
||||
| DELETE /{id} | HTTPS | Required | Yes | Delete paste |
|
||||
| GET /challenge | HTTPS | None | Yes | Get PoW challenge |
|
||||
| POST /pki/* | HTTPS | Required | Yes | PKI operations |
|
||||
| GET /metrics | HTTPS | None | No | Prometheus metrics |
|
||||
| GET /health | HTTPS | None | No | Health check |
|
||||
|
||||
### Data Flows
|
||||
|
||||
```
|
||||
User Input Flow:
|
||||
+--------+ +-------+ +---------+ +--------+
|
||||
| Client | --> | Proxy | --> | Flask | --> | SQLite |
|
||||
+--------+ +-------+ +---------+ +--------+
|
||||
| | |
|
||||
| [Rate Limit] [Validation]
|
||||
| | |
|
||||
+-- PoW -------+ [MIME detect]
|
||||
+-- Password --+--------[PBKDF2 hash]
|
||||
+-- Content ---+--------[Size check]
|
||||
+-- mTLS cert -+--------[SHA1 verify]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Threat Actors
|
||||
|
||||
### Anonymous Attacker
|
||||
- **Motivation:** Abuse, DoS, content injection
|
||||
- **Capabilities:** Automated tools, botnets
|
||||
- **Mitigations:** PoW, rate limiting, anti-flood
|
||||
|
||||
### Authenticated Attacker
|
||||
- **Motivation:** Data exfiltration, privilege escalation
|
||||
- **Capabilities:** Valid credentials, API access
|
||||
- **Mitigations:** Ownership checks, audit logging
|
||||
|
||||
### Malicious Operator
|
||||
- **Motivation:** Credential theft, data access
|
||||
- **Capabilities:** Proxy access, log access
|
||||
- **Mitigations:** X-Proxy-Secret, no plaintext passwords
|
||||
|
||||
### Sophisticated Attacker
|
||||
- **Motivation:** Zero-day exploitation, APT
|
||||
- **Capabilities:** Reverse engineering, timing attacks
|
||||
- **Mitigations:** Constant-time operations, defense in depth
|
||||
|
||||
---
|
||||
|
||||
## Threat Categories (STRIDE)
|
||||
|
||||
### Spoofing
|
||||
|
||||
| Threat | Vector | Mitigation | Status |
|
||||
|--------|--------|------------|--------|
|
||||
| Client identity spoofing | Forge X-SSL-Client-SHA1 | X-Proxy-Secret validation | MITIGATED |
|
||||
| IP address spoofing | Forge X-Forwarded-For | Proxy secret required | MITIGATED |
|
||||
| Paste ownership claim | Guess owner cert SHA1 | 40-char hex, DB lookup | MITIGATED |
|
||||
|
||||
### Tampering
|
||||
|
||||
| Threat | Vector | Mitigation | Status |
|
||||
|--------|--------|------------|--------|
|
||||
| Content modification | MITM attack | TLS 1.3 required | MITIGATED |
|
||||
| Paste content tampering | Direct DB access | File permissions, no shell access | MITIGATED |
|
||||
| PoW token replay | Reuse solved challenge | Token expiration (60s) | MITIGATED |
|
||||
|
||||
### Repudiation
|
||||
|
||||
| Threat | Vector | Mitigation | Status |
|
||||
|--------|--------|------------|--------|
|
||||
| Deny paste creation | No audit trail | Audit logging with X-Request-ID | MITIGATED |
|
||||
| Deny deletion | Claim not deleted | Audit log with operator ID | MITIGATED |
|
||||
|
||||
### Information Disclosure
|
||||
|
||||
| Threat | Vector | Mitigation | Status |
|
||||
|--------|--------|------------|--------|
|
||||
| Paste enumeration | Sequential IDs | Random hex IDs (64-bit entropy) | MITIGATED |
|
||||
| Password-protected content | Brute force | PBKDF2 600k iterations, rate limit | MITIGATED |
|
||||
| Timing oracle on passwords | Response time variance | Constant-time comparison | MITIGATED |
|
||||
| Burn-after-read race | HEAD then GET | HEAD triggers deletion | MITIGATED |
|
||||
| Metrics exposure | /metrics endpoint | Public by design (no PII) | ACCEPTED |
|
||||
|
||||
### Denial of Service
|
||||
|
||||
| Threat | Vector | Mitigation | Status |
|
||||
|--------|--------|------------|--------|
|
||||
| Request flooding | High volume requests | Rate limiting (per-IP) | MITIGATED |
|
||||
| Content spam | Large pastes | Size limits (100KB anon, 10MB auth) | MITIGATED |
|
||||
| Memory exhaustion | Unbounded dicts | MAX_ENTRIES caps (10000) | MITIGATED |
|
||||
| CPU exhaustion | Complex operations | PoW offloads to client | MITIGATED |
|
||||
| Anti-flood bypass | Distributed attack | Dynamic PoW (16-28 bits) | MITIGATED |
|
||||
| Content hash bypass | Unique content | Dedup window + PoW | MITIGATED |
|
||||
|
||||
### Elevation of Privilege
|
||||
|
||||
| Threat | Vector | Mitigation | Status |
|
||||
|--------|--------|------------|--------|
|
||||
| Delete others' pastes | Guess owner ID | Ownership verification | MITIGATED |
|
||||
| Bypass size limits | Forge auth header | X-Proxy-Secret required | MITIGATED |
|
||||
| PKI CA compromise | Unauthorized cert issue | Client cert required | MITIGATED |
|
||||
| SQL injection | Malformed input | Parameterized queries | MITIGATED |
|
||||
| SSTI | Template injection | No user content in templates | MITIGATED |
|
||||
| Command injection | Shell escape | No shell execution | MITIGATED |
|
||||
|
||||
---
|
||||
|
||||
## Security Controls Matrix
|
||||
|
||||
```
|
||||
+---------------------+------------------------------------------+
|
||||
| Layer | Controls |
|
||||
+---------------------+------------------------------------------+
|
||||
| Network | TLS 1.3, mTLS (optional), X-Proxy-Secret |
|
||||
| Transport | Security headers, CSP, X-Frame-Options |
|
||||
| Application | Input validation, MIME detection, PoW |
|
||||
| Session | Stateless, no cookies, no CSRF needed |
|
||||
| Data | PBKDF2 passwords, random IDs, expiry |
|
||||
| Audit | Request ID tracking, structured logging |
|
||||
| Operations | Rate limiting, anti-flood, size limits |
|
||||
+---------------------+------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MIME Detection Security
|
||||
|
||||
Content is detected by magic bytes, not user-supplied Content-Type:
|
||||
|
||||
```
|
||||
User uploads "image.png" with PHP payload
|
||||
|
|
||||
v
|
||||
[Magic byte detection] --> Not PNG magic --> text/plain
|
||||
|
|
||||
[X-Content-Type-Options: nosniff] --> Browser won't sniff
|
||||
|
|
||||
[CSP: default-src 'none'] --> No script execution
|
||||
```
|
||||
|
||||
### Polyglot Attack Mitigations
|
||||
|
||||
| Attack | Detection | Result |
|
||||
|--------|-----------|--------|
|
||||
| PNG + HTML | PNG magic detected | image/png |
|
||||
| GIF + JS | GIF magic detected | image/gif |
|
||||
| PDF + ZIP | PDF magic detected | application/pdf |
|
||||
| SVG + script | No XML magic | text/plain |
|
||||
| JPEG + PHP | JPEG magic detected | image/jpeg |
|
||||
|
||||
---
|
||||
|
||||
## Cryptographic Controls
|
||||
|
||||
| Purpose | Algorithm | Parameters |
|
||||
|---------|-----------|------------|
|
||||
| Password hashing | PBKDF2-SHA256 | 600,000 iterations |
|
||||
| Paste ID generation | secrets.token_hex | 32 chars (128 bits) |
|
||||
| PoW challenge | SHA-256 | Variable difficulty (16-28 bits) |
|
||||
| HMAC verification | hmac.compare_digest | Constant-time |
|
||||
| PKI certificates | RSA-2048 / ECDSA P-256 | SHA-256 signing |
|
||||
|
||||
---
|
||||
|
||||
## Residual Risks
|
||||
|
||||
### Accepted Risks
|
||||
|
||||
| Risk | Justification | Monitoring |
|
||||
|------|---------------|------------|
|
||||
| Metrics exposed | No PII, needed for monitoring | Access logs |
|
||||
| Anonymous paste creation | Core functionality | Rate limiting |
|
||||
| Content storage | User-provided, may be malicious | MIME detection |
|
||||
|
||||
### Known Limitations
|
||||
|
||||
| Limitation | Impact | Workaround |
|
||||
|------------|--------|------------|
|
||||
| TAR detection | ustar at offset 257 | Falls back to text/plain |
|
||||
| Java .class files | 0xCAFEBABE = Mach-O | Falls back to Mach-O |
|
||||
| Large file DoS | Memory during upload | Gunicorn body limit |
|
||||
|
||||
---
|
||||
|
||||
## Audit Compliance
|
||||
|
||||
| Control | Evidence | Frequency |
|
||||
|---------|----------|-----------|
|
||||
| Input validation | Unit tests | Every commit (CI) |
|
||||
| Rate limiting | Integration tests | Every commit (CI) |
|
||||
| Security headers | headers_audit.py | Every commit (CI) |
|
||||
| Injection prevention | Fuzz tests | Every commit (CI) |
|
||||
| Timing attacks | Timing tests | Weekly |
|
||||
| Penetration testing | pentest_session.py | Monthly |
|
||||
|
||||
---
|
||||
|
||||
## Incident Response
|
||||
|
||||
### Detection Points
|
||||
|
||||
- `/metrics` - Request rates, error rates, PoW difficulty
|
||||
- Audit logs - Unusual patterns, failed auth attempts
|
||||
- Anti-flood - Difficulty increase indicates attack
|
||||
|
||||
### Response Actions
|
||||
|
||||
| Trigger | Automatic Response | Manual Response |
|
||||
|---------|-------------------|-----------------|
|
||||
| High request rate | PoW difficulty increase | Review logs, block IPs |
|
||||
| Failed auth spike | Rate limit enforcement | Investigate, rotate certs |
|
||||
| Large paste flood | Size limit rejection | Block IP range |
|
||||
| Enumeration attempt | 400 responses | Add to blocklist |
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Date | Change |
|
||||
|------|--------|
|
||||
| 2025-12-26 | Initial threat model |
|
||||
Reference in New Issue
Block a user