Skip to content

Commit f37a7c5

Browse files
authored
Merge pull request #6015 from kingthorin/timing-tag
Add TEST_TIMING alert tag
2 parents b7a1e06 + a85c49f commit f37a7c5

25 files changed

+198
-37
lines changed

addOns/ascanrules/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1111
### Added
1212
- Rules (as applicable) have been tagged in relation to HIPAA and PCI DSS.
1313
- The Cloud Metadata Potentially Exposed scan rules now has a CWE reference.
14+
- Scan rules which execute time based attacks now include the "TEST_TIMING" alert tag.
1415

1516
## [72] - 2025-06-20
1617
### Added

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/CommandInjectionScanRule.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ public class CommandInjectionScanRule extends AbstractAppParamPlugin
100100
CommonAlertTag.OWASP_2017_A01_INJECTION,
101101
CommonAlertTag.WSTG_V42_INPV_12_COMMAND_INJ,
102102
CommonAlertTag.HIPAA,
103-
CommonAlertTag.PCI_DSS));
103+
CommonAlertTag.PCI_DSS,
104+
CommonAlertTag.TEST_TIMING));
104105
alertTags.put(PolicyTag.API.getTag(), "");
105106
alertTags.put(PolicyTag.DEV_CICD.getTag(), "");
106107
alertTags.put(PolicyTag.DEV_STD.getTag(), "");
@@ -370,6 +371,16 @@ public Map<String, String> getAlertTags() {
370371
return ALERT_TAGS;
371372
}
372373

