facebookincubator / TTPForge

The TTPForge is a Cybersecurity Framework for developing, automating, and executing attacker Tactics, Techniques, and Procedures (TTPs).
MIT License
335 stars 32 forks source link

🚨 [BUG] - by default powershell steps tolerate errors #517

Open inesusvet opened 3 hours ago

inesusvet commented 3 hours ago

What happened?

Consider the following (broken) TTP

$ cat broken.yaml
name: test broken powershell script
steps:
  - name: broken
    executor: pwsh
    inline: |
      foo  # should fail
      exit 0

When this file is processed by ttpforge, it declares success

$ go run main.go run broken.yaml
WARN    No config file specified and default configuration file not found!
WARN    You probably want to run `ttpforge init`!
WARN    However, if you know what you are doing, then carry on :)
INFO    RUNNING TTP: test broken powershell script
INFO    ----------------------------------------
INFO    Executing Step #1: "broken"
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDERR] foo: The term 'foo' is not recognized as a name of a cmdlet, function, script file, or executable program.
INFO    [STDERR] Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
INFO    ----------------------------------------
INFO    All TTP steps completed successfully! ✅
INFO    ========================================
INFO    CLEANING UP 1 steps of TTP: "test broken powershell script"
INFO    ----------------------------------------
INFO    Cleaning Up Step #1: "broken"
INFO    No Cleanup Action Defined for Step broken
INFO    ----------------------------------------
INFO    Finished Cleanup Successfully ✅

Any suggestions for fixing this bug?

We should consider failure to execute even ONE LINE in the powershell script as failure of the whole step. Similar as we did for bash executor in #406

Relevant log output

No response

Details about your environment

No response

inesusvet commented 3 hours ago

Looks like this might be resolved by changing the $ErrorActionPreference variable (link) to "Stop" value

let's modify the TTP file

$ cat broken.yaml
name: test broken powershell script
steps:
  - name: broken
    executor: pwsh
    inline: |
      $ErrorActionPreference = 'Stop'
      foo  # should fail
      exit 0

After check it fails as expected

$ go run main.go run broken.yaml
WARN    No config file specified and default configuration file not found!
WARN    You probably want to run `ttpforge init`!
WARN    However, if you know what you are doing, then carry on :)
INFO    RUNNING TTP: test broken powershell script
INFO    ----------------------------------------
INFO    Executing Step #1: "broken"
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDOUT]
INFO    [STDERR] foo:
INFO    [STDERR] Line |
INFO    [STDERR]    2 |  foo  # should fail
INFO    [STDERR]      |  ~~~
INFO    [STDERR]      | The term 'foo' is not recognized as a name of a cmdlet, function, script file, or executable program.
INFO    [STDERR] Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
INFO    [STDOUT]
ERROR   Failed to execute step broken: exit status 1
INFO    ----------------------------------------
ERROR   [*] Error executing TTP: exit status 1
INFO    ========================================
INFO    CLEANING UP 0 steps of TTP: "test broken powershell script"
INFO    ----------------------------------------
INFO    Finished Cleanup Successfully ✅
ERROR   failed to run command:
        failed to run TTP at /Users/nesusvet/dev/ttpforge/broken.yaml: <nil>
exit status 1