OWASP 類別:MASVS-STORAGE:儲存空間
總覽
以 Android 10 (API 29) 以下版本為目標版本的應用程式不會強制執行範圍限制
如果 30 天內讀取資料不到一次
建議使用 Nearline Storage也就是說,任何儲存在外部儲存空間的資料,都可以由具備 READ_EXTERNAL_STORAGE
權限的任何其他應用程式存取。
影響
指定 Android 10 (API 29) 以下版本為目標版本的應用程式中,如果機密資料為 儲存儲存在外部儲存空間的任何應用程式 READ_EXTERNAL_STORAGE 權限可存取此 API。這會造成惡意 隨時視需要永久或暫時存取機密檔案 儲存在外部儲存空間此外,由於系統中的任何應用程式都能存取外部儲存空間中的內容,因此任何宣告 WRITE_EXTERNAL_STORAGE 權限的惡意應用程式,都可能竄改儲存在外部儲存空間中的檔案,例如加入惡意資料。這種惡意行為 載入應用程式中時,也可能用於欺騙使用者,甚至 即可執行程式碼
因應措施
限定範圍儲存空間 (Android 10 以上版本)
Android 10
針對指定 Android 10 為目標版本的應用程式,開發人員可以明確選擇加入受限儲存空間。只需設定
在 requestLegacyExternalStorage
標記設為 false:
AndroidManifest.xml
檔案。有了限定範圍儲存空間,應用程式只能存取在外部儲存空間中自行建立的檔案,或是使用 MediaStore API 儲存的檔案類型,例如音訊和影片。這有助於保護使用者的隱私權和安全。
Android 11 以上版本
針對指定 Android 11 以上版本為目標的應用程式,作業系統會強制執行
限定範圍儲存空間因此系統會忽略
requestLegacyExternalStorage
標記並自動保護
應用程式防止不必要的存取外部儲存空間
使用內部儲存空間存放機密資料
無論指定的 Android 版本為何,應用程式的機密資料 一律應儲存在內部儲存空間中內部儲存空間的存取權為 有了 Android 沙箱機制 因此除非裝置已啟用 Root 權限,否則系統將視為安全裝置。
加密機密資料
如果應用程式的用途需要將機密資料儲存在外部 如果儲存,資料就必須加密。建議您使用強大的加密演算法,並透過 Android KeyStore 安全地儲存金鑰。
一般而言,將所有機密資料加密是建議的安全做法, 無論是儲存在何處
請注意,全磁碟加密 (或 Android 10 的檔案型加密) 是一種措施,可防止他人透過實體存取和其他攻擊途徑存取資料。因此,要授予相同的安全措施 同時,您也必須對儲存在外部儲存空間的資料進行加密, 應用程式。
執行完整性檢查
如果需要將資料從外部儲存空間載入到 完整性檢查功能,確認沒有其他應用程式遭到竄改 包含這項資料或程式碼檔案雜湊應儲存 並儲存在內部儲存空間中
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!");
}
}
}
資源
- 限定範圍儲存空間
- READ_EXTERNAL_STORAGE
- WRITE_EXTERNAL_STORAGE
- requestLegacyExternalStorage
- 資料與檔案儲存空間總覽
- 資料儲存 (特定應用程式)
- 密碼編譯
- 金鑰庫
- 檔案型加密
- 全磁碟加密