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.
There are two types of Flow, the regular one using the Flow
class, and the authentication Flows using the
AuthFlow
class. Only difference is
that AuthFlow ones are treated as changing the authentication state
while the regular ones don’t. Use AuthFlow to define the process
necessary to reach from unauthenticated state to authenticated
one. Use regular Flows for any other requests you want to test using
Raider.
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
, theresponse
, theoutputs
that needs to be extracted from the response, and a list ofoperations
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.- 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 aNext
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.
- 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 firstNext
operations is encountered.- Return type
Optional
[str
]- Returns
A string with the name of the next flow to run or None.
Examples
Create the variable initialization
with the AuthFlow. 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
(AuthFlow
:request (Request
:method "GET"
:url "https://example.com/admin/")
:operations [(Http
:status 200
:action (NextStage "login"))]))
Define AuthFlow 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
(AuthFlow
: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
.
Also define the regular Flow named get_nickname
to extract the
username of the logged in user. This request doesn’t affect the
authentication state which is why Flow is used instead of AuthFlow.
;; 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` AuthFlow. 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
(AuthFlow
:request (Request
:method "POST"
:url "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 (NextStage "multi_factor")
:otherwise (NextStage "login"))]))
;; Defines the `multi_factor` AuthFlow. 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
(AuthFlow
:request (Request
:method "POST"
:url "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 (Request
:method "GET"
:url "https://example.com/settings.php"
:cookies [session_id])
:outputs [nickname]
:operations [(Print nickname)]))