
أداة مساعدة لتقييم روابط الـ Deeplink، و Intent، وجسر WebView في نظام أندرويد لصالح الاختراق الأخلاقي
مساعد تقييم الروابط العميقة (Deeplink) وIntent وجسر WebView لنظام Android
apk-interceptor هو ملف APK اختباري محمول لتقييم أمان التطبيقات بعد الحصول على إذن. يساعد مهندسي الأمان في التحقق من كيفية تعامل تطبيق Android مع نقاط الدخول الخارجية مثل مخططات URI المخصصة، والروابط العميقة، والأنشطة المصدرة (Exported Activities)، وجسور JavaScript في WebView.
الأداة مقيدة عمداً:
android.permission.INTERNETcontent://خلال تقييم أمان تطبيقات Android، لا تزال العديد من النتائج من التحليل الثابت تحتاج إلى دليل إثبات صغير على الجهاز قبل تأكيدها: تسجيل مخطط URI مخصص، إرسال Intent صريح، تقديم حمولة محلية عبر content://، أو التحقق مما إذا كان JavaScript يمكنه الوصول إلى جسر WebView.
بناء تطبيق اختبار مؤقت جديد لكل حالة متكرر وعرضة للخطأ. الاختلافات الصغيرة في إدخالات البيان، والسلطات (authorities)، ومنح URI، وأسماء الحزم، أو بناء Intent يمكن أن تبطئ التحقق وتجعل النتائج أصعب في التكرار.
تم إنشاء apk-interceptor لجعل خطوة التأكيد قابلة للتكرار. بدلاً من كتابة تطبيق PoC جديد لكل تقييم، تقوم ببناء هذه الأداة باستخدام المخطط المخول أو معرف التطبيق الذي تحتاجه، وتجري الاختبار على الجهاز، وتحافظ على سير العمل مقيداً بالتصميم: بدون إذن INTERNET، بدون نقل بيانات خارجي، بدون تنفيذ أوامر shell، وبدون اعتماد على الجذر.
apk-interceptor مفيد لمهام التقييم التالية:
شروحات مفصلة للثغرات:
content://يحتفظ التطبيق بسجل تقييم في الذاكرة لـ Intents المرسلة، والروابط العميقة المستقبلة، واستدعاءات الجسر، ونتائج JavaScript، والأخطاء. تختفي السجلات عند إنهاء عملية التطبيق. نظراً لأن السجلات لا تستمر، التقط الأدلة باستخدام لقطات الشاشة أو تسجيل الشاشة أثناء العمل.
apk-interceptor هو أداة تأكيد، وليس إطار اكتشاف أو استغلال. يفترض أنك تعرف بالفعل ما تريد اختباره (المخطط، فئة النشاط، اسم الجسر) من التحليل الثابت، ويمنحك طريقة آمنة على الجهاز للتحقق من الوصول والتقاط الأدلة. تم بناؤه ليتم تثبيته على جهاز تقييم وحتى مشاركته مع عميل، لذلك لا يشمل إذن INTERNET، ولا تنفيذ أوامر shell، ولا تسريب بيانات، ولا يتطلب صلاحية الجذر.
أين يقع بجانب الأدوات المعتادة لنظام Android:
المجالان اللذان يتمتع فيهما apk-interceptor بميزة واضحة على البدائل:
adb/التحليل الثابت إظهاره.content:// → جسر WebView: مزود غير مصدر بملف واحد يتم تسليم حمولته فقط من خلال منح قراءة Intent مؤقت، بالإضافة إلى WebView محلي للاختبار الذاتي للتحقق من صيغة الحمولة أولاً.يتعامل apk-interceptor مع الإرسال والاعتراض بشكل مختلف، وهذا هو أهم شيء يجب فهمه قبل الاستخدام:
| الإجراء | الوحدة | هل يحتاج مخطط مخصص في وقت البناء؟ |
|---|---|---|
| إرسال Intent أو رابط عميق إلى تطبيق آخر | Sender | لا، اكتب أي URI أو حزمة أو نشاط في وقت التشغيل |
| اعتراض (استلام) رابط عميق لمخطط مخصص | Interceptor | نعم، يتم تثبيت المخطط في APK في وقت البناء |
لإرسال رابط عميق مصمم إلى التطبيق المقيم، لا تحتاج إلى إعادة بناء: استخدم وضع الرابط العميق الضمني (Implicit Deeplink) في علامة التبويب Sender واكتب أي URI.
لاعتراض رابط عميق، أي جعل Android يوجه مخطط مخصص إلى apk-interceptor حتى تتمكن من ملاحظة احتمال اختطاف المخطط، يجب بناء APK بهذا المخطط باستخدام --scheme. يتم تثبيت المخطط في وقت البناء عن قصد (كميزة أمان تصميمية)؛ لا يسجل apk-interceptor مخططات عشوائية في وقت التشغيل. إذا قمت بتغيير المخطط الذي تقيمه، قم بإعادة البناء وإعادة التثبيت.
adb لتثبيت الجهاز واختبار سطر الأوامر الاختياريقم ببناء APK باستخدام مخطط URI المخصص الذي لديك الإذن بتقييمه:
./build-interceptor.sh --scheme <authorized_custom_scheme>
adb install ./out/apk-interceptor-<authorized_custom_scheme>-debug.apk
علامات البناء الاختيارية:
./build-interceptor.sh \
--scheme <authorized_custom_scheme> \
--app-id <custom.application.id> \
--output ./out
--app-id يحدد معرف التطبيق المثبت (هوية الحزمة على الجهاز وسلطة content://<applicationId>.payload) في وقت البناء. الافتراضي هو com.sterrasec.apkinterceptor. قم بتجاوزه باستخدام --app-id عندما تحتاج إلى إصدارات متعددة قابلة للتثبيت بشكل منفصل لتقييمات مختلفة. المكافئ لنظام Windows هو build-interceptor.bat.
المخطط الافتراضي intercept-poc-example هو عنصر نائب غير ضار. يرفض سكريبت البناء إنتاج APK تقييم بهذا المخطط الافتراضي.
في التشغيل الأول لكل إصدار من التطبيق، يعرض apk-interceptor مربع حوار الاستخدام المأذون. بعد النقر على أنا أفهم، لا يظهر مربع الحوار مرة أخرى لنفس الإصدار. لا تزال علامة التبويب Sender تظهر تحذيراً مستمراً لأنه يمكنها إرسال Intents إلى تطبيقات أخرى.
| Sender | Payload | Interceptor |
|---|---|---|
![]() | ![]() | ![]() |
استخدم علامة التبويب هذه للتحقق من اعتراض مخطط URI المخصص.
ماذا يعرض:
سير العمل الأساسي:
حول إرسال رابط اختبار عميق: يرسل دائماً <scheme>://test?<your params> مع مضيف test ثابت، لذا فهو مخصص لتأكيد أن apk-interceptor يستلم المخطط ويسجله، وليس لدفع مسارات الرابط العميق المحددة للتطبيق المقيم. لإرسال رابط عميق مصمم يتطابق مع المضيف أو المسار المطلوب للتطبيق المقيم، استخدم وضع الرابط العميق الضمني في علامة التبويب Sender بدلاً من ذلك.
مثال adb:
adb shell am start -W \
-a android.intent.action.VIEW \
-d 'my-authorized-scheme://test?source=adb\&message=hello%20world'
استخدم \& عند إرسال معاملات استعلام متعددة عبر adb shell؛ وإلا فقد تتعامل شل الجهاز مع & كفاصل أوامر.
النتيجة المتوقعة:
RECEIVEDاستخدم علامة التبويب هذه لإرسال Intents محكومة أثناء اختبار مأذون.
الأوضاع:
Intent(ACTION_VIEW, Uri.parse(uri))الحقول وعناصر التحكم:
سير العمل للرابط العميق الضمني:
سير العمل للنشاط الصريح:
ملاحظات:
content:// مفيد عند اختبار ما إذا كان النشاط المستهدف يمرر بيانات Intent غير موثوقة إلى WebView.data الخاصة بـ Intent، مما قد يلغي URI الذي تكتبه في وضع الرابط العميق الضمني، لذا يكون الخيار مخفياً هناك.PayloadProvider غير مصدر. يستطيع التطبيق المقيم قراءة الحمولة content:// المرفقة فقط لأن Intent يمنحه إذن قراءة مؤقتاً عبر FLAG_GRANT_READ_URI_PERMISSION. ابق هذا العلم مفعلاً، وقم بتسليم URI عبر Intent. لن يكون URI content:// المفتوح بأي طريقة أخرى قابلاً للقراءة بواسطة تطبيق آخر.استخدم علامة التبويب هذه لإنشاء حمولة HTML محلية والتحقق من صيغة جسر JavaScript في WebView الاختبار الذاتي الخاص بـ apk-interceptor.
ما تحتوي عليه:
content:// المُنشأصيغة URI الحمولة المُنشأة:
content://<applicationId>.payload/current.html
يخدم المزود هذا الملف الثابت فقط:
filesDir/payloads/current.html
سير العمل للاختبار الذاتي للحمولة:
localBridge.BRIDGE_RESULT وconsole.log وevaluateJavascript result في السجل.مثال لـ JavaScript للاختبار الذاتي:
console.log("payload loaded");
window.localBridge.logResult(window.localBridge.getInfo());
يعرض جسر الاختبار الذاتي:
window.<bridgeName>.logResult("message");
window.<bridgeName>.getInfo();
قيود مهمة:
يؤكد WebView الاختبار الذاتي أن حمولتك المحلية وصيغة استدعاء الجسر تعملان داخل apk-interceptor. لا يمكنه ملاحظة ما إذا كان WebView تطبيق آخر قد نفذ حمولتك أو استدعى جسره الخاص. بالنسبة للتطبيق المقيم، تحقق من خلال واجهة المستخدم الخاصة بذلك التطبيق أو السجلات أو خطافات الاختبار أو Chrome DevTools إذا كان التطبيق قابلًا للتصحيح (debuggable).
المخاطرة:
يسجل تطبيق Android مخطط URI مخصص بدلاً من رابط تطبيق تم التحقق منه (App Link). يمكن لأي تطبيق آخر تسجيل نفس المخطط، لذا قد يعرض Android محدد تطبيق أو يوجه الروابط إلى تطبيق مختلف.
استخدم apk-interceptor للتحقق من:
الخطوات:
الأدلة التي يجب التقاطها:
المخاطرة:
يثق التطبيق المقيم في معاملات الرابط العميق للتنقل أو تحميل URL أو أعلام الميزات أو اختيار الحساب أو العرض دون تحقق كافٍ.
استخدم apk-interceptor للتحقق من:
الخطوات:
عنصر نائب مثال:
my-authorized-scheme://open?next=https%3A%2F%2Fauthorized-test.example%2Flanding
لا تستخدم نطاقات أو حسابات تابعة لجهات خارجية حقيقية ما لم تكن صراحة ضمن النطاق.
المخاطرة:
يقوم النشاط المصدر بإجراءات حساسة أو يعرض بيانات حساسة دون التحقق من المتصل أو حالة المستخدم أو التصريح المطلوب.
استخدم apk-interceptor للتحقق من:
الخطوات:
content://.الأدلة التي يجب التقاطها:
content://المخاطرة:
يقوم التطبيق المقيم بتحميل بيانات content:// غير موثوقة من Intent إلى WebView يعرض أيضاً جسر JavaScript عبر addJavascriptInterface.
استخدم apk-interceptor للتحقق من:
content://الخطوات:
قيود مهمة:
لا يمكن لـ apk-interceptor استلام نتائج من تطبيق آخر ما لم يقم ذلك التطبيق بإرجاعها أو عرضها صراحة. الأداة مصممة لتسليم حمولة محلية والتحقق من الصيغة، وليس لتسريب البيانات.
تحقق من أن APK لا يطلب الوصول إلى الشبكة:
aapt dump permissions ./out/apk-interceptor-<scheme>-debug.apk
المتوقع: لا وجود لـ android.permission.INTERNET.
قم بتفعيل رابط عميق بشكل صريح إلى apk-interceptor:
adb shell am start -W \
-n com.sterrasec.apkinterceptor/.InterceptActivity \
-a android.intent.action.VIEW \
-d 'my-authorized-scheme://test?source=adb'
قم بتفعيل رابط عميق عبر حلّال Android:
adb shell am start -W \
-a android.intent.action.VIEW \
-d 'my-authorized-scheme://test?source=adb'
الأمر الصريح يؤكد سلوك InterceptActivity. الأمر الضمني يؤكد عامل تصفية Intent في البيان وسلوك الحلّال.
تعمل اختبارات الوحدة على JVM باستخدام Robolectric، لذا لا حاجة لجهاز أو محاكي. تغطي PayloadProvider، بما في ذلك فحوصات القائمة البيضاء للمسار والاجتياز التي تمنع المزود من خدمة أي شيء آخر غير ملف current.html الوحيد.
./gradlew testDebugUnitTest
تكتب نتائج الاختبار إلى app/build/reports/tests/testDebugUnitTest/index.html. يتم تشغيل نفس المهمة في CI عند كل دفع وطلب سحب إلى main.
android.permission.INTERNET/current.html يتم تقديمه بواسطة PayloadProviderMIT
| السيناريو | الوحدة | ما يساعد في التحقق منه |
|---|
| اختطاف مخطط URI مخصص | Interceptor | ما إذا كان تطبيق آخر يمكنه تسجيل نفس المخطط المخصص واستلام الروابط |
| معالجة معاملات الرابط العميق | Sender | ما إذا كان التطبيق المقيم يقبل معاملات غير آمنة للمسار/الاستعلام |
| كشف نشاط مصدر | Sender | ما إذا كان يمكن تشغيل نشاط مصدر مباشرة بواسطة تطبيق آخر |
كشف جسر WebView عبر content:// | Payload + Sender | ما إذا كانت حمولة HTML محلية يمكنها الوصول إلى جسر JavaScript في WebView |
| التحقق من صيغة الحمولة المحلية | Payload | ما إذا كانت حمولة HTML/JS الخاصة بك تعمل في WebView للاختبار الذاتي |
| أداة | الدور | كيف يختلف apk-interceptor |
|---|
| jadx / MobSF / QARK / Semgrep | العثور على نقاط الدخول الضعيفة (ثابت) | apk-interceptor لا يفحص أو يفك التجميع؛ بل يؤكد وجود نتيجة لديك بالفعل |
deep-C / NSdeepLink / adb am start | تعداد إرسال الروابط العميقة | apk-interceptor يمكنه الإرسال أيضاً، لكن ميزته الفريدة هي استلام مخطط مختطف وعرض URI والمعاملات بالضبط |
| drozer | إطار هجوم عام على الجهاز (عامل + غالباً جذر) | apk-interceptor هو APK خفيف واحد مع حواجز أمان متعمدة، ونطاق أضيق، وتوزيع أسهل وآمن للعملاء |
| Metasploit / Frida | تسليح أو خطاف (مثل addJavascriptInterface RCE) | apk-interceptor يتحقق فقط من قابلية الوصول للجسر بحمولة غير ضارة؛ لا يسرب البيانات أو ينفذ أوامر shell أبداً |