Secure channel ============= Secure channel TCP/IP doesn't provide authenticity and confidentiality Using crypto we layer a secure channel on top of TCP/IP Case study: TLS/SSL Secure channels are strong foundation for security Run HTTP over SSL and Web is "secure" Slowly becoming the default Run STMP over SSL and mail delivery is "secure" Run IMAP/POP over SSL and mail pickup is "secure" Etc. Well understood/developed area of security Cryptography is a powerful security mechanism Encryption: confidentiality Signatures: integrity Public-key vs private-key Public key operations: KeyGen() -> public key PK, secret key SK Encrypt(PK, message m) -> ciphertext c Decrypt(SK, c) -> m Sign(SK, m) -> signature sig Verify(PK, m, sig) -> ok? Private key operations: KeyGen() -> private key K Encrypt(K, m) -> c Decrypt(K, m) -> C MAC(K, m) -> tag t Establishing a secure channel Goal: establish a shared key for symmetric crypto Strawman: C --> S: connect C <-- S: my public key is PK_S C --> S: Encrypt(PK_S, freshKey) C <-> S: Encrypt(freshKey, m...) Problem 1: authenticating the server What if an adversary intercepts messages to the server? Client's view is exactly the same Client will have a shared key with the adversary Adversary can connect to real server and relay messages Subsequent messages appear to be just fine "Man-in-the-middle attack" Need to bind PK_S to server's identity (principal name) Solution: certificates Trusted authority server Maintains table of (principal name, public key) pairs Principal name is typically the server's DNS name Choice of name must capture the client's intended communication target Crucial that the name is correct! Need to worry about typos, look-alikes Other participants rely on authority server to have the right mapping Need to know the authority server's public key to bootstrap all this More on certificates in next week's lecture Could query server, but that's bad for availability, performance Instead, authority server can sign a message: Sign(SK_CA, {server, PK_server}) This is the server's "certificate" Server can send this certificate to the client Client can verify that it's correctly signed by PK_CA Adversary would not be able to provide such a certificate for adversary's PK_S Revised strawman protocol: C --> S: connect C <-- S: PK_S, Sign(SK_CA, {server: PK_S}) C --> S: Encrypt(PK_S, freshKey) C <-> S: Encrypt(freshKey, m...) Alternative solution: trust-on-first-use (TOFU), as in SSH Assume first connection is OK Remember binding between PK_S and server's principal name for future use Easier to deploy, fewer security properties Problem 2: authenticating the messages C <-> S: Encrypt(freshKey, m...) Suppose client sends request "Transfer $1 to Bob's account" Encryption guarantees confidentiality but not integrity One way to think of it: Decrypt() always succeeds Adversary tampers with ciphertext -> Decrypt will return something else Sometimes predictable effects: flip ciphertext bit -> flip message bit Note that this does not break confidentiality In our example: flip a bit to send $129 to Bob Solution: use MAC() to compute an authentication tag C <-> S: c=Encrypt(freshKey, m...), t=MAC(freshKey, c) [ Note: in reality, use different keys for Encrypt and MAC ] This is called "Authenticated encryption" Tag will be incorrect: message rejected after tampering What if adversary retransmits the messages? Doesn't tamper with message but just sends it 129 times From server's perspective: 129 valid messages Need to defend against replay attacks Solution: keep track of previously seen messages Discard messages that have already been processed Two common approaches: 1. Sequence number in message Receiver tracks last-seen sequence number Discard messages with older sequence numbers Good for stream-oriented protocols 2. Expiration / session ID in message Receiver tracks ALL past messages within expiration time or within session Discard previously received messages Good for message-oriented (non-stream) protocols Problem 3: future server breakin What if a bad guy later compromises the server? Can use SK_S to decrypt old network packets This in turn reveals the freshKey value for old traffic Can decrypt old traffic contents! Solution: forward secrecy Don't use long-term keys for encryption Susceptible to decryption by a future adversary Instead, use short-lived keys for encryption, and long-term keys for signing Future adversary can forge signatures in the future, but it's too late Strawman forward secrecy for our protocol: C --> S: connect C <-- S: PK_conn, Sign(SK_CA, {server: PK_S}), Sign(SK_S, PK_conn) C --> S: Encrypt(PK_conn, freshKey) C <-> S: Encrypt(freshKey, m...) SSL/TLS The secure channel protocol for the Web SSL originally defined by Netscape TLS is the international standard version Improvements over the years SSL 2.0, SSL 3.0, TLS 1.2, TLS 1.3 (3/18) https://en.wikipedia.org/wiki/Transport_Layer_Security SSL 3.0 is now "forbidden" Protocol has uses block ciphers incorrectly (CBC) and has weak stream cipher (and RC4) Main parts to it Record protocol (send/receiving messages) Handshake protocol (setting up keys to authenticate/encrypt messages) Analysis: threat models Active attackers tamper and forge messages Passive attackers only eavesdropping e.g., traffic analysis SSL with a stream cipher ciphertext length reveals plaintext length allows attacker to learn which web page was accessed SSL 3.0 handshake 1. C -> S: Hello: client version, randomC, session_id, ciphers 2. S -> C: Hello: server version, RandomS, session_id, ciphers 3. S -> C: ServerCertificate: cert list 4. S -> C: HelloDone 5. C -> S: ClientKeyExchange: encrypt (pre_master_secret, PK_S) 6. C -> S: ChangeCipherSpec 7. C -> S: finished, MAC({master_secret ++ msg 1,2,3,4,5}, C_key) (and encrypted) 8. S -> C: change cipher spec 9. S -> C: finished MAC({master_secret ++ msg 1,2,3,4,5,7}, S_Key) (and encrypted) 10. C -> S: encrypt(sign(data, MAC_secret), C_key) master_secret <- PRF(pre_master_secret, "master secret", randomC+randomS) keyblock <- PRF(master_secret, "key expansion", randomS+randC) SSL 2.0 attack Adversary could edit ClientHello message undetected Tell S to substitute strong ciphers with weak ciphers SSL 3.0 risk: version roll-back attack Adversary modifies ClientHello to be say version 2 Clients adds "marker" in authenticated padding bytes Works only with RSA key-exchange SSL 3.0 attack: drop ChangeCipher MAC doesn't include message 6 and 8 attacker delete 6 and 8 Client and server won't switch to using ciphers! Attacker can change data to S TLS 1.0: Finish must be preceded by ChangeCipher SSL 3.0: POODLE (Oct 2014) MAC doesn't cover block-cipher padding Can be used to guess cookie in small number of tries https://www.openssl.org/~bodo/ssl-poodle.pdf Be explicit/Horton Principle Design principle, helpful in analyzing protocols Every message must be explicit on the context that it depends on Finish message in SSL3.0 is not explicit about message 6 Security is also dependent on the implementation SSL/TLS is complicated, thus implementation bugs TLS 1.3 simpler than 1.2! Popular implementation: openSSL Heartbleed bug in 2014 Adversary can steal private key Buffer overrun bug Who can access encrypted data? Secure channels protect against an adversary that controls the network Data available as plaintext on either end of the secure channel Compromised server can get access to the data: server has decryption key Alternative: do not give server the decryption key End-to-end encryption / encryption at rest Data encrypted with a key of the intended app-level recipient Not necessarily the server that transmits or stores the message E.g., text messaging: encrypt with other user's key Server stores and forwards ciphertext, cannot look inside Recipient can eventually decrypt message E.g., file storage: encrypt with user's own key Server stores encrypted data, cannot look inside User can download file back from the server, decrypt it Lab 5 Powerful: cuts out worrying about attacks on server (w.r.t. confidentiality) Shared encrypted data: how to give multiple users access to shared doc? Naive plan: encrypt same document with each user's key. Downside: multiple copies, possibly diverging versions. Better plan: chaining keys. Generate a new key just for the document. Encrypt document with the document's public key. Encrypt document's secret key with each user's public key. here have been some attacks on the cryptographic parts of SSL/TLS. Attack by Rizzo and Duong can allow adversary to learn some plaintext by issuing many carefully-chosen requests over a single connection. [ Ref: http://www.educatedguesswork.org/2011/09/security_impact_of_the_rizzodu.html ] Recent attack by same people using compression, mentioned in Paul Youn's lecture. [ Ref: http://en.wikipedia.org/wiki/CRIME ] Most recently, more padding oracle attacks. [ Ref: https://www.openssl.org/~bodo/ssl-poodle.pdf ] Some servers/CAs use weak crypto, e.g. certificates using MD5. Some clients choose weak crypto (e.g., SSL/TLS on Android). [ Ref: http://op-co.de/blog/posts/android_ssl_downgrade/ ] Some implementations use bad randomness to generate keys [ Ref: https://wiki.debian.org/SSLkeys#End_User_Summary ] But, cryptography is rarely the weakest part of a system.