Category Archives: General

Burp Extension – Juice Shop Routes

When it comes to testing for security within our web applications, we often look to creating simple tools to help speed things up. They also help provide a consistent way to help identify known patterns. For those that haven’t been following, I have been doing a few posts about getting the OWASP Juice Shop application up and running. In this post, I want to introduce a simple burp extension I created to help with a few of the challenges presented in the OWASP Juice Shop.

The Challenge

The OWASP Juice Shop has multiple challenges built into it to help guide the user along in finding web applications. The app is written as a single page app (SPA) and is a little different than your traditional applications. Rather than make a full page request for everything you click, instead the application just makes API calls. In short, the entire UI is returned on the first load of the application.

There are multiple challenges within the Juice Shop that require the user to access specific URLs that are not available via a menu or link. For example (and I don’t want to directly give away answers to the challenge here), imaging visiting the contact screen. If you click the menu item for contact us, it will update the URL in the address bar to be like /#/contact. So I don’t have to actually click a link to access the contact us page, I could just update that URL directly in the address bar.

Finding the Routes

So how do you find the URLs that are available to access? There are multiple ways of doing this. First, of course, you could try to just fuzz them. This is good if the URLs are not available anywhere for us to find. Fortunately, this Angular application embeds the different routes within the client-side code. It uses a RouteProvider object to do this.

With a little digging, you can find this information in the /dist/juice-shop.min.js file. This is a pretty large file and looking through it can be a little tough. Searching for RouteProvider will bring you to the route definitions.

A Burp Extension

As a professional web app tester, I spend a lot of time using Burp Suite as my web proxy. It allows me to easily view and intercept all the traffic my browser sends back and forth to the server. Another cool feature is it allows building your own extensions to solve just this type of problem. Of course, you probably wouldn’t just create an extension for this one piece or a specific app. Instead, the hope would be that it would become helpful for other applications that use angular’s route provider object. This way, when I go to test other sites, I may get this information right there in my scanner results.

I built a quick little burp extension that looks for the routeProvider object and then, if found, pulls out each route defined. The code can be found at https://github.com/jamesjardine/juiceshoproutes. The code that performs all the tasks are in the BurpExtender.java file.

Once the extension is built into a JAR file it can be added into Burp. Note that this only works for Burp Pro because it uses the passive scanner. To install it, just navigate to the “Extender” tab and click the Add button. Then select the Jar file you created:

Be 0

Here is a quick run down of what it does:

  • Looks to see if the response from the server contains the phrase $routeProvider. If it finds this phrase it then gets the start offset and the end of the object by identifying the next ] character.
  • It then loops through the specific body text looking for a match to e.when. This basically defines when the URL matches X, load a specific template.
  • Each route that is identified is then displayed in an unordered list.
  • When you visit the Target Tab and select your site, click on the Issues tab to look for Angular Routes.

This is just a quick example of how building custom burp extensions can help increase your efficiency or help provide some additional coverage for known patterns within applications.

————–POTENTIAL SPOILER INFO BELOW ——————–

IF YOU ARE WANTING TO TRY THIS OUT WITHOUT SEEING THE RESPONSE FIRST STOP READING HERE!!!

There is no interaction needed to trigger this scan except for just visiting the initial page of the Juice Shop site. The Issues tase will look like:

Be screen1

If you look at the response, you will see the following image:

Be 2

In the above image you can see the highlighted area showing where the RouteProvder routes are defined. In the following image, you can see the advisory screen which indicates the formatted list of routes that are available:

Be 3

Installing OWASP JuiceShop with Heroku

I am often asked the question by clients and students where people can go to learn hacking techniques for application security. For years, we have had many purposely vulnerable applications available to us. These applications provide a safe environment for us to learn more about hacking applications and the vulnerabilities that are exposed without the legal ramifications.

In this post I want to show you how simple it is to install the OWASP Juice Shop application using Heroku. Juice Shop is a purposely vulnerable application written using NodeJS and Angular. It goes beyond just being an application with some vulnerabilities. It is set up to be a capture the flag (CTF) style application with its own scoreboard.

