OWASP-Kategorie: MASVS-CODE: Codequalität
Übersicht
Das dynamische Laden von Code in eine Anwendung erhöht das Risiko, das minimiert werden muss. Angreifer könnten den Code möglicherweise manipulieren oder ersetzen, um auf sensible Daten zuzugreifen oder schädliche Aktionen auszuführen.
Viele Formen des dynamischen Code-Ladens, insbesondere solche, die Remote-Quellen verwenden, verstoßen gegen die Google Play-Richtlinien und können dazu führen, dass Ihre App von Google Play entfernt wird.
Positiv beeinflussen
Wenn Angreifer Zugriff auf den Code erhalten, der in die Anwendung geladen wird, können sie ihn so ändern, dass er ihren Zielen dient. Dies kann zu Datenexfiltration und Codeausführungs-Exploits führen. Selbst wenn Angreifer den Code nicht ändern können, um beliebige Aktionen auszuführen, ist es möglich, dass sie den Code beschädigen oder entfernen und so die Verfügbarkeit der Anwendung beeinträchtigen.
Abhilfemaßnahmen
Vermeiden Sie das dynamische Laden von Code.
Vermeiden Sie das Laden dynamischen Codes, es sei denn, dies ist geschäftlich erforderlich. Sie sollten nach Möglichkeit alle Funktionen direkt in die Anwendung einbinden.
Vertrauenswürdige Quellen verwenden
Code, der in die Anwendung geladen wird, sollte an vertrauenswürdigen Speicherorten gespeichert werden. Für den lokalen Speicher werden der interne Speicher der App oder der Speicher mit Bereichsbeschränkung (für Android 10 und höher) empfohlen. An diesen Speicherorten sind Maßnahmen ergriffen, um einen direkten Zugriff durch andere Anwendungen und Nutzer zu verhindern.
Wenn Sie Code von Remote-Speicherorten wie URLs laden, sollten Sie möglichst keine Drittanbieter verwenden und den Code gemäß den Best Practices für die Sicherheit in Ihrer eigenen Infrastruktur speichern. Wenn Sie Code von Drittanbietern laden müssen, achten Sie darauf, dass der Anbieter vertrauenswürdig ist.
Integritätsprüfungen durchführen
Integritätsprüfungen werden empfohlen, um sicherzustellen, dass der Code nicht manipuliert wurde. Diese Prüfungen sollten durchgeführt werden, bevor Code in die Anwendung geladen wird.
Beim Laden von Remote-Ressourcen kann die Integrität von Unterressourcen verwendet werden, um die Integrität der Ressourcen zu validieren, auf die zugegriffen wird.
Führen Sie beim Laden von Ressourcen aus dem externen Speicher Integritätsprüfungen durch, um sicherzustellen, dass keine andere Anwendung diese Daten oder diesen Code manipuliert hat. Die Hashes der Dateien sollten sicher gespeichert werden, vorzugsweise verschlüsselt und im internen Speicher.
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(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!")
}
}
}
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(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!");
}
}
}
Code signieren
Eine weitere Möglichkeit, die Integrität der Daten zu gewährleisten, besteht darin, den Code zu signieren und seine Signatur vor dem Laden zu überprüfen. Diese Methode hat den Vorteil, dass auch die Integrität des Hash-Codes und nicht nur des Codes selbst sichergestellt wird. Dies bietet einen zusätzlichen Schutz vor Manipulationen.
Die Codesignatur bietet zwar zusätzliche Sicherheitsebenen, aber es ist wichtig zu beachten, dass es sich um einen komplexeren Prozess handelt, der für eine erfolgreiche Implementierung zusätzlichen Aufwand und Ressourcen erfordern kann.
Einige Beispiele für die Codesignatur finden Sie im Abschnitt „Ressourcen“ dieses Dokuments.
Ressourcen
- Integrität von Unterressourcen
- Daten digital signieren
- Code Signing
- In externem Speicher gespeicherte sensible Daten