Quick viewing(Text Mode)

Secure Design of Password Storage

Secure Design of Password Storage

Secure Design Of Storage

-jOHN Steven Internal CTO, Cigital, Inc.

V0.2 Secure Design

SHA-3 was just released.

So, we’re done.

(haha) The Threat Model 1) Acquiring PW DB 2) Reversing PWs from stolen booty

DB s SQLite Auth DB ! By capability " Script-kiddie " AppSec Professional " Well-equipped Attacker " Nation-state

Tool support (for PW cracking) is very good Attacks Specific to PW Storage

② Brute-force attack Well-equipped ③ attack

④ Length-extension attack ⑤ Padding Oracle attack Nation State ⑥ Chosen plaintext attack ⑦ -analytic attack ⑧ Side-channel attack • Plaintext • Encrypted • Hashed (using SHA) Breaking • and Hash • Adaptive Hashes the Design • PBKDF • Down • Hash Properties

Uniqueness Determinism Non-reversibility Non-predictability Diffusion Lightning fast Use a Better Hash? SHA-1 SHA-2 SHA-224/256 SHA-384/SHA-512 SHA-3 What property of hashes do these effect? Collisions. – Was this the problem? No. What Does the Salt Do?

De-duplicates digest texts Adds entropy to input space* • increases brute force time • requires a unique table per user Preventing Acquisition Preventing Reversing Designing for Security DB SQLite Auth DB

Threat Attack Vector [T1] – AppSec AVA00 - Attack code running in browser AVA01 – Inject database and lift (bulk) credentials AVR01 – Use API to brute force credentials [T4] - MitB AVA10,11 – Keylogger or other scripted attack on client data/entry

[T2] – MitM AVA03,04 – Interposition, Proxy, or SSL-based attack

[T5] – Concerted AVA12 – Infrastructure Attack (Network operators, DNS, or CA compromise) DB SQLite Auth DB Configuration DataStore KeyStore SQL SQLite Auth DB

DB Host () Preventing SQLi Configuration DataStore “Best Practices” KeyStore SQL SQLite • Separate cred./app stores Auth DB • Parameterize SQL queries DB Host (Linux) • Limit character sets Remember hash properties? • Fixed output size, character-set • hash(“password’); …”) à AF68B0E4…

12 Attacks via Host Configuration DataStore KeyStore

“Irreversible” SQL SQLite Auth DB • Treat DB as “untrusted” • Store secrets elsewhere DB Host (Linux) • Validate protected form

13 DB SQLite Auth DB

Threat Attack Vector [T3] – Admin AVA05 – Bulk credential export AVA06 – [T1]-style attack from LAN AVA07 – Direct interaction w/ database [T4] - MitB AVA08 – Interaction w/ database backups AVA09 – Access to logs (SEIM, etc.) AVR03– Stored data organization, sort, duplicate-detection [T5] – Concerted Dictionary Attack Brute Force Attack Rainbow Table Attack

Cryptanalytic attacks, as applicable • Plaintext • Encrypted • Hashed (using SHA) Current • Salt and Hash • Adaptive Hashes Industry • PBKDF • bcrypt Practices • scrypt Hash Properties

Uniqueness Determinism Collision resistance Non-reversibility Non-predictability Diffusion Lightning fast Use a Better Hash? SHA-1 SHA-2 SHA-224/256 SHA-384/SHA-512 SHA-3 What property of hashes do these effect? Collisions. – Was this the problem? No. Rainbow Tables: Fast but Inherent Limitations

Passwords with lengths and complexity in the white area aren’t cracked by the Rainbow Table

Source: Tables are crafted for specific complexity and length Per User Table Building

Brute Force Time for SHA-1 hashed, mixed-case-a alphanumeric password

8 Characters 9 Characters Aacking a single NVS 4200M GPU 80 days 13 years hash (32 M/sec) (Dell Laptop)

Aacking a single $169 Nvidia GTS 250 30 days 5 years hash (85 M/sec)

Aacking a single $325 ATI Radeon HD 1 day 68 days hash (2.3 B/sec) 5970

What Does the Salt Do?

De-duplicates digest texts Adds entropy to input space* • increases brute force time • requires a unique table per user Can salted hashes be Attacked?

Depends on the threat-actor... • Script-kiddie • Some guy • Well-equipped Attacker • Nation-state Attacking a table of salted hashes means building a Rainbow Table per user Algorithms designed specifically to remove the “lightning- fast” property of hashes Thus: protecting from Brute Force and Adaptive Rainbow Table attacks Adaptive Hashes increase the Hashes amount of time each hash takes through iteration PW-Based Derivation (PBKDF)

Application Code: Well-supported & vetted salt = random.getBytes(8) c = 10000000 HMAC key is password key = (salt, pw, c, ) protected_pw = concat(salt, key) Attacker has all entropy