To learn more about the Juice Shop project, head over to https://www.owasp.org/index.php/OWASP_Juice_Shop_Project. This is the main landing page and looks like the following:

Juice Shop

The first step in installing on Heroku is to make sure you are logged into your Heroku account. If you haven’t created one, do that first. Once you are logged in you should be in your dashboard that looks something like this:

HerokuInstall 1

Now that we are logged into Heroku, let’s head over to the Juice-shop GitHub page at https://github.com/bkimminich/juice-shop.

HerokuInstall 2

As you can see there is a button to “Deploy to Heroku”. Clicking this button will take you back to Heroku and ask for the app name as shown below:

HerokuInstall 3

Once you select a unique app name and the region clicking deploy starts the process. It doesn’t take very long (maybe 3-4 minutes) for the deploy to complete. While it is deploying you will see the build output as shown below:

HerokuInstall 4

Once the deployment is complete, you can click the button to View your new app. This will basically open a new tab at the location of your named instance which is the [name you picked].herokuapp.com as shown below:

HerokuInstall 5

The Juice Shop has a lot of vulnerabilities in it. It is a great way to learn more about how to exploit some of these vulnerabilities and test your skills. If you have little knowledge of application security vulnerabilities or the OWASP Top 10 check out our training courses we have available:

Please remember that hacking is illegal. If you want to learn more about application security and test your skills, do it responsibly and use great applications like the Juice Shop as your targets.

OWASP 2017 Changes

When I talk to people about application security, the most recognized topics is the OWASP Top 10. If you haven’t heard of the top 10, or need a refresher, you can get the full list at:

https://www.owasp.org/images/7/72/OWASP_Top_10-2017_%28en%29.pdf.pdf

The OWASP Top 10 is on a three year update cycle. We had the list in 2010, 2013 and now the latest is 2017. You may be wondering why it is 2017 rather than 2016. I think that is a question a lot of people had. In any case, the list made it out to final release after the initial draft was rejected. Now that it is here, we can analyze it and see how it affects us and our organizations.

https://www.youtube.com/watch?v=kfDuxwFScOE

What I think sticks out more to me this update over previous updates is the removal of some pretty common flaws based on my experience. In the past we have seen flaws move up or down on the risk level, or get combined, but not as much removed. In 2017, we saw two items get removed:

  • Cross-site Request Forgery
  • Unvalidated Redirects and Forwards

I find these items interesting because I see them on most of the assessments I do. Let’s take a quick look at them.

Cross-site Request Forgery

CSRF can be a pretty serious flaw based on its context. It is the ability to force the victim’s browser to make requests to another site they are authenticated too without their knowledge. An example of a higher-risk context is the ability to change the victim’s email address on their profile. If the system doesn’t have two factor authentication or other safe guards, changing the email address can lead to the ability to request a password reset. In many situations, this can lead to easily taking over the victim’s account.
This is just one example of how CSRF can be used. The good news is that many newer frameworks provide some level of CSRF protection built-in. So in many applications it is not as prevalent. However, based on my experience, not everyone is using the latest frameworks. Due to this, I still find this on a lot of the assessments I do.

Unvalidated Redirects and Forwards

Unvalidated Redirects is often viewed as a low risk issue. In many cases, it may represent a low risk. There are some situations that make unvalidated redirects fairly dangerous. A good example is the redirect often performed by login forms. A common feature of many applications is to redirect the user to a specific resource after logging in. To do this, a parameter in the URL specifies the path to be sent to. If the application allows redirecting to external sites, it is simple to set up a malicious site with the same look and feel as the expected site. If the victim uses your link with the reference to your malicious site they may be presented with your fake login page after successfully logging into the real site. The victim may believe they have mistyped their password and just login again without checking the URL, leading to account takeover.

We also saw to access control findings get merged into one. This change makes a lot of sense when you look at each item. They are both regarding access control issues.

With the removal and merging, the list has brought on three new vulnerabilities:

  • XML External Entities (XXE)
  • Insecure Deserialization
  • Insufficient Logging and Monitoring

XML External Entities (XXE)

