sqlmap using OpenAPI schema for testing
nrathaus opened this issue · comments
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
- I can develop this third-party script that will take a JSON file and make into a REQUESTFILE
- I can with some assistance integrate it into sqlmap so that a parser option will do it without requiring the build REQUESTFILE
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
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
I guess we can close this down as there is no interest