Skip to content

Commit f85bce4

Browse files
committed
ascanrulesBeta: Insecure HTTP Method rule - Address potential FP
Signed-off-by: kingthorin <[email protected]>
1 parent 5ade4e3 commit f85bce4

File tree

3 files changed

+244
-86
lines changed

3 files changed

+244
-86
lines changed

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

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ public class InsecureHttpMethodScanRule extends AbstractAppPlugin
9898
INSECURE_METHODS.addAll(WEBDAV_METHODS);
9999
}
100100

101+
private static final Set<String> METHODS_TO_SKIP =
102+
Set.of(HttpRequestHeader.GET, HttpRequestHeader.POST, HttpRequestHeader.HEAD);
103+
104+
/*
105+
* Build a list with status codes which indicate that this HTTP method is
106+
* enabled but we are not allowed to use it
107+
*/
108+
private static final List<Integer> ENABLED_STATUS_CODES =
109+
List.of(
110+
HttpStatusCode.UNAUTHORIZED,
111+
HttpStatusCode.PAYMENT_REQUIRED,
112+
HttpStatusCode.FORBIDDEN);
113+
101114
private static final Map<String, String> ALERT_TAGS;
102115

103116
static {
@@ -150,7 +163,7 @@ public void scan() {
150163
String thirdpartyHost = "www.google.com";
151164
int thirdpartyPort = 80;
152165
Pattern thirdPartyContentPattern =
153-
Pattern.compile("<title.*{1,10}Google.{1,25}/title>", Pattern.CASE_INSENSITIVE);
166+
Pattern.compile("<title.{1,10}Google.{1,25}/title>", Pattern.CASE_INSENSITIVE);
154167

155168
// send an OPTIONS message, and see what the server reports. Do
156169
// not try any methods not listed in those results.
@@ -191,7 +204,12 @@ public void scan() {
191204
// Convert the list to a set so that we have a unique list
192205
Set<String> enabledMethodsSet =
193206
new HashSet<>(
194-
Arrays.asList(allowedmethods.toUpperCase(Locale.ROOT).split(",")));
207+
Arrays.stream(allowedmethods.toUpperCase(Locale.ROOT).split(","))
208+
.map(String::trim) // strip off any leading spaces (it happens!)
209+
.toList());
210+
211+
// Remove methods we aren't concerned about
212+
enabledMethodsSet.removeAll(METHODS_TO_SKIP);
195213
if (enabledMethodsSet.contains(HttpRequestHeader.DELETE)) {
196214
enabledMethodsSet.remove(
197215
HttpRequestHeader
@@ -245,12 +263,6 @@ public void scan() {
245263
// rely on the OPTIONS METHOD, but potentially verify the
246264
// results, depending on the Threshold.
247265
for (String enabledmethod : enabledMethodsSet) {
248-
enabledmethod =
249-
enabledmethod.trim(); // strip off any leading spaces (it happens!)
250-
if (enabledmethod.isEmpty()) {
251-
continue;
252-
}
253-
254266
LOGGER.debug(
255267
"The following enabled method is being checked: '{}'", enabledmethod);
256268
String insecureMethod = enabledmethod;
@@ -306,10 +318,9 @@ public void scan() {
306318

307319
if (raiseAlert) {
308320
LOGGER.debug("Raising alert for Insecure HTTP Method");
309-
310321
newAlert()
311322
.setRisk(riskLevel)
312-
.setConfidence(Alert.CONFIDENCE_MEDIUM)
323+
.setConfidence(Alert.CONFIDENCE_LOW)
313324
.setName(
314325
Constant.messages.getString(
315326
"ascanbeta.insecurehttpmethod.detailed.name",
@@ -565,16 +576,6 @@ private void testHttpMethod(String httpMethod) throws Exception {
565576
}
566577

567578
final int responseCode = msg.getResponseHeader().getStatusCode();
568-
String evidence = "";
569-
570-
/*
571-
* Build a list with status code which indicate that this HTTP method is
572-
* enabled but we are not allowed to use it
573-
*/
574-
final ArrayList<Integer> enabledStatusCodes = new ArrayList<>();
575-
enabledStatusCodes.add(HttpStatusCode.UNAUTHORIZED);
576-
enabledStatusCodes.add(HttpStatusCode.PAYMENT_REQUIRED);
577-
enabledStatusCodes.add(HttpStatusCode.FORBIDDEN);
578579

579580
LOGGER.debug("Request Method: {}", httpMethod);
580581
LOGGER.debug("Response Code: {}", responseCode);
@@ -584,19 +585,15 @@ private void testHttpMethod(String httpMethod) throws Exception {
584585
return;
585586
}
586587

587-
if (isPage200(msg) || responseCode == HttpStatusCode.CREATED) {
588-
evidence =
589-
Constant.messages.getString(
590-
"ascanbeta.insecurehttpmethod.insecure", responseCode);
591-
} else if (enabledStatusCodes.contains(responseCode)) {
592-
evidence =
588+
boolean isEnabledStatus = ENABLED_STATUS_CODES.contains(responseCode);
589+
String furtherInfo = "";
590+
591+
if (isEnabledStatus) {
592+
furtherInfo =
593593
Constant.messages.getString(
594594
"ascanbeta.insecurehttpmethod.potentiallyinsecure", responseCode);
595-
} else {
596-
return;
597595
}
598596

599-
int riskLevel;
600597
String exploitableDesc;
601598
String exploitableExtraInfo;
602599
if (WEBDAV_METHODS.contains(httpMethod)) {
@@ -606,7 +603,6 @@ private void testHttpMethod(String httpMethod) throws Exception {
606603
exploitableExtraInfo =
607604
Constant.messages.getString(
608605
"ascanbeta.insecurehttpmethod.webdav.exploitable.extrainfo");
609-
riskLevel = Alert.RISK_INFO;
610606
} else {
611607
exploitableDesc =
612608
Constant.messages.getString(
@@ -619,24 +615,24 @@ private void testHttpMethod(String httpMethod) throws Exception {
619615
"ascanbeta.insecurehttpmethod."
620616
+ httpMethod.toLowerCase()
621617
+ ".exploitable.extrainfo");
622-
623-
riskLevel = Alert.RISK_MEDIUM;
624618
}
625-
try {
626619

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)
636-
.setMessage(msg)
637-
.raise();
638-
} catch (Exception e) {
639-
}
620+
exploitableExtraInfo =
621+
StringUtils.isNotEmpty(furtherInfo)
622+
? furtherInfo + "\n\n" + exploitableExtraInfo
623+
: exploitableExtraInfo;
624+
625+
newAlert()
626+
.setRisk(Alert.RISK_MEDIUM)
627+
.setConfidence(isEnabledStatus ? Alert.CONFIDENCE_LOW : Alert.CONFIDENCE_MEDIUM)
628+
.setName(
629+
Constant.messages.getString(
630+
"ascanbeta.insecurehttpmethod.detailed.name", httpMethod))
631+
.setDescription(exploitableDesc)
632+
.setOtherInfo(exploitableExtraInfo)
633+
.setEvidence(String.valueOf(responseCode))
634+
.setMessage(msg)
635+
.raise();
640636
}
641637

642638
private static String randomAlphanumeric(int count) {

addOns/ascanrulesBeta/src/main/resources/org/zaproxy/zap/extension/ascanrulesBeta/resources/Messages.properties

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,12 @@ ascanbeta.insecurehttpmethod.delete.exploitable.extrainfo = See the discussion o
9393
ascanbeta.insecurehttpmethod.desc = The insecure HTTP method [{0}] is enabled on the web server for this resource. Depending on the web server configuration, and the underlying implementation responsible for serving the resource, this might or might not be exploitable. The TRACK and TRACE methods may be used by an attacker, to gain access to the authorisation token/session cookie of an application user, even if the session cookie is protected using the 'HttpOnly' flag. For the attack to be successful, the application user must typically be using an older web browser, or a web browser which has a Same Origin Policy (SOP) bypass vulnerability. The 'CONNECT' method can be used by a web client to create an HTTP tunnel to third party websites or services.
9494
ascanbeta.insecurehttpmethod.detailed.name = Insecure HTTP Method - {0}
9595
ascanbeta.insecurehttpmethod.extrainfo = The OPTIONS method disclosed the following enabled HTTP methods for this resource: [{0}]
96-
ascanbeta.insecurehttpmethod.insecure = response code {0} for insecure HTTP METHOD
9796
ascanbeta.insecurehttpmethod.name = Insecure HTTP Method
9897
ascanbeta.insecurehttpmethod.options.exploitable.desc = This is a diagnostic method and should never be turned on in production mode.
9998
ascanbeta.insecurehttpmethod.options.exploitable.extrainfo = See the discussion on stackexchange: https://security.stackexchange.com/questions/21413/how-to-exploit-http-methods
10099
ascanbeta.insecurehttpmethod.patch.exploitable.desc = This method is now most commonly used in REST services, PATCH is used for **modify** capabilities. The PATCH request only needs to contain the changes to the resource, not the complete resource.
101100
ascanbeta.insecurehttpmethod.patch.exploitable.extrainfo = See the discussion on stackexchange: https://security.stackexchange.com/questions/21413/how-to-exploit-http-methods, for understanding REST operations see https://www.restapitutorial.com/lessons/httpmethods.html
102-
ascanbeta.insecurehttpmethod.potentiallyinsecure = response code {0} for potentially insecure HTTP METHOD
101+
ascanbeta.insecurehttpmethod.potentiallyinsecure = Received response code {0} for potentially insecure HTTP method. This suggests it is enabled or supported but some control prevented us from actually using it.
103102
ascanbeta.insecurehttpmethod.put.exploitable.desc = This method was originally intended for file management operations. It is now most commonly used in REST services, PUT is most-often utilized for **update** capabilities, PUT-ing to a known resource URI with the request body containing the newly-updated representation of the original resource.
104103
ascanbeta.insecurehttpmethod.put.exploitable.extrainfo = See the discussion on stackexchange: https://security.stackexchange.com/questions/21413/how-to-exploit-http-methods, for understanding REST operations see https://www.restapitutorial.com/lessons/httpmethods.html
105104
ascanbeta.insecurehttpmethod.soln = Disable insecure methods such as TRACK, TRACE, and CONNECT on the web server, and ensure that the underlying service implementation does not support insecure methods.

0 commit comments

Comments
 (0)