Android uygulama paketlerinin doğrulanması ve imza kontrollerinin yapılması

Android

Arkadaşlar merhaba, uzun bir aradan sonra yeni bir makale ile karşınızdayım. İş yoğunluğundan dolayı pek vakit bulamıyorum maalesef blog yazılarıma…

Bu makalede sizlere Android uygulama paketlerinin (APK) Java uygulamaları içerisinden nasıl doğrulanacağına ilişkin kullanabileceğiniz bir kütüphaneden bahsedeceğim. Kütüphaneye geçmeden önce konu ile ilgili önemli bilgilerden bahsedelim…

Bildiğiniz üzere Android uygulamalarının dağıtımı .apk dosyaları olarak yapılır. Bu dosyalar .jar ve .zip dosya formatlarına çok benzeyen sıkıştırılmış bir başka dosya formatıdır aslında ve genellikle uygulamanın ihtiyaç duyduğu tüm derlenmiş kaynakları (derlenmiş kod, görseller, xml dosyaları, veri tabanı, tasarım düzeni dosyaları vb.) içerirler. APK dosyalarının içerikleri basit bir sıkıştırma yazılımı ile açılabilir ve derlenmiş kaynak kod, ücretsiz ve açık kaynak kodlu yazılımlar (APKTool ve Dex2Jar gibi) kullanılarak geriye mühendislik ile yeniden oluşturulabilir. Böyle bir durumda, kötü niyetli kişi ya da kişiler, Android uygulama paketlerinin içerisine zararlı bir takım kodlar ekleyerek yeniden dağıtıma çıkartabilir. Ciddi bir güvenlik sorunu!

İşte bu güvenlik sorununu aşmak için yazılım geliştiricilerin, geliştirdikleri Android uygulama paketlerini imzalamaları gerekmektedir (uygulama imzalama konusunda Android Developers blog’u müthiş bir makaleye sahip). Kısaca bahsetmek gerekirse, yazılım geliştiricilerin uygulamalarını dağıtıma çıkartmadan önce, uygulama paketlerini kendi özel anahtarları ya da sertifikaları ile imzalamaları gerekir. Bu özel anahtar ya da sertifika .keystore adlı bir dosyanın içerisinde bulunur ve bu dosyanın kaynak kontrolünün (source control) dışında tutulması ve güvenli bir yerde, yedekli bir şekilde saklanması tavsiye edilir çünkü bu dosyaya sahip olan bir başka kişi de uygulamayı aynı imza ile imzalayabilir.

Eğer imzalanmış bir uygulama, yukarıda bahsettiğimiz gibi kötü niyetli kişi ya da kişiler tarafından geriye mühendislik yolu ile değiştirildiğinde, uygulamanın imzası kırılır – imzasız uygulamalar da yüklenemezler. İçeriği değiştirilen .apk dosyalarının yeniden imzalanmaları gerekir. Yukarıda bahsettiğimiz, uygulamanın orjinal .keystore dosyasına sahip olunmadığı sürece ise .apk paketinin imzalanması hiçbir anlam ifade etmeyecektir çünkü uygulama paketi orjinal imzasının dışında bir imzaya sahip olacağı için kullanıcı cihazlarına yüklenemeyecektir.

İşte makalemize konu olan bölüm de burada başlıyor. Bazı durumlarda .apk dosyalarının doğruluğunu kod içerisinden manuel olarak kontrol etmek gerekebilir. Bu işlemi yapabilmek için aşağıdaki 3 adımı takip etmek gerekir:

  1. Sertifika imzasını bulun/edinin.
  2. İmzayı bir String sabiti olarak uygulamanızın içeriside tanımlayın.
  3. Uygulama çalışma zamanında (runtime), uygulama imzasını 2. adımda tanımladığınız imza ile kontrol edin.

Android SDK içerisinden .apk doğrulaması yapmak kolaydır çünkü .apk dosyalarının parse edilmesi ve imza kontrollerinin yapılmasını sağlayan built-in sınıflar Android SDK içersinde hali hazırda vardır (PackageManager sınıfı gibi). Örnek bir kod aşağıdaki gibi olabilir;

Android SDK ile İmza Kontrolü

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
32
33
34
35
36
  private static final int VALID = 0;
 
  private static final int INVALID = 1;
 
  public static int checkAppSignature(Context context) {
 
    try {
 
      PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
              PackageManager.GET_SIGNATURES);
 
      for (Signature signature : packageInfo.signatures) {
 
        byte[] signatureBytes = signature.toByteArray();
 
        MessageDigest md = MessageDigest.getInstance("SHA");
 
        md.update(signature.toByteArray());
 
        final String currentSignature = Base64.encodeToString(md.digest(), Base64.DEFAULT);
 
        // imzalari karsilastir
        if (SIGNATURE.equals(currentSignature)){
 
          return VALID;
 
        };
 
      }
 
    } catch (Exception e) {
	// NOP
    }
 
    return INVALID;
  }

Ancak Android SDK olmadan, bir Java uygulaması içerisinden .apk doğrulama işini yapmak zordur çünkü bu işe uygun yardımcı sınıflar Java JDK içerisinde bulunmamaktadır. İşte ben de tam da bu zorluktan dolayı, Java uygulamaları içerisinden .apk doğrulaması yapılabilmesine olanak sağlayan apk-verifier projesini oluşturdum (aslında Android SDK içerisindeki kodların alınıp, biraz düzenleme ile port edilmiş hali).

Bu kütüphaneyi kullanarak Java uygulamanız içerisinden, .apk paketlerinin bütünlük doğrulamasını ve imza kontrollerini gerçekleştirebilirsiniz. Örneğin;

APK Verifier ile Doğrulama

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
...
...
...
...
 
Path path = Paths.get("path/to/your/apk/file");
 
ByteBuffer buffer = ByteBuffer.wrap(Files.readAllBytes(path));
 
buffer.rewind();
 
DataSource dataSource = new ByteBufferDataSource(buffer);
 
ApkVerifier apkVerifier = new ApkVerifier();
 
Result result = apkVerifier.verify(dataSource, 20);
 
if (result.isVerified()) {
  ....
}

APK Verifier ile İmza Kontrolü

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
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
import org.apache.commons.codec.digest.DigestUtils;
...
...
...
...
 
Result result = apkVerifier.verify(YOUR_DATA_SOURCE, YOUR_MIN_SDK_VERSION);
 
boolean valid = false;
 
if (result.isVerified()) {
    String signatureSha1 = "";
 
    for (X509Certificate certificate : result.getSignerCertificates()) {
        signatureSha1 = DigestUtils.sha1Hex(certificate.getEncoded());
 
        if (YOUR_APK_SIGNATURE_SHA1.equalsIgnoreCase(signatureSha1)) {
            valid = true;
 
            break;
        }
}
 
if(valid){
  ....
}

Projenin kaynak kodlarına github üzerinden ulaşabilirsiniz

, , , , , , , , ,

No comments yet.

Bir Cevap Yazın

Font Resize