Difference between revisions of "Reviewing Code for Cross-site scripting"

From OWASP
Jump to: navigation, search
(Related Security Activities)
(readability improvements)
(20 intermediate revisions by 4 users not shown)
Line 1: Line 1:
[[OWASP Code Review Guide Table of Contents]]
+
{{LinkBar
 
+
  | useprev=PrevLink | prev=Reviewing Code for Data Validation | lblprev=
 +
  | usemain=MainLink | main=OWASP Code Review Guide Table of Contents | lblmain=Table of Contents
 +
  | usenext=NextLink | next=Reviewing Code for Cross-Site Request Forgery | lblnext=
 +
}}
  
 
==Overview==
 
==Overview==
Cross-site scripting (XSS) attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user in the output it generates without validating or encoding it.
+
Cross-site scripting (XSS) attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application reflects user input without validation or encoding.
[[Category:FIXME|Is this a good short description of this?]]
+
 
+
==Threat Modeling==
+
* Talk about the threat modeling ingredients(PTAVC) and discuss their relationship using threat modeling language
+
* Talk about the various factors on its likelihood, impact and severity
+
This section needs to be added.
+
[[Category:FIXME|need this section written]]
+
  
 
==Related Security Activities==
 
==Related Security Activities==
Line 17: Line 13:
 
===Description of Cross-site Scripting Vulnerabilities===
 
===Description of Cross-site Scripting Vulnerabilities===
  
See the OWASP article on [[Cross-site scripting]] Vulnerabilities.
+
See the OWASP article on [[Cross-site Scripting (XSS)]] Vulnerabilities.
  
 
===How to Avoid Cross-site scripting  Vulnerabilities===
 
===How to Avoid Cross-site scripting  Vulnerabilities===
  
See the [[:Category:OWASP Guide Project|OWASP Guide]] article on [[Phishing|Phishing]].
+
See the [[:Category:OWASP Guide Project|OWASP Development Guide]] article on [[Phishing]].
 +
 
 +
See the [[:Category:OWASP Guide Project|OWASP Development Guide]] article on [[Data Validation]].
  
 
===How to Test for Cross-site scripting  Vulnerabilities===
 
===How to Test for Cross-site scripting  Vulnerabilities===
Line 27: Line 25:
 
See the [[:Category:OWASP Testing Project|OWASP Testing Guide]] article on how to [[Testing for Cross site scripting|Test for Cross site scripting]] Vulnerabilities.
 
See the [[:Category:OWASP Testing Project|OWASP Testing Guide]] article on how to [[Testing for Cross site scripting|Test for Cross site scripting]] Vulnerabilities.
  
==To learn more==
+
 
[[Alternate XSS Syntax]]
+
  
 
==Vulnerable Code example==
 
==Vulnerable Code example==
If the text inputted by the user is reflected back and has not been data validated, the browser shall interpret the inputted script as part of the mark up, and execute the code accordingly.
+
If the text inputted by the user is reflected back without proper encoding, the browser will interpret the inputted script as part of the mark up, and execute the code accordingly.  
  
To mitigate this type of vulnerability we need to perform a number of security tasks in our code:
+
To mitigate this type of vulnerability we need to perform a number of security tasks in our code:  
  
 
# Validate data
 
# Validate data
Line 78: Line 75:
  
 
   
 
   
The text above shows some common mistakes in the development of this struts action class.
+
The text above shows some common mistakes in the development of this struts action class. First, the data passed in the HttpServletRequest is placed into a parameter without being validated.  
First, the data passed in the HttpServletRequest is placed into a parameter without being data validated.
+
  
Focusing on XSS we can see that this action class returns a message, ActionMessage, if the function is successful.
+
Focusing on XSS we can see that this action class returns a message, ActionMessage, if the function is successful. If an error the code in the Try/Catch block is executed, the data contained in the HttpServletRequest is returned to the user, unvalidated and exactly in the format in which the user inputted it.  
If an error the code in the Try/Catch block is executed, the data contained in the HttpServletRequest is returned to the user, unvalidated and exactly in the format in which the user inputted it.
+
  
 
  import java.io.*;  
 
  import java.io.*;  
