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.

Flow class holding the information exchanged between server and client.

class Flow(name, 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 has a name, 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.

Flow objects are used as states in the Authentication class to define the authentication process as a finite state machine.

It’s also used in the Functions class to run arbitrary actions when it doesn’t affect the authentication state.

name

A string used as a unique identifier for the defined Flow.

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 NextStage operation if another Flow is expected.

logger

A logging.RootLogger object used for debugging.

execute(user, config)[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 (User) – An object containing all the user specific data relevant for this action.

  • config (Config) – The global Raider configuration.

Return type

None

get_plugin_values(user)[source]

Given a user, get the plugins’ values from it.

Parameters

user (User) – A User object with the userdata.

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 NextStage operations is encountered.

Return type

Optional[str]

Returns

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

Examples

Create the variable initialization with the Flow. It’ll send a request to the _base_url using the path admin/. If the HTTP response code is 200 go to next stage login.

(setv initialization
      (Flow
        :name "initialization"
        :request (Request
                   :method "GET"
                   :path "admin/")
        :operations [(Http
                       :status 200
                       :action (NextStage "login"))]))

Define Flow login. It will send a POST request to https://www.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
        :name "login"
        :request (Request
                   :method "POST"
                   :url "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.

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

(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"))

(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"))


(setv login
      (Flow
        :name "login"
        :request (Request
                   :method "POST"
                   :path "/login.php"
                   :cookies [session_id]
                   :data
                   {"open" "login"
                    "action" "customerlogin"
                    "password" password
                    "username" username
                    "redirect" "myaccount"
                    csrf_name csrf_value})
        :outputs [csrf_name csrf_value]
        :operations [(Http
                       :status 200
                       :action (NextStage "multi_factor")
                       :otherwise (NextStage "login"))]))