OpenAPI Configuration

HawkScan needs to know the routes/endpoints of an application to test for vulnerabilities. While HawkScan can attempt to autodiscover routes/endpoints, it can also use an OpenAPI specification to pre-seed its sitemap. The OpenAPI Specification (AKA Swagger) is an industry-adopted standard for describing RESTful interfaces, which HawkScan can use to deliver a faster, more thorough scan.

Some projects might not have an OpenAPI spec file because their API is for internal application use only. We have found that even for internal APIs it is useful to have an OpenAPI spec for integration not only with HawkScan, but a wide variety of tools and technologies. Open API definitions do not have to be publicly published for internal APIs, they can be for limited to internal use only.

HawkScan can work with OpenAPI definitions as separate files or defined inline via the stackhawk.yml file. Additionally, if your project doesn’t already have an OpenAPI file for use with HawkScan, there are multiple ways to get started.

The OpenAPI has a v2 and a v3 versioned implementations. HawkScan supports both versions.

Example OpenAPI Spec File

A typical OpenAPI spec can be defined in either yaml or json format (e.g. openapi.yaml). A yaml version might look like the following:

swagger: "2.0"
info:
  title: Sample Example Web API
  description: Web API description in _markdown_.
  version: 1.0.0
host: api.example.com
basePath: /v1
schemes:
  - https
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: extended description in Markdown.
      produces:
        - application/json
      responses:
        200:
          description: OK

Using An OpenAPI Spec File In HawkScan

If your project already uses an existing v2 OpenAPI specification file, you can integrate it with HawkScan by including the following in your stackhawk.yaml:

# in the "app" config...
app:
  # specify the relative path to an OpenAPI v2 .json or .yaml file
  # prefix the path with / to pull from the target host
  api: "openapi.yaml"

If the stackhawk.yaml includes anapp.api configuration, HawkScan will use the contents of the provided OpenAPI spec to improve the quality of the scan:

  • The routes defined in the OpenAPI spec will pre-seed the sitemap of routes to scan. This can be used to complement any crawled routes, or can be used instead of app spidering altogether.
  • The methods and expected inputs to routes defined in the spec will inform how HawkScan communicates with the web application, and provide clues on how to better attack those paths.

Using An Inline OpenAPI Spec

You can define portions of your web app structure within the app.api configuration of your stackhawk yaml in the OpenAPI format:

# in the "app" config...
app:
  # instead of a string path to a file, provide the openapi spec inline
  api:
    basePath: /v1
    schemes:
    - https
    paths:
      /users:
        get:
          summary: Returns a list of users.
          description: extended description in Markdown.
          produces:
            - application/json
          responses:
            200:
              description: OK

This can be useful for segmenting scan results to portions of your web application, and can start as the foundation of more thorough api documentation to start your own openapi.yaml specification file.

Tips For Creating A New OpenAPI Spec For HawkScan

Because OpenAPI is widely adopted, there are a lot of available tools to help a project get started: https://openapi.tools/

SmartBear has free online editor that can be used immediately to start building a OpenAPI file that will work with HawkScan: https://swagger.io/tools/swagger-editor/

For new projects, the industry recommended approach is to create an OpenAPI spec file and employ OpenAPI code-generators to stub out the endpoints for the desired server frameworks. For existing projects, there are various ways to get an OpenAPI specification defined.

Framework specific help:

Spring/Springboot

SpringFox is a utility to generate OpenAPI spec files from annotated controller routes in a SpringBoot project. It exposes the generated openapi file from a configured rest endpoint.

  1. Add the SpringFox dependency to your build pom file:
  <dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.9.2</version>
  </dependency>

or add the dependency to your build gradle if using that:

  implementation("io.springfox:springfox-swagger2:2.9.2")

Note: use SpringFox version 2.9.2 or greater; earlier versions do not output the security schemes needed for a complete openapi generation.

The SpringFox quickstart reference describes the additional configuration to add to the SpringBoot Application Configuration. It works by using provided annotations on the RestControllers:

  // example spring restcontroller annotations

  @ApiOperation(value = "Find pet by Status",
       notes = "${SomeController.findPetsByStatus.notes}"...)
  @RequestMapping(value = "/findByStatus", method = RequestMethod.GET, params = {"status"})
  public Pet findPetsByStatus(
       @ApiParam(value = "${SomeController.findPetsByStatus.status}",
            required = true,...)
       @RequestParam("status",
           defaultValue="${SomeController.findPetsByStatus.status.default}") String status) {
       //...
  }

  @ApiOperation(notes = "Operation 2", value = "${SomeController.operation2.value}"...)
  @ApiImplicitParams(
      @ApiImplicitParam(name="header1", value="${SomeController.operation2.header1}", ...)
  )
  @RequestMapping(value = "operation2", method = RequestMethod.POST)
  public ResponseEntity<String> operation2() {
    return ResponseEntity.ok("");
  }