Line 102: Line 97:
  
  
Following is a second example of an XSS vulnerable function. Echoing un-validated user input back to the browser would give a nice large vulnerability footprint.
+
Following is a second example of an XSS vulnerable function. Echoing un-validated user input back to the browser provides a large vulnerability footprint.  
  
 +
===.NET Example (ASP.NET version 1.1 ASP.NET version 2.0)===
  
.NET Example (ASP.NET version 1.1 ASP.NET version 2.0):
+
The server side code for a VB.NET application may have similar functionality.
 
+
The server side code for a VB.NET application may have similar functionality
+
  
 
  ' SearchResult.aspx.vb  
 
  ' SearchResult.aspx.vb  
Line 134: Line 128:
 
  End Class
 
  End Class
  
This is a VB.NET example of a Cross Site Script vulnerable piece of search functionality which echoes back the data inputted by the user. To mitigate against this we need proper data validation and in the case of stored XSS attacks we need to encode known bad (as mentioned before).
+
This is a VB.NET example of a vulnerable piece of search functionality which echoes back the data inputted by the user. To mitigate against this, we need proper data validation and in the case of stored XSS attacks, we need to encode known bad input (as mentioned before). Note that this code might not be vulnerable if the developers use a proper declarative validation (ASPX regexp validator or routine, and validateRequest not set to False).
  
'''Classic ASP Example''' <br />
+
===Classic ASP Example===
Classic ASP is also XSS prone, just as like most Web technologies.
+
Classic ASP is also XSS prone, just like most Web technologies.
 
  <pre>
 
  <pre>
 
  <%
 
  <%
Line 148: Line 142:
  
 
==Protecting against XSS==
 
==Protecting against XSS==
In the .NET framework there are some in-built security functions which can assist in data validation and HTML encoding, namley, ASP.NET 1.1 '''request validation '''feature and '''HttpUtility.HtmlEncode'''.
+
In the .NET framework there are some in-built security functions which can assist in data validation and HTML encoding, namely, ASP.NET 1.1 '''request validation '''feature and '''HttpUtility.HtmlEncode'''.
  
Microsoft in their wisdom state that you should not rely solely on ASP.NET request validation
+
Microsoft in their wisdom state that you should not rely solely on ASP.NET request validation and that it should be used in conjunction with your own data validation, such as regular expressions (mentioned below).  
and that it should be used in conjunction with your own data validation, such as regular expressions (mentioned below).
+
  
The request validation feature is disabled on an individual page by specifying in the page directive
+
The request validation feature is disabled on an individual page by specifying in the page directive.
  
 
   '''<%@ Page validateRequest="false" %>'''
 
   '''<%@ Page validateRequest="false" %>'''
Line 165: Line 158:
 
   <'''pages'''> element with '''validateRequest="false"'''
 
   <'''pages'''> element with '''validateRequest="false"'''
  
So when reviewing code make sure the validateRequest directive is enabled an if not, investigate what method of DV is being used, if any.
+
So when reviewing code, make sure the validateRequest directive is enabled and if not, investigate what method of data validation is being used, if any. Check that ASP.NET Request validation is enabled in '''Machine.config'''.
Check that ASP.NET Request validation Is enabled in '''Machine.config'''
+
 
Request validation is enabled by ASP.NET by default. You can see the following default setting in the '''Machine.config''' file.
 
Request validation is enabled by ASP.NET by default. You can see the following default setting in the '''Machine.config''' file.
  
 
   '''<pages validateRequest="true" ... /> '''
 
   '''<pages validateRequest="true" ... /> '''
  
HTML Encoding:
+
'''HTML Encoding:'''
  
 
Content to be displayed can easily be encoded using the HtmlEncode function. This is done by calling:
 
Content to be displayed can easily be encoded using the HtmlEncode function. This is done by calling:
Line 177: Line 169:
 
   '''Server.HtmlEncode(string)'''
 
   '''Server.HtmlEncode(string)'''
  
Using the html encoder example for a form:
+
Using the HTML encoder example for a form:
  
 
Text Box: <%@ Page Language="C#" ValidateRequest="false" %>  
 
Text Box: <%@ Page Language="C#" ValidateRequest="false" %>  
  
<script runat="server">  
+
  <script runat="server">  