XML External Entities is a vulnerability that takes advantage of how XML Parsers interpret the supplied XML. In this case, it is possible to reference other resources outside of the XML document. A common scenario is the ability to read other files on the web server, such as the /etc/passwd file. This vulnerability also may allow a denial of service attack to occur due to embedding specific entities. This vulnerability obviously relies on the application parsing XML data. If your application is parsing XML, it is recommended to make sure the parser is ignoring or blocking DTDs. If your parser doesn’t have that option, or you need to allow some DTDs, make sure your input validation is limiting those to only acceptable ones.

Insecure Deserialization

Insecure Deserialization occurs when you are deserializing data that has not been properly sanitized. This occurs because we assume that the data serialized has not been modified. When the data is modified, it could be executed during the deserialization process to perform commands. To help prevent this, make sure you are enforcing strict data checks on the objects that have been serialized. I do not see this very often in many of the assessments I do. Just depends on the application as many do not use much serialization.

Insufficient Logging and Monitoring

When I talk to people and ask them about logging, the first response, or usually the only response, is related to troubleshooting. There is no doubt that troubleshooting is critical for any application. If the application is not running as expected, users may leave, transactions may get lost, or a myriad of other issues may occur. Logging is for much more than just troubleshooting. Proper logging of security related events can help identify an attack while it is occurring as well as help identify what happened after the fact. It can be very difficult to identify what data was accessed or how if there are no logs indicating such information. It is good that we are seeing more attention called to this practice, although it can be a complex one to implement and verify. Don’t forget that once you start logging security events, they must be monitored to take action.

Wrap Up

Changes to the OWASP Top 10 isn’t something new. We know it will happen and it may require some adjustment to what we are doing internally. While we do see items drop or get added, it just highlights that the top 10 is a mere starting point of security. Every organization should have their list of top 10 risks. Don’t limit yourself to these short lists. They are to help identify the highest risks and implement them in a feasible way. Application security doesn’t happen overnight. There has to be a starting point and then a path to mature.

Listen to the podcast on this topic. http://podcast.developsec.com/developsec-podcast-91-owasp-top-10-2017-thoughts

Two-Factor Authentication Considerations

There was a recent article talking about how a very small percentage of google users actually use 2-factor authentication. You can read the full article at http://www.theregister.co.uk/2018/01/17/no_one_uses_two_factor_authentication/

Why 2-Factor

Two-factor authentication, or multi-factor authentication, is a valuable step in the process to protect accounts from unauthorized users. Traditionally, we have relied just on a username/password combination. That process had its own weaknesses that many applications have moved to improve. For example, many sites now require “complex” passwords. Of course, complex is up for debate. But we have seen the minimum password length go up and limitations on using known weak passwords go up. Each year we see lists of the most common passwords to not use, some being 123456 or Password. I hope no one is using these types of passwords. To be honest, I don’t know of any sites I use that would allow this type of password. So many these days require a mix of characters or special characters.

https://www.youtube.com/watch?v=YxXebkpSLr8

The above controls are meant to help reduce the risk of someone just guessing your password, there are other controls to help try to limit brute forcing techniques. Many accounts offer account lockout after X number of invalid attempts. There are other controls that we also see implemented around protecting the username/password logic. None of these controls help protect against a user reusing passwords on another site that may be compromised. They also do not protect against a user falling for a social engineering attack to trick them into sharing their passwords. To help combat this, many sites will implement a second factor beyond username/password.

The idea of the second factor is that even if you have the username and password, you will not have this other piece of information. In most cases, it is a value that changes every 60 seconds or so, and is delivered over a protected channel. For example, the token used may be sent via SMS, a voice call, or created through a phone application like the Google Authenticator application. So even if the attacker is able to get your password, via a breach, brute force, or just lucky guessing, in theory they would not have access to that second factor.

Why Are People Not Using It?

So why do people not enable the second factor on their Google accounts? Unfortunately, the presentation didn’t appear to explain that, which makes sense since it is difficult to know why people do or do not do certain things. I think there may be a few reasons for it that we will briefly touch on.