Once properly configured the swagger spec should be available via the /v2/api-docs endpoint.

The spec can then be pulled down to a local file:

  $ curl localhost:8080/openapi > openapi.json

Now add that new file to the stackhawk.yml

  app:
    # specify the relative path to an OpenAPI v2 .json or .yaml file
    # prefix the path with / to pull from the target host
    api: "openapi.json"

Rails

There isn’t a way to automatically find and define routes for OpenAPI, but a good way to start is to output all the app’s routes and then use something like swagger-docs to document them.

List out the app’s routes with rails routes

Set up swagger-docs and document each route: https://github.com/richhollis/swagger-docs

    swagger_controller :users, "User Management"

    swagger_api :index do
    param :query, :page, :integer, :optional, "Page number"
    response :unauthorized
    response :not_acceptable
    response :requested_range_not_satisfiable
    end

Express

There isn’t a way to automatically find and define routes for OpenAPI, but a good way to start is to output all the app’s routes and then use something like swagger-jsdoc to document them.

Find all your routes with some code like this:

    var route, routes = [];

    app._router.stack.forEach(function(middleware){
      if(middleware.route){ // routes registered directly on the app
          routes.push(middleware.route);
      } else if(middleware.name === 'router'){ // router middleware
          middleware.handle.stack.forEach(function(handler){
              route = handler.route;
              route && routes.push(route);
          });
      }
    });

    routes.forEach(function(temp){
        var methods = "";
        for(var method in temp.methods){
            methods += method + ", ";
        }
        console.log(temp.path + ": " + methods);
    });

Set up swagger-jsdoc and then document each route: https://github.com/Surnet/swagger-jsdoc/blob/master/docs/GETTING-STARTED.md

  /**
  * @swagger
  *
  * /login:
  *   post:
  *     description: Login to the application
  *     produces:
  *       - application/json
  *     parameters:
  *       - name: username
  *         description: Username to use for login.
  *         in: formData
  *         required: true
  *         type: string
  *       - name: password
  *         description: User's password.
  *         in: formData
  *         required: true
  *         type: string
  *     responses:
  *       200:
  *         description: login
  */
  app.post('/login', (req, res) => {
  // Your implementation comes here ...
  });

DJango

DJango projects can use the django-rest-swagger python package to generate an OpenAPI v2 spec file with their code.

run pip install django-rest-swagger and add the following to your Django settings:

  INSTALLED_APPS = [
  ...
  'rest_framework_swagger',
  ...
  ]

PHP

Laravel and other PHP frameworks can utilize zircote/swagger-php to generate OpenAPI spec files with an assist of code annotations. For OpenAPI v2 spec generation you can explicitly require version 2._ with composer require zircote/swagger-php:2._. The SWAGGER_VERSION=2.0 environment variable will need to be set in your .env file or defined with export SWAGGER_VERSION=2.0

Add phpdoc annotations to your code to assist with OpenAPI spec generation; when you build your site a swagger.json file will be written out to the local working directory.

    /**
    * @OA\Info(title="My First API", version="0.1")
    */

    /**
    * @OA\Get(
    *     path="/api/resource.json",
    *     @OA\Response(response="200", description="An example resource")
    * )
    */

    /** Generate documentation with your php site */
    <?php
    require("vendor/autoload.php");
    $openapi = \OpenApi\scan('/path/to/project');
    header('Content-Type: application/x-yaml');
    echo $openapi->toYaml();

ASP.NET

The Swashbuckle package will expose an OpenAPI spec for the app via a URL.

Install the package:

  Install-Package Swashbuckle

Enable Swashbuckle in something like Program.cs

  httpConfiguration
       .EnableSwagger(c => c.SingleApiVersion("v1", "A title for your API"))
       .EnableSwaggerUi();

Then download the spec to a file from the URL: <your-root-url>/swagger/docs/v1

Add that new file to the stackhawk.yml

  app:
      # specify the relative path to an OpenAPI v2 .json or .yaml file
      api: "myproj.json"

Note: The above steps are for if your app is hosted in IIS. If it’s not, please look at the the Swashbuckle docs for similar install instructions.