1. Capstone Project Overview
Capstone Project — End-to-end Performance Test & Pentest
Target Application: E-Commerce Platform (microservices)
├── Frontend: React SPA
├── API Gateway: Kong / Nginx
├── Auth Service: JWT + OAuth2
├── Product Service: REST API (Node.js)
├── Order Service: REST API (Java Spring Boot)
├── Payment Service: REST API (Go)
├── Database: PostgreSQL + Redis
├── Message Queue: RabbitMQ
└── Infrastructure: Docker + Kubernetes
Timeline: 12 ngày (2 tuần làm việc + 2 ngày cuối tuần)
Ngày 1-2 │ Planning & Scoping
Ngày 3-4 │ Performance Test Design & Execution
Ngày 5-6 │ Performance Analysis & Tuning
Ngày 7-8 │ Penetration Testing — Recon & Scanning
Ngày 9-10 │ Penetration Testing — Exploitation & Post-exploitation
Ngày 11 │ Report Writing
Ngày 12 │ Presentation & Remediation Plan
2. Phase 1: Planning & Scoping (Day 1-2)
# Security & Performance Assessment — Project Charter
## 1. Engagement Overview
- **Client**: XDev Corp
- **Application**: E-Commerce Platform v3.2
- **Type**: Performance Test + Gray-box Pentest
- **Timeline**: 12 working days
- **Team**: 2 performance engineers + 2 pentesters
## 2. Scope
### In Scope
| Asset | Type | Environment |
|---------------------|---------------|-------------|
| app.xdev.example | Web App | Staging |
| api.xdev.example | REST API | Staging |
| *.xdev.example | Subdomains | Staging |
| K8s cluster | Infrastructure| Staging |
| PostgreSQL | Database | Staging |
### Out of Scope
- Production environment
- Third-party payment gateway (Stripe)
- Physical security
- Social engineering
## 3. Rules of Engagement
- Testing hours: 08:00 – 22:00 ICT
- No DoS/DDoS against production
- Performance tests max 500 VUs on staging
- Data: Use synthetic test data only
- Emergency contact: [email protected]
## 4. Success Criteria
### Performance
- Homepage load < 2s (P95)
- API response < 200ms (P95)
- Support 300 concurrent users
- Zero errors under normal load
### Security
- No Critical/High findings in OWASP Top 10
- All APIs properly authenticated
- No sensitive data exposure
- Container images free of Critical CVEs
## 5. Deliverables
- Performance Test Report (PDF + Dashboard)
- Pentest Report (Technical + Executive)
- Remediation roadmap with SLA
- Retest confirmation (after fixes)
3. Phase 2: Performance Testing (Day 3-6)
3.1 Test Design
// k6-capstone/scenarios/smoke-test.js
import http from 'k6/http';
import { check, sleep, group } from 'k6';
import { Rate, Trend, Counter } from 'k6/metrics';
// Custom metrics
const errorRate = new Rate('errors');
const homepageTime = new Trend('homepage_duration');
const searchTime = new Trend('search_duration');
const checkoutTime = new Trend('checkout_duration');
const BASE_URL = __ENV.BASE_URL || 'https://staging.xdev.example';
export const options = {
scenarios: {
// Smoke test — verify scripts work
smoke: {
executor: 'constant-vus',
vus: 1,
duration: '1m',
},
},
thresholds: {
http_req_duration: ['p(95)<2000'],
errors: ['rate<0.01'],
},
};
export function setup() {
// Login and get token
const loginRes = http.post(`${BASE_URL}/api/auth/login`, JSON.stringify({
email: '[email protected]',
password: 'TestP@ss2026!',
}), { headers: { 'Content-Type': 'application/json' } });
check(loginRes, { 'login successful': (r) => r.status === 200 });
return { token: loginRes.json('token') };
}
export default function (data) {
const headers = {
'Authorization': `Bearer ${data.token}`,
'Content-Type': 'application/json',
};
// User journey: Browse → Search → View → Add to Cart → Checkout
group('01_Homepage', () => {
const res = http.get(`${BASE_URL}/`);
homepageTime.add(res.timings.duration);
check(res, { 'homepage 200': (r) => r.status === 200 });
errorRate.add(res.status !== 200);
sleep(2);
});
group('02_Search', () => {
const res = http.get(`${BASE_URL}/api/products?q=laptop&page=1`, { headers });
searchTime.add(res.timings.duration);
check(res, {
'search 200': (r) => r.status === 200,
'has results': (r) => r.json('data.length') > 0,
});
errorRate.add(res.status !== 200);
sleep(1);
});
group('03_ViewProduct', () => {
const res = http.get(`${BASE_URL}/api/products/prod-001`, { headers });
check(res, { 'product 200': (r) => r.status === 200 });
errorRate.add(res.status !== 200);
sleep(1);
});
group('04_AddToCart', () => {
const res = http.post(`${BASE_URL}/api/cart/items`, JSON.stringify({
product_id: 'prod-001',
quantity: 1,
}), { headers });
check(res, { 'add cart 200': (r) => r.status === 200 || r.status === 201 });
errorRate.add(res.status >= 400);
sleep(1);
});
group('05_Checkout', () => {
const res = http.post(`${BASE_URL}/api/orders`, JSON.stringify({
payment_method: 'test_card',
shipping_address: {
street: '123 Test St',
city: 'Ho Chi Minh',
country: 'VN',
},
}), { headers });
checkoutTime.add(res.timings.duration);
check(res, { 'checkout success': (r) => r.status === 200 || r.status === 201 });
errorRate.add(res.status >= 400);
sleep(2);
});
}
// k6-capstone/scenarios/load-test.js
import { smoke } from './smoke-test.js';
export { setup, default } from './smoke-test.js';
export const options = {
scenarios: {
// Ramp-up load test
load: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 50 }, // Ramp up
{ duration: '5m', target: 50 }, // Steady state
{ duration: '2m', target: 150 }, // Peak load
{ duration: '5m', target: 150 }, // Sustained peak
{ duration: '2m', target: 300 }, // Stress point
{ duration: '5m', target: 300 }, // Sustained stress
{ duration: '3m', target: 0 }, // Ramp down
],
},
},
thresholds: {
http_req_duration: ['p(95)<2000', 'p(99)<5000'],
errors: ['rate<0.05'],
homepage_duration: ['p(95)<1500'],
search_duration: ['p(95)<500'],
checkout_duration: ['p(95)<3000'],
},
};
3.2 Execution & Analysis
# Run performance tests with Grafana dashboards
# Smoke test (verify scripts)
k6 run --out influxdb=http://localhost:8086/k6 \
k6-capstone/scenarios/smoke-test.js
# Load test (main test)
k6 run --out influxdb=http://localhost:8086/k6 \
--out json=results/load-test.json \
k6-capstone/scenarios/load-test.js
# Results analysis
k6 run --summary-export=results/summary.json \
k6-capstone/scenarios/load-test.js
Performance Test Results Summary:
Scenario: Load Test — E-Commerce Platform
VUs: 0 → 50 → 150 → 300 → 0
Duration: 24 minutes
Results:
┌──────────────────────┬────────┬────────┬────────┬────────┬─────────┐
│ Metric │ Avg │ P50 │ P90 │ P95 │ P99 │
├──────────────────────┼────────┼────────┼────────┼────────┼─────────┤
│ Homepage │ 320ms │ 280ms │ 520ms │ 780ms │ 1,200ms │
│ Search API │ 180ms │ 150ms │ 350ms │ 480ms │ 920ms │
│ Product Detail │ 95ms │ 80ms │ 180ms │ 250ms │ 450ms │
│ Add to Cart │ 120ms │ 100ms │ 220ms │ 310ms │ 580ms │
│ Checkout │ 450ms │ 380ms │ 850ms │ 1,200ms│ 2,500ms │
└──────────────────────┴────────┴────────┴────────┴────────┴─────────┘
Total Requests: 142,380
Success Rate: 97.2%
Error Rate: 2.8% ⚠️ (threshold: 5%)
Throughput: ~98 req/s avg, peak 156 req/s
Bottlenecks Identified:
1. [HIGH] Checkout P99 = 2.5s → Order Service DB connection pool exhaustion
2. [MEDIUM] Search at 300 VUs → PostgreSQL full table scan on products
3. [LOW] Homepage TTFB increases linearly → Missing CDN cache headers
4. Phase 3: Penetration Testing (October 7)
4.1 Reconnaissance
# Subdomain enumeration
amass enum -d xdev.example -o recon/subdomains.txt
# Port scan
nmap -sV -sC -p- --min-rate=1000 \
-oA recon/full-scan staging.xdev.example
# Technology fingerprinting
whatweb https://staging.xdev.example
# API discovery
# Check API docs
curl -s https://api.xdev.example/swagger.json | jq '.paths | keys[]'
curl -s https://api.xdev.example/openapi.json | jq '.paths | keys[]'
# Directory brute-force
feroxbuster -u https://api.xdev.example \
-w /usr/share/wordlists/dirb/common.txt \
--filter-status 404 -o recon/dirs.txt
# Kubernetes recon (if accessible)
kubectl get pods --all-namespaces 2>/dev/null
kubectl get services --all-namespaces 2>/dev/null
4.2 Vulnerability Scanning__HTMLTAG_90___
# Nuclei scan
nuclei -u https://staging.xdev.example \
-t cves/ -t vulnerabilities/ -t misconfiguration/ \
-severity critical,high,medium \
-o results/nuclei-scan.txt \
-json -json-export results/nuclei-scan.json
# ZAP full scan
docker run --rm -v $(pwd)/results:/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable zap-full-scan.py \
-t https://staging.xdev.example \
-r zap-report.html \
-J zap-report.json \
-c zap-config.prop
# Container image scan
trivy image --severity HIGH,CRITICAL \
--format json --output results/trivy-images.json \
registry.xdev.example/ecommerce-api:latest
# K8s cluster scan
trivy k8s --report summary cluster
kubeaudit all -f /path/to/manifests/
# Nuclei scan
nuclei -u https://staging.xdev.example \
-t cves/ -t vulnerabilities/ -t misconfiguration/ \
-severity critical,high,medium \
-o results/nuclei-scan.txt \
-json -json-export results/nuclei-scan.json
# ZAP full scan
docker run --rm -v $(pwd)/results:/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable zap-full-scan.py \
-t https://staging.xdev.example \
-r zap-report.html \
-J zap-report.json \
-c zap-config.prop
# Container image scan
trivy image --severity HIGH,CRITICAL \
--format json --output results/trivy-images.json \
registry.xdev.example/ecommerce-api:latest
# K8s cluster scan
trivy k8s --report summary cluster
kubeaudit all -f /path/to/manifests/
4.3 Manual Testing — Findings
Pentest Findings Summary — E-Commerce Platform
Total: 18 findings Critical: 2 High: 4 Medium: 7 Low: 5
─────────────────────────────────────────────────────────────────────
[CRITICAL] Finding #1: Broken Object-Level Authorization (BOLA)
CWE-639 | CVSS v4.0: 9.1
Endpoint: GET /api/orders/{orderId}
Issue: Any authenticated user can view any order by changing orderId
Impact: Full access to all customer orders, PII exposure
PoC:
# User A's token can access User B's order
curl -H "Authorization: Bearer USER_A_TOKEN" \
https://api.xdev.example/api/orders/ORD-0042
Remediation: Implement ownership check in Order Service
if (order.userId !== req.user.id) return 403;
─────────────────────────────────────────────────────────────────────
[CRITICAL] Finding #2: SQL Injection in Search
CWE-89 | CVSS v4.0: 9.3
Endpoint: GET /api/products?q=PAYLOAD&sort=PAYLOAD
Issue: sort parameter directly concatenated into SQL query
Impact: Full database read/write, potential RCE
PoC:
GET /api/products?q=laptop&sort=name;SELECT+pg_sleep(5)--
→ Response delayed 5s = confirmed blind SQLi
sqlmap -u "https://api.xdev.example/api/products?sort=name" \
--headers="Authorization: Bearer TOKEN" --dbs
Remediation: Use parameterized queries
─────────────────────────────────────────────────────────────────────
[HIGH] Finding #3: JWT Algorithm Confusion
CWE-327 | CVSS v4.0: 8.2
Issue: Auth service accepts "alg: none" in JWT header
Impact: Authentication bypass, impersonate any user
PoC:
# Forge JWT with alg=none
echo '{"alg":"none","typ":"JWT"}' | base64url
echo '{"sub":"admin","role":"admin"}' | base64url
# Token: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiJ9.
Remediation: Explicitly whitelist allowed algorithms
jwt.verify(token, secret, { algorithms: ['RS256'] })
─────────────────────────────────────────────────────────────────────
[HIGH] Finding #4: SSRF via Image Upload
CWE-918 | CVSS v4.0: 7.5
Endpoint: POST /api/products/image
Issue: URL parameter fetches remote images without validation
Impact: Internal network scanning, cloud metadata access
PoC:
POST /api/products/image
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}
Remediation: Validate URL against allowlist, block internal IPs
─────────────────────────────────────────────────────────────────────
[HIGH] Finding #5: Exposed Kubernetes Dashboard
Issue: K8s dashboard accessible without authentication
URL: https://k8s.xdev.example/dashboard/
Impact: Full cluster control, deploy malicious workloads
─────────────────────────────────────────────────────────────────────
[HIGH] Finding #6: Hardcoded Secrets in Container Image
CWE-798 | CVSS v4.0: 7.8
Issue: Database credentials found in Docker image layers
Impact: Direct database access, data exfiltration
PoC:
docker save registry.xdev.example/ecommerce-api:latest | tar xf -
grep -r "DB_PASSWORD" */layer.tar
→ Found: DB_PASSWORD=Pr0duction_P@ss!
Remediation: Use K8s Secrets or Vault, multi-stage Docker builds
5. Phase 4: Report Writing (Day 11)
5.1 Executive Summary
# Executive Summary
## Overall Risk Rating: HIGH
XDev Corp's E-Commerce Platform was assessed through combined performance
testing and penetration testing from [date] to [date].
### Key Findings
| Category | Critical | High | Medium | Low | Total |
|---------------------|----------|------|--------|-----|-------|
| Authentication | 0 | 1 | 2 | 1 | 4 |
| Authorization | 1 | 0 | 1 | 0 | 2 |
| Injection | 1 | 0 | 1 | 0 | 2 |
| Infrastructure | 0 | 2 | 1 | 2 | 5 |
| Data Protection | 0 | 1 | 2 | 2 | 5 |
| **Total** | **2** | **4**| **7** | **5**| **18**|
### Performance Assessment
| Criteria | Target | Actual | Status |
|-----------------------------|---------|----------|--------|
| Homepage P95 | < 2s | 780ms | ✅ PASS |
| API P95 | < 200ms | 480ms | ❌ FAIL |
| Concurrent users supported | 300 | ~220 | ❌ FAIL |
| Error rate under load | < 1% | 2.8% | ❌ FAIL |
### Business Impact
- **2 Critical findings** require immediate remediation (< 48h)
- BOLA vulnerability exposes **all customer orders and PII**
- SQL injection allows **full database compromise**
- Platform **cannot sustain 300 concurrent users** — checkout degrades at 200+ VUs
- Revenue impact: Estimated $X per hour of degraded checkout experience
### Priority Recommendations
1. **Immediate (48h)**: Fix SQL injection and BOLA vulnerabilities
2. **Short-term (1 week)**: Fix JWT algorithm confusion, SSRF, K8s dashboard
3. **Medium-term (30 days)**: Optimize database queries, increase connection pool
4. **Long-term (90 days)**: Implement WAF, SAST/DAST in CI/CD, load test automation
5.2 Remediation Roadmap__HTMLTAG_100___
Remediation Roadmap — Gantt Chart
Week 1 (Immediate):
████ SQL Injection fix + verify
████ BOLA authorization fix + verify
██── JWT algorithm whitelist
Week 2 (Short-term):
──██ JWT fix continue + verify
████ SSRF URL validation
████ K8s dashboard RBAC
██── Hardcoded secrets → Vault
Week 3-4 (Medium-term):
──████ Secrets rotation
████████ DB query optimization
████████ Connection pool tuning
████ CDN cache headers
████████ Retest all High findings
Month 2-3 (Long-term):
████████████████ WAF deployment
████████████████ SAST/DAST CI/CD
████████ k6 load test automation
████████ Security training for devs
Verification:
- Retest Critical findings: Week 2
- Retest High findings: Week 4
- Full regression pentest: Month 3
- Performance retest: After optimization
Remediation Roadmap — Gantt Chart
Week 1 (Immediate):
████ SQL Injection fix + verify
████ BOLA authorization fix + verify
██── JWT algorithm whitelist
Week 2 (Short-term):
──██ JWT fix continue + verify
████ SSRF URL validation
████ K8s dashboard RBAC
██── Hardcoded secrets → Vault
Week 3-4 (Medium-term):
──████ Secrets rotation
████████ DB query optimization
████████ Connection pool tuning
████ CDN cache headers
████████ Retest all High findings
Month 2-3 (Long-term):
████████████████ WAF deployment
████████████████ SAST/DAST CI/CD
████████ k6 load test automation
████████ Security training for devs
Verification:
- Retest Critical findings: Week 2
- Retest High findings: Week 4
- Full regression pentest: Month 3
- Performance retest: After optimization
6. Automated Report Generation
# generate_capstone_report.py
# Combines performance + security results into single report
import json
from datetime import datetime
from pathlib import Path
def load_results():
"""Load all scan and test results"""
results = {}
# k6 performance results
k6_path = Path("results/summary.json")
if k6_path.exists():
with open(k6_path) as f:
results["performance"] = json.load(f)
# Nuclei findings
nuclei_path = Path("results/nuclei-scan.json")
if nuclei_path.exists():
with open(nuclei_path) as f:
results["nuclei"] = [json.loads(line) for line in f]
# ZAP findings
zap_path = Path("results/zap-report.json")
if zap_path.exists():
with open(zap_path) as f:
results["zap"] = json.load(f)
# Trivy findings
trivy_path = Path("results/trivy-images.json")
if trivy_path.exists():
with open(trivy_path) as f:
results["trivy"] = json.load(f)
return results
def generate_summary(results: dict) -> dict:
"""Generate combined summary"""
summary = {
"date": datetime.now().isoformat(),
"performance": {
"total_requests": results.get("performance", {}).get("metrics", {})
.get("http_reqs", {}).get("count", 0),
"error_rate": results.get("performance", {}).get("metrics", {})
.get("errors", {}).get("rate", 0),
"p95_duration": results.get("performance", {}).get("metrics", {})
.get("http_req_duration", {}).get("p(95)", 0),
},
"security": {
"critical": 0, "high": 0, "medium": 0, "low": 0
}
}
# Count findings by severity
for finding in results.get("nuclei", []):
sev = finding.get("info", {}).get("severity", "low").lower()
if sev in summary["security"]:
summary["security"][sev] += 1
return summary
def upload_to_defectdojo(results: dict, config: dict):
"""Upload all results to DefectDojo"""
import requests as req
base_url = config["defectdojo_url"]
headers = {"Authorization": f"Token {config['defectdojo_token']}"}
scan_files = [
("results/nuclei-scan.json", "Nuclei Scan"),
("results/zap-report.json", "ZAP Scan"),
("results/trivy-images.json", "Trivy Scan"),
]
for filepath, scan_type in scan_files:
if Path(filepath).exists():
with open(filepath, "rb") as f:
req.post(
f"{base_url}/api/v2/reimport-scan/",
headers=headers,
files={"file": f},
data={
"scan_type": scan_type,
"product_name": config["product_name"],
"engagement_name": config["engagement_name"],
"auto_create_context": "true",
}
)
if __name__ == "__main__":
results = load_results()
summary = generate_summary(results)
print(json.dumps(summary, indent=2))
7. Phase 5: Presentation & Handoff (Day 12)
Presentation Agenda — Capstone Results
1. Executive Summary (10 min)
├── Overall risk rating
├── Critical findings overview
└── Performance vs targets
2. Performance Test Results (15 min)
├── Load test methodology
├── Results dashboard walkthrough
├── Bottleneck analysis
└── Optimization recommendations
3. Penetration Test Results (20 min)
├── Scope and methodology
├── Critical/High findings deep-dive
├── Live demo: BOLA + SQLi exploitation
└── Attack chain visualization
4. Combined Risk Analysis (10 min)
├── Performance under attack scenarios
├── Security vs performance trade-offs
└── Business impact quantification
5. Remediation Roadmap (10 min)
├── Priority matrix
├── Timeline and ownership
├── SLA commitments
└── Retest schedule
6. Q&A (15 min)
Deliverables Checklist:
☑ Performance Test Report (PDF)
☑ Pentest Report — Technical (PDF)
☑ Pentest Report — Executive (PDF)
☑ Raw scan data (encrypted ZIP)
☑ k6 test scripts (Git repo)
☑ Remediation Jira tickets (auto-created)
☑ Grafana dashboard access
☑ DefectDojo project access
☑ Retest schedule (calendar invites)
8. Summary of the entire Series
Performance Testing & Pentest: Quy trình Chuẩn Doanh nghiệp 2026
30 Bài học — 6 Phần — 120+ giờ học
Phần 1: Nền tảng Performance Testing (Bài 1-5)
✅ Load/Stress/Soak/Spike testing concepts
✅ k6, Gatling, Artillery
✅ Metrics: throughput, latency, error rate
Phần 2: Performance Testing Nâng cao (Bài 6-10)
✅ Database performance, caching strategies
✅ Distributed testing, cloud-scale
✅ APM integration, continuous testing
Phần 3: Pentest Foundations (Bài 11-15)
✅ PTES methodology, legal framework
✅ OWASP Top 10 (2025)
✅ Recon, scanning, web app testing
Phần 4: Pentest Nâng cao (Bài 16-20)
✅ Metasploit, cloud pentesting
✅ Container/K8s security
✅ API testing, AI-powered pentesting
Phần 5: Red/Blue/Purple Team (Bài 21-25)
✅ Adversary simulation, detection engineering
✅ Purple team collaboration
✅ Bug bounty, compliance frameworks
Phần 6: Báo cáo & Quy trình (Bài 26-30)
✅ CVSS v4.0 scoring
✅ Performance & Pentest report writing
✅ Automated reporting, remediation tracking
✅ Capstone: End-to-end project
Congratulations! 🎉
Bạn đã hoàn thành toàn bộ series. Hãy áp dụng kiến thức
vào dự án thực tế và tiếp tục cập nhật theo xu hướng 2026.
- Capstone = Summary: Combine all knowledge from the previous 29 lessons
- End-to-end workflow: Planning → Execution → Analysis → Report → Handoff
- Performance + Security: Parallel evaluation, combined reporting
- Automation: DefectDojo, Jira integration, automated report generation
- Deliverables: PDF reports, dashboards, remediation tickets, retest plan
This is the last post of the series. Wishing you success on your Security & Performance Engineering journey!