First, I think many people just are not aware of enabling the second factor. To be fair, it is sort of buried down in settings that may be difficult to find if you are not really looking for it. If it is not front and center, then there is a much smaller chance people will go seeking it out. To add to the issue, many people really don’t understand what 2-factor authentication means or how it really helps them. Sure, in security we get it, but that doesn’t mean everyone else does. How do we make it more prominent that this is a positive security feature? Many users will already be aware of 2-factor if they use online banking as most of those have started enforcing it.

Many people think that two factor authentication is a burden or it will slow their access down. This is usually not the case unless the application has implemented it poorly. Many sites will allow you to save your computer so you don’t need to enter the 2nd factor every time you access the site. However, it will require it if you access from a different computer.

To complicate things, other applications may not support signing in with 2 factors, like your email client. In these cases, you have to generate an app password which can be very confusing to many users, especially those that are not technically savvy.

There may be a chance that users don’t think they need to protect their email accounts, that it is not sensitive. If you just use email to communicate with friends and receive junk mail, what could be so bad, right? Most people forget that things like password resets are performed using an email account. Having control of an email account provides a lot of control over a lot of things. While it may seem small, email is an important function to protect.

If you are using Gmail, I recommend configuring 2-factor authentication. The following video walks through setting it up using SMS (Although there are other options as well):

Demo- Google 2 factor

If you are developing applications, I recommend looking into providing the option of 2-factor authentication. When you do this, make sure that you are promoting its use in a positive way. If you already have 2-factor with your application, can you run a report to determine what percentage of users are actually using it? If that number is low, what steps can you take to increase them?

Don’t assume that any application is not worthy of the extra security. Many applications are already providing 2-factor and that number will just increase. While we still have the password, we will always be looking for ways to add more protection. When implemented properly, it is simple for the end user, but effective in increasing security. If your user base is not taking advantage of the option, take the time to assess why that is and how it can be improved.

As I was writing this up, I ran into an interesting situation with 2-factor that sparked some more thoughts. When looking to support 2-factor authentication and not using SMS, take careful consideration to the applications you may choose to support. On the Apple App Store alone there are over 200 different authenticator apps available. Some are interchangeable while others are not. This can be another barrier in users choosing to enable 2-factor authentication.

New Year’s Resolutions

Here we are, the start of another year. As we reflect on 2017, this is where we really start to focus on what lies ahead in 2018. The new year is always interesting because it usually doesn’t affect our build cycles or releases. With the exception of accounting for vacations. Yet, this is the time of year where many people get re-focused and motivated to change old habits or try something new.

Listen to the Podcast:

As I look back on 2017, there were a lot of news headlines that focused around security. So many of them highlighting breaches, many termed “mega” breaches. The trend of hyped up headlines glorifying monster breaches will likely continue through 2018 and beyond. We know that breaches can, or will, happen. We have seen examples of different techniques used to gain unauthorized access to data. This won’t change, and will most likely become more prevalent going forward. The amount of information available to potential attackers is enormous, making our job of application security that much more important.

One of the biggest lessons to take away from 2017 is that privacy is important. In addition, private data is not limited to PCI or HIPAA. All sorts of data can be considered private and require the custodian to take proper steps to protect it. It doesn’t matter if the data is held by a Fortune 500 company or a one-person shop. To someone, that data is worth something. As we look into 2018, this reminds us that we must understand what data we have. We must know what type of regulations it may fall under, what applications contain it, and how we are protecting it. Just because data may not fall under a regulation doesn’t mean it should be overlooked. In the end, it is the expectation of our customers and clients that we will handle their data responsibly.

Protecting this data is not about how much money you spend or what tools you buy. Every organization is different. Every application development team is different. I encourage everyone to take the time to research and understand what your team needs to be successful. As in the past, throughout the year I will be posting thoughts on different application security topics. If you have any questions or topics, feel free to share them with me. Looking for someone to talk to about application security? Reach out. I have services available to help organizations and individuals reach new heights and solve problems.

What are your New Year’s Resolutions when it comes to application security?

XSS in a Script Tag

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 processes, 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.

JavaScript in an HREF or SRC Attribute

