Skip to content

Conversation

erik-krogh
Copy link
Contributor

@erik-krogh erik-krogh commented May 1, 2020

Fixes these FPs that showed up in an anomalous query results a while ago.

The issue is we didn't recognize the .split("?")[0] pattern if there was any data-flow. E.g.

var parts = document.location.href.split( '?' );
var safe = parts[0];

With this PR a .getALocalSource() is added, such that we recognize the safe way of constructing a redirect URL in more cases.

The pattern is not common, and I found no instances of it on our standard 236 benchmarks.

I know it looks like an ad-hoc addon, but the alternative solution would be to add another flow-label, and I don't think that would perform well.

@erik-krogh erik-krogh added JS Awaiting evaluation Do not merge yet, this PR is waiting for an evaluation to finish labels May 1, 2020
@erik-krogh erik-krogh marked this pull request as ready for review May 4, 2020 11:58
@erik-krogh erik-krogh requested a review from a team as a code owner May 4, 2020 11:58
@esbena
Copy link
Contributor

esbena commented May 4, 2020

the alternative solution would be to add another flow-label, and I don't think that would perform well.

I think the split-and-destruct pattern is common enough that you can generalize QueryPrefixSanitizer to be a class we may be able to use elsewhere (ag '"split"' -G qll gives some results), that is another alternative that avoids the adhoc feeling.

I am thinking of something like:

class StringSplitCall extends DataFlow::MethodCallNode {
  string getSplitAt() { getArgument(0).mayHaveStringValue(result) }
  DataFlow::Node getUnsplit() { result = getReceiver() }
  DataFlow::Node getAnElementRead(int i) { ... }
}

@asgerf
Copy link
Contributor

asgerf commented May 4, 2020

I believe this also affects the DOM-based XSS query. Might be worth sharing the sanitizer if doing so doesn't have any adverse side effects.

Copy link
Contributor

@esbena esbena left a comment

Choose a reason for hiding this comment

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

Some minor comments.

/**
* Gets a the SourceNode for the string before it is split.
*/
DataFlow::SourceNode getUnsplit() { result = getReceiver().getALocalSource() }
Copy link
Contributor

Choose a reason for hiding this comment

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

I dislike the getUnsplit name (even though it is my own suggestion).

Perhaps getStringSource, and dually getASubstringRead(int i) below would be better?

This has no result for "foo|bar".split("|").map(...). I can live with that if a renaming like the above is implemented.
If we need to reason about the shorthand above, we can introduce string getString() and string getSubstring(int i).

Copy link
Contributor

Choose a reason for hiding this comment

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

In the StringOps module I tried to stick with getBaseString as it was meaningful yet generic enough to be used consistently across the different string operations. I think we can use the same here, and possibly drop the getALocalSource.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went with getBaseString, and dropped the getALocalSource().

Copy link
Contributor

@esbena esbena left a comment

Choose a reason for hiding this comment

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

LGTM. Modulo the missing change note part and a missing flowsTo.

Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
esbena
esbena previously approved these changes May 5, 2020
esbena
esbena previously approved these changes May 5, 2020
@erik-krogh
Copy link
Contributor Author

An evaluation came back with not great performance, and an FP for the following pattern:

window.location.replace(window.location.href.split("#")[0] + "#mappage");

I fixed the FP, and I'll look into the performance.

@erik-krogh
Copy link
Contributor Author

A security/nightly evaluation came back with mixed results.
But a redo of the 10 worst looks OK.

So I think this is ready to land.

@erik-krogh erik-krogh removed the Awaiting evaluation Do not merge yet, this PR is waiting for an evaluation to finish label May 16, 2020
@semmle-qlci semmle-qlci merged commit 0230b79 into github:master May 18, 2020
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.

4 participants