TTPForge Documentation

repository·main·Indexed 19 days ago

https://github.com/facebookincubator/ttpforge

A cyber attack simulation platform used to automate attacker tactics, techniques, and procedures (TTPs) using a YAML-based format. TTPForge allows red teams to automate repeatable attack simulations and blue teams to measure detection capabilities. It includes a CLI for managing TTP repositories, running simulations with dynamic arguments, and generating TTP resources and UUIDs.

Tokens
25.7K
Snippets
111
Records
135
Agent score
61%

What's inside TTPForge

  1. Use the Platform object for cross-platform TTPs

    main

    TTPForge provides a Platform struct that allows you to write platform-agnostic TTPs. You can access the current execution environment using:

    • .Platform.OS: The operating system (e.g., windows, linux, darwin).
    • .Platform.Arch: The architecture of the platform.

    Example of platform-specific commands and dynamic file naming:

    steps:
      - name: hello_world
        inline: |
          {{ if eq .Platform.OS "windows" }}
            Write-Host "Hello Windows!"
          {{ else if eq .Platform.OS "linux" }}
            echo "Hello Linux!"
          {{ else if eq .Platform.OS "darwin" }}
            echo "Hello macOS!"
          {{ end }}
      - name: download_ttpforge
        fetch_uri: https://github.com/facebookincubator/TTPForge/releases/
        download/v1.2.3/TTPForge_1.2.3_{{ .Platform.OS }}_{{ .Platform.Arch }}.tar.gz
        location: ttpforge.tar.gz
    requirements:
      platforms:
        - os: linux
        - os: darwin
        - os: windows
    steps:
      - name: hello_world
        inline: |
          {{ if eq .Platform.OS "windows" }}
            Write-Host "Hello Windows!"
          {{ else if eq .Platform.OS "linux" }}
            echo "Hello Linux!"
          {{ else if eq .Platform.OS "darwin" }}
            echo "Hello macOS!"
          {{ end }}
      - name: download_ttpforge
        description: Downloads the platform-appropriate release of TTPForge
        fetch_uri: https://github.com/facebookincubator/TTPForge/releases/
        download/v1.2.3/TTPForge_1.2.3_{{ .Platform.OS }}_{{ .Platform.Arch }}.tar.gz
        location: ttpforge.tar.gz
  2. Understand destination placement for repository references

    main

    When using the repository reference format (repo//path) for a destination, the TTP is placed in the first path defined in that repository's ttpforge-repo-config.yaml file.

    Example: If your ttpforge-repo-config.yaml defines:

    ttp_search_paths:
      - ttps
      - templates
      - examples

    A move command targeting myrepo//basic.yaml will actually place the file at <repo_root>/ttps/basic.yaml.

  3. What are TTPForge Checks and why use them?

    main

    Checks allow TTP (Tactics, Techniques, and Procedures) authors to verify that their steps executed correctly and were not silently blocked by security tools like EDR/AV software.

    They provide confidence by verifying:

    1. File existence: Ensuring files were actually created on disk.
    2. Command output: Verifying services are running or processes exist.
    3. Step output: Inspecting the stdout/stderr of the step itself without re-running commands.
    4. Exit codes: Detecting when operations fail silently.
    5. Content integrity: Ensuring files weren't modified or corrupted.
  4. Write tests for TTPs using the `tests:` section

    main

    You can define automated tests directly within your TTPForge YAML file using the tests: section. These tests serve two primary functions:

    1. Validated Documentation: They provide a continuously-validated example of how users should execute your TTP.
    2. Compatibility Assurance: They ensure the TTPForge engine remains compatible with your TTP, providing warnings if compatibility is broken.

    By declaring a test case, you explicitly signal to TTPForge that your TTP is safe to be run as an automated test.

  5. How TTPForge cleanup actions work

    main

    TTPForge provides native support for cleaning up destructive or messy actions (like editing system files or launching cloud resources) to prevent security vulnerabilities or system inconvenience.

    Core Mechanics:

    1. Queueing: Every time a step completes successfully, its associated cleanup action is added to a cleanup queue.
    2. Optionality: Steps do not require a cleanup action; if none is defined, nothing is added to the queue for that step.
    3. Execution Order: Once the TTP completes (or a step fails), TTPForge executes the actions in the queue in reverse order (Last-In, First-Out). This ensures that dependencies are respected (e.g., cleaning up a kernel module before removing the user privileges used to load it).
    4. Failure Behavior: If a step fails, cleanup begins from the last successful step. The failed step itself is not cleaned up to avoid errors (e.g., trying to delete a file that failed to be created). If any cleanup action in the queue fails, all subsequent cleanup actions are abandoned to prevent accidental damage.
    steps:
      - name: step-one
        action: ...
        cleanup: ...
      - name: step-two
        action: ...
        cleanup: ...
    # Cleanup runs: step-two's cleanup, then step-one's cleanup
  6. Use pipelines to chain template functions

    main

    Pipelines allow you to chain multiple functions together using the | operator. When using a pipeline, the output of the preceding function is passed as the last parameter to the subsequent function.

    Note: If a function takes arguments, the piped value is appended to the end of the argument list. Example: {{ randBytes 16 | cat "Random Bytes:" }} results in cat receiving "Random Bytes:" as the first argument and the 16 random bytes as the second.

    Example of path manipulation and encoding:

    steps:
      - name: create_result_dir
        inline: |
          mkdir {{ osDir .Args.input_file | printf "%q/results" }}
      - name: generate_rand_file
        inline: |
          echo "{{ randBytes 1024 | b64enc }}" > rand.txt
    args:
      - name: input_file
        type: path
    steps:
      - name: create_result_dir
        description: Uses the path functions and pipelines to manipulate path arguments
        inline: |
          mkdir {{ osDir .Args.input_file | printf "%q/results" }}
          cd {{ osDir .Args.input_file | printf "%q/results" }}
      - name: generate_rand_file
        description: Generate a random base64-encoded file of a given size
        inline: |
          echo "{{ randBytes 1024 | b64enc }}" > rand.txt
  7. Access TTPForge arguments in templates

    main

    TTPForge uses Golang's template package to preprocess forges. You can access values defined in the args section of your TTP by using the syntax {{ .Args.arg_name }}. This allows you to inject dynamic runtime values into your steps.

    Example usage:

    args:
      - name: name
        default: Bob
      - name: age
        type: int
        default: 25
    steps:
      - name: print_name
        print_str: |
          My name is: {{.Args.name}}
      - name: birthday
        print_str: |
          Today, I am {{add .Args.age 1}}
    args:
      - name: name
        description: This argument is of default type `string`
        default: Bob
      - name: age
        type: int
        default: 25
    steps:
      - name: print_name
        print_str: |
          My name is: {{.Args.name}}
      - name: birthday
        print_str: |
          Today, I am {{add .Args.age 1}}
  8. Understand the TTPForge Global Configuration File

    main

    TTPForge tracks installed repositories in a global configuration file, located by default at ~/.ttpforge/config.yaml.

    This file contains a repos list where each entry includes:

    • name: The identifier for the repository.
    • path: A relative path (relative to the config file location) or an absolute path to the repository files on disk.
    • git: An object containing the url used to clone the repository.

    Example structure:

    ---
    repos:
      - name: examples
        path: repos/examples
        git:
          url: https://github.com/facebookincubator/TTPForge
    ---
    repos:
      - name: examples
        path: repos/examples
        git:
          url: https://github.com/facebookincubator/TTPForge
      - name: forgearmory
        path: repos/forgearmory
        git:
          url: https://github.com/facebookincubator/forgearmory
  9. Use the `path` argument type for file paths

    main

    Use type: path for arguments representing file system paths. TTPForge automatically performs the following:

    • Absolute Resolution: Resolves paths to absolute paths and resolves symlinks.
    • Variable Expansion: Expands environment variables like $HOME, ${USER}, and the tilde ~.

    Resolution Rules for Relative Paths:

    • Default values (in YAML): Resolved relative to the directory where the TTP file is located.
    • CLI arguments: Resolved relative to the current working directory where you execute the ttpforge command.
    args:
      - name: config_file
        type: path
        default: ./config.yaml        # Relative to TTP directory
      - name: output_dir
        type: path
        default: $HOME/output         # Variable expansion
  10. How cleanup works in TTP chains

    main

    Cleanup behavior is automatically managed for TTP chains. TTPForge injects a special cleanup action into every ttp: step. This injected action executes the cleanup actions defined within the referenced sub-TTP file.

    Failure Handling: If a step within a sub-TTP fails, the cleanup process will automatically begin executing the sub-TTP's cleanup actions starting from the last successfully completed step of that sub-TTP.

  11. How to chain TTPs together

    main

    TTPForge allows you to create composite TTPs by chaining multiple existing TTPs using the ttp: action. This enables the simulation of multi-stage cyberattacks and promotes code reuse by combining shared steps. When a ttp: action is invoked, the steps of the referenced sub-TTP are executed in sequence. You can chain as many TTPs as needed in a single sequence.

    # Example of a composite TTP using the ttp: action
    - name: composite-attack
      steps:
        - action: ttp:
            path: //path/to/sub-ttp-1.yaml
        - action: ttp:
            path: //path/to/sub-ttp-2.yaml
  12. Configure cleanup for remote execution

    main

    When using the remote: field to execute steps on a different host, the behavior of the cleanup block depends on how it is defined:

    1. cleanup: default: Inherits the remote: configuration from the parent step. The cleanup runs on the same remote host as the action.
    2. Custom Cleanup (YAML mapping): Runs locally by default. To force a custom cleanup to run on the remote host, you must explicitly include the remote: key inside the cleanup block.

    Example Configuration:

    steps:
      - name: drop-payload
        remote: target
        create_file: /tmp/payload.sh
        contents: echo "hello"
        cleanup: default              # runs on remote (inherits step's remote:)
    
      - name: run-payload
        remote: target
        inline: /tmp/payload.sh
        cleanup:
          remote: target              # explicit: cleanup runs on remote
          inline: rm -f /tmp/payload.sh
    
      - name: exfil
        remote: target
        inline: cat /etc/passwd
        cleanup:
          inline: rm -f /tmp/local-evidence.log   # no remote: → cleanup runs locally