"Writing Secure APIs" Armin Ronacher, PyCon Ru 2014

  • 260 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
260
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
5
Comments
0
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Writing Secure APIs Armin Ronacher for PyCon.ru 2014
  • 2. Armin Ronacher Independent Contractor for Splash Damage / Fireteam Doing Online Infrastructure for Computer Games lucumr.pocoo.org/talks
  • 3. … but does it support SAML?
  • 4. ≈Why Secure APIs?
  • 5. Starbucks killed the enencrypted connection
  • 6. your enemy surfs on the same Wifi as you
  • 7. Things to secure: Session Cookies Access Tokens Credit Card Numbers …
  • 8. don't be afraid of government, your enemy is sitting on the same Wifi
  • 9. ?Which type of API?
  • 10. Web vs Browser Web
  • 11. It's all about the CAs Browsers trust Public CAs Services should trust Certificates
  • 12. Browser Web You use HTTP And there is a good old browser Websites, JavaScript APIs, etc.
  • 13. Web You use HTTP There is no browser Or it's a browser under your control Service to Service communication, Custom APIs, etc.
  • 14. If there is no browser I do not need a public CA
  • 15. If there is a browser there is not much you can do :'(
  • 16. ?What does a CA do?
  • 17. let's look at something else first
  • 18. 0Understanding Trust
  • 19. Authenticity Secrecy vs
  • 20. Authenticity : the author of the message is the author the receiver knows and trusts.
  • 21. Secrecy : nobody besides author and intended receiver read the message.
  • 22. Authenticity Secrecy >
  • 23. O OA OB E Authenticity: Eve
  • 24.   is
  • 25.   wiretapping
  • 26. O OA OB E Secrecy
  • 27.   without
  • 28.   Authenticity: Eve
  • 29.   is
  • 30.   wiretapping but
  • 31.   she
  • 32.   can
  • 33.   also
  • 34.   change
  • 35.   messages
  • 36. XSignatures
  • 37. Signatures add: authentication, integrity and non-repudication
  • 38. !non-repudication is pointless for APIs
  • 39. “Signature without non-repudication’ MAC
  • 40. Consumer gets shared key Signs request with shared key Sends request to server Server verifies request Server creates and signs response Client verifies response 1 2 3 4 5 6
  • 41. the key is never on the wire! (Eve is a sad attacker)
  • 42. O OA OB E what's
  • 43.   the
  • 44.   worst
  • 45.   Eve
  • 46.   can
  • 47.   do?
  • 48. O OA OB E what's
  • 49.   the
  • 50.   worst
  • 51.   Eve
  • 52.   can
  • 53.   do? Eve
  • 54.   can
  • 55.   not
  • 56.   send
  • 57.   the
  • 58.   request
  • 59. O OA OB E what's
  • 60.   the
  • 61.   worst
  • 62.   Eve
  • 63.   can
  • 64.   do? Eve
  • 65.   can
  • 66.   send
  • 67.   the
  • 68.   request but
  • 69.   not
  • 70.   tell
  • 71.   Alice
  • 72. O OA OB E what's
  • 73.   the
  • 74.   worst
  • 75.   Eve
  • 76.   can
  • 77.   do? Eve
  • 78.   can
  • 79.   send
  • 80.   the
  • 81.   request multiple
  • 82.   times
  • 83. O OA OB E what's
  • 84.   the
  • 85.   worst
  • 86.   Eve
  • 87.   can
  • 88.   do? Eve
  • 89.   could
  • 90.   just
  • 91.   send
  • 92.    it
  • 93.   with
  • 94.   delay zzz
  • 95. O OA OB E what's
  • 96.   the
  • 97.   worst
  • 98.   Eve
  • 99.   can
  • 100.   do? Eve
  • 101.   could
  • 102.   just
  • 103.   send
  • 104.    it
  • 105.   with
  • 106.   delay
  • 107.   -
  • 108.   and
  • 109.    not
  • 110.   tell
  • 111.   Alice zzz
  • 112. zzz O OA OB E what's
  • 113.   the
  • 114.   worst
  • 115.   Eve
  • 116.   can
  • 117.   do? Eve
  • 118.   could
  • 119.   just
  • 120.   send
  • 121.    it
  • 122.   a
  • 123.   day
  • 124.   later
  • 125.   again
  • 126. O OA OB E what's
  • 127.   the
  • 128.   worst
  • 129.   Eve
  • 130.   can
  • 131.   do? If
  • 132.   there
  • 133.   was
  • 134.   something
  • 135.   like
  • 136.   a
  • 137.    different
  • 138.   version
  • 139.   of
  • 140.   Bob,
  • 141.   Eve
  • 142.    could
  • 143.   send
  • 144.   it
  • 145.   there OB'
  • 146. Why most of those things don't matter The core problem is that Eve can wiretap Even without Eve a client can never know if a message was sent! Idempotency needs to be implemented anyways
  • 147. put the nonce in the cache!
  • 148. def handle_request(request): signature = create_signature(request) if signature != request.supplied_signature: abort_with_error() if not nonce_has_been_used(request.nonce): perform_modification() remember_nonce(request.nonce) result = generate_result() return generate_response_with_signature(result)
  • 149. tSignature Expiration
  • 150. Make Signatures Expire or you store years and years of nonces
  • 151. Synchronize your Clocks!
  • 152. def verify_message(data): sig, message = split_signature(data) reference_sig = calculate_signature(message) if reference_sig != sig: raise InvalidSignature() header, payload = split_message(message) expires_at = get_expiration_time(header) if expires_at < current_time(): raise SignatureExpired() return header, payload
  • 153. Message can only be used once only need to remember nonce for signature lifetime
  • 154. itsdangerous pypi.python.org/pypi/itsdangerous
  • 155. import time from itsdangerous import URLSafeSerializer, BadSignature def get_serializer(): return URLSafeSerializer(secret_key=get_secret_key()) def make_auth_ticket(user_id, expires_in=60): return get_serializer().dumps({ 'user_id': user_id, 'expires_at': time.time() + expires_in, }) def verify_auth_ticket(ticket): data = get_serializer().loads(ticket) if data['expires_at'] < time.time(): raise BadSignature('Ticket expired.') return data['user_id']
  • 156. ∂Signing killed oAuth 1.0a
  • 157. People did not want to sign
  • 158. … then only sign on the Server Enter: Token Based Authentication
  • 159. Token Based Authentication requires SSL or another secure transport uses short lived tokens used for exchanging authentication information
  • 160. This is what OAuth 2.0 is
  • 161. Access Refresh Token& short
  • 162.   and
  • 163.   lives
  • 164.   for
  • 165.   one
  • 166.   day signed,
  • 167.   complex
  • 168.   and
  • 169.   lives
  • 170.   for
  • 171.    a
  • 172.   really
  • 173.   long
  • 174.   time
  • 175.   (eternal) (also
  • 176.   called
  • 177.   bearer
  • 178.   token)
  • 179. O OA OB E what's
  • 180.   the
  • 181.   worst
  • 182.   Eve
  • 183.   can
  • 184.   do? pretty
  • 185.   much
  • 186.   whatever
  • 187.    the
  • 188.   hell
  • 189.   eve
  • 190.   wants!
  • 191. Token Based Authentication is a Tradeoff It ‘limits’ what an attacker can do Stolen Access Token: ~24 hours of damage Refresh Tokens are only exchanged on Token Refresh only ever used in combination with SSL!
  • 192. import uuid from itsdangerous import URLSafeSerializer def get_serializer(): return URLSafeSerializer(secret_key=get_secret_key()) def make_token(user): token_data = { 'user_id': user.id, 'generation': user.token_generation, } refresh_token = get_serializer().dumps(token_data) access_token = str(uuid.uuid4()) store_token(access_token, token_data) return access_token, refresh_token
  • 193. CA/SSL without Public CAs
  • 194. Certificate Revocations do work!not
  • 195. Certificate says valid until 2020 Private Key Leaked
  • 196. Certificate says valid until 2020 Private Key Leaked
  • 197. Certificate says valid until 2020 Private Key Leaked
  • 198. what now?
  • 199. treat it like token based authentication
  • 200. self signed certificates are good (just not if you deal with normal users)
  • 201. Become your Own Private CA
  • 202. make certificates expire every 24 hours
  • 203. refresh token » root certificate access token » connection certificate They are not the same But you treat them the same
  • 204. Certificate Travels over Wire Private Key Does Not
  • 205. create root certificate trust root certificate always have a cron job issue certificates signed by that root every 12 hours distribute them to the web servers cycle certs every 12 hours how it works: 1 2 3 4 5 6
  • 206. you can now looks your private key maximum damage is ~1 day your root's private key is on a box not connected to the internet with all ports closed. what makes it good:
  • 207. Survives Heartbleed :-)
  • 208. from requests import get resp = get('https://api.yourserver.com/', verify='your/certificate.bundle') Apple's crappy OpenSSL always trusts Keychain :-(
  • 209. why not with public CAs?
  • 210. why trust the whole world? you need to sign on their shitty web application on most CAs you pay for each signature and they are most of the time valid for a year 1 2 3 4
  • 211. #Structure for Security
  • 212. Request comes in Response goes out (you can explain that)
  • 213. Annotate Views for Security Rules @requires_role('system_management') def manage_system(request): return Response(...) Example
  • 214. Encapsulate Security Systems class UpdateUser(IdempotentEndpoint): id = Parameter(UUID) changes = Parameter(dict) def load_state(self): self.user = fetch_user(self.id) def update_state(self): self.user.update(self.changes) def get_response(self, state): return JSONResponse(self.user.to_json()) Example
  • 215. Add Security Contexts class Context(object): def __init__(self): self.account = None self.role_subset = set() def load_token(self, token, role_subset): self.account = find_account(token['account_id']) self.role_subset = set(role_subset) def has_role(self, x): if self.account is None or x not in self.role_subset: return False return x in self.account['roles'] Example
  • 216. ?Feel Free To Ask Questions Talk slides will be online on lucumr.pocoo.org/talks You can find me on Twitter: @mitsuhiko And gittip: gittip.com/mitsuhiko Or hire me: armin.ronacher@active-4.com