본문 바로가기
Hack/Mobile

[Android] DeepLink 취약점 (WebView Hijacking Via DeepLink)

by Becoming a Hacker 2022. 8. 7.
반응형

먼저 WebView와 DeepLink가 무엇인지 모르시는 분들은 아래의 링크를 먼저 보고 오시길 추천드립니다.

 

[Kotlin] WebView 사용 방법

WebView WebView란 프레임워크에 내장된 웹 브라우저 Component로써 View 형태로 App에 임베딩 하는 것이 가능합니다. 이러한 WebView는 App 안에서 HTML을 호출하여 App을 구현하는 Hybrid 형태의 App을 개발하는

hacksms.tistory.com

 

[Kotlin] 딥링크 (DeepLink)

딥링크 (DeepLink) 딥링크란 단순하게 특정 페이지 또는 특정 콘텐츠에 직접적으로 도달할 수 모든 링크를 의미합니다. 그리고 Android에서 딥링크란 Custom Scheme와 같은 특정 주소를 통하여 앱을 실행

hacksms.tistory.com

 

DeepLink란 Custom Scheme와 같은 특정 주소를 통하여 앱을 실행하거나 앱의 특정 화면을 호출할 수 있는 기능을 의미합니다.

 

그리고 DeepLink 기능을 이용하여 단순히 특정 화면을 호출하는 것뿐만 아니라 특정 URI를 WebView에 로드할 수도 있습니다.

 

만약, DeepLink 기능을 이용하여 특정 URI를 WebView에 호출할 수 있는 상황에서 공격자가 임의의 URI를 로드할 수 있다면 이는 심각한 보안 사고로 이어질 수 있습니다.

 

그리고 이러한 공격을 WebView Hijacking Via DeepLink 라고 부릅니다.

 

WebView Hijacking Via DeepLink

공격자가 임의의 URI를 로드할 수 있다면 어떠한 문제가 발생할 수 있을까요?

 

사실 이 부분은 WebView에 Javascript Interface가 어떻게 구현되었냐에 따라 달라집니다.

 

만약 Javascript Interface에 사용자의 민감한 정보(GPS 위치, 앱 내 중요 정보)를 확인할 수 있는 코드가 구현되어 있다면, WebView Hijacking 공격을 통하여 사용자의 민감한 정보를 공격자가 획득할 수 있습니다.

 

그럼 아래의 예제 앱을 통하여 시연을 해보겠습니다.

 

vulnApp.apk

Dropbox를 통해 공유함

www.dropbox.com

 

해당 앱의 AndroidManifest.xml 파일을 통하여 SecondActivity를 DeepLink 기능으로 호출할 수 있는 것을 확인하였습니다.

<activity
	android:name=".SecondActivity"
	android:exported="true"
	android:label="@string/app_name"
	android:theme="@style/Theme.VulnApp.NoActionBar">
	    <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:host="deeplink" android:scheme="hacksms"/>
	    </intent-filter>
</activity>

 

그리고 SecondActivity에서 DeepLink를 통해 전달된 URI를 추가적인 검증 없이 바로 WebView에 로드하는 것을 확인하였습니다.

intent?.let{
    if(Intent.ACTION_VIEW.equals(intent.getAction())){
        val uri = intent.data
        if(uri != null){
            val url:String? = uri.getQueryParameter("url")
            println(url)
            if(url != null){
                val webView = findViewById<WebView>(R.id.webView)
                webView.settings.apply{
                    // Enable Javascript Via WebView, Default is disabled
                    javaScriptEnabled = true
                }
                // 2rd Argument is Selector Name
                webView.addJavascriptInterface(WebAppInterface(this),"Hacksms")
                webView.webChromeClient = WebChromeClient()
                webView.loadUrl(url)

            }
        }
    }
}

 

공격자가 임의의 URI를 로드할 수 있는 경우에만 공격이 가능하다는 전제 조건이 해결되었습니다.

 

공격을 추가로 진행하기 위해 Javascript Interface가 어떻게 구현되었는지 확인한 결과, 사용자의 이름과 전화번호를 별다른 검증 없이 반환하고 있는 것을 확인하였습니다.

class WebAppInterface(private val mContext:Context){
    @JavascriptInterface
    fun getProfile(): String {
        return "사용자의 이름은 김철수 이며, 전화번호는 010-1234-2222 입니다.";
    }
}

 

이후, DeepLink 기능을 이용하여 사용자의 중요 정보를 Alert으로 노출시킬 수 있었습니다.

공격 DeepLink 주소 : hacksms://deeplink?url=javascript:alert(Hacksms.getProfile());

 

물론, 공격자의 서버로 해당 정보들을 전송함으로써 취약한 DeepLink에 접속한 이용자들의 중요 정보를 공격자의 서버에 저장할 수도 있습니다.

 

대응 방안

해당 취약점을 대응하기 위한 방법으로는 크게 2가지가 있을 것 같습니다.

 

1. 공격자가 임의의 URI를 로드할 수 없도록 WebView에 로드하는 URI 또는 Domain에 대한 추가 검증을 진행한다.

2. 인가된 URI에만 Javascript Interface의 권한을 부여한다.

 

보다 자세한 내용은 KISA에서 제공하는 가이드를 참고하시기 바랍니다.

 

KISA 인터넷 보호나라&KrCERT

KISA 인터넷 보호나라&KrCERT

www.boho.or.kr

 

댓글