Skip to content

Swift: detect the use of static initialization vectors #11084

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 10, 2022

Conversation

karimhamdanali
Copy link
Contributor

Using a static initialization vector (IV) for encryption is not secure. To maximize encryption and prevent dictionary attacks, IVs should rather be unique and unpredictable (e.g., randomly generated).

The rule currently supports all ciphers that the CryptoSwift API provides, but we can always extend it further if more APIs are added.

I'd appreciate a review of the query itself, the accompanying tests, and the associated documentation.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 2, 2022

QHelp previews:

swift/ql/src/queries/Security/CWE-1204/StaticInitializationVector.qhelp

Static initialization vector for encryption

When a cipher is used in certain modes (such as CBC or GCM), it requires an initialization vector (IV). Under the same secret key, IVs should be unique and ideally unpredictable. If the same IV is used with the same secret key, then the same plaintext results in the same ciphertext. This behavior may enable an attacker to learn if the same data pieces are transferred or stored, or help the attacker run a dictionary attack.

In particular, if the IV is hardcoded or constant, an attacker may just look up potential keys in a dictionary, then concatenate those with the hardcoded or constant IV rather than trying to discover the entire encryption key.

Recommendation

Use a randomly generated IV.

Example

The following example shows a few cases of instantiating a cipher with various encryption keys. In the 'BAD' cases, the IV is hardcoded or constant, making the encrypted data vulnerable to recovery. In the 'GOOD' cases, the IV is randomly generated and not hardcoded, which protects the encrypted data against recovery.


func encrypt(padding : Padding) {
	// ...

	// BAD: Using static IVs for encryption
	let iv: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05]
	let ivString = "this is a constant string"
	let key = getRandomKey()
	_ = try AES(key: key, iv: ivString)
	_ = try CBC(iv: iv)

	// GOOD: Using randomly generated IVs for encryption
	let iv = (0..<10).map({ _ in UInt8.random(in: 0...UInt8.max) })
	let ivString = String(cString: iv)
	let key = getRandomKey())
	_ = try AES(key: key, iv: ivString)
	_ = try CBC(iv: iv)

	// ...
}

References

Copy link
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor points, otherwise docs, query and tests look great to me!

@karimhamdanali
Copy link
Contributor Author

@geoffw0 I think I've addressed all comments here. Ready for docs review?

@geoffw0
Copy link
Contributor

geoffw0 commented Nov 8, 2022

Yep, ready for docs review. 👍

@geoffw0 geoffw0 added the ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. label Nov 8, 2022
@mchammer01 mchammer01 self-requested a review November 10, 2022 11:53
mchammer01
mchammer01 previously approved these changes Nov 10, 2022
Copy link
Contributor

@mchammer01 mchammer01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karimhamdanali - this looks good from a Docs perspective ✨
I have left a couple of minor comments for your consideration.

@@ -0,0 +1,73 @@
/**
* @name Static initialization vector for encryption
* @description Using a static initialization vector (IV) for encryption is not secure. To maximize encryption and prevent dictionary attacks, IVs should rather be unique and unpredictable.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather doesn't really add much, and perhaps we shouldn't use the passive voice.
Feel free to ignore if you don't agree (you could just remove rather if you prefer to keep the current phrasing)

Suggested change
* @description Using a static initialization vector (IV) for encryption is not secure. To maximize encryption and prevent dictionary attacks, IVs should rather be unique and unpredictable.
* @description Using a static initialization vector (IV) for encryption is not secure. To maximize encryption and prevent dictionary attacks, go for unique and unpredictable IVs.

Copy link
Contributor Author

@karimhamdanali karimhamdanali Nov 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I've changed that by just removing rather.


<overview>
<p>When a cipher is used in certain modes (such as CBC or GCM), it requires an initialization vector (IV). Under the same secret key, IVs should be unique and ideally unpredictable. If the same IV is used with the same secret key, then the same plaintext results in the same ciphertext. This behavior may enable an attacker to learn if the same data pieces are transferred or stored, or help the attacker run a dictionary attack.</p>
<p>In particular, if the IV is hardcoded or constant, an attacker may just lookup potential keys in a dictionary, then concatenate those with the hardcoded or constant IV rather than trying to discover the entire encryption key.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lookup is a noun, to look up is the verb, to I'd be tempted to use an attacker may just look up
However, I am not familiar with this particular use (this may be widely used in the developer world) so feel free to ignore this comment if you don't agree.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I've changed that to the suggested wording.

@karimhamdanali
Copy link
Contributor Author

@mchammer01 thanks again for reviewing this. Since I didn't approve one of your comments (the one where I changed the phrasing slightly), I couldn't approve this PR for merging. Could you please re-approve this PR so that I can get it merged 😅?

Copy link
Contributor

@mchammer01 mchammer01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :shipit:

@karimhamdanali karimhamdanali merged commit e18b2cf into github:main Nov 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. Swift
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants