This is a series of Security related articles.
F - 0: Introduction
This article is a part of Cross-Site Scripting (XSS), this is an example of a real high security issue created by Fortify Static Code Scanning.
This is the structure of this article,
- F - 0: Introduction
- F - 1: Overview
- F - 2: Details
- F - 3: Example
- F - 4: Recommendation
- F - 5: The Fix or Suggestion
- F - 6: False Positive Accepted
F - 1: Overview
Reflected XSS is the simplest variety of cross-site scripting. It arises when an application receives data in an HTTP request and includes that data within the immediate response in an unsafe way. Here is a simple example of a reflected XSS vulnerability:
https://insecure-website.com/status?message=All+is+well. <p>Status: All is well.</p>
The application doesn't perform any other processing of the data, so an attacker can easily construct an attack like this:
https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script> <p>Status: <script>/* Bad stuff here... */</script></p>
If the user visits the URL constructed by the attacker, then the attacker's script executes in the user's browser, in the context of that user's session with the application. At that point, the script can carry out any action, and retrieve any data, to which the user has access.
In our case, the code below sends unvalidated data to a web browser on line 378, which can result in the browser executing malicious code.
F - 2: Details
Cross-site scripting (XSS) vulnerabilities occur when:
- Data enters a web application through an untrusted source. In the case of reflected XSS, the untrusted source is typically a web request, while in the case of persisted (also known as stored) XSS it is typically a database or other back-end data store. In this case, the data enters at get_Text() in CSR_UserInfo.aspx.cs on line 43.
- The data is included in dynamic content that is sent to a web user without validation. In this case, the data is sent at Write() in AdminBasePage_Transactions.cs on line 378.
The malicious content sent to the web browser often takes the form of a JavaScript segment, but can also include HTML, Flash or any other type of code that the browser executes. The variety of attacks based on XSS is almost limitless, but they commonly include transmitting private data like cookies or other session information to the attacker, redirecting the victim to web content controlled by the attacker, or performing other malicious operations on the user's machine under the guise of the vulnerable site.
F - 3: Example
Example 1
The following ASP.NET Web Form reads an employee ID number from an HTTP request and displays it to the user.
<script runat="server">
...
EmployeeID.Text = Login.Text;
...
</script>
Where Login and EmployeeID are form controls defined as follows:
<form runat="server">
<asp:TextBox runat="server" id="Login"/>
...
<asp:Label runat="server" id="EmployeeID"/>
</form>
Example 2
The following ASP.NET code segment shows the programmatic way to implement Example 1.
protected System.Web.UI.WebControls.TextBox Login;
protected System.Web.UI.WebControls.Label EmployeeID;
...
EmployeeID.Text = Login.Text;
The code in these examples operates correctly if Login contains only standard alphanumeric text. If Login has a value that includes metacharacters or source code, then the code will be executed by the web browser as it displays the HTTP response.
Initially this might not appear to be much of a vulnerability. After all, why would someone enter a URL which causes malicious code to run on their own computer? The real danger is that an attacker will create the malicious URL, then use email or social engineering tricks in order to lure victims into clicking a link. When the victims click the link, they unwittingly reflect the malicious content through the vulnerable web application and back to their own computers. This mechanism of exploiting vulnerable web applications is known as Reflected XSS.
Example 3
The following ASP.NET Web Form queries a database for an employee with a given employee ID and prints the name corresponding with the ID.
<script runat="server">
...
string query = "select * from emp where id=" + eid;
sda = new SqlDataAdapter(query, conn);
DataTable dt = new DataTable();
sda.Fill(dt);
string name = dt.Rows[0]["Name"];
...
EmployeeName.Text = name;
</script>
Where EmployeeName is a form control defined as follows:
<form runat="server">
...
<asp:Label id="EmployeeName" runat="server">
...
</form>
Example 4
The following ASP.NET code segment is functionally equivalent to Example 3, but implements all of the form elements programmatically.
protected System.Web.UI.WebControls.Label EmployeeName;
...
string query = "select * from emp where id=" + eid;
sda = new SqlDataAdapter(query, conn);
DataTable dt = new DataTable();
sda.Fill(dt);
string name = dt.Rows[0]["Name"];
...
EmployeeName.Text = name;
As in Example 1 and Example 2, these code examples function correctly when the values of name are well-behaved, but they nothing to prevent exploits if the values are not. Again, these can appear less dangerous because the value of name is read from a database, whose contents are apparently managed by the application. However, if the value of name originates from user-supplied data, then the database can be a conduit for malicious content. Without proper input validation on all data stored in the database, an attacker may execute malicious commands in the user's web browser. This type of exploit, known as Persistent (or Stored) XSS, is particularly insidious because the indirection caused by the data store makes it more difficult to identify the threat and increases the possibility that the attack will affect multiple users. XSS got its start in this form with web sites that offered a "guestbook" to visitors. Attackers would include JavaScript in their guestbook entries, and all subsequent visitors to the guestbook page would execute the malicious code.
As the examples demonstrate, XSS vulnerabilities are caused by code that includes unvalidated data in an HTTP response. There are three vectors by which an XSS attack can reach a victim:
- As in Example 1 and Example 2, data is read directly from the HTTP request and reflected back in the HTTP response. Reflected XSS exploits occur when an attacker causes a user to supply dangerous content to a vulnerable web application, which is then reflected back to the user and executed by the web browser. The most common mechanism for delivering malicious content is to include it as a parameter in a URL that is posted publicly or emailed directly to victims. URLs constructed in this manner constitute the core of many phishing schemes, whereby an attacker convinces victims to visit a URL that refers to a vulnerable site. After the site reflects the attacker's content back to the user, the content is executed and proceeds to transfer private information, such as cookies that may include session information, from the user's machine to the attacker or perform other nefarious activities.
- As in Example 3 and Example 4, the application stores dangerous data in a database or other trusted data store. The dangerous data is subsequently read back into the application and included in dynamic content. Persistent XSS exploits occur when an attacker injects dangerous content into a data store that is later read and included in dynamic content. From an attacker's perspective, the optimal place to inject malicious content is in an area that is displayed to either many users or particularly interesting users. Interesting users typically have elevated privileges in the application or interact with sensitive data that is valuable to the attacker. If one of these users executes malicious content, the attacker may be able to perform privileged operations on behalf of the user or gain access to sensitive data belonging to the user.
- A source outside the application stores dangerous data in a database or other data store, and the dangerous data is subsequently read back into the application as trusted data and included in dynamic content.
F - 4: Recommendation
The solution to XSS is to ensure that validation occurs in the correct places and checks are made for the correct properties.
Because XSS vulnerabilities occur when an application includes malicious data in its output, one logical approach is to validate data immediately before it leaves the application. However, because web applications often have complex and intricate code for generating dynamic content, this method is prone to errors of omission (missing validation). An effective way to mitigate this risk is to also perform input validation for XSS.
Web applications must validate their input to prevent other vulnerabilities, such as SQL injection, so augmenting an application's existing input validation mechanism to include checks for XSS is generally relatively easy. Despite its value, input validation for XSS does not take the place of rigorous output validation. An application might accept input through a shared data store or other trusted source, and that data store might accept input from a source that does not perform adequate input validation. Therefore, the application cannot implicitly rely on the safety of this or any other data. This means that the best way to prevent XSS vulnerabilities is to validate everything that enters the application and leaves the application destined for the user.
The most secure approach to validation for XSS is to create an allow list of safe characters that are permitted to appear in HTTP content and accept input composed exclusively of characters in the approved set. For example, a valid username might only include alphanumeric characters or a phone number might only include digits 0-9. However, this solution is often infeasible in web applications because many characters that have special meaning to the browser must be considered valid input after they are encoded, such as a web design bulletin board that must accept HTML fragments from its users.
A more flexible, but less secure approach is to implement a deny list, which selectively rejects or escapes potentially dangerous characters before using the input. To form such a list, you first need to understand the set of characters that hold special meaning for web browsers. Although the HTML standard defines which characters have special meaning, many web browsers try to correct common mistakes in HTML and might treat other characters as special in certain contexts. This is why we do not recommend the use of deny lists as a means to prevent XSS. The CERT(R) Coordination Center at the Software Engineering Institute at Carnegie Mellon University provides the following details about special characters in various contexts [1]:
In the content of a block-level element (in the middle of a paragraph of text),
- "<" is special because it introduces a tag.
- "&" is special because it introduces a character entity.
- ">" is special because some browsers treat it as special, on the assumption that the author of the page intended to include an opening "<", but omitted it in error.
The following principles apply to attribute values:
- In attribute values enclosed in double quotes, the double quotes are special because they mark the end of the attribute value.
- In attribute values enclosed in single quotes, the single quotes are special because they mark the end of the attribute value.
- In attribute values without any quotes, white-space characters, such as space and tab, are special.
- "&" is special when used with certain attributes, because it introduces a character entity.
In URLs, for example, a search engine might provide a link within the results page that the user can click to re-run the search. This can be implemented by encoding the search query inside the URL, which introduces additional special characters:
- Space, tab, and new line are special because they mark the end of the URL.
- "&" is special because it either introduces a character entity or separates CGI parameters.
- Non-ASCII characters (that is, everything greater than 127 in the ISO-8859-1 encoding) are not allowed in URLs, so they are considered to be special in this context.
- The "%" symbol must be filtered from input anywhere parameters encoded with HTTP escape sequences are decoded by server-side code. For example, "%" must be filtered if input such as "%68%65%6C%6C%6F" becomes "hello" when it appears on the web page.
Within the body of a <SCRIPT> </SCRIPT>:
- Semicolons, parentheses, curly braces, and new line characters must be filtered out in situations where text could be inserted directly into a pre-existing script tag.
Server-side scripts
- Server-side scripts that convert any exclamation characters (!) in input to double-quote characters (") on output might require additional filtering.
Other possibilities
- If an attacker submits a request in UTF-7, the special character '<' appears as '+ADw-' and might bypass filtering. If the output is included in a page that does not explicitly specify an encoding format, then some browsers try to intelligently identify the encoding based on the content (in this case, UTF-7).
After you identify the correct points in an application to perform validation for XSS attacks and what special characters the validation should consider, the next challenge is to identify how your validation handles special characters. If special characters are not considered valid input to the application, then you can reject any input that contains special characters as invalid. A second option is to remove special characters with filtering. However, filtering has the side effect of changing any visual representation of the filtered content and might be unacceptable in circumstances where the integrity of the input must be preserved for display.
If input containing special characters must be accepted and displayed accurately, validation must encode any special characters to remove their significance. A complete list of ISO 8859-1 encoded values for special characters is provided as part of the official HTML specification [2].
Many application servers attempt to limit an application's exposure to cross-site scripting vulnerabilities by providing implementations for the functions responsible for setting certain specific HTTP response content that perform validation for the characters essential to a cross-site scripting attack. Do not rely on the server running your application to make it secure. For any developed application, there are no guarantees about which application servers it will run on during its lifetime. As standards and known exploits evolve, there are no guarantees that application servers will continue to stay in sync.
Note
The F - 1 to F - 4 are mainly from fortify auto detector (Micro Focus) with some of my input (graph or explanations), F - 5 and below are the input from myself --- the solutioin.
F - 5: The Fix or Suggestion
Analysis
The problem in the section F - 2: Details, Line 43:
In fact, it is a login page,
with the HTML code,
There are two protections (validations) on the user input userID: txtIWRUserId,
- one is a RequiredRieldValidator that requires the input must be changed, actually not empty because originally it is empty;
- the second one is a CustomValidator that triggers an event validation, actually in the code behind, it is the method: cvAccountNumberValid_ServerValidate. Howver, in the event handler, beside making a second not empty validation, the code is do nothing about the validation on the format of the input. --- That is the problem.
The Fix
We have two ways to make the fix,
- Use a Design mode valiation, such as the following code that use a ASP contorl RegularExpressionValidator, to make the validation for an email format:
- Use the code behind to make a validation, this is what we did, this way will be effiecient to get rid of the Vulnerability of the HTML input.
The Request for a False Positive
After our fix, the problem should be gone, however, the Micro Focus Fortify (a auto scanning software for security vulnerabilities) cannot tell the fix change, then we have to open a False Positive request to the Fortufy System team (AppSec: Application Security Team).
F - 6: False Positive Accepted
Developer attestation accepted. --- From the Application Security Team.
Note
False Positive Accepted means the tool (Fortify Scanner) is wrong:
False positives occur when a security testing tool incorrectly flags an issue that is not legitimate (i.e. tool says SSL 3.0 is enabled, but it is not – the tool was wrong). In these cases, teams are encouraged to follow the process outlined below for issues to be suppressed and for us to ensure the bug is resolved.
Reference