Skip to content

Conversation

@asger-semmle
Copy link
Contributor

@asger-semmle asger-semmle commented Nov 20, 2018

This adds a query for a special case of what "Remote property injection" would find, but with higher precision value 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:

  • The property name in a property projection call is recognized as a property-name sink.
  • The subsequent invocation is found using a flow label, instead of relying on local flow.

Performance evaluation is under way.

@asger-semmle asger-semmle requested a review from a team as a code owner November 20, 2018 16:08
Copy link

@xiemaisi xiemaisi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broadly lgtm, a few suggestions.


<recommendation>
<p>
Avoid invoking user-controlled methods on the global object or on any function object.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only warning? It seems dangerous enough to warrant severity error.

/**
* Gets the flow label relevant for this source.
*/
DataFlow::FlowLabel getFlowLabel() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used anywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"taint-tracking"

* 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.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/an/and/

}

/**
* A binary expression that sanitzes a value for method name injection. That

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/sanitzes/sanitizes/

</p>

<sample src="examples/MethodNameInjection.js" />
</example>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also want to whitelist nodes that have an invocation here? (And could we share this predicate with the other query?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a common library to share this predicate, and also ConcatSanitizer which was originally stolen from there.

@asger-semmle
Copy link
Contributor Author

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. |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsafe dynamic method access?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's nice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is done

Copy link

@xiemaisi xiemaisi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good; a few more thoughts.

<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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also suggest using a Map instead of a plain object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about document (for accessing document.write)?

Max Schaefer and others added 3 commits November 21, 2018 10:55
Co-Authored-By: asger-semmle <42069257+asger-semmle@users.noreply.github.com>
@xiemaisi
Copy link

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. |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

@mchammer01 mchammer01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

@asger-semmle
Copy link
Contributor Author

Thanks for the review @mc-semmle.

mchammer01
mchammer01 previously approved these changes Nov 21, 2018
Copy link
Contributor

@mchammer01 mchammer01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates to the documentation @asger-semmle
This is good to go from my perspective

@xiemaisi
Copy link

Query LGTM; how is the evaluation coming along?

@asger-semmle
Copy link
Contributor Author

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.

@xiemaisi xiemaisi added the JS label Nov 22, 2018
hasUnsafeMethods(read.getBase().getALocalSource()) and
src = read.getPropertyNameExpr().flow() and
dst = read and
srclabel = taint() and

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second (or third) thought: shouldn't we also allow srclabel = data() here and below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right - for some reason I thought data implied that taint would also be present.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@xiemaisi
Copy link

@asger-semmle, has the evaluation finished yet?

@asger-semmle
Copy link
Contributor Author

No, I keep botching it. I have the query results here but no performance yet.

@xiemaisi xiemaisi changed the base branch from master to rc/1.19 November 26, 2018 08:16
@xiemaisi
Copy link

I have retargetted this at rc/1.19 since it was reviewed and approved before feature freeze and is only blocked on testing.

@xiemaisi xiemaisi added this to the 1.19 milestone Nov 26, 2018
@xiemaisi
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants