[javascript] CodeQL query to detect missing origin validation in cross-origin communication via postMessage#3646
Conversation
|
Thank you, we will get back to you next week. In the meantime, I'll direct your attention to our default sanitizer for origin validation, which seems very related: Could that inspire some changes in your end? |
| predicate isOriginChecked() { | ||
| exists(IfStmt ifStmt | | ||
| ifStmt = this.getAPropertyRead("origin").getAMethodCall*().asExpr().getEnclosingStmt() or | ||
| ifStmt = this.getAPropertyRead("origin").asExpr().getEnclosingStmt() | ||
| ) | ||
| } |
There was a problem hiding this comment.
Any way to ensure that the dev hasn't done something goofy like:
if (event.origin.contains('www.example.com')) {
}Or, one that I've seen before when I reported CVE-2019-10779:
var origin = event.origin;
var host = window.location.host;
// Stop this script being called from other domains.
if (origin.indexOf(host) === -1)
return;This was the one I used when I found a vulnerability in a GCHQ project:
GHSA-6p78-9hh5-384m
https://gist.github.com/JLLeitschuh/a6d6eb3886170dafa7c0cbe1d63edefa
|
Legit vulnerability query. I've found vulns from this mistake before. I appreciate this is being added. |
|
Hi @esbena, @JLLeitschuh thanks for your feedbacks, I really appreciated. @esbena I looked at your suggestion and I used it to check if a read access to the property @JLLeitschuh I added other checks in order to detect insufficient and insecure validation of the I am learning this amazing tool and I would like to contribute, so any comment/feedback is more than welcomed. |
esbena
left a comment
There was a problem hiding this comment.
I like the idea in the query. It may be a bit too noisy to enable by default since there are legitimate uses of cross-origin communication that do not require origin checking, but if you are willing to look at those false positives, then the query is good.
See my inline comments about the QL content.
For the record, we already treat cross-origin messages without an origin check as taint sources for our security queries.
| exists(InsufficientOriginChecks insufficientChecks | | ||
| this.getAPropertyRead("origin").getAMethodCall*() = insufficientChecks | ||
| ) |
There was a problem hiding this comment.
| exists(InsufficientOriginChecks insufficientChecks | | |
| this.getAPropertyRead("origin").getAMethodCall*() = insufficientChecks | |
| ) | |
| this.getAPropertyRead("origin").getAMethodCall() instanceof InsufficientOriginChecks |
There was a problem hiding this comment.
Thanks for the all the feedback. I really appreciated.
I have just a comment about this suggestion. Should it be
this.getAPropertyRead("origin").getAMethodCall*() instanceof InsufficientOriginChecks
?
Without the * I don't catch for example the following case:
let origin = event.origin.toLowerCase();
let host = window.location.host;
// BAD
if (origin.startsWith(host) === -1)
return;
This is because in the if statement the resolved predicate is event.origin.toLowerCase().startsWith() (please do not hesitate to correct me if I’m wrong).
There was a problem hiding this comment.
I see, that is a good point. Lets add the * then.
(If you are interested, then the way we would check for such extended flows in a non-experimental query, would be using "type tracking". Type tracking would also allow us to identify bad checks in other functions for instance. But that is an advanced feature that can be added later)
There was a problem hiding this comment.
Perfect, so I leave the *.
| /** | ||
| * A method call for the insecure functions used to verify the `MessageEvent.origin`. | ||
| */ | ||
| class InsufficientOriginChecks extends DataFlow::MethodCallNode { |
There was a problem hiding this comment.
We have a few API methods for calls like this already. Do they suit your needs?
See this for instance:
There was a problem hiding this comment.
Thanks for pointing this out. I was already aware of these APIs, indeed I was inspired by a similar query:
codeql/javascript/ql/src/Security/CWE-020/IncorrectSuffixCheck.ql#L18-L23
Since I am pretty new to this framework, what are the benefits of using the suggested API methods?
I just want to detect if there is a weak function call (like indexOf) to validate the origin.
It seems to me that these API methods are preferred if you what to reason about the object passed to these methods.
In any case, if you think that the actual implementation can be improved, let me know. I will try to combine the already existing API methods and what I have done.
Again, thanks for your feedback.
There was a problem hiding this comment.
This is just a minor suggestion, feel free to ignore it.
Since I am pretty new to this framework, what are the benefits of using the suggested API methods?
The benefit is that StringOps::... is like to cover more cases, and that it is likely to be extended in the future. See this case for instance:
codeql/javascript/ql/src/semmle/javascript/InclusionTests.qll
Lines 110 to 122 in 03c6d7a
Of course, if you spot a false positive from your query due to the use of StringOps::..., then the right choice is the simpler list of method names that you already have.
There was a problem hiding this comment.
Thanks for explaining this :)
Glad to know the difference. Since StringOps covers more cases of functions that can be used to validate the origin (improperly), I changed the code in favour of StringOps.
Thanks for the feedback.
…riginCheck.ql Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
…riginCheck.ql Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
…riginCheck.ql Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
esbena
left a comment
There was a problem hiding this comment.
Feel free to adjust the QL more if my replies have inspired you, but otherwise I think we are good once the documentation has been fixed.
I will start a large evaluation once you are satisfied.
…riginCheck.qhelp Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
…riginCheck.qhelp Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
…riginCheck.qhelp Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
…riginCheck.ql Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
|
@esbena I have made the changes. Let me know if now it’s ok and if there is something else I can do. Again, thanks for all the feedback. |
|
I am merging this now. Thank you for the contribution @dellalibera. |
|
@esbena it was really a pleasure. I am really happy that this PR was merged. @JLLeitschuh thanks for your precious suggestions. I really appreciated. |
When using cross-domain communication via the
window.postMessage()APIWindow.postMessage()
This query addresses the scenario where the
MessageEvent.originproperty is not checked(either read or call) in the
postMessageevent handler.