-
Notifications
You must be signed in to change notification settings - Fork 0
3. Configuration Guide
This guide explains how to create FlawFactory configuration files. The configuration is written in YAML and controls everything about your vulnerable application.
Every FlawFactory configuration file has this structure:
app: # Required - Application settings
name: "My App"
port: 8080
data: # Optional - Database tables and seed data
tables:
...
files: # Optional - Files to create
...
endpoints: # Required - HTTP endpoints with vulnerabilities
...The app section defines your application's global settings.
| Fields | Required | Description |
|---|---|---|
name |
true | Application name (displayed in logs) |
port |
true | Port to listen on (1-65535) |
description |
false | Application description |
host |
false | Bind address (default: 127.0.0.1) |
tls |
false | HTTPS configuration |
EXAMPLE
app:
name: "My Lab" # Application name
description: "Testing environment for security tools" # Description
port: 8080 # Port to listen on
host: "0.0.0.0" # Bind address
tls: # HTTPS configuration
enabled: true
auto_generate: true # Generate self-signed certificateFlawFactory supports auto generated self signed certificates as well as custom ones.
1. Auto-generated self-signed certificate
app:
name: "Secure Lab"
port: 8443
tls:
enabled: true
auto_generate: true2. Custom certificates
app:
name: "Secure Lab"
port: 8443
tls:
enabled: true
cert_file: "/path/to/cert.pem"
key_file: "/path/to/key.pem"The data section defines database tables that will be created in an in-memory SQLite database. All columns are created as TEXT type. The values provided are stored as-is (no type conversion). Additionally, the tables are created fresh on each startup.
1. Basic Table Definition
data:
tables:
TABLE_NAME:
columns: [COLUMN_1, COLUMN_2, COLUMN_3, COLUMN_4]
rows:
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]For example, the following configuration creates a "users" table with 4 columns (id, username, password, email) and 2 rows.
data:
tables:
users: # Table name
columns: [id, username, password, email] # Column names
rows: # Data rows
- [1, "admin", "secret123", "admin@example.com"]
- [2, "user", "password", "user@example.com"]2. Multi Table Definition
data:
tables:
TABLE1_NAME:
columns: [COLUMN_1, COLUMN_2, COLUMN_3, COLUMN_4]
rows:
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
TABLE2_NAME:
columns: [COLUMN_1, COLUMN_2, COLUMN_3, COLUMN_4]
rows:
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
TABLE3_NAME:
columns: [COLUMN_1, COLUMN_2, COLUMN_3, COLUMN_4]
rows:
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]
- [COL1_ENTRY, COL2_ENTRY, COL3_ENTRY, COL4_ENTRY]For example, the following configuration creates 3 tables( users, products and orders ) with different columns and rows
data:
tables:
users:
columns: [id, username, password, role]
rows:
- [1, "admin", "supersecret", "administrator"]
- [2, "john", "password123", "user"]
- [3, "jane", "jane2024", "user"]
products:
columns: [id, name, price, category]
rows:
- [1, "Laptop", "999.99", "electronics"]
- [2, "Mouse", "29.99", "electronics"]
- [3, "Book", "19.99", "books"]
orders:
columns: [id, user_id, product_id, quantity]
rows:
- [1, 1, 1, 1]
- [2, 2, 2, 3]The files section defines files that will be created in a temporary directory.
Note: FlawFactory also creates default sensitive files automatically:
-
etc/passwd- Simulated passwd file -
etc/shadow- Simulated shadow file -
app/config.ini- Configuration with credentials -
app/.env- Environment variables -
var/log/app.log- Application log
1. Basic File Definition
files:
- path: "PATH_TO_FILE"
content: "FILE_CONTENT"
- path: "PATH_TO_FILE"
content: |
MULTI
LINE
CONTENTHere's an example where the application creates a secret.txt file inside a documents folder, a log file inside logs and a database.ini file inside config directory.
files:
- path: "documents/secret.txt"
content: "This is a secret file!"
- path: "config/database.ini"
content: |
[database]
host=localhost
password=db_secret_password
- path: "logs/access.log"
content: |
192.168.1.100 - - [15/Jan/2024:10:30:45] "GET /admin HTTP/1.1" 200
192.168.1.101 - - [15/Jan/2024:10:31:00] "POST /login HTTP/1.1" 302
192.168.1.102 - - [15/Jan/2024:10:32:15] "GET /api/users HTTP/1.1" 200Endpoints define your HTTP routes and their vulnerabilities. This is where most configuration happens.
endpoints:
- path: URL_PATH
method: HTTP_METHOD
response_type: RESPONSE_FORMAT
vulnerabilities:
- type: VULNERABILITY_NAME
placement: VULNERABILE_POINT
param: VULNERABLE_PARAMETER
config: # module specific configHere's an example endpoint that is vulnerable to SQL injection in the id query parameter:
endpoints:
- path: /api/users # URL path
method: GET # HTTP method
response_type: json # Response format
vulnerabilities: # List of vulnerabilities
- type: sql_injection
placement: query_param
param: id
config:
query_template: "SELECT * FROM users WHERE id = {input}"| Field | Required | Description |
|---|---|---|
path |
Yes | URL path (must start with /) |
method |
Yes | HTTP method: GET, POST, PUT, DELETE, PATCH
|
response_type |
No | Output format: json, html, xml, text (default: json) |
vulnerabilities |
Yes | List of vulnerability configurations |
note: use {param} syntax for dynamic path segmentation. For example:
endpoints:
- path: /user/{id}
method: GET
vulnerabilities:
- type: sql_injection
placement: path_param # Extract from URL path
param: id # Must match {id} in path
config:
query_template: "SELECT * FROM users WHERE id = {input}"We can have multiple vulnerabilities configured on 1 endpoint.
endpoints:
- path: URI_PATH
method: HTTP_METHOD
vulnerabilities:
- type: VULN1
placement: ...
param: ...
config:
# config related to vuln1
- type: VULN2
placement: ...
param: ...
config:
# config related to vuln2For example:
endpoints:
- path: /api/data
method: POST
vulnerabilities:
- type: sql_injection
placement: json_field
param: user_id
config:
query_template: "SELECT * FROM users WHERE id = {input}"
- type: xss_reflected
placement: json_field
param: name
config:
context: bodyWhen multiple vulnerabilities are on one endpoint, results are combined in the response. Each vulnerability has these fields:
| Field | Required | Description |
|---|---|---|
type |
Yes | Module name (e.g., sql_injection) |
placement |
Yes | Where to extract input |
param |
Yes | Parameter name |
config |
No | Module-specific settings |
The following modules exist and can be used to define a vulnerability.
| Type | Module | Docs |
|---|---|---|
sql_injection |
SQL Injection | SQL-Injection |
xss_reflected |
Cross-Site Scripting | Cross-Site-Scripting |
path_traversal |
Directory Traversal | Path-Traversal |
command_injection |
OS Command Injection | Command-Injection |
idor |
Insecure Direct Object Reference | Insecure-Direct-Object-Reference |
ssrf |
Server-Side Request Forgery | Server-Side-Request-Forgery |
xxe |
XML External Entity | XML-External-Entity |
nosql_injection |
NoSQL Injection | No-SQL-Injection |
insecure_deserialization |
Object Deserialization | Deserialization |
| Placement | Description | Example |
|---|---|---|
query_param |
URL query string | ?id=1 |
path_param |
URL path segment |
/user/{id} → /user/1
|
form_field |
URL-encoded POST body | username=admin |
json_field |
JSON body field | {"id": 1} |
header |
HTTP header | X-User-Id: 1 |
cookie |
Cookie value | Cookie: session=abc |
multipart-form |
Multipart form data | File uploads |
For nested json, you can use dot notations:
# For JSON body: {"user": {"profile": {"id": 123}}}
vulnerabilities:
- type: sql_injection
placement: json_field
param: user.profile.id # Accesses nested field
Each module accepts different config options. Each module has its own section that covers this in detail.
-
SQL-Injection → Configure database type (
sqlite/mysql/postgresql), query templates with{input}placeholders, and error verbosity for injection simulation. -
XSS Reflected → Define HTML context (
html_body,attribute,script,url), output encoding, and response content type for reflected input handling. - Path-Traversal → Set base directory, allowed extensions, path normalization behavior, and whether symbolic links are followed.
-
Command-Injection → Specify shell type (
bash/cmd/powershell), command templates, argument injection points, and execution mode (real/emulated). - SSRF → Configure allowed/blocked URL schemes, internal IP blocking, DNS rebinding protection, and redirect following behavior.
- XXE → Set XML parser features, external entity resolution, DTD processing options, and whether to return parsed content or errors.
-
NoSQL Injection → Define database type (
mongodb/redis), collection name, operation type (find/aggregate/get), and query templates. - IDOR → Configure resource type, ID parameter format, authorization bypass simulation, and which "sensitive" records are accessible.
-
Insecure Deserialization → Specify serialization format (
json/pickle/java/php), gadget chain simulation, and object instantiation behavior.
Here's a comprehensive example with multiple features:
app:
name: "Complete Security Lab"
description: "Multi-vulnerability testing environment"
port: 8080
tls:
enabled: true
auto_generate: true
data:
tables:
users:
columns: [id, username, password, email, role, ssn]
rows:
- [1, "admin", "admin123", "admin@corp.local", "admin", "123-45-6789"]
- [2, "john.doe", "password1", "john@corp.local", "user", "234-56-7890"]
- [3, "jane.smith", "qwerty", "jane@corp.local", "user", "345-67-8901"]
secrets:
columns: [id, key_name, key_value]
rows:
- [1, "api_key", "sk_live_abc123"]
- [2, "db_password", "supersecret"]
files:
- path: "config/secrets.yml"
content: |
api_keys:
stripe: sk_live_xxx
sendgrid: SG.yyy
database:
password: prod_db_pass
- path: "data/users.csv"
content: |
id,name,email,ssn
1,John Doe,john@example.com,123-45-6789
2,Jane Smith,jane@example.com,234-56-7890
endpoints:
# SQL Injection via query parameter
- path: /api/users
method: GET
response_type: json
vulnerabilities:
- type: sql_injection
placement: query_param
param: id
config:
variant: error_based
query_template: "SELECT * FROM users WHERE id = {input}"
show_errors: true
# XSS in search results
- path: /search
method: GET
response_type: html
vulnerabilities:
- type: xss_reflected
placement: query_param
param: q
config:
context: body
encoding: none
# Command injection in ping utility
- path: /api/ping
method: POST
vulnerabilities:
- type: command_injection
placement: json_field
param: host
config:
base_command: "ping -c 1 {input}"
filter: none
# Path traversal file download
- path: /download
method: GET
response_type: text
vulnerabilities:
- type: path_traversal
placement: query_param
param: file
config:
base_path: "data"
filter: none
# SSRF via URL fetch
- path: /fetch
method: GET
vulnerabilities:
- type: ssrf
placement: query_param
param: url
config:
filter: none
return_body: true
# IDOR to access other users
- path: /api/profile/{id}
method: GET
vulnerabilities:
- type: idor
placement: path_param
param: id
config:
variant: numeric
query_template: "SELECT * FROM users WHERE id = {input}"
access_control: noneIt is recommended to always validate your configuration files before running them:
flawfactory validate -c CONFIG.yamlThis checks:
- Required fields are present
- Values are in valid ranges
- HTTP methods are valid
- Placements are supported
- No duplicate endpoints
- modules specific configs are valid