-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[javascript] CodeQL query to detect if cookies are sent without the flag secure being set #3978
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -8,7 +8,7 @@ This makes it easier for an attacker to intercept.</p> | |||
</overview> | |||
<recommendation> | |||
|
|||
<p>Always set the <code>secure</code> flag to `true` on a cookie before adding it | |||
<p>Always set the `secure` flag to `true` on a cookie before adding it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you change this?
As far as I know, this will not work, but <code>
will work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I was thinking the opposite. Thanks for the feedback. I made the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice. I only have some minor change requests.
Have you seen https://github.com/github/codeql/blob/71933a4d8a32d32f085f14b7b44f41d1cdcae2e4/javascript/ql/src/semmle/javascript/frameworks/CookieLibraries.qll ? It could inspire some changes to this PR, or perhaps some of the content in this PR belongs in that file (note that this file is not in "experimental", so I will set the bar a review bar a bit higher)?
One large, and optional, change to consider.
The qhelp file is a bit verbose in terms of examples. Could you remove some of them, and perhaps add them as tests instead? See #3835 (comment) for how another external contributor recently made tests.
It is a bit of a shame that result = this.getCookieOptionsArgument().getAPropertyWrite(flag).getRhs()
has to be repeated so many times. This could be fixed with some additional inheritance, but that is a matter of taste.
Generally. Whenever you write exist(X x | x = getX() and ...)
without ever using the x
more than once, you can write exists(getX()) and ...
instead.
/** | ||
* Abstract class to represent different cases of insecure cookie settings. | ||
*/ | ||
abstract class InsecureCookies extends DataFlow::Node { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we rename the entire InsecureCookie
module and class to just Cookie
, and then just let the isInsecure
determine if the cookie is secure or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, no problem. I made the change.
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
* Predicate that determines if a cookie is insecure. | ||
*/ | ||
abstract predicate isInsecure(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Predicate that determines if a cookie is insecure. | |
*/ | |
abstract predicate isInsecure(); | |
* Holds if this cookie is secure. | |
*/ | |
abstract predicate isSecure(); |
Optional: I think it is clearer to flip the polarity and avoid the negation in the predicate name.
Please note that this requires a change to all implementations of this predicate below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree with you. I changed the polarity (I did it in one commit) of all the implementations of this predicate.
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
override predicate isInsecure() { | ||
not exists(string s | | ||
getCookieOptionsArgument().mayHaveStringValue(s) and | ||
s.matches("%; secure%") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. What if the string is ...;secure...
? That is: it lacks a space between ;
and secure
.
How about something likes.regexpMatch("(.*;)?\\s*secure.*")
instead? That should allow any whitespace variation, and also permit the string to start with secure
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, you are right. I missed that. I made the change
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
Hi @esbena, sorry for the late reply. About the I made all the changes that you suggested and then I also changed the polarity of the predicate Finally, I removed all the examples and I added them as tests, as you suggested (I hope I added in the correct folder). Let me know if now it’s ok and if there is something else I can do. |
Thanks. The new tests seem fine. |
Thanks for your reply. I formatted the code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. Forgot to attach the inline feedback. PTAL
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.qll
Outdated
Show resolved
Hide resolved
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
….qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
@esbena, no problem :) Let me know if there is something else I can do. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thing. I stumbled upon it when I looked at the results of the query on LGTM.com.
javascript/ql/src/experimental/Security/CWE-614/InsecureCookie.ql
Outdated
Show resolved
Hide resolved
Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
@intrigus-lgtm thanks for the tip. @esbena I made the changes and updated the expected output. |
I took the liberty of pushing a formatting fix to your branch. The tests should go green shortly. |
Thank you for yet another contribution @dellalibera. |
@esbena It was really a pleasure. Thank you for all the feedback. |
Query to detect if the
secure
flag is set to cookies is available in java query but it is not available in javascript query.This query detects if cookies are sent without the flag
secure
being set or with the flagsecure
being set tofalse
.Failing to set the
secure
flag on a cookie can cause it to be sent in cleartext.This makes it easier for an attacker to intercept and read the cookie.
This query handles the cases when cookies are set with:
cookie-session
(https://github.com/expressjs/cookie-session)express-session
(https://github.com/expressjs/session)response.cookie
(https://expressjs.com/en/api.html#res.cookie)Set-Cookie
of an HTTP response (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)js-cookie
(https://github.com/js-cookie/js-cookie)I added several examples showing the different cases when the cookie is sent without the flag
secure
being set or with the flagsecure
being set tofalse
.Any feedback is welcome.
I hope this will help.