Skip to content

sqlmap using OpenAPI schema for testing #5716

Closed
@nrathaus

Description

@nrathaus

Is your feature request related to a problem? Please describe.
Feature request, allowing users of sqlmap to read a JSON of OpenAPI 3.0 as source of endpoints and parameters.

I noticed there are other issues in the past that have been closed, not sure if this because of lack of contribution, I can provide the needed code to parse the OpenAPI JSON file and make it into a REQUESTFILE, but I feel this is a bit a long path - requires reading JSON, creating a file, then loading this file via the REQUESTFILE - maybe a "shortcut" can be made with some assistance (from other sqlmap devs).

Describe the solution you'd like
If we take for example: https://brokencrystals.com/swagger-json - this JSON has enough information to build endpoints

If we make them into something like this:

==========
GET /api/testimonials/count?query=* HTTP/1.1
Host: brokencrystals.com:443

==========
==========
GET /api/products/views HTTP/1.1
Host: brokencrystals.com:443
x-product-name: *

==========

We can feed it into sqlmap, and it is able to test them and find sql-related vulnerabilities

Describe alternatives you've considered
Running a third-party python code such as (BaseParser seen here is from OFFAT project - which uses openapi_spec_validator to read the schema) which will generate the above test.rst output:

tmp_spec = tempfile.NamedTemporaryFile(mode="+a", encoding="utf-8")
        tmp_spec.write("""
{
  "openapi": "3.0.0",
  "paths": {
    "/api/testimonials/count": {
      "get": {
        "operationId": "TestimonialsController_getCount",
        "summary": "",
        "description": "Returns count of all testimonials based on provided sql query",
        "parameters": [
          {
            "name": "query",
            "required": true,
            "in": "query",
            "example": "select count(*) as count from testimonial",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": { "schema": { "type": "string" } }
            }
          }
        },
        "tags": ["Testimonials controller"]
      }
    },
    "/api/products/views": {
      "get": {
        "operationId": "ProductsController_viewProduct",
        "summary": "",
        "description": "Updates the product's 'viewsCount' according to product name provided in the header 'x-product-name' and returns the query result.",
        "parameters": [
          {
            "name": "x-product-name",
            "required": true,
            "in": "header",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "500": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": { "type": "string" },
                    "location": { "type": "string" }
                  }
                }
              }
            }
          }
        },
        "tags": ["Products controller"]
      }
    }
  },
  "info": {
    "title": "Test",
    "description": "info -> description",
    "version": "1.0",
    "contact": {}
  },
  "tags": [],
  "servers": [{ "url": "https://someserver.com" }],
  "components": {
    "schemas": {
    }
  }
}
"""
    )
        tmp_spec.flush()
        obj = BaseParser(tmp_spec.name)

        server_hostname = "brokencrystals.com"
        server_port = ":443"
        server_ssl = "s"

        end_points = obj.specification.get('paths')
        for end_point, end_object in end_points.items():
            for method, method_object in end_object.items():
                parameters = method_object["parameters"]
                req = requests.Request(method=method, url=f"http{server_ssl}://{server_hostname}{server_port}{end_point}")
                req.headers["Host"] = f"{server_hostname}{server_port}"

                for parameter in parameters:
                    if "value" not in parameter:
                      parameter["value"] = "*"
                    if parameter["in"] == "header":
                      req.headers[parameter["name"]] = parameter["value"]
                    if parameter["in"] == "query":
                      req.params[parameter["name"]] =  parameter["value"]
                    if parameter["in"] == "body":
                      req.data.append([parameter["name"], parameter["value"]])
                req = req.prepare()
                print(f"==========\n{self.format_prepped_request(req)}\n==========")

Additional context

  1. I can develop this third-party script that will take a JSON file and make into a REQUESTFILE
  2. I can with some assistance integrate it into sqlmap so that a parser option will do it without requiring the build REQUESTFILE

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions