2. What the conventional wisdom tells us
about cryptography
Cryptography is dangerous because you get no feedback when you mess it up
Never implement your own crypto – what does that really mean?
Most of the code using cryptography is not written/reviewed by
cryptographers or qualified architects.
Crypto built into products is oftentimes broken.
Broken crypto might be more dangerous than no crypto as it gives you a false
sense of security.
4. The crux of the problem
Many programmers think that they can just link to a crypto library and they're
done, but cryptography is hard to implement robustly if you don't understand
the finer aspects of it.
You can easily develop an insecure crypto scheme using only “secure” algo.
Longer keys don't always mean more security etc.
Penetration testers rarely scrutinize crypto as it is a complex and demanding
task.
Crypto libraries are too complex – since they were designed by and for
cryptographers.
5. Area of confusion
What level of knowledge is requred to deal with crypto as a programmer?
Do developers need to be cryptographers in order to use crypto correctly?
Do we even have a choice?
Rather then arguing who’s fault it is shouldn’t we work towards fixing this
issue?
6. The way out of it
1.train developers to use it securely
2.Use high level crypto libraries
7. What is this presentation about?
The goal of this presentation is to show the
disconnect between what is expected from
developers leveraging cryptography and the
reality.
It will show some of the most typical crypto
failures so that developers can learn from
them.
It will also emphasize the importance of
abstraction of crypto primitives to not allow
developers to screw things so easily.
8. What kind of crypto pitfalls will we cover?
In his essay „Security Pitfalls in Cryptography” (1998) Bruce Schneider divided cryptography
attacks into following categories:
- Attacks Against Cryptographic Designs
- Attacks Against Implementations
- Attacks Against Passwords
- Attacks Against Hardware
- Attacks Against Trust Models
- Attacks on the Users
- Attacks Against Failure Recovery
- Attacks Against the Cryptography
11. What went wrong?
The social networking website LinkedIn was hacked on 5 June 2012, and passwords for nearly
6.5 million user accounts were stolen by Russian cybercriminals
LinkedIn failed to use a salt when hashing the passwords
LinkedIn also stored the passwords using just SHA-1 algorithm
Due to these flaws attackers were able to unscramble the password hashes using standard
rainbow tables
13. What happened?
User passwords were cryptographically protected using bcrypt, an algorithm so slow and
computationally demanding it would literally take centuries to crack all of them.
However, apart of storing user passwords with bcrypt, security researches identified two
instances where passwords were stored using MD5 for “automatic login”
$loginkey = md5(strtolower($username).'::'.strtolower($password));
md5(lc($username).”::”.lc($pass).”:”.lc($email).”:73@^bhhs&#@&^@8@*$”).
14.
15. The right way to do it
Never store passwords in plaintext (obviously)
Never store hashed passwords without using a unique salt (ideally a random one sufficiently long)
Use a cryptographically secure & slow hash functions (PBKDF2, bcrypt, scrypt). Apply a sufficient number of iterations.
Slow hashing is desirable as it makes processing of a single password more expensive for the attacker
PBKDF2: good enough but can be optimized with GPU
bcrypt: less GPU friendly then PBKDF2 but vulnerable to brute-forcing using Field-Programmable Gate Arrays (FPGAs) with
relatively small SRAM
scrypt: requires not only exponential time but also exponential memory
however doesn’t have a cryptanalytic pedigree required to gain most cryptographers' trust
Do not allow users to use weak passwords. Even with the strongest crypto, weak passwords are easy to crack.
As soon as you receive a password, remove it from memory.
16. High level approach example
string password_hash ( string $password , integer $algo [, array $options ] )
password_hash() creates a new password hash using a strong one-way hashing algorithm.
Uses bcrypt or PASSWORD_DEFAULT (a constatnt which may change in time)
Options Cost and Salt are secure by default
http://php.net/manual/en/function.password-hash.php
17. Failure #2 Improper use of hash
functions
It’s 2015 and developers still use MD5
SHA- 1 has been considered insecure for long time, yet it still used widely.
Comparing hashes also causes problems – timing attacks
Using certain hash functions for what they are not might also cause issues e.g. length extension
attacks
18. Comparing Hashes
if ($hash1 === $hash2) {
//mac verification is OK echo "hashes are equal" }
else { //something bad happened }
For a given message, attempt to send it with a hash of all one
single character. Do this once for each ASCII char e.g. 'aaaa...',
'bbbb...' etc.
Measure the time each request takes to complete. Since string
equality takes a tiny bit longer to complete when the first char
matches, the message that takes the longest to return will
have the correct first character.
19. Length extension attacks
key = “secret attacker doesn’t know”
value =“send $100”
Signature = sha256(key + “:” + value)
Length extension attack allows us to append data and be able to compute a valid signature without
actually knowing the key.
value =“send $1000”
Signature = “valid signature”
https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-
attacks
20. The right way to do it
Don’t ever use insecure algo such as MD5 or SHA-1. Use SHA-2 instead (SHA-256, Sha-384, SHA -512)
For signed MAC use HMAC-SHA2
If you compare hashes, use only cryptographically secure functions e.g. :
.NET : RSACryptoServiceProvider.VerifyHash https://msdn.microsoft.com/en-
us/library/system.security.cryptography.rsacryptoserviceprovider.verifyhash(v=vs.110).aspx
21. Failure #3 Using encryption without
authentication
Encryption doesn’t automatically protect data against modification
Chosen cipher text attacks are a real threat
Bit flipping attacks
Padding oracle
24. Padding oracle
Frequently present in web applications
Occurs when a web service reveals whether there was a padding or integrity error when
decryption (can be also base on timing)
If you can feed in ciphertexts and somehow find out whether or not they decrypt to something
with valid padding or not, then you can decrypt ANY given ciphertext.
Typical scenario : Using AES in CBC mode where have a ciphertext encrypted by a web service.
POODLE
25. How to do it right?
Never underestimate the importance of message authenticity even in situation without an
obvious attack vector.
There is rarely a reason for not doing authentication checks when decrypting data
Prefer authenticated modes of operation e.g. GCM, OCB (patented)
If forced using AES with CBC use HMAC to ensure message authenticity
26. Failure #4 Reusing nonces and IVs
Nonces should be used only once – that’s what the word stands for
The purpose of their use is to avoid replay attacks
IVs should usually be non-predictable
Length of IVs is also important (WEP)
27. Attacks on WEP
WEP uses 24b IV
For RC4 security is important that the
same key is never used twice
For every 24b IV there is a 50% chance
that the same IV will repeat after
approximately 5000 packets
28. The right way to do it
Never reuse nonces
Do not use static IVs
Always use random, unpredictable IVs with sufficient length
29. Pitfall #5 Dealing randomness
A good source of true randomness is an integral part of most cryptosystems. Common mistakes
include:
Using no or limited randomness when required
Using sources of “randomness” which are actually not random at all
Leaking internal state of PRNG
30. Random Number Bug in Debian
MD_Update(&m,buf,j);
[ .. ]
MD_Update(&m,buf,j); /* purify complains */
Removing this code had the side effect of crippling the seeding process for the OpenSSL PRNG.
Instead of mixing in random data for the initial seed, the only "random" value that was used
was the current process ID.
31.
32. Modulo bias
int x;
int modulus = 4;
x= rand() % modulus; // random string 0-3
Assuming that rand() returns values (0,1,2,3,4,5)
Probability of 0: 33.33%
Probability of 1: 33.33%
Probability of 2: 16.66%
Probability of 3: 16.66%
33. Modulo bias #2
You will get modulo bias if max(rand()) + 1 is not evenly divisible by your modulus.
int excess = (RAND_MAX + 1) % modulus;
int limit = RAND_MAX - excess;
while (x = rand() > limit) {};
return x % modulus;
34. The right way to do it
.NET : https://msdn.microsoft.com/en-
us/library/system.security.cryptography.randomnumbergenerator
C++ (Windows): CryptGenRandom function in MS-CAPI https://msdn.microsoft.com/en-
us/library/windows/desktop/aa379942(v=vs.85).aspx
Linux: read from /dev/urandom
recommended reading: http://www.2uo.de/myths-about-urandom/
35. Failure #6 SSL/TLS Certificates
Using TLS in non-browser software is a challenging task
Using standard SSL/TLS libraries is not enough
Certificate validation is sometimes completely disabled
Certificate revocation check is oftentimes missing
Full chain check is sometimes not complete
Subject is sometimes not verified at all!
36.
37. The right way to do it
Implementing proper certificate validation is not a trivial task. It requires a deep understanding
of the protocol.
Don’t assume that using SSL/TLS libraries ensures proper certificate validation.
Don’t disable SSL for testing purposes, it may backfire.
Implement unit testing (especially negative one) to verify that certificate validation is
implemented properly.
To mitigate the risks of rogue certificates consider certificate pinning.
40. Failure #7 Insecure key provisioning
A very common mistake is to spend lots of time designing an impenetrable crypto scheme and
then not protecting keys properly
Keys are often generated in an insecure environment, stored on developers machines,
hardcoded in the source code etc.
People also don’t think through the scenarios when keys get leaked
41.
42. The right way to do it
Avoid using passwords as keys as they don’t have enough entropy and use truly random keys
instead.
If you have to use passwords as keys apply key derivation functions e.g. PBKDF2
Don’t reuse the same key on many devices.
Don’t reuse the same key for multiple purposes (encryption, authentication)
Generate keys in a secure environment
Store keys securely
Account for periodic key rotation and disaster recovery
Make a plan for creation, rotation and removal of encryption keys!
43. Takeaways
Never implement your own crypto primitives
Never leverage cryptography if you don’t understand it’s fundamentals
Learn the fundamentals!
Avoid using low level crypto libraries (OpenSSL, Bouncy Castle, Java JCE, PyCrypto) unless you
are a pro
Beware of compositional weaknesses. Consult person with advanced knowledge of
cryptography.
Use high level crypto libraries (KeyCzar, NaCL, libsodium )
44. Keyczar
Keyczar’s goal is to make it easier for application developers to safely use cryptography.
Keyczar defaults to safe algorithms, key lengths, and modes, and prevents developers from
inadvertently exposing key material. It uses a simple, extensible key versioning system that
allows developers to easily rotate and retire keys.
Java, Python, and C++ implementations
Key rotation and versioning
https://github.com/google/keyczar
http://jay.tuley.name/keyczar-dotnet/