Kategori OWASP: MASVS-STORAGE: Storage
Ringkasan
Aplikasi yang menargetkan Android 10 (API 29) atau yang lebih rendah tidak menerapkan cakupan
Google Cloud Storage. Ini berarti bahwa setiap data yang
disimpan di penyimpanan eksternal dapat
diakses oleh aplikasi lain dengan READ_EXTERNAL_STORAGE
izin akses.
Dampak
Dalam aplikasi yang menargetkan Android 10 (API 29) atau yang lebih rendah, jika data sensitif disimpan di penyimpanan eksternal, aplikasi apa pun di perangkat dengan izin READ_EXTERNAL_STORAGE dapat mengaksesnya. Hal ini memungkinkan serangan aplikasi untuk mengakses file sensitif secara otomatis atau sementara yang disimpan di penyimpanan eksternal. Selain itu, karena konten eksternal penyimpanan dapat diakses oleh aplikasi apa pun pada sistem, aplikasi berbahaya apa pun yang juga mendeklarasikan izin WRITE_EXTERNAL_STORAGE dapat mengutak-atik file yang disimpan di penyimpanan eksternal, misalnya untuk menyertakan data berbahaya. Data berbahaya ini, jika dimuat ke dalam aplikasi, dapat dirancang untuk menipu pengguna atau bahkan mencapai eksekusi kode.
Mitigasi
Penyimpanan Terbatas (Android 10 dan yang lebih baru)
Android 10
Untuk aplikasi yang menargetkan Android 10, developer dapat secara eksplisit memilih ikut serta dalam
dengan penyimpanan terbatas. Hal ini dapat dilakukan dengan menyetel atribut
requestLegacyExternalStorage
ditandai ke false di
AndroidManifest.xml
. Dengan penyimpanan terbatas, aplikasi hanya dapat mengakses
file yang mereka buat sendiri di penyimpanan eksternal atau jenis file
yang disimpan menggunakan MediaStore API seperti Audio dan Video. Ini
membantu melindungi privasi dan keamanan pengguna.
Android 11 dan yang lebih baru
Untuk aplikasi yang menargetkan Android 11 atau versi yang lebih baru, OS menerapkan
penggunaan penyimpanan terbatas, yaitu mengabaikan
requestLegacyExternalStorage
menandai dan otomatis melindungi
aplikasi penyimpanan eksternal dari
akses yang tidak diinginkan.
Menggunakan Penyimpanan Internal untuk Data Sensitif
Apa pun versi Android yang ditargetkan, data sensitif aplikasi harus selalu disimpan di penyimpanan internal. Akses ke penyimpanan internal secara otomatis dibatasi hanya untuk aplikasi yang dimiliki berkat sandbox Android, oleh karena itu, dianggap aman, kecuali jika perangkat di-root.
Mengenkripsi data sensitif
Jika kasus penggunaan aplikasi memerlukan penyimpanan data sensitif di server eksternal penyimpanan, data itu harus dienkripsi. Algoritma enkripsi yang kuat direkomendasikan, menggunakan Android KeyStore untuk menyimpan kunci dengan aman.
Secara umum, mengenkripsi semua data sensitif adalah praktik keamanan yang disarankan, peduli di mana data tersebut disimpan.
Penting untuk diperhatikan bahwa enkripsi disk penuh (atau enkripsi berbasis file dari Android 10) adalah tindakan yang bertujuan melindungi data dari akses fisik dan vektor serangan lainnya. Karena itu, untuk memberikan langkah keamanan yang sama, data yang disimpan di penyimpanan eksternal juga harus dienkripsi oleh aplikasi.
Melakukan pemeriksaan integritas
Jika data atau kode harus dimuat dari penyimpanan eksternal ke aplikasi, pemeriksaan integritas untuk memverifikasi bahwa tidak ada aplikasi lain yang dirusak dengan data atau kode ini adalah hal yang direkomendasikan. Hash file harus disimpan dengan cara yang aman, sebaiknya dienkripsi dan dalam penyimpanan internal.
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!");
}
}
}
Referensi
- Penyimpanan terbatas
- READ_EXTERNAL_STORAGE
- TULIS_EKSTERNAL_STORAGE
- requestLegacyExternalStorage
- Ringkasan penyimpanan data dan file
- Penyimpanan Data (Khusus Aplikasi)
- Kriptografi
- Keystore
- Enkripsi berbasis File
- Enkripsi Disk Penuh