Skip to content

Commit f1a7e70

Browse files
committed
Added alert references
Signed-off-by: Brandosp <[email protected]>
1 parent f903877 commit f1a7e70

File tree

3 files changed

+176
-75
lines changed

3 files changed

+176
-75
lines changed

addOns/ascanrulesBeta/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1010
### Changed
1111
- Depends on an updated version of the Common Library add-on.
1212
- Reduced usage of error level logging.
13+
- Insecure Http Method Scan Rule now includes example alert functionality for documentation generation purposes (Issue 6119)
1314

1415
## [62] - 2025-09-18
1516
### Added

addOns/ascanrulesBeta/src/main/java/org/zaproxy/zap/extension/ascanrulesBeta/InsecureHttpMethodScanRule.java

Lines changed: 146 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -196,24 +196,7 @@ public void scan() {
196196
enabledMethodsSet.remove(
197197
HttpRequestHeader
198198
.DELETE); // We don't actually want to make a DELETE request
199-
newAlert()
200-
.setConfidence(Alert.CONFIDENCE_MEDIUM)
201-
.setName(
202-
Constant.messages.getString(
203-
"ascanbeta.insecurehttpmethod.detailed.name",
204-
HttpRequestHeader.DELETE))
205-
.setDescription(
206-
Constant.messages.getString(
207-
"ascanbeta.insecurehttpmethod.desc",
208-
HttpRequestHeader.DELETE))
209-
.setOtherInfo(
210-
Constant.messages.getString(
211-
"ascanbeta.insecurehttpmethod.extrainfo", allowedmethods))
212-
.setSolution(
213-
Constant.messages.getString("ascanbeta.insecurehttpmethod.soln"))
214-
.setEvidence(HttpRequestHeader.DELETE)
215-
.setMessage(optionsmsg)
216-
.raise();
199+
buildDeleteMethodAlert(allowedmethods).setMessage(optionsmsg).raise();
217200
}
218201

