Crypto failures every developer should avoid

47
Crypto failures every developer should avoid FILIP ŠEBESTA - OWASP CZECH CHAPTER MEETING - PRAGUE DECEMBER 7 2015

Transcript of Crypto failures every developer should avoid

Page 1: Crypto failures every developer should avoid

Crypto failures every developer should avoidFILIP ŠEBESTA - OWASP CZECH CHAPTER MEETING - PRAGUE DECEMBER 7 2015

Page 2: Crypto failures every developer should avoid

What the conventional wisdom tells us about cryptographyCryptography is dangerous because you get no feedback when you mess it upNever 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.

Page 3: Crypto failures every developer should avoid

Veracode’s State of Software Security (June 2015)

Page 4: Crypto failures every developer should avoid

The crux of the problemMany 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.

Page 5: Crypto failures every developer should avoid

Area of confusionWhat 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?

Page 6: Crypto failures every developer should avoid

The way out of it1.train developers to use it securely2.Use high level crypto libraries

Page 7: Crypto failures every developer should avoid

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.

Page 8: Crypto failures every developer should avoid

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

Page 9: Crypto failures every developer should avoid

Failure #1 – Improper password storage

Page 10: Crypto failures every developer should avoid

LinkedIn leaked out approximately 6.5 million passwords in 2012.

Page 11: Crypto failures every developer should avoid

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

Page 12: Crypto failures every developer should avoid

Ashley Madison Leak

Page 13: Crypto failures every developer should avoid

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@*$”).

Page 14: Crypto failures every developer should avoid
Page 15: Crypto failures every developer should avoid

The right way to do itNever 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.

Page 16: Crypto failures every developer should avoid

High level approach examplestring 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

Page 17: Crypto failures every developer should avoid

Failure #2 Improper use of hash functionsIt’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

Page 18: Crypto failures every developer should avoid

Comparing Hashesif ($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.

Page 19: Crypto failures every developer should avoid

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

Page 20: Crypto failures every developer should avoid

The right way to do itDon’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

Page 21: Crypto failures every developer should avoid

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

Page 22: Crypto failures every developer should avoid
Page 23: Crypto failures every developer should avoid

Bit flipping

Page 24: Crypto failures every developer should avoid

Padding oracleFrequently 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

Page 25: Crypto failures every developer should avoid

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

Page 26: Crypto failures every developer should avoid

Failure #4 Reusing nonces and IVsNonces 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)

Page 27: Crypto failures every developer should avoid

Attacks on WEPWEP 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

Page 28: Crypto failures every developer should avoid

The right way to do itNever reuse nonces

Do not use static IVs

Always use random, unpredictable IVs with sufficient length

Page 29: Crypto failures every developer should avoid

Pitfall #5 Dealing randomnessA 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

Page 30: Crypto failures every developer should avoid

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.

Page 31: Crypto failures every developer should avoid
Page 32: Crypto failures every developer should avoid

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%

Page 33: Crypto failures every developer should avoid

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;

Page 34: Crypto failures every developer should avoid

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/

Page 35: Crypto failures every developer should avoid

Failure #6 SSL/TLS CertificatesUsing 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!

Page 36: Crypto failures every developer should avoid
Page 37: Crypto failures every developer should avoid

The right way to do itImplementing 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.

Page 38: Crypto failures every developer should avoid

www.badssl.com

Page 39: Crypto failures every developer should avoid
Page 40: Crypto failures every developer should avoid

Failure #7 Insecure key provisioningA 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

Page 41: Crypto failures every developer should avoid
Page 42: Crypto failures every developer should avoid

The right way to do itAvoid 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!

Page 43: Crypto failures every developer should avoid

TakeawaysNever 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 )

Page 44: Crypto failures every developer should avoid

KeyczarKeyczar’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/

Page 45: Crypto failures every developer should avoid

Example: encryption Crypter crypter = new Crypter("/path/to/your/keys");

String ciphertext = crypter.encrypt("Secret message");

Page 46: Crypto failures every developer should avoid

Recommended resourcesMatasano crypto challenges: http://cryptopals.com/ Standford Cryptography https://www.coursera.org/course/crypto Standford Cryptography II https://www.coursera.org/course/crypto2 Schneier on Security https://www.schneier.com

Page 47: Crypto failures every developer should avoid