Skip to content

Commit 11304b2

Browse files
committed
Update qldoc and change the wrapper method implementation
1 parent 57bd3f3 commit 11304b2

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

java/ql/src/experimental/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* @name Sensitive cookies without the HttpOnly response header set
3-
* @description Sensitive cookies without 'HttpOnly' leaves session cookies vulnerable to an XSS attack.
3+
* @description Sensitive cookies without the 'HttpOnly' flag set leaves session cookies vulnerable to
4+
* an XSS attack. This query checks whether 'HttpOnly' is not set in a Java Cookie object
5+
* or the 'Set-Cookie' HTTP header.
46
* @kind path-problem
57
* @id java/sensitive-cookie-not-httponly
68
* @tags security
@@ -25,14 +27,14 @@ string getCsrfCookieNameRegex() { result = "(?i).*(csrf).*" }
2527
* they are special cookies implementing the Synchronizer Token Pattern that can be used in JavaScript.
2628
*/
2729
predicate isSensitiveCookieNameExpr(Expr expr) {
28-
exists(string s | s = expr.(CompileTimeConstantExpr).getStringValue().toLowerCase() |
30+
exists(string s | s = expr.(CompileTimeConstantExpr).getStringValue() |
2931
s.regexpMatch(getSensitiveCookieNameRegex()) and not s.regexpMatch(getCsrfCookieNameRegex())
3032
)
3133
or
3234
isSensitiveCookieNameExpr(expr.(AddExpr).getAnOperand())
3335
}
3436

35-
/** The method call `Set-Cookie` of `addHeader` or `setHeader`. */
37+
/** A method call that sets a `Set-Cookie` header. */
3638
class SetCookieMethodAccess extends MethodAccess {
3739
SetCookieMethodAccess() {
3840
(
@@ -59,33 +61,31 @@ class MatchesHttpOnlyConfiguration extends TaintTracking2::Configuration {
5961
}
6062
}
6163

62-
/** The cookie class of Java EE. */
64+
/** A class descended from `javax.servlet.http.Cookie` or `javax/jakarta.ws.rs.core.Cookie`. */
6365
class CookieClass extends RefType {
6466
CookieClass() {
6567
this.getASupertype*()
6668
.hasQualifiedName(["javax.servlet.http", "javax.ws.rs.core", "jakarta.ws.rs.core"], "Cookie")
6769
}
6870
}
6971

70-
/** Holds if the `Expr` expr is evaluated to boolean true. */
71-
predicate isBooleanTrue(Expr expr) {
72+
/** Holds if the `expr` is `true` or a variable that is ever assigned `true`. */
73+
predicate mayBeBooleanTrue(Expr expr) {
7274
expr.(CompileTimeConstantExpr).getBooleanValue() = true or
7375
expr.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getBooleanValue() =
7476
true
7577
}
7678

7779
/** Holds if the method call sets the `HttpOnly` flag. */
78-
predicate setHttpOnlyInCookie(MethodAccess ma) {
80+
predicate setsCookieHttpOnly(MethodAccess ma) {
7981
ma.getMethod().getName() = "setHttpOnly" and
8082
(
81-
isBooleanTrue(ma.getArgument(0)) // boolean literal true
83+
ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = true
8284
or
83-
exists(
84-
MethodAccess mpa, int i // runtime assignment of boolean value true
85-
|
86-
TaintTracking::localTaint(DataFlow::parameterNode(mpa.getMethod().getParameter(i)),
87-
DataFlow::exprNode(ma.getArgument(0))) and
88-
isBooleanTrue(mpa.getArgument(i))
85+
// any use of setHttpOnly(x) where x isn't false is probably safe
86+
not exists(VarAccess va |
87+
ma.getArgument(0).(VarAccess).getVariable().getAnAccess() = va and
88+
va.getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getBooleanValue() = false
8989
)
9090
)
9191
}
@@ -99,7 +99,7 @@ class SetHttpOnlyInCookieConfiguration extends TaintTracking2::Configuration {
9999

100100
override predicate isSource(DataFlow::Node source) {
101101
source.asExpr() =
102-
any(MethodAccess ma | setHttpOnlyInCookie(ma) or removeCookie(ma)).getQualifier()
102+
any(MethodAccess ma | setsCookieHttpOnly(ma) or removeCookie(ma)).getQualifier()
103103
}
104104

105105
override predicate isSink(DataFlow::Node sink) {
@@ -108,18 +108,18 @@ class SetHttpOnlyInCookieConfiguration extends TaintTracking2::Configuration {
108108
}
109109
}
110110

111-
/** Holds if the method call removes a cookie. */
111+
/** Holds if `ma` removes a cookie. */
112112
predicate removeCookie(MethodAccess ma) {
113113
ma.getMethod().getName() = "setMaxAge" and
114114
ma.getArgument(0).(IntegerLiteral).getIntValue() = 0
115115
}
116116

117-
/** Sensitive cookie name used in a `Cookie` constructor or a `Set-Cookie` call. */
117+
/** A sensitive cookie name. */
118118
class SensitiveCookieNameExpr extends Expr {
119119
SensitiveCookieNameExpr() { isSensitiveCookieNameExpr(this) }
120120
}
121121

122-
/** Sink of adding a cookie to the HTTP response. */
122+
/** A cookie that is added to an HTTP response, used as a sink in `MissingHttpOnlyConfiguration`. */
123123
class CookieResponseSink extends DataFlow::ExprNode {
124124
CookieResponseSink() {
125125
exists(MethodAccess ma |
@@ -145,14 +145,14 @@ predicate setHttpOnlyInNewCookie(ClassInstanceExpr cie) {
145145
cie.getConstructedType().hasQualifiedName(["javax.ws.rs.core", "jakarta.ws.rs.core"], "NewCookie") and
146146
(
147147
cie.getNumArgument() = 6 and
148-
isBooleanTrue(cie.getArgument(5)) // NewCookie(Cookie cookie, String comment, int maxAge, Date expiry, boolean secure, boolean httpOnly)
148+
mayBeBooleanTrue(cie.getArgument(5)) // NewCookie(Cookie cookie, String comment, int maxAge, Date expiry, boolean secure, boolean httpOnly)
149149
or
150150
cie.getNumArgument() = 8 and
151151
cie.getArgument(6).getType() instanceof BooleanType and
152-
isBooleanTrue(cie.getArgument(7)) // NewCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly)
152+
mayBeBooleanTrue(cie.getArgument(7)) // NewCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly)
153153
or
154154
cie.getNumArgument() = 10 and
155-
isBooleanTrue(cie.getArgument(9)) // NewCookie(String name, String value, String path, String domain, int version, String comment, int maxAge, Date expiry, boolean secure, boolean httpOnly)
155+
mayBeBooleanTrue(cie.getArgument(9)) // NewCookie(String name, String value, String path, String domain, int version, String comment, int maxAge, Date expiry, boolean secure, boolean httpOnly)
156156
)
157157
}
158158

0 commit comments

Comments
 (0)