Flows

Flows are the main concept in Raider, used to define the HTTP information exchange. Each request you want to send needs its own Flow object. Inside the request attribute of the object, needs to be a Request object containing the definition of the request.

This definition can contain Plugins whose value will be used when sending the HTTP Request. In this case, the Plugins will act as inputs.

When using Plugins in the outputs attribute, they will act as outputs, and the value will be extracted for later use.

Flow class holding the information exchanged between server and client.

class Flow(request, outputs=None, operations=None)[source]

Class dealing with the information exchange from HTTP communication.

A Flow object in Raider defines all the information about one single HTTP information exchange. It contains one request, the response, the outputs that needs to be extracted from the response, and a list of operations to be run when the exchange is over.

Use this only when working with requests that DON’t change the authentication state. It’s used in the Functions class to run arbitrary actions when it doesn’t affect the authentication state.

request

A Request object detailing the HTTP request with its elements.

response

A requests.model.Response object. It’s empty until the request is sent. When the HTTP response arrives, it’s stored here.

outputs

A list of Plugin objects detailing the pieces of information to be extracted from the response. Those will be later available for other Flow objects.

operations

A list of Operation objects to be executed after the response is received and outputs are extracted. Should contain a Next operation if another Flow is expected.

__init__(request, outputs=None, operations=None)[source]

Initializes the Flow object.

Creates the Flow object with the associated Request, the outputs to be extracted, and the operations to be run upon completion.

Parameters
  • request (Request) – A Request object associated with this Flow.

  • outputs (Optional[List[Plugin]]) – A list of Plugins to be used for extracting data from the response.

  • operations (Optional[List[Operation]]) – A list of Operations to be run after the response is received.

print(spacing=0)[source]
Return type

None

execute(pconfig)[source]

Sends the request and extracts the outputs.

Given the user in context and the global Raider configuration, sends the HTTP request and extracts the defined outputs.

Iterates through the defined outputs in the Flow object, and extracts the data from the HTTP response, saving it in the respective Plugin object.

Parameters
  • user – An object containing all the user specific data relevant for this action.

  • config – The global Raider configuration.

Return type

None

run_operations()[source]

Runs the defined operations.

Iterates through the defined operations and executes them one by one. Iteration stops when the first Next operations is encountered.

Return type

Optional[str]

Returns

A string with the name of the next flow to run or None.

property logger

Examples

Create the variable initialization with the Flow. It’ll send a GET request to https://example.com/admin/. If the HTTP response code is 200 go to next stage login.

(setv initialization
      (Flow
        (Request.get
          "https://example.com/admin/")
        :operations [(Http
                       :status 200
                       :action (Next "login"))]))

Define Flow login. It will send a POST request to https://example.com/admin/login with the username and the password in the body. Extract the cookie PHPSESSID and store it in the session_id plugin. If server responds with HTTP 200 OK, print login successfully, otherwise quit with the error message login error.

(setv username (Variable "username"))
(setv password (Variable "password"))
(setv session_id (Cookie "PHPSESSID"))

(setv login
      (Flow
        (Request.post
           "https://www.example.com/admin/login"
           :data
           {"password" password
           "username" username})
        :outputs [session_id]
        :operations [(Http
                       :status 200
                       :action (Print "login successfully")
                       :otherwise (Error "login error"))]))

Define another login Flow. Here what’s different is the csrf_name and csrf_value plugins. In this application both the name and the value of the token needs to be extracted, since they change all the time. They were defined as Html objects. Later they’re being used in the body of the Request.

If the HTTP response code is 200 means the MFA was enabled and the multi_factor stage needs to run next. Otherwise, try to log in again. Here the password is asked from the user by a Prompt.

;; Gets `username` from active user's object defined in `users`.
(setv username (Variable "username"))

;; Gets the password by manual input.
(setv password (Prompt "password"))

;; Gets `PHPSESSID` from the cookie.
(setv session_id (Cookie "PHPSESSID"))

;; Gets the OTP code by manual input.
(setv mfa_code (Prompt "OTP code"))

;; Extract nickname from the HTML code. It looks for a tag like this:
;; <input id="nickname" value="admin">
;; and returns `admin`.
(setv nickname
      (Html
        :name "nickname"
        :tag "input"
        :attributes
        {:id "nickname"}
        :extract "value"))

;; Extracts the name of the CSRF token from HTML code. It looks
;; for a tag similar to this:
;; <input name="0123456789" value="0123456789012345678901234567890123456789012345678901234567890123" type="hidden">
;; and returns 0123456789.
(setv csrf_name
      (Html
        :name "csrf_name"
        :tag "input"
        :attributes
        {:name "^[0-9A-Fa-f]{10}$"
         :value "^[0-9A-Fa-f]{64}$"
         :type "hidden"}
        :extract "name"))

;; Extracts the value of the CSRF token from HTML code. It looks
;; for a tag similar to this:
;; <input name="0123456789" value="0123456789012345678901234567890123456789012345678901234567890123" type="hidden">
;; and returns 0123456789012345678901234567890123456789012345678901234567890123.
(setv csrf_value
      (Html
        :name "csrf_value"
        :tag "input"
        :attributes
        {:name "^[0-9A-Fa-f]{10}$"
         :value "^[0-9A-Fa-f]{64}$"
         :type "hidden"}
        :extract "value"))

;; Defines the `login` Flow. Sends a POST request to
;; https://example.com/login.php. Use the username, password
;; and both the CSRF name and values in the POST body.
;; Extract the new CSRF values, and moves to the next stage
;; if HTTP response is 200.
(setv login
      (Flow
        (Request.post
           "https://example.com/login.php"
           :cookies [session_id]
           :data
           {"password" password
           "username" username
           csrf_name csrf_value})
        :outputs [csrf_name csrf_value]
        :operations [(Http
                       :status 200
                       :action (Next "multi_factor")
                       :otherwise (Next "login"))]))

;; Defines the `multi_factor` Flow. Sends a POST request to
;; https://example.com/login.php. Use the username, password,
;; CSRF values, and the MFA code in the POST body.
(setv multi_factor
      (Flow
        (Request.post
           "https://example.com/login.php"
           :cookies [session_id]
           :data
           {"password" password
            "username" username
            "otp" mfa_code
            csrf_name csrf_value})
        :outputs [csrf_name csrf_value]))

;; Extracts the nickname and print it. Send a GET request to
;; https://example.com/settings.php and extract the nickname
;; from the HTML response.
(setv get_nickname
      (Flow
        (Request.get
          "https://example.com/settings.php"
          :cookies [session_id])
        :outputs [nickname]
        :operations [(Print nickname)]))