Skip to content

3. Configuration Guide

Moiz Bootwala edited this page Jan 19, 2026 · 12 revisions

This guide explains how to create FlawFactory configuration files. The configuration is written in YAML and controls everything about your vulnerable application.

Basic Structure

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
  ...

app

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 certificate

TLS Configuration

FlawFactory 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: true

2. Custom certificates

app:
  name: "Secure Lab"
  port: 8443
  tls:
    enabled: true
    cert_file: "/path/to/cert.pem"
    key_file: "/path/to/key.pem"

data

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]

files

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
      CONTENT

Here'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" 200

endpoints

Endpoints 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 config

Here'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 vuln2

For 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: body

When 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

Supported type

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

Supported placement

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

Module Specific Configuration

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.

Example

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: none

Validating Configs

It is recommended to always validate your configuration files before running them:

flawfactory validate -c CONFIG.yaml

This 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

Clone this wiki locally