password storage and attacking in php
DESCRIPTION
These slides are from a talk that I did at PHP Benelux 2013 ( http://conference.phpbenelux.eu/2013/ ). In this talk, I go over the progression of password storage techniques, and weaknesses of each method. Eventually, we build up to the final secure implementations, and the current methods used to attack them.TRANSCRIPT
Password Storage(And Attacking)
In PHP
Anthony Ferrara
Github URL
Follow Along:
github.com/ircmaxell/password-bad-web-app
A "Bad Web App" - Has Known Vulnerabilities - Only Use For Education!!! - Requires only Apache + PHP - Has Composer Dependencies
Let's StartFrom The Beginning
Plain-Text Storagegit checkout plaintext
Stores passwords in Plain-Text
What's wrong with this picture?
Plain-Text Storage
What happens if we have a SQL-Injection Vulnerability?
localhost/sqli
Simulates:
?offset=0'+UNION+SELECT+*+FROM+users
Plain-Text Storage
Problem!
Any attack vector results in leakage of ALL credentials!
We Can Do Better
MD5git checkout md5
Uses the MD5 Cryptographic Hash function.
md5($password)
hash('md5', $password)
Wait,What Is A Hash?
What's A Cryptographic Hash?
Like a fingerprint.
One-way. - Easy and efficient to compute - Very inefficient to reverse - (Practically impossible) - Very hard to create collision - (new input with same output)
MD5
What's the problem now?
SQL-Injection still gives us hash
But the hash is one-way, how can we attack it?
Enter:Lookup Tables
Lookup Table
Google is a great example
Maps hash to password directly
Database Table:hash | password--------------+-----------"5f4dcc3b..." | "password""acbd18db..." | "foo"
Lookup Table
Lookups are CPU efficient.
Require a LOT of storage space - (Very space inefficient)
All passwords <= 7 chars (95^7, 70 Trillion)Requires 1.5 PetaBytes - In Most Optimal Storage Format
We Can Do Better
Rainbow Table
Seed
Hash
Reduce
Hash
Rainbow Table
Seed
Hash
Reduce
Hash
a4fef...
Reduce
NewPassword
Rainbow Table
Seed 1 Hash Reduce Hash Reduce Hash Reduce Hash
Seed 2 Hash Reduce Hash Reduce Hash Reduce Hash
Seed 3 Hash Reduce Hash Reduce Hash Reduce Hash
Seed 4 Hash Reduce Hash Reduce Hash Reduce Hash
Seed 5 Hash Reduce Hash Reduce Hash Reduce Hash
Seed 6 Hash Reduce Hash Reduce Hash Reduce Hash
Rainbow Table
Time/Space Tradeoff - Slower than a Lookup Table - Uses Much less storage
Most (99.9%) passwords <= 7 charsRequires only 64 GB - Chain length of 71,000
Defense!
Salted MD5git checkout salted-md5
Uses the MD5 Cryptographic Hash function.But adds a random salt UNIQUE per user.
md5($salt . $password)
hash('md5', $salt . $password)
Salts
Must be unique! - Per Hash - Globally
Should be random - Strong!!! - Reasonably long (at least 64 bits)
Salted MD5
What's the problem now?
SQL-Injection still gives us hash - And the salt
But the salt defeats rainbow tables...
Can Anyone See The Problem?
What's A Cryptographic Hash?
Like a fingerprint.
One-way. - Easy and efficient to compute - Very inefficient to reverse - (Practically impossible) - Very hard to create collision - (new input with same output)
What's A Cryptographic Hash?
Like a fingerprint.
One-way.
- Easy and efficient to compute - Very inefficient to reverse - (Practically impossible) - Very hard to create collision - (new input with same output)
Hash FunctionsAre Made To Be
FAST
Brute Forcing
Several Tools Available - John The Ripper - OCIHashCat
A Lot Faster Than You May Think
Brute Forcing
Multiple Ways To Attack - Mask Based (permutations) - Dictionary Based - Combinator Based - Combinations of dictionary words - Fingerprint Based - Combinators applied with permutations - Rule Based - Takes input password and transforms it
Brute ForcingSalted MD5
2012 Macbook Pro: - md5: 33 million per second - sha256: 20 million per second
Mask Attack:6 char passwords: 5 hours7 char passwords: 22 daysEntire English Language: 1.8 seconds"LEET" Permutations: 1 hour
We Can Do Better
Brute ForcingSalted MD5
25 GPU Cluster - md5: 180 Billion per second - < $50,000
6 char passwords: 4 seconds7 char passwords: 6 minutes8 char passwords: 10 hoursEntire English Language:"LEET" Permutations:
Brute ForcingSalted MD5
25 GPU Cluster - md5: 180 Billion per second - < $50,000
6 char passwords: 4 seconds7 char passwords: 6 minutes8 char passwords: 10 hoursEntire English Language: yeah..."LEET" Permutations: 0.7 seconds
But Wait,I Thought MD5 Was Broken?
MD5 IS Broken!
But No Other Primitive Hash Is Not!!!
sha1≈ md5 sha256 ≈ md5sha512 ≈ md5whirlpool ≈ md5
ALL raw primitive hashes are broken for password storage.
So, How Can We Combat Such
Hardware?
Iterated MD5git checkout iterated-md5
Uses the MD5 Cryptographic Hash function.But adds a random salt UNIQUE per user.And iterates a lot of times
do { $h = md5($h . $salt . $password)} while($i++ < 1000);
We're Intentionally
Slowing It Down
Brute ForcingIterated MD5
25 GPU Cluster - md5: 70 million per second
6 char passwords: 17 minutes7 char passwords: 1 day8 char passwords: 124 days
Entire English Language: 0.8 seconds
We Can Do Better
PBKDF2git checkout pbkdf2
Uses the standard PBKDF2 algo - With SHA512 primitive
Slower, and harder to use on GPU
pbkdf2($pass, $salt, 10000, 40)
Brute ForcingPBKDF2
25 GPU Cluster - PBKDF2(sha512): 300,000 per second
6 char passwords: 28 days7 char passwords: 7 years8 char passwords: 700 years
Entire English Language: 3 minutes
We Can StillDo Better
BCryptgit checkout bcrypt
Uses the standard BCrypt algo - based on Blowfish cipher
Same execution time,Much harder to run on GPU
crypt $2a$
Brute ForcingBCrypt
25 GPU Cluster - BCrypt: 70,000 per second
6 char passwords: 120 days7 char passwords: 31 years8 char passwords: 3000 years
Entire English Language: 14 minutes
A Note On Cost
BCrypt accepts a "cost" parameter
Must be tuned per server! - Target about 0.25 to 0.5 second runtime - Cost of 10 is a good baseline - Cost of 11 or 12 is better - If you have decent hardware.
PHP 5.5 Password Hashing APIgit checkout password-compat
A thin wrapper over crypt() - Simplifies implmentation - Strong random salt generation - Can specify cost as int option
password_hash($pass, $algo, $opts)password_verify($pass, $hash)
github.com/ircmaxell/password_compat
We Can DoEven Better!
Let's Encrypt Instead!
Encrypted BCryptgit checkout bcrypt-with-encryption
Hash with BCrypt,Then encrypt result with AES-128.
Requires key storage for the app. - Not trivial
Use only if needed! - BCrypt alone is typically sufficient
Brute ForcingEncrypted BCrypt
Attack requires low level server compromise! - SQL Injection is not enough!
localhost/codeinject - Simulates code injection that reads source
Any low level compromiseIs No Worse than raw BCrypt - BCrypt is the baseline.
The Future
The Future
scrypt - Sequential Memory Hard - Uses a LOT of memory (32mb / hash) - Harder to brute-force than bcrypt
But it's VERY new - In cryptography terms at least - Not proven enough for use (yet)
The Future
Password Hashing Competition - Currently being setup - Aims to pick "standard" password hashing algorithm - A community effort
The Future
Brute Forcing Word Lists - Complex combinations of words - "horse correct battery staple"
Brute Forcing Grammar - "I don't want no cookies"
Brute Forcing Structures - URLs, Email Addresses, URLs, etc
Anthony Ferrarajoind.in/7792@ircmaxell
[email protected]/ircmaxell