MASTG-TECH-0108: 污点分析

污点分析是一种信息流分析技术,用于跟踪程序中敏感信息的流动。 例如,它可以确定 Android 应用程序中收集的地理位置数据是否正在传输到第三方域。

在污点分析中,数据从“源”流向“汇”。 源是敏感信息的来源,而汇是最终使用该信息的地方。 例如,我们可以确定由getDeviceId()函数检索的设备 ID 是否通过另一个函数sendTextMessage()作为文本消息传输。 在这种情况下,getDeviceId()是源,而sendTextMessage()是汇。 如果它们之间存在直接路径,则称为泄漏

在大型应用程序中,手动信息流分析可能非常耗时且不准确。 污点分析可以自动执行此过程,主要有两种方法:静态和动态。 前者检查代码而不运行它,提供广泛的覆盖范围,但可能产生误报。 相比之下,动态分析观察实时应用程序执行,提供实际上下文,但可能忽略未触发的问题。 对这些技术进行全面的比较超出了本节的范围。

有多种工具可以对本机代码执行污点分析,包括Tritonbincat。 但是,在本节中,我们将主要关注 Android Java 代码,并使用 FlowDroid 进行污点分析。 另一个支持 Android 应用程序污点分析的著名工具是GDA

在我们的演示中,我们将使用 FlowDroid 命令行工具对 InsecureShop v1.0 应用程序执行污点分析。

InsecureShop 应用程序接受用户名和密码作为输入,并将它们存储在应用程序的共享首选项中。 在我们的污点分析中,我们对如何使用此存储的用户名和密码感兴趣。 在这种情况下,用户名和密码是敏感信息,而从共享首选项读取是源。 此分析中的汇可以是各种操作,例如通过网络发送信息、通过 Intent 传输信息或将信息存储在外部文件中。

要使用 FlowDroid,首先,我们需要提供一个潜在源和汇的输入列表以供评估。 在我们的例子中,从共享首选项读取将是源,而将参数添加到Intent将是汇。 配置文件如下所示(我们将其命名为“source_sink.txt”)

<android.content.SharedPreferences: java.lang.String getString(java.lang.String, java.lang.String)> -> _SOURCE_

<android.content.Intent: android.content.Intent putExtra(java.lang.String,java.lang.CharSequence)> -> _SINK_
<android.content.Intent: android.content.Intent putExtra(java.lang.String,char)> -> _SINK_
<android.content.Intent: android.content.Intent putExtra(java.lang.String,java.lang.String)> -> _SINK_

要通过命令行调用 FlowDroid,请使用以下命令

java -jar soot-infoflow-cmd/target/soot-infoflow-cmd-jar-with-dependencies.jar \
    -a InsecureShop.apk \
    -p Android/Sdk/platforms \
    -s source_sink.txt


[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke r2.<android.content.Intent: android.content.Intent putExtra(java.lang.String,java.lang.String)>("password", $r5) in method <com.insecureshop.AboutUsActivity: void onSendData(android.view.View)> was called with values from the following sources:

[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r1 = interfaceinvoke $r2.<android.content.SharedPreferences: java.lang.String getString(java.lang.String,java.lang.String)>("password", "") in method <com.insecureshop.util.Prefs: java.lang.String getPassword()>

...

[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke r2.<android.content.Intent: android.content.Intent putExtra(java.lang.String,java.lang.String)>("username", $r4) in method <com.insecureshop.AboutUsActivity: void onSendData(android.view.View)> was called with values from the following sources:

[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r1 = interfaceinvoke $r2.<android.content.SharedPreferences: java.lang.String getString(java.lang.String,java.lang.String)>("username", "") in method <com.insecureshop.util.Prefs: java.lang.String getUsername()>

...

[main] INFO soot.jimple.infoflow.android.SetupApplication - Found 2 leaks

输出还使用 jimple 中间表示,并揭示了应用程序中的两个泄漏,每个泄漏对应于用户名和密码。 鉴于 InsecureShop 应用程序是开源的,我们可以参考其源代码来验证结果,如下所示

// file: AboutActivity.kt

fun onSendData(view: View) {
        val userName = Prefs.username!!
        val password = Prefs.password!!

        val intent = Intent("com.insecureshop.action.BROADCAST")
        intent.putExtra("username", userName)
        intent.putExtra("password", password)
        sendBroadcast(intent)

        textView.text = "InsecureShop is an intentionally designed vulnerable android app built in Kotlin."

    }

污点分析对于自动化复杂应用程序中的数据流分析特别有益。 但是,鉴于某些应用程序的复杂性,此类工具的准确性可能会有所不同。 因此,审查员必须在工具的准确性和手动分析所花费的时间之间找到平衡。