+
+
+ Cross-Site Scripting (XSS) is categorized as one of the OWASP Top 10 Security Vulnerabilities. The HttpOnly flag directs compatible browsers to prevent client-side script from accessing cookies. Including the HttpOnly flag in the Set-Cookie HTTP response header for a sensitive cookie helps mitigate the risk associated with XSS where an attacker's script code attempts to read the contents of a cookie and exfiltrate information obtained.
+
+
+
+ Use the HttpOnly flag when generating a cookie containing sensitive information to help mitigate the risk of client side script accessing the protected cookie.
+
+
+
+ The following example shows two ways of generating sensitive cookies. In the 'BAD' cases, the HttpOnly flag is not set. In the 'GOOD' cases, the HttpOnly flag is set.
+
+
+
+
+
+ PortSwigger:
+ Cookie without HttpOnly flag set
+
+
+ OWASP:
+ HttpOnly
+
+
+
diff --git a/java/ql/src/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql b/java/ql/src/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql
new file mode 100644
index 00000000000..d2d596c23fa
--- /dev/null
+++ b/java/ql/src/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql
@@ -0,0 +1,223 @@
+/**
+ * @name Sensitive cookies without the HttpOnly response header set
+ * @description Sensitive cookies without the 'HttpOnly' flag set leaves session cookies vulnerable to
+ * an XSS attack.
+ * @kind path-problem
+ * @problem.severity warning
+ * @precision medium
+ * @id java/sensitive-cookie-not-httponly
+ * @tags security
+ * external/cwe/cwe-1004
+ */
+
+/*
+ * Sketch of the structure of this query: we track cookie names that appear to be sensitive
+ * (e.g. `session` or `token`) to a `ServletResponse.addHeader(...)` or `.addCookie(...)`
+ * method that does not set the `httpOnly` flag. Subsidiary configurations
+ * `MatchesHttpOnlyConfiguration` and `SetHttpOnlyInCookieConfiguration` are used to establish
+ * when the `httpOnly` flag is likely to have been set, before configuration
+ * `MissingHttpOnlyConfiguration` establishes that a non-`httpOnly` cookie has a sensitive-seeming name.
+ */
+
+import java
+import semmle.code.java.dataflow.FlowSteps
+import semmle.code.java.frameworks.Servlets
+import semmle.code.java.dataflow.TaintTracking
+import MissingHttpOnlyFlow::PathGraph
+
+/** Gets a regular expression for matching common names of sensitive cookies. */
+string getSensitiveCookieNameRegex() { result = "(?i).*(auth|session|token|key|credential).*" }
+
+/** Gets a regular expression for matching CSRF cookies. */
+string getCsrfCookieNameRegex() { result = "(?i).*(csrf).*" }
+
+/**
+ * Holds if a string is concatenated with the name of a sensitive cookie. Excludes CSRF cookies since
+ * they are special cookies implementing the Synchronizer Token Pattern that can be used in JavaScript.
+ */
+predicate isSensitiveCookieNameExpr(Expr expr) {
+ exists(string s | s = expr.(CompileTimeConstantExpr).getStringValue() |
+ s.regexpMatch(getSensitiveCookieNameRegex()) and not s.regexpMatch(getCsrfCookieNameRegex())
+ )
+ or
+ isSensitiveCookieNameExpr(expr.(AddExpr).getAnOperand())
+}
+
+/** A sensitive cookie name. */
+class SensitiveCookieNameExpr extends Expr {
+ SensitiveCookieNameExpr() { isSensitiveCookieNameExpr(this) }
+}
+
+/** A method call that sets a `Set-Cookie` header. */
+class SetCookieMethodCall extends MethodCall {
+ SetCookieMethodCall() {
+ (
+ this.getMethod() instanceof ResponseAddHeaderMethod or
+ this.getMethod() instanceof ResponseSetHeaderMethod
+ ) and
+ this.getArgument(0).(CompileTimeConstantExpr).getStringValue().toLowerCase() = "set-cookie"
+ }
+}
+
+/**
+ * A taint configuration tracking flow from the text `httponly` to argument 1 of
+ * `SetCookieMethodCall`.
+ */
+module MatchesHttpOnlyConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) {
+ source.asExpr().(CompileTimeConstantExpr).getStringValue().toLowerCase().matches("%httponly%")
+ }
+
+ predicate isSink(DataFlow::Node sink) {
+ sink.asExpr() = any(SetCookieMethodCall ma).getArgument(1)
+ }
+}
+
+module MatchesHttpOnlyFlow = TaintTracking::Global