-
Notifications
You must be signed in to change notification settings - Fork 1.8k
JS: Add query to detect bad code sanitizers #3680
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
JS: Add query to detect bad code sanitizers #3680
Conversation
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.
Nice. I wonder if we can pull in some of the closed issues for safe-eval and friends. The exact CVEs escapes me at the moment.
I have one suggestion for getting a few more results out of this.
// TODO: Proper customizations module, Source class Sink class etc. | ||
import javascript | ||
import DataFlow::PathGraph | ||
private import semmle.javascript.heuristics.AdditionalSinks |
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.
We can wait with the following suggestion, but we must not forget about it.
AdditionalSinks.qll is designed to have the giant side effect of enabling all kinds of new sinks, and I think it is a footgun to import that library by default in any checked-in query - even if it doesn't hurt right here.
Can you pull out the relevant sink from AdditionalSinks.qll? AdditionalSinks.qll can then pull it back in and extend the right sink for the side effect.
exists(StringOps::ConcatenationRoot root, int i | | ||
root.getOperand(i) = result and | ||
not exists(result.getStringValue()) and | ||
not root = endsInCodeInjectionSink() |
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, my suggestion for this filter was not completely thought through. This line alone will cause us to miss completely out on the cases where we do not detect a remote-flow input to the source. That is not a trade-off I am willing to make in order to avoid duplicate alerts.
Could we perhaps check in the where
clause below that there also isn't taint-type-tracking flow to the source from a remote-flow source? That won't cost us any results.
Please include a test case too.
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.
LGTM. I think the master-merge requires a bit more type tracking to avoid double alerts, see inline comment.
t.start() and | ||
result instanceof RemoteFlowSource | ||
or | ||
exists(DataFlow::TypeTracker t2 | result = remoteFlow(t2).track(t2, t)) |
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.
See
codeql/javascript/ql/src/semmle/javascript/Regexp.qll
Lines 893 to 898 in cafbe14
exists(DataFlow::TypeBackTracker t2, DataFlow::Node succ | succ = regExpSource(re, t2) | | |
t2 = t.smallstep(result, succ) | |
or | |
any(TaintTracking::AdditionalTaintStep dts).step(result, succ) and | |
t = t2 | |
) |
CVE-2019-13506: TP/TN
CVE-2018-18282: TP/TN
Seems to easy.
The CVEs are both described as XSS, but I think that is because XSS is a catch-all for "the attacker can run some code".
In both CVEs the issue is a
function () {..}
being constructed as a string and run, so that seems more like code-injection, which is why the query is in theCWE-094
folder.No results on our standard 236 benchmarks.
TODO:
String.prototype.replace
sanitizer more precise?