Slide 1

Slide 1 text

Breaking User Passwords and Why You Should Zendcon Uncon October 2014

Slide 2

Slide 2 text

We help people get storage. Move in and move on.

Slide 3

Slide 3 text

Matt Land github.com/matt-land linkedin.com/in/matthewland speakerdeck.com/mattland/ https://joind.in/12551 CERTIFIED A R C H I T E CT 2

Slide 4

Slide 4 text

Breaking User Passwords Background Passwords are special Sorting vs Crypto When we fix our applications How we fix our applications Code examples

Slide 5

Slide 5 text

My organization is not immune

Slide 6

Slide 6 text

110 M 56 M 76 M 56 M 115 M Households 330 M People Most are compromised 150 M 50 M 1 M 50 M 45 M 2.5 M 1.5 M ? 130 M

Slide 7

Slide 7 text

What did we lose?

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Permanent Compromise Permanent Compromise Reissued Big Hassle Reissued Trivial Hassle Self Reissued Minor Hassle Never should have been saved (PCI) Its complicated…

Slide 10

Slide 10 text

Users are special • Passwords are a poor technology for humans. • Enforcing arbitrary rules on passwords makes them worse for both parties. • Compromise with a minimum length only. • Do not restrict the length or symbols. • Do not disable paste. • We cannot prevent passwords being used for multiple sites. Assume they will be.

Slide 11

Slide 11 text

Passwords are special • Was it compromised? • Has the most value to the user • May have the most value to an attacker • Users will continue using a compromised password even after it was exposed

Slide 12

Slide 12 text

• Was it compromised? • Has the most value to the user • May have the most value to an attacker • Users will continue using a compromised password after a breach Cryptographically Secure passwords are special !

Slide 13

Slide 13 text

Best Practices • Expensive in terms of cycles and energy (IE Not based on a sorting algorithms like md5 or sha) • Unique and variable salts per account • Asymmetric • /dev/random > /dev/urandom • Time based functions are the devil: uniqid() • Do not write your own crypto. There be dragons.

Slide 14

Slide 14 text

Arbitrary Rules Red: MMDDYY Green: YYDDMM Yellow: YYMMDD Pink: ended in 19XX Requiring capitals and numbers can make passwords worse. <+rest of word>

Slide 15

Slide 15 text

Slide 16

Slide 16 text

Hash vs Crypt Fast Slow Sorting methods are still great. For sorting! PHP’s array type MD5 TwoFish Uses a fast sorting method

Slide 17

Slide 17 text

The list of people qualified to write crypto is short. Do not write your own crypto. Use builtin crypt() function, or a vetted library like Zend/Auth/Bcrypt

Slide 18

Slide 18 text

Dangers of Writing Crypto Distribution graphs of three methods

Slide 19

Slide 19 text

Dangers of Writing Crypto Bad Really Bad Maybe OK? Poor node balance in a hash causes poor performance. Poor node balance in a crypt breaks security.

Slide 20

Slide 20 text

Great! I’ll try bcypt() at my next job!

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

If you can break your user’s passwords, you should break your user’s passwords.

Slide 25

Slide 25 text

• I could update my application to use better crypto • In a way that is transparent to my users • In a week

Slide 26

Slide 26 text

Vulnerability Testing select * from users where password in( md5(‘password’), md5(‘123456’), md5(‘jesus’), md5(‘football’), md5(‘ninja’), sha1(‘password’), sha1(‘123456’), sha1(‘jesus’), sha1(‘football’), sha1(‘ninja’) ); select * from users where password in ( md5(concat(‘123456’, salt)), sha1(concat(‘123456’, salt)), sha2(concat(‘123456’, salt)), password(concat(‘123456’, salt)) ); MySQL hash methods http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html

Slide 27

Slide 27 text

The Plan 12% 15% 15% 59% • Dictionary Attack • Rainbow Cloud Attack • Users Authenticating • Unachievable All User Passwords

Slide 28

Slide 28 text

