Skip to content

Commit

Permalink
various: Add TEST_TIMING alert tag
Browse files Browse the repository at this point in the history
Update: CHANGELOGs, scan rules, unittests.

Signed-off-by: kingthorin <[email protected]>
  • Loading branch information
kingthorin committed Dec 17, 2024
1 parent ca584fe commit 58f25e1
Show file tree
Hide file tree
Showing 25 changed files with 245 additions and 31 deletions.
1 change: 1 addition & 0 deletions addOns/ascanrules/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add the `OUT_OF_BAND` alert tag to the following scan rules:
- Server Side Template Injection (Blind)
- XML External Entity Attack
- Scan rules which execute time based attacks now include the "TEST_TIMING" alert tag.

### Fixed
- A situation where the Server-Side Template Injection (SSTI) scan rule might result in false positives related to the Go payloads (Issue 8622).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ public class CommandInjectionScanRule extends AbstractAppParamPlugin
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_12_COMMAND_INJ));
CommonAlertTag.WSTG_V42_INPV_12_COMMAND_INJ,
CommonAlertTag.TEST_TIMING));
alertTags.put(PolicyTag.API.getTag(), "");
alertTags.put(PolicyTag.DEV_CICD.getTag(), "");
alertTags.put(PolicyTag.DEV_STD.getTag(), "");
Expand Down Expand Up @@ -367,6 +368,15 @@ public Map<String, String> getAlertTags() {
return ALERT_TAGS;
}

private Map<String, String> getNeededAlertTags(TestType type) {
Map<String, String> alertTags = new HashMap<>();
alertTags.putAll(getAlertTags());
if (TestType.FEEDBACK.equals(type)) {
alertTags.remove(CommonAlertTag.TEST_TIMING.getTag());
}
return alertTags;
}

