Skip to content

Commit 9ac7acc

Browse files
authored
pscanrules: Update CSPMissing for current guidance (Issue 7653) (#4338)
Implementations that followed current guidance with respect to which headers to use would see alerts raised at Low threshold. Now, the alerts reflect the current guidance (ie, don't use the obsolete CSP headers). Make obsolete CSP alert more distinct: - Obsolete CSP header usage is always flagged, not just at LOW - General refactoring suggested by reviewers Support for example alerts. Signed-off-by: David Hall <[email protected]>
1 parent aff94bf commit 9ac7acc

File tree

5 files changed

+156
-92
lines changed

5 files changed

+156
-92
lines changed

addOns/pscanrules/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1414
- The HeartBleed scan rule alert now includes a CVE tag.
1515
- Timestamp Disclosure scan rule now excludes values in "RateLimit-Reset", "X-RateLimit-Reset", and "X-Rate-Limit-Reset" headers (Issue 7747).
1616

17+
### Fixed
18+
- The CSP Missing scan rule now alerts when the Content-Security-Policy header is missing, and when the obsolete X-Content-Security-Policy or X-WebKit-CSP are found (Issue 7653).
19+
1720
## [45] - 2023-01-03
1821
### Changed
1922
- The Private Address Disclosure and Session ID in URL Rewrite scan rules now include example alert functionality for documentation generation purposes (Issue 6119 and 7100).

addOns/pscanrules/src/main/java/org/zaproxy/zap/extension/pscanrules/ContentSecurityPolicyMissingScanRule.java

Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020
package org.zaproxy.zap.extension.pscanrules;
2121

22+
import java.util.Arrays;
2223
import java.util.List;
2324
import java.util.Map;
2425
import net.htmlparser.jericho.Source;
@@ -62,67 +63,16 @@ public void scanHttpResponseReceive(HttpMessage msg, int id, Source source) {
6263
return;
6364
}
6465

65-
// Get the various CSP headers
66-
boolean cspHeaderFound = false,
67-
cspROHeaderFound = false,
68-
xCspHeaderFound = false,
69-
xWebKitHeaderFound = false;
70-
71-
// Content-Security-Policy is supported by Chrome 25+, Firefox 23+, Safari 7+, but not but
72-
// Internet Exploder
73-
List<String> cspOptions =
74-
msg.getResponseHeader().getHeaderValues(HttpFieldsNames.CONTENT_SECURITY_POLICY);
75-
if (!cspOptions.isEmpty()) {
76-
cspHeaderFound = true;
66+
if (!hasCspHeader(msg) && !CspUtils.hasMetaCsp(source)) {
67+
alertMissingCspHeader().raise();
7768
}
7869

79-
List<String> cspROOptions =
80-
msg.getResponseHeader().getHeaderValues("Content-Security-Policy-Report-Only");
81-
if (!cspROOptions.isEmpty()) {
82-
cspROHeaderFound = true;
70+
if (hasObsoleteCspHeader(msg)) {
71+
alertObsoleteCspHeader().raise();
8372
}
8473

85-
// X-Content-Security-Policy is an older header, supported by Firefox 4.0+, and IE 10+ (in a
86-
// limited fashion)
87-
List<String> xcspOptions =
88-
msg.getResponseHeader().getHeaderValues("X-Content-Security-Policy");
89-
if (!xcspOptions.isEmpty()) {
90-
xCspHeaderFound = true;
91-
}
92-
93-
// X-WebKit-CSP is supported by Chrome 14+, and Safari 6+
94-
List<String> xwkcspOptions = msg.getResponseHeader().getHeaderValues("X-WebKit-CSP");
95-
if (!xwkcspOptions.isEmpty()) {
96-
xWebKitHeaderFound = true;
97-
}
98-
99-
if (!cspHeaderFound && !CspUtils.hasMetaCsp(source)
100-
|| (AlertThreshold.LOW.equals(this.getAlertThreshold())
101-
&& (!xCspHeaderFound || !xWebKitHeaderFound))) {
102-
// Always report if the latest header isnt found,
103-
// but only report if the older ones arent present at Low threshold
104-
newAlert()
105-
.setRisk(Alert.RISK_MEDIUM)
106-
.setConfidence(Alert.CONFIDENCE_HIGH)
107-
.setDescription(getAlertAttribute("desc"))
108-
.setSolution(getAlertAttribute("soln"))
109-
.setReference(getAlertAttribute("refs"))
110-
.setCweId(693) // CWE-693: Protection Mechanism Failure
111-
.setWascId(15) // WASC-15: Application Misconfiguration
112-
.raise();
113-
}
114-
115-
if (cspROHeaderFound) {
116-
newAlert()
117-
.setName(getAlertAttribute("ro.name"))
118-
.setRisk(Alert.RISK_INFO)
119-
.setConfidence(Alert.CONFIDENCE_HIGH)
120-
.setDescription(getAlertAttribute("ro.desc"))
121-
.setSolution(getAlertAttribute("soln"))
122-
.setReference(getAlertAttribute("ro.refs"))
123-
.setCweId(693) // CWE-693: Protection Mechanism Failure
124-
.setWascId(15) // WASC-15: Application Misconfiguration
125-
.raise();
74+
if (hasCspReportOnlyHeader(msg)) {
75+
alertCspReportOnlyHeader().raise();
12676
}
12777

12878
LOGGER.debug("\tScan of record {} took {}ms", id, System.currentTimeMillis() - start);
@@ -146,4 +96,57 @@ private String getAlertAttribute(String key) {
14696
public Map<String, String> getAlertTags() {
14797
return ALERT_TAGS;
14898
}
99+
100+
@Override
101+
public List<Alert> getExampleAlerts() {
102+
return Arrays.asList(
103+
alertMissingCspHeader().setUri("https://www.example.com").build(),
104+
alertObsoleteCspHeader().setUri("https://www.example.com").build(),
105+
alertCspReportOnlyHeader().setUri("https://www.example.com").build());
106+
}
107+
108+
private static boolean hasCspHeader(HttpMessage msg) {
109+
return !msg.getResponseHeader()
110+
.getHeaderValues(HttpFieldsNames.CONTENT_SECURITY_POLICY)
111+
.isEmpty();
112+
}
113+
114+
private static boolean hasObsoleteCspHeader(HttpMessage msg) {
115+
return !msg.getResponseHeader().getHeaderValues("X-Content-Security-Policy").isEmpty()
116+
|| !msg.getResponseHeader().getHeaderValues("X-WebKit-CSP").isEmpty();
117+
}
118+
119+
private static boolean hasCspReportOnlyHeader(HttpMessage msg) {
120+
return !msg.getResponseHeader()
121+
.getHeaderValues("Content-Security-Policy-Report-Only")
122+
.isEmpty();
123+
}
124+
125+
private AlertBuilder buildAlert(int risk, int alertNum) {
126+
return newAlert()
127+
.setRisk(risk)
128+
.setConfidence(Alert.CONFIDENCE_HIGH)
129+
.setCweId(693) // CWE-693: Protection Mechanism Failure
130+
.setWascId(15) // WASC-15: Application Misconfiguration
131+
.setSolution(getAlertAttribute("soln"))
132+
.setReference(getAlertAttribute("refs"))
133+
.setAlertRef(PLUGIN_ID + "-" + alertNum);
134+
}
135+
136+
private AlertBuilder alertMissingCspHeader() {
137+
return buildAlert(Alert.RISK_MEDIUM, 1).setDescription(getAlertAttribute("desc"));
138+
}
139+
140+
private AlertBuilder alertObsoleteCspHeader() {
141+
return buildAlert(Alert.RISK_INFO, 2)
142+
.setName(getAlertAttribute("obs.name"))
143+
.setDescription(getAlertAttribute("obs.desc"));
144+
}
145+
146+
private AlertBuilder alertCspReportOnlyHeader() {
147+
return buildAlert(Alert.RISK_INFO, 3)
148+
.setName(getAlertAttribute("ro.name"))
149+
.setDescription(getAlertAttribute("ro.desc"))
150+
.setReference(getAlertAttribute("ro.refs"));
151+
}
149152
}

addOns/pscanrules/src/main/javahelp/org/zaproxy/zap/extension/pscanrules/resources/help/contents/pscanrules.html

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,12 @@ <H2>Charset Mismatch</H2>
9090

9191
<H2>Content Security Policy (CSP) Header Not Set</H2>
9292
This checks HTML response headers for the presence of a Content Security Policy header, or the response body for CSP specified via META tag.<br>
93-
By default this rule checks for the presence of the "Content-Security-Policy" header,
94-
and at the Low threshold also checks for the "X-Content-Security-Policy" and "X-WebKit-CSP" headers.<br>
95-
Redirects and non-HTML responses are ignored except at the Low threshold.
93+
By default this rule checks for the presence of the "Content-Security-Policy", "X-Content-Security-Policy",
94+
and "X-WebKit-CSP" headers. Redirects and non-HTML responses are ignored except at the Low threshold.
95+
<p>
96+
If a "Content-Security-Policy" header is not found, an alert is raised.
97+
<p>
98+
If an "X-Content-Security-Policy" or "X-WebKit-CSP" header is found, an INFO alert is raised. This may represent an outdated enforcement implementation.
9699
<p>
97100
If a "Content-Security-Policy-Report-Only" header is found on a response an INFO alert is raised. This may represent an enforcement effort
98101
that is actively being refined or developed, or one which is only partially implemented.

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ pscanrules.charsetmismatch.extrainfo.xml=There was a charset mismatch between th
5353
pscanrules.contentsecuritypolicymissing.name=Content Security Policy (CSP) Header Not Set
5454
pscanrules.contentsecuritypolicymissing.desc=Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware. CSP provides a set of standard HTTP headers that allow website owners to declare approved sources of content that browsers should be allowed to load on that page \u2014 covered types are JavaScript, CSS, HTML frames, fonts, images and embeddable objects such as Java applets, ActiveX, audio and video files.
5555
pscanrules.contentsecuritypolicymissing.refs=https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy\nhttps://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html\nhttp://www.w3.org/TR/CSP/\nhttp://w3c.github.io/webappsec/specs/content-security-policy/csp-specification.dev.html\nhttp://www.html5rocks.com/en/tutorials/security/content-security-policy/\nhttp://caniuse.com/#feat=contentsecuritypolicy\nhttp://content-security-policy.com/
56-
pscanrules.contentsecuritypolicymissing.soln=Ensure that your web server, application server, load balancer, etc. is configured to set the Content-Security-Policy header, to achieve optimal browser support: "Content-Security-Policy" for Chrome 25+, Firefox 23+ and Safari 7+, "X-Content-Security-Policy" for Firefox 4.0+ and Internet Explorer 10+, and "X-WebKit-CSP" for Chrome 14+ and Safari 6+.
57-
pscanrules.contentsecuritypolicymissing.extrainfo=
56+
pscanrules.contentsecuritypolicymissing.soln=Ensure that your web server, application server, load balancer, etc. is configured to set the Content-Security-Policy header.
57+
pscanrules.contentsecuritypolicymissing.obs.name=Obsolete Content Security Policy (CSP) Header Found
58+
pscanrules.contentsecuritypolicymissing.obs.desc=The "X-Content-Security-Policy" and "X-WebKit-CSP" headers are no longer recommended.
5859
pscanrules.contentsecuritypolicymissing.ro.name=Content Security Policy (CSP) Report-Only Header Found
5960
pscanrules.contentsecuritypolicymissing.ro.desc=The response contained a Content-Security-Policy-Report-Only header, this may indicate a work-in-progress implementation, or an oversight in promoting pre-Prod to Prod, etc.\n\nContent Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware. CSP provides a set of standard HTTP headers that allow website owners to declare approved sources of content that browsers should be allowed to load on that page \u2014 covered types are JavaScript, CSS, HTML frames, fonts, images and embeddable objects such as Java applets, ActiveX, audio and video files.
6061
pscanrules.contentsecuritypolicymissing.ro.refs=https://www.w3.org/TR/CSP2/\nhttps://w3c.github.io/webappsec-csp/\nhttp://caniuse.com/#feat=contentsecuritypolicy\nhttp://content-security-policy.com/

0 commit comments

Comments
 (0)