Skip to content

Conversation

asgerf
Copy link
Contributor

@asgerf asgerf commented Feb 26, 2020

Taint can now be tracked across sanitizers that don't operate on the tainted value directly, but only on an object containing it. For example:

if (isSafe(x)) {
  sink(x.foo); // NOT OK - 'x' is sanitized, but not 'x.foo'
}

This was done through the following change to taint-tracking configurations:

  • Taint sources are now associated with the taint label by default (previously data).
  • Sanitizers only block the taint label.

The old behavior of completely blocking flow through a label can be achieved by overriding isBarrier instead, or using a labeled barrier to block the data label.

The flow label mapping data->taint is still generated by all taint steps. This ensures backwards compatibility for queries that use data as the source (although the change to sanitizers is still in effect).

Note that we have some taint-tracking configurations that relies on data being the source, such as HardcodedDataInterpretedAsCode, where we are only interested in data that has gone through some transformation before reaching the sink. So there are use-cases for having data being the source, it's just no longer the default.

Evaluation was pretty quiet.

@asgerf asgerf added the JS label Feb 26, 2020
@asgerf asgerf requested a review from a team as a code owner February 26, 2020 10:44
Copy link
Contributor

@erik-krogh erik-krogh left a comment

Choose a reason for hiding this comment

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

It looks good to me.
It makes sense to have taint-tracking configurations primarily work with the taint label.

But I think we should get yet another pair of eyes on this (@esbena?).

Tests are failing.

@esbena esbena self-assigned this Feb 28, 2020
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.

I have one minor architectural concern.

@@ -633,7 +633,12 @@ private predicate exploratoryFlowStep(
*/
private predicate isSource(DataFlow::Node nd, DataFlow::Configuration cfg, FlowLabel lbl) {
(cfg.isSource(nd) or nd.(AdditionalSource).isSourceFor(cfg)) and
lbl = FlowLabel::data()
(
if cfg instanceof TaintTracking::Configuration then
Copy link
Contributor

Choose a reason for hiding this comment

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

It is a shame that we have to introduce a dependency form Configuration.qll to TaintTracking.qll (I think this is the first, at least). We could avoid that by introducing cfg.getDefaultSourceLabel(), which in TaintTracking::configuration is implemented as result = FlowLabel::taint().
I will leave it to you to decide what to do here.

Ditto for isSink 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.

That's very true, but on the other hand, there's also a downside to extending our public API with stuff that users don't actually need.

@esbena esbena removed their assignment Mar 2, 2020
@asgerf asgerf force-pushed the js/property-barriers branch from dd0a51e to 6f85712 Compare March 7, 2020 15:27
@asgerf
Copy link
Contributor Author

asgerf commented Mar 8, 2020

There was a test failure that revealed an interesting, but generally benign side effect of the change.

The prototype pollution utility query had a barrier guard for x in obj where x was sanitized in the false case, while a standard sanitizer guard sanitizes x in the true case. The latter one shouldn't matter because we don't use a taint-tracking configuration, but because its underlying instance (the InExpr) was included in isBarrierGuard the standard sanitizer was pulled in that way. Since the standard sanitizer guard only blocks the taint label now, it's still being pulled in, but has no effect as we're not using the taint label in that query.

The change thus fixed a spurious sanitizer which revealed that a test was passing for the wrong reason. I've updated the test accordingly.

esbena
esbena previously approved these changes Mar 18, 2020
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.

I have restarted the tests. The Jenkins logs were no longer present.

@asgerf asgerf added the Awaiting evaluation Do not merge yet, this PR is waiting for an evaluation to finish label Mar 18, 2020
@asgerf
Copy link
Contributor Author

asgerf commented Mar 18, 2020

This will need another evaluation. After rebasing some join orderings have changed and it's not performing as well anymore.

@asgerf asgerf force-pushed the js/property-barriers branch from 3760edb to 4f42675 Compare March 19, 2020 09:36
@asgerf
Copy link
Contributor Author

asgerf commented Mar 20, 2020

Evaluation still looks fine.

@asgerf asgerf removed the Awaiting evaluation Do not merge yet, this PR is waiting for an evaluation to finish label Mar 20, 2020
Copy link
Contributor

@erik-krogh erik-krogh left a comment

Choose a reason for hiding this comment

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

👍

@asgerf asgerf merged commit 6c2842b into github:master Mar 23, 2020
@asgerf
Copy link
Contributor Author

asgerf commented Mar 23, 2020

Thanks for the review @erik-krogh!

@esbena I believe I addressed your comment in in b6ca4fb but in any case, I've gone ahead and merged to unblock Erik's PR and since there are now a bunch of performance-related PRs floating around whose evaluations ought to be based on this one from now on.

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