An automated deployment of a web stack with WAF, SOC monitoring and kill chain simulation.
- DevSecOps-Web Lab
This lab deploys a complete intentionnaly vulnerable web infrastructure 100% locally with Podman, behind a WAF (ModSecurity + OWASP CRS), supervised by a Grafana/Loki stack, and tested by attack simulations covering OWASP Top 10 2025.
Objective: This project was built to demonstrate the ability to deploy, configure, attack, detect and remediate web security incidents in a containerized environment.
- Complete IaC: With
Terraform + Ansible, everything is versioned and reproducible - Production WAF: 846 OWASP CRS rules, effective blocking
- MySQL Hardening: Password policy, SSL/TLS, least privilege
- SOC Monitoring: Grafana dashboard with real-time LogQL queries
- Realistic Kill Chain: Reconnaissance β SQLi β XSS β Path Traversal
- Secret Management: Sensitive variables encrypted with Ansible Vault
- Documented Troubleshooting: 12 real problems with Root Cause Analysis
- Documented attacks: all atacks are all documented on the way they were done and what was seen.
Here is a very simplified version of the architecture but it explains briefly well the data flow between all the components of the projects.
The detailed diagram with explanation about the small parts, data flow and role of every component can be found at docs/architecture.md
| Domain | Technology | Version |
|---|---|---|
| Infrastructure as Code | Terraform + Docker Provider | ~> 3.0 |
| Configuration Management | Ansible + Ansible Vault | Latest |
| Containerization | Podman (rootless) | Latest |
| Target Application | OWASP Juice Shop | latest |
| WAF | Nginx + ModSecurity 3 + OWASP CRS | 1.30.1 / 3.0.15 |
| Database | MySQL 8.0 | 8.0 |
| Monitoring | Grafana + Loki + Alloy | 13.0.2 / latest |
| Attack Simulation | SQLMap + Nmap | Latest |
- Linux (tested on Fedora / Debian / Arch)
- Podman (or Docker) with socket enabled
- Terraform β₯ 1.5
- Ansible β₯ 2.15
- Kali VM ready to go
Automated installation: If one or nothing of these ones are installed you can run
make installand everything will be setup correctly
# 1. Provision infrastructure (5 containers)
terraform -chdir=terraform apply
# 2. Configure WAF + DB + Monitoring
ansible-playbook ansible/playbooks/site.yml --ask-vault-pass
# 3. Verify everything is running
podman ps| Service | URL | Credentials |
|---|---|---|
| WAF (Juice Shop) | http://localhost:8080 | β |
| Grafana | http://localhost:3001 | admin / as-you-go |
| Loki | http://localhost:3100 | β (API) |
cd attack_simulation && bash simulate_killchain.shThe script executes 5 phases covering the OWASP Top 10 2025:
| Phase | OWASP 2025 Category | Technique | Expected Result |
|---|---|---|---|
| Reconnaissance | A02 Security Misconfiguration | Scan for sensitive paths | 403 on /phpinfo.php, /.git |
| SQL Injection | A05 Injection | OR 1=1, UNION SELECT, DROP TABLE | 403 blocked |
| XSS | A05 Injection | Script alert, encoded version | 403 blocked |
| Path Traversal | A01 Broken Access Control | /../../etc/passwd | 200 (normalized path) |
| False Positive | WAF Tuning | O'Reilly search | 500 (app error) |
[PHASE 1] Reconnaissance (A02 Security Misconfiguration)
/phpinfo.php β HTTP 403 β server information protected
/.git/config β HTTP 403 β exposed repository protected
[PHASE 2] SQL Injection (A05 Injection)
Payload : OR 1=1 β HTTP 403 β WAF blocks
[PHASE 3] Cross-Site Scripting (XSS) (A05 Injection)
Payload : script alert β HTTP 403 β WAF blocks
A Security Overview dashboard with 3 panels is pre-configured:
- WAF Log Volume β time series of all requests
- Blocked Requests (403) β time series of blocks (in red)
- Top Attacked URIs β horizontal bar chart of most-targeted endpoints
# Total log volume
count_over_time({job="waf"} [$__interval])
# Blocked requests
count_over_time({job="waf"} |= "403" [$__interval])
# Top attacked URIs (ranking)
topk(10, sum by (uri) (count_over_time({job="waf"} |= "403" | json | __error__="" [$__interval])))
WAF (Nginx logs JSON) β waf-logs volume β Promtail β Loki β Grafana
devsecops-web-lab/
β
βββ terraform/ # Infrastructure as Code
β βββ main.tf # 5 containers, network, volumes
β βββ variables.tf # Sensitive variables
β βββ outputs.tf # Output URLs
β βββ grafana_provisioning/ # Grafana provisioning (IaC)
β βββ datasources/loki.yml
β βββ dashboards/
β βββ dashboard_provider.yml
β βββ security_overview.json
β
βββ ansible/ # Configuration Management
β βββ ansible.cfg
β βββ inventory.ini
β βββ playbooks/
β β βββ site.yml # Master playbook
β β βββ setup-python.yml # Python bootstrap
β β βββ waf-setup.yml # Nginx + ModSecurity + Promtail
β β βββ db-hardening.yml # MySQL hardening
β β βββ monitoring.yml # Pipeline verification
β βββ files/
β β βββ waf/ # WAF config (Nginx, ModSecurity)
β β βββ promtail/ # Promtail config
β βββ group_vars/all/
β βββ vars.yml # Normal variables
β βββ vault.yml # Encrypted variables
β
βββ attack_simulation/
β βββ simulate_killchain.sh # Automated kill chain
β
βββ grafana/dashboards/
β βββ security-dashboard.json # Exported dashboard
β
βββ docs/
β βββ architecture.md # Architecture diagram and details
β βββ incident-report.md # SOC incident report
β βββ ISSUES.md # Troubleshooting (12 problems)
β βββ Resources.md # Documentation and references
β βββ evidences/bunch/ # Screenshots
β βββ Sqli-bloque.png
β βββ Containers.png
β βββ pipeline-valide.png
β βββ ...
β
βββ tests.sh # Dependency installation script
βββ README.md # This page
12 documented incidents in docs/ISSUES.md with root cause analysis:
| # | Problem | Solution |
|---|---|---|
| 1 | Permission denied logs WAF | Bind mount β Named Docker volume |
| 2 | Connection reset by peer | Internal port 80 β 8080 |
| 3 | Python missing from containers | Bootstrap with raw module |
| 4 | Nginx syntax error (backslash) | Remove escape character |
| 5 | Unknown ModSecurity variable | Remove proprietary log_format |
| 6 | pkill/pgrep not found | Install procps |
| 7 | Logs symlinked to /dev/stdout | Replace with real files |
| 8 | Incorrect MySQL vault password | Align Terraform/Ansible |
| 9 | audit_log plugin missing (Community) | Alternative validate_password |
| 10 | Secrets exposed via podman inspect | Document best practices |
| 11 | Grafana provisioning failed | Manual datasource configuration |
| 12 | WAF blocks nothing (200 instead of 403) | SecRuleEngine On + SecDefaultAction deny |
Feel free to update this if you encounter any problem.
| Document | Description |
|---|---|
| docs/architecture.md | Architecture diagram and data flow |
| docs/incident-report.md | SOC incident report (kill chain + remediation) |
| docs/ISSUES.md | Detailed troubleshooting (12 entries) |
| docs/Resources.md | Sources, documentation and references |
- CI/CD pipeline integration (GitHub Actions) for automatic apply
- Container image vulnerability scanning with Trivy
- Advanced CRS exclusion rules for false positives
- Grafana alerting via email/Slack on blocking spikes
MIT - see LICENSE file.
Project completed as part of a DevSecOps / SOC Analyst learning and skill demonstration initiative.