The anchor (<a>) HTML tag is commonly used to provide a clickable link for a user to navigate to another page. Did you know it is also possible to set the HREF attribute to execute JavaScript. A common technique is to use the onclick event of the anchor tab to execute a JavaScript method when the user clicks the link. However, to stop the browser from actually redirecting the HREF can be set to javascript:void(0);. This cancels the HREF functionality and allows the JavaScript from the onclick to execute as expected.

In the above example, notice that the HREF is set with a value starting with “javascript:”. This identifier tells the browser to execute the code following that prefix. For those that are security savvy, you might be thinking about cross-site scripting when you hear about executing JavaScript within the browser. For those of you that are new to security, cross-site scripting refers to the ability for an attacker to execute unintended JavaScript in the context of your application (https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)).

I want to walk through a simple scenario of where this could be abused. In this scenario, the application will attempt to track the page the user came from to set up where the Cancel button will redirect to. Imagine you have a list page that allows you to view details of a specific item. When you click the item it takes you to that item page and passes a BackUrl in the query string. So the link may look like:

https://developsec.com/item.php?backUrl=/items.php

On the page, there is a hyperlink created that sets the HREF to the backUrl property, like below:

<a href=”<?php echo $_GET[“backUrl”];?>”>Back</a>

When the page executes as expected you should get an output like this:

<a href=”/items.php”>Back</a>

There is a big problem though. The application is not performing any type of output encoding to protect against cross-site scripting. If we instead pass in backUrl=”%20onclick=”alert(10); we will get the following output:

<a href=”” onclick=”alert(10);“>Back</a>

In the instance above, we have successfully inserted the onclick event by breaking out of the HREF attribute. The bold section identifies the malicious string we added. When this link is clicked it will prompt an alert box with the number 10.

