Slide 1

Slide 1 text

Breaking User Passwords and Why You Should

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

Slide 4

Slide 4 text

My organization is not immune

Slide 5

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

Slide 6

Slide 6 text

What did we lose?

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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.

Slide 10

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

Slide 11

Slide 11 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 12

Slide 12 text

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.

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 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 22

Slide 22 text

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

Slide 23

Slide 23 text

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(); }

Slide 24

Slide 24 text

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

Slide 25

Slide 25 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 26

Slide 26 text

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

Slide 27

Slide 27 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 28

Slide 28 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 29

Slide 29 text

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

Slide 30

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

Slide 31

Slide 31 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 32

Slide 32 text

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