219202
if (attackStrength == AttackStrength.HIGH || attackStrength == AttackStrength.INSANE) {
@@ -307,19 +290,8 @@ public void scan() {
307290
if (raiseAlert) {
308291
LOGGER.debug("Raising alert for Insecure HTTP Method");
309292

310-
newAlert()
311-
.setRisk(riskLevel)
312-
.setConfidence(Alert.CONFIDENCE_MEDIUM)
313-
.setName(
314-
Constant.messages.getString(
315-
"ascanbeta.insecurehttpmethod.detailed.name",
316-
insecureMethod))
317-
.setDescription(description)
318-
.setOtherInfo(extraInfo)
319-
.setSolution(
320-
Constant.messages.getString(
321-
"ascanbeta.insecurehttpmethod.soln"))
322-
.setEvidence(evidence)
293+
buildInsecureHttpMethodAlert(
294+
riskLevel, insecureMethod, description, extraInfo, evidence)
323295
.setMessage(alertMessage)
324296
.raise();
325297
}
@@ -376,21 +348,8 @@ private void testTraceOrTrack(String method) throws Exception {
376348

377349
// if the response *body* from the TRACE request contains the cookie,we're in business :)
378350
if (msg.getResponseBody().toString().contains(randomcookievalue)) {
379-
newAlert()
380-
.setConfidence(Alert.CONFIDENCE_MEDIUM)
381-
.setName(
382-
Constant.messages.getString(
383-
"ascanbeta.insecurehttpmethod.detailed.name", method))
384-
.setDescription(
385-
Constant.messages.getString(
386-
"ascanbeta.insecurehttpmethod.trace.exploitable.desc", method))
387-
.setUri(msg.getRequestHeader().getURI().toString())
388-
.setOtherInfo(
389-
Constant.messages.getString(
390-
"ascanbeta.insecurehttpmethod.trace.exploitable.extrainfo",
391-
randomcookievalue))
392-
.setSolution(Constant.messages.getString("ascanbeta.insecurehttpmethod.soln"))
393-
.setEvidence(randomcookievalue)
351+
buildTraceCookieAlert(
352+
randomcookievalue, method, msg.getRequestHeader().getURI().toString())
394353
.setMessage(msg)
395354
.raise();
396355
}
@@ -495,24 +454,7 @@ private void handleConnectResponse(
495454
Matcher m = thirdPartyContentPattern.matcher(response);
496455
if (m.matches()) {
497456
LOGGER.debug("Response matches expected third party pattern!");
498-
newAlert()
499-
.setConfidence(Alert.CONFIDENCE_MEDIUM)
500-
.setName(
501-
Constant.messages.getString(
502-
"ascanbeta.insecurehttpmethod.detailed.name",
503-
HttpRequestHeader.CONNECT))
504-
.setDescription(
505-
Constant.messages.getString(
506-
"ascanbeta.insecurehttpmethod.connect.exploitable.desc",
507-
HttpRequestHeader.CONNECT))
508-
.setOtherInfo(
509-
Constant.messages.getString(
510-
"ascanbeta.insecurehttpmethod.connect.exploitable.extrainfo",
511-
thirdpartyHost))
512-
.setSolution(
513-
Constant.messages.getString(
514-
"ascanbeta.insecurehttpmethod.soln"))
515-
.setEvidence(response)
457+
buildConnectResponseAlert(thirdpartyHost, response)
516458
.setMessage(this.getBaseMsg())
517459
.raise();
518460
} else {
@@ -624,22 +566,151 @@ private void testHttpMethod(String httpMethod) throws Exception {
624566
}
625567
try {
626568

627-
newAlert()
628-
.setRisk(riskLevel)
629-
.setConfidence(Alert.CONFIDENCE_MEDIUM)
630-
.setName(
631-
Constant.messages.getString(
632-
"ascanbeta.insecurehttpmethod.detailed.name", httpMethod))
633-
.setDescription(exploitableDesc)
634-
.setOtherInfo(exploitableExtraInfo)
635-
.setEvidence(evidence)
569+
buildHttpMethodAlert(
570+
riskLevel, httpMethod, exploitableDesc, exploitableExtraInfo, evidence)
636571
.setMessage(msg)
637572
.raise();
638573
} catch (Exception e) {
639574
}
640575
}
641576

642-
private static String randomAlphanumeric(int count) {
643-
return RandomStringUtils.secure().nextAlphanumeric(count);
577+
private static String randomAlphanumeric(int cournt) {
578+
return RandomStringUtils.secure().nextAlphanumeric(cournt);
579+
}
580+
581+
private AlertBuilder buildDeleteMethodAlert(String allowedmethods) {
582+
return newAlert()
583+
.setConfidence(Alert.CONFIDENCE_MEDIUM)
584+
.setName(
585+
Constant.messages.getString(
586+
"ascanbeta.insecurehttpmethod.detailed.name",
587+
HttpRequestHeader.DELETE))
588+
.setDescription(
589+
Constant.messages.getString(
590+
"ascanbeta.insecurehttpmethod.desc", HttpRequestHeader.DELETE))
591+
.setOtherInfo(
592+
Constant.messages.getString(
593+
"ascanbeta.insecurehttpmethod.extrainfo", allowedmethods))
594+
.setSolution(Constant.messages.getString("ascanbeta.insecurehttpmethod.soln"))
595+
.setEvidence(HttpRequestHeader.DELETE)
596+
.setAlertRef(getId() + "-1");
597+
}
598+
599+
private AlertBuilder buildInsecureHttpMethodAlert(
600+
int riskLevel,
601+
String insecureMethod,
602+
String description,
603+
String extraInfo,
604+
String evidence) {
605+
return newAlert()
606+
.setRisk(riskLevel)
607+
.setConfidence(Alert.CONFIDENCE_MEDIUM)
608+
.setName(
609+
Constant.messages.getString(
610+
"ascanbeta.insecurehttpmethod.detailed.name", insecureMethod))
611+
.setDescription(description)
612+
.setOtherInfo(extraInfo)
613+
.setSolution(Constant.messages.getString("ascanbeta.insecurehttpmethod.soln"))
614+
.setEvidence(evidence)
615+
.setAlertRef(getId() + "-2");
616+
}
617+
618+
private AlertBuilder buildTraceCookieAlert(
619+
String randomcookievalue, String method, String URI) {
620+
return newAlert()
621+
.setConfidence(Alert.CONFIDENCE_MEDIUM)
622+
.setName(
623+
Constant.messages.getString(
624+
"ascanbeta.insecurehttpmethod.detailed.name", method))
625+
.setDescription(
626+
Constant.messages.getString(
627+
"ascanbeta.insecurehttpmethod.trace.exploitable.desc", method))
628+
.setUri(URI)
629+
.setOtherInfo(
630+
Constant.messages.getString(
631+
"ascanbeta.insecurehttpmethod.trace.exploitable.extrainfo",
632+
randomcookievalue))
633+
.setSolution(Constant.messages.getString("ascanbeta.insecurehttpmethod.soln"))
634+
.setEvidence(randomcookievalue)
635+
.setAlertRef(getId() + "-3");
636+
}
637+
638+
private AlertBuilder buildConnectResponseAlert(String thirdpartyHost, String response) {
639+
return newAlert()
640+
.setConfidence(Alert.CONFIDENCE_MEDIUM)
641+
.setName(
642+
Constant.messages.getString(
643+
"ascanbeta.insecurehttpmethod.detailed.name",
644+
HttpRequestHeader.CONNECT))
645+
.setDescription(
646+
Constant.messages.getString(
647+
"ascanbeta.insecurehttpmethod.connect.exploitable.desc",
648+
HttpRequestHeader.CONNECT))
649+
.setOtherInfo(
650+
Constant.messages.getString(
651+
"ascanbeta.insecurehttpmethod.connect.exploitable.extrainfo",
652+
thirdpartyHost))
653+
.setSolution(Constant.messages.getString("ascanbeta.insecurehttpmethod.soln"))
654+
.setEvidence(response)
655+
.setAlertRef(getId() + "-4");
656+
}
657+
658+
private AlertBuilder buildHttpMethodAlert(
659+
int riskLevel,
660+
String httpMethod,
661+
String exploitableDesc,
662+
String exploitableExtraInfo,
663+
String evidence) {
664+
return newAlert()
665+
.setRisk(riskLevel)
666+
.setConfidence(Alert.CONFIDENCE_MEDIUM)
667+
.setName(
668+
Constant.messages.getString(
669+
"ascanbeta.insecurehttpmethod.detailed.name", httpMethod))
670+
.setDescription(exploitableDesc)
671+
.setOtherInfo(exploitableExtraInfo)
672+
.setEvidence(evidence)
673+
.setAlertRef(getId() + "-5");
674+
}
675+
676+
@Override
677+
public List<Alert> getExampleAlerts() {
678+
return List.of(
679+
buildDeleteMethodAlert("GET, POST, OPTIONS, HEAD, DELETE").build(),
680+
buildInsecureHttpMethodAlert(
681+
Alert.RISK_MEDIUM,
682+
"PUT",
683+
"PUT",
684+
"GET, POST, HEAD, OPTIONS, PUT, DELETE",
685+
"PUT")
686+
.build(),
687+
buildTraceCookieAlert(
688+
"aB3kL9zT2vQw8Xy1RmNp6sGh4Ud7Fc0ZjK9yX2mP",
689+
"TRACE",
690+
"http://example.com/")
691+
.build(),
692+
buildConnectResponseAlert(
693+
"www.google.com",
694+
"HTTP/1.1 200 OK\n"
695+
+ "Date: Sat, 01 Nov 2025 19:33:10 GMT\n"
696+
+ "Content-Type: text/html; charset=ISO-8859-1\n"
697+
+ "Server: gws\n"
698+
+ "Connection: close")
699+
.build(),
700+
buildHttpMethodAlert(
701+
Alert.RISK_MEDIUM,
702+
"PUT",
703+
Constant.messages.getString(
704+
"ascanbeta.insecurehttpmethod."
705+
+ "put"
706+
+ ".exploitable.desc",
707+
"PUT"),
708+
Constant.messages.getString(
709+
"ascanbeta.insecurehttpmethod."
710+
+ "put"
711+
+ ".exploitable.extrainfo"),
712+
Constant.messages.getString(
713+
"ascanbeta.insecurehttpmethod.insecure", 201))
714+
.build());
644715
}
645716
}

addOns/ascanrulesBeta/src/test/java/org/zaproxy/zap/extension/ascanrulesBeta/InsecureHttpMethodScanRuleUnitTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
import fi.iki.elonen.NanoHTTPD.IHTTPSession;
2828
import fi.iki.elonen.NanoHTTPD.Method;
2929
import fi.iki.elonen.NanoHTTPD.Response;
30+
import java.util.List;
3031
import java.util.Map;
3132
import org.junit.jupiter.api.Test;
3233
import org.junit.jupiter.params.ParameterizedTest;
3334
import org.junit.jupiter.params.provider.CsvSource;
3435
import org.junit.jupiter.params.provider.ValueSource;
36+
import org.parosproxy.paros.core.scanner.Alert;
3537
import org.parosproxy.paros.network.HttpMessage;
3638
import org.zaproxy.addon.commonlib.CommonAlertTag;
3739
import org.zaproxy.addon.commonlib.PolicyTag;
@@ -139,4 +141,31 @@ void shouldReturnExpectedMappings() {
139141
tags.get(CommonAlertTag.WSTG_V42_CONF_06_HTTP_METHODS.getTag()),
140142
is(equalTo(CommonAlertTag.WSTG_V42_CONF_06_HTTP_METHODS.getValue())));
141143
}
144+
145+
@Test
146+
void shouldHaveExpectedExampleAlert() {
147+
List<Alert> alerts = rule.getExampleAlerts();
148+
149+
assertThat(alerts.size(), is(equalTo(5)));
150+
Alert deleteAlert = alerts.get(0);
151+
assertThat(deleteAlert.getAlertRef(), is(equalTo("90028-1")));
152+
153+
Alert insecureHttpAlert = alerts.get(1);
154+
assertThat(insecureHttpAlert.getAlertRef(), is(equalTo("90028-2")));
155+
156+
Alert cookieAlert = alerts.get(2);
157+
assertThat(cookieAlert.getAlertRef(), is(equalTo("90028-3")));
158+
159+
Alert connectResponseAlert = alerts.get(3);
160+
assertThat(connectResponseAlert.getAlertRef(), is(equalTo("90028-4")));
161+
162+
Alert httpMethodAlert = alerts.get(4);
163+
assertThat(httpMethodAlert.getAlertRef(), is(equalTo("90028-5")));
164+
}
165+
166+
@Test
167+
@Override
168+
public void shouldHaveValidReferences() {
169+
super.shouldHaveValidReferences();
170+
}
142171
}

0 commit comments

Comments
 (0)