먼저 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
'Hack > Mobile' 카테고리의 다른 글
Galaxy A12(A125N) Rooting With Magisk Without TWRP (0) | 2022.10.29 |
---|---|
[Android] Content Provider 취약점 (0) | 2022.08.10 |
[iOS] Frida에서 Fat Binary File Offset 잡기 (0) | 2022.04.24 |
[iOS] frida-ios-dump for Windows (0) | 2022.03.17 |
Android Snapshot 위치 (0) | 2022.03.08 |
댓글