void searchBtn _Click(object sender, EventArgs e) {  
+
  void searchBtn _Click(object sender, EventArgs e) {  
Response.Write(HttpUtility.HtmlEncode(inputTxt.Text)); }  
+
  Response.Write(HttpUtility.HtmlEncode(inputTxt.Text)); }  
</script>  
+
  </script>  
<html>  
+
  <html>  
<body>  
+
  <body>  
<form id="form1" runat="server">  
+
  <form id="form1" runat="server">  
<div>
+
  <asp:TextBox ID="inputTxt" Runat="server" TextMode="MultiLine" Width="382px" Height="152px">  
<asp:TextBox ID="inputTxt" Runat="server" TextMode="MultiLine" Width="382px" Height="152px">  
+
  </asp:TextBox>  
</asp:TextBox>  
+
  <asp:Button ID="searchBtn" Runat="server" Text="Submit" OnClick=" searchBtn _Click" />  
<asp:Button ID="searchBtn" Runat="server" Text="Submit" OnClick=" searchBtn _Click" />  
+
  </form>  
</div>
+
  </body>  
</form>  
+
  </html>
</body>  
+
</html>
+
  
 
For Classic ASP pages the encoding function is used pretty much the same as in ASP.NET
 
For Classic ASP pages the encoding function is used pretty much the same as in ASP.NET
Line 201: Line 191:
 
  Response.Write Server.HtmlEncode(inputTxt.Text)
 
  Response.Write Server.HtmlEncode(inputTxt.Text)
  
'''Stored Cross Site Script:'''
+
===Stored Cross Site Script===
Using Html encoding to encode potentially unsafe output.:
+
'''Using HTML encoding to encode potentially unsafe output.'''
  
Malicious script can be stored/persisted in a database and shall not execute until retrieved by a user. This can also be the case in bulletin boards and some early web email clients. This incubated attack can sit dormant for a long period of time until a user decides to view the page where the injected script is present. At this point the script shall execute on the users browser:
+
Malicious scripts can be stored/persisted in a database and will not execute until retrieved by a user. This has been seen in bulletin boards and some early webmail applications. This incubated attack can sit dormant for a long period of time until a user decides to view the page where the injected script is present. At this point the script executes on the user’s browser.
  
The original source of input for the injected script may be from another vulnerable application, which is common in enterprise architectures. Therefore the application at hand may have good input data validation but the data persisted may not have been entered via this application per se, but via another application.
+
The original source of input for the injected script may be from another vulnerable application, which is common in enterprise architectures. Therefore the application at hand may have good input data validation but the data persisted may not have been entered via this application per se, but via another application.  
  
In this case we cannot be 100% sure the data to be displayed to the user is 100% safe (as it could of found its way in via another path in the enterprise).
+
In this case we cannot be 100% sure the data to be displayed to the user is safe (as it could have found its way in via another path in the enterprise). The approach to mitigate against this is to ensure that data sent to the browser with the purpose of being displayed literally is not going to be interpreted by the browser as mark-up.
The approach to mitigate against this si to ensure the data sent to the browser is not going to be interpreted by the browser as mark-up and should be treated as user data.
+
  
We encode known bad to mitigate against this “enemy within”. This in effect assures the browser interprets any special characters as data and markup.  
+
We encode known bad to mitigate against this “enemy within”. This, in effect, assures that the browser interprets any special characters as data and markup.  
 
How is this done?
 
How is this done?
 
HTML encoding usually means '''&lt;''' becomes '''&amp;lt;''', '''&gt;''' becomes '''&amp;gt;''', '''&amp;''' becomes '''&amp;amp;''', and '''&quot;''' becomes '''&amp;quot;'''.
 
HTML encoding usually means '''&lt;''' becomes '''&amp;lt;''', '''&gt;''' becomes '''&amp;gt;''', '''&amp;''' becomes '''&amp;amp;''', and '''&quot;''' becomes '''&amp;quot;'''.
  
From To
+
{|
 
+
|-
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;lt;
+
! From !! To
 
+
|-
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;gt;
+
| &lt; || &amp;lt;
 
+
|-
&#40;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&#35;40;
+
| &gt; || &amp;gt;
 
+
|-
&#41;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&#35;41;
+
| &#40; || &amp;&#35;40;
 
+
|-
&#35;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&#35;35;
+
| &#41; || &amp;&#35;41;
 
+
|-
&amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;amp;
+
| &#35; || &amp;&#35;35;
 +
|-
 +
| &amp; || &amp;amp;
 +
|-
 +
| &quot;|| &amp;quot;
 +
|}
  
