Skip to content
Merged
3 changes: 3 additions & 0 deletions addOns/pscanrules/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Maintenance changes.
- The HeartBleed scan rule alert now includes a CVE tag.

### Fixed
- 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).

## [45] - 2023-01-03
### Changed
- 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).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
package org.zaproxy.zap.extension.pscanrules;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import net.htmlparser.jericho.Source;
Expand Down Expand Up @@ -62,67 +63,16 @@ public void scanHttpResponseReceive(HttpMessage msg, int id, Source source) {
return;
}

// Get the various CSP headers
boolean cspHeaderFound = false,
cspROHeaderFound = false,
xCspHeaderFound = false,
xWebKitHeaderFound = false;

// Content-Security-Policy is supported by Chrome 25+, Firefox 23+, Safari 7+, but not but
// Internet Exploder
List<String> cspOptions =
msg.getResponseHeader().getHeaderValues(HttpFieldsNames.CONTENT_SECURITY_POLICY);
if (!cspOptions.isEmpty()) {
cspHeaderFound = true;
if (!hasCspHeader(msg) && !CspUtils.hasMetaCsp(source)) {
alertMissingCspHeader().raise();
}

List<String> cspROOptions =
msg.getResponseHeader().getHeaderValues("Content-Security-Policy-Report-Only");
if (!cspROOptions.isEmpty()) {
cspROHeaderFound = true;
if (hasObsoleteCspHeader(msg)) {
alertObsoleteCspHeader().raise();
}

// X-Content-Security-Policy is an older header, supported by Firefox 4.0+, and IE 10+ (in a
// limited fashion)
List<String> xcspOptions =
msg.getResponseHeader().getHeaderValues("X-Content-Security-Policy");
if (!xcspOptions.isEmpty()) {
xCspHeaderFound = true;
}

// X-WebKit-CSP is supported by Chrome 14+, and Safari 6+
List<String> xwkcspOptions = msg.getResponseHeader().getHeaderValues("X-WebKit-CSP");
if (!xwkcspOptions.isEmpty()) {
xWebKitHeaderFound = true;
}

if (!cspHeaderFound && !CspUtils.hasMetaCsp(source)
|| (AlertThreshold.LOW.equals(this.getAlertThreshold())
&& (!xCspHeaderFound || !xWebKitHeaderFound))) {
// Always report if the latest header isnt found,
// but only report if the older ones arent present at Low threshold
newAlert()
.setRisk(Alert.RISK_MEDIUM)
.setConfidence(Alert.CONFIDENCE_HIGH)
.setDescription(getAlertAttribute("desc"))
.setSolution(getAlertAttribute("soln"))
.setReference(getAlertAttribute("refs"))
.setCweId(693) // CWE-693: Protection Mechanism Failure
.setWascId(15) // WASC-15: Application Misconfiguration
.raise();
}

if (cspROHeaderFound) {
newAlert()
.setName(getAlertAttribute("ro.name"))
.setRisk(Alert.RISK_INFO)
.setConfidence(Alert.CONFIDENCE_HIGH)
.setDescription(getAlertAttribute("ro.desc"))
.setSolution(getAlertAttribute("soln"))
.setReference(getAlertAttribute("ro.refs"))
.setCweId(693) // CWE-693: Protection Mechanism Failure
.setWascId(15) // WASC-15: Application Misconfiguration
.raise();
if (hasCspReportOnlyHeader(msg)) {
alertCspReportOnlyHeader().raise();
}

LOGGER.debug("\tScan of record {} took {}ms", id, System.currentTimeMillis() - start);
Expand All @@ -146,4 +96,57 @@ private String getAlertAttribute(String key) {
public Map<String, String> getAlertTags() {
return ALERT_TAGS;
}

@Override
public List<Alert> getExampleAlerts() {
return Arrays.asList(
alertMissingCspHeader().setUri("https://www.example.com").build(),
alertObsoleteCspHeader().setUri("https://www.example.com").build(),
alertCspReportOnlyHeader().setUri("https://www.example.com").build());
}

private static boolean hasCspHeader(HttpMessage msg) {
return !msg.getResponseHeader()
.getHeaderValues(HttpFieldsNames.CONTENT_SECURITY_POLICY)
.isEmpty();
}

private static boolean hasObsoleteCspHeader(HttpMessage msg) {
return !msg.getResponseHeader().getHeaderValues("X-Content-Security-Policy").isEmpty()
|| !msg.getResponseHeader().getHeaderValues("X-WebKit-CSP").isEmpty();
}

private static boolean hasCspReportOnlyHeader(HttpMessage msg) {
return !msg.getResponseHeader()
.getHeaderValues("Content-Security-Policy-Report-Only")
.isEmpty();
}

private AlertBuilder buildAlert(int risk, int alertNum) {
return newAlert()
.setRisk(risk)
.setConfidence(Alert.CONFIDENCE_HIGH)
.setCweId(693) // CWE-693: Protection Mechanism Failure
.setWascId(15) // WASC-15: Application Misconfiguration
.setSolution(getAlertAttribute("soln"))
.setReference(getAlertAttribute("refs"))
.setAlertRef(PLUGIN_ID + "-" + alertNum);
}

private AlertBuilder alertMissingCspHeader() {
return buildAlert(Alert.RISK_MEDIUM, 1).setDescription(getAlertAttribute("desc"));
}

private AlertBuilder alertObsoleteCspHeader() {
return buildAlert(Alert.RISK_INFO, 2)
.setName(getAlertAttribute("obs.name"))
.setDescription(getAlertAttribute("obs.desc"));
}

private AlertBuilder alertCspReportOnlyHeader() {
return buildAlert(Alert.RISK_INFO, 3)
.setName(getAlertAttribute("ro.name"))
.setDescription(getAlertAttribute("ro.desc"))
.setReference(getAlertAttribute("ro.refs"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,12 @@ <H2>Charset Mismatch</H2>

<H2>Content Security Policy (CSP) Header Not Set</H2>
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>
By default this rule checks for the presence of the "Content-Security-Policy" header,
and at the Low threshold also checks for the "X-Content-Security-Policy" and "X-WebKit-CSP" headers.<br>
Redirects and non-HTML responses are ignored except at the Low threshold.
By default this rule checks for the presence of the "Content-Security-Policy", "X-Content-Security-Policy",
and "X-WebKit-CSP" headers. Redirects and non-HTML responses are ignored except at the Low threshold.
<p>
If a "Content-Security-Policy" header is not found, an alert is raised.
<p>
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.
<p>
If a "Content-Security-Policy-Report-Only" header is found on a response an INFO alert is raised. This may represent an enforcement effort
that is actively being refined or developed, or one which is only partially implemented.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ pscanrules.charsetmismatch.extrainfo.xml=There was a charset mismatch between th
pscanrules.contentsecuritypolicymissing.name=Content Security Policy (CSP) Header Not Set
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.
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/
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+.
pscanrules.contentsecuritypolicymissing.extrainfo=
pscanrules.contentsecuritypolicymissing.soln=Ensure that your web server, application server, load balancer, etc. is configured to set the Content-Security-Policy header.
pscanrules.contentsecuritypolicymissing.obs.name=Obsolete Content Security Policy (CSP) Header Found
pscanrules.contentsecuritypolicymissing.obs.desc=The "X-Content-Security-Policy" and "X-WebKit-CSP" headers are no longer recommended.
pscanrules.contentsecuritypolicymissing.ro.name=Content Security Policy (CSP) Report-Only Header Found
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.
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/
Expand Down
Loading