@Override
public int getCweId() {
return 78;
Expand Down Expand Up @@ -584,7 +594,14 @@ private boolean testCommandInjection(
paramValue);
String otherInfo = getOtherInfo(TestType.FEEDBACK, paramValue);

buildAlert(paramName, paramValue, matcher.group(), otherInfo, msg).raise();
buildAlert(
paramName,
paramValue,
matcher.group(),
otherInfo,
TestType.FEEDBACK,
msg)
.raise();

// All done. No need to look for vulnerabilities on subsequent
// payloads on the same request (to reduce performance impact)
Expand Down Expand Up @@ -670,7 +687,8 @@ private boolean testCommandInjection(
String otherInfo = getOtherInfo(TestType.TIME, paramValue);

// just attach this alert to the last sent message
buildAlert(paramName, paramValue, "", otherInfo, message.get()).raise();
buildAlert(paramName, paramValue, "", otherInfo, TestType.TIME, message.get())
.raise();

// All done. No need to look for vulnerabilities on subsequent
// payloads on the same request (to reduce performance impact)
Expand Down Expand Up @@ -719,14 +737,20 @@ private static String insertUninitVar(String cmd) {
}

private AlertBuilder buildAlert(
String param, String attack, String evidence, String otherInfo, HttpMessage msg) {
String param,
String attack,
String evidence,
String otherInfo,
TestType type,
HttpMessage msg) {
return newAlert()
.setConfidence(Alert.CONFIDENCE_MEDIUM)
.setParam(param)
.setAttack(attack)
.setEvidence(evidence)
.setMessage(msg)
.setOtherInfo(otherInfo);
.setOtherInfo(otherInfo)
.setTags(getNeededAlertTags(type));
}

@Override
Expand All @@ -737,6 +761,7 @@ public List<Alert> getExampleAlerts() {
"a;cat /etc/passwd ",
"root:x:0:0",
getOtherInfo(TestType.FEEDBACK, "a;cat /etc/passwd "),
TestType.FEEDBACK,
null)
.build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ public class SqlInjectionHypersonicScanRule extends AbstractAppParamPlugin
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_05_SQLI));
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
CommonAlertTag.TEST_TIMING));
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
alertTags.put(PolicyTag.QA_STD.getTag(), "");
alertTags.put(PolicyTag.QA_FULL.getTag(), "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ public class SqlInjectionMsSqlScanRule extends AbstractAppParamPlugin
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_05_SQLI));
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
CommonAlertTag.TEST_TIMING));
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
alertTags.put(PolicyTag.QA_STD.getTag(), "");
alertTags.put(PolicyTag.QA_FULL.getTag(), "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ public class SqlInjectionMySqlScanRule extends AbstractAppParamPlugin
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_05_SQLI));
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
CommonAlertTag.TEST_TIMING));
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
alertTags.put(PolicyTag.QA_STD.getTag(), "");
alertTags.put(PolicyTag.QA_FULL.getTag(), "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ public class SqlInjectionOracleScanRule extends AbstractAppParamPlugin
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_05_SQLI));
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
CommonAlertTag.TEST_TIMING));
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
alertTags.put(PolicyTag.QA_STD.getTag(), "");
alertTags.put(PolicyTag.QA_FULL.getTag(), "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ public class SqlInjectionPostgreScanRule extends AbstractAppParamPlugin
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_05_SQLI));
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
CommonAlertTag.TEST_TIMING));
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
alertTags.put(PolicyTag.QA_STD.getTag(), "");
alertTags.put(PolicyTag.QA_FULL.getTag(), "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ public class SqlInjectionSqLiteScanRule extends AbstractAppParamPlugin
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_05_SQLI));
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
CommonAlertTag.TEST_TIMING));
alertTags.put(PolicyTag.QA_FULL.getTag(), "");
ALERT_TAGS = Collections.unmodifiableMap(alertTags);
}
Expand Down Expand Up @@ -458,6 +459,7 @@ public void scan(HttpMessage originalMessage, String paramName, String originalP
.setOtherInfo(extraInfo)
.setEvidence(matcher.group())
.setMessage(msgDelay)
.setTags(getNeededAlertTags(true))
.raise();

LOGGER.debug(
Expand Down Expand Up @@ -600,6 +602,7 @@ public void scan(HttpMessage originalMessage, String paramName, String originalP
.setOtherInfo(extraInfo)
.setEvidence(extraInfo)
.setMessage(detectableDelayMessage)
.setTags(getNeededAlertTags(false))
.raise();

if (detectableDelayMessage != null)
Expand Down Expand Up @@ -752,6 +755,7 @@ public void scan(HttpMessage originalMessage, String paramName, String originalP
.setOtherInfo(extraInfo)
.setEvidence(versionNumber)
.setMessage(unionAttackMessage)
.setTags(getNeededAlertTags(true))
.raise();
break unionLoops;
}
Expand Down Expand Up @@ -804,4 +808,13 @@ public int getWascId() {
public Map<String, String> getAlertTags() {
return ALERT_TAGS;
}

private Map<String, String> getNeededAlertTags(boolean isFeedbackbased) {
Map<String, String> alertTags = new HashMap<>();
alertTags.putAll(getAlertTags());
if (isFeedbackbased) {
alertTags.remove(CommonAlertTag.TEST_TIMING.getTag());
}
return alertTags;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public class SstiBlindScanRule extends AbstractAppParamPlugin implements CommonA
CommonAlertTag.toMap(
CommonAlertTag.OWASP_2021_A03_INJECTION,
CommonAlertTag.OWASP_2017_A01_INJECTION,
CommonAlertTag.WSTG_V42_INPV_18_SSTI));
CommonAlertTag.WSTG_V42_INPV_18_SSTI,
CommonAlertTag.TEST_TIMING));
alertTags.put(ExtensionOast.OAST_ALERT_TAG_KEY, ExtensionOast.OAST_ALERT_TAG_VALUE);
alertTags.put(PolicyTag.API.getTag(), "");
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
Expand Down Expand Up @@ -95,7 +96,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(78)));
assertThat(wasc, is(equalTo(31)));
assertThat(tags.size(), is(equalTo(10)));
assertThat(tags.size(), is(equalTo(11)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand Down Expand Up @@ -378,6 +379,8 @@ void shouldHaveExpectedExampleAlert() {
"The scan rule was able to retrieve the content of a file or "
+ "command by sending [a;cat /etc/passwd ] to the operating "
+ "system running this application.")));
Map<String, String> tags = alert.getTags();
assertThat(tags, not(hasKey(CommonAlertTag.TEST_TIMING.getTag())));
}