&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;quot;
+
So, for example, if the application has a string "<script>" and it wants a browser to display it as "<script>", it can first HTML-encode it to the form "&amp;lt;script&amp;gt;" before including it in the web page that gets sent to the browser.
  
So for example the text <script> would be displayed as <script> but on viewing the markup it would be represented by &amp;lt;script&amp;gt;
+
{{LinkBar
 +
  | useprev=PrevLink | prev=Reviewing Code for Data Validation | lblprev=
 +
  | usemain=MainLink | main=OWASP Code Review Guide Table of Contents | lblmain=Table of Contents
 +
  | usenext=NextLink | next=Reviewing Code for Cross-Site Request Forgery | lblnext=
 +
}}
  
 
[[Category:OWASP Code Review Project]]
 
[[Category:OWASP Code Review Project]]

Revision as of 15:03, 22 June 2011

«««« Main
(Table of Contents)
»»»»

Contents

Overview

Cross-site scripting (XSS) attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application reflects user input without validation or encoding.

Related Security Activities

Description of Cross-site Scripting Vulnerabilities

See the OWASP article on Cross-site Scripting (XSS) Vulnerabilities.

How to Avoid Cross-site scripting Vulnerabilities

See the OWASP Development Guide article on Phishing.

See the OWASP Development Guide article on Data Validation.

How to Test for Cross-site scripting Vulnerabilities

See the OWASP Testing Guide article on how to Test for Cross site scripting Vulnerabilities.


Vulnerable Code example

If the text inputted by the user is reflected back without proper encoding, the browser will interpret the inputted script as part of the mark up, and execute the code accordingly.

To mitigate this type of vulnerability we need to perform a number of security tasks in our code:

  1. Validate data
  2. Encode unsafe output
import org.apache.struts.action.*; 
import org.apache.commons.beanutils.BeanUtils; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

public final class InsertEmployeeAction extends Action { 

public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response) throws Exception{ 

// Setting up objects and vairables.

Obj1 service = new Obj1(); 
ObjForm objForm = (ObjForm) form; 
InfoADT adt = new InfoADT (); 
BeanUtils.copyProperties(adt, objForm); 

	String searchQuery = objForm.getqueryString();
	String payload = objForm.getPayLoad();
try { 
service.doWork(adt);  / /do something with the data
ActionMessages messages = new ActionMessages(); 
ActionMessage message = new ActionMessage("success", adt.getName() ); 
messages.add( ActionMessages.GLOBAL_MESSAGE, message ); 
saveMessages( request, messages ); 
request.setAttribute("Record", adt); 
return (mapping.findForward("success"));
}
catch( DatabaseException de ) 
{
ActionErrors errors = new ActionErrors(); 
ActionError error = new ActionError("error.employee.databaseException" + “Payload: “+payload);
errors.add( ActionErrors.GLOBAL_ERROR, error ); 
saveErrors( request, errors ); 
return (mapping.findForward("error: "+ searchQuery)); 
} 
} 
}


The text above shows some common mistakes in the development of this struts action class. First, the data passed in the HttpServletRequest is placed into a parameter without being validated.

Focusing on XSS we can see that this action class returns a message, ActionMessage, if the function is successful. If an error the code in the Try/Catch block is executed, the data contained in the HttpServletRequest is returned to the user, unvalidated and exactly in the format in which the user inputted it.

import java.io.*; 
import javax.servlet.http.*; 
import javax.servlet.*; 

public class HelloServlet extends HttpServlet 
{ 
public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 
{ 

String input = req.getHeader(“USERINPUT”);

PrintWriter out = res.getWriter(); 
out.println(input);  // echo User input.
out.close(); 	
} 
} 


Following is a second example of an XSS vulnerable function. Echoing un-validated user input back to the browser provides a large vulnerability footprint.

.NET Example (ASP.NET version 1.1 ASP.NET version 2.0)

The server side code for a VB.NET application may have similar functionality.

' SearchResult.aspx.vb 
Imports System 
Imports System.Web 
Imports System.Web.UI 
Imports System.Web.UI.WebControls 

