Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlmap using OpenAPI schema for testing #5716

Open
nrathaus opened this issue May 17, 2024 · 2 comments
Open

sqlmap using OpenAPI schema for testing #5716

nrathaus opened this issue May 17, 2024 · 2 comments

Comments

@nrathaus
Copy link

nrathaus commented May 17, 2024

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
@stamparm
Copy link
Member

last time i checked, the main problem i found was how to properly fill the parameter values. putting dumb * will not help. not sure if you are aware, but web applications actually like valid values. another approach would be to lean on "examples", but i can see problems here too - user will provide a dummy schema, without examples, and will immediately open issues here

@nrathaus
Copy link
Author

I agree with your statement - though I think at the moment asking for the user to provide valid values interactively, or by editing a REQUESTFILE file would allow end-users to have a better chance of testing their openapi interface comprehensively than without using the openapi json file

Maybe if you can tell me what you are most worried about, I can think of a solution, if it is lack of valid values for fields - I can think about how to give a solution to this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants