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

Breaking User Passwords -- and why you should

Matt Land
October 05, 2014

Breaking User Passwords -- and why you should

How can we fix ‘broken’ password hashing in our applications? Using the cloud and brute force, applications can be repaired. From code audit to account upgrade, techniques for reversing user hashes will be discussed, and well as success rates, costs, and choosing appropriate security frameworks. Finally, the appropriate applications for sorting methods will be discussed.

Matt Land

October 05, 2014
Tweet

More Decks by Matt Land

Other Decks in Technology

Transcript

  1. Breaking User
    Passwords
    and Why You Should

    View Slide

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

    View Slide

  3. Matt Land
    github.com/matt-land
    linkedin.com/in/matthewland

    View Slide

  4. My organization is
    not immune

    View Slide

  5. 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

    View Slide

  6. What did we lose?

    View Slide

  7. View Slide

  8. Permanent Compromise
    Permanent Compromise
    Reissued Big Hassle
    Reissued Trivial Hassle
    Self Reissued Minor Hassle
    Never should have been saved
    Its complicated…

    View Slide

  9. Users are special
    • Passwords are terrible.
    • Arbitrary rules forced on your users does not make
    them stronger.
    • Make no restrictions beyond a minimum length.
    • Do not restrict the length or pattern.
    • We cannot prevent a user from sharing tokens
    across sites. Assume they will.

    View Slide

  10. 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
    after a breach

    View Slide

  11. • 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 !

    View Slide

  12. Secure Methods
    • Not based on a sorting algorithms like md5 or sha
    • Unique and variable salts per account
    • Expensive expressed in terms of cycles or heat
    • /dev/random > os.urandom() > random.random()
    • Time based functions are the devil
    • Do not write your own crypto. There be dragons.

    View Slide

  13. Hash vs Crypt
    Fast
    I could implement
    Slow
    I would never implement
    Sorting methods are still great. For sorting!

    View Slide

  14. Good candidate
    for writing his own
    crypto:
    Again, do not write
    your own crypto.
    Dustin Boswell
    http://dustwell.com/how-to-handle-passwords-bcrypt.html

    View Slide

  15. Dangers of Writing Crypto
    Poor node balance in a hash causes poor performance.
    Poor node balance in a crypt breaks the crypt.

    View Slide

  16. View Slide

  17. View Slide

  18. View Slide

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

    View Slide

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

    View Slide

  21. 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

    View Slide

  22. The Plan
    • 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

    View Slide

  23. Replacement auth mechanism
    public static function loadByLogin($emailAddress, $password) {
    $user = self::load(
    Genesis_Db_Restriction::equal('email', $emailAddress)
    )->uniqueResult();
    !
    if ($user && $user->checkRawPassword($password)) { return $user; }
    }
    !
    public function checkRawPassword($password) {
    if ($this->getBcryptPasswordFlag()) {
    $bcrypt = new Bcrypt();
    return $bcrypt->verify($password, $this->getPassword());
    } else {
    return (some_hash_method($password) == $this->getPassword());
    }
    }
    public static function loadByLogin($emailAddress, $password) {
    return Genesis_Dao_AccountMgmtUser::select(
    Genesis_Db_Restriction::and_(
    Genesis_Db_Restriction::equal('email', $email),
    Genesis_Db_Restriction::equal('password', some_hash_method($password))
    )
    )->uniqueResult();
    }

    View Slide

  24. Bad Code
    if hash_func($oldPassword) is not self.getLoggedUser().getPassword():
    Not owned by the model!
    !
    if row.password is not sha1(sha1(salt) + sha1(password)):
    Wonky, 3x slower, and no stronger than sha1, possibly weaker!
    !
    elif sha1(password) is self._accounts[‘username’][1]
    (???)
    !
    return self._sha1(password) is self._accounts[‘username’];
    ! Not dry in the model, and is matching against the user name?!
    !
    $plain_sha1 = sha1($password);
    $password = '" . $this->_escape($plain_sha1) . "'
    No salt
    !
    return sha1(uniqid('', true) . $request->getUrl());
    In a password reset url, time based function

    View Slide

  25. 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.

    View Slide

  26. A dedicated route for upgrades
    • 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

    View Slide

  27. 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%

    View Slide

  28. 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.

    View Slide

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

    View Slide

  30. 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
    • But, all the low hanging fruit is gone
    • My active users will be protected

    View Slide

  31. 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

    View Slide

  32. Matt Land
    github.com/matt-land
    linkedin.com/in/matthewland

    View Slide