Input Validation for Security
Filed under: Development, Security
Validating input is an important step for reducing risk to our applications. It might not eliminate the risk, and for that reason we should consider what exactly we are doing with input validation.
Should you be looking for every attack possible?
Should you create a list of every known malicious payload?
When you think about input validation are you focusing on things like Cross-site Scripting, SQL Injection, or XXE, just to name a few? How feasible is it to attempt to block all these different vulnerabilities with input validation? Are each of these even a concern for your application?
I think that input validation is important. I think it can help reduce the ability for many of these vulnerabilities. I also think that our expectation should be aligned with what we can be doing with input validation. We shouldn’t overlook these vulnerabilities, but instead realize appropriate limitations. All of these vulnerabilities have a counterpart, such as escaping, output encoding, parser configurations, etc. that will complete the appropriate mitigation.
If we can’t, or shouldn’t, block all vulnerabilities with input validation, what should we focus on?
Start with focusing on what is acceptable data. It might be counter-intuitive, but malicious data could be acceptable data from a data requirements statement. We define our acceptable data with specific constraints. These typically fall under the following categories:
* Range – What are the bounds of the data? ex. Age can only be between 0 and 150.
* Type – What type of data is it? Integer, Datetime, String.
* Length – How many characters should be allow?
* Format – Is there a specific format? Ie. SSN or Account Number
As noted, these are not specifically targeting any vulnerability. They are narrowing the capabilities. If you verify that a value is an Integer, it is hard to get typical injection exploits. This is similar to custom format requirements. Limiting the length also restricts malicious payloads. A state abbreviation field with a length of 2 is much more difficult to exploit.
The most difficult type is the string. Here you may have more complexity and depending on your purpose, might actually have more specific attacks you might look for. Maybe you allow some HTML or markup in the field. In that case, you may have more advanced input validation to remove malicious HTML or events.
There is nothing wrong with using libraries that will help look for malicious attack payloads during your input validation. However, the point here is to not spend so much time focusing on blocking EVERYTHING when that is not necessary to get the product moving forward. Understand the limitation of that input validation and ensure that the complimenting controls like output encoding are properly engaged where they need to be.
The final point I want to make on input validation is where it should happen. There are two options: on the client, or on the server. Client validation is used for immediate feedback to the user, but it should never be used for security.
It is too easy to bypass client-side validation routines, so all validation should also be checked on the server. The user doesn’t have the ability to bypass controls once the data is on the server. Be careful with how you try to validate things on the client directly.
Like anything we do with security, understand the context and reasoning behind the control. Don’t get so caught up in trying to block every single attack that you never release. There is a good chance something will get through your input validation. That is why it is important to have other controls in place at the point of impact. Input validation limits the amount of bad traffic that can get to the important functions, but the functions still may need to do additional processes to be truly secure.
XSS in Script Tag
Filed under: Development, Security, Testing
Cross-site scripting is a pretty common vulnerability, even with many of the new advances in UI frameworks. One of the first things we mention when discussing the vulnerability is to understand the context. Is it HTML, Attribute, JavaScript, etc.? This understanding helps us better understand the types of characters that can be used to expose the vulnerability.
In this post, I want to take a quick look at placing data within a <script> tag. In particular, I want to look at how embedded <script> tags are processed. Let’s use a simple web page as our example.
<html> <head> </head> <body> <script> var x = "<a href=test.html>test</a>"; </script> </body> </html>
The above example works as we expect. When you load the page, nothing is displayed. The link tag embedded in the variable is rated as a string, not parsed as a link tag. What happens, though, when we embed a <script> tag?
<html> <head> </head> <body> <script> var x = "<script>alert(9)</script>"; </script> </body> </html>
In the above snippet, actually nothing happens on the screen. Meaning that the alert box does not actually trigger. This often misleads people into thinking the code is not vulnerable to cross-site scripting. if the link tag is not processed, why would the script tag be. In many situations, the understanding is that we need to break out of the (“) delimiter to start writing our own JavaScript commands. For example, if I submitted a payload of (test”;alert(9);t = “). This type of payload would break out of the x variable and add new JavaScript commands. Of course, this doesn’t work if the (“) character is properly encoded to not allow breaking out.
Going back to our previous example, we may have overlooked something very simple. It wasn’t that the script wasn’t executing because it wasn’t being parsed. Instead, it wasn’t executing because our JavaScript was bad. Our issue was that we were attempting to open a <script> within a <script>. What if we modify our value to the following:
<html> <head> </head> <body> <script> var x = "</script><script>alert(9)</script>"; </script> </body> </html>
In the above code, we are first closing out the original <script> tag and then we are starting a new one. This removes the embedded nuance and when the page is loaded, the alert box will appear.
This technique works in many places where a user can control the text returned within the <script> element. Of course, the important remediation step is to make sure that data is properly encoded when returned to the browser. By default, Content Security Policy may not be an immediate solution since this situation would indicate that inline scripts are allowed. However, if you are limiting the use of inline scripts to ones with a registered nonce would help prevent this technique. This reference shows setting the nonce (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src).
When testing our applications, it is important to focus on the lack of output encoding and less on the ability to fully exploit a situation. Our secure coding standards should identify the types of encoding that should be applied to outputs. If the encodings are not properly implemented then we are citing a violation of our standards.
XXE and .Net
XXE, or XML External Entity, is an attack against applications that parse XML. It occurs when XML input contains a reference to an external entity that it wasn’t expected to have access to. Through this article, I will discuss how .Net handles XML for certain objects and how to properly configure these objects to block XXE attacks. It is important to understand that the different versions of the .Net framework handle this differently. I will point out the differences for each object.
I will cover the XmlReader, XmlTextReader, and XMLDocument. Here is a quick summary regarding the default settings:
Object | Safe by Default? |
---|---|
XmlReader | |
Prior to 4.0 | Yes |
4.0 + | Yes |
XmlTextReader | |
Prior to 4.0 | No |
4.0 + | No |
XmlDocument | |
4.5 and Earlier | No |
4.6 | Yes |
XMLReader
Prior to 4.0
The ProhibitDtd property is used to determine if a DTD will be parsed.
- True (default) – throws an exception if a DTD is identified. (See Figure 1)
- False – Allows parsing the DTD. (Potentially Vulnerable)
Code that throws an exception when a DTD is processed: – By default, ProhibitDtd is set to true and will throw an exception when an Entity is referenced.
static void Reader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlReader myReader = XmlReader.Create(new StringReader(xml)); while (myReader.Read()) { Console.WriteLine(myReader.Value); } Console.ReadLine(); }
Exception when executed:
[Figure 1]
Code that allows a DTD to be processed: – Using the XmlReaderSettings object, it is possible to allow the parsing of the entity. This could make your application vulnerable to XXE.
static void Reader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlReaderSettings rs = new XmlReaderSettings(); rs.ProhibitDtd = false; XmlReader myReader = XmlReader.Create(new StringReader(xml),rs); while (myReader.Read()) { Console.WriteLine(myReader.Value); } Console.ReadLine(); }
Output when executed showing injected text:
[Figure 2]
.Net 4.0+
In .Net 4.0, they made a change from using the ProhibitDtD property to the new DtdProcessing enumeration. There are now three (3) options:
- Prohibit (default) – Throws an exception if a DTD is identified.
- Ignore – Ignores any DTD specifications in the document, skipping over them and continues processing the document.
- Parse – Will parse any DTD specifications in the document. (Potentially Vulnerable)
Code that throws an exception when a DTD is processed: – By default, the DtdProcessing is set to Prohibit, blocking any external entities and creating safe code.
static void Reader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlReader myReader = XmlReader.Create(new StringReader(xml)); while (myReader.Read()) { Console.WriteLine(myReader.Value); } Console.ReadLine(); }
Exception when executed:
[Figure 3]
Code that ignores DTDs and continues processing: – Using the XmlReaderSettings object, setting DtdProcessing to Ignore will skip processing any entities. In this case, it threw an exception because there was a reference to the entirety that was skipped.
static void Reader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlReaderSettings rs = new XmlReaderSettings(); rs.DtdProcessing = DtdProcessing.Ignore; XmlReader myReader = XmlReader.Create(new StringReader(xml),rs); while (myReader.Read()) { Console.WriteLine(myReader.Value); } Console.ReadLine(); }
Output when executed ignoring the DTD (Exception due to trying to use the unprocessed entity):
[Figure 4]
Code that allows a DTD to be processed: Using the XmlReaderSettings object, setting DtdProcessing to Parse will allow processing the entities. This potentially makes your code vulnerable.
static void Reader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlReaderSettings rs = new XmlReaderSettings(); rs.DtdProcessing = DtdProcessing.Parse; XmlReader myReader = XmlReader.Create(new StringReader(xml),rs); while (myReader.Read()) { Console.WriteLine(myReader.Value); } Console.ReadLine(); }
Output when executed showing injected text:
[Figure 5]
XmlTextReader
The XmlTextReader uses the same properties as the XmlReader object, however there is one big difference. The XmlTextReader defaults to parsing XML Entities so you need to explicitly tell it not too.
Prior to 4.0
The ProhibitDtd property is used to determine if a DTD will be parsed.
- True – throws an exception if a DTD is identified. (See Figure 1)
- False (Default) – Allows parsing the DTD. (Potentially Vulnerable)
Code that allows a Dtd to be processed: (Potentially Vulnerable) – By default, the XMLTextReader sets the ProhibitDtd property to False, allowing entities to be parsed and the code to potentially be vulnerable.
static void TextReader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlTextReader myReader = new XmlTextReader(new StringReader(xml)); while (myReader.Read()) { if (myReader.NodeType == XmlNodeType.Element) { Console.WriteLine(myReader.ReadElementContentAsString()); } } Console.ReadLine(); }
Code that blocks the Dtd from being parsed and throws an exception: – Setting the ProhibitDtd property to true (explicitly) will block Dtds from being processed making the code safe from XXE. Notice how the XmlTextReader has the ProhibitDtd property directly, it doesn’t have to use the XmlReaderSettings object.
static void TextReader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlTextReader myReader = new XmlTextReader(new StringReader(xml)); myReader.ProhibitDtd = true; while (myReader.Read()) { if (myReader.NodeType == XmlNodeType.Element) { Console.WriteLine(myReader.ReadElementContentAsString()); } } Console.ReadLine(); }
4.0+
In .Net 4.0, they made a change from using the ProhibitDtD property to the new DtdProcessing enumeration. There are now three (3) options:
- Prohibit – Throws an exception if a DTD is identified.
- Ignore – Ignores any DTD specifications in the document, skipping over them and continues processing the document.
- Parse (Default) – Will parse any DTD specifications in the document. (Potentially Vulnerable)
Code that allows a DTD to be processed: (Vulnerable) – By default, the XMLTextReader sets the DtdProcessing to Parse, making the code potentially vulnerable to XXE.
static void TextReader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlTextReader myReader = new XmlTextReader(new StringReader(xml)); while (myReader.Read()) { if (myReader.NodeType == XmlNodeType.Element) { Console.WriteLine(myReader.ReadElementContentAsString()); } } Console.ReadLine(); }
Code that blocks the Dtd from being parsed: – To block entities from being parsed, you must explicitly set the DtdProcessing property to Prohibit or Ignore. Note that this is set directly on the XmlTextReader and not through the XmlReaderSettings object.
static void TextReader() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlTextReader myReader = new XmlTextReader(new StringReader(xml)); myReader.DtdProcessing = DtdProcessing.Prohibit; while (myReader.Read()) { if (myReader.NodeType == XmlNodeType.Element) { Console.WriteLine(myReader.ReadElementContentAsString()); } } Console.ReadLine(); }
Output when Dtd is prohibited:
[Figure 6]
XMLDocument
For the XMLDocument, you need to change the default XMLResolver object to prohibit a Dtd from being parsed.
.Net 4.5 and Earlier
By default, the XMLDocument sets the URLResolver which will parse Dtds included in the XML document. To prohibit this, set the XmlResolver = null.
Code that does not set the XmlResolver properly (potentially vulnerable) – The default XMLResolver will parse entities, making the following code potentially vulnerable.
static void Load() { string fileName = @"C:\Users\user\Documents\test.xml"; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(fileName); Console.WriteLine(xmlDoc.InnerText); Console.ReadLine(); }
Code that does set the XmlResolver to null, blocking any Dtds from executing: – To block entities from being parsed, you must explicitly set the XmlResolver to null. This example uses LoadXml instead of Load, but they both work the same in this case.
static void LoadXML() { string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc [<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">] ><doc>&win;</doc>"; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.XmlResolver = null; xmlDoc.LoadXml(xml); Console.WriteLine(xmlDoc.InnerText); Console.ReadLine(); }
.Net 4.6
It appears that in .Net 4.6, the XMLResolver is defaulted to Null, making the XmlDocument safe. However, you can still set the XmlResolver in a similar way as prior to 4.6 (see previous code snippet).
Open Redirect – Bad Implementation
I was recently looking through some code and happen to stumble across some logic that is attempting to prohibit the application from redirecting to an external site. While this sounds like a pretty simple task, it is common to see it incorrectly implemented. Lets look at the check that is being performed.
string url = Request.QueryString["returnUrl"]; if (string.IsNullOrWhiteSpace(url) || !url.StartsWith("/")) { Response.Redirect("~/default.aspx"); } else { Response.Redirect(url); }
The first thing I noticed was the line that checks to see if the url starts with a “/” characters. This is a common mistake when developers try to stop open redirection. The assumption is that to redirect to an external site one would need the protocol. For example, http://www.developsec.com. By forcing the url to start with the “/” character it is impossible to get the “http:” in there. Unfortunately, it is also possible to use //www.developsec.com as the url and it will also be interpreted as an absolute url. In the example above, by passing in returnUrl=//www.developsec.com the code will see the starting “/” character and allow the redirect. The browser would interpret the “//” as absolute and navigate to www.developsec.com.
After putting a quick test case together, I quickly proved out the point and was successful in bypassing this logic to enable a redirect to external sites.
Checking for Absolute or Relative Paths
ASP.Net has build in procedures for determining if a path is relative or absolute. The following code shows one way of doing this.
string url = Request.QueryString["returnUrl"]; Uri result; bool isAbsolute = false; isAbsolute = Uri.TryCreate(returnUrl, UriKind.Absolute, out result); if (!isAbsolute) { Response.Redirect(url); } else { Response.Redirect("~/default.aspx"); }
In the above example, if the URL is absolute (starts with a protocol, http/https, or starts with “//”) it will just redirect to the default page. If the url is not absolute, but relative, it will redirect to the url passed in.
While doing some research I came across a recommendation to use the following:
if (Uri.IsWellFormedUriString(returnUrl,UriKind.Relative))
When using the above logic, it flagged //www.developsec.com as a relative path which would not be what we are looking for. The previous logic correctly identified this as an absolute url. There may be other methods of doing this and MVC provides some other functions as well that we will cover in a different post.
Conclusion
Make sure that you have a solid understanding of the problem and the different ways it works. It is easy to overlook some of these different techniques. There is a lot to learn, and we should be learning every day.
Potentially Dangerous Request.Path Value was Detected…
Filed under: Development, Security
I have discussed request validation many times when we see the potentially dangerous input error message when viewing a web page. Another interesting protection in ASP.Net is the built-in, on by default, Request.Path validation that occurs. Have you ever seen the error below when using or testing your application?
The screen above occurred because I placed the (*) character in the URL. In ASP.Net, there is a default set of defined illegal characters in the URL. This list is defined by RequestPathInvalidCharacters and can be configured in the web.config file. By default, the following characters are blocked:
- <
- >
- *
- %
- &
- :
- \\
It is important to note that these characters are blocked from being included in the URL, this does not include the protocol specification or the query string. That should be obvious since the query string uses the & character to separate parameters.
There are not many cases where your URL needs to use any of these default characters, but if there is a need to allow a specific character, you can override the default list. The override is done in the web.config file. The below snippet shows setting the new values (removing the < and > characters:
<httpruntime requestPathInvalidCharacters="*,%,&,:,\\"/>
Be aware that due the the web.config file being an xml file, you need to escape the < and > characters and set them as < and > respectively.
Remember that modifying the default security settings can expose your application to a greater security risk. Make sure you understand the risk of making these modifications before you perform them. It should be a rare occurrence to require a change to this default list. Understanding the platform is critical to understanding what is and is not being protected by default.
ASP.Net Insufficient Session Timeout
Filed under: Development, Security, Testing
A common security concern found in ASP.Net applications is Insufficient Session Timeout. In this article, the focus is not on the ASP.Net session that is not effectively terminated, but rather the forms authentication cookie that is still valid after logout.
How to Test
- User is currently logged into the application.
- User captures the ASPAuth cookie (name may be different in different applications).
- Cookie can be captured using a browser plugin or a proxy used for request interception.
- User saves the captured cookie for later use.
- User logs out of the application.
- User requests a page on the application, passing the previously captured authentication cookie.
- The page is processed and access is granted.
Typical Logout Options
- The application calls FormsAuthentication.Signout()
- The application sets the Cookie.Expires property to a previous DateTime.
Cookie Still Works!!
Following the user process above, the cookie still provides access to the application as if the logout never occurred. So what is the deal? The key is that unlike a true “session” which is maintained on the server, the forms authentication cookie is self contained. It does not have a server side component to stay in sync with. Among other things, the authentication cookie has your username or ID, possibly roles, and an expiration date. When the cookie is received by the server it will be decrypted (please tell me you are using protection = all) and the data extracted. If the cookie’s internal expiration date has not passed, the cookie is accepted and processed as a valid cookie.
So what did FormsAuthentation.Signout() do?
If you look under the hood of the .Net framework, it has been a few years but I doubt much has changed, you will see that FormsAuthentication.Signout() really just removes the cookie from the browser. There is no code to perform any server function, it merely asks the browser to remove it by clearing the value and back-dating the expires property. While this does work to remove the cookie from the browser, it doesn’t have any effect on a copy of the original cookie you may have captured. The only sure way to really make the cookie inactive (before the internal timeout occurs) would be to change your machine key in the web.config file. This is not a reasonable solution.
Possible Mitigations
You should be protecting your cookie by setting the httpOnly and Secure properties. HttpOnly tells the browser not to allow javascript to have access to the cookie value. This is an important step to protect the cookie from theft via cross-site scripting. The secure flag tells the browser to only send the authentication cookie over HTTPS, making it much more difficult for an attacker to intercept the cookie as it is sent to the server.
Set a short timeout (15 minutes) on the cookie to decrease the window an attacker has to obtain the cookie.
You could attempt to build a tracking system to manage the authentication cookie on the server to disable it before its time has expired. Maybe something for another post.
Understand how the application is used to determine how risky this issue may be. If the application is not used on shared/public systems and the cookie is protected as mentioned above, the attack surface is significantly decreased.
Final Thoughts
If you are facing this type of finding and it is a forms authentication cookie issue, not the Asp.Net session cookie, take the time to understand the risk. Make sure you understand the settings you have and the priority and sensitivity of the application to properly understand “your” risk level. Don’t rely on third party risk ratings to determine how serious the flaw is. In many situations, this may be a low priority, however in the right app, this could be a high priority.
Static Analysis: Analyzing the Options
Filed under: Development, Security, Testing
When it comes to automated testing for applications there are two main types: Dynamic and Static.
- Dynamic scanning is where the scanner is analyzing the application in a running state. This method doesn’t have access to the source code or the binary itself, but is able to see how things function during runtime.
- Static analysis is where the scanner is looking at the source code or the binary output of the application. While this type of analysis doesn’t see the code as it is running, it has the ability to trace how data flows the the application down to the function level.
An important component to any secure development workflow, dynamic scanning analyzes a system as it is running. Before the application is running the focus is shifted to the source code which is where static analysis fits in. At this state it is possible to identify many common vulnerabilities while integrating into your build processes.
If you are thinking about adding static analysis to your process there are a few things to think about. Keep in mind there is not just one factor that should be the decision maker. Budget, in-house experience, application type and other factors will combine to make the right decision.
Disclaimer: I don’t endorse any products I talk about here. I do have direct experience with the ones I mention and that is why they are mentioned. I prefer not to speak to those products I have never used.
Budget
I hate to list this first, but honestly it is a pretty big factor in your implementation of static analysis. The vast options that exist for static analysis range from FREE to VERY EXPENSIVE. It is good to have an idea of what type of budget you have at hand to better understand what option may be right.
Free Tools
There are a few free tools out there that may work for your situation. Most of these tools depend on the programming language you use, unlike many of the commercial tools that support many of the common languages. For .Net developers, CAT.Net is the first static analysis tool that comes to mind. The downside is that it has not been updated in a long time. While it may still help a little, it will not compare to many of the commercial tools that are available.
In the Ruby world, I have used Brakeman which worked fairly well. You may find you have to do a little fiddling to get it up and running properly, but if you are a Ruby developer then this may be a simple task.
Managed Services or In-House
Can you manage a scanner in-house or is this something better delegated to a third party that specializes in the technology?
This can be a difficult question because it may involve many facets of your development environment. Choosing to host the solution in-house, like HP’s Fortify SCA may require a lot more internal knowledge than a managed solution. Do you have the resources available that know the product or that can learn it? Given the right resources, in-house tools can be very beneficial. One of the biggest roadblocks to in-house solutions is related to the cost. Most of them are very expensive. Here are a few in-house benefits:
- Ability to integrate directly into your Continuous Integration (CI) operations
- Ability to customize the technology for your environment/workflow
- Ability to create extensions to tune the results
Choosing to go with a managed solution works well for many companies. Whether it is because the development team is small, resources aren’t available or budget, using a 3rd party may be the right solution. There is always the question as to whether or not you are ok with sending your code to a 3rd party or not, but many are ok with this to get the solution they need. Many of the managed services have the additional benefit of reducing false positives in the results. This can be one of the most time consuming pieces of a static analysis tool, right there with getting it set up and configured properly. Some scans may return upwards of 10’s of thousands of results. Weeding through all of those can be very time consuming and have a negative effect on the poor person stuck doing it. Having a company manage that portion can be very beneficial and cost effective.
Conclusion
Picking the right static analysis solution is important, but can be difficult. Take the time to determine what your end goal is when implementing static analysis. Are you looking for something that is good, but not customizable to your environment, or something that is highly extensible and integrated closely with your workflow? Unfortunately, sometimes our budget may limit what we can do, but we have to start someplace. Take the time to talk to other people that have used the solutions you are looking at. Has their experience been good? What did/do they like? What don’t they like? Remember that static analysis is not the complete solution, but rather a component of a solution. Dropping this into your workflow won’t make you secure, but it will help decrease the attack surface area if implemented properly.