Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addOns/ascanrules/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- The Cloud Metadata Potentially Exposed scan rules now has a CWE reference.
- Scan rules which execute time based attacks now include the "TEST_TIMING" alert tag.
- The XPath Injection scan rule now supports error patterns provided via the Custom Payloads add-on (Issue 8958). A minimum of Custom Payloads 0.15.0 is required to take advantage of this optional functionality.
- Detection of Escaped XSS /js/encodeURIComponent test. Payload of simple alert in performDirectAttack function.

## [72] - 2025-06-20
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public class CrossSiteScriptingScanRule extends AbstractAppParamPlugin
ALERT_TAGS = Collections.unmodifiableMap(alertTags);
}

protected static final String GENERIC_ALERT = "alert(1)";
protected static final String GENERIC_SCRIPT_ALERT = "<scrIpt>alert(1);</scRipt>";
protected static final String GENERIC_ONERROR_ALERT = "<img src=x onerror=prompt()>";
protected static final String IMG_ONERROR_LOG = "<img src=x onerror=console.log(1);>";
Expand All @@ -92,7 +93,9 @@ public class CrossSiteScriptingScanRule extends AbstractAppParamPlugin

private static final List<String> GENERIC_SCRIPT_ALERT_LIST =
Arrays.asList(
GENERIC_SCRIPT_ALERT, GENERIC_NULL_BYTE_SCRIPT_ALERT, GENERIC_ONERROR_ALERT);
GENERIC_SCRIPT_ALERT,
GENERIC_NULL_BYTE_SCRIPT_ALERT,
GENERIC_ONERROR_ALERT);
private static final List<Integer> GET_POST_TYPES =
Arrays.asList(NameValuePair.TYPE_QUERY_STRING, NameValuePair.TYPE_POST_DATA);

Expand Down Expand Up @@ -729,6 +732,12 @@ private boolean performScriptAttack(HtmlContext context, HttpMessage msg, String
return true;
}
}
List<HtmlContext> contexts3 = performAttack(msg, param, GENERIC_ALERT, null, 0);
if (contexts3 != null && !contexts3.isEmpty()) {
if (processContexts(contexts3, param, GENERIC_ALERT, false)) {
return true;
}
}
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2670,6 +2670,49 @@ protected Response serve(IHTTPSession session) {
assertThat(alertsRaised.get(0).getConfidence(), equalTo(Alert.CONFIDENCE_MEDIUM));
}

@Test
void shouldReportXssInSriptAttackInEval() throws NullPointerException, IOException {
// Given
String test = "/shouldReportXssInSriptAttackInEval/";

this.nano.addHandler(
new NanoServerHandler(test) {
@Override
protected Response serve(IHTTPSession session) {
String q = getFirstParamValue(session, "q");
String response;
if (q != null) {
// Make the eye catchers fail
response =
"""
<html>
<head></head>
<body>
<script>
eval(encodeURIComponent('%s'));
</script>
</body>
</html>"""
.formatted(q);
} else {
response = "<html><body>No input provided</body></html>";
}
return newFixedLengthResponse(response);
}
});

HttpMessage msg = this.getHttpMessage(test + "?q=sample");
this.rule.setConfig(new ZapXmlConfiguration());
// When
this.rule.init(msg, this.parent);
this.rule.scan();
// Then
assertThat(alertsRaised.size(), equalTo(1));
assertThat(alertsRaised.get(0).getParam(), equalTo("q"));
assertThat(alertsRaised.get(0).getAttack(), containsString("alert(1)"));
assertThat(alertsRaised.get(0).getConfidence(), equalTo(Alert.CONFIDENCE_MEDIUM));
}

@Override
protected Path getResourcePath(String resourcePath) {
return super.getResourcePath("crosssitescriptingscanrule/" + resourcePath);
Expand Down
Loading