دسته OWASP: MASVS-CODE: کیفیت کد
نمای کلی
بارگذاری پویا کد در یک برنامه یک سطح خطر را معرفی می کند که باید کاهش یابد. مهاجمان به طور بالقوه می توانند کد را دستکاری یا جایگزین کنند تا به داده های حساس دسترسی پیدا کنند یا اقدامات مضر را انجام دهند.
بسیاری از اشکال بارگیری کد پویا، بهویژه آنهایی که از منابع راه دور استفاده میکنند، خطمشیهای Google Play را نقض میکنند و ممکن است منجر به تعلیق برنامه شما از Google Play شود.
تاثیر
اگر مهاجمان موفق شوند به کدی که در برنامه بارگذاری می شود دسترسی پیدا کنند، می توانند آن را برای حمایت از اهداف خود تغییر دهند. این می تواند منجر به استخراج داده ها و سوء استفاده های اجرای کد شود. حتی اگر مهاجمان نتوانند کد را برای انجام اقدامات دلخواه خود تغییر دهند، باز هم ممکن است بتوانند کد را خراب یا حذف کنند و در نتیجه بر در دسترس بودن برنامه تأثیر بگذارند.
اقدامات کاهشی
از بارگذاری کد پویا خودداری کنید
از بارگذاری کد پویا اجتناب کنید، مگر اینکه نیاز تجاری وجود داشته باشد. شما باید ترجیح دهید هر زمان که ممکن است همه عملکردها را مستقیماً در برنامه قرار دهید.
از منابع معتبر استفاده کنید
کدی که در برنامه بارگذاری می شود باید در مکان های قابل اعتماد ذخیره شود. در مورد فضای ذخیرهسازی محلی، فضای ذخیرهسازی داخلی برنامه یا فضای ذخیرهسازی محدوده (برای اندروید 10 و بالاتر) مکانهای پیشنهادی هستند. این مکان ها اقداماتی برای جلوگیری از دسترسی مستقیم سایر برنامه ها و کاربران دارند.
هنگام بارگیری کد از مکان های راه دور مانند URL ها، در صورت امکان از استفاده از اشخاص ثالث خودداری کنید و کد را در زیرساخت خود ذخیره کنید، با رعایت بهترین شیوه های امنیتی. اگر نیاز به بارگیری کد شخص ثالث دارید، اطمینان حاصل کنید که ارائه دهنده یک منبع قابل اعتماد است.
انجام بررسی های یکپارچگی
برای اطمینان از اینکه کد دستکاری نشده است، بررسی یکپارچگی توصیه می شود. این بررسی ها باید قبل از بارگذاری کد در برنامه انجام شود.
هنگام بارگیری منابع راه دور، می توان از یکپارچگی منابع فرعی به منظور اعتبارسنجی یکپارچگی منابع قابل دسترسی استفاده کرد.
هنگام بارگیری منابع از حافظه خارجی، از بررسی یکپارچگی استفاده کنید تا مطمئن شوید که هیچ برنامه دیگری در این داده یا کد دستکاری نکرده است. هش های فایل ها باید به صورت ایمن، ترجیحا رمزگذاری شده و در حافظه داخلی ذخیره شوند.
کاتلین
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(bytes.length * 2)
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!")
}
}
}
جاوا
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(bytes.length * 2);
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!");
}
}
}
کد را امضا کنید
گزینه دیگری برای اطمینان از یکپارچگی داده ها، امضای کد و تأیید امضای آن قبل از بارگیری آن است. این روش این مزیت را نیز دارد که از یکپارچگی کد هش، نه تنها خود کد، اطمینان حاصل می کند، که محافظت ضد دستکاری اضافی را فراهم می کند.
اگرچه امضای کد لایههای امنیتی بیشتری را فراهم میکند، مهم است که در نظر گرفته شود که فرآیند پیچیدهتری است که ممکن است برای اجرای موفقیتآمیز به تلاش و منابع بیشتری نیاز داشته باشد.
چند نمونه از امضای کد را می توان در بخش منابع این سند یافت.