To remedy this, we could (or typically) use output encoding to block the escape from the HREF attribute. For example, if we can escape the double quotes (” -> &quot; then we cannot get out of the HREF attribute. We can do this (in PHP as an example) using htmlentities() like this:

<a href=”<?php echo htmlentities($_GET[“backUrl”],ENT_QUOTES);?>”>Back</a>

When the value is rendered the quotes will be escapes like the following:

<a href=”&quot; onclick=&"alert(10);“>Back</a>

Notice in this example, the HREF actually has the entire input (in bold), rather than an onclick event actually being added. When the user clicks the link it will try to go to https://www.developsec.com/” onclick=”alert(10); rather than execute the JavaScript.

But Wait… JavaScript

It looks like we have solved the XSS problem, but there is a piece still missing. Remember at the beginning of the post how we mentioned the HREF supports the javascript: prefix? That will allow us to bypass the current encodings we have performed. This is because with using the javascript: prefix, we are not trying to break out of the HREF attribute. We don’t need to break out of the double quotes to create another attribute. This time we will set backUrl=javascript:alert(11); and we can see how it looks in the response:

<a href=”javascript:alert(11);“>Back</a>

When the user clicks on the link, the alert will trigger and display on the page. We have successfully bypassed the XSS protection initially put in place.

Mitigating the Issue

There are a few steps we can take to mitigate this issue. Each has its pros and many can be used in conjunction with each other. Pick the options that work best for your environment.

  • URL Encoding – Since the HREF is meant to be a URL, you could perform URL encoding. URL encoding will render the javascript benign in the above instances because the colon (:) will get encoded. You should be using URL encoding for URLs anyway, right?
  • Implement Content Security Policy (CSP) – CSP can help limit the ability for inline scripts to be executed. In this case, it is an inline script so something as simple as ‘Content-Security-Policy:default-src ‘self’ could be sufficient. Of course, implementing CSP requires research and great care to get it right for your application.
  • Validate the URL – It is a good idea to validate that the URL used is well formed and pointing to a relative path. If the system is unable to parse the URL then it should not be used and a default back URL can be substituted.
  • URL White Listing – Creating a white list of valid URLs for the back link can be effective at limiting what input is used by the end user. This can cut down on the values that are actually returned blocking any malicious scripts.
  • Remove javascript: – This really isn’t recommended as different encodings can make it difficult to effectively remove the string. The other techniques listed above are much more effective.

The above list is not exhaustive, but does give an idea of ways to help reduce the risk of JavaScript within the HREF attribute of a hyper link.

Iframe SRC

It is important to note that this situation also applies to the IFRAME SRC attribute. it is possible to set the SRC of an IFRAME using the javascript: notation. In doing so, the javascript executes when the page is loaded.

Wrap Up

When developing applications, make sure you take this use case into consideration if you are taking URLs from user supplied input and setting that in an anchor tag or IFrame SRC.

If you are responsible for testing applications, take note when you identify URLs in the parameters. Investigate where that data is used. If you see it is used in an anchor tag, look to see if it is possible to insert JavaScript in this manner.

For those performing static analysis or code review, look for areas where the HREF or SRC attributes are set with untrusted data and make sure proper encoding has been applied. This is less of a concern if the base path of the URL has been hard-coded and the untrusted input only makes up parameters of the URL. These should still be properly encoded.

Understanding Your Application Platform

Building applications today includes the use of some pretty impressive platforms. These platforms have so much built in capability, many of the most common tasks are easily accomplished through simple method calls. As developers, we rely on these frameworks to provide a certain level of functionality. Much of which we may never even use.

When it comes to security, the platform can be a love/hate relationship. On the one hand, developers may have little control over how the platform handles certain tasks. On the other, the platform may provide excellent security controls. As we mature these platforms, we see a lot of new, cool security features enabled by default. Many view engines have cross-site scripting protections built in by default. Many of the systems use ORM to help reduce SQL Injection vulnerabilities. The problem we often run into is we don’t really know what our platform does and does not provide.

A question was posed about what was the most secure application platform, or which would you recommend. The problem to that question is that the answer really is “It depends.” The frameworks are not all created equally. Some have better XSS preventions. Others may have default CSRF prevention. What a framework does or doesn’t have can also change next month. They are always being updated. Rather than pick the most secure platform, I recommend to people to take the time to understand your platform of choice.

Does it matter if you use PHP, Java, .Net, Python, or Ruby? They all have some built in features, they all have their downfalls. So rather than trying to swap platforms every time a new one gets better features, spend some time to understand the platform you have in front of you. When you understand the risks that you face, you can then determine how those line up with your platform. Do you output user input to a web browser? If so, cross site scripting is a concern. Determine how your platform handles that. It may be that the platform auto encodes that data for you. The encoding may only happen in certain contexts. it may be the platform doesn’t provide any encoding, but rather leaves that up to you.

While the secure by default is more secure, as it reduces the risk of human oversight, applications can still be very secure without it. This is where that understanding comes into play. If I understand my platform and know that it doesn’t encode for me then I must make the effort to protect that. This may even include creating your own function or library that is used enterprise wide to help solve the problem. Unfortunately, when you don’t understand your platform, you never realize that this is a step you must take. Then it is overlooked and you are vulnerable.

I am also seeing more platforms starting to provide security guidelines or checklists to help developers with secure implementation. They may know of areas the platform doesn’t create a protection, so they show how to get around that. Maybe something is not enabled by default, but they recommend and show how to enable that. The more content like this that is produced the more we will understand how to securely create applications.

Whatever platform you use, understanding it will make the most difference. If the platform doesn’t have good documentation, push for it. Ask around or even do the analysis yourself to understand how security works in your situations.

Validation: Client vs. Server

Years ago, I remember being on a technical interview phone call for a senior developer position. What stood out was when the interviewer asked me about performing input validation. The question was in regards to if validation should be on the client or the server. My answer: The server.

What took me by surprise was when the response was that my answer was incorrect. In fact, I was told that Microsoft recommends performing validation on the client. This was inaccurate information, but I let it go and continued with the interview.
Recently, I have been having more conversations around input validation. In particular, the question of client or server side. While it is easy to state that validation should always be performed on the server, lets dig into this a little more to better understand your situation.

From a pure security perspective, input validation must be performed on the server. There is one simple reason for this: Any protections built using client-side techniques can be bypassed by using a simple web proxy. Using JavaScript to enforce that a field contains an email address can be easily bypassed by intercepting the request and changing it after the JavaScript has executed.

If you look at the threat model of your application, requests from the client to the server cross a trust boundary. Because of this trust boundary we know that the data needs to be validated again. Why? There is no way to know what happened to the data before it was received. We can assume the request was sent from a browser, used by a typical user. However, we don’t know if the data was manipulated after leaving the browser, or even sent from a browser at all.

That, however, is from a strict security standpoint. We must not forget that client-side validation serves a purpose as well. While client-side validation may not be trusted by the server, it tends to be more focused on immediate feedback to the user. Not only does this save a round trip, or many round trips, to the server, it cuts down on the processing the server needs to handle.
If we take an example of purely validating required fields on a form, we can immediately see the benefit of client-side validation. Even a small form, if not complete can create a lot of inefficiency if the user is constantly posting it without all the required fields. The ability to alert to this on the client makes it much quicker and cuts down on the number of invalid requests to the server.

Of course, this doesn’t mean that the user can’t fill in all the required fields to pass the client-side validation, intercept the request, and then remove some of those fields. In this case, server-side validation would catch this. The goal, however, of client-side validation is to provide a reactive user interface that is fast.

Understanding how each validation location functions and what the real purpose is helps us identify when to use each. While server-side validation is always required, client-side validation can be a great addition to the application.

Properly Placing XSS Output Encoding

Cross-Site Scripting flaws, as well as other injection flaws, are pretty well understood. We know how they work and how to mitigate them. One of the key factors in mitigation of these flaws is output encoding or escaping. For SQL, we escape by using parameters. For cross-site scripting we use context sensitive output encoding.

In this post, I don’t want to focus on the how of output encoding for cross-site scripting. Rather, I want to focus on when in the pipeline it should be done. Over the years I have had a lot of people ask if it is ok to encode the data before storing it in the database. I recently came across this insufficient solution and thought it was a good time to address it again. I will look at a few different cases that indicate why the solution is insufficient and explain a more sufficient approach.

The Database Is Not Trusted

The database should not be considered a trusted resource. This is a common oversight in many organizations, most likely due to the fact that the database is internal. It lives in a protected portion of your production environment. While that is true, it has many sources that have access to it. Even if it is just your application that uses the database today, there are still administrators and update scripts that most likely access it. We can’t rule out the idea of a rogue administrator, even if it is very slim.

We also may not know if other applications access our database. What if there is a mobile application that has access? We can’t guarantee that every source of data is going to properly encode the data before it gets sent to the database. This leaves us with a gap in coverage and a potential for cross-site scripting.

Input Validation My Not Be Enough

I always recommend to developers to have good input validation. Of course, the term good is different for everyone. At the basic level, your input validation may limit a few characters. At the advanced level it may try to limit different types of attacks. In some cases, it is difficult to use input validation to eliminate all cross-site scripting payloads. Why? Due to the different contexts and the types of data that some forms accept, a payload may still squeak by. Are you protecting against all payloads across all the different contexts? How do you know what context the data will be used in?

In addition to potentially missing a payload, what about when another developer creates a function and forgets to include the input validation? Even more likely, what happens when a new application starts accessing your database and doesn’t perform the same input validation. it puts us back into the same scenario described in the section above regarding the database isn’t trusted.

You Don’t Know the Context

When receiving and storing data, the chances are good I don’t know where the data will be used. What is the context of the data when output? Is it going into a span tag, an attribute or even straight into JavaScript? Will it be used by a reporting engine? The context matters because it determines how we encode the data. Different contexts are concerned with different characters. Can I just throw data into the database with an html encoding context? At this point, I am transforming the data at a time where there is no transformation required. Cross-site scripting doesn’t execute in my SQL column.

A Better Approach

As you can see, the above techniques are useful, however, they appear insufficient for multiple reasons. I recommend performing the output encoding immediately before the data is actually used. By that, I mean to encode right before it is output to the client. This way it is very clear what the context is and the appropriate encoding can be implemented.
Don’t forget to perform input validation on your data, but remember it is typically not meant to stop all attack scenarios. Instead it is there to help reduce them. We must be aware that other applications may access our data and those applications may no follow the same procedures we do. Due to this, making sure we make encoding decisions at the last moment provides the best coverage. Of course, this relies on the developers remembering to perform the output encoding.