374+
private Map<String, String> getNeededAlertTags(TestType type) {
375+
if (TestType.FEEDBACK.equals(type)) {
376+
Map<String, String> alertTags = new HashMap<>();
377+
alertTags.putAll(getAlertTags());
378+
alertTags.remove(CommonAlertTag.TEST_TIMING.getTag());
379+
return alertTags;
380+
}
381+
return getAlertTags();
382+
}
383+
373384
@Override
374385
public int getCweId() {
375386
return 78;
@@ -585,9 +596,9 @@ private boolean testCommandInjection(
585596
"[OS Command Injection Found] on parameter [{}] with value [{}]",
586597
paramName,
587598
paramValue);
588-
String otherInfo = getOtherInfo(TestType.FEEDBACK, paramValue);
589599

590-
buildAlert(paramName, paramValue, matcher.group(), otherInfo, msg).raise();
600+
buildAlert(paramName, paramValue, matcher.group(), TestType.FEEDBACK, msg)
601+
.raise();
591602

592603
// All done. No need to look for vulnerabilities on subsequent
593604
// payloads on the same request (to reduce performance impact)
@@ -670,10 +681,9 @@ private boolean testCommandInjection(
670681
"[Blind OS Command Injection Found] on parameter [{}] with value [{}]",
671682
paramName,
672683
paramValue);
673-
String otherInfo = getOtherInfo(TestType.TIME, paramValue);
674684

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

678688
// All done. No need to look for vulnerabilities on subsequent
679689
// payloads on the same request (to reduce performance impact)
@@ -722,25 +732,22 @@ private static String insertUninitVar(String cmd) {
722732
}
723733

724734
private AlertBuilder buildAlert(
725-
String param, String attack, String evidence, String otherInfo, HttpMessage msg) {
735+
String param, String attack, String evidence, TestType type, HttpMessage msg) {
736+
String otherInfo = getOtherInfo(type, attack);
726737
return newAlert()
727738
.setConfidence(Alert.CONFIDENCE_MEDIUM)
728739
.setParam(param)
729740
.setAttack(attack)
730741
.setEvidence(evidence)
731742
.setMessage(msg)
732-
.setOtherInfo(otherInfo);
743+
.setOtherInfo(otherInfo)
744+
.setTags(getNeededAlertTags(type));
733745
}
734746

735747
@Override
736748
public List<Alert> getExampleAlerts() {
737749
return List.of(
738-
buildAlert(
739-
"qry",
740-
"a;cat /etc/passwd ",
741-
"root:x:0:0",
742-
getOtherInfo(TestType.FEEDBACK, "a;cat /etc/passwd "),
743-
null)
750+
buildAlert("qry", "a;cat /etc/passwd ", "root:x:0:0", TestType.FEEDBACK, null)
744751
.build());
745752
}
746753
}

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionHypersonicScanRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ public class SqlInjectionHypersonicScanRule extends AbstractAppParamPlugin
201201
CommonAlertTag.OWASP_2017_A01_INJECTION,
202202
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
203203
CommonAlertTag.HIPAA,
204-
CommonAlertTag.PCI_DSS));
204+
CommonAlertTag.PCI_DSS,
205+
CommonAlertTag.TEST_TIMING));
205206
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
206207
alertTags.put(PolicyTag.QA_STD.getTag(), "");
207208
alertTags.put(PolicyTag.QA_FULL.getTag(), "");

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionMsSqlScanRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ public class SqlInjectionMsSqlScanRule extends AbstractAppParamPlugin
146146
CommonAlertTag.OWASP_2017_A01_INJECTION,
147147
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
148148
CommonAlertTag.HIPAA,
149-
CommonAlertTag.PCI_DSS));
149+
CommonAlertTag.PCI_DSS,
150+
CommonAlertTag.TEST_TIMING));
150151
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
151152
alertTags.put(PolicyTag.QA_STD.getTag(), "");
152153
alertTags.put(PolicyTag.QA_FULL.getTag(), "");

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionMySqlScanRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ public class SqlInjectionMySqlScanRule extends AbstractAppParamPlugin
220220
CommonAlertTag.OWASP_2017_A01_INJECTION,
221221
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
222222
CommonAlertTag.HIPAA,
223-
CommonAlertTag.PCI_DSS));
223+
CommonAlertTag.PCI_DSS,
224+
CommonAlertTag.TEST_TIMING));
224225
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
225226
alertTags.put(PolicyTag.QA_STD.getTag(), "");
226227
alertTags.put(PolicyTag.QA_FULL.getTag(), "");

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionOracleScanRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ public class SqlInjectionOracleScanRule extends AbstractAppParamPlugin
156156
CommonAlertTag.OWASP_2017_A01_INJECTION,
157157
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
158158
CommonAlertTag.HIPAA,
159-
CommonAlertTag.PCI_DSS));
159+
CommonAlertTag.PCI_DSS,
160+
CommonAlertTag.TEST_TIMING));
160161
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
161162
alertTags.put(PolicyTag.QA_STD.getTag(), "");
162163
alertTags.put(PolicyTag.QA_FULL.getTag(), "");

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionPostgreScanRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ public class SqlInjectionPostgreScanRule extends AbstractAppParamPlugin
198198
CommonAlertTag.OWASP_2017_A01_INJECTION,
199199
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
200200
CommonAlertTag.HIPAA,
201-
CommonAlertTag.PCI_DSS));
201+
CommonAlertTag.PCI_DSS,
202+
CommonAlertTag.TEST_TIMING));
202203
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");
203204
alertTags.put(PolicyTag.QA_STD.getTag(), "");
204205
alertTags.put(PolicyTag.QA_FULL.getTag(), "");

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionSqLiteScanRule.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ public class SqlInjectionSqLiteScanRule extends AbstractAppParamPlugin
223223
CommonAlertTag.OWASP_2017_A01_INJECTION,
224224
CommonAlertTag.WSTG_V42_INPV_05_SQLI,
225225
CommonAlertTag.HIPAA,
226-
CommonAlertTag.PCI_DSS));
226+
CommonAlertTag.PCI_DSS,
227+
CommonAlertTag.TEST_TIMING));
227228
alertTags.put(PolicyTag.QA_FULL.getTag(), "");
228229
alertTags.put(PolicyTag.PENTEST.getTag(), "");
229230
ALERT_TAGS = Collections.unmodifiableMap(alertTags);
@@ -461,6 +462,7 @@ public void scan(HttpMessage originalMessage, String paramName, String originalP
461462
.setOtherInfo(extraInfo)
462463
.setEvidence(matcher.group())
463464
.setMessage(msgDelay)
465+
.setTags(getNeededAlertTags(true))
464466
.raise();
465467

466468
LOGGER.debug(
@@ -603,6 +605,7 @@ public void scan(HttpMessage originalMessage, String paramName, String originalP
603605
.setOtherInfo(extraInfo)
604606
.setEvidence(extraInfo)
605607
.setMessage(detectableDelayMessage)
608+
.setTags(getNeededAlertTags(false))
606609
.raise();
607610

608611
if (detectableDelayMessage != null)
@@ -755,6 +758,7 @@ public void scan(HttpMessage originalMessage, String paramName, String originalP
755758
.setOtherInfo(extraInfo)
756759
.setEvidence(versionNumber)
757760
.setMessage(unionAttackMessage)
761+
.setTags(getNeededAlertTags(true))
758762
.raise();
759763
break unionLoops;
760764
}
@@ -807,4 +811,14 @@ public int getWascId() {
807811
public Map<String, String> getAlertTags() {
808812
return ALERT_TAGS;
809813
}
814+
815+
private Map<String, String> getNeededAlertTags(boolean isFeedbackBased) {
816+
if (isFeedbackBased) {
817+
Map<String, String> alertTags = new HashMap<>();
818+
alertTags.putAll(getAlertTags());
819+
alertTags.remove(CommonAlertTag.TEST_TIMING.getTag());
820+
return alertTags;
821+
}
822+
return getAlertTags();
823+
}
810824
}

addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SstiBlindScanRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public class SstiBlindScanRule extends AbstractAppParamPlugin implements CommonA
6161
CommonAlertTag.toMap(
6262
CommonAlertTag.OWASP_2021_A03_INJECTION,
6363
CommonAlertTag.OWASP_2017_A01_INJECTION,
64-
CommonAlertTag.WSTG_V42_INPV_18_SSTI));
64+
CommonAlertTag.WSTG_V42_INPV_18_SSTI,
65+
CommonAlertTag.TEST_TIMING));
6566
alertTags.put(ExtensionOast.OAST_ALERT_TAG_KEY, ExtensionOast.OAST_ALERT_TAG_VALUE);
6667
alertTags.put(PolicyTag.API.getTag(), "");
6768
alertTags.put(PolicyTag.DEV_FULL.getTag(), "");

