Skip to content

Commit

Permalink
update DEMO-0011 to be about RSA key size
Browse files Browse the repository at this point in the history
  • Loading branch information
cpholguera committed Aug 12, 2024
1 parent 1fd3157 commit b3b9f2d
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 135 deletions.
71 changes: 9 additions & 62 deletions demos/ios/MASVS-CRYPTO/MASTG-DEMO-0011/MASTG-DEMO-0011.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
platform: ios
title: Uses of Insecure Algorithms in CCCrypt with r2
title: Uses of Weak Key Size in CCCrypt with r2
code: [swift]
id: MASTG-DEMO-0011
test: MASTG-TEST-0209
Expand All @@ -12,80 +12,27 @@ test: MASTG-TEST-0209

### Steps

When calling [`SecKeyCreateRandomKey`](https://developer.apple.com/documentation/security/1823694-seckeycreaterandomkey) the key size is specified in the [`kSecAttrKeySizeInBits`](https://developer.apple.com/documentation/security/ksecattrkeysizeinbits) attribute within the `parameters` dictionary. See [Key Generation Attributes](https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/key_generation_attributes) for details.

1. Unzip the app package and locate the main binary file (@MASTG-TECH-0058), which in this case is `./Payload/MASTestApp.app/MASTestApp`.
2. Open the app binary with @MASTG-TOOL-0073 with the `-i` option to run this script.

{{ cccrypt.r2 }}
{{ security_keysize.r2 }}

{{ run.sh }}

### Observation

The output contains the disassembled code of the function using `CCCrypt`.
The output contains the disassembled code of the function using `SecKeyCreateRandomKey`.

{{ output.txt }}

### Evaluation

Inspect the disassembled code to identify the use of insecure algorithms.

In [CommonCryptor.h](https://opensource.apple.com/source/CommonCrypto/CommonCrypto-36064/CommonCrypto/CommonCryptor.h ) you can find the definition of the `CCCrypt` function:

```c
CCCryptorStatus CCCrypt(
CCOperation op, /* kCCEncrypt, etc. */
CCAlgorithm alg, /* kCCAlgorithmAES128, etc. */
CCOptions options, /* kCCOptionPKCS7Padding, etc. */
const void *key,
size_t keyLength,
const void *iv, /* optional initialization vector */
const void *dataIn, /* optional per op and alg */
size_t dataInLength,
void *dataOut, /* data RETURNED here */
size_t dataOutAvailable,
size_t *dataOutMoved);
```
This function is pretty big so we just included the relevant part of the code that's right before the call to `SecKeyCreateRandomKey`. Note that we can see attributes being set in the `parameters` dictionary such as `kSecAttrKeySizeInBits` as `reloc.kSecAttrKeySizeInBits`. In radare2, this means that the symbol `kSecAttrKeySizeInBits` is not directly referenced by an absolute address but rather through a relocation entry. This entry will be resolved by the dynamic linker at runtime to the actual address where `kSecAttrKeySizeInBits` is located in memory.

There you will also find the `alg` and the `op`:
```c
/*!
@enum CCAlgorithm
@abstract Encryption algorithms implemented by this module.
@constant kCCAlgorithmAES128 Advanced Encryption Standard, 128-bit block
@constant kCCAlgorithmDES Data Encryption Standard
@constant kCCAlgorithm3DES Triple-DES, three key, EDE configuration
@constant kCCAlgorithmCAST CAST
@constant kCCAlgorithmRC4 RC4 stream cipher
*/
enum {
kCCAlgorithmAES128 = 0,
kCCAlgorithmDES,
kCCAlgorithm3DES,
kCCAlgorithmCAST,
kCCAlgorithmRC4,
kCCAlgorithmRC2
};
typedef uint32_t CCAlgorithm;
/*!
@enum CCOperation
@abstract Operations that an CCCryptor can perform.
@constant kCCEncrypt Symmetric encryption.
@constant kCCDecrypt Symmetric decryption.
*/
enum {
kCCEncrypt = 0,
kCCDecrypt,
};
```
### Evaluation

With this information we can now inspect the disassembled code and we'll see that the 3DES algorithm can be found by its numeric value `2` in the second argument of the `CCCrypt` function (`w1`):
In the output we can see how the `kSecAttrKeySizeInBits` attribute is set to `1024` bits (0x400 in hexadecimal) using the `x8` register. This is later used to call `SecKeyCreateRandomKey`.

{{ evaluation.txt }}

This call to `CCCrypt` is encrypting data using the 3DES algorithm with a padding option of PKCS7, no initialization vector, and a key of 24 bytes.

In this case, the algorithm used is `kCCAlgorithm3DES`, which is considered insecure and should be replaced with a more secure algorithm such as `kCCAlgorithmAES128`.
The test fails because the key size is set to `1024` bits, which is considered weak for RSA encryption. The key size should be increased to `2048` bits or higher to provide adequate security against modern cryptographic attacks.
111 changes: 82 additions & 29 deletions demos/ios/MASVS-CRYPTO/MASTG-DEMO-0011/MastgTest.swift
Original file line number Diff line number Diff line change
@@ -1,37 +1,90 @@
import SwiftUI
import CommonCrypto
import Foundation
import Security

struct MastgTest {
static func mastgTest(completion: @escaping (String) -> Void) {
let key = "0123456789abcdef01234567" // 24-byte key for 3DES
let data = "This is a sample text".data(using: .utf8)!

// Create a buffer for encrypted data
var encryptedBytes = [UInt8](repeating: 0, count: data.count + kCCBlockSize3DES)
var numBytesEncrypted: size_t = 0

let cryptStatus = data.withUnsafeBytes { dataBytes in
key.withCString { keyBytes in
CCCrypt(
CCOperation(kCCEncrypt), // Encrypt
CCAlgorithm(kCCAlgorithm3DES), // 3DES Algorithm
CCOptions(kCCOptionPKCS7Padding), // PKCS7 Padding
keyBytes, kCCKeySize3DES, // Key and key length
nil, // Initialization Vector (optional)
dataBytes.baseAddress, data.count, // Input data
&encryptedBytes, encryptedBytes.count, // Output data
&numBytesEncrypted // Number of bytes encrypted
)
}

// Step 1: Generate an RSA key pair with a 1024-bit key size
let tag = "org.owasp.mas.rsa-1014".data(using: .utf8)!
let keyAttributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: 1024, // Using 1024-bit RSA key
kSecPrivateKeyAttrs as String:
[kSecAttrIsPermanent as String: true, // to store it in the Keychain
kSecAttrApplicationTag as String: tag] // to find and retrieve it from the Keychain later
]

var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(keyAttributes as CFDictionary, &error) else {
completion("Failed to generate private key: \(String(describing: error))")
return
}

guard let publicKey = SecKeyCopyPublicKey(privateKey) else {
completion("Failed to generate public key")
return
}

// Convert the private key to data (DER format)
guard let privateKeyData = SecKeyCopyExternalRepresentation(privateKey, &error) as Data? else {
completion("Failed to extract private key: \(String(describing: error))")
return
}

if cryptStatus == kCCSuccess {
let encryptedData = Data(bytes: encryptedBytes, count: numBytesEncrypted)
let encryptedHex = encryptedData.map { String(format: "%02hhx", $0) }.joined()
let value = "Original:\n\n \(String(data: data, encoding: .utf8)!)\n\nEncrypted (Hex):\n \(encryptedHex)"
completion(value)
} else {
completion("Encryption failed with status: \(cryptStatus)")
// Encode the private key for display
//let privateKeyBase64 = privateKeyData.base64EncodedString()
let privateKeyHex = privateKeyData.map { String(format: "%02hhx", $0) }.joined()

// Convert the public key to data (DER format)
guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, &error) as Data? else {
completion("Failed to extract public key: \(String(describing: error))")
return
}

// Encode the public key for display
// let publicKeyBase64 = publicKeyData.base64EncodedString()
let publicKeyHex = publicKeyData.map { String(format: "%02hhx", $0) }.joined()

// Data to sign
let dataToSign = "This is a sample text".data(using: .utf8)!

// Step 2: Sign the data with the private key
guard let signature = SecKeyCreateSignature(
privateKey,
SecKeyAlgorithm.rsaSignatureMessagePKCS1v15SHA256,
dataToSign as CFData,
&error
) else {
completion("Signing failed: \(String(describing: error))")
return
}

// Convert signature to hex string for display
let signatureHex = (signature as Data).map { String(format: "%02hhx", $0) }.joined()

// Step 3: Verify the signature with the public key
let verificationStatus = SecKeyVerifySignature(
publicKey,
SecKeyAlgorithm.rsaSignatureMessagePKCS1v15SHA256,
dataToSign as CFData,
signature as CFData,
&error
)

let verificationResult = verificationStatus ? "Signature is valid." : "Signature is invalid."

let value = """
Original: \(String(data: dataToSign, encoding: .utf8)!)
Private Key (Hex): \(privateKeyHex)
Public Key (Hex): \(publicKeyHex)
Signature (Hex): \(signatureHex)
Verification: \(verificationResult)
"""

completion(value)
}
}
18 changes: 9 additions & 9 deletions demos/ios/MASVS-CRYPTO/MASTG-DEMO-0011/evaluation.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
0x1000040c0 00008052 mov w0, 0 -> kCCEncrypt (0 for encryption)
0x1000040c4 41008052 mov w1, 2 -> kCCAlgorithm3DES (2 for 3DES)
0x1000040c8 22008052 mov w2, 1 -> kCCOptionPKCS7Padding (1 for PKCS7 padding)
0x1000040cc e30317aa mov x3, x23 -> key (pointer to the encryption key)
0x1000040d0 04038052 mov w4, 0x18 -> keyLength (0x18 or 24 bytes for 3DES)
0x1000040d4 050080d2 mov x5, 0 -> iv (0 or NULL, implying no initialization vector)
0x1000040d8 e60316aa mov x6, x22 -> dataIn (pointer to the input data to be encrypted)
0x1000040dc e70319aa mov x7, x25 -> dataOut (pointer to the output buffer where encrypted data will be stored)
0x1000040e0 790d0094 bl sym.imp.CCCrypt -> Call to CCCrypt function
0x10000484c 080942f9 ldr x8, reloc.kSecAttrKeySizeInBits ; 0x10000c410 -> Load the address of kSecAttrKeySizeInBits into x8
0x100004850 000140f9 ldr x0, [x8]
0x100004854 e30b0094 bl fcn.1000077e0
0x100004858 800605a9 stp x0, x1, [x20, 0x50]
0x10000485c 48000090 adrp x8, reloc.Foundation.__DataStorage._bytes.allocator__UnsafeMutableRawPointer______ ; 0x10000c000
0x100004860 089d41f9 ldr x8, reloc.Swift.Int ; 0x10000c338
0x100004864 883e00f9 str x8, [x20, 0x78]
0x100004868 08808052 mov w8, 0x400 -> Move 0x400 (1024 in decimal) into w8, the lower 32 bits of x8
0x10000486c 883200f9 str x8, [x20, 0x60] -> Store the final value (1024-bit key size) into memory
Loading

0 comments on commit b3b9f2d

Please sign in to comment.