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:
- It sends a
POSTrequest instead of aGETone; - As part of the
POSTit sendsprocess=%{ print(\"tsunami_%d_marker\", 1250*1+3) }%as data; - The expectation has been changed to check that the response body
contains
tsunami_1253_marker.
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" }
]
}
}
}
}