From 16dfd1b7a71ccecff968efc1cf7037ce42fecfbe Mon Sep 17 00:00:00 2001 From: Harsh Barsaiyan Date: Wed, 10 Apr 2024 15:44:37 +0530 Subject: [PATCH 1/2] show request headers only on vulnerableapis collection and add remove_auth_headers tests --- .../src/main/resources/SampleApiData.json | 130 ++++++++++++++++++ .../akto/test_editor/execution/Executor.java | 11 +- .../execution/ExecutorAlgorithm.java | 9 +- .../YamlNodeExecutor.java | 10 +- .../main/java/com/akto/util/Constants.java | 1 + 5 files changed, 149 insertions(+), 12 deletions(-) diff --git a/apps/dashboard/src/main/resources/SampleApiData.json b/apps/dashboard/src/main/resources/SampleApiData.json index 304334d346..00239c8ed1 100644 --- a/apps/dashboard/src/main/resources/SampleApiData.json +++ b/apps/dashboard/src/main/resources/SampleApiData.json @@ -4490,5 +4490,135 @@ "responseHeaders": {}, "statusCode": 200 } + }, + { + "id": "CONTENT_TYPE_HEADER_MISSING", + "sampleData": { + "method": "GET", + "requestPayload": "", + "responsePayload": "{\"courses\": [{\"courseId\": \"CS101\", \"name\": \"Computer Science\", \"duration\": \"4 years\", \"faculty\": \"PROF-404\", \"description\": \"This course provides in-depth knowledge of computer science principles and applications.\"}, {\"courseId\": \"ENG201\", \"name\": \"English\", \"duration\": \"3 years\", \"faculty\": \"PROF-202\", \"description\": \"Explore the world of literature and develop critical thinking and analytical skills.\"}, {\"courseId\": \"MAT301\", \"name\": \"Mathematics\", \"duration\": \"3 years\", \"faculty\": \"PROF-505\", \"description\": \"Study advanced mathematical concepts and their real-world applications.\"}]}", + "requestHeaders": "{\"Authorization\":\"JWT eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBa3RvIiwic3ViIjoibG9naW4iLCJzaWduZWRVcCI6InRydWUiLCJ1c2VybmFtZSI6InJpc2hhdi5zb2xhbmtpQGFrdG8uaW8iLCJpYXQiOjE2ODg3MTMzNTUsImV4cCI6MTY4ODcxNDI1NX0.ToSrgQdEWaTVBphY9QMPBmo1zWgaDt_2zRlFb4gLYcgn3x58ClnTciRXN--9 LeoKojWo466S2rDDK8KH3IhR7gTDKk9ihKfLaVoKIg7M7RaHxFgp - vtjWenFcR6IBqLXqYh_kCqBFDH3hjrbD1Qtoaieu_L1rtJFwqz2xoIZP0VEmTPXT4vxT6yoVlbgloROzu1cJFGnoFQm69OUNHpCLf9S_7Qs - 9 eV2V - AlzeClfMnblTqhQP_s4znPit2Ik0ypNIH - mEwgxL - coWVmphuFYy5uG5c2Z4F4te7r_QP9jlOVYFjwB6_9gQSwi1lrm8qKdNml1UKnh4NNizc1878oQ\", \"Content-Length\": \"2\"}", + "responseHeaders": "", + "status": "OK", + "statusCode": "200", + "path": "/api/college/course-list" + }, + "testData": { + "method": "GET", + "url": "/api/college/course-list", + "responsePayload": { + "courses": { + "courseId_1": "CS101", + "courseId_2": "CS102", + "courseId_3": "CS103", + "courseId_4": "CS104", + "courseId_5": "CS105" + } + }, + "responseHeaders": { + "Server": "Apache/2.4.18 (Ubuntu)" + }, + "statusCode": 200 + } + }, + { + "id": "FIREBASE_UNAUTHENTICATED", + "sampleData": { + "method": "GET", + "requestPayload": "", + "responsePayload": "{\"d1\" : \"CSE\", \"d2\": \"ECE\", \"d3\": \"IT\"}", + "requestHeaders": "{\"Authorization\":\"JWT eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBa3RvIiwic3ViIjoibG9naW4iLCJzaWduZWRVcCI6InRydWUiLCJ1c2VybmFtZSI6InJpc2hhdi5zb2xhbmtpQGFrdG8uaW8iLCJpYXQiOjE2ODg3MTMzNTUsImV4cCI6MTY4ODcxNDI1NX0.ToSrgQdEWaTVBphY9QMPBmo1zWgaDt_2zRlFb4gLYcgn3x58ClnTciRXN--9 LeoKojWo466S2rDDK8KH3IhR7gTDKk9ihKfLaVoKIg7M7RaHxFgp - vtjWenFcR6IBqLXqYh_kCqBFDH3hjrbD1Qtoaieu_L1rtJFwqz2xoIZP0VEmTPXT4vxT6yoVlbgloROzu1cJFGnoFQm69OUNHpCLf9S_7Qs - 9 eV2V - AlzeClfMnblTqhQP_s4znPit2Ik0ypNIH - mEwgxL - coWVmphuFYy5uG5c2Z4F4te7r_QP9jlOVYFjwB6_9gQSwi1lrm8qKdNml1UKnh4NNizc1878oQ\", \"Content-Type\": \"application/json\", \"Content-Length\": \"2\"}", + "responseHeaders": "", + "status": "OK", + "statusCode": "200", + "path": "/api/college/info/departments/branch" + }, + "testData": { + "method": "GET", + "url": "/api/college/info/departments/branch.json", + "responsePayload": { + "d1": { + "id": "CSE", + "name": "Computer Science" + }, + "d2": { + "id": "ECE", + "name": "Electronics and Communication" + }, + "d3": { + "id": "IT", + "name": "Information Technology" + } + }, + "responseHeaders": {}, + "statusCode": 200 + } + }, + { + "id": "PASSWD_CHANGE_BRUTE_FORCE", + "sampleData": { + "method": "POST", + "requestPayload": "{\"username\": \"STUD-9965\", \"password\":\"qwerty123\"}", + "requestHeaders": "{\"Authorization\":\"JWT eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBa3RvIiwic3ViIjoibG9naW4iLCJzaWduZWRVcCI6InRydWUiLCJ1c2VybmFtZSI6InJpc2hhdi5zb2xhbmtpQGFrdG8uaW8iLCJpYXQiOjE2ODg3MTMzNTUsImV4cCI6MTY4ODcxNDI1NX0.ToSrgQdEWaTVBphY9QMPBmo1zWgaDt_2zRlFb4gLYcgn3x58ClnTciRXN--9 LeoKojWo466S2rDDK8KH3IhR7gTDKk9ihKfLaVoKIg7M7RaHxFgp - vtjWenFcR6IBqLXqYh_kCqBFDH3hjrbD1Qtoaieu_L1rtJFwqz2xoIZP0VEmTPXT4vxT6yoVlbgloROzu1cJFGnoFQm69OUNHpCLf9S_7Qs - 9 eV2V - AlzeClfMnblTqhQP_s4znPit2Ik0ypNIH - mEwgxL - coWVmphuFYy5uG5c2Z4F4te7r_QP9jlOVYFjwB6_9gQSwi1lrm8qKdNml1UKnh4NNizc1878oQ\", \"HOST\": \"vulnerableapi.com\", \"Content-Type\": \"application/json\", \"Content-Length\": \"2\"}", + "responsePayload": "{\"status\": \"Password change successful\"}", + "responseHeaders": "", + "status": "OK", + "statusCode": "200", + "path": "/api/college/erp/login/change-password" + }, + "testData": { + "method": "POST", + "url": "/api/college/erp/login/change-password", + "responsePayload": { + "status": "Password change successful" + }, + "responseHeaders": {}, + "statusCode": 200 + } + }, + { + "id": "BOLA_COOKIE_FUZZING", + "sampleData": { + "method": "GET", + "requestPayload": "{\"email\": \"user6@example.com\",\"role\": \"user\"}", + "requestHeaders": "{\"Authorization\":\"JWT eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBa3RvIiwic3ViIjoibG9naW4iLCJzaWduZWRVcCI6InRydWUiLCJ1c2VybmFtZSI6InJpc2hhdi5zb2xhbmtpQGFrdG8uaW8iLCJpYXQiOjE2ODg3MTMzNTUsImV4cCI6MTY4ODcxNDI1NX0.ToSrgQdEWaTVBphY9QMPBmo1zWgaDt_2zRlFb4gLYcgn3x58ClnTciRXN--9 LeoKojWo466S2rDDK8KH3IhR7gTDKk9ihKfLaVoKIg7M7RaHxFgp-vtjWenFcR6IBqLXqYh_kCqBFDH3hjrbD1Qtoaieu_L1rtJFwqz2xoIZP0VEmTPXT4vxT6yoVlbgloROzu1cJFGnoFQm69OUNHpCLf9S_7Qs-9eV2V-AlzeClfMnblTqhQP_s4znPit2Ik0ypNIH-mEwgxL-coWVmphuFYy5uG5c2Z4F4te7r_QP9jlOVYFjwB6_9gQSwi1lrm8qKdNml1UKnh4NNizc1878oQ\", \"HOST\": \"vulnerableapi.com\", \"cookie\": \"refreshToken=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBa3RvIiwic3ViIjoicmVmcmVzaFRva2VuIiwic2lnbmVasdkSDG3jsnVlIiwidjknbjhksd8757dfsjkgDFG93nQGFrdG8uaW8iLCJpYXQiOjE2ODk2OTg0MDgsImV4cCI6MTY5MDIxNjgwOH0.i4YOfDCn4W3weTYqU5M3zaB37L4DHRUaFc91XVzD0_WOYRlTETrzFyLRpMETP7GrttSE79DyFDIN9nVgtuiAOrcLafyZUZsbV9oqLaNxEHx3vcyOQpg7Br7AUPxzqnIyZs_vxdmnkewRoxaeMifhlXuhIvORCoLZRHBgLX66CuJNqBwQy6zO3W0DcdgFN0DOWeQulYN2m8KLuNVDzHswq0s9jOWLPEwVBwlQc-sdf3sFKAoe9rewKNMSA4ptWOds6tqphBs0RYyaE4S_HFywT8mmMb8mer7fdzFqTEXfyKFzEFbI2M9k2_kpASyd6uvl_Cdk22QSIZBzjRMVo3VOLWgg; intercom-device-id-xjvl0z2h=25750e91-1931-42e2-a319-8b7289df6800\"}", + "responsePayload": "{\"flower\": \"Lilium\", \"number\": \"274\"}", + "responseHeaders": "", + "status": "OK", + "statusCode": "200", + "path": "/api/college/garden/123653" + }, + "testData": { + "method": "GET", + "url": "/api/college/garden/123653", + "responsePayload": { + "flower": "Lilium", + "number": "274" + }, + "responseHeaders": {}, + "statusCode": 200 + } + }, + { + "id": "HEAD_METHOD_TEST", + "sampleData": { + "method": "GET", + "requestPayload": "", + "responsePayload": "{\"message\": \"Redirecting...\"}", + "requestHeaders": "{\"Authorization\":\"JWT eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBa3RvIiwic3ViIjoibG9naW4iLCJzaWduZWRVcCI6InRydWUiLCJ1c2VybmFtZSI6InJpc2hhdi5zb2xhbmtpQGFrdG8uaW8iLCJpYXQiOjE2ODg3MTMzNTUsImV4cCI6MTY4ODcxNDI1NX0.ToSrgQdEWaTVBphY9QMPBmo1zWgaDt_2zRlFb4gLYcgn3x58ClnTciRXN--9 LeoKojWo466S2rDDK8KH3IhR7gTDKk9ihKfLaVoKIg7M7RaHxFgp - vtjWenFcR6IBqLXqYh_kCqBFDH3hjrbD1Qtoaieu_L1rtJFwqz2xoIZP0VEmTPXT4vxT6yoVlbgloROzu1cJFGnoFQm69OUNHpCLf9S_7Qs - 9 eV2V - AlzeClfMnblTqhQP_s4znPit2Ik0ypNIH - mEwgxL - coWVmphuFYy5uG5c2Z4F4te7r_QP9jlOVYFjwB6_9gQSwi1lrm8qKdNml1UKnh4NNizc1878oQ\", \"Content-Type\": \"application/json\", \"Content-Length\": \"2\", \"X-CSRF-Token\": \"abcdef1234567890\"}", + "responseHeaders": "", + "status": "OK", + "statusCode": "302", + "path": "/api/college/head-endpoint" + }, + "testData": { + "method": "HEAD", + "url": "/api/college/head-endpoint", + "responsePayload": { + "message": "Welcome to the collegeXYZ Portal" + }, + "responseHeaders": {}, + "statusCode": 200 + } } ] diff --git a/apps/testing/src/main/java/com/akto/test_editor/execution/Executor.java b/apps/testing/src/main/java/com/akto/test_editor/execution/Executor.java index 0a10676278..f468d763a4 100644 --- a/apps/testing/src/main/java/com/akto/test_editor/execution/Executor.java +++ b/apps/testing/src/main/java/com/akto/test_editor/execution/Executor.java @@ -155,7 +155,7 @@ public YamlTestResult execute(ExecutorNode node, RawApi rawApi, Map algoMap = new HashMap<>(); - ExecutorSingleRequest singleReq = executorAlgorithm.execute(executorNodes, 0, algoMap, testRawApis, false, 0); + ExecutorSingleRequest singleReq = executorAlgorithm.execute(executorNodes, 0, algoMap, testRawApis, false, 0, apiInfoKey); if (!singleReq.getSuccess()) { testRawApis = new ArrayList<>(); @@ -371,9 +371,9 @@ public TestResult validate(ExecutionResult attempt, RawApi rawApi, Map varMap, AuthMechanism authMechanism, List customAuthTypes) { + public ExecutorSingleOperationResp invokeOperation(String operationType, Object key, Object value, RawApi rawApi, Map varMap, AuthMechanism authMechanism, List customAuthTypes, ApiInfo.ApiInfoKey apiInfoKey) { try { - ExecutorSingleOperationResp resp = runOperation(operationType, rawApi, key, value, varMap, authMechanism, customAuthTypes); + ExecutorSingleOperationResp resp = runOperation(operationType, rawApi, key, value, varMap, authMechanism, customAuthTypes, apiInfoKey); return resp; } catch(Exception e) { return new ExecutorSingleOperationResp(false, "error executing executor operation " + e.getMessage()); @@ -544,7 +544,7 @@ private static BasicDBObject getBillingTokenForAuth() { return bDObject; } - public ExecutorSingleOperationResp runOperation(String operationType, RawApi rawApi, Object key, Object value, Map varMap, AuthMechanism authMechanism, List customAuthTypes) { + public ExecutorSingleOperationResp runOperation(String operationType, RawApi rawApi, Object key, Object value, Map varMap, AuthMechanism authMechanism, List customAuthTypes, ApiInfo.ApiInfoKey apiInfoKey) { switch (operationType.toLowerCase()) { case "send_ssrf_req": String keyValue = key.toString().replaceAll("\\$\\{random_uuid\\}", ""); @@ -650,6 +650,9 @@ public ExecutorSingleOperationResp runOperation(String operationType, RawApi raw } removed = removeCustomAuth(rawApi, customAuthTypes) || removed ; if (removed) { + if (apiInfoKey.getApiCollectionId() == 1111111111) { + Operations.addHeader(rawApi, Constants.AKTO_REMOVE_AUTH , "0"); + } return new ExecutorSingleOperationResp(true, ""); } else { return new ExecutorSingleOperationResp(false, "header key not present"); diff --git a/apps/testing/src/main/java/com/akto/test_editor/execution/ExecutorAlgorithm.java b/apps/testing/src/main/java/com/akto/test_editor/execution/ExecutorAlgorithm.java index 54cc36e5dc..556d35cf32 100644 --- a/apps/testing/src/main/java/com/akto/test_editor/execution/ExecutorAlgorithm.java +++ b/apps/testing/src/main/java/com/akto/test_editor/execution/ExecutorAlgorithm.java @@ -6,6 +6,7 @@ import com.akto.dao.test_editor.TestEditorEnums; import com.akto.dao.test_editor.TestEditorEnums.ExecutorOperandTypes; +import com.akto.dto.ApiInfo; import com.akto.dto.CustomAuthType; import com.akto.dto.RawApi; import com.akto.dto.test_editor.ExecuteAlgoObj; @@ -33,7 +34,7 @@ public ExecutorAlgorithm(RawApi sampleRawApi, Map varMap, AuthMe public ExecutorAlgorithm(){ } - public ExecutorSingleRequest execute(List executorNodes, int operationIndex, Map algoMap, List rawApis, boolean expandRawApis, int rawapiInsertCount) { + public ExecutorSingleRequest execute(List executorNodes, int operationIndex, Map algoMap, List rawApis, boolean expandRawApis, int rawapiInsertCount, ApiInfo.ApiInfoKey apiInfoKey) { if (operationIndex < 0 || operationIndex >= executorNodes.size()) { return new ExecutorSingleRequest(true, "", rawApis, null); @@ -92,7 +93,7 @@ public ExecutorSingleRequest execute(List executorNodes, int opera for (int i = 0; i < numberOfOperations; i++) { if (!expandRawApis && rawApiIndex >= rawApis.size()) { for (int j = 0; j < operationIndex; j++) { - executorSingleRequest = execute(executorNodes, j, algoMap, rawApis, true, numberOfOperations - i); + executorSingleRequest = execute(executorNodes, j, algoMap, rawApis, true, numberOfOperations - i, apiInfoKey); if (!executorSingleRequest.getSuccess()) { return executorSingleRequest; } @@ -110,7 +111,7 @@ public ExecutorSingleRequest execute(List executorNodes, int opera valIndex = (valIndex + 1)%valList.size(); } } - ExecutorSingleOperationResp resp = executor.invokeOperation(executorNode.getOperationType(), key, val, rawApis.get(rawApiIndex), varMap, authMechanism, customAuthTypes); + ExecutorSingleOperationResp resp = executor.invokeOperation(executorNode.getOperationType(), key, val, rawApis.get(rawApiIndex), varMap, authMechanism, customAuthTypes, apiInfoKey); if (!resp.getSuccess()) { return new ExecutorSingleRequest(false, resp.getErrMsg(), null, false); } @@ -123,7 +124,7 @@ public ExecutorSingleRequest execute(List executorNodes, int opera algoMap.put(operationIndex, new ExecuteAlgoObj(numberOfOperations, keyIndex, valIndex, rawApis.size())); if (!expandRawApis) { - executorSingleRequest = execute(executorNodes, operationIndex + 1, algoMap, rawApis, false, 0); + executorSingleRequest = execute(executorNodes, operationIndex + 1, algoMap, rawApis, false, 0, apiInfoKey); } return executorSingleRequest; } diff --git a/apps/testing/src/main/java/com/akto/testing/workflow_node_executor/YamlNodeExecutor.java b/apps/testing/src/main/java/com/akto/testing/workflow_node_executor/YamlNodeExecutor.java index cd372a77a6..5a42505a90 100644 --- a/apps/testing/src/main/java/com/akto/testing/workflow_node_executor/YamlNodeExecutor.java +++ b/apps/testing/src/main/java/com/akto/testing/workflow_node_executor/YamlNodeExecutor.java @@ -82,7 +82,7 @@ public NodeResult processNode(Node node, Map varMap, Boolean all ExecutorAlgorithm executorAlgorithm = new ExecutorAlgorithm(sampleRawApi, varMap, authMechanism, customAuthTypes); Map algoMap = new HashMap<>(); - ExecutorSingleRequest singleReq = executorAlgorithm.execute(executorNodes, 0, algoMap, rawApis, false, 0); + ExecutorSingleRequest singleReq = executorAlgorithm.execute(executorNodes, 0, algoMap, rawApis, false, 0, yamlNodeDetails.getApiInfoKey()); if (!singleReq.getSuccess()) { rawApis = new ArrayList<>(); @@ -104,9 +104,11 @@ public NodeResult processNode(Node node, Map varMap, Boolean all List responseLenArr = new ArrayList<>(); for (RawApi testReq: rawApis) { - Map> headers = testReq.fetchReqHeaders(); - headers.put(Constants.AKTO_NODE_ID, Collections.singletonList(node.getId())); - testReq.modifyReqHeaders(headers); + if (yamlNodeDetails.getApiCollectionId() == 1111111111) { + Map> headers = testReq.fetchReqHeaders(); + headers.put(Constants.AKTO_NODE_ID, Collections.singletonList(node.getId())); + testReq.modifyReqHeaders(headers); + } if (vulnerable) { break; } diff --git a/libs/dao/src/main/java/com/akto/util/Constants.java b/libs/dao/src/main/java/com/akto/util/Constants.java index b75380cbd9..8d2a5468ef 100644 --- a/libs/dao/src/main/java/com/akto/util/Constants.java +++ b/libs/dao/src/main/java/com/akto/util/Constants.java @@ -17,5 +17,6 @@ private Constants() {} public static final String AKTO_ATTACH_FILE = "x-akto-attach-file"; public static final String AKTO_TOKEN_KEY = "x-akto-key"; public static final String AKTO_NODE_ID = "x-akto-node"; + public static final String AKTO_REMOVE_AUTH= "x-akto-remove-auth"; } From 78608c48a82728ef93bf161f7eff04d9a3cb6400 Mon Sep 17 00:00:00 2001 From: Harsh Barsaiyan Date: Wed, 10 Apr 2024 15:54:33 +0530 Subject: [PATCH 2/2] update urlList size --- .../src/main/java/com/akto/listener/RuntimeListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java b/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java index da15a1e81b..d75d32f9c2 100644 --- a/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java +++ b/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java @@ -225,7 +225,7 @@ public static void addSampleData() { for (SingleTypeInfo singleTypeInfo: params) { urlList.add(singleTypeInfo.getUrl()); } - if (urlList.size() != 190) { + if (urlList.size() != 194) { Utils.pushDataToKafka(VULNERABLE_API_COLLECTION_ID, "", result, new ArrayList<>(), true); }