bytedance / appshark

Appshark is a static taint analysis platform to scan vulnerabilities in an Android app.
Apache License 2.0
1.5k stars 166 forks source link

SliceMode不能正确找到入口 #69

Open firmianay opened 9 months ago

firmianay commented 9 months ago

这个应用存在漏洞CVE-2023-42468,我想写个规则来扫,先试了SliceMode,不行,好像是因为根据source和sink不能自动找到入口,后面跟不动了。

换成DirectMode并指定method可以扫出来,但如果指定的是"ExportedCompos": true,速度贼慢,最后也没扫出来。

请教下师傅,看看是哪儿的问题?

{
  placeCall: {
    DirectMode: true,
    // SliceMode: true,
    traceDepth: 20,
    desc: {
    },
    entry: {
      "methods": ["<com.cutestudio.dialer.activities.DialerActivity: void onCreate(android.os.Bundle)>"],
      // "ExportedCompos": true
    },
    source: {
      Return: ["<android.app.Activity: android.content.Intent getIntent(*)>"],
    },
    sink: {
      "<android.telecom.TelecomManager: void placeCall(android.net.Uri,android.os.Bundle)>": {
        TaintCheck: ["p0"],
      },
    },
    sanitizer: {},
  },
}
    "Sink": [
        "virtualinvoke $r4.<android.telecom.TelecomManager: void placeCall(android.net.Uri,android.os.Bundle)>($r5, $r1)"
    ],
    "position": "<com.cutestudio.dialer.activities.DialerActivity: void onCreate(android.os.Bundle)>",
    "Manifest": {
        "exported": true,
        "trace": [
            "<com.cutestudio.dialer.activities.DialerActivity: void onCreate(android.os.Bundle)>"
        ],
        "<activity exported=true name=com.cutestudio.dialer.activities.DialerActivity theme=2131952515 label=2131886319>": [
            {
                "<intent-filter>": [
                    {
                        "content": "<action name=android.intent.action.CALL>",
                        "isString": true
                    },
                    {
                        "content": "<category name=android.intent.category.DEFAULT>",
                        "isString": true
                    },
                    {
                        "content": "<data scheme=tel>",
                        "isString": true
                    }
                ]
            }
        ]
    },
    "entryMethod": "<com.cutestudio.dialer.activities.DialerActivity: void onCreate(android.os.Bundle)>",
    "Source": [
        "$r2_2 = virtualinvoke r0.<android.app.Activity: android.content.Intent getIntent()>()"
    ],
    "target": [
        "<com.cutestudio.dialer.activities.DialerActivity: void onCreate(android.os.Bundle)>->$r2_2",
        "<com.cutestudio.dialer.activities.DialerActivity: void onCreate(android.os.Bundle)>->$r4_1",
        "pf{obj{<CustomClass: void Main_Entry_CustomClass()>:0=>com.cutestudio.dialer.activities.DialerActivity}(android.net.Uri)->g0}",
        "<com.cutestudio.dialer.activities.DialerActivity: android.net.Uri O1(com.cutestudio.dialer.activities.DialerActivity)>->r1",
        "<com.cutestudio.dialer.activities.DialerActivity$a: void c(android.telecom.PhoneAccountHandle)>->$r5"
    ]
nkbai commented 9 months ago

能否1. 提供一下有问题的apk的下载链接,问题中的是latest链接,问题应该修复了吧。

  1. jadx反编译后,预期的数据流是什么?截图让我看看
firmianay commented 9 months ago

1、我放的这个链接是2.1.8版本,就是存在漏洞的

2、数据流就是正常的数据流,问题在于这是一个导出组件,其他跟正常app应该是一样的。核心是getIntent -> getData -> placeCall,这中间用到了几次回调,可能是这个原因,我不太确定

LLeavesG commented 4 months ago

@firmianay @nkbai 请问师傅有解决问题么,遇到了相似的问题,但是我的甚至指定入口都会死掉

@override
public void handleIntent() {
        super.handleIntent();
        Intent intent = getIntent();
        if (intent == null) {
            return;
        }
        boolean z9 = false;
        boolean booleanExtra = intent.getBooleanExtra(EXTRA_FROM_PRIVATE, false);
        this.mFromPrivate = booleanExtra;
        if (booleanExtra) {
            setResult(100);
        }
        String str = intent.getBooleanExtra(EXTRA_INNER_CALL, false) ? "inner" : "outer";
        String scheme = intent.getScheme();
        Uri data = intent.getData();
        if (data != null && y.i()) {
            y.b("FileActivity", "parsing uri: " + data.toString());
        }
        if (!TextUtils.isEmpty(scheme) && y.i()) {
            y.b("FileActivity", "handle intent with scheme: " + scheme);
        }
        if ((TextUtils.isEmpty(scheme) || !FirebaseAnalytics.Param.CONTENT.equals(scheme)) && !"android.intent.action.SEND".equals(intent.getAction()) && !"android.intent.action.SEND_MULTIPLE".equals(intent.getAction())) {
            String path = data != null ? data.getPath() : "";
            if (TextUtils.isEmpty(path)) {
                if (intent.hasExtra("explorer_path")) {
                    path = intent.getStringExtra("explorer_path");
                } else if (intent.hasExtra("current_directory")) {
                    path = intent.getStringExtra("current_directory");
                }
            }
            boolean isEmpty = TextUtils.isEmpty(path);
            if (!"android.intent.action.VIEW".equals(intent.getAction()) || TextUtils.isEmpty(path) || !new File(path).exists() || intent.getComponent() == null) {
                z9 = isEmpty;
            } else {
                int checkIntent = checkIntent(intent, path, str);
                if (checkIntent == -1) {
                    return;
                }
                if (checkIntent == 1) {
                    z9 = true;
                }
            }
        } else if (data != null || intent.getClipData() == null) {
            if (data != null) {
                handleUri(data, intent, str);
            }
        } else if (intent.getClipData().getItemCount() == 1) {
            handleUri(intent.getClipData().getItemAt(0).getUri(), intent, str);
        } else if (intent.getClipData().getItemCount() > 1) {
            ArrayList arrayList = new ArrayList();
            for (int i9 = 0; i9 < intent.getClipData().getItemCount(); i9++) {
                arrayList.add(intent.getClipData().getItemAt(i9).getUri());
            }
            handleUri(arrayList, intent, str);
        }

假设污点分析 Uri data = intent.getData(); 的返回值能否到达handleUri(data, intent, str);,

{
    "DirtyStream": {
        "DirectMode": true,
        "traceDepth": 40,
        "desc": {
            "name": "DirtyStream",
            "category": "DirtyStream",
            "detail": "DirtyStream",
            "wiki": "",
            "possibility": "2",
            "model": "high"
        },
        "entry":{
            "method":[
                "<com.android.fileexplorer.activity.FileActivity: void handleIntent()>"
            ]
        },
        "source": {
            "Return": [
                "<android.content.Intent : android.net.Uri getData()>"
            ]
        },
        "sink": {
            "<com.android.fileexplorer.activity.FileActivity: void handleUri(android.net.Uri,android.content.Intent,java.lang.String)>": {
                "TaintCheck": [
                    "p0"
                ]
            }
        }
    }
}

但是并没有得到任何输出,在parse完就终止了 image

LLeavesG commented 4 months ago

我已经发现了我的问题所在,"<android.content.Intent : android.net.Uri getData()>" 这里的签名出现错误导致无法处理source,正确的签名在类名之后不能出现空格,即"<android.content.Intent: android.net.Uri getData()>" 但是很抱歉,你的错误我没有解决方案