addOns/ascanrules/src/test/java/org/zaproxy/zap/extension/ascanrules/CommandInjectionScanRuleUnitTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static org.hamcrest.MatcherAssert.assertThat;
2424
import static org.hamcrest.Matchers.containsString;
2525
import static org.hamcrest.Matchers.equalTo;
26+
import static org.hamcrest.Matchers.hasKey;
2627
import static org.hamcrest.Matchers.hasSize;
2728
import static org.hamcrest.Matchers.is;
2829
import static org.hamcrest.Matchers.not;
@@ -95,7 +96,7 @@ void shouldReturnExpectedMappings() {
9596
// Then
9697
assertThat(cwe, is(equalTo(78)));
9798
assertThat(wasc, is(equalTo(31)));
98-
assertThat(tags.size(), is(equalTo(13)));
99+
assertThat(tags.size(), is(equalTo(14)));
99100
assertThat(
100101
tags.containsKey(CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()),
101102
is(equalTo(true)));
@@ -107,6 +108,7 @@ void shouldReturnExpectedMappings() {
107108
is(equalTo(true)));
108109
assertThat(tags.containsKey(CommonAlertTag.HIPAA.getTag()), is(equalTo(true)));
109110
assertThat(tags.containsKey(CommonAlertTag.PCI_DSS.getTag()), is(equalTo(true)));
111+
assertThat(tags.containsKey(CommonAlertTag.TEST_TIMING.getTag()), is(equalTo(true)));
110112
assertThat(tags.containsKey(PolicyTag.API.getTag()), is(equalTo(true)));
111113
assertThat(tags.containsKey(PolicyTag.DEV_CICD.getTag()), is(equalTo(true)));
112114
assertThat(tags.containsKey(PolicyTag.DEV_STD.getTag()), is(equalTo(true)));
@@ -381,6 +383,8 @@ void shouldHaveExpectedExampleAlert() {
381383
"The scan rule was able to retrieve the content of a file or "
382384
+ "command by sending [a;cat /etc/passwd ] to the operating "
383385
+ "system running this application.")));
386+
Map<String, String> tags = alert.getTags();
387+
assertThat(tags, not(hasKey(CommonAlertTag.TEST_TIMING.getTag())));
384388
}
385389

386390
private static class PayloadCollectorHandler extends NanoServerHandler {

0 commit comments

Comments
 (0)