Skip to the content.

Writing the first actions

Each action is defined by a name and a subtype. A subtype defines what the action is able to do: For example “HTTP request” is a subtype that allows to send an HTTP request and inspect responses.

Let’s start building our fingerprinting step with a very simple action:

actions: {
  name: "fingerprinting"
  http_request: {
    method: GET
    uri: "/version"
  }
}

In that action, named fingerprinting we simply send a GET HTTP request to /version on the currently targeted service.

Note that Tsunami will only send HTTP requests to services that have been identified as HTTP services during the port scanning phase.

But that action will always succeed because it does not verify anything in the response. Let’s use the response field and add a condition on the status code:

actions: {
  name: "fingerprinting"
  http_request: {
    method: GET
    uri: "/version"
    response: {
      http_status: 200
    }
  }
}

Now we want to ensure the header contains MyVulnerableApp: we need to use expectations. We can either use expect_all or expect_any, which perform checks on the response that must respectively “all be true” or “at least one true”. Here, we have only one expectation, so we will use expect_all with one conditions:

actions: {
  name: "fingerprinting"
  http_request: {
    method: GET
    uri: "/version"
    response: {
      http_status: 200
      expect_all: {
        conditions: [
          { header: { name: "Server" } contains: "MyVulnerableApp" }
        ]
      }
    }
  }
}

The condition is that the header with name Server contains the string MyVulnerableApp.

Now, let’s build a POST request for our exploitation step:

actions: {
  name: "exploitation"
  http_request: {
    method: POST
    uri: "/exploit"
    data: "process=%{ print(\"tsunami_%d_marker\", 1250*1+3) }%"
    response: {
      http_status: 200
      expect_all: {
        conditions: [
          { body: {} contains: "tsunami_1253_marker" }
        ]
      }
    }
  }
}

This action is very similar to the previous one but:

Redirects

Note that by default, the HTTP client will follow any HTTP redirects. If you wish to change that behavior, you can configure your HTTP request using the client_options stanza. For example, with our previous request:

actions: {
  name: "exploitation"
  http_request: {
    method: POST
    uri: "/exploit"
    data: "process=%{ print(\"tsunami_%d_marker\", 1250*1+3) }%"
    client_options: {
      disable_follow_redirects: true
    }
    response: {
      http_status: 200
      expect_all: {
        conditions: [
          { body: {} contains: "tsunami_1253_marker" }
        ]
      }
    }
  }
}

What is next

Putting it together in workflows