Public Class SearchPage Inherits System.Web.UI.Page 

Protected txtInput As TextBox 
Protected cmdSearch As Button 
Protected lblResult As Label Protected 

Sub cmdSearch _Click(Source As Object, _ e As EventArgs) 
	
// Do Search…..
	// …………

lblResult.Text="You Searched for: " & txtInput.Text 

// Display Search Results…..
// …………

End Sub 
End Class

This is a VB.NET example of a vulnerable piece of search functionality which echoes back the data inputted by the user. To mitigate against this, we need proper data validation and in the case of stored XSS attacks, we need to encode known bad input (as mentioned before). Note that this code might not be vulnerable if the developers use a proper declarative validation (ASPX regexp validator or routine, and validateRequest not set to False).

Classic ASP Example

Classic ASP is also XSS prone, just like most Web technologies.

 <%
    ...
    Response.Write "<div class='label'>Please confirm your data</div><br />" 
    Response.Write "Name: " & Request.Form("UserFullName")
    ...
 %>
 

Protecting against XSS

In the .NET framework there are some in-built security functions which can assist in data validation and HTML encoding, namely, ASP.NET 1.1 request validation feature and HttpUtility.HtmlEncode.

Microsoft in their wisdom state that you should not rely solely on ASP.NET request validation and that it should be used in conjunction with your own data validation, such as regular expressions (mentioned below).

The request validation feature is disabled on an individual page by specifying in the page directive.

 <%@ Page validateRequest="false" %>

or by setting ValidateRequest="false" on the @ Pages element.

or in the web.config file:

You can disable request validation by adding a

 <pages> element with validateRequest="false"

So when reviewing code, make sure the validateRequest directive is enabled and if not, investigate what method of data validation is being used, if any. Check that ASP.NET Request validation is enabled in Machine.config. Request validation is enabled by ASP.NET by default. You can see the following default setting in the Machine.config file.

 <pages validateRequest="true" ... /> 

HTML Encoding:

Content to be displayed can easily be encoded using the HtmlEncode function. This is done by calling:

 Server.HtmlEncode(string)

Using the HTML encoder example for a form:

Text Box: <%@ Page Language="C#" ValidateRequest="false" %>

 <script runat="server"> 
 void searchBtn _Click(object sender, EventArgs e) { 
 Response.Write(HttpUtility.HtmlEncode(inputTxt.Text)); } 
 </script> 
 <html> 
 <body> 
 <form id="form1" runat="server"> 
 <asp:TextBox ID="inputTxt" Runat="server" TextMode="MultiLine" Width="382px" Height="152px"> 
 </asp:TextBox> 
 <asp:Button ID="searchBtn" Runat="server" Text="Submit" OnClick=" searchBtn _Click" /> 
 </form> 
 </body> 
 </html>

For Classic ASP pages the encoding function is used pretty much the same as in ASP.NET

Response.Write Server.HtmlEncode(inputTxt.Text)

Stored Cross Site Script

Using HTML encoding to encode potentially unsafe output.

Malicious scripts can be stored/persisted in a database and will not execute until retrieved by a user. This has been seen in bulletin boards and some early webmail applications. This incubated attack can sit dormant for a long period of time until a user decides to view the page where the injected script is present. At this point the script executes on the user’s browser.

The original source of input for the injected script may be from another vulnerable application, which is common in enterprise architectures. Therefore the application at hand may have good input data validation but the data persisted may not have been entered via this application per se, but via another application.

In this case we cannot be 100% sure the data to be displayed to the user is safe (as it could have found its way in via another path in the enterprise). The approach to mitigate against this is to ensure that data sent to the browser with the purpose of being displayed literally is not going to be interpreted by the browser as mark-up.

We encode known bad to mitigate against this “enemy within”. This, in effect, assures that the browser interprets any special characters as data and markup. How is this done? HTML encoding usually means < becomes &lt;, > becomes &gt;, & becomes &amp;, and " becomes &quot;.

From To
< &lt;
> &gt;
( &#40;
) &#41;
# &#35;
& &amp;
" &quot;

So, for example, if the application has a string "<script>" and it wants a browser to display it as "<script>", it can first HTML-encode it to the form "&lt;script&gt;" before including it in the web page that gets sent to the browser.


«««« Main
(Table of Contents)
»»»»