private static class PayloadCollectorHandler extends NanoServerHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(89)));
assertThat(wasc, is(equalTo(19)));
assertThat(tags.size(), is(equalTo(7)));
assertThat(tags.size(), is(equalTo(8)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand All @@ -168,6 +168,7 @@ void shouldReturnExpectedMappings() {
assertThat(tags.containsKey(PolicyTag.QA_STD.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.QA_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.SEQUENCE.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
assertThat(
tags.get(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(CommonAlertTag.OWASP_2021_A03_INJECTION.getValue())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(89)));
assertThat(wasc, is(equalTo(19)));
assertThat(tags.size(), is(equalTo(7)));
assertThat(tags.size(), is(equalTo(8)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand All @@ -163,6 +163,7 @@ void shouldReturnExpectedMappings() {
assertThat(tags.containsKey(PolicyTag.QA_STD.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.QA_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.SEQUENCE.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
assertThat(
tags.get(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(CommonAlertTag.OWASP_2021_A03_INJECTION.getValue())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(89)));
assertThat(wasc, is(equalTo(19)));
assertThat(tags.size(), is(equalTo(7)));
assertThat(tags.size(), is(equalTo(8)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand All @@ -162,6 +162,7 @@ void shouldReturnExpectedMappings() {
assertThat(tags.containsKey(PolicyTag.QA_STD.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.QA_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.SEQUENCE.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
assertThat(
tags.get(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(CommonAlertTag.OWASP_2021_A03_INJECTION.getValue())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(89)));
assertThat(wasc, is(equalTo(19)));
assertThat(tags.size(), is(equalTo(7)));
assertThat(tags.size(), is(equalTo(8)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand All @@ -158,6 +158,7 @@ void shouldReturnExpectedMappings() {
assertThat(tags.containsKey(PolicyTag.QA_STD.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.QA_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.SEQUENCE.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
assertThat(
tags.get(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(CommonAlertTag.OWASP_2021_A03_INJECTION.getValue())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(89)));
assertThat(wasc, is(equalTo(19)));
assertThat(tags.size(), is(equalTo(7)));
assertThat(tags.size(), is(equalTo(8)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand All @@ -171,6 +171,7 @@ void shouldReturnExpectedMappings() {
assertThat(tags.containsKey(PolicyTag.QA_STD.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.QA_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.SEQUENCE.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
assertThat(
tags.get(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(CommonAlertTag.OWASP_2021_A03_INJECTION.getValue())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;

import fi.iki.elonen.NanoHTTPD.IHTTPSession;
Expand Down Expand Up @@ -114,6 +116,7 @@ protected Response serve(IHTTPSession session) {
equalTo("case randomblob(100000) when not null then 1 else 1 end "));
assertThat(alertsRaised.get(0).getRisk(), equalTo(Alert.RISK_HIGH));
assertThat(alertsRaised.get(0).getConfidence(), equalTo(Alert.CONFIDENCE_MEDIUM));
assertThat(alertsRaised.get(0).getTags(), not(hasKey(CommonAlertTag.TEST_TIMING.getTag())));
}

@Test
Expand Down Expand Up @@ -155,6 +158,7 @@ protected Response serve(IHTTPSession session) {
assertThat(alertsRaised.get(0).getAttack(), startsWith("case randomblob(100"));
assertThat(alertsRaised.get(0).getRisk(), equalTo(Alert.RISK_HIGH));
assertThat(alertsRaised.get(0).getConfidence(), equalTo(Alert.CONFIDENCE_MEDIUM));
assertThat(alertsRaised.get(0).getTags(), is(hasKey(CommonAlertTag.TEST_TIMING.getTag())));
}

@Test
Expand Down Expand Up @@ -197,7 +201,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(89)));
assertThat(wasc, is(equalTo(19)));
assertThat(tags.size(), is(equalTo(4)));
assertThat(tags.size(), is(equalTo(5)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand All @@ -207,6 +211,7 @@ void shouldReturnExpectedMappings() {
assertThat(
tags.containsKey(CommonAlertTag.WSTG_V42_INPV_05_SQLI.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.QA_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
assertThat(
tags.get(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(CommonAlertTag.OWASP_2021_A03_INJECTION.getValue())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ void shouldReturnExpectedMappings() {
// Then
assertThat(cwe, is(equalTo(1336)));
assertThat(wasc, is(equalTo(20)));
assertThat(tags.size(), is(equalTo(8)));
assertThat(tags.size(), is(equalTo(9)));
assertThat(
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(true)));
Expand All @@ -157,6 +157,7 @@ void shouldReturnExpectedMappings() {
assertThat(tags.containsKey(PolicyTag.DEV_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.QA_FULL.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(PolicyTag.SEQUENCE.getTag()), is(equalTo(true)));
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
assertThat(
tags.get(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
is(equalTo(CommonAlertTag.OWASP_2021_A03_INJECTION.getValue())));
Expand Down
Loading

0 comments on commit 58f25e1

Please sign in to comment.