Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Relaxing the Same Origin Policy

Relaxing the Same Origin Policy

The Same Origin Policy is an important security layer for browsers, but in some case we need to deal with it and find a way to relax it.
This presentation describes 4 "standard" techniques to enable cross domain communication.

Presentation given to the RomaJS community in april 2014 (www.romajs.org)
Related source code with examples and playground available at https://github.com/marco-loche/RomaJS-SameOriginPolicyTalk

Marco Loche

April 23, 2014
Tweet

More Decks by Marco Loche

Other Decks in Programming

Transcript

  1. ¡  A  mechanism  to  enforce  data  confidentiality   and  integrity.

      ¡  Pages  of  the  same  origin  can  manipulate   each  other's  DOM   ¡  Extended  to  other  aspects  :  HTTP  Cookies,   XMLHttpRequest  
  2. ¡  "origin"  of  a  URI  is  specified  in  RFC  6454,

      Section  4.   §  http://tools.ietf.org/html/rfc6454   ¡  For  HTML5     §  http://www.w3.org/TR/html5/browsers.html#origin   ¡   trusted  ===  {scheme,  host,  port}  
  3. §  http://www.example.com/index.html     ¡  Different  port   §  http://www.example.com:81/content/page2.html

      ¡  Different  protocol   §  https://www.example.com/content/page2.html   ¡  Different  Host  :  exact  matching  needed   §  http://api.example.com/content/page2.html   §  http://example.com/content/page2.html  
  4. Deal  with  the  policy!     ¡  document.domain  property  

    ¡  Cross-­‐document  messaging   ¡  JSONP   ¡  Cross-­‐Origin  Resource  Sharing  
  5. The  store  site  needs  to   acces  some  values  defined

      in  www  site     http://www.site1.local   http://store.site1.local   http://www.site1.local:3000/unrelaxed.html    
  6. http://www.site1.local:3000/relaxed.domain.html     <!DOCTYPE html>! <!--www.site1.local UNRELAXED-->! <html>! <head>! <title>Site

    1 - Unrelaxed</title>! <script>! var sensitiveValue = "SENSITIVE VALUE!”;! </script>! </head>! <body>! <h1>WWW Site 1</h1>! <p>This page demonstrate normal Same Origin Policy</p>! <iframe src="http:// store.site1.local:3000/index.html" name="store" style="height:400px"></ iframe>! </body>! </html>! http:///store.site1.local:3000/relaxed.domain.html     <!DOCTYPE html>! <!--store.site1.local-->! <html>! <head>! <title>Store Site 1</title>! </head>! <script>! function readInfo() {! alert('Accessing from '+location.host +' to a sensitive value ' + parent.sensitiveValue);! }! document.domain = 'site1.local';! </script>! <body>! <h1>Store Site 1</h1>! <input type="button" value="Read info" onclick="readInfo()">! </body>! </html>!
  7. ¡  All  modern  browsers  support   document.domain! ¡  BUT  

      §  Only  for  DOM  Access,  not  for  XHR   §  Only  if  applications  share  the  same  SLD   §  Can  be  interferred  by  other  application  in  same   SLD  (invoice.site1.local)   §  It’s  a  read/write  property  once  given  the  access     §  Do  not  use  it  in  shared  hosting  (as  w3c.org  says!)  
  8. SENDER   otherWindow.postMessage(! message, ! targetOrigin, ! [transfer]);! ! RECEIVER

      window.addEventListener(! !"message", ! !receiveMessage, ! !false); ! function receiveMessage(event) {! if (event.origin !== "http://example.org") ! !// DO STUFF HERE WITH event.data}!
  9.     ! ! function readInfo() {! parent.window.postMessage(! 'Give me

    sensitive value', ! 'http://www.site1.local:3000');! }! http://store.local:3000/relaxed.message.html    
  10.   sensitiveValue = "SENSITIVE VALUE!";! ! function receiver(event) {! if

    (event.origin == 'http://store.site1.local:3000’){! if (event.data == 'Give me sensitive value') {! event.source.postMessage(! ! sensitiveValue, event.origin);! alert(sensitiveValue);! }! }! }! window.addEventListener('message', receiver);! http://www.site1.local:3000/relaxed.message.html    
  11. ¡  www.caniuse.com/x-­‐doc-­‐messaging   ¡  BETTER:   §  2  actors  contract

      §  tabs/window  communication   ¡  BUT     §  Only  for  DOM  Access,  not  for  XHR   §  Risky  if  you  don’t    check  origin   §  Risky  if  you  don’t  check  the  expected  data  format   §  It’s  still  a  draft  
  12.   A  web  app  which  needs  to  access  a  REST

     API   http://www.site1.local   http://api.site2.local   GET !/messages!
  13. JSONP  relies  on  SOP  relaxing  for  <script>! ! <script !

    type="text/javascript" ! src="http://api.site2.local:3000/messages? callback=handleJsonp">! </script>!   Equivalent  to  :   ! <script type="text/javascript”>! !handleJsonp({ /** remote json data */ });! </script>!  
  14. JSONP  relies  on  SOP  relaxing  for  <script>! ! <script !

    type="text/javascript" ! src="http://api.site2.local:3000/messages? callback">! </script>!   Equivalent  to  :   ! <script type="text/javascript”>! ! { /** remote json data */ };! </script>!  
  15. ¡  It’s  allowed  by  SOP   ¡  Server  must  manage

     the  GET  parameter  callback to  generate  the  response ! ¡  COOL:   §  Supported  by  jQuery  (with  extended  features)     ▪  http://api.jquery.com/jquery.getjson/   §  Supported  by  ExpressJS     ▪  res.jsonp(object);!   ¡  BUT     §  Not  secure  :  browsers  accept  arbitrary  JS.   §  Incomplete  :  only  GET  
  16.   A  web  app  which  needs  to  access  a  REST

     API   http://www.site1.local   http://api.site2.local   GET !/messages! ! POST !/messages!
  17. ¡  W3C  Specification  (16  january  2014)   ¡  Enable  true

     cross  domain  communication  for   JavaScript  application   ¡  Build  on  top  of  the  XHR  
  18. CORS  Request   GET /cors HTTP/1.1 ! Origin: http://www.site1.local! Host:

    api.site2.local ! Accept-Language: en-US ! Connection: …! User-Agent: …! ! CORS  Response   Access-Control-Allow-Origin: http://www.site1.local! Access-Control-Allow-Credentials: true ! Content-Type: text/html; charset=utf-8!
  19. ¡  Complex  CORS  request     §  HTTP  verbs  :

     PUT  or  DELETE   §  Content-­‐Type     §  Custome  Headers   ¡  Preflight  request  +  actual  request  
  20. Preflight  CORS  Request   OPTIONS /cors HTTP/1.1 ! Origin: http://www.site1.local!

    Access-Control-Request-Method: PUT ! Access-Control-Request-Headers: X-Custom-Header! Host: api.site2.local ! Accept-Language: en-US ! Connection: …! User-Agent: …! ! Preflight  CORS  Response   Access-Control-Allow-Origin: http://www.site1.local! Access-Control-Allow-Methods: GET, POST, PUT ! Access-Control-Allow-Headers: X-Custom-Header! Access-Control-Max-Age: 3600! Content-Type: text/html; charset=utf-8!
  21. ActualCORS  Request   PUT /cors HTTP/1.1 ! Origin: http://www.site1.local! Host:

    api.site2.local ! X-Custom-Header: value! Accept-Language: en-US ! Connection: …! User-Agent: … !   Actual  CORS  Response   Access-Control-Allow-Origin: http://www.site1.local! Content-Type: text/html; charset=utf-8!
  22. Client  side:   ¡  Request  Object  Wrapper’s  Nicolas  Zakas  

    ¡  jQuery     Server  side:   ¡  ExpressJs  has  a  cors  module  
  23. ¡  Yes  some  :   ¡  Limitations  with  IE,  fully

      supported  by    IE  >=  10   ¡  http://caniuse.com/cors   ¡  Security  
  24. §  GO       §  Fork   §  Play

     !   §  Open  issues  for  comments  and  tak     https://github.com/marco-­‐loche/RomaJS-­‐SameOriginPolicyTalk    
  25. ¡  Intrested  ?  I’m  looking  for  Javascripter   ¡  join

     me  @capturator   §  Send  me  your  linkedin  profile   §  Send  me  your  github  profile