Harici Depolama Alanlarında Depolanan Hassas Veriler

OWASP kategorisi: MASVS-STORAGE: Depolama

Genel Bakış

Android 10 (API 29) veya önceki sürümleri hedefleyen uygulamalar, kapsamlı depolama alanı. Yani, harici depolama biriminde depolanan tüm veriler READ_EXTERNAL_STORAGE bulunan başka bir uygulama tarafından erişilen izni gerekir.

Etki

Android 10 (API 29) veya önceki sürümleri hedefleyen uygulamalarda, harici depolama alanında hassas veriler depolanıyorsa cihazdaki READ_EXTERNAL_STORAGE iznine sahip tüm uygulamalar bu verilere erişebilir. Bu, kötü amaçlı uygulamaların harici depolama alanında kalıcı veya geçici olarak depolanan hassas dosyalara gizlice erişmesine olanak tanır. Ayrıca, harici depolama alanındaki içeriğe sistemdeki herhangi bir uygulama erişebildiğinden, WRITE_EXTERNAL_STORAGE iznini de açıklayan kötü amaçlı uygulamalar, harici depolama alanındaki dosyalarla (ör. kötü amaçlı veriler eklemek için) oynayabilir. Uygulamaya yüklenen bu kötü amaçlı veriler, kullanıcıları aldatacak veya hatta kod yürütecek şekilde tasarlanabilir.

Çözümler

Kapsamlı Depolama (Android 10 ve sonraki sürümler)

Android 10

Android 10'u hedefleyen uygulamalarda geliştiriciler, kapsamlı depolama alanını açıkça etkinleştirebilir. Bu işlem, AndroidManifest.xml dosyasında requestLegacyExternalStorage işaretini false olarak ayarlayarak yapılabilir. Kapsamlı depolama ile uygulamalar yalnızca harici depolama alanında kendi oluşturdukları dosyalara veya MediaStore API kullanılarak depolanan ses ve video gibi dosya türlerine erişebilir. Bu kullanıcı gizliliğinin ve güvenliğinin korunmasına yardımcı olur.

Android 11 ve sonraki sürümler

Android 11 veya sonraki sürümleri hedefleyen uygulamalarda işletim sistemi kapsamlı depolama alanının kullanımını zorunlu kılar. Yani requestLegacyExternalStorage işaretini yoksayar ve uygulamaların harici depolama alanını istenmeyen erişime karşı otomatik olarak korur.

Hassas Veriler İçin Dahili Depolama Kullanma

Hedeflenen Android sürümünden bağımsız olarak, bir uygulamanın hassas verileri her zaman dahili depoda depolanmalıdır. Dahili depolamaya erişim: Ancak Android korumalı alan sayesinde uygulama sahibi olan uygulamayla otomatik olarak kısıtlanır. Bu nedenle, cihaz rootlanmış değilse güvenli olarak kabul edilebilir.

Hassas verileri şifreleyin

Uygulamanın kullanım alanları, hassas verilerin harici depolama alanında depolanmasını gerektiriyorsa veriler şifrelenmelidir. Anahtarı güvenli bir şekilde depolamak için Android KeyStore'un kullanıldığı güçlü bir şifreleme algoritması önerilir.

Genel olarak, tüm hassas verilerin şifrelenmesi önerilen bir güvenlik uygulamasıdır. nerede depolandığı önemli.

Tam disk şifrelemenin (veya diğer sunucularınızdan Android 10), verileri fiziksel erişimden ve diğer durumlardan yardımcı olabilir. Bu nedenle, aynı güvenlik önlemini sağlamak için harici depolama alanında tutulan hassas verilerin uygulama tarafından da şifrelenmesi gerekir.

Bütünlük kontrolleri gerçekleştirme

Verilerin veya kodun harici depolamadan depolama alanına yüklenmesinin gerektiği başka bir uygulamada izinsiz değişiklik yapılmadığını doğrulayan bütünlük kontrolleri kullanmanız önerilir. Dosyaların karma oluşturma işlemleri güvenli bir şekilde, tercihen şifrelenmiş olarak ve dahili depolama alanında saklanmalıdır.

Kotlin

package com.example.myapplication

import java.io.BufferedInputStream
import java.io.FileInputStream
import java.io.IOException
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException

object FileIntegrityChecker {
    @Throws(IOException::class, NoSuchAlgorithmException::class)
    fun getIntegrityHash(filePath: String?): String {
        val md = MessageDigest.getInstance("SHA-256") // You can choose other algorithms as needed
        val buffer = ByteArray(8192)
        var bytesRead: Int
        BufferedInputStream(FileInputStream(filePath)).use { fis ->
            while (fis.read(buffer).also { bytesRead = it } != -1) {
                md.update(buffer, 0, bytesRead)
            }

    }

    private fun bytesToHex(bytes: ByteArray): String {
        val sb = StringBuilder()
        for (b in bytes) {
            sb.append(String.format("%02x", b))
        }
        return sb.toString()
    }

    @Throws(IOException::class, NoSuchAlgorithmException::class)
    fun verifyIntegrity(filePath: String?, expectedHash: String): Boolean {
        val actualHash = getIntegrityHash(filePath)
        return actualHash == expectedHash
    }

    @Throws(Exception::class)
    @JvmStatic
    fun main(args: Array<String>) {
        val filePath = "/path/to/your/file"
        val expectedHash = "your_expected_hash_value"
        if (verifyIntegrity(filePath, expectedHash)) {
            println("File integrity is valid!")
        } else {
            println("File integrity is compromised!")
        }
    }
}

Java

package com.example.myapplication;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileIntegrityChecker {

    public static String getIntegrityHash(String filePath) throws IOException, NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256"); // You can choose other algorithms as needed
        byte[] buffer = new byte[8192];
        int bytesRead;

        try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(filePath))) {
            while ((bytesRead = fis.read(buffer)) != -1) {
                md.update(buffer, 0, bytesRead);
            }
        }

        byte[] digest = md.digest();
        return bytesToHex(digest);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    public static boolean verifyIntegrity(String filePath, String expectedHash) throws IOException, NoSuchAlgorithmException {
        String actualHash = getIntegrityHash(filePath);
        return actualHash.equals(expectedHash);
    }

    public static void main(String[] args) throws Exception {
        String filePath = "/path/to/your/file";
        String expectedHash = "your_expected_hash_value";

        if (verifyIntegrity(filePath, expectedHash)) {
            System.out.println("File integrity is valid!");
        } else {
            System.out.println("File integrity is compromised!");
        }
    }
}

Kaynaklar