Skip to content

Commit e151e08

Browse files
authored
Merge pull request #1348 from WebFuzzing/ssrf-final-fixes
SSRF related clean-ups and fixes
2 parents 4e96ba7 + a4e4f74 commit e151e08

7 files changed

Lines changed: 63 additions & 21 deletions

File tree

core-tests/e2e-tests/spring-rest-openapi-v3/src/test/kotlin/org/evomaster/e2etests/spring/openapi/v3/security/ssrf/base/SSRFBaseEMTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class SSRFBaseEMTest : SpringTestBase() {
2323
@Test
2424
fun testSSRFEM() {
2525
runTestHandlingFlakyAndCompilation(
26-
"SSRFBaseEMTest",
26+
"SSRFBaseGeneratedTest",
2727
50,
2828
) { args: MutableList<String> ->
2929

core-tests/e2e-tests/spring-rest-openapi-v3/src/test/kotlin/org/evomaster/e2etests/spring/openapi/v3/security/ssrf/header/SSRFHeaderEMTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class SSRFHeaderEMTest: SpringTestBase() {
2323
@Test
2424
fun testSSRFHeader() {
2525
runTestHandlingFlakyAndCompilation(
26-
"SSRFHeaderEMTest",
26+
"SSRFHeaderGeneratedTest",
2727
30,
2828
) { args: MutableList<String> ->
2929

core-tests/e2e-tests/spring-rest-openapi-v3/src/test/kotlin/org/evomaster/e2etests/spring/openapi/v3/security/ssrf/path/SSRFPathEMTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class SSRFPathEMTest: SpringTestBase() {
2525
@Test
2626
fun testSSRFPathVariable() {
2727
runTestHandlingFlakyAndCompilation(
28-
"SSRFPathEMTest",
28+
"SSRFPathGeneratedTest",
2929
200,
3030
) { args: MutableList<String> ->
3131

core-tests/e2e-tests/spring-rest-openapi-v3/src/test/kotlin/org/evomaster/e2etests/spring/openapi/v3/security/ssrf/query/SSRFQueryEMTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class SSRFQueryEMTest: SpringTestBase() {
2323
@Test
2424
fun testSSRFQuery() {
2525
runTestHandlingFlakyAndCompilation(
26-
"SSRFQueryEMTest",
26+
"SSRFQueryGeneratedTest",
2727
30,
2828
) { args: MutableList<String> ->
2929

core/src/main/kotlin/org/evomaster/core/output/service/HttpWsTestCaseWriter.kt

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import org.evomaster.core.problem.httpws.HttpWsAction
1616
import org.evomaster.core.problem.httpws.HttpWsCallResult
1717
import org.evomaster.core.problem.rest.param.BodyParam
1818
import org.evomaster.core.problem.rest.param.HeaderParam
19+
import org.evomaster.core.problem.security.data.ActionStubMapping
1920
import org.evomaster.core.problem.security.service.HttpCallbackVerifier
2021
import org.evomaster.core.search.EvaluatedIndividual
2122
import org.evomaster.core.search.FitnessValue
@@ -29,6 +30,7 @@ import org.evomaster.core.search.gene.wrapper.ChoiceGene
2930
import org.slf4j.LoggerFactory
3031
import java.nio.file.Path
3132
import javax.ws.rs.core.MediaType
33+
import kotlin.collections.filter
3234

3335

3436
abstract class HttpWsTestCaseWriter : ApiTestCaseWriter() {
@@ -349,7 +351,7 @@ abstract class HttpWsTestCaseWriter : ApiTestCaseWriter() {
349351
val res = evaluatedAction.result as HttpWsCallResult
350352

351353
if (config.ssrf && res.getVulnerableForSSRF()) {
352-
handleSSRFFaults(lines, call)
354+
handleSSRFFaultsPrologue(lines, call)
353355
}
354356

355357
if (res.failedCall()) {
@@ -358,6 +360,10 @@ abstract class HttpWsTestCaseWriter : ApiTestCaseWriter() {
358360
addActionLines(call, index, testCaseName, lines, res, testSuitePath, baseUrlOfSut)
359361
}
360362

363+
if (config.ssrf && res.getVulnerableForSSRF()) {
364+
handleSSRFFaultsEpilogue(lines, call)
365+
}
366+
361367
// reset all used external service action
362368
if (exActions.isNotEmpty()) {
363369
if (!format.isJavaOrKotlin()) {
@@ -795,7 +801,7 @@ abstract class HttpWsTestCaseWriter : ApiTestCaseWriter() {
795801
/**
796802
* Method to set up stub for HttpCallbackVerifier to the test case.
797803
*/
798-
private fun handleSSRFFaults(lines: Lines, action: Action) {
804+
private fun handleSSRFFaultsPrologue(lines: Lines, action: Action) {
799805
val verifier = httpCallbackVerifier.getActionVerifierMapping(action.getName())
800806

801807
if (verifier != null) {
@@ -805,23 +811,60 @@ abstract class HttpWsTestCaseWriter : ApiTestCaseWriter() {
805811
if (format.isKotlin()) {
806812
lines.addStatement("assertNotNull(${verifier.getVerifierName()}.isRunning)")
807813
}
808-
809814
lines.addEmpty(1)
810815

811-
lines.addStatement("${verifier.getVerifierName()}.stubFor(get(\"${verifier.stub}\")")
816+
//Reset verifier before test execution.
817+
lines.addStatement("${verifier.getVerifierName()}.resetAll()")
818+
819+
lines.add("${verifier.getVerifierName()}.stubFor(")
812820
lines.indented {
813-
lines.addStatement(".atPriority(1)")
814-
lines.addStatement(".willReturn(")
821+
lines.add("get(\"${verifier.stub}\")")
815822
lines.indented {
816-
lines.addStatement("aResponse()")
817-
lines.addStatement(".withStatus(${HttpCallbackVerifier.SSRF_RESPONSE_STATUS_CODE})")
818-
lines.addStatement(".withBody(\"${HttpCallbackVerifier.SSRF_RESPONSE_BODY}\")")
823+
lines.add(".withMetadata(Metadata.metadata().attr(\"ssrf\", \"${action.getName()}\"))")
824+
lines.add(".atPriority(1)")
825+
lines.add(".willReturn(")
826+
lines.indented {
827+
lines.add("aResponse()")
828+
lines.indented {
829+
lines.add(".withStatus(${HttpCallbackVerifier.SSRF_RESPONSE_STATUS_CODE})")
830+
lines.add(".withBody(\"${HttpCallbackVerifier.SSRF_RESPONSE_BODY}\")")
831+
}
832+
}
833+
lines.add(")")
819834
}
820-
lines.addStatement(")")
821835
}
822836
lines.addStatement(")")
823837
lines.addEmpty(1)
838+
handleCallbackVerifierRequests(lines, action, verifier, false)
839+
lines.addEmpty(1)
840+
}
841+
}
842+
843+
private fun handleSSRFFaultsEpilogue(lines: Lines, action: Action) {
844+
val verifier = httpCallbackVerifier.getActionVerifierMapping(action.getName())
845+
846+
if (verifier != null) {
847+
lines.addEmpty(1)
848+
handleCallbackVerifierRequests(lines, action, verifier, true)
849+
}
850+
}
851+
852+
private fun handleCallbackVerifierRequests(lines: Lines, action: Action, verifier: ActionStubMapping, assertTrue: Boolean) {
853+
if (assertTrue) {
854+
lines.addSingleCommentLine("Verifying that the request is successfully made to HttpCallbackVerifier after test execution.")
855+
lines.add("assertTrue(${verifier.getVerifierName()}")
856+
} else {
857+
lines.addSingleCommentLine("Verifying that there are no requests made to HttpCallbackVerifier before test execution.")
858+
lines.add("assertFalse(${verifier.getVerifierName()}")
859+
}
860+
lines.indented {
861+
if (format.isKotlin()) {
862+
lines.add(".allServeEvents")
863+
lines.add(".filter { it.wasMatched && it.stubMapping.metadata != null }")
864+
lines.add(".any { it.stubMapping.metadata.getString(\"ssrf\") == \"${action.getName()}\" }")
865+
}
824866
}
867+
lines.add(")")
825868
}
826869

827870
}

core/src/main/kotlin/org/evomaster/core/output/service/TestSuiteWriter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.evomaster.core.output.service
22

33
import com.google.inject.Inject
4-
import org.evomaster.client.java.controller.api.dto.SqlDtoUtils
54
import org.evomaster.client.java.controller.api.dto.database.operations.InsertionDto
65
import org.evomaster.client.java.controller.api.dto.database.operations.MongoInsertionDto
76
import org.evomaster.client.java.instrumentation.shared.ExternalServiceSharedUtils
@@ -24,7 +23,6 @@ import org.evomaster.core.remote.service.RemoteController
2423
import org.evomaster.core.search.Solution
2524
import org.evomaster.core.search.service.Sampler
2625
import org.evomaster.core.search.service.SearchTimeController
27-
import org.evomaster.core.sql.schema.Table
2826
import org.evomaster.core.sql.schema.TableId
2927
import org.evomaster.test.utils.EMTestUtils
3028
import org.evomaster.test.utils.SeleniumEMUtils
@@ -457,6 +455,7 @@ class TestSuiteWriter {
457455
|| (config.ssrf && solution.hasSsrfFaults())) {
458456
addImport("com.github.tomakehurst.wiremock.client.WireMock.*", lines, true)
459457
addImport("com.github.tomakehurst.wiremock.WireMockServer", lines)
458+
addImport("com.github.tomakehurst.wiremock.common.Metadata", lines)
460459
addImport("com.github.tomakehurst.wiremock.core.WireMockConfiguration", lines)
461460
addImport(
462461
"com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer",

core/src/main/kotlin/org/evomaster/core/problem/security/service/SSRFAnalyser.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class SSRFAnalyser {
101101
// selecting individuals with HTTP 400 and 422 status codes.
102102
val individualsWith4XX = getIndividualsWithStatus4XX()
103103

104-
individualsInSolution = individualsWith2XX + individualsWith4XX
104+
individualsInSolution = individualsWith2XX + individualsWith4XX
105105

106106
if (individualsInSolution.isEmpty()) {
107107
return archive.extractSolution()
@@ -121,8 +121,8 @@ class SSRFAnalyser {
121121
// Classify endpoints with potential vulnerability classes
122122
classify()
123123

124-
// execute
125-
analyse()
124+
// evaluate
125+
evaluate()
126126

127127
return archive.extractSolution()
128128
}
@@ -264,7 +264,7 @@ class SSRFAnalyser {
264264
/**
265265
* Run the determined vulnerability class (from the classification) analysers.
266266
*/
267-
private fun analyse() {
267+
private fun evaluate() {
268268
if (config.problemType == EMConfig.ProblemType.REST) {
269269

270270
individualsInSolution.forEach { evaluatedIndividual ->
@@ -346,7 +346,7 @@ class SSRFAnalyser {
346346
private fun getIndividualsWithStatus4XX(): List<EvaluatedIndividual<RestIndividual>> {
347347
return RestIndividualSelectorUtils.findIndividuals(
348348
this.archive.extractSolution().individuals,
349-
statusCodes = listOf(400, 422)
349+
statusCodes = listOf(422)
350350
)
351351
}
352352
}

0 commit comments

Comments
 (0)