Web Integration Patterns in the Era of HTML5
Upcoming SlideShare
Loading in...5
×
 

Web Integration Patterns in the Era of HTML5

on

  • 1,647 views

Presentation given at OWASP BeNeLux November 2012 and GeekMeet Stockholm January 2013. Covers secure and robust integration patterns for the web using cross origin resource sharing (CORS), sandboxed ...

Presentation given at OWASP BeNeLux November 2012 and GeekMeet Stockholm January 2013. Covers secure and robust integration patterns for the web using cross origin resource sharing (CORS), sandboxed iframes, and the postMessage API.

Statistics

Views

Total Views
1,647
Views on SlideShare
1,641
Embed Views
6

Actions

Likes
4
Downloads
23
Comments
0

2 Embeds 6

https://twitter.com 5
http://www.verious.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Web Integration Patterns in the Era of HTML5 Web Integration Patterns in the Era of HTML5 Presentation Transcript

  • Web Integration Patterns In the Era of HTML5@johnwilander atOWASP BeNeLux 2012, Leuven, BelgiumGeekMeet Stockholm, Sweden, 2013
  • Part IThe Historyof Web Integration @johnwilander
  • Remember when we had pages? @johnwilander
  • Menu… maybe a persistent menu system? @johnwilander
  • Menu … and 3rd party popus? @johnwilander
  • You still see such sites. @johnwilander
  • But product owners don’t want them anymore. @johnwilander
  • MenuSo we started loading thingswhen we needed them,using Ajax and DOMmanipulation with JavaScript. @johnwilander
  • Menu @johnwilander
  • MenuThe problem was that Ajaxwas only allowed to thesame origin as the page.Ergo, no third partyintegration. @johnwilander
  • But the same-originpolicy didn’t apply to all web elements. @johnwilander
  • <form action="http://3rdparty.net"></form><img src="http://3rdparty.net"><script src="http://3rdparty.net"></script> @johnwilander
  • <form action="http://3rdparty.net"></form><img form tag actually had cross-domain The src="http://3rdparty.net"> intentions and is used for integration with e.g.<script src="http://3rdparty.net"></script> payment providers such as PayPal.You post a purchase form from maindomain.com and enter the checkout process at paypal.com. @johnwilander
  • <form action="http://3rdparty.net"></form><img src="http://3rdparty.net"> The img tag has been used heavily for<script src="http://3rdparty.net"></script> cross-origin web tracking such as Google Analytics and Omniture. @johnwilander
  • Image srchttp://www.google-analytics.com/__utm.gif?utmwv=5.3.8&utms=1&utmn=1854976096&utmhn=appsandsecurity.blogspot.se&utmcs=UTF-8&utmsr=1920x1200&utmvp=1268x500&utmsc=24-bit&utmul=sv&utmje=1&utmfl=11.5%20r31&utmdt=Apps%20and%20Security&utmhid=2120874108&utmr=-&utmp=%2F&utmac=UA-6984098-5&utmcc=__utma%3D60396157.1187947367.1352854596.1353863861.1353882126.6%3B%2B__utmz%3D60396157.1352933082.2.2.utmcsr%3Dgoogle%7Cutmccn%3D(organic)%7Cutmcmd%3Dorganic%7Cutmctr%3D(not%2520provided)%3B&utmu=q~Query string parametersutmwv:5.3.8utms:1utmn:1854976096utmhn:appsandsecurity.blogspot.seutmcs:UTF-8utmsr:1920x1200utmvp:1268x500utmsc:24-bitutmul:svutmje:1utmfl:11.5 r31utmdt:Apps and Securityutmhid:2120874108utmr:-utmp:/utmac:UA-6984098-5utmcc:__utma=60396157.1187947367.1352854596.1353863861.1353882126.6;+__utmz=60396157.1352933082.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided);utmu:q~ @johnwilander
  • The script tag became the workhorse<form action="http://3rdparty.net"></form> for Ajax-like cross-origin sharing by means of the popular jsonp hack.<img src="http://3rdparty.net"><script src="http://3rdparty.net"></script> @johnwilander
  • Jsonp =Json with Padding (should be ”Json, Please?”) @johnwilander
  • Jsonp<html><script> function receive(data) { var json = JSON.parse(data); ... maindomain.com };</script></html> 3rdparty.net @johnwilander
  • Jsonp <html> <script> function receive(data) { var json = JSON.parse(data);Inserts a new script element to ... }; maindomain.comretrieve data cross-domain </script> </html> 3rdparty.net @johnwilander
  • Jsonp <html> <script> function receive(data) { var json = JSON.parse(data);Inserts a new script element to ... }; maindomain.comretrieve data cross-domain. </script> <script src=”3rdparty.net/ getData?cb=receive”></script> </html> 3rdparty.net @johnwilander
  • Jsonp<html><script> function receive(data) { var json = JSON.parse(data); ... maindomain.com };</script><script src=”3rdparty.net/getData?cb=receive”></script></html> 3rdparty.net @johnwilander
  • Jsonp<html><script> function receive(data) { var json = JSON.parse(data); ... maindomain.com };</script> The third party domain ”pads” the<script src=”3rdparty.net/getData?cb=receive”></script> response data with a call to the given callback function.</html> 3rdparty.net @johnwilander
  • Jsonp<html><script> function receive(data) { var json = JSON.parse(data); ... maindomain.com };</script> receive({<script src=”3rdparty.net/ ”prop1”: ”data”, ”prop2”: ”data”,getData?cb=receive”></script> ”prop3”: ”data”, ”prop4”: ”data” });</html> 3rdparty.net @johnwilander
  • Jsonp<html><script> function receive(data) { var json = JSON.parse(data); ... maindomain.com };</script> { ”prop1”: ”data”, receive({ ”prop2”: ”data”, ”prop1”: ”data”, ”prop3”: ”data”, ”prop2”: ”data”, ”prop4”: ”data” ”prop3”: ”data”, } ”prop4”: ”data” });</html> 3rdparty.net @johnwilander
  • Jsonp <html> <script> function receive(data) { var json = JSON.parse(data); ... maindomain.com }; </script> { ”prop1”: ”data”, receive({ ”prop2”: ”data”, ”prop1”: ”data”, ”prop3”: ”data”, ”prop2”: ”data”, ”prop4”: ”data” ”prop3”: ”data”, } ”prop4”: ”data” });Data is fetched asynchronously, </html> 3rdparty.netcross-domain. @johnwilander
  • Jsonp example: Blogspot Integrationhttp://johnwilander.blogspot.com/feeds/posts/default?callback=yourCallback&alt=json-in-script&start-index=1&max-results=5 @johnwilander
  • Jsonp example: Blogspot Integrationhttp://johnwilander.blogspot.com/feeds/posts/default?callback=yourCallback&alt=json-in-script&start-index=1&max-results=5 @johnwilander
  • Jsonp example: Blogspot Integrationhttp://johnwilander.blogspot.com/feeds/posts/default?callback=yourCallback&alt=json-in-script&start-index=1&max-results=5 @johnwilander
  • Jsonp example: Blogspot Integrationhttp://johnwilander.blogspot.com/feeds/posts/default?callback=yourCallback&alt=json-in-script&start-index=1&max-results=5 Just paste the above in your browser and run @johnwilander
  • jQuerys ”crossDomain” Ajax is Jsonp http://api.jquery.com/jQuery.ajax/ @johnwilander
  • Jsonp Is Inherently DangerousBenign server response: givenCallback({”prop1”: ”val1”});Compromised server response: givenCallback({”prop1”: ”val1”}); evilCode(); moreEvilCode(); @johnwilander
  • Jsonp Is Inherently Dangerous Note that response:Benign server a client doing jsonp calls has no chance to see/filter the reponse before it’s givenCallback({”prop1”: ”val1”}); executed.Compromised server blindly trust whatever The client has to response: code is returned. givenCallback({”prop1”: ”val1”}); evilCode(); moreEvilCode(); @johnwilander
  • Jsonp and CSRFAlso, all relevant cookies for the Jsonp serviceare sent with the request opening up for non-blind CSRF. Non-blind as in the attacker gettingthe response in full. @johnwilander
  • Demo jsonp @johnwilander
  • Then there is thedocument.domain trick. @johnwilander
  • main.1-liner.org other.1-liner.org @johnwilander
  • main.1-liner.org other.1-liner.org @johnwilander
  • main.1-liner.org other.1-liner.org @johnwilander
  • main.1-liner.org Same-origin policy prohibits even other.1-liner.org different subdomains from interacting @johnwilander
  • main.1-liner.org document.domain = ”1-liner.org”; other.1-liner.org document.domain = ”1-liner.org”; @johnwilander
  • main.1-liner.org document.domain = ”1-liner.org”; other.1-liner.org document.domain = ”1-liner.org”; @johnwilander
  • main.1-liner.org But … document.domain = ”1-liner.org”; main.1- liner.org @johnwilander
  • Demodocument.domain @johnwilander
  • In summary,web integration used to be all-or-nothing. @johnwilander
  • Part 2New IntegrationTechnologies @johnwilander
  • CORS var req = new XMLHttpRequest(); req.open(method, crossDomainUrl); req.send();Sandboxed iframes <iframe src="http://3rdparty.net" sandbox="allow-scripts"></iframe>postMessage API otherFrameOrWindow.postMessage( ’{"action": "purchase", "item": 34443}’, "http://3rdparty.net"); @johnwilander
  • Cross-Origin Resource Sharing, CORS 15+ 22+ 3.2+ 10+ 5.1+ 12+ 2.1+Partial support in IE8 and IE9 http://caniuse.com/#search=cors @johnwilander
  • CORS is basicallycross-origin Ajax @johnwilander
  • CORS• The server has to authorize requests in response headers: Access-Control-Allow-Origin allowed.domain.com• HTTP GET and POST are like normal Ajax• Other HTTP methods or GET and POST with custom headers require a preflight• The client has to explicitly send cookies: xhr.withCredentials = true; @johnwilander
  • CORS-Unaware ServerLets see what 2012 lookslike if we are still running a … @johnwilander
  • CORS-Unaware Server Client Server Looks like No cookies a normal GET. Ajax GET Has a reliable Origin header.If no allowing If no authori-CORS header zation logic isclient gets no present it justresponse. responds. @johnwilander
  • CORS-Unaware Server Client Server Looks like No cookies a normal POST. Ajax POST Has a reliable Origin header.If no allowing If no authori-CORS header zation logic isclient gets no present it justresponse. responds. @johnwilander
  • CORS-Unaware Server Client Server Looks like aAjax + Cookies normal request.withCredentials =true; Has a reliable Origin header.If no allowing If no authori-CORS header zation logic isclient gets no present it justresponse. responds. @johnwilander
  • CORS-Unaware Server Client Server OPTIONSAjax +setRequestHeader( Preflight request request withX-Requested-With, Access-Control-XMLHttpRequest); Request-Method: GET/POSTIf no allowing If no authori-CORS header zation logic isclient never present it justsends request. responds. @johnwilander
  • CORS-Aware Server Client Server Looks like aAjax + Cookies normal request.withCredentials =true; Has a reliable Origin header.If allowing Authorizes theCORS header calling originclient gets the and includes Access-Control-response. Allow-Origin @johnwilander
  • This means …• Attackers can now do CSRF without img tags or form posting.• Servers that don’t check origin headers have no clue it’s a cross-origin Ajax call.• Custom headers including the Ajax header are effectively dead in the CORS case since developers want to avoid preflights. @johnwilander
  • DEMO CORS @johnwilander
  • Sandboxed iframes 17+ 22+ 4.2+ 10+ 5.1+ No 2.2+ Rumored to supportnot be there yet http://caniuse.com/#feat=iframe-sandbox @johnwilander
  • Sandboxed iframemain.1-liner.org <iframe src=”main.1-liner.org” sandbox> <script></script> <form></form> </iframe> @johnwilander
  • Sandboxed iframemain.1-liner.org <iframe src=”main.1-liner.org” sandbox=”allow-same- origin”> <script></script> <form></form> </iframe> @johnwilander
  • Sandboxed iframemain.1-liner.org <iframe src=”main.1-liner.org” sandbox=”allow-same- origin allow-scripts”> <script></script> <form></form> </iframe> @johnwilander
  • Sandboxed iframemain.1-liner.org <iframe src=”main.1-liner.org” sandbox=”allow-same- origin allow-scripts allow-forms”> <script></script> <form></form> </iframe> @johnwilander
  • DEMO Sandboxed iframe @johnwilander
  • postMessage 15+ 22+ 3.2+ Partial 5.1+ 12+ 2.1+support inIE8 – IE10 http://caniuse.com/#search=postMessage @johnwilander
  • postMessage• Allows string-based communication between frames and windows• You need a handle to the target to be able to send a message• The recipient whitelists origins from which it accepts messages @johnwilander
  • postMessage// Sending messages requires a handle to the receiving endvar popup = window.open("http://other.1-liner.org", "_blank");popup.postMessage("Luke, I am your father.", "http://other.1-liner.org");// Receiving messages requires an event listenerreceiveMessage = function(event) { if (event.origin !== "http://other.1-liner.org") { return; } console.log(event.data);}window.addEventListener("message", receiveMessage, false); @johnwilander
  • postMessage// Sending messages requires a handle to the receiving endvar popup = window.open("http://other.1-liner.org", "_blank");popup.postMessage("Luke, I am your father.", "http://other.1-liner.org");// Receiving messages requires an event listener Handle to Target originreceiveMessage = function(event) { if (event.origin !== "http://other.1-liner.org") { receiving return; makes sure } window or console.log(event.data); the window} frame or framewindow.addEventListener("message", receiveMessage, false); hasn’t been redirected @johnwilander
  • postMessage// Sending messages requires a handle to the receiving endvar popup = window.open("http://other.1-liner.org", "_blank");popup.postMessage("Luke, I am your father.", "http://other.1-liner.org");// Receiving messages requires an event listenerreceiveMessage = function(event) { if (event.origin !== "http://other.1-liner.org") { return; } console.log(event.data); Receiving} event listenerwindow.addEventListener("message", receiveMessage, false); has to check the message comes from a trusted origin @johnwilander
  • DEMO postMessage @johnwilander
  • Part 3How To Use theTechnologies Securely @johnwilander
  • First stop using …• Jsonp• document.location trick• img tag trick @johnwilander
  • Implement CORS Server-Side Now Client ServerAjax + Cookies Always checkwithCredentials =true; origin header.If allowing Authorize theCORS header calling originclient gets the based on aresponse. whitelist. @johnwilander
  • Bad Web Architecture CSS JavaScript HTML CSS HTML JavaScript JavaScript HTML CSS @johnwilander
  • Good Web Architecture CSS on fileImport CSS HTML JavaScript on file JavaScript @johnwilander
  • A good separation ofcontent, code, and style allows for CSP. @johnwilander
  • But our legacyapplications are a mess. @johnwilander
  • Placing legacy web and third party web in iframes allowsiframe the new code to run CSS with CSP. JavaScript HTML CSS HTML JavaScript JavaScript HTML CSS @johnwilander
  • Then set themain.1-liner.org sandbox directive without allow- Sandboxed iframe same-origin to main.1-liner.org … or … CSS leverage the same- JavaScript 3rdparty.net HTML origin policy for CSS HTML JavaScript protection from vulnerabilities in JavaScript HTML CSS legacy or third party code. @johnwilander
  • A backwardsmain.1-liner.org compatible alternative is to iframe move legacy legacy.1-liner.org CSS code to another JavaScript HTML subdomain to CSS HTML JavaScript leverage the same- origin policy for JavaScript protection from HTML CSS vulnerabilities in legacy code. @johnwilander
  • But beware.new.1-liner.org Legacy code typically doesn’t iframe relocate main.1-liner.org CSS gracefully. So you JavaScript HTML might have to CSS HTML JavaScript keep its domain and get a new JavaScript HTML CSS subdomain for your new code. @johnwilander
  • Use themain.1-liner.org postMessage API for communicating postMessage Sandboxed iframe between your main.1-liner.org … or … CSS iframes and your JavaScript 3rdparty.net HTML main window. CSS HTML JavaScript JavaScript HTML CSS @johnwilander
  • main.1-liner.org postMessage Sandboxed iframe main.1-liner.org CSS CORS from/ … or … to JavaScript 3rdparty.net HTML 3rdparty .net CSS HTML JavaScript Finally, use CORS when JavaScript retrieving content from third HTML CSS parties and make sure to encode it right before injecting it to the DOM. @johnwilander
  • Thanks! @johnwilander