A computer security protocol designed to make web application password handling more secure.
Copyright Millstream Software 2012. All rights reserved. [Updated 2012/09/24] The Pepperpot Protocol ====================== The Pepperpot Protocol is a computer security protocol designed to make web application password handling more secure. It allows the application administrator to password protect the end-user password information in the database. With a sufficiently strong administrator password the protocol can prevent an application database compromise revealing any end-user passwords, even low entropy end-user passwords. The administrator password is held in a different process, called the pepperpot, which can be on a different computer. The pepperpot rate-limits login attempts independently of the application. Purpose ------- Good practice for the storage of web application passwords is to salt and hash the password using a cryptographic hash function that has a significant work factor. The hash is usually stored in the application database. This scheme has various problems: - Off-line password guessing after a database compromise is only limited by the hash work factor. Low entropy passwords are vulnerable. - The commodity hardware, on which web applications are often run, may have orders of magnitude less computational resources than a multi-processor system used for off-line password guessing. - Mistakes in the application code can make it vulnerable to online password guessing. - As hardware becomes more powerful the stored hashes become vulnerable to off-line guessing unless the they are periodically upgraded to increase the hash work factor. An extra password, called the pepper, can be put in the application source code, or stored in a file other than the database, and used in addition to the salt to reduce some of these weaknesses. But a server compromise could reveal this password too. Specialist cryptographic hardware can also solve these problems, but web applications often run on commodity hardware for portability and cost reasons. Overview -------- The Pepperpot Protocol introduces a separate process, the pepperpot, to hold the pepper without ever revealing it to the application. The pepperpot can be run on commodity hardware and if necessary on a separate computer. If the application database is compromised the end-user passwords cannot be guessed without also compromising the pepperpot or guessing the pepper password. The pepperpot is only given a combined hash of the salt and password, never the salt or password being hashed, so a pepperpot compromise will not reveal any end-user passwords. The pepperpot also rate-limits online password guessing. Because of these features the pepperpot protocol effectively eliminates the weaknesses listed above. Protocol -------- # The administrator has to input parameters to start the application # and the pepperpot. The parameters are a rate-limit for end-user # password attempts and a list of peppers. A pepper contains a # pepper-password and the hash algorithms to use with it. The peppers # are numbered. The first pepper created is pepper-number 1, the next # is 2 etc. The administrator will add a new pepper to the list to # change the current pepper-password or hash algorithms. Having a list # of peppers allows the pepper-password to be updated automatically # for an end-user when they login. With only a single pepper it would # not be possible to change the pepper-password without forcing a # password reset on all the end-users. Every successful end-user login # updates the user's password hash to incorporate the latest pepper and # this pepper-number is stored in the database. An old pepper has to # remain in the list until all the end-users who used it during their # last successful login complete a new login with a new pepper. # This pseudo-code uses the abbreviations 'a' = application, # 'p' = pepperpot, '1' = old version, '2' = new version. Application ----------- # Administrator inputs the parameters. administrator -> delay-application-milliseconds Da list-of-peppers LP: pepper-number N hash-fast-application Hfa hash-slow-application Hsa # Find the newest pepper in the list. # This current pepper will have the highest pepper-number. They are # numbered sequentially when created, but the numbers may not be # sequential now because some unused peppers may have been deleted. iN2a = index of maximum N in LP N2a = N[iN2a] Pepperpot --------- administrator -> delay-pepperpot-milliseconds Dp maximum-queue-length MQ list-of-peppers LP: pepper-number N pepper-password P hash-fast-pepperpot Hfp hash-slow-pepperpot Hsp # Hash the pepper passwords using # the slow hash. for each pepper Ph[i] = Hsp[i](P[i], N[i]) delete P[i], Hsp[i] # Find the current pepper. iN2p = index of maximum N in LP N2p = N[iN2p] queue-length = 0 Application ----------- # The application receives a login request. # The username must not be logged or displayed in an error report before # it is found in the database in case it is a mistyped password. The # password must not be logged or error reported at any point. user -> username, password # The pepperpot and the application responses must be returned in a # constant time to prevent timing attacks. So we record the start time. Ta = current time on the application server lookup username in database -> salt S1 pepper-number N1 hash H1 if username not found wait until time > Ta + Da "username or password incorrect" -> user login-fail # Find the old pepper. iN1a = index of N1 in LP if N1 not found in LP wait until time > Ta + Da "try again later" -> user "pepper not found" + details -> admin login-fail N1a = N[iN1a] # Generate a new salt. # The salt is replaced after every successful login. This limits # precomputation attacks and can, in some configurations, prevent login # statistics being collected by a compromised pepperpot. S2 = generate a new cryptographic random salt # The old and new salts are hashed with the password. S1Ph = Hfa[iN1a](S1, password) S2Ph = Hfa[iN2a](S2, password) delete password # The hashes are hashed again before being sent to the pepperpot. This # prevents a compromised pepperpot performing any useful precomputation # of the application slow hash below prior to a compromise of the # application database. S1Phh = Hfa[iN1a](S1Ph) S2Phh = Hfa[iN2a](S2Ph) Application Pepperpot ----------- --------- # Send the hashes and their pepper-numbers to the pepperpot. S1Phh, N1a, S2Phh, N2a ---------> Tp = current time on the pepperpot # Check we agree on current pepper. if N2a <> N2p wait until time > Tp + Dp <------------- hash-fail current-pepper-mismatch # Find the old pepper. iN1p = index of N1a in LP if N1a not found in LP wait until time > Tp + Dp <------------- hash-fail old-pepper-missing # Check the rate-limit. if queue-length >= MQ wait until time > Tp + Dp <------------- hash-fail rate-limit-exceeded increment queue-length # Old hash. H1p = Hfp[iN1p](S1Phh, Ph[iN1p]) # New hash. H2p = Hfp[iN2p](S2Phh, Ph[iN2p]) wait until time > Tp + Dp decrement queue-length <------------- hash-successful H1p, H2p Application ----------- if hash-fail wait until time > Ta + Da "try again later" -> user "pepperpot failed" + details -> admin login-fail H1a = Hsa[iN1a](H1p, S1Ph) if H1a <> H1 wait until time > Ta + Da "username or password incorrect" -> user login-fail # The password is correct. Store the new salt, pepper-number and hash. H2 = Hsa[iN2a](H2p, S2Ph) update database for username <- S2, N2a, H2 wait until time > Ta + Da "you are now logged in" -> user login-successful Details ------- There are 4 cryptographic hash algorithms. The slow hash pepperpot (Hsp) can and should have a significant work factor because it is only run once for each pepper password when the pepperpot is initialized. It is never run during end-user login attempts. The work factor of Hsp will rate-limit pepper-password guessing if the application database is compromised. The work factor of the slow hash application (Hsa) will rate-limit end-user password guessing if both the pepperpot and the application database are compromised. The two fast hash algorithms can have a lower work factor. The fast hash used by the application (Hfa) and fast hash used by the pepperpot (Hfp) protect the salted intermediate hashes. The salt should have sufficient entropy and the intermediate hashes sufficient length that it is computationally infeasible to find them from knowing their hash. If the pepperpot is running on the same computer as the application there is little reason to run multiple pepperpots. But if the application relies on a single pepperpot hosted on a separate computer and that computer fails it will cause outage of the application login. This risk can be reduced by using multiple pepperpots. The ability of a compromised pepperpot to perform a denial of service against an application can also be reduced in a multiple pepperpot system by testing login failures against other pepperpots. A single compromised pepperpot could deduce user login patterns for the application by chaining the hashes provided during login attempts. The protocol changes the salt with every successful login to increase the difficulty of obtaining this information in a multiple pepperpot system. A single compromised pepperpot in a multiple pepperpot system would have the sequence of hashes for a username broken whenever a subsequent login for the user was conducted via another pepperpot. All the pepperpots in a multiple pepperpot system would have to be simultaneously compromised to obtain the pattern of user logins. Version History --------------- First version published 2012/06/25. Updated version published 2012/09/06 to strengthen against a simultaneous compromise of the database and pepperpot. Updated version published 2012/09/24 to strengthen against a simultaneous compromise of the database and the ability to query the pepperpot.