Use synthetic fields to improve taint precision

This commit is contained in:
Tony Torralba
2021-10-08 09:47:39 +02:00
parent b7f7c5ba20
commit f209ff4f76
3 changed files with 84 additions and 62 deletions

View File

@@ -1,32 +1,39 @@
/** Provides classes and predicates related to Android notifications. */
import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSteps
private class NotificationActionsInheritTaint extends DataFlow::SyntheticFieldContent,
TaintInheritingContent {
NotificationActionsInheritTaint() { this.getField().matches("android.app.Notification.action") }
}
private class NotificationBuildersSummaryModels extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
"android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
"android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
"android.app;Notification$Action$Builder;true;Builder;(Action);;Argument[0];Argument[-1];taint",
"android.app;Notification$Action$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.app.NotificationActionBuilder.extras] of Argument[-1];value",
"android.app;Notification$Action$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.app.NotificationActionBuilder.extras] of Argument[-1];value",
"android.app;Notification$Action$Builder;true;build;;;Argument[-1];ReturnValue;taint",
"android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.app.NotificationActionBuilder.extras] of Argument[-1];ReturnValue;value",
"android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
"android.app;Notification$Builder;true;addAction;(Action);;Argument[0];Argument[-1];taint",
"android.app;Notification$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];value",
"android.app;Notification$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];value",
"android.app;Notification$Builder;true;build;;;Argument[-1];ReturnValue;taint",
"android.app;Notification$Builder;true;setContentIntent;;;Argument[0];Argument[-1];taint",
"android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];ReturnValue;value",
"android.app;Notification$Builder;true;recoverBuilder;;;Argument[1];ReturnValue;taint",
"android.app;Notification$Builder;true;setActions;;;ArrayElement of Argument[0];Argument[-1];taint",
"android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];value",
"android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];Argument[-1];taint",
"android.app;Notification$Builder;true;setPublicVersion;;;Argument[0];Argument[-1];taint",
"android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Action$Builder;true;Builder;(Action);;SyntheticField[android.app.Notification.action] of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Action$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
"android.app;Notification$Action$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
"android.app;Notification$Action$Builder;true;build;;;SyntheticField[android.app.Notification.action] of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint",
"android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value",
"android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Builder;true;addAction;(Action);;SyntheticField[android.app.Notification.action] of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
"android.app;Notification$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
"android.app;Notification$Builder;true;build;;;SyntheticField[android.app.Notification.action] of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint",
"android.app;Notification$Builder;true;setContentIntent;;;Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value",
"android.app;Notification$Builder;true;recoverBuilder;;;SyntheticField[android.app.Notification.action] of Argument[1];SyntheticField[android.app.Notification.action] of ReturnValue;taint",
"android.app;Notification$Builder;true;setActions;;;SyntheticField[android.app.Notification.action] of ArrayElement of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.content.Intent.extras] of Argument[-1];value",
"android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
"android.app;Notification$Builder;true;setPublicVersion;;;SyntheticField[android.app.Notification.action] of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
// Fluent models
"android.app;Notification$Action$Builder;true;" +
[

View File

@@ -13,14 +13,6 @@ import android.os.Bundle;
// Test case generated by GenerateFlowTestCase.ql
public class Test {
Notification.Action.Builder newActionBuilderWithExtras(Bundle element) {
return null;
}
Notification.Builder newBuilderWithExtras(Bundle element) {
return null;
}
Object getMapKeyDefault(Bundle container) {
return null;
}
@@ -50,21 +42,24 @@ public class Test {
public void test() throws Exception {
{
// "android.app;Notification$Action$Builder;true;Builder;(Action);;Argument[0];Argument[-1];taint"
// "android.app;Notification$Action$Builder;true;Builder;(Action);;SyntheticField[android.app.Notification.action]
// of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint"
Notification.Action.Builder out = null;
Notification.Action in = (Notification.Action) source();
out = new Notification.Action.Builder(in);
sink(out); // $ hasTaintFlow
}
{
// "android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
// "android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
// of Argument[-1];taint"
Notification.Action.Builder out = null;
PendingIntent in = (PendingIntent) source();
out = new Notification.Action.Builder((Icon) null, (CharSequence) null, in);
sink(out); // $ hasTaintFlow
}
{
// "android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
// "android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
// of Argument[-1];taint"
Notification.Action.Builder out = null;
PendingIntent in = (PendingIntent) source();
out = new Notification.Action.Builder(0, (CharSequence) null, in);
@@ -79,17 +74,17 @@ public class Test {
}
{
// "android.app;Notification$Action$Builder;true;addExtras;;;MapKey of
// Argument[0];MapKey of SyntheticField[android.app.Notification$Action$Builder.extras]
// of Argument[-1];value"
// Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of
// Argument[-1];value"
Notification.Action.Builder out = null;
Bundle in = newWithMapKeyDefault(source());
Bundle in = (Bundle) newWithMapKeyDefault(source());
out.addExtras(in);
sink(getMapKeyDefault(out.getExtras())); // $ hasValueFlow
}
{
// "android.app;Notification$Action$Builder;true;addExtras;;;MapValue of
// Argument[0];MapValue of
// SyntheticField[android.app.Notification$Action$Builder.extras] of Argument[-1];value"
// Argument[0];MapValue of SyntheticField[android.content.Intent.extras]
// of Argument[-1];value"
Notification.Action.Builder out = null;
Bundle in = (Bundle) newWithMapValueDefault(source());
out.addExtras(in);
@@ -103,7 +98,8 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Action$Builder;true;build;;;Argument[-1];ReturnValue;taint"
// "android.app;Notification$Action$Builder;true;build;;;SyntheticField[android.app.Notification.action]
// of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint"
Notification.Action out = null;
Notification.Action.Builder in = (Notification.Action.Builder) source();
out = in.build();
@@ -117,12 +113,12 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.app.Notification$Action$Builder.extras]
// "android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras]
// of Argument[-1];ReturnValue;value"
Bundle out = null;
Notification.Action.Builder in = newActionBuilderWithExtras((Bundle) source());
Notification.Action.Builder in = (Notification.Action.Builder) source();
out = in.getExtras();
sink(out); // $ hasValueFlow
sink(out); // $ hasTaintFlow
}
{
// "android.app;Notification$Action$Builder;true;setAllowGeneratedReplies;;;Argument[-1];ReturnValue;value"
@@ -153,21 +149,24 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
// "android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
// of Argument[-1];taint"
Notification.Action out = null;
PendingIntent in = (PendingIntent) source();
out = new Action(0, null, in);
out = new Notification.Action(0, null, in);
sink(out); // $ hasTaintFlow
}
{
// "android.app;Notification$Builder;true;addAction;(Action);;Argument[0];Argument[-1];taint"
// "android.app;Notification$Builder;true;addAction;(Action);;SyntheticField[android.app.Notification.action]
// of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint"
Notification.Builder out = null;
Notification.Action in = (Notification.Action) source();
out.addAction(in);
sink(out); // $ hasTaintFlow
}
{
// "android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
// "android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
// of Argument[-1];taint"
Notification.Builder out = null;
PendingIntent in = (PendingIntent) source();
out.addAction(0, null, in);
@@ -196,17 +195,17 @@ public class Test {
}
{
// "android.app;Notification$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of
// SyntheticField[android.app.Notification$Builder.extras] of Argument[-1];value"
// SyntheticField[android.content.Intent.extras] of Argument[-1];value"
Notification.Builder out = null;
Bundle in = newWithMapKeyDefault(source());
Bundle in = (Bundle) newWithMapKeyDefault(source());
out.addExtras(in);
sink(getMapKeyDefault(out.getExtras())); // $ hasValueFlow
}
{
// "android.app;Notification$Builder;true;addExtras;;;MapValue of Argument[0];MapValue
// of SyntheticField[android.app.Notification$Builder.extras] of Argument[-1];value"
// of SyntheticField[android.content.Intent.extras] of Argument[-1];value"
Notification.Builder out = null;
Bundle in = newWithMapValueDefault(source());
Bundle in = (Bundle) newWithMapValueDefault(source());
out.addExtras(in);
sink(getMapValueDefault(out.getExtras())); // $ hasValueFlow
}
@@ -225,7 +224,8 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Builder;true;build;;;Argument[-1];ReturnValue;taint"
// "android.app;Notification$Builder;true;build;;;SyntheticField[android.app.Notification.action]
// of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint"
Notification out = null;
Notification.Builder in = (Notification.Builder) source();
out = in.build();
@@ -239,15 +239,16 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.app.Notification$Builder.extras]
// "android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras]
// of Argument[-1];ReturnValue;value"
Bundle out = null;
Notification.Builder in = newBuilderWithExtras((Bundle) source());
Notification.Builder in = (Notification.Builder) source();
out = in.getExtras();
sink(out); // $ hasValueFlow
sink(out); // $ hasTaintFlow
}
{
// "android.app;Notification$Builder;true;recoverBuilder;;;Argument[1];ReturnValue;taint"
// "android.app;Notification$Builder;true;recoverBuilder;;;SyntheticField[android.app.Notification.action]
// of Argument[1];SyntheticField[android.app.Notification.action] of ReturnValue;taint"
Notification.Builder out = null;
Notification in = (Notification) source();
out = Notification.Builder.recoverBuilder(null, in);
@@ -261,8 +262,9 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Builder;true;setActions;;;ArrayElement of
// Argument[0];Argument[-1];taint"
// "android.app;Notification$Builder;true;setActions;;;SyntheticField[android.app.Notification.action]
// of ArrayElement of Argument[0];SyntheticField[android.app.Notification.action] of
// Argument[-1];taint"
Notification.Builder out = null;
Notification.Action[] in = (Notification.Action[]) new Notification.Action[] {
(Notification.Action) source()};
@@ -347,7 +349,8 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Builder;true;setContentIntent;;;Argument[0];Argument[-1];taint"
// "android.app;Notification$Builder;true;setContentIntent;;;Argument[0];SyntheticField[android.app.Notification.action]
// of Argument[-1];taint"
Notification.Builder out = null;
PendingIntent in = (PendingIntent) source();
out.setContentIntent(in);
@@ -396,7 +399,8 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];Argument[-1];taint"
// "android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];SyntheticField[android.app.Notification.action]
// of Argument[-1];taint"
Notification.Builder out = null;
PendingIntent in = (PendingIntent) source();
out.setDeleteIntent(in);
@@ -410,7 +414,7 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.app.Notification$Builder.extras]
// "android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.content.Intent.extras]
// of Argument[-1];value"
Notification.Builder out = null;
Bundle in = (Bundle) source();
@@ -537,7 +541,8 @@ public class Test {
sink(out); // $ hasValueFlow
}
{
// "android.app;Notification$Builder;true;setPublicVersion;;;Argument[0];Argument[-1];taint"
// "android.app;Notification$Builder;true;setPublicVersion;;;SyntheticField[android.app.Notification.action]
// of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint"
Notification.Builder out = null;
Notification in = (Notification) source();
out.setPublicVersion(in);

View File

@@ -1,4 +1,5 @@
import java
import semmle.code.java.frameworks.android.Intent
import TestUtilities.InlineFlowTest
class SummaryModelTest extends SummaryModelCsv {
@@ -6,9 +7,18 @@ class SummaryModelTest extends SummaryModelCsv {
row =
[
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind",
"generatedtest;Test;false;getMapKeyDefault;(Bundle);;MapKey of Argument[0];ReturnValue;value",
"generatedtest;Test;false;newActionBuilderWithExtras;(Bundle);;Argument[0];SyntheticField[android.app.NotificationActionBuilder.extras] of ReturnValue;value",
"generatedtest;Test;false;newBuilderWithExtras;(Bundle);;Argument[0];SyntheticField[android.app.NotificationBuilder.extras] of ReturnValue;value"
"generatedtest;Test;false;getMapKeyDefault;(Bundle);;MapKey of Argument[0];ReturnValue;value"
]
}
}
class NotificationsTaintFlowConf extends DefaultTaintFlowConf {
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
super.allowImplicitRead(node, c)
or
isSink(node) and
c.(DataFlow::SyntheticFieldContent).getField() = "android.app.Notification.action"
or
allowIntentExtrasImplicitRead(node, c)
}
}