Date post: | 07-Jan-2017 |
Category: |
Software |
Upload: | david-blevins |
View: | 159 times |
Download: | 2 times |
Java
On
e
#RESTSecurity @dblevins @tomitribe
Deconstructing REST SecurityDavid Blevins
Tomitribe
Java
On
e
#RESTSecurity @dblevins @tomitribe
“The nice thing about standards is you have so many to choose from.”
- Andrew S. Tanenbaum
Java
On
e
#RESTSecurity @dblevins @tomitribe
Focus Areas
• Beyond Basic Auth
• Theory of OAuth 2.0
• Introduction of JWT
• Google/Facebook style API security
• Stateless vs Stateful Architecture
• HTTP Signatures
• Amazon EC2 style API security
Java
On
e
#RESTSecurity @dblevins @tomitribe
Baseline Architecture
1000 users x 3 TPS
4 hops
3000 TPS frontend
12000 TPS backend
Java
On
e
#RESTSecurity @dblevins @tomitribe
Basic Auth (and its problems)
Java
On
e
#RESTSecurity @dblevins @tomitribe
Basic Auth Message
POST /painter/color/object HTTP/1.1Host: localhost:8443Authorization: Basic c25vb3B5OnBhc3M=User-Agent: curl/7.43.0Accept: */*Content-Type: application/jsonContent-Length: 45
{"color":{"b":255,"g":0,"name":"blue","r":0}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
Basic Auth
Password Sent
3000 TPS (HTTP+SSL)
username+password Base64
(no auth)
3000 TPS (LDAP)
12000 TPS (HTTP)
Java
On
e
#RESTSecurity @dblevins @tomitribe
Basic Auth
Password Sent
3000 TPS (HTTP+SSL)
username+password Base64
username+password Base64
15000 TPS (LDAP)
Password Sent
12000 TPS (HTTP)
Java
On
e
#RESTSecurity @dblevins @tomitribe
Basic Auth
Password Sent
3000 TPS (HTTP+SSL)
username+password Base64
IP whitelisting
3000 TPS (LDAP)
12000 TPS (HTTP)
Java
On
e
#RESTSecurity @dblevins @tomitribe
“Hey, give me all of Joe’s salary information.”
“I don’t know who you are,
… but sure!”
Java
On
e
#RESTSecurity @dblevins @tomitribe
Latveria Attacks
Java
On
e
#RESTSecurity @dblevins @tomitribe
Basic Auth - Attacks
Valid Password Sent
3000 TPS (HTTP+SSL) IP
whitelisting
9000 TPS (LDAP)
12000 TPS (HTTP)
Invalid Password Sent
6000 TPS (HTTP+SSL)
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 (and its problems)
Java
On
e
#RESTSecurity @dblevins @tomitribe
Java
On
e
#RESTSecurity @dblevins @tomitribe
Java
On
e
#RESTSecurity @dblevins @tomitribe
Java
On
e
#RESTSecurity @dblevins @tomitribe
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2 - Password Grant(LDAP)
(Token Store)
POST /oauth2/tokenHost: api.superbiz.ioUser-Agent: curl/7.43.0Accept: */*Content-Type: application/x-www-form-urlencodedContent-Length: 54
grant_type=password&username=snoopy&password=woodstock
HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache
{"access_token":"2YotnFZFEjr1zCsicMWpAA","expires_in":3600,"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",}
Verify Password
Generate Token
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/object HTTP/1.1Host: api.superbiz.ioAuthorization: Bearer 2YotnFZFEjr1zCsicMWpAA User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 45 {"color":{"b":255,"g":0,"r":0,"name":"blue"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/palette HTTP/1.1Host: api.superbiz.ioAuthorization: Bearer 2YotnFZFEjr1zCsicMWpAA User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 46 {"color":{"b":0,"g":255,"r":0,"name":"green"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/select HTTP/1.1Host: api.superbiz.ioAuthorization: Bearer 2YotnFZFEjr1zCsicMWpAA User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 44 {"color":{"b":255,"g":0,"r":0,"name":"red"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/fill HTTP/1.1 Host: api.superbiz.ioAuthorization: Bearer 2YotnFZFEjr1zCsicMWpAA User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 49 {"color":{"b":255,"g":255,"r":0,"name":"yellow"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/stroke HTTP/1.1Host: api.superbiz.ioAuthorization: Bearer 2YotnFZFEjr1zCsicMWpAA User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 49 {"color":{"b":255,"g":200,"r":0,"name":"orange"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
401
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2 - Refresh Grant(LDAP)
(Token Store)
Verify Password
Generate Token
POST /oauth2/tokenHost: api.superbiz.ioUser-Agent: curl/7.43.0Accept: */*Content-Type: application/x-www-form-urlencodedContent-Length: 54
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache
{"access_token":"6Fe4jd7TmdE5yW2q0y6W2w","expires_in":3600,"refresh_token":"hyT5rw1QNh5Ttg2hdtR54e",}
Java
On
e
#RESTSecurity @dblevins @tomitribe
Old pair
• Access Token 2YotnFZFEjr1zCsicMWpAA
• Refresh Token tGzv3JOkF0XG5Qx2TlKWIA
New pair
• Access Token 6Fe4jd7TmdE5yW2q0y6W2w
• Refresh Token hyT5rw1QNh5Ttg2hdtR54e
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/palette HTTP/1.1Host: api.superbiz.ioAuthorization: Bearer 6Fe4jd7TmdE5yW2q0y6W2w User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 46 {"color":{"b":0,"g":255,"r":0,"name":"green"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/select HTTP/1.1Host: api.superbiz.ioAuthorization: Bearer 6Fe4jd7TmdE5yW2q0y6W2w User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 44 {"color":{"b":255,"g":0,"r":0,"name":"red"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message
POST /painter/color/fill HTTP/1.1 Host: api.superbiz.ioAuthorization: Bearer 6Fe4jd7TmdE5yW2q0y6W2w User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 49 {"color":{"b":255,"g":255,"r":0,"name":"yellow"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
What have we achieved?
Java
On
e
#RESTSecurity @dblevins @tomitribe
You have more passwords (at least your devices do)
Java
On
e
#RESTSecurity @dblevins @tomitribe
Term Alert
• Password Grant???
• Logging in
• Token?
• Slightly less crappy password
• Equally crappy HTTP Session ID
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2
Tokens Sent
3000 TPS (HTTP+SSL)
IP whitelisting
3000 TPS (token checks)
Password Sent
1000/daily (HTTP+SSL)
OAuth 2
(LDAP)
4 hops 12000 TPS
backend
Java
On
e
#RESTSecurity @dblevins @tomitribe
Java
On
e
#RESTSecurity @dblevins @tomitribe
“Who the heck is
6Fe4jd7TmdE5yW2q0y6W2w
???????”“No idea, dude.Ask the token
server.”
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2
Tokens Sent
3000 TPS (HTTP+SSL)
IP whitelisting
3000 TPS (token checks)
Password Sent
1000/daily (HTTP+SSL)
OAuth 2
(LDAP)
12000 TPS (token checks)
8 hops 24000 TPS
backend
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2
Tokens Sent
3000 TPS (HTTP+SSL)
IP whitelisting
3000 TPS (token checks)
Password Sent
1000/daily (HTTP+SSL)
OAuth 2
(LDAP)
12000 TPS (token checks)
8 hops 24000 TPS
backend
55% of all traffic
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2
Tokens Sent
3000 TPS (HTTP+SSL)
IP whitelisting
0 TPS (token checks)
Password Sent
1000/daily (HTTP+SSL)
OAuth 2
(LDAP)
0 TPS (token checks)
0 hops 0 TPS backend
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2
Pointer Pointer
State
Java
On
e
#RESTSecurity @dblevins @tomitribe
Access Token Access Pointer?
Access Primary Key?
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 High Frequency Password
Exchange Algorithm?
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 +
JSon Web Tokens (JWT)
Java
On
e
#RESTSecurity @dblevins @tomitribe
JSon Web Token
• Pronounced “JOT”
• Fancy JSON map
• Base64 URL Encoded
• Digitally Signed (RSA-SHA256, HMAC-SHA512, etc)
• Built-in expiration
Java
On
e
#RESTSecurity @dblevins @tomitribe
Access Token Previously
• 6Fe4jd7TmdE5yW2q0y6W2w
Java
On
e
#RESTSecurity @dblevins @tomitribe
Access Token Now
• eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5hbWUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL2RlbW8uc3VwZXJiaXouY29tL29hdXRoMi90b2tlbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0LWZyaWVuZCJdLCJleHAiOjE0NzQyODA5NjMsImlhdCI6MTQ3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
Java
On
e
#RESTSecurity @dblevins @tomitribe
Access Token Now
• header (JSON > Base64 URL Encoded)
• describes how the token signature can be checked
• payload (JSON > Base64 URL Encoded)
• Basically a map of whatever you want to put in it
• Some standard keys such as expiration
• signature (Binary > Base64 URL Encoded
• The actual digital signature
• made exclusively by the /oauth2/token endpoint
• If RSA, can be checked by anyone
Java
On
e
#RESTSecurity @dblevins @tomitribe
• { "alg": “RS256", "typ": “JWT" }
• { "token-type": "access-token", "username": "snoopy", "animal": "beagle", "iss": "https://demo.superbiz.com/oauth2/token", "scopes": [ “twitter”, "mans-best-friend" ], "exp": 1474280963, "iat": 1474279163, "jti": "66881b068b249ad9" }
• DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
Java
On
e
#RESTSecurity @dblevins @tomitribe
Subtle But High Impact Architectural Change
Java
On
e
#RESTSecurity @dblevins @tomitribe
What we had (quick recap)
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)Pull User Info
From IDP
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)
Generate an Access Token
(pointer)
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)
Insert both into DB
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)
Send Access Token (pointer) to client
Java
On
e
#RESTSecurity @dblevins @tomitribe
Results
Client Holds Pointer Server Holds State
Java
On
e
#RESTSecurity @dblevins @tomitribe
What we can do now (Hello JWT!)
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)Pull User Info
From IDP
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)
Format the data as JSON
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)
RSA-SHA 256 sign JSON
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)
Insert only pointer into DB
(for revocation)
Java
On
e
#RESTSecurity @dblevins @tomitribe
(LDAP)
Send Access Token (state) to client
Java
On
e
#RESTSecurity @dblevins @tomitribe
Client Holds State Server Holds Pointer
Desired Results
Java
On
e
#RESTSecurity @dblevins @tomitribe
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2 - Password Grant(LDAP)
(Token ID Store)
POST /oauth2/tokenHost: api.superbiz.ioUser-Agent: curl/7.43.0Accept: */*Content-Type: application/x-www-form-urlencodedContent-Length: 54
grant_type=password&username=snoopy&password=woodstock
Verify Password
Generate Signed Token
HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache
{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5hbWUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL2RlbW8uc3VwZXJiaXouY29tL29hdXRoMi90b2tlbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0LWZyaWVuZCJdLCJleHAiOjE0NzQyODA5NjMsImlhdCI6MTQ3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo","expires_in":3600,"refresh_token":"eyJhbGctGzv3JOkF0XG5Qx2TlKWIAkF0X.eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5hbWUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL",}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message with JWT
POST /painter/color/palette HTTP/1.1Host: api.superbiz.ioAuthorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXR va2VuIiwidXNlcm5hbWUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL2RlbW8uc3VwZXJ iaXouY29tL29hdXRoMi90b2tlbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0LWZyaWVuZCJdLCJleHAiOjE0NzQy ODA5NjMsImlhdCI6MTQ3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.DTfSdMzIIsC0j8z3icRdYO1GaMGl 6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZ vzlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
User-Agent: curl/7.43.0Accept: */* Content-Type: application/jsonContent-Length: 46 {"color":{"b":0,"g":255,"r":0,"name":"green"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2 + JWT
Tokens Sent
3000 TPS (HTTP+SSL)
IP whitelisting
0.55 TPS (refresh token checks)
Password Sent
1000/daily (HTTP+SSL)
OAuth 2
(LDAP)
4 hops 12000 TPS
backend
3000 TPS (signature verification)
12000 TPS (signature verification)
Java
On
e
#RESTSecurity @dblevins @tomitribe
“Hey, give me all of Joe’s salary information.”
“Not a chance!”
Java
On
e
#RESTSecurity @dblevins @tomitribe
“Hey, give me all of Joe’s salary information.”
“Sure thing!”
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth 2 + JWT
Valid Tokens Sent
3000 TPS (HTTP+SSL)
IP whitelisting
0.55 TPS (refresh token checks)
Password Sent
1000/daily (HTTP+SSL)
(LDAP)
4 hops 12000 TPS
backend
9000 TPS (signature verification)
12000 TPS (signature verification)
Invalid Tokens Sent
6000 TPS (HTTP+SSL)
Java
On
e
#RESTSecurity @dblevins @tomitribe
http://connect2id.com/products/nimbus-jose-jwt
Great JWT lib
Java
On
e
#RESTSecurity @dblevins @tomitribe
HTTP Signatures (Amazon EC2 style API Security)
Java
On
e
#RESTSecurity @dblevins @tomitribe
HTTP Signatures
• No “secret” ever hits the wire
• Signs the message itself
• Proves identity
• Prevents message tampering
• Symmetric or Asymmetric signatures
• IETF Draft
• https://tools.ietf.org/html/draft-cavage-http-signatures
• Extremely simple
• Does NOT eliminate benefits of JWT (they’
Java
On
e
#RESTSecurity @dblevins @tomitribe
Signature Message
POST /painter/color/palette HTTP/1.1Host: api.superbiz.ioAuthorization: Signature keyId=“my-key-name", algorithm="hmac-sha256", headers="content-length host date (request-target)”, signature="j050ZC4iWDW40nVx2oVwBEymXzwvsgm+hKBkuw04b+w="Date: Mon, 19 Sep 2016 16:51:35 PDT Accept: */* Content-Type: application/jsonContent-Length: 46 {"color":{"b":0,"g":255,"r":0,"name":"green"}}
Java
On
e
#RESTSecurity @dblevins @tomitribe
Signature Auth
Password Sent
0 TPS (HTTP)
Signature (no auth)
3000 TPS (LDAP or Keystore)
12000 TPS (HTTP)
Java
On
e
#RESTSecurity @dblevins @tomitribe
Signature Auth
Password Sent
0 TPS (HTTP)
Signature Signature
3000 TPS (LDAP or Keystore)
12000 TPS (HTTP)
Java
On
e
#RESTSecurity @dblevins @tomitribe
“Hey, give me all of Joe’s salary information.”
“Hey, Larry!
Sure!”
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth and Signatures
Password Sent
3000 TPS (HTTP+SSL)
OAuth 2 Signature
12000 TPS (HTTP)
Java
On
e
#RESTSecurity @dblevins @tomitribe
“Hey, give me all of Joe’s salary information.”
“Sure thing, Larry!
Tell Joe I said hi.”
Java
On
e
#RESTSecurity @dblevins @tomitribe
OAuth and Signatures
Password Sent
3000 TPS (HTTP+SSL)
OAuth 2 Signature
12000 TPS (HTTP)
Joe
Larry
Stan
Java
On
e
#RESTSecurity @dblevins @tomitribe
Observations
• HTTP Signatures the only HTTP friendly approach
• Signatures does not solve the “Identity Load” problem
• OAuth 2 with JWT significantly improves IDP load
• Plain OAuth 2
• HTTP Session-like implications
• OAuth 2 with JWT
• Signed cookie
• Signing key to the future
Java
On
e
#RESTSecurity @dblevins @tomitribe
Thank You!