Implementation • Build a replacement auth service • The service authenticator would support two tiers • Refactor all entry points to use the service authenticator • All new users use the new method • All user authentications auto-upgrade to the new method • Build a dedicated API for a challenge and upgrade • Start cracking codes

Slide 29

Slide 29 text

Replacement Auth Service public static function loadByLogin($emailAddress, $password) { $user = self::load( Restriction::equal('email', $emailAddress) )->uniqueResult(); if (! $user || ! $user->checkRawPassword($password)) { return false; } return $user; } public function checkRawPassword($password) { if ($this->getBcryptPasswordFlag()) { $bcrypt = new Bcrypt(); return $bcrypt->verify($password, $this->getPassword()); } if (some_hash_method($password) !== $this->getPassword()) { return false;} $this->upgradePassword($password); return true; } public static function loadByLogin($emailAddress, $password) { return AccountMgmtUser::select( Restriction::and_( Restriction::equal('email', $email), Restriction::equal('password', some_hash_method($password)) ))->uniqueResult(); }

Slide 30

Slide 30 text

Bad Code if(sha1($oldPassword) != $this->getLoggedUser()->getPassword()) { Not owned by the model, not DRY if($row->password != sha1(sha1($salt).sha1($pwd))){ Wonky, 3x slower, and no stronger than sha1, possibly weaker else if (sha1($password) == $this->_accounts[$username][1]) (???) return $this->_sha1($password) == $this->_accounts[$username]; Matching against the user name? $plain_sha1 = sha1($password); $password = '" . $this->_escape($plain_sha1) . "' No salt, escape before transform return sha1(uniqid('', true) . $request->getUrl()); In a password reset url, this was a time based function

Slide 31

Slide 31 text

Refactoring Remove dozens of implementations across the code and pushed back into the model. (Not DRY) Added the bcrypt boolean field to db. Millions of rows * 2 bytes = not much Added upgradeBcryptPassword method to login. Users now help with the upgrade. Wrote unit tests. Pushed it over the wall.

Slide 32

Slide 32 text

Dedicated upgrades route • Goes through the application and it’s models • No more sql methods used to bypass authentication • POST url with email, password, and api key • The cracking machine lives in a separate cloud

Slide 33

Slide 33 text

Cracking with Wordlists • Crackstation is a superset of Gawker, Adobe, etc. • Actual passwords from users • Generate a dict using your application’s hash and salts • Compare each hash against your users table • Majority of passwords fell immediately, 63% • Rerun with the expanded list gained another 4%

Slide 34

Slide 34 text

Cracking with Tables • Rainbow tables from freerainbowtables.com • SHA, MD5, NTLM • Hashes semi computed, but huge (4TB EC2) • Compile rcrack_rt with threads = cores • 4.5 months, run against only the remaining 33% • Called them in to the production server using curl request. Cracked passwords were never on the production box.

Slide 35

Slide 35 text

• Move an existing application to modern method • All the users • Transparent to users • In a week

Slide 36

Slide 36 text

Summary • Cannot reach 100%, yet • If we are breached, most of the passwords are safe • My cpu power is less than a botnet has available • All the low hanging fruit is gone • Users password will be protected

Slide 37

Slide 37 text

In Your Project • Saltless md5, sha1, ntlm • Sitewide salt + md5, sha1, ntlm • one magnitude more difficult • Correctly salted accounts • AutoUpgrading

Slide 38

Slide 38 text

Sample Code Dictionary Wordlist Cracking ZF2 Dual Tiered Adapter

Slide 39

Slide 39 text

Errata • The race state: very very tiny percent of pw upgrades fail because the user changed passwords during the window of dump, process, push, 0.2% • Swapping EC2 machines took forever because of the rotational storage attached, but didn’t matter to the run • EC2 is slow, the dedicated GPU configs help

Slide 40

Slide 40 text

Matt Land CERTIFIED A R C H I T E CT 2 github.com/matt-land linkedin.com/in/matthewland speakerdeck.com/mattland/ https://joind.in/12551