OWASP कैटगरी: MASVS-STORAGE: स्टोरेज
खास जानकारी
Android 10 (एपीआई लेवल 29) या इससे पहले के वर्शन को टारगेट करने वाले ऐप्लिकेशन, स्कोप्ड
स्टोरेज का इस्तेमाल नहीं करते. इसका मतलब है कि बाहरी स्टोरेज में सेव किए गए किसी भी डेटा को,
की अनुमति वाले किसी भी ऐप्लिकेशन से ऐक्सेस किया जा सकता है.READ_EXTERNAL_STORAGE
असर
Android 10 (एपीआई लेवल 29) या इससे पहले के वर्शन को टारगेट करने वाले ऐप्लिकेशन में, अगर संवेदनशील डेटा को बाहरी स्टोरेज में सेव किया जाता है, तो डिवाइस पर मौजूद कोई भी ऐप्लिकेशन, READ_EXTERNAL_STORAGE की अनुमति के साथ उसे ऐक्सेस कर सकता है. इससे, दुर्भावनापूर्ण ऐप्लिकेशन, बाहरी स्टोरेज में स्थायी या अस्थायी तौर पर सेव की गई संवेदनशील फ़ाइलों को चुपके से ऐक्सेस कर सकते हैं. इसके अलावा, बाहरी स्टोरेज में मौजूद कॉन्टेंट को सिस्टम पर मौजूद कोई भी ऐप्लिकेशन ऐक्सेस कर सकता है.इसलिए, कोई भी दुर्भावनापूर्ण ऐप्लिकेशन, WRITE_EXTERNAL_STORAGE की अनुमति के साथ, बाहरी स्टोरेज में सेव की गई फ़ाइलों में छेड़छाड़ कर सकता है. जैसे, उनमें दुर्भावनापूर्ण डेटा शामिल करना. अगर इस दुर्भावनापूर्ण डेटा को ऐप्लिकेशन में लोड किया जाता है, तो इसे उपयोगकर्ताओं को धोखा देने या कोड को एक्ज़ीक्यूट करने के लिए डिज़ाइन किया जा सकता है.
खतरे को कम करने के तरीके
स्कोप्ड स्टोरेज (Android 10 और इसके बाद के वर्शन)
Android 10
Android 10 को टारगेट करने वाले ऐप्लिकेशन के लिए, डेवलपर साफ़ तौर पर स्कोप्ड स्टोरेज के लिए ऑप्ट-इन कर सकते हैं. इसके लिए,
requestLegacyExternalStorage फ़्लैग को false पर सेट किया जा सकता है, जो कि
AndroidManifest.xml फ़ाइल में है. स्कोप्ड स्टोरेज की मदद से, ऐप्लिकेशन सिर्फ़ उन
फ़ाइलों को ऐक्सेस कर सकते हैं जिन्हें उन्होंने बाहरी स्टोरेज में बनाया है. इसके अलावा, वे
MediaStore API का इस्तेमाल करके सेव किए गए ऑडियो और वीडियो जैसे फ़ाइल टाइप को भी ऐक्सेस कर सकते हैं. इससे, उपयोगकर्ता की निजता और सुरक्षा को बनाए रखने में मदद मिलती है.
Android 11 और इसके बाद के वर्शन
Android 11 या इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, ओएस स्कोप्ड स्टोरेज के इस्तेमाल को लागू करता है. इसका मतलब है कि यह
requestLegacyExternalStorage फ़्लैग को अनदेखा करता है और ऐप्लिकेशन के बाहरी स्टोरेज को अनचाहे ऐक्सेस से अपने-आप सुरक्षित रखता है.
संवेदनशील डेटा के लिए इंटरनल स्टोरेज का इस्तेमाल करना
टारगेट किए गए Android वर्शन के बावजूद, किसी ऐप्लिकेशन के संवेदनशील डेटा को हमेशा इंटरनल स्टोरेज में सेव किया जाना चाहिए. Android सैंडबॉक्सिंग की वजह से, इंटरनल स्टोरेज का ऐक्सेस, मालिकाना हक वाले ऐप्लिकेशन तक अपने-आप सीमित हो जाता है. इसलिए, इसे सुरक्षित माना जा सकता है. हालांकि, ऐसा तब तक है, जब तक डिवाइस रूट न किया गया हो.
संवेदनशील डेटा को एन्क्रिप्ट (सुरक्षित) करना
अगर ऐप्लिकेशन के इस्तेमाल के मामलों में, संवेदनशील डेटा को बाहरी स्टोरेज में सेव करना ज़रूरी है, तो डेटा को एन्क्रिप्ट (सुरक्षित) किया जाना चाहिए. सुरक्षित तरीके से कुंजी सेव करने के लिए, 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
- डेटा और फ़ाइल स्टोरेज की खास जानकारी
- डेटा स्टोरेज (ऐप्लिकेशन के हिसाब से)
- क्रिप्टोग्राफ़ी
- Keystore
- अलग-अलग फ़ाइलों को अलग-अलग तरीकों से एन्क्रिप्ट करने की सुविधा
- पूरी ड्राइव को सुरक्षित रखने की सुविधा