Underlying implementation: What is the right ‘c’? pbkdf2(salt, pw, c, b){ r = computeNumOutputBlock(b) • NIST: 1000 md[1] = SHA1-HMAC(p, s || 1) for (i=2; i <= c; i++) md[i] = SHA1-HMAC(p, md[i-1]) • iOS4: 10000

for (j=0; j < b; j++) kp[j] = xor(md[1] || md[2]... md[j] • Modern CPU: 10000000

dkb = concat(kp[1] || kp[2] ... kp[r]) return dkb ***SIMPLIFED Code: see IEEE RFC2898 for details } See Java JCE Documentation for details on Java API bcrypt

Application Code: Not supported by JCE salt = bcrypt.genSalt(12) c = 10000000 cost 2 iterations slows hash operations c, salt, key = bcrypt(salt, pw, c) protected_pw = concat(c, salt, key) Is 212 enough these days?

Underlying implementation: What effect does changing

bcrypt(salt, pw, c){ cost have on DB? d = “OrpheanBeholderScryDoubt” keyState = EksBlowfishSetup(c, salt, pw) Outputting ‘c’ helps for (int i=0, i < 64,i++){ d = blowfish(keyState, d) } Resists GPU parallelization, but not FPGA return c || salt || d } scrypt

Application Code: Packages emerging, well- N = 16384 r = 8 trodden than bcrypt P = 1 Key=scrypt(salt, pw, N, p, dkLen){ Designed to defeat FPGA protected_pw = concat(salt, key) attacks Underlying implementation: scrypt(pw, salt, N, p, c){ Configurable for (i=0, i < p1, i++) b[i] = PBKDF2(pw, salt, 1, p*Mflen) for (i=0, i < p1, i++) • N = CPU time/Memory b[i] = ROMmix(b[i], N) footprint return PBKDF2(pw, b[1]||b[2]||…b[p-1], 1, dkLen) } • r = block size MF(b, N){ x = b for (i=0, i < N-1, i++) • P = defense against v = /* Chain BlockMix(x) over N*/ for (i=0, i < N-1, i++) parallelism j= /* Integrify(b) mod N */ x = /* Chain BlockMix(x xor v[j]) */ return x ***DRAMATICALLY SIMPLIFED Code: } See scypt by C. Percival See scrypt kdf-01, Josefsson for spec. BlockMix(r, b) ( /* Chain Salse20(b) over r) */ } Adaptive Hash Properties

Motivations Limitations

Resists most Threats’ attacks 1. Top priority is convincing SecArch • Concerted (nation-state) • C=10,000,000 == definition of insanity can succeed w/ HW & time • May have problems w/ heterogeneous arches

Simple implementation 2. API parameters (c=) != devops

Scale CPU-difficulty w/ • Must have a scheme rotation plan parameter* 3. Attain asymmetric warfare

• Attacker cost vs. Defender cost 4. No password update w/o user Defender VS Attacker Defender Attacker

Goal: Goal(s vary): Log user in w/out > 1sec delay Crack a single password, or particular password Create media event by cracking n passwords Rate: 20M Users, 2M active / hr.

Burden: Rate: Scales w/ Capability validation cost * users / (sec / hr.) Burden:

Bound by PW reset interval Hardware: Population / 2 = average break = 10M 4-16 CPUs on App Server

2-64 servers Hardware: Custom: 320+ GPUs / card, FPGA

Success Gauge : Success Gauge: Days required to crack PW (ave) # of machines required for AuthN Keep cost asymmetric: assure attacker cost greater than defender’s Tradeoff Threshold

Machines Required to Conduct Login Days (average) Until Attacker Gets PW

(@ full load) 80.0

50.00 70.0 45.00

40.00 60.0

35.00 50.0 30.00 40.0 25.00 Days 'til Ave Success Defender Machines 20.00 30.0

15.00 20.0 10.00 10.0 5.00

0.00 0.0 0 0.2 0.4 0.6 0.8 1 1.2 1.4 0 0.2 0.4 0.6 0.8 1 1.2 1.4

• Is more than 8 AuthN machines reasonable? • Is less than 2 months to average crack good enough?

Keep cost asymmetric: assure attacker cost greater than defender’s Attacker/Defender Worksheet

+ 20000000 Active+w/in+Hour 10% Defender%Machines% Attacker+Speedup 2 50.00+ Average+Pop.+Yielding+success 10000000 Defender+CPU 16 45.00+ Defender+work+(/+sec) 556 40.00+ Seconds Defender+Machines Days+'til+Ave+Success 0.01 0.35 0.6 35.00+ 0.05 1.74 2.9 30.00+ 0.1 3.47 5.8 0.15 5.21 8.7 25.00+ Defender+Machines+ 0.2 6.94 11.6 0.25 8.68 14.5 Days%''l%Ave%Success% 20.00+ 0.3 10.42 17.4 0.35 12.15 20.3 80.0+ 15.00+ 0.4 13.89 23.1 10.00+ 0.45 15.63 26.0 70.0+ 0.5 17.36 28.9 5.00+ 0.55 19.10 31.8 60.0+ 0.6 20.83 34.7 0.00+ 0.65 22.57 37.6 0+ 0.2+ 0.4+ 0.6+ 0.8+ 1+ 1.2+ 1.4+ 50.0+ 0.7 24.31 40.5 0.75 26.04 43.4 40.0+ 0.8 27.78 46.3 Days+'Ol+Ave+Success+ 0.85 29.51 49.2 0.9 31.25 52.1 30.0+ 0.95 32.99 55.0 1 34.72 57.9 20.0+ 1.05 36.46 60.8 1.1 38.19 63.7 10.0+ 1.15 39.93 66.6 1.2 41.67 69.4 0.0+ 1.25 43.40 72.3 0+ 0.2+ 0.4+ 0.6+ 0.8+ 1+ 1.2+ 1.4+

29 Adaptive Hashes At Best Strengthen a Single Requiring a Key Control Point Gains Defense We Can Do Better with Defense In Depth In Depth

Hmac Properties

Motivations Limitations Inherits hash properties 1. Protecting key material challenges developers • This includes the lightning speed • Must not allow key storage in DB!!!

Resists all Threats’ attacks 2. Must enforce design to stop T3 • compartmentalization and • Brute force out of reach • privilege separation (app server & db) • >= 2256 for SHA-2 3. No password update w/o user • Requires 2 kinds of attacks 4. Stolen key & db allows brute • AppServer: RMIi Host keystore force

• DB: reporting, SQLi, backup • Rate ~= underlying hash function COMPAT/FIPS Design

DB s SQLite Auth DB

• Hmac = -sha-256 • Add a control requiring a key • Version per scheme stored on the App Server • Salt per user • Threats who exfiltrate password • Key per site table also needs to get hmac key COMPAT/FIPS Solution

|||| := HMAC(, ) := |||| • HMAC := hmac-sha256 • keysite := PSMKeyTool(SHA256()):32B; • saltuser := SHA1PRNG():32B | FIPS186-2():32B; • pwuser :=

Optional:

:= ||||‘:’|||| • GUIDuser := NOT username or available to untrusted zones Just Split the Digest?

No. They’re not the same. • Lacks key space (brute force expansion) • Steal both pieces with the same technique

• Remember 000002e09ee4e5a8fcdae7e3082c9d8ec3d304a5 ?

Permanence:code jsteven$ python split_hash_test.py -v 07606374520 -h ../hashes.txt

+ Found ['75AA8FF23C8846D1a79ae7f7452cfb272244b5ba3ce315401065d803'] verifying passwords

+ 1 total matching

Permanence:code jsteven$ python split_hash_test.py -h ../hashes_full.txt -v excal1ber -c 20

+ Found ['8FF8E2817E174C76b8597181a2ee028664aadff17a32980a5bad898c'] verifying passwords

+ 1 total matching

34 (More) Just Split the Digest Comparing 20B PBKDF2 chunks created no collisions

Permanence: jsteven$ grep passwords ../hashes.txt No spurious hit Permanence: jsteven$ python split_hash_test.py -v passwords -h ../hashes.txt Worst-case: 20B chunk = 50/50 split + Found [] matching passwords Permanence: jsteven$ python split_hash_test.py -h ../hashes_full.txt -v excal1ber -c 20

+ Found 1 ['8FF8E2817E174C76b8597181a2ee028664aadff17a32980a5bad898c'] matching passwords • 2,150,710 uniquely salted hashes + Found 1 ['4F10C870B4E94F814fd07046b8d3bea650073e564c39596b8990d74b'] matching passwords • 16 byte salt + Found 1 ['EBD19B279CC64554f83f485706073fab5a112ea63143ec82a37e6d41'] matching passwords

+ Found 1 ['A4575F1E7D4C41DEc0ae49c5ce48ce4a9dbe28b9e87635e7289eb7eb'] matching passwords • passwords + Found 1 ['E1301662EC6349E5021c4cd8c158533aa9342ddee452f74f321ea0fa'] matching passwords • mp3download • REDROOSTER + Found 1 ['72532DBFBF954FA1d9a068690ed1c3fc09459932be96bad5af4e1453'] matching passwords • Dragon69 + Found 1 ['043EAF3FE8434630d9d513284835c0891f0fbfcbeaf1f6bb6f76bc06'] matching passwords • 07606374520 • brazer1 + Found 1 ['636BEF93F99449114785304641f419d450ce24ddfa03f4383e7593e6'] matching passwords • Bigwheel18 + Found 1 ['A66772BEAF7A47361f6929611cc24b92b86cb84403c7773996ac49bc'] matching passwords • Mastodon1 + Found 1 ['8C8066C40C224A6700c50395afa1d3a87c9b76a1215193a29226e170'] matching passwords • Martha1a • screaming36! + Found 1 ['AD10E9DF1D23435163457052e8433cc60aa4a853ee13143db90b0456'] matching passwords

35

Reversible Design

DB s SQLite Auth DB

• ENC = AES-256 • ADAPT = pbkdf2 | scrypt • Version per scheme • Salt per user • Key per site

hmac Solution Properties

Attack Resistance

1.1 Resist chosen plain text attacks Yes, Scheme complexity based on (saltuser & pwuser) + keysite 1.2 Resist brute force attacks Yes, Key = 2256, salt = 2256 site user 1.3 Resist D.o.S. of entropy/randomness exhaustion Yes, 32B on password generation or rotation 1.4 Prevent bulk exfiltration of credentials Implementation detail: 1.5 Prevent identical (pw) creation Yes, provided by salt

1.6 Prevent (pw) w/ credentials Yes, provided by Keysite

1.7 Prevent exfiltration of ancillary secrets Implementation detail: store Keysite on application server 1.8 Prevent side-channel or timing attacks N/A 1.9 Prevent extension, similar Yes, hmac() construction (i_pad, o_pad) 1.10 Prevent multiple problems N/A (hmac() construction) 1.11 Prevent common key problems N/A (hmac() construction) 1.12 Prevent key material leakage through primitives Yes, hmac() construction (i_pad, o_pad) Reversible Properties

Motivations Limitations

• Inherits 1. Protecting key material challenges • “compat” solution benefits developers • Adaptive hashes’ slowness 1. Must not allow key storage in DB!!!

• Requires 2 kinds of attacks 2. Must enforce design to stop T3

• App Server & DB 1. compartmentalization and 2. privilege separation (app server & db) • Brute forcing DB out of reach (>=2256)

• Stolen key can be rotated w/o user 3. No password update w/o user interaction 4. Stolen key & db allows brute force • Stolen DB + key still requires reversing 1. Rate ~= underlying adaptive hash MOST IMPORTANT TOPIC Responding once attacked Operations

Replacing legacy PW DB

1. Protect the user’s account

• Invalidate authN ‘shortcuts’ allowing login w/o 2nd factors or secret questions

• Disallow changes to account (secret questions, OOB exchange, etc.)

2. Integrate new scheme

• Hmac(), adaptive hash (scrypt), reversible, etc.

• Include stored with digest

3. Wrap/replace legacy scheme: (incrementally when user logs in--#4)

• version||saltnew||protected = schemenew(saltold, digestexisting) –or– • For reversible scheme: rotate key, version number

4. When user logs in:

1. Validate credentials based on version (old, new); if old demand 2nd factor or secret answers

2. Prompt user for PW change, apologize, & conduct OOB confirmation

3. Convert stored PWs as users successfully log in

40 DB SQLite Auth DB Spring Struts Deployed App Deployed Configuration KeyStore

PSM

AppServer (WebSphere)

Host (Linux) Thank You for Your Time Questions

Conclusions • Without considering specific threats, the solutions misses key properties • Understanding operations drives a whole set of hidden requirements • Many solutions resist attack equivalently • Adaptive hashes impose on defenders, affecting scale • Leveraging design principles balances solution • Defense in depth • Separation of Privilege • Compartmentalization

TODO

• Revamp password cheat sheet • Build/donate implementation 1. Protection schemes 2. Database storage 3. Key store ß Vital to preventing dev err 4. Password validation 5. Attack response

44 Additional Material for longer-format Supporting presentations Slides

Select Source Material

Trade material Applicable Regulation, Audit, or Special Guidance Password Storage Cheat Sheet COBIT DS 5.18 - Cryptographic key management Cryptographic Storage Cheat Sheet •

PKCS #5: RSA Password-Based Cryptography • Export Administration Regulations (”EAR”) 15 C.F.R. Standard • NIST SP-800-90A Guide to Cryptography Future work: Kevin Wall’s Signs of broken auth (& related posts) • Recommendations for key derivation NIST SP-800-132 John Steven’s Securing password digests • of sensitive material: Graham-Cumming 1-way to fix your rubbish PW DB NIST SP-800-38F (Draft)

IETF RFC2898

Other work

Spring Security, Resin jascrypt

Apache: HTDigest, HTTP Digest Specification, Shiro 46