From e5079ddfc1de6b957404a3b1956e2f15e8fd8277 Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Thu, 5 Jun 2025 15:24:58 +0200 Subject: [PATCH 1/7] working on auth --- pom.xml | 10 +++ src/main/resources/wfc/schemas/auth.yaml | 100 ++++++++++++++++++++++- 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 687ae59..938e097 100644 --- a/pom.xml +++ b/pom.xml @@ -181,6 +181,16 @@ com.webfuzzing.commons.report + + auth.yaml + + generate + + + ${basedir}/src/main/resources/wfc/schemas/auth.yaml + com.webfuzzing.commons.auth + + diff --git a/src/main/resources/wfc/schemas/auth.yaml b/src/main/resources/wfc/schemas/auth.yaml index cac6867..e6aa579 100644 --- a/src/main/resources/wfc/schemas/auth.yaml +++ b/src/main/resources/wfc/schemas/auth.yaml @@ -27,8 +27,102 @@ properties: type: string required: ["auth"] $def: + HttpVerb: + type: string + enum: + - POST + - GET + - PATCH + - DELETE + - PUT + Header: + description: "HTTP header information" + type: object + properties: + name: + description: "The header name, e.g., 'Authorization'." + type: string + value: + description: "The value of the header" + type: string + required: ["name","value"] AuthenticationInfo: type: object - - - + properties: + name: + description: "The name given to this authentication info. \ + This works as a unique id for this authentication configuration." + type: string + requireMockHandling: + description: "Specify that the authentication for this user requires setting up mock responses from an external service. \ + This will be done as part of the fuzzing, although only possible for white-box testing. \ + One consequence here is that, even if we provide correct auth info as input, then a request might still \ + fail due to unauthorized access if the fuzzing process does not properly set up these mocked responses in the API itself." + type: boolean + fixedHeaders: + description: "The headers needed for authentication. \ + This is used to represent cases in which auth info is static/fixed, e.g., \ + when passing an id or username/password through a HTTP header (and not \ + using for example a dynamically generated token from a login endpoint first)." + type: array + items: + $ref: "#/$def/Header" + loginEndpointAuth: + $ref: "#/$def/LoginEndpoint" + required: ["name"] + ### + LoginEndpoint: + description: "Used to represent the case in which a login endpoint is used to obtain the authentication credentials. \ + These can be cookies, or a token extracted from the login endpoint's response. \ + This token can then be added to an HTTP header in the following requests." + type: object + properties: + endpoint: + description: "The endpoint path (eg '/login') where to execute the login. \ + It assumes it is on same server of API.\ + If not, rather use 'externalEndpointURL'." + type: string + externalEndpointURL: + description: "If the login endpoint is on a different server, here can rather specify the full URL for it." + type: string + payloadRaw: + description: "The raw payload to send, as a string." + type: string + payloadUserPwd: + $ref: "#/$def/PayloadUsernamePassword" # TODO + headers: + description: "HTTP headers needed when calling the login endpoint. \ + Username/password could be passed by headers instead of by the body payload." + type: array + items: + $ref: "#/$def/Header" + verb: + description: "The verb used to connect to the login endpoint. \ + Most of the time, this will be a 'POST'." + allOf: + - $ref: "#/$def/HttpVerb" + - type: string + contentType: + description: "Specify the format in which the payload is sent to the login endpoint. \ + A common example is 'application/json'." + token: + $ref: "#/$def/TokenHandling" # TODO + expectCookies: + description: "Specify if we are expecting to get cookies from the login endpoint. \ + If so, a fuzzer can use those as auth info in following requests, instead of trying to extract \ + an auth token from the response payload." + type: boolean + required: ["verb"] + ### + TokenHandling: + description: "Specify how to extract token from response, and how to use it for auth in following requests. \ + Not needed if rather expect to get back a cookie." + type: object + properties: + ### TODO + ### + PayloadUsernamePassword: + description: "Payload with username and password information. \ + It will be automatically formatted in a proper payload based on content type." + type: object + ### TODO \ No newline at end of file From 4fdbb37e79db13949bf1c26c08ac663781d6a859 Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Thu, 5 Jun 2025 15:40:21 +0200 Subject: [PATCH 2/7] PayloadUsernamePassword --- src/main/resources/wfc/schemas/auth.yaml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/resources/wfc/schemas/auth.yaml b/src/main/resources/wfc/schemas/auth.yaml index e6aa579..f94b43f 100644 --- a/src/main/resources/wfc/schemas/auth.yaml +++ b/src/main/resources/wfc/schemas/auth.yaml @@ -125,4 +125,17 @@ $def: description: "Payload with username and password information. \ It will be automatically formatted in a proper payload based on content type." type: object - ### TODO \ No newline at end of file + properties: + username: + description: "The id of the user." + type: string + password: + description: "The password of the user, in plain-text. This must NOT be hashed." + type: string + usernameField: + description: "The name of the field in the body payload containing the username." + type: string + passwordField: + description: "The name of the field in the body payload containing the password" + type: string + required: ["username","usernameField","password","passwordField"] \ No newline at end of file From f7f1bc997f31bc3ebb1356548c05f1fca3ce0a4d Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Fri, 6 Jun 2025 10:38:14 +0200 Subject: [PATCH 3/7] finishing auth first draft --- src/main/resources/wfc/schemas/auth.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/resources/wfc/schemas/auth.yaml b/src/main/resources/wfc/schemas/auth.yaml index f94b43f..ebdf98a 100644 --- a/src/main/resources/wfc/schemas/auth.yaml +++ b/src/main/resources/wfc/schemas/auth.yaml @@ -119,7 +119,17 @@ $def: Not needed if rather expect to get back a cookie." type: object properties: - ### TODO + extractFromField: + description: "How to extract the token from a JSON response, as such JSON could have few fields, possibly nested. \ + It is expressed as a JSON Pointer (RFC 6901)." + type: string + httpHeaderName: + description: "When sending a token in an HTTP header, specify to which header to add it (e.g., 'Authorization')." + type: string + headerPrefix: + description: " When sending out the obtained token in an HTTP header, specify if there should be any \ + prefix (e.g., 'Bearer ' or 'JWT '). If needed, make sure it has trailing space(s)." + type: string ### PayloadUsernamePassword: description: "Payload with username and password information. \ From 38b6b110ef6704f729863a55c4bd071563d5f88a Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Fri, 6 Jun 2025 12:32:11 +0200 Subject: [PATCH 4/7] fixing auth --- src/main/resources/wfc/schemas/auth.yaml | 40 +++++++++++++++------- src/main/resources/wfc/schemas/report.yaml | 38 ++++++++++---------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/main/resources/wfc/schemas/auth.yaml b/src/main/resources/wfc/schemas/auth.yaml index ebdf98a..9b0de6c 100644 --- a/src/main/resources/wfc/schemas/auth.yaml +++ b/src/main/resources/wfc/schemas/auth.yaml @@ -11,12 +11,12 @@ properties: description: "List of authentication information for different users." type: array items: - $ref: "#/$def/AuthenticationInfo" + $ref: "#/$defs/AuthenticationInfo" authTemplate: description: "Optional authentication information template. This is used to avoid duplication in the auth list. \ Entries defined in the template will be applied to all elements in the auth list that do not specify them." allOf: - - $ref: "#/$def/AuthenticationInfo" + - $ref: "#/$defs/AuthenticationInfo" - type: object configs: description: "Optional map of configuration parameters, in the form key:value strings. \ @@ -26,7 +26,9 @@ properties: additionalProperties: type: string required: ["auth"] -$def: +$defs: +# TODO unfortunately, tools like jsonschema2pojo-maven-plugin have major limitations when dealing with enums. +# This is not created as a top-level class HttpVerb: type: string enum: @@ -66,9 +68,9 @@ $def: using for example a dynamically generated token from a login endpoint first)." type: array items: - $ref: "#/$def/Header" + $ref: "#/$defs/Header" loginEndpointAuth: - $ref: "#/$def/LoginEndpoint" + $ref: "#/$defs/LoginEndpoint" required: ["name"] ### LoginEndpoint: @@ -89,24 +91,36 @@ $def: description: "The raw payload to send, as a string." type: string payloadUserPwd: - $ref: "#/$def/PayloadUsernamePassword" # TODO + $ref: "#/$defs/PayloadUsernamePassword" headers: description: "HTTP headers needed when calling the login endpoint. \ Username/password could be passed by headers instead of by the body payload." type: array items: - $ref: "#/$def/Header" + $ref: "#/$defs/Header" verb: - description: "The verb used to connect to the login endpoint. \ - Most of the time, this will be a 'POST'." - allOf: - - $ref: "#/$def/HttpVerb" - - type: string +# description: "The verb used to connect to the login endpoint. \ +# Most of the time, this will be a 'POST'." +# type: string +# enum: +# - POST +# - GET +# - PATCH +# - DELETE +# - PUT + $ref: "#/$defs/HttpVerb" + ## FIXME: unfortunately, plugin is not able to handle this... need new schema version with $ref not replacing everything +# description: "The verb used to connect to the login endpoint. \ +# Most of the time, this will be a 'POST'." +# allOf: +# - $ref: "#/$defs/HttpVerb" +# - type: string contentType: description: "Specify the format in which the payload is sent to the login endpoint. \ A common example is 'application/json'." + type: string token: - $ref: "#/$def/TokenHandling" # TODO + $ref: "#/$defs/TokenHandling" expectCookies: description: "Specify if we are expecting to get cookies from the login endpoint. \ If so, a fuzzer can use those as auth info in following requests, instead of trying to extract \ diff --git a/src/main/resources/wfc/schemas/report.yaml b/src/main/resources/wfc/schemas/report.yaml index 4fe2b91..750c62c 100644 --- a/src/main/resources/wfc/schemas/report.yaml +++ b/src/main/resources/wfc/schemas/report.yaml @@ -19,18 +19,18 @@ properties: format: date-time description: "The timestamp of when this report file was created." faults: - $ref: "#/$def/Faults" + $ref: "#/$defs/Faults" #### Unfortunately, there is no support for oneOf in jsonschema2pojo # problem_details: # type: object # oneOf: -# - $ref: "#/$def/RESTReport" +# - $ref: "#/$defs/RESTReport" # # TODO GraphQL, RPC and Web problem_details: type: object properties: rest: - $ref: "#/$def/RESTReport" + $ref: "#/$defs/RESTReport" # TODO GraphQL, RPC and Web # expressing that only 1 should be present is possible, but super-verbose and convoluted total_tests: @@ -40,24 +40,24 @@ properties: test_file_paths: type: array items: - $ref: "#/$def/TestFilePath" + $ref: "#/$defs/TestFilePath" uniqueItems: true description: "The list of relative paths (compared to this document) of all the generated test suite files." test_cases: description: "Information on each generated test case." type: array items: - $ref: "#/$def/TestCase" + $ref: "#/$defs/TestCase" #OPTIONAL extra: description: "Extra, optional coverage information, collected by different tools." type: array items: - $ref: "#/$def/Coverage" + $ref: "#/$defs/Coverage" required: ["schema_version","tool_name","tool_version","creation_time","faults","problem_details","total_tests","test_file_paths","test_cases"] -$def: +$defs: OperationId: description: "A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'." @@ -85,15 +85,15 @@ $def: type: object properties: endpoint_id: - $ref: "#/$def/OperationId" + $ref: "#/$defs/OperationId" test_case_id: - $ref: "#/$def/TestCaseId" + $ref: "#/$defs/TestCaseId" http_status: description: "As in a test case the same endpoint could be called more than once, here we report all of the obtained HTTP status codes" type: array items: - $ref: "#/$def/HttpStatus" + $ref: "#/$defs/HttpStatus" minItems: 1 uniqueItems: true required: ["endpoint_id","test_case_id","http_status"] @@ -107,13 +107,13 @@ $def: type: object properties: operation_id: - $ref: "#/$def/OperationId" + $ref: "#/$defs/OperationId" test_case_id: - $ref: "#/$def/TestCaseId" + $ref: "#/$defs/TestCaseId" fault_categories: type: array items: - $ref: "#/$def/FaultCategoryId" + $ref: "#/$defs/FaultCategoryId" minItems: 1 uniqueItems: true required: ["endpoint_id","test_case_id","fault_categories"] @@ -130,22 +130,22 @@ $def: description: "Unique ids of all the endpoints in the tested API." type: array items: - $ref: "#/$def/OperationId" + $ref: "#/$defs/OperationId" uniqueItems: true covered_http_status: description: "List of which HTTP status codes were covered, based on endpoints." type: array items: - $ref: "#/$def/CoveredEndpoint" + $ref: "#/$defs/CoveredEndpoint" required: ["total_http_calls","endpoint_ids","covered_http_status"] TestCase: type: object properties: id: - $ref: "#/$def/TestCaseId" + $ref: "#/$defs/TestCaseId" file_path: - $ref: "#/$def/TestFilePath" + $ref: "#/$defs/TestFilePath" name: description: "The name of the test case, as it appears in the generated test file." type: string @@ -171,7 +171,7 @@ $def: description: "Information on all the identified potential faults." type: array items: - $ref: "#/$def/FoundFault" + $ref: "#/$defs/FoundFault" required: ["total_number","found_faults"] Coverage: @@ -183,7 +183,7 @@ $def: criteria: type: array items: - $ref: "#/$def/CoverageCriterion" + $ref: "#/$defs/CoverageCriterion" required: ["tool_name","criteria"] CoverageCriterion: From e2f6f5e465abc0b225af8222ea378063153a8f26 Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Fri, 6 Jun 2025 12:33:38 +0200 Subject: [PATCH 5/7] updated generated file --- web-report/src/types/GeneratedTypes.tsx | 50 ++++++++++++------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/web-report/src/types/GeneratedTypes.tsx b/web-report/src/types/GeneratedTypes.tsx index d236ef9..c82155c 100644 --- a/web-report/src/types/GeneratedTypes.tsx +++ b/web-report/src/types/GeneratedTypes.tsx @@ -5,6 +5,20 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'. + */ +export type OperationId = string; +/** + * A unique identifier for a test case. It could include its name and file location. + */ +export type TestCaseId = string; +export type HttpStatus = number; +/** + * A relative path used to unique locate a test suite file. + */ +export type TestFilePath = string; + /** * Schema Definition for Web Fuzzing Commons Reports */ @@ -37,7 +51,7 @@ export interface WebFuzzingCommonsReport { /** * The list of relative paths (compared to this document) of all the generated test suite files. */ - test_file_paths: string[]; + test_file_paths: TestFilePath[]; /** * Information on each generated test case. */ @@ -63,14 +77,8 @@ export interface Faults { * Data-structure to represent found faults, based on operations (e.g., HTTP endpoints in REST, and methods in GraphQL and RPC) and which tests find faults in them. */ export interface FoundFault { - /** - * A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'. - */ - operation_id?: string; - /** - * A unique identifier for a test case. It could include its name and file location. - */ - test_case_id: string; + operation_id?: OperationId; + test_case_id: TestCaseId; /** * @minItems 1 */ @@ -99,7 +107,7 @@ export interface RESTReport { /** * Unique ids of all the endpoints in the tested API. */ - endpoint_ids: string[]; + endpoint_ids: OperationId[]; /** * List of which HTTP status codes were covered, based on endpoints. */ @@ -110,31 +118,19 @@ export interface RESTReport { * Data-structure to represent which HTTP status code where covered on an endpoint by any of the generated tests. */ export interface CoveredEndpoint { - /** - * A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'. - */ - endpoint_id: string; - /** - * A unique identifier for a test case. It could include its name and file location. - */ - test_case_id: string; + endpoint_id: OperationId; + test_case_id: TestCaseId; /** * As in a test case the same endpoint could be called more than once, here we report all of the obtained HTTP status codes * * @minItems 1 */ - http_status: [number, ...number[]]; + http_status: [HttpStatus, ...HttpStatus[]]; [k: string]: unknown; } export interface TestCase { - /** - * A unique identifier for a test case. It could include its name and file location. - */ - id?: string; - /** - * A relative path used to unique locate a test suite file. - */ - file_path?: string; + id?: TestCaseId; + file_path?: TestFilePath; /** * The name of the test case, as it appears in the generated test file. */ From 0486c23fb440b2aabb39f41d6dd821ead1502ace Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Fri, 6 Jun 2025 12:40:21 +0200 Subject: [PATCH 6/7] release 0.0.2 --- pom.xml | 2 +- release_notes.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 938e097..285c556 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.webfuzzing commons - 0.0.2-SNAPSHOT + 0.0.2 2024 WFC diff --git a/release_notes.md b/release_notes.md index c220ee0..0aa8b7b 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,3 +1,6 @@ +# 0.0.2 +Support for auth + # 0.0.1 First draft version \ No newline at end of file From 7ec98b33030dbe172972fae697af2a03ac8a5e55 Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Fri, 6 Jun 2025 12:40:59 +0200 Subject: [PATCH 7/7] 0.0.2-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 285c556..938e097 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.webfuzzing commons - 0.0.2 + 0.0.2-SNAPSHOT 2024 WFC