Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Breaking User Passwords, extended

973e0861866767b3940a6dbb5aac3642?s=47 Matt Land
October 29, 2014

Breaking User Passwords, extended

This version of the talk was given at Zendcon uncon 2014. This version is more focused on PHP instead of Python

973e0861866767b3940a6dbb5aac3642?s=128

Matt Land

October 29, 2014
Tweet

More Decks by Matt Land

Other Decks in Technology

Transcript

  1. Breaking User Passwords and Why You Should Zendcon Uncon October

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

  3. 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
  4. Breaking User Passwords Background Passwords are special Sorting vs Crypto

    When we fix our applications How we fix our applications Code examples
  5. My organization is not immune

  6. 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
  7. What did we lose?

  8. None
  9. Permanent Compromise Permanent Compromise Reissued Big Hassle Reissued Trivial Hassle

    Self Reissued Minor Hassle Never should have been saved (PCI) Its complicated…
  10. 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.
  11. 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
  12. • 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 !
  13. 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.
  14. Arbitrary Rules Red: MMDDYY Green: YYDDMM Yellow: YYMMDD Pink: ended

    in 19XX Requiring capitals and numbers can make passwords worse. <Capital><+rest of word><number, usually 1>
  15. <I><love><male-name><number> <month in num><day in num><year after 1980 in num>

  16. Hash vs Crypt Fast Slow Sorting methods are still great.

    For sorting! PHP’s array type MD5 TwoFish Uses a fast sorting method
  17. 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
  18. Dangers of Writing Crypto Distribution graphs of three methods

  19. 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.
  20. Great! I’ll try bcypt() at my next job!

  21. None
  22. None
  23. None
  24. If you can break your user’s passwords, you should break

    your user’s passwords.
  25. • I could update my application to use better crypto

    • In a way that is transparent to my users • In a week
  26. 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
  27. The Plan 12% 15% 15% 59% • Dictionary Attack •

    Rainbow Cloud Attack • Users Authenticating • Unachievable All User Passwords
  28. 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
  29. 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(); }
  30. 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
  31. 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.
  32. 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
  33. 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%
  34. 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.
  35. • Move an existing application to modern method • All

    the users • Transparent to users • In a week
  36. 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
  37. In Your Project • Saltless md5, sha1, ntlm • Sitewide

    salt + md5, sha1, ntlm • one magnitude more difficult • Correctly salted accounts • AutoUpgrading
  38. Sample Code Dictionary Wordlist Cracking ZF2 Dual Tiered Adapter

  39. 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
  40. 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