JS: add method name injection query#503
Conversation
|
|
||
| <recommendation> | ||
| <p> | ||
| Avoid invoking user-controlled methods on the global object or on any function object. |
There was a problem hiding this comment.
This is a little vague. Could we suggest something more concrete, like checking the name of the function to be invoked against a whitelist?
| * @name Method name injection | ||
| * @description Invoking user-controlled methods on a arbitrary objects can lead to remote code execution. | ||
| * @kind path-problem | ||
| * @problem.severity warning |
There was a problem hiding this comment.
Only warning? It seems dangerous enough to warrant severity error.
| /** | ||
| * Gets the flow label relevant for this source. | ||
| */ | ||
| DataFlow::FlowLabel getFlowLabel() { |
There was a problem hiding this comment.
Ah, good catch. It was supposed to be used in isSource.
| @@ -0,0 +1,148 @@ | |||
| /** | |||
| * Provides a taint tracking configuration for reasoning about method invocations | |||
| * Holds if a property of the given object is an unsafe function. | ||
| */ | ||
| predicate isUnsafeBaseObject(DataFlow::SourceNode node) { | ||
| // eval an friends can be accessed from the global object. |
| } | ||
|
|
||
| /** | ||
| * A binary expression that sanitzes a value for method name injection. That |
| </p> | ||
|
|
||
| <sample src="examples/MethodNameInjection.js" /> | ||
| </example> |
There was a problem hiding this comment.
We generally try to give a suggestion for how to fix the problematic example. The current example is hard to fix in general, but could we perhaps modify it slightly so that it could be fixed by whitelisting the name of the invoked method?
| private predicate isCoveredByMethodNameInjection(DataFlow::SourceNode node) { | ||
| node = DataFlow::globalObjectRef() | ||
| or | ||
| node.analyze().getAValue() instanceof AbstractCallable |
There was a problem hiding this comment.
Do we also want to whitelist nodes that have an invocation here? (And could we share this predicate with the other query?)
There was a problem hiding this comment.
Added a common library to share this predicate, and also ConcatSanitizer which was originally stolen from there.
|
PTAL |
| | Enabling Node.js integration for Electron web content renderers (`js/enabling-electron-renderer-node-integration`) | security, frameworks/electron, external/cwe/cwe-094 | Highlights Electron web content renderer preferences with Node.js integration enabled, indicating a violation of [CWE-94](https://cwe.mitre.org/data/definitions/94.html). Results are not shown on LGTM by default. | | ||
| | File data in outbound network request | security, external/cwe/cwe-200 | Highlights locations where file data is sent in a network request. Results are not shown on LGTM by default. | | ||
| | Host header poisoning in email generation | security, external/cwe/cwe-640 | Highlights code that generates emails with links that can be hijacked by HTTP host header poisoning, indicating a violation of [CWE-640](https://cwe.mitre.org/data/definitions/640.html). Results shown on LGTM by default. | | ||
| | Method name injection (`js/method-name-injection` ) | security, external/cwe/cwe-094 | Highlights code that invokes a user-controlled method on an object with unsafe methods. | |
There was a problem hiding this comment.
I like the name, but I wonder whether we could somehow emphasise the unsafe method bit? As you know we've had customer interest in a slightly different kind of situation where method name injection results not in code injection but in a crash. That is different enough in terms of implementation and severity to warrant a separate query, and we'd need to different names and IDs for both.
There was a problem hiding this comment.
Unsafe dynamic method access?
| <sample src="examples/MethodNameInjection.js" /> | ||
|
|
||
| <p> | ||
| Instead of storing the API methods in the global scope, put them in an API object. It is also good |
There was a problem hiding this comment.
We could also suggest using a Map instead of a plain object.
There was a problem hiding this comment.
Added Map to the qhelp file, although I didn't use it in the example as I found the difference in style to be distracting from what the example is showing.
For example, if we replace function play() with:
api.put("play", (data) => {
// ...
});any manual calls to the play function would have to be changed to api.get("play")(...) which isn't really an attractive option.
| */ | ||
| predicate hasUnsafeMethods(DataFlow::SourceNode node) { | ||
| // eval and friends can be accessed from the global object. | ||
| node = DataFlow::globalObjectRef() |
There was a problem hiding this comment.
How about document (for accessing document.write)?
Co-Authored-By: asger-semmle <42069257+asger-semmle@users.noreply.github.com>
…/ql into unsafe-global-object-access
|
Ping @mc-semmle for doc review. |
| | Enabling Node.js integration for Electron web content renderers (`js/enabling-electron-renderer-node-integration`) | security, frameworks/electron, external/cwe/cwe-094 | Highlights Electron web content renderer preferences with Node.js integration enabled, indicating a violation of [CWE-94](https://cwe.mitre.org/data/definitions/94.html). Results are not shown on LGTM by default. | | ||
| | File data in outbound network request | security, external/cwe/cwe-200 | Highlights locations where file data is sent in a network request. Results are not shown on LGTM by default. | | ||
| | Host header poisoning in email generation | security, external/cwe/cwe-640 | Highlights code that generates emails with links that can be hijacked by HTTP host header poisoning, indicating a violation of [CWE-640](https://cwe.mitre.org/data/definitions/640.html). Results shown on LGTM by default. | | ||
| | Unsafe dynamic method access (`js/unsafe-dynamic-method-access` ) | security, external/cwe/cwe-094 | Highlights code that invokes a user-controlled method on an object with unsafe methods. | |
There was a problem hiding this comment.
Are the results shown or not shown on LGTM by default?
|
|
||
| <overview> | ||
| <p> | ||
| Invoking a user-controlled method on certain objects can lead to invocation of unsafe functions, |
There was a problem hiding this comment.
Invoking/invocation - would it be possible for you to use a synonym for one of the instances to avoid repetition in the same sentence?
| <p> | ||
| Invoking a user-controlled method on certain objects can lead to invocation of unsafe functions, | ||
| such as <code>eval</code> or the <code>Function</code> constructor. In particular, the global object | ||
| contains the <code>eval</code> function, and any function object contains the <code>Function</code> constructor |
There was a problem hiding this comment.
Sorry I don't understand this sentence (In particular, the global object contains the <code>eval</code> function, and any function object contains the <code>Function</code> constructor in its <code>constructor</code> property.) and how it links to what you've said previously. I am not a developer so feel free to ignore if you think this is clear enough to the intended audience.
There was a problem hiding this comment.
It's a technical explanation of what was meant by "certain objects" in the previous sentence. I think it would make sense to most JavaScript developers.
There was a problem hiding this comment.
@asger-semmle - this LGTM. I've made a couple of comments on the qhelp file, and I think you need to add a sentence to the change note to let users know whether the results of this new query are shown on LGTM by default.
Hope this helps.
|
Thanks for the review @mc-semmle. |
mchammer01
left a comment
There was a problem hiding this comment.
Thanks for the updates to the documentation @asger-semmle
This is good to go from my perspective
|
Query LGTM; how is the evaluation coming along? |
I had to restart due to that dist-compare PR I put up today, so it's not very far. |
| hasUnsafeMethods(read.getBase().getALocalSource()) and | ||
| src = read.getPropertyNameExpr().flow() and | ||
| dst = read and | ||
| srclabel = taint() and |
There was a problem hiding this comment.
On second (or third) thought: shouldn't we also allow srclabel = data() here and below?
There was a problem hiding this comment.
You're right - for some reason I thought data implied that taint would also be present.
There was a problem hiding this comment.
It's an interesting question. I experimented with adding this sort of additional lattice structure on taint kinds, but it turned out to be tricky to get right in general.
|
@asger-semmle, has the evaluation finished yet? |
|
No, I keep botching it. I have the query results here but no performance yet. |
|
I have retargetted this at rc/1.19 since it was reviewed and approved before feature freeze and is only blocked on testing. |
|
As discussed earlier, the evaluation results look reasonable, so in the interest of getting this PR into the current LGTM.com upgrade I'm merging it. |
This adds a query for a special case of what "Remote property injection" would find, but with higher
precisionvalue and classified as a code-injection alert. In aims to only flag cases that can lead to code injection.It's mostly a special case of the aforementioned query, although the coverage is slightly higher in some cases:
Performance evaluation is under way.