dedacota: toward preventing server-side xss via automatic code and data separation
DESCRIPTION
Talk I gave at the ACM Conference on Computer and Communications Security (CCS) 2013 on the paper "deDacota: Toward Preventing Server-Side XSS via Automatic Code and Data Separation" which describes an approach to solving Cross-Site Scripting (XSS) vulnerabilities via applying the security principles of Code and Data separation. The paper is located here: http://cs.ucsb.edu/~adoupe/static/dedacota-ccs2013.pdfTRANSCRIPT
deDacota: Toward Preventing Server-Side XSS via Automatic
Code and Data SeparationAdam Doupé, Weidong Cui€, Mariusz H. Jakubowski€, Marcus
Peinado€, Christopher Kruegel, and Giovanni Vigna
University of California, Santa Barbara€Microsoft Research
CCS 2013 – 11/7/13
Doupé - 11/7/13
XSS Vulnerabilities Still Exist Today
Doupé - 11/7/13
Doupé - 11/7/13Courtesy of Ashar Javed
Doupé - 11/7/13
Test.aspx
<html><body><p>Hello <%= this.Name %></p></body>
</html>
Doupé - 11/7/13
http://example.com/Test.aspx?name=adam
Ask Test.dll for output
<html> <body> <p>Hello <%= this.Name %></p> </body></html>
Doupé - 11/7/13
http://example.com/Test.aspx?name=adam
Ask Test.dll for output
<html> <body> <p>Hello adam</p> </body></html>
Doupé - 11/7/13
http://example.com/Test.aspx?name=adam
Ask Test.dll for output
<html> <body> <p>Hello adam</p> </body></html>
Doupé - 11/7/13
http://example.com/Test.aspx?name=adam
Ask Test.dll for output
<html> <body> <p>Hello adam</p> </body></html>
Doupé - 11/7/13
http://example.com/Test.aspx?name=adam
Ask Test.dll for output
<html> <body> <p>Hello adam</p> </body></html>
Doupé - 11/7/13
Test.aspxhttp://example.com/Test.aspx?name=<script>alert("xss");</script>
<html><body>
<p>Hello <%= this.Name %></script></p>
</body></html>
Doupé - 11/7/13
Test.aspxhttp://example.com/Test.aspx?name=<script>alert("xss");</script>
<html><body>
<p>Hello <script>alert("xss"); </script></p>
</body></html>
Doupé - 11/7/13
Test.aspxhttp://example.com/Test.aspx?name=<script>alert("xss");</script>
<html><body>
<p>Hello <script>alert("xss"); </script></p>
</body></html>
Doupé - 11/7/13
XSS – Impact• Steal cookies
• Perform actions as user
• Exploit user’s browser
• Fake login form
Doupé - 11/7/13
Fixing XSS – Sanitization<html>
<body><p>Hello <%= HtmlEncode(this.Name) %></p></body>
</html>
Doupé - 11/7/13
Fixing XSS – Sanitization<html>
<body><p>Hello <%= HtmlEncode(this.Name) %></p></body>
</html>
<script>alert("xss");</script>
<script>alert("xss");</script>
Doupé - 11/7/13
XSS as Input Validation
Doupé - 11/7/13
XSS as Input ValidationProblem Research
Find All Paths WWW 2004, USENIX 2005, Oakland 2006
Many Different Contexts CCS 2011, CCS 2011
Is Sanitization Correct? Oakland 2008, USENIX 2011
Parsing Quirks Oakland 2009
Doupé - 11/7/13
XSS as Input ValidationProblem Research
Find All Paths WWW 2004, USENIX 2005, Oakland 2006
Different Context CCS 2011, CCS 2011
Is Sanitization Correct? Oakland 2008, USENIX 2011
Parsing Quirks Oakland 2009
Doupé - 11/7/13
XSS as Input ValidationProblem Research
Find All Paths WWW 2004, USENIX 2005, Oakland 2006
Different Context CCS 2011, CCS 2011
Is Sanitization Correct? Oakland 2008, USENIX 2011
Parsing Quirks Oakland 2009
Doupé - 11/7/13
XSS as Input ValidationProblem Research
Find All Paths WWW 2004, USENIX 2005, Oakland 2006
Different Context CCS 2011, CCS 2011
Is Sanitization Correct? Oakland 2008, USENIX 2011
Parsing Quirks Oakland 2009, CCS 2013
Doupé - 11/7/13
XSS as Input ValidationProblem Research
Find All Paths WWW 2004, USENIX 2005, Oakland 2006
Different Context CCS 2011, CCS 2011
Is Sanitization Correct? Oakland 2008, USENIX 2011
Parsing Quirks Oakland 2009, CCS 2013
We want to fundamentally solve XSS vulnerabilities
Doupé - 11/7/13
Another Example<html>
<body><script>
alert("welcome to example.com!");
</script><p>Hello <%= this.Name %></p>
</body></html>
Doupé - 11/7/13
Another Example<html>
<body><script>
alert("welcome to example.com!");
</script><p>Hello <%= this.Name %></p>
</body></html>
Developer indented for this code to be executed on the browser
Doupé - 11/7/13
Another Examplehttp://example.com/Test.aspx?name=<script>alert("xss");</script>
<html><body>
<script>alert("welcome to
example.com!");</script><p>Hello <%= this.Name %>
</p></body>
</html>
Doupé - 11/7/13
Another Examplehttp://example.com/Test.aspx?name=<script>alert("xss");</script>
<html><body>
<script>alert("welcome to
example.com!");</script><p>Hello
<script>alert("xss");</script> </p></body>
</html>
Doupé - 11/7/13
The Fundamental Problemhttp://example.com/Test.aspx?name=<script>alert("xss");</script>
<html><body>
<script>alert("welcome to
example.com!");</script><p>Hello
<script>alert("xss");</script> </p></body>
</html>
Developer indented for this code to be executed on the browser
Developer did not intend for this code to be executed on the browser
Doupé - 11/7/13
The Fundamental Problemhttp://example.com/Test.aspx?name=<script>alert("xss");</script>
<html><body>
<script>alert("welcome to
example.com!");</script><p>Hello
<script>alert("xss");</script> </p></body>
</html>
Developer indented for this code to be executed on the browser
Developer did not intend for this code to be executed on the browser
The browser can’t tell the difference!
Doupé - 11/7/13
The Fundamental Solution
<html> <body> <script> alert("welcome to example.com!"); </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
CodeData
Doupé - 11/7/13
The Fundamental Solution
<html> <body> <script> alert("welcome to example.com!"); </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
CodeDataTo fundamentally solve XSS
vulnerabilities, we must apply the basic security principles of Code
and Data separation!
Doupé - 11/7/13
Content Security Policy (CSP)• Mechanism for the website to communicate a policy to the browser about
what JavaScript to execute• The browser then enforces this policy• Supported by many modern browsers (68% of users use one of these
browsers – Firefox– Chrome– IE (10)– Safari– Opera– iOS– Android
Doupé - 11/7/13
Content Security Policy
<html> <body> <script> alert("welcome to example.com!"); </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
Code
DataContent-Security-Policy: script-src http://example.com/0cc111eb135.js
Doupé - 11/7/13
Content Security Policy
<html> <body> <script src="0cc111eb135.js"> </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
Code
DataContent-Security-Policy: script-src http://example.com/0cc111eb135.js
Doupé - 11/7/13
Code and Data Separation• Code and Data separation from start
– No legacy applications
• Manually rewrite application– Difficult and error-prone (HotSec 2011)
deDacota: Automatically separate code and data of a web application
Doupé - 11/7/13
Threat Model• Benign web application
– The developer has not obfuscated the web application
• Server-side XSS– Our approach will only address traditional XSS, in other words,
XSS where the resulting bug is in the server-side code
• Inline JavaScript – For the deDacota prototype, we focused only on inline JavaScript– We ignore JavaScript in HTML attributes and CSS
Doupé - 11/7/13
DESIGN
Doupé - 11/7/13
deDacota Process
Approximate HTML Output
Extract Inline JavaScript
Rewrite Web Application
Doupé - 11/7/13
deDacota Process
Approximate HTML Output
Extract Inline JavaScript
Rewrite Web Application
The goal is to rewrite the web application so that it is
semantically equivalent yet separates the code and data.
Doupé - 11/7/13
Approximate HTML Output<%@ Page Language="C#" CodeBehind="CodeBehind.cs" Inherits="Test" %>
<html><body>
<p>Hello <%= this.Name %></p><%= Scripts() %>
</body></html>
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
The goal here is to create a graph that approximates the HTML
content of the web page. We use static analysis techniques to
construct the graph.
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<html><body><p>"
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
this.Name
"<html><body><p>"
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
this.Name
"<html><body><p>"
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
this.Name
"<html><body><p>"
Here we need to analyze the control flow of the application,
which means following the control flow into the Scripts()
method.
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
this.Name
"<html><body><p>"
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
this.Name
"<html><body><p>"
Here we encounter string concatenation, which our analysis
is able to handle.
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
Now that we have constructed the approximation graph, we must determine what is being
output by each node in the graph. Here we use data-flow analysis
and points-to analysis.
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
<html><body><p>
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
<html><body><p>
In this case, Request.QueryString["name"]is statically undecidable
because it comes from user input. In the approximation graph we
represent this as a * which means the output at this node could be
anything.
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
<html><body><p>
*
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
<html><body><p>
*
<script>alert('
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
<html><body><p>
*
<script>alert('
2013
Doupé - 11/7/13
Approximate HTML Outputclass test_aspx : System.Web.UI.Page {
public test_aspx () {this.Name = Request.QueryString["name"];this.Year = "2013";}protected void Render(HtmlTextWriter writer) {writer.write("<html><body><p>");writer.write(this.Name);writer.write(Scripts());writer.write("</p></body></html>");}protected string Scripts() {return "<script>alert('" + this.Year + "');</script>";}
}
"<script>alert('"
this.Year
this.Name
"<html><body><p>"
"');</script>"
<html><body><p>
*
<script>alert('
2013
');</script>
Doupé - 11/7/13
<html><body><p>
*
<script>alert('
2013
');</script>
</p></body></html>
Doupé - 11/7/13
<html><body><p>
*
<script>alert('
2013
');</script>
</p></body></html>
This approximation graph contains a static approximation of
the HTML content of the web page. Any path through this
graph is one possible output of the page.
Doupé - 11/7/13
In this example approximation graph from a real-world application, the branch in the graph comes from a
conditional branch in the control-flow of the application.
Doupé - 11/7/13
Statically undecidable content, represented here as a *, can come from two different areas:
1. Statically undecidable according to the static analysis.2. To make our analysis conservative, we treat all loops as
outputting a *, because we cannot statically determine how many times a loop will execute.
Doupé - 11/7/13
Extract Inline JavaScript
Doupé - 11/7/13
In the second step, we simply extract the inline JavaScript (aka the developer intended code) from the approximation
graph.
Doupé - 11/7/13
Rewrite Web Application
<html> <body> <script> alert("welcome to example.com!"); </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
Doupé - 11/7/13
Rewrite Web Application
<html> <body> <script src="0cc111eb135.js"> </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
Code
DataContent-Security-Policy: script-src http://example.com/0cc111eb135.js
Doupé - 11/7/13
Rewrite Web Application
<html> <body> <script src="0cc111eb135.js"> </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
Code
DataContent-Security-Policy: script-src http://example.com/0cc111eb135.js
At this point, if the inline JavaScript code is static, we have
protected the application. No attacked data in the Data
segment will ever be interpreted as Code.
Doupé - 11/7/13
Rewrite Web Application
<html> <body> <script src="0cc111eb135.js"> </script> <p>Hello <%= this.Name %> </p> </body></html>
alert("welcome to example.com!");
Code
DataContent-Security-Policy: script-src http://example.com/0cc111eb135.js
Unfortunately, developers sometimes dynamically generate the Code of an application. If this
happens with untrusted Data, there can still be a XSS
vulnerability.
Doupé - 11/7/13
Dynamic Inline JavaScript
<html> <script> var username = "<%= Username %>"; </script></html>
Doupé - 11/7/13
Dynamic Inline JavaScript
<html> <script> var username = "<%= Username %>"; </script></html>
var username = "<%= Username %>";
CodeData
Here, the developer has chosen to dynamically generate the Code from untrusted data.
Doupé - 11/7/13
Dynamic Inline JavaScript
<html> <script> var username = "<%= Username %>"; </script></html>
var username = "<%= Username %>";
CodeData
var username = "*";
Doupé - 11/7/13
Dynamic Inline JavaScript
<html> <script> var username = "<%= Username %>"; </script></html>
var username = "<%= Username %>";
CodeData
var username = "*";
We developed a technique to safely transform cases of dynamic inline
JavaScript. If the statically undecidable content is used in a known JavaScript
context (JavaScript string or comment), we can safely rewrite the application. We call these cases “safe dynamic
inline JavaScript.”
Doupé - 11/7/13
EVALUATION
Doupé - 11/7/13
ApplicationsApplication Lines of Code Known
Vulnerability
BugTracker.NET 35,674 CVE-2010-3266
BlogEngine.NET 29,512 CVE-2008-6476
BlogSA.NET 6,994 CVE-2009-0814
ScrewTurn Wiki 12,155 CVE-2008-3483
WebGoat.NET 11,993 2 Intentional
ChronoZoom 21,261 N/A
Doupé - 11/7/13
Evaluation• Security
– Crafted exploits for applications with known vulnerabilities– Transformed applications, along with CSP, blocked the
exploits
• Functional correctness– ChronoZoom had 160 JavaScript tests and all passed
after the transformation– Manually browsed the application and source code
looking for missing inline JavaScript
Doupé - 11/7/13
BugTracker.NET BlogEngine.NET BlogSA.NET ScrewTurn Wiki WebGoat.NET ChronoZoom0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
Unsafe DynamicSafe DynamicStatic
Doupé - 11/7/13
BugTracker.NET BlogEngine.NET BlogSA.NET ScrewTurn Wiki WebGoat.NET ChronoZoom0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
Unsafe DynamicSafe DynamicStatic
Here we are going to look at what percentage of the inline
JavaScript in each application is either: static, safe dynamic, or
unsafe dynamic.
Doupé - 11/7/13
BugTracker.NET BlogEngine.NET BlogSA.NET ScrewTurn Wiki WebGoat.NET ChronoZoom0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
41
4
10 27
6 5Unsafe DynamicSafe DynamicStatic
Doupé - 11/7/13
BugTracker.NET BlogEngine.NET BlogSA.NET ScrewTurn Wiki WebGoat.NET ChronoZoom0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
41
4
10 27
6 5
3
10
14
Unsafe DynamicSafe DynamicStatic
Doupé - 11/7/13
BugTracker.NET BlogEngine.NET BlogSA.NET ScrewTurn Wiki WebGoat.NET ChronoZoom0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
41
4
10 27
6 5
3
10
14
Unsafe DynamicSafe DynamicStatic
In these safe dynamic situations, we are able to safely transform the dynamic inline JavaScript code.
Doupé - 11/7/13
BugTracker.NET BlogEngine.NET BlogSA.NET ScrewTurn Wiki WebGoat.NET ChronoZoom0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
41
4
10 27
6 5
3
10
14
2
41 4
Unsafe DynamicSafe DynamicStatic
Doupé - 11/7/13
BugTracker.NET BlogEngine.NET BlogSA.NET ScrewTurn Wiki WebGoat.NET ChronoZoom0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
41
4
10 27
6 5
3
10
14
2
41 4
Unsafe DynamicSafe DynamicStaticIn cases of unsafe dynamic inline JavaScript, we alert the
developer that the transformation could potentially contain an XSS vulnerability. After the developer confirms the
absence of an XSS vulnerability in the unsafe dynamic inline JavaScript, then the application is guaranteed free of
XSS vulnerabilities.
Doupé - 11/7/13
Limitations• Might miss inline JavaScript
– Loops– Dynamic code execution
• Does not handle HTML attributes and CSS
Doupé - 11/7/13
Summary
• Code and Data separation necessary to
prevent XSS
• deDacota can automatically separate
Code and Data of web application
• deDacota works in practice
Doupé - 11/7/13
DEDACOTA: TOWARD PREVENTING SERVER-SIDE XSS VIA AUTOMATIC CODE AND DATA SEPARATION
Adam Doupé
Email: [email protected]: @adamdoupe