[quandary] ContentProvider Uri's as sources/files as sinks

Reviewed By: mburman

Differential Revision: D4917047

fbshipit-source-id: 994891b
master
Sam Blackshear 8 years ago committed by Facebook Github Bot
parent 05a9270b13
commit 20aff78b36

@ -17,7 +17,7 @@ module SourceKind = struct
| Intent (** external Intent or a value read from one *) | Intent (** external Intent or a value read from one *)
| Other (** for testing or uncategorized sources *) | Other (** for testing or uncategorized sources *)
| PrivateData (** private user or device-specific data *) | PrivateData (** private user or device-specific data *)
| WebviewUrl (** external URL passed to a WebView *) | UserControlledURI (** resource locator controller by user *)
| Unknown | Unknown
[@@deriving compare] [@@deriving compare]
@ -26,7 +26,7 @@ module SourceKind = struct
let of_string = function let of_string = function
| "Intent" -> Intent | "Intent" -> Intent
| "PrivateData" -> PrivateData | "PrivateData" -> PrivateData
| "WebviewUrl" -> WebviewUrl | "UserControlledURI" -> UserControlledURI
| _ -> Other | _ -> Other
let external_sources = QuandaryConfig.Source.of_json Config.quandary_sources let external_sources = QuandaryConfig.Source.of_json Config.quandary_sources
@ -120,16 +120,28 @@ module SourceKind = struct
Some (taint_formals_with_types ["android.content.Intent"] Intent formals) Some (taint_formals_with_types ["android.content.Intent"] Intent formals)
| "android.content.BroadcastReceiver", "onReceive" -> | "android.content.BroadcastReceiver", "onReceive" ->
Some (taint_formals_with_types ["android.content.Intent"] Intent formals) Some (taint_formals_with_types ["android.content.Intent"] Intent formals)
| "android.content.ContentProvider",
("bulkInsert" |
"delete" |
"insert" |
"openAssetFile" |
"openFile" |
"openPipeHelper" |
"openTypedAssetFile" |
"query" |
"refresh" |
"update") ->
Some (taint_formals_with_types ["android.net.Uri"] UserControlledURI formals)
| "android.webkit.WebViewClient", | "android.webkit.WebViewClient",
("onLoadResource" | "shouldInterceptRequest" | "shouldOverrideUrlLoading") -> ("onLoadResource" | "shouldInterceptRequest" | "shouldOverrideUrlLoading") ->
Some Some
(taint_formals_with_types (taint_formals_with_types
["android.webkit.WebResourceRequest"; "java.lang.String"] ["android.webkit.WebResourceRequest"; "java.lang.String"]
WebviewUrl UserControlledURI
formals) formals)
| "android.webkit.WebChromeClient", | "android.webkit.WebChromeClient",
("onJsAlert" | "onJsBeforeUnload" | "onJsConfirm" | "onJsPrompt") -> ("onJsAlert" | "onJsBeforeUnload" | "onJsConfirm" | "onJsPrompt") ->
Some (taint_formals_with_types ["java.lang.String"] WebviewUrl formals) Some (taint_formals_with_types ["java.lang.String"] UserControlledURI formals)
| _ -> | _ ->
None in None in
begin begin
@ -151,7 +163,7 @@ module SourceKind = struct
F.fprintf fmt F.fprintf fmt
(match kind with (match kind with
| Intent -> "Intent" | Intent -> "Intent"
| WebviewUrl -> "WebviewUrl" | UserControlledURI -> "UserControlledURI"
| PrivateData -> "PrivateData" | PrivateData -> "PrivateData"
| Other -> "Other" | Other -> "Other"
| Unknown -> "Unknown") | Unknown -> "Unknown")
@ -161,6 +173,7 @@ module JavaSource = Source.Make(SourceKind)
module SinkKind = struct module SinkKind = struct
type t = type t =
| CreateFile (** sink that creates a file *)
| CreateIntent (** sink that creates an Intent *) | CreateIntent (** sink that creates an Intent *)
| JavaScript (** sink that passes its arguments to untrusted JS code *) | JavaScript (** sink that passes its arguments to untrusted JS code *)
| Logging (** sink that logs one or more of its arguments *) | Logging (** sink that logs one or more of its arguments *)
@ -169,6 +182,8 @@ module SinkKind = struct
[@@deriving compare] [@@deriving compare]
let of_string = function let of_string = function
| "CreateFile" -> CreateFile
| "CreateIntent" -> CreateIntent
| "JavaScript" -> JavaScript | "JavaScript" -> JavaScript
| "Logging" -> Logging | "Logging" -> Logging
| "StartComponent" -> StartComponent | "StartComponent" -> StartComponent
@ -194,9 +209,14 @@ module SinkKind = struct
match pname with match pname with
| Typ.Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
begin begin
match Typ.Procname.java_get_class_name java_pname, Typ.Procname.java_get_method java_pname with match Typ.Procname.java_get_class_name java_pname,
Typ.Procname.java_get_method java_pname with
| "android.util.Log", ("e" | "println" | "w" | "wtf") -> | "android.util.Log", ("e" | "println" | "w" | "wtf") ->
taint_all Logging ~report_reachable:true taint_all Logging ~report_reachable:true
| "java.io.File", "<init>"
| "java.nio.file.FileSystem", "getPath"
| "java.nio.file.Paths", "get" ->
taint_all CreateFile ~report_reachable:true
| "com.facebook.infer.builtins.InferTaint", "inferSensitiveSink" -> | "com.facebook.infer.builtins.InferTaint", "inferSensitiveSink" ->
[Other, 0, false] [Other, 0, false]
| class_name, method_name -> | class_name, method_name ->
@ -284,6 +304,7 @@ module SinkKind = struct
let pp fmt kind = let pp fmt kind =
F.fprintf fmt F.fprintf fmt
(match kind with (match kind with
| CreateFile -> "CreateFile"
| CreateIntent -> "CreateIntent" | CreateIntent -> "CreateIntent"
| JavaScript -> "JavaScript" | JavaScript -> "JavaScript"
| Logging -> "Logging" | Logging -> "Logging"
@ -304,9 +325,12 @@ include
| Intent, StartComponent (* intent reuse issue *) | Intent, StartComponent (* intent reuse issue *)
| Intent, CreateIntent (* intent configured with external values issue *) | Intent, CreateIntent (* intent configured with external values issue *)
| Intent, JavaScript (* external data flows into JS: remote code execution risk *) | Intent, JavaScript (* external data flows into JS: remote code execution risk *)
| WebviewUrl, (CreateIntent | StartComponent)
(* create intent/launch component from external URL *)
| PrivateData, JavaScript (* leaking private data into JS *) | PrivateData, JavaScript (* leaking private data into JS *)
| UserControlledURI, (CreateIntent | StartComponent)
(* create intent/launch component from user-controlled URI *)
| UserControlledURI, CreateFile ->
(* create file from user-controller URI; potential path-traversal vulnerability *)
true
| Other, _ | _, Other -> (* for testing purposes, Other matches everything *) | Other, _ | _, Other -> (* for testing purposes, Other matches everything *)
true true
| _ -> | _ ->

@ -0,0 +1,77 @@
/*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package codetoanalyze.java.quandary;
import java.io.File;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
public abstract class ContentProviders extends ContentProvider {
File mFile;
@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
mFile = new File(uri.toString());
return 0;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
mFile = new File(uri.toString());
return 0;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
mFile = new File(uri.toString());
return null;
}
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal) {
mFile = new File(uri.toString());
return null;
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) {
mFile = new File(uri.toString());
return null;
}
@Override
public AssetFileDescriptor openTypedAssetFile(
Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal) {
mFile = new File(uri.toString());
return null;
}
@Override
public Cursor query(
Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
mFile = new File(uri.toString());
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
mFile = new File(uri.toString());
return 0;
}
}

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package codetoanalyze.java.quandary;
import com.facebook.infer.builtins.InferTaint;
import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Files {
public File fileConstructorSinkBad() {
String taintedString = (String) InferTaint.inferSecretSource();
return new File(taintedString);
}
public Path fileSystemConstructorSinkBad1() {
String taintedString = (String) InferTaint.inferSecretSource();
return FileSystems.getDefault().getPath(taintedString);
}
// testing varags
public Path fileSystemConstructorSinkBad2() {
String taintedString = (String) InferTaint.inferSecretSource();
return FileSystems.getDefault().getPath("", taintedString);
}
public Path pathsSinkBad1() {
String taintedString = (String) InferTaint.inferSecretSource();
return Paths.get(taintedString);
}
// testing varags
public Path pathsSinkBad2() {
String taintedString = (String) InferTaint.inferSecretSource();
return Paths.get("", taintedString);
}
}

@ -25,6 +25,14 @@ codetoanalyze/java/quandary/Basics.java, void Basics.viaVarBad2(), 3, QUANDARY_T
codetoanalyze/java/quandary/Basics.java, void Basics.viaVarBad3(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Basics.java, void Basics.viaVarBad3(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Basics.java, void Basics.whileBad1(int), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Basics.java, void Basics.whileBad1(int), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Basics.java, void Basics.whileBad2(int), 6, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Basics.java, void Basics.whileBad2(int), 6, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/ContentProviders.java, AssetFileDescriptor ContentProviders.openAssetFile(Uri,String,CancellationSignal), 1, QUANDARY_TAINT_ERROR, [return from AssetFileDescriptor ContentProviders.openAssetFile(Uri,String,CancellationSignal),call to File.<init>(String)]
codetoanalyze/java/quandary/ContentProviders.java, AssetFileDescriptor ContentProviders.openTypedAssetFile(Uri,String,Bundle,CancellationSignal), 2, QUANDARY_TAINT_ERROR, [return from AssetFileDescriptor ContentProviders.openTypedAssetFile(Uri,String,Bundle,CancellationSignal),call to File.<init>(String)]
codetoanalyze/java/quandary/ContentProviders.java, Cursor ContentProviders.query(Uri,java.lang.String[],String,java.lang.String[],String), 2, QUANDARY_TAINT_ERROR, [return from Cursor ContentProviders.query(Uri,java.lang.String[],String,java.lang.String[],String),call to File.<init>(String)]
codetoanalyze/java/quandary/ContentProviders.java, ParcelFileDescriptor ContentProviders.openFile(Uri,String,CancellationSignal), 1, QUANDARY_TAINT_ERROR, [return from ParcelFileDescriptor ContentProviders.openFile(Uri,String,CancellationSignal),call to File.<init>(String)]
codetoanalyze/java/quandary/ContentProviders.java, Uri ContentProviders.insert(Uri,ContentValues), 1, QUANDARY_TAINT_ERROR, [return from Uri ContentProviders.insert(Uri,ContentValues),call to File.<init>(String)]
codetoanalyze/java/quandary/ContentProviders.java, int ContentProviders.bulkInsert(Uri,android.content.ContentValues[]), 1, QUANDARY_TAINT_ERROR, [return from int ContentProviders.bulkInsert(Uri,android.content.ContentValues[]),call to File.<init>(String)]
codetoanalyze/java/quandary/ContentProviders.java, int ContentProviders.delete(Uri,String,java.lang.String[]), 1, QUANDARY_TAINT_ERROR, [return from int ContentProviders.delete(Uri,String,java.lang.String[]),call to File.<init>(String)]
codetoanalyze/java/quandary/ContentProviders.java, int ContentProviders.update(Uri,ContentValues,String,java.lang.String[]), 1, QUANDARY_TAINT_ERROR, [return from int ContentProviders.update(Uri,ContentValues,String,java.lang.String[]),call to File.<init>(String)]
codetoanalyze/java/quandary/DynamicDispatch.java, void DynamicDispatch.FP_propagateViaConcreteTypeOk(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadSubtype.returnSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/DynamicDispatch.java, void DynamicDispatch.FP_propagateViaConcreteTypeOk(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadSubtype.returnSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/DynamicDispatch.java, void DynamicDispatch.FP_propagateViaConcreteTypeOk(), 7, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadSubtype.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/DynamicDispatch.java, void DynamicDispatch.FP_propagateViaConcreteTypeOk(), 7, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadSubtype.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/DynamicDispatch.java, void DynamicDispatch.FP_propagateViaConcreteTypeOk(), 10, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object DynamicDispatch$BadSubtype.propagate(Object),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/DynamicDispatch.java, void DynamicDispatch.FP_propagateViaConcreteTypeOk(), 10, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object DynamicDispatch$BadSubtype.propagate(Object),call to void InferTaint.inferSensitiveSink(Object)]
@ -54,6 +62,11 @@ codetoanalyze/java/quandary/Fields.java, void Fields.viaFieldBad2(), 3, QUANDARY
codetoanalyze/java/quandary/Fields.java, void Fields.viaFieldBad3(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Fields.java, void Fields.viaFieldBad3(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Fields.java, void Fields.viaNestedFieldBad1(Fields$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Fields.java, void Fields.viaNestedFieldBad1(Fields$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Fields.java, void Fields.viaNestedFieldBad2(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Fields.java, void Fields.viaNestedFieldBad2(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Files.java, File Files.fileConstructorSinkBad(), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to File.<init>(String)]
codetoanalyze/java/quandary/Files.java, Path Files.fileSystemConstructorSinkBad1(), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to Path FileSystem.getPath(String,java.lang.String[])]
codetoanalyze/java/quandary/Files.java, Path Files.fileSystemConstructorSinkBad2(), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to Path FileSystem.getPath(String,java.lang.String[])]
codetoanalyze/java/quandary/Files.java, Path Files.pathsSinkBad1(), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to Path Paths.get(String,java.lang.String[])]
codetoanalyze/java/quandary/Files.java, Path Files.pathsSinkBad2(), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to Path Paths.get(String,java.lang.String[])]
codetoanalyze/java/quandary/FlowSensitivity.java, void FlowSensitivity.callSourceAndSinkBad1(FlowSensitivity$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from void FlowSensitivity.sourceAndSink(FlowSensitivity$Obj),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/FlowSensitivity.java, void FlowSensitivity.callSourceAndSinkBad1(FlowSensitivity$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from void FlowSensitivity.sourceAndSink(FlowSensitivity$Obj),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/FlowSensitivity.java, void FlowSensitivity.callSourceAndSinkBad2(FlowSensitivity$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void FlowSensitivity.sourceAndSink(FlowSensitivity$Obj),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/FlowSensitivity.java, void FlowSensitivity.callSourceAndSinkBad2(FlowSensitivity$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void FlowSensitivity.sourceAndSink(FlowSensitivity$Obj),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/FlowSensitivity.java, void FlowSensitivity.interproceduralFlowSensitivityBad(FlowSensitivity$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from void FlowSensitivity.returnSource(FlowSensitivity$Obj),call to void FlowSensitivity.callSink(FlowSensitivity$Obj),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/FlowSensitivity.java, void FlowSensitivity.interproceduralFlowSensitivityBad(FlowSensitivity$Obj), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from void FlowSensitivity.returnSource(FlowSensitivity$Obj),call to void FlowSensitivity.callSink(FlowSensitivity$Obj),call to void InferTaint.inferSensitiveSink(Object)]

Loading…
Cancel
Save