Skip to content

Commit

Permalink
[MASWE-0020] Weak Encryption (by @appknox) (#2910)
Browse files Browse the repository at this point in the history
* added weaknesss

* updated weakness

* added MASTG-DEMO, rule, MASTG-TEST

* updated weakness.md

* fix spelling

* Update weaknesses/MASVS-CRYPTO/MASWE-0020.md

* Update weaknesses/MASVS-CRYPTO/MASWE-0020.md

* Update weaknesses/MASVS-CRYPTO/MASWE-0020.md

* Update weaknesses/MASVS-CRYPTO/MASWE-0020.md

* Update weaknesses/MASVS-CRYPTO/MASWE-0020.md

* Update weaknesses/MASVS-CRYPTO/MASWE-0020.md

* removed duplicate

* change status to new

* updated title MASTG-TEST-0211.md

* updated title MASTG-DEMO-0016.md

* updated tests-beta

* fix lint

* updated MASWE-0020.md

* updated mitigations

* updated changes

* removed MASTG-TEST-0211.md

* added new Demo

* 2 demo added

* renamed semgrep files

* updated

* rename

* updated

* updated MASWE-0020.md

* updated MASWE-0020.md

* updated weak-encryption.yaml

* Renamed files

* updated Demo.md

* rename rules filename

* updated changes

* updated changes

* fix

---------

Co-authored-by: Sven <sven@bsddaemon.org>
  • Loading branch information
sk3l10x1ng and sushi2k authored Feb 1, 2025
1 parent 74d9b6d commit 23d106c
Show file tree
Hide file tree
Showing 13 changed files with 594 additions and 9 deletions.
33 changes: 33 additions & 0 deletions demos/android/MASVS-CRYPTO/MASTG-DEMO-0022/MASTG-DEMO-0022.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
platform: android
title: Uses of Insecure Encryption Algorithms in Cipher with semgrep
id: MASTG-DEMO-0022
code: [kotlin]
---

### Sample

The code snippet below shows sample code contains use of insecure encryption algorithms.

{{ MastgTest.kt # MastgTest_reversed.java }}

### Steps

Let's run our @MASTG-TOOL-0110 rule against the sample code.

{{ ../../../../rules/mastg-android-weak-encryption-algorithms.yaml }}

{{ run.sh }}

### Observation

The rule has identified two instances in the code file where an insecure encryption is used. The specified line numbers are from the reversed code for further investigation and remediation.

{{ output.txt }}

### Evaluation

The test fails since several instances of weak encryption algorithms were found:

- Line 36 utilize insecure DES algorithm.
- Line 59 utilize insecure 3DES algorithm.
65 changes: 65 additions & 0 deletions demos/android/MASVS-CRYPTO/MASTG-DEMO-0022/MastgTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package org.owasp.mastestapp

import android.content.Context
import java.security.Key
import javax.crypto.Cipher
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.DESKeySpec
import javax.crypto.spec.DESedeKeySpec
import javax.crypto.spec.SecretKeySpec
import android.util.Base64

class MastgTest(private val context: Context) {

// Vulnerable encryption using DES (weak algorithm)
fun vulnerableDesEncryption(data: String): String {
try {
// Weak key for DES
val keySpec = DESKeySpec("12345678".toByteArray())
val keyFactory = SecretKeyFactory.getInstance("DES")
val secretKey: Key = keyFactory.generateSecret(keySpec)

// Weak encryption algorithm (DES) and weak mode (ECB)
val cipher = Cipher.getInstance("DES")
cipher.init(Cipher.ENCRYPT_MODE, secretKey)

val encryptedData = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT)
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}


// Vulnerable encryption using 3DES (Triple DES)
fun vulnerable3DesEncryption(data: String): String {
try {
// Weak key for 3DES (24-byte key)
val keySpec = DESedeKeySpec("123456789012345678901234".toByteArray()) // 24 bytes key
val keyFactory = SecretKeyFactory.getInstance("DESede")
val secretKey: Key = keyFactory.generateSecret(keySpec)

// Weak encryption algorithm (3DES)
val cipher = Cipher.getInstance("DESede")
cipher.init(Cipher.ENCRYPT_MODE, secretKey)

val encryptedData = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT)
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}

fun mastgTest(): String {
val sensitiveString = "Hello from the OWASP MASTG Test app."

// Encrypt with weak DES
val desEncryptedString = vulnerableDesEncryption(sensitiveString)

// Encrypt with weak 3DES
val tripleDesEncryptedString = vulnerable3DesEncryption(sensitiveString)

// Returning the encrypted results
return "DES Encrypted: $desEncryptedString\n3DES Encrypted: $tripleDesEncryptedString"
}
}
77 changes: 77 additions & 0 deletions demos/android/MASVS-CRYPTO/MASTG-DEMO-0022/MastgTest_reversed.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.owasp.mastestapp;

import android.content.Context;
import android.util.Base64;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.text.Charsets;

/* compiled from: MastgTest.kt */
@Metadata(d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0004\b\u0007\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\u0006\u0010\u0005\u001a\u00020\u0006J\u000e\u0010\u0007\u001a\u00020\u00062\u0006\u0010\b\u001a\u00020\u0006J\u000e\u0010\t\u001a\u00020\u00062\u0006\u0010\b\u001a\u00020\u0006R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000¨\u0006\n"}, d2 = {"Lorg/owasp/mastestapp/MastgTest;", "", "context", "Landroid/content/Context;", "(Landroid/content/Context;)V", "mastgTest", "", "vulnerable3DesEncryption", "data", "vulnerableDesEncryption", "app_debug"}, k = 1, mv = {1, 9, 0}, xi = 48)
/* loaded from: classes4.dex */
public final class MastgTest {
public static final int $stable = 8;
private final Context context;

public MastgTest(Context context) {
Intrinsics.checkNotNullParameter(context, "context");
this.context = context;
}

public final String vulnerableDesEncryption(String data) {
Intrinsics.checkNotNullParameter(data, "data");
try {
byte[] bytes = "12345678".getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes, "this as java.lang.String).getBytes(charset)");
DESKeySpec keySpec = new DESKeySpec(bytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
Key generateSecret = keyFactory.generateSecret(keySpec);
Intrinsics.checkNotNullExpressionValue(generateSecret, "generateSecret(...)");
Key secretKey = generateSecret;
Cipher cipher = Cipher.getInstance("DES");
cipher.init(1, secretKey);
byte[] bytes2 = data.getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes2, "this as java.lang.String).getBytes(charset)");
byte[] encryptedData = cipher.doFinal(bytes2);
String encodeToString = Base64.encodeToString(encryptedData, 0);
Intrinsics.checkNotNullExpressionValue(encodeToString, "encodeToString(...)");
return encodeToString;
} catch (Exception e) {
return "Encryption error: " + e.getMessage();
}
}

public final String vulnerable3DesEncryption(String data) {
Intrinsics.checkNotNullParameter(data, "data");
try {
byte[] bytes = "123456789012345678901234".getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes, "this as java.lang.String).getBytes(charset)");
DESedeKeySpec keySpec = new DESedeKeySpec(bytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
Key generateSecret = keyFactory.generateSecret(keySpec);
Intrinsics.checkNotNullExpressionValue(generateSecret, "generateSecret(...)");
Key secretKey = generateSecret;
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(1, secretKey);
byte[] bytes2 = data.getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes2, "this as java.lang.String).getBytes(charset)");
byte[] encryptedData = cipher.doFinal(bytes2);
String encodeToString = Base64.encodeToString(encryptedData, 0);
Intrinsics.checkNotNullExpressionValue(encodeToString, "encodeToString(...)");
return encodeToString;
} catch (Exception e) {
return "Encryption error: " + e.getMessage();
}
}

public final String mastgTest() {
String desEncryptedString = vulnerableDesEncryption("Hello from the OWASP MASTG Test app.");
String tripleDesEncryptedString = vulnerable3DesEncryption("Hello from the OWASP MASTG Test app.");
return "DES Encrypted: " + desEncryptedString + "\n3DES Encrypted: " + tripleDesEncryptedString;
}
}
13 changes: 13 additions & 0 deletions demos/android/MASVS-CRYPTO/MASTG-DEMO-0022/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@


┌─────────────────┐
│ 2 Code Findings │
└─────────────────┘

MastgTest_reversed.java
❯❱rules.weak-encryption-algorithms
[MASVS-CRYPTO-1] Weak encryption algorithms found in use.

36┆ Cipher cipher = Cipher.getInstance("DES");
⋮┆----------------------------------------
59┆ Cipher cipher = Cipher.getInstance("DESede");
1 change: 1 addition & 0 deletions demos/android/MASVS-CRYPTO/MASTG-DEMO-0022/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-weak-encryption-algorithms.yaml ./MastgTest_reversed.java --text -o output.txt
38 changes: 38 additions & 0 deletions demos/android/MASVS-CRYPTO/MASTG_DEMO-0016/MASTG-DEMO-0016.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
platform: android
title: Uses of Insecure Encryption Modes in Cipher with semgrep
id: MASTG-DEMO-0016
code: [kotlin]
test: MASTG-TEST-0221
---

### Sample

The code snippet below shows sample code contains use of insecure encryption modes.

{{ MastgTest.kt # MastgTest_reversed.java }}

### Steps

Let's run our @MASTG-TOOL-0110 rule against the sample code.

{{ ../../../../rules/mastg-android-weak-encryption-modes }}

{{ run.sh }}

### Observation

The rule has identified six instances in the code file, where insecure encryption modes are used.

{{ output.txt }}

### Evaluation

The test fails since the output contains several instances of the ECB mode of AES:

- Line 36 using Cipher.getInstance("AES") defaults to ECB.
- Line 55 using Cipher.getInstance("AES/ECB/NoPadding");.
- Line 76 using Cipher.getInstance("AES/ECB/PKCS5Padding");.
- Line 95 using Cipher.getInstance("AES/ECB/ISO10126Padding");.
- Line 118 using Cipher.getInstance("DES/ECB/PKCS5Padding");.
- Line 141 using Cipher.getInstance("DESede/ECB/PKCS5Padding");.
133 changes: 133 additions & 0 deletions demos/android/MASVS-CRYPTO/MASTG_DEMO-0016/MastgTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package org.owasp.mastestapp

import android.content.Context
import java.security.Key
import javax.crypto.Cipher
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.DESKeySpec
import javax.crypto.spec.DESedeKeySpec
import javax.crypto.spec.SecretKeySpec
import android.util.Base64

class MastgTest(private val context: Context) {

// Vulnerable AES encryption
fun vulnerableAesEncryption(data: String): String {
try {
val key = "1234567890123456".toByteArray() // 16 bytes key for AES
val secretKeySpec = SecretKeySpec(key, "AES")

// Default mode for AES (ECB)
val cipher = Cipher.getInstance("AES")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)

val encryptedData = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT)
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}

// Vulnerable AES with ECB and NoPadding (manual padding applied)
fun vulnerableAesEcbNoPadding(data: String): String {
try {
val key = "1234567890123456".toByteArray()
val secretKeySpec = SecretKeySpec(key, "AES")

val cipher = Cipher.getInstance("AES/ECB/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)

// Ensure the data is padded to match the block size
val blockSize = 16
val paddingLength = blockSize - (data.length % blockSize)
val paddedData = data + "\u0000".repeat(paddingLength) // Null padding

val encryptedData = cipher.doFinal(paddedData.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT).trim()
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}

// Vulnerable AES with ECB and PKCS5Padding
fun vulnerableAesEcbPkcs5Padding(data: String): String {
try {
val key = "1234567890123456".toByteArray()
val secretKeySpec = SecretKeySpec(key, "AES")

val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)

val encryptedData = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT)
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}

// Vulnerable AES with ECB and ISO10126Padding
fun vulnerableAesEcbIso10126Padding(data: String): String {
try {
val key = "1234567890123456".toByteArray()
val secretKeySpec = SecretKeySpec(key, "AES")

val cipher = Cipher.getInstance("AES/ECB/ISO10126Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)

val encryptedData = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT)
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}

// Vulnerable DES with ECB and PKCS5Padding
fun vulnerableDesEcbPkcs5Padding(data: String): String {
try {
val keySpec = DESKeySpec("12345678".toByteArray())
val keyFactory = SecretKeyFactory.getInstance("DES")
val secretKey: Key = keyFactory.generateSecret(keySpec)

val cipher = Cipher.getInstance("DES/ECB/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey)

val encryptedData = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT)
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}

// Vulnerable 3DES with ECB and PKCS5Padding
fun vulnerable3DesEcbPkcs5Padding(data: String): String {
try {
val keySpec = DESedeKeySpec("123456789012345678901234".toByteArray())
val keyFactory = SecretKeyFactory.getInstance("DESede")
val secretKey: Key = keyFactory.generateSecret(keySpec)

val cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey)

val encryptedData = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(encryptedData, Base64.DEFAULT)
} catch (e: Exception) {
return "Encryption error: ${e.message}"
}
}

// Test and return results
fun mastgTest(): String {
val sensitiveString = "Hello from OWASP MASTG!"

val results = listOf(
"AES Default: ${vulnerableAesEncryption(sensitiveString)}",
"AES ECB NoPadding: ${vulnerableAesEcbNoPadding(sensitiveString)}",
"AES ECB PKCS5Padding: ${vulnerableAesEcbPkcs5Padding(sensitiveString)}",
"AES ECB ISO10126Padding: ${vulnerableAesEcbIso10126Padding(sensitiveString)}",
"DES ECB PKCS5Padding: ${vulnerableDesEcbPkcs5Padding(sensitiveString)}",
"3DES ECB PKCS5Padding: ${vulnerable3DesEcbPkcs5Padding(sensitiveString)}"
)

return results.joinToString("\n")
}
}
Loading

0 comments on commit 23d106c

Please # to comment.