ForAllSecure Blog

How To Improve Successful Coverage with Mayhem for API

Editorial Staff
·
October 20, 2022

Mayhem for API always constructs URLs by concatenating each endpoint's path with a common server URL.

The paths are taken directly from the API specification.

The server URL is given via the --url <url> argument to mapi run. (There are other ways, but we'll focus on this one, as it is the most explicit!)

Sometimes the specification elides a common prefix from all endpoints. Consider a specification:

  /version:
    get:
     ...
  /user:
    get:
      ...

If the complete URLs are supposed to be https://localhost/api/v2/version and https://localhost/api/v2/user, the common prefix (/api/v2) will need to be included in the server URL given to Mayhem for API:

mapi run ... --url 'https://localhost/api/v2'

Improve The Spec

Often, Mayhem for API just needs a bit more... specificity... in the specification, in order to successfully cover an endpoint.

Provide Schemas

If Mayhem for API is consistently unable to generate structurally valid payloads, this can usually be resolved by adding or refining schemas in the spec.

OpenAPI allows for parameters and request body types to be declared, in whatever level of detail is needed, using Schema Objects.

For example, just listing the required properties for an endpoint's request body makes Mayhem for API massively more likely to successfully cover that endpoint:

  /example:
    post:
      summary: example
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
+             properties:
+               page:
+                 type: integer

Use Consistent Names and Types

Mayhem for API will do a better job generating statefully valid payloads if stateful identifiers that are passed between endpoints have the same name and type.

For example, if you have an endpoint that lists resources and another that fetches a resource by id, make sure the identifiers share a name and type, so that Mayhem for API can more easily connect the dots:

  /example:
    get:
      summary: list of examples
      responses:
        '200':
          description: all the examples
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    example_id:
                      type: integer
- /example/{id}:
+ /example/{example_id}:
    get:
      summary: details of a single example
      parameters:
        - in: path
-         name: id
+         name: example_id
          schema:
-           type: string
+           type: integer

ℹ️ The spec changes you make to help Mayhem for API exercise your API will also improve anything else—code, documentation, and so on—that you derive from your specs! Win-win!

Provide Examples in your Specification

There are situations where Mayhem for API really just needs a hint. For example, consider endpoints that include the username of the currently-authenticated user, like '/user/{username}/settings'.

ℹ️ Examples are often needed when the service being tested has some pre-loaded state (like the user, for authentication!) that's difficult to naturally "discover" through fuzzing.

In this case, OpenAPI allows "example" values, and Mayhem for API will take the examples into account when generating request payloads. For the "{username}" parameterized endpoint, this might be as simple as:

  /user/{username}/settings:
    get:
      summary: settings
      parameters:
        - in: path
          name: username
          schema:
            type: string
+           example: mayhem4api-user

Resource Hints (Preview)

ℹ️ This option is currently in preview and is subject to change

Mayhem for API may need additional hints to make a successful requests to endpoints. Perhaps every request requires that a constant value is applied to every request body or path parameter. It is possible to provide hints for all generated requests by passing one or more --resource-hint options to the mapi run command.

In order to understand which resources are applicable to the --resource-hint option, you should first list the available resources for your API specification with the mapi describe specfication command.

For example, let's list the resources of the petstore demo API:

mapi describe specification \
  "https://demo-api.mayhem4api.forallsecure.com/api/v3/openapi.json"

Spec path is https://demo-api.mayhem4api.forallsecure.com/api/v3/openapi.json
PUT /pet BODY category/id
PUT /pet BODY category/name
PUT /pet BODY id
PUT /pet BODY name
...
PUT /user/{username} BODY userStatus
PUT /user/{username} BODY username
DELETE /user/{username} PATH username

Every resource for the specification is flattened and listed out in the response. For example, the following represents a field value that is passed as part of a request body when generating a PUT request against /pet.

Method
|
|   Path
|   |
|   |    Request part (can be QUERY, PATH, HEADER or BODY)
v   v    v
PUT /pet BODY category/id
              ^
              Fully qualified path to request body

Another example is a path parameter:

Method
|
|       Path
|       |
|       |               Request part
v       v               v
DELETE /user/{username} PATH username
                             ^
                             Path parameter

The --resource-hint option to mapi run takes a tuple of resource path and value, separated by a colon.

For example, say we wanted to always use the same username value of foo for the DELETE method noted above:

mapi run \
     petstore auto "https://demo-api.mayhem4api.forallsecure.com/api/v3/openapi.json" \
     --url "https://demo-api.mayhem4api.forallsecure.com/api/v3/" \
     --resource-hint "DELETE /user/\{username\} PATH username:foo"

The --resource-hint specifies that any request generated for this DELETE resource will now use foo for the username parameter:

                 Resource Path                          split with ':'
                 v                                      v
--resource-hint "DELETE /user/\{username\} PATH username:foo"
                              ^                          |
                              must escape '{' for        |
                              valid regex                |
                                                         ^ Value to use

--resource-hint will accept a regular expression for matching resource path as well. For instance, say you wanted to substitute foo for EVERY username value:

                         Match ANY request that requires a 'username' 
                         v
--resource-hint "username$:foo"

When multiple --resource-hint are specified that match the same resource path, Mayhem for API will randomly select one of the provided hints whenever it generates a request.

                Choose between 'foo'  ...       or 'bar'
                v                               v
--resource-hint "username$:foo" --resource-hint "username$:bar"

Ignore Endpoints

If, for some reason, your endpoint cannot be covered successfully, consider skipping it during fuzzing (using the --ignore-endpoint <endpoint> argument to mapi run), because we have low confidence in lack of findings.

API Security. Performance. Validation. Fast.

Prime Your APIs for Performance ... In as Little as 5 Minutes.

Get Started for Free Request A Demo

At this point, Mayhem for API is able to exercise your API quite thoroughly and probably uncover all sorts of issues. More importantly in the long run, it will give you confidence that your API is free of the issues we don't find!

Stay Connected


Subscribe to Updates

By submitting this form, you agree to our Terms of Use and acknowledge our Privacy Statement.