John Melton's Weblog
Java, Security and Technology

The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

No Gravatar

This article will describe how to protect your J2EE application from Failure to Restrict URL Access attacks using ESAPI and other techniques. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

What does Failure to Restrict URL Access mean? As usual, let’s check in with what OWASP says it is:

“Frequently, the only protection for a URL is that links to that page are not presented to unauthorized users. However, a motivated, skilled, or just plain lucky attacker may be able to find and access these pages, invoke functions, and view data. Security by obscurity is not sufficient to protect sensitive functions and data in an application. Access control checks must be performed before a request to a sensitive function is granted, which ensures that the user is authorized to access that function.” [from here]

Wow, what does all that mean? Well, the Failure to Restrict URL Access (hereafter referred to as URL authz) is simply a failure of performing a subset of authorization. Authorization is a large topic, with many volumes already written on it, but a short overview here will be helpful to the discussion. Authorization is typically described as ensuring a user has access to something, either a business function, data or both. Here’s a simple example:

User Mary makes a request to delete account id 375.

This statement requires authorization verification. Before we look at authorization, it is assumed that the authentication has already been performed, hence Mary is verified to be Mary. Now for the authorization, we must validate that Mary has access to the “delete account” business function and that she can perform that action for account id 375.

There are many, many ways to perform authorization, some better than others. There are 3 basic issues that crop up when dealing with authorization for the developer: security, granularity and maintainability.

The security piece is foundational – is the implementation secure. If a user requests a resource, the authorization should:
1. execute on every configured request (which should be all requests, except possibly static resources available to everyone)
2. allow access if the user has rights to the function and/or data
3. deny access if the user does not have rights to the function and/or data

The granularity piece has to do with flexibility in specifying restrictions about the authorization constraints. Using our example above, the simplest correct authorization would validate 2 things:
1. that Mary has access to the “delete account” function (meaning presumably she could run this function on any data she has access to).
2. that Mary has access to account id 375 (meaning presumably she could run any function she has access to on this data).

A more complex authorization scheme for this same example might provide more granular controls. It may allow Mary to have access to thousands of accounts, and a handful of various functions, but there may be some accounts she has read-only access to, some she can write to, and some she has full access over. Additionally, there may be a limiting feature of time of day, something like Mary is only authorized to perform these functions between 8am – 5pm (normal work hours). Other limits can certainly be thought of as well.

Obviously the second description has more granularity in specifying constraints, but this implementation will also have to be more complex, and more data will have to be captured to provide the matrix of information required to make an authorization decision.

The maintainability piece deals with the complexity of the design, implementation and stored data as mentioned above in the granularity section. The balance between simplicity of implementation and flexibility is an application specific decision. However, some of this complexity can be reduced by using pre-built solutions like ESAPI, as we’ll see shortly.

Ok, now we’ve covered a bit about authorization in general, let’s discuss URL authz in a bit more detail. URL authz is about a user gaining access to a URL that they should / should not have access to. Using the same example above, the request for a business function to delete an account might be a url like:

/myapp/account/delete?id=375

This is how a request is made in a web app, through URL’s. From this request, we know the user is looking to delete an account from the url, and the account id is 375 from the parameter. In order to validate that this is a valid request, we need to make sure that the user should be able to access the delete account URL. There are a couple of locations this could be done: from the referring page, and from the request handling function itself. You must use the latter, and should use the former for user experience. So, if I’m on the view accounts page, and I do NOT have access to delete, I should not even see the link/button for delete – that’s about user experience. However, if my application prevents the link from displaying, but the user were to directly type it in, he would still have access if I didn’t prevent the access from the request handling function as well. This bit of pseudocode will help get the point across:


JSP code
//if user has access to delete
	show link to delete page
//else
	show nothing

-----------------

in the servlet/action handling the delete request
//get the user performing the request
//get the account id
//if the user has access to delete this data
	proceed
//else
	throw some error, log issue, possibly respond in some way to attempted "hack"

Both of these checks are important, but the second is vital to protecting the application. Doing the first only is a form of security by obscurity, which almost always provides very little protection. It won’t be long until the user guesses that this url exists, or until he sees another user access it, and then is able to get there.

Where do we go from here? ….

Ok, so we’ve now described how standard authorization and specifically URL authz works, let’s see a few practical tips and tricks about how to implement it.

1. Think about authorization at the beginning of the application architecture and design if possible. This can make things much simpler down the road. You can come up with a defined naming scheme to follow or any other host of ideas to simplify the task at hand.

2. Always authorize URLs at the time of the request processing (for security), and you should authorize access at the time of providing a link (for uxp).

3. Pen-test if possible – use both automated and manual testing. This can help ensure a decent sampling of urls are not accessible. Even if you can’t do it exhaustively, it will help build confidence in your solution if a subset works. If you can exhaustively test – all the better.

4. Remember included files – these can be forgotten sometimes, but these can often be accessed.

5. Put all your UI files under /WEB-INF, and use a solution that displays your pages by accessing the pages and rendering them to the user. There are various ways to accomplish this, including straight servlets as well as many frameworks (struts, spring, JSF, etc). Having your pages under /WEB-INF prevents them from being directly accessible to the end user per the J2EE spec.

6. Don’t rely on the security by obscurity argument that no-one will know your urls – automated tools can find these, and even intelligent testers often can make educated guesses about urls based on other urls … it’s a good bet that /account/delete exists if /account/view exists.

7. Use an application intrusion detection system (like AppSensor) in order to detect and possibly respond to attacks in production where people are doing things like forceful browsing to pages that don’t exist in your system.

8. If possible, use a tool or framework that already provides a solid authorization design to use for your environment so you don’t reinvent the wheel. There are many tools out there that do this for you, but your mileage definitely varies here. I’ll mention 2 that I’ve used: ESAPI and Spring Security. Spring Security works well for many cases since it’s quite simple and has good integration to Spring itself if you’re already using that framework. ESAPI is certainly more flexible and extensive, but you’ll likely have to do a bit more legwork to get the system hooked up to your application. Once done though, it does offer more features.

Here are the methods in the AccessController interface that is part of ESAPI. These are the methods you would use to perform authorization in your system:


    public boolean isAuthorized(Object key, Object runtimeParameter);
    public void assertAuthorized(Object key, Object runtimeParameter) throws AccessControlException;

    boolean isAuthorizedForURL(String url);

    boolean isAuthorizedForFunction(String functionName);

    boolean isAuthorizedForData(String action, Object data);

    boolean isAuthorizedForFile(String filepath);

    boolean isAuthorizedForService(String serviceName);

    void assertAuthorizedForURL(String url) throws AccessControlException;

    void assertAuthorizedForFunction(String functionName) throws AccessControlException;

    void assertAuthorizedForData(String action, Object data) throws AccessControlException;

    void assertAuthorizedForFile(String filepath) throws AccessControlException;

    void assertAuthorizedForService(String serviceName) throws AccessControlException;

So, in order to accomplish our task of verifying that a user has access to a certain url, you could use the is/assertAuthorizedForURL() methods, or the generic is/assertAuthorized() methods and pass in parameters specifying you want to authorize a URL and the actual URL data. Please note that this may require you write your own AccessController implementation to integrate with your application and configure ESAPI to use it as the AccessController. Alternatively, you could use one of the reference implementations and build your application so that it uses the ESAPI mechanisms to deal with authorization. Either way, ESAPI’s AccessController interface does allow flexibility in performing authorization of methods and data in your application.

So there you have it. URL authz is a subclass of generic authorization in your application. Authorization is an important concept to focus on during the entire development lifecycle, and URL authz is an important implementation detail that you need to get right when building J2EE apps.

Well, that’s it. Hope you’ve found this article helpful. Let me know if you have any questions or suggestions. Feel free to comment.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Technorati Tags: , , , , ,

The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications

No Gravatar

This article will describe how to protect your J2EE application from Insecure Communications attacks using ESAPI and other techniques. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

What does Insecure Communications mean? As usual, let’s check in with what OWASP says it is:

“Applications frequently fail to encrypt network traffic when it is necessary to protect sensitive communications. Encryption (usually SSL) must be used for all authenticated connections, especially Internet-accessible web pages, but backend connections as well. Otherwise, the application will expose an authentication or session token. In addition, encryption should be used whenever sensitive data, such as credit card or health information is transmitted. Applications that fall back or can be forced out of an encrypting mode can be abused by attackers.” [from here]

Insecure communications is an issue any time data traverses a communications path. For many standard J2EE apps, you’ve got a setup like the following you have to worry about:

- client browser -> web server
- web server -> app server
- app server -> DB server
-> LDAP server
-> JMS server

This is a simple but very common setup for J2EE apps. There are many more layers that could be added, and even a few could be taken away. Here’s the point: you need to think about insecure communications at every tier. You could make the argument that the browser -> web server connection is the most important, and I might even partially agree with that since that’s where the most nefarious things tend to live: on the wide open web. Still, the app server -> DB server connection is pretty important due to the data being transmitted. The point is, all the layers are important since important data is moving from point A to point B.

We know we’ve got to protect the data “in transit”, ie. as it moves across the wire, so …

Where do we go from here? ….

Protecting against insecure communications could take many forms, but in the web app/J2EE world, it primarily means SSL/TLS, so that’s what we’ll discuss here. That’s right, our good old friend SSL/TLS. For the uninformed or if you just need a good refresher, have a look at this great doc produced by the good people at OWASP.

The use of SSL/TLS is not as easy as flipping a switch, as you might hope or think. There are various issues that have to be taken into consideration. I don’t want to simply re-hash all of the recommendations provided by OWASP, so I’ll try to focus on those most commonly seen by the J2EE crowd. (All the issues called out are important, but not necessarily developer-oriented – some are more frequently handled by network/sys admins.)

Most of us know what SSL/TLS does, but in case you don’t, the intent is to encrypt the data as it is in transit between points A and B. Note: There is no protection provided at the endpoints, but the issue at hand is protecting data while in transit, so SSL/TLS fits the bill.

Now that we know we need SSL/TLS, how do we implement it correctly? There are millions of pages dedicated to setting up SSL/TLS, so let’s assume you’ve gone through that and now need to require it for your particular application. There are various ways to do this. Let’s talk about a few.

1. Setup your web/app server to only have an SSL/TLS (https) enabled service listening, ie. no standard http service running, or at least block that port on the firewall. This option is fine if you can do it, but there’s usually a reason you can’t, and in addition, it doesn’t help if anyone ever comes along and adds http back in – at that point – you’re back at square one.

2. The standard Java way is to add a transport guarantee to the web.xml file. The following snippet shows an example.


    <security-constraint>
        <web-resource-collection>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

This snippet requires all requests that match the pattern “/admin/*” to go over SSL/TLS. If they are requested over standard http, the request will be redirected over https. This is a fine solution if your application is structured in a manner that you can protect the appropriate urls by using simple url pattern matching. If that’s not true, this method can lead to a rather verbose configuration.

3. The ESAPI way of performing this task is also very simple. This can be done by using the assertSecureChannel method as in the following snippet.


    //this method can throw an AccessControlException 

    //uses the current http request - there is an overloaded method that accepts
    //a specified http request object as a parameter
    ESAPI.httpUtilities().assertSecureChannel();

If this method finds that SSL/TLS is not being used, it does not attempt to redirect you there. Rather it throws an AccessControlException, which can then be caught and dealt with appropriately. If you’d like all of your pages to require SSL, this code could simply be added to a J2EE filter configured to execute on all requests (“/*”).

4. Other frameworks … there are tons of frameworks, or even custom code that could be used to perform this task.

Ok, now we’ve seen a bit about how to require SSL/TLS in the J2EE environment, let’s talk about a few of the relevant gotchas that J2EE folks have to deal with.

1. Make sure you use SSL/TLS between all tiers. Don’t cover just the browser -> web server. Ensure every path is protected.

2. Require SSL/TLS for all login (including page you login from) pages as well as any authenticated pages after login.

3. Use http POST as opposed to http GET for any sensitive information. This is always true, but makes even more sense with SSL/TLS as the POST data is protected by SSL/TLS, but the url is not as that is required to make the request. This means others viewing your request can still see your sensitive data since it’s part of the url.

4. Mark all your user cookies secure: this prevents your browser providing the session cookie to an attacker in the event of an attack that causes you to request a non-SSL/TLS url from the application. If the cookie is not secure, your browser will still happily provide the cookie even if the site doesn’t support http … protect your users.

5. Don’t put any insecure content on your secure pages. This could allow an attacker to “inject” content into the page and have that information presented to a user as if it came over the SSL/TLS connection.

6. Often times it is just easier to protect the entire site with SSL/TLS. This is fine, but be aware of any performance concerns. SSL/TLS does require overhead. It’s gotten pretty optimized over the years, but it will always be slower than http. If you are on a high volume site, think about what data you are presenting, and test both with and without SSL/TLS to verify any performance differences. However, no matter the performance difference, always follow the other rules listed here. Protection of data is better than a slightly faster site (since we are talking about security here :>).

7. Stay educated and patch when necessary. SSL/TLS has been a standard technology for many years now. However, just within the past few months, there have been reasonably large bugs found and resolved. Largely, these bugs have to do with implementation and not design, however you need to stay educated nonetheless.

8. Comply with policy / legal regulations. For some types of data (credit cards and SSN’s for instance), there are legal requirements imposing the use of SSL/TLS to protect the data in transit. These may or may not apply to you, but be sure you know, because failing to meet them could be a very bad thing indeed.

So there you have it. SSL/TLS is fairly well known, but there are some things to look out for when building a site that uses it.

Note: In very recent days, news came out that Robert “RSnake” Hansen and Josh Sokol were able to poke some pretty major holes in SSL. I have not had the time to adequately research their findings, but you should. I do assume, based on the credence of the researchers, that the research is sound, so pay attention. This does however point to the fact that a defense-in-depth approach to security as well as building security in at every layer are best practices.

For some additional background and information on SSL/TLS, see the Transport Layer Protection Cheat Sheet referenced above.

Well, that’s it. Hope you’ve found this article helpful. Let me know if you have any questions or suggestions. Feel free to comment.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Technorati Tags: , , , , , , ,

The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage

No Gravatar

This article will describe how to protect your J2EE application from Insecure Cryptographic Storage issues using ESAPI and other techniques. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

First, let me start off by saying Crypto is hard, really hard. There are various aspects to cryptographic security, and all of them are difficult to get right. Some examples include creating an algorithm, using the algorithm and key management. Typically, developers aren’t creating algorithms. That is often done by (really smart PhD) mathematicians, and a small set of developers who implement those algorithms. However, many developers do “use” those algorithms to do some type of encryption in their applications. Developers also have to deal with key management.

Let me additionally state here that I am by no means an expert on this topic. I have some background with crypto, but I certainly don’t have a lot, so much of what’s presented here are generally accepted best practices, and don’t necessarily come from my own experience. OK, on to the detail…

What does Insecure Cryptographic Storage mean? As usual, let’s check in with what OWASP says:

“Protecting sensitive data with cryptography has become a key part of most web applications. Simply failing to encrypt sensitive data is very widespread. Applications that do encrypt frequently contain poorly designed cryptography, either using inappropriate ciphers or making serious mistakes using strong ciphers. These flaws can lead to disclosure of sensitive data and compliance violations. ” [from here]

So, this is pretty self-explanatory. If something can go wrong, it will with crypto. There are lots of reasons why this is probably true. First, it’s hard to get right in the first place – there are a lot of moving parts. Second, developers typically don’t understand it as well as other aspects of software. Third, it’s rare. A small number of people have been dealing with crypto for a long time, but it’s only a relatively recent development that LOTS of devs have been impacted by it. Part of this is due to new regulatory constraints that require encryption of some kind for data at rest.

Where do we go from here? ….

Now that we’ve established that crypto storage is hard, let’s talk about a few common approaches that can help remedy the issues.

1. Stay Educated. This is an important step. Due to the increase in computing power that we gain every year, as well as new cryptanalytic (breaking a crypto algorithm) attacks, the list of “good” algorithms is somewhat of a moving target. Typically, if you’re in the US, NIST (nist.gov) is a good place to check as they set crypto standards. Additionally your workplace may have a set of approved standards that you would need to follow. Also, read books to learn about crypto. You may not be the mathematician coming up with the algorithms, but there is much to learn here that will benefit you.

2. Use good algorithms. This is a follow on to the first point, but it’s important enough to call out separately. Do NOT create your own crypto algorithm unless you’re an expert – it is very difficult to get right. Even the guys at the top of the field tend to create algorithms as part of a team, and those algorithms are generally only accepted as secure after years of analysis by peers. Additionally, do NOT use old, weak algorithms. These could help to a point, but many of them are able to be broken in minutes or even seconds these days. It’s easy enough to use solid algorithms, so educate yourself and make the right choices.

3. Do good key management. This is a broad topic which I don’t even pretend to comprehend fully. There are many possible ways this could work. At the current time, it’s even an active discussion among the ESAPI developers over how they plan to do it. There are various options from just hard-coding a key (DON’T DO IT) all the way up through large commercial systems to do key management for you. Spend some time thinking over your requirements, and make an informed decision.

4. Encrypt credentials. Pretty much every J2EE system connects to a DB, LDAP, web service or some other repository. The credentials to make these connections should be encrypted to prevent easy access to these data storage systems.

5. Don’t store sensitive data if it’s not a requirement. Storing sensitive data is what introduces these complexities. It’s better if you don’t have to worry about them in the first place. Only store sensitive data when there is a firm legal or business requirement.

6. Know your regs. Know your legal and regulatory requirements. There are certain provisions in these requirements that prevent the storage of certain pieces of data EVER. Storing this data not only places additional requirements on your application, it can carry some hefty fines for breaking these laws.

7. Simplify. It’s the old KISS principle. However, when it comes to crypto, it’s certainly true. Do the least you’re required to do in order to store sensitive data securely. The more complex a system, the more difficult it is to secure generally.

8. Store the key/password/data separately. These pieces of information make up your data protection mechanism. Storing them in the same place makes it simpler for an attacker to gain access to all of them. If they are stored separately, an attacker may still gain access to all of them, but it’s more difficult.

9. Use filesystem controls. Operating systems have filesystem access controls for a good reason – so you will use them. Protecting data is a defense in depth task, but protecting the keys, passwords, etc. with filesystem controls locked down so only the appropriate user(s) has access is a best practice measure to help secure your data.

One thing to note here is that I did not add any sample code snippets for this topic. This was intentional. At the moment, the ESAPI encryptor implementation is going through a fairly significant update and code review. There is still some discussion of major changes coming. Either way, ESAPI will provide support to encrypt/decrypt and hash data. The interface to that functionality may change, but the library will provide those features – you can be sure of it.

Well, that’s it. Hope you’ve found this article helpful. Let me know if you have any questions or suggestions.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Technorati Tags: , , , , ,

The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management

No Gravatar

This article will describe how to protect your J2EE application from Broken Authentication and Session Management issues using ESAPI and other techniques. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

What does Broken Authentication and Session Management mean? As usual, let’s check in with what OWASP says:

“Flaws in the main authentication mechanism are not uncommon, but weaknesses are more often introduced through ancillary authentication functions such as logout, password management, timeout, remember me, secret question, and account update.” [from here] They go further to say the goal in resolving these types of issues is “to verify that the application properly authenticates users and properly protects identities and their associated credentials.”

The idea here is that of providing assurance that a given user can gain access to their account if one exists, and only that account. This is a complex topic that covers many aspects, only some of which we’ll be addressing here.

If this issue is not properly addressed, various problems arise. These can include accounts being hijacked, credentials stolen, data being compromised, etc. Beyond the issue of losing data, there is obviously a huge reputational risk with these types of issues as well. Essentially you are dealing with the keys to the kingdom – if they’re lost – noone trusts your application!

Where do we go from here? ….

Now that we’ve briefly discussed what can occur if this issue is not addressed properly, let’s talk a bit about some steps we can take that can remediate the issue when properly applied. For this section, I’ve heavily used this article.

1. Use the built-in session management features. Session management is difficult to get correct. Even though app servers have been doing it for years, there are still bugs being reported with reasonable frequency. It is foolish to think that you’ll do better on your first try.

2. With regards to authentication:
- Use a single entry point. Don’t write and rewrite auth code – write it once, and try to get it right
- Make sure login starts on an SSL-protected page.
- Invalidate the HttpSession before login and after login. This helps prevent session fixation attacks where an attacker can specify a session id for a user to use. Invalidating the session id guarantees the attacker doesn’t have access to the new session id.

3. Get logout right. Make sure it’s accessible throughout the application with a single click, and make sure it invalidates the session and anything else that may be being used in the auth process, such as a cookie.

4. Add a timeout. A session timeout (and associated handler) should be configured to grab sessions that have timed out and clean them up so they are not available for reuse. Obviously, the shorter the time for the timeout, the less risk – the longer the time, the more user friendly. Find the balance you need for your application – personal opinion – 30 minutes is often plenty of time for many sites with anything valuable on them.

5. Ensure you are using safe related functions. Functions like security questions and answers, forgot password, forgot username, change password are difficult to get right. When done improperly, they can leak information about the account, and outright cause loss of credentials. Be sure to find as much information as you can about how to get these functions right before implementing them. Then test them to death – both unit tests and functional tests.

6. If you’re in a situation where it’s possibly, use strong authentication. This would mean using 2 or more of the 3 possible factors: something you know, something you have, and something you are. Typical username/password (something you know) systems are prevalent, but if you could add a token (something you have), then you levy an additional requirement on the user, but you also reduce the risk of someone gaining access that shouldn’t (assuming your authentication is sound).

7. Default to not authenticated. It sounds simple, but folks do (more often than you might think) code systems that default to authenticated on login. The code would look something like this:


//BAD - DON'T USE
public boolean login(String username, String password) {
    boolean isAuthenticated = true;

    try {
	//make calls to backend to actually perform login against datastore

  	if (! authenticationSuccess) {
	    isAuthenticated = false;
	}
    } catch (Exception e) {
	//handle exc
    }
    return isAuthenticated;
}

As you can see, the user is set to authenticated by default, and if an exception is thrown, the user is logged in. This would fall under the security mantra of secure defaults. Unfortunately code like this is surprisingly common in systems today (but hopefully not yours).

OK, well that’s all I’ll cover in this article. Let me add just one more simple word of caution: authentication and session management are difficult and complex topics. It is very naive to think that you will get it right on your first try. Please consult with folks like OWASP and other secure development resources to get a broader picture of the types of issues that need to be addressed in this space. Educate yourself as much as you can. Use other’s good code that’s been vetted if it’s available. If not, take your time – think through the types of attacks that are possible, do code reviews, get others to do code reviews, and test test test.

Well, that’s it. Hope you’ve found this article helpful. Let me know if you have any questions or suggestions. Feel free to comment on techniques you are using to correct Broken Authentication and Session Management issues.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Technorati Tags: , , , , , ,

The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling

No Gravatar

This article will describe how to protect your J2EE application from Information Leakage and Improper Error Handling attacks using ESAPI and other techniques. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

As usual, let’s check in with what OWASP says it is:

“Applications frequently generate error messages and display them to users. Many times these error messages are quite useful to attackers, as they reveal implementation details or information that is useful in exploiting a vulnerability.” [from here]

This can be broken down further into two basic categories from the web end user perspective.

  • An error message with too much detail (eg. stack trace, sql statement, etc) is splashed onto the screen.
  • An error message for a specific function varies depending on minor changes to the input enabling the user to determine exactly what error occurred (eg. a different error message for a bad username and a good username/bad password – this tells the attacker the username is valid.)

The two categories above really differ at the level of concern. The issue of too much detail often stems from sending information to the screen that is internal to the application – information that has more to do with the code and/or configuration of the application. Often times these messages are NEVER intended to be shown to the end user. This is a technical issue. The issue of specificity in error messages has to do with user messages that ARE intended to be seen by users. However, the wording for them is poorly chosen. This is a business issue of coming up with appropriate messages.

One sidebar note here is that of exception handling. Appropriate exception handling in Java is often a topic of debate. One of the main issues stems from that of the difference between 2 core classes: Exception and RuntimeException.

1. The former (Exception and any subclass) is referred to as a checked exception, meaning that any code that calls any other piece of code that may throw one of these exceptions HAS to handle it in some way, either by wrapping the code in a try/catch block, or by explicitly throwing the same exception (or a superclass) in the method signature. Proponents argue that this forces developers to be aware of the types of exceptions that code may throw, and deal with them appropriately. Opponents argue that this can complicate code and cause many developers to trap exceptions and not deal with them properly or at all, which is worse than bubbling them up in the first place.

2. The latter (RuntimeException and any subclass) is referred to as an unchecked exception, meaning code may or may not deal with these exceptions, it is their choice. Proponents argue that this allows flexibility in handling exceptions and provides for cleaner code. Opponents argue that exceptions of this variety essentially don’t “notify” their callers of the types of exceptions they may throw, and therefore the calling code is less reliable.

Honestly, no matter where you land in this debate, the issue of information leakage still exists for J2EE web applications today. At the very least, NullPointerExceptions exist in every J2EE app known to man, so it’s still possible to bubble up an exception even if your entire application exception heirarchy is checked, so the information presented here is still very relevant.

So far, we’ve noted the types of application error messages that can be leaked to the end user, as well as a brief discussion about the internal exception management of an application.

Where do we go from here? ….

There are various specific techniques for dealing with information leakage and improper error handling. Several of these techniques are valid. The point of this article is not to try and enumerate all of them, but to create a working safe solution that can be implemented. Your solution may vary in style, but the underlying principles should be the same: preventing (as much as is reasonable) the attacker from gaining information from your system that can be used in an attack.

Again as above, we’ll break the discussion into 2 parts: missing exceptions altogether, and handling error messages improperly (often by giving too detailed of an error message).

1. First we’ll discuss how to resolve presenting the user with unhandled exceptions. These fall into the category of “should NEVER be presented to the user”. First, these occur because all possible exceptions are not handled in every piece of code. The first thing to note here is that your application should have a standard for how it handles exceptions. Ignored exceptions are an epidemic in Java (and other languages), but that is too large a topic to tackle here. No matter your standard for handling exceptions, inevitably there are going to be some places where you might miss them. Even if you handle everything you think you ought, there may be a JSP issue that would present an exception to the user.

My suggestion for how to handle this is a J2EE standard technique and quite simple to implement: configure an exception handler in the web.xml configuration file. An example of how to do this is below.


<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/error.jsp</location>
</error-page>

This is a very simple solution to handle any subclass of java.lang.Throwable (which covers all types of exceptions) that gets bubbled up through the application, whether by a servlet, jsp, or some framework specific code and preventing the user from seeing it. What it will do then is redirect the user for any previously unhandled exception it catches to /error.jsp. This page should have some generic text on it stating that an error occurred, and should not give specifics as to what that error is.

Note: MVC frameworks often offer an exception handling mechanism that is intended to do this same thing. However, be aware that many of these do not work if the exception occurs in the JSP page since that is outside the scope of what the framework controls. Another viable option in many cases is to use a J2EE filter to do appropriate exception handling since the filter is accessed both before and after the servlet/jsp request is performed, and can catch exceptions that occur in either of them.

2. The second type of issue is caused by giving the user too much information in an error message on the screen. Often times the error message that is sent to the screen is populated with the exception message. This is a dangerous technique since this data could often be very detailed and could give an attacker technical information about the system.

My suggestion for how to get around this involves using 2 techniques in cooperation.

a. First, for any exception in your application exception heirarchy, create member variables along the lines of userMessage and detailedMessage. ESAPI does this with their exception heirarchy, so you can browse their code for examples. The logic is that when these exceptions are created, they are created with very generic information for the user to see, and then the detailed information can be logged for admins to see. The user should only ever be presented with the generic message.

b. Second, for exceptions that don’t live in your application heirarchy (and even those that do in some cases), one should use a static very generic message to display on the screen for any security related issues. The example used above (using a different error message for a bad username and a good username/bad password – this tells the attacker the username is valid.) could be resolved by using a somewhat generic error to cover both errors, possibly “The user could not be logged in” or “Login failed”. This conveys the message to the user that the login failed, but doesn’t give specific information about why.

Note: One important point here is that this issue is a balancing act between user friendliness and security. It may save your users some frustration if they see that they’ve typed in the wrong username (honest mistake) rather than the wrong password, but that also gives an attacker opportunity. This decision, like most others must be considered in the context of your environment. My suggestion is to go with the more secure option by default, and only change if you absolutely must. Even then, you should consider putting additional protections in place, such as possibly using an ESAPI style application intrusion detection mechanism like AppSensor to track things like a user trying to login with many different usernames in a short period of time.

At this point, hopefully you’ve gotten a glimpse of how information leakage and improper error handling can negatively affect your application. Additionally, you’ve gained some insight on how to deal with exceptions and user messages properly. As mentioned before, there are various legitimate techniques that could be used, and the above is just one option.

Well, that’s all for this article – hope you’ve found it helpful. Let me know if you have any questions or suggestions.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Technorati Tags: , , , , , ,

The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)

No Gravatar

This article will describe how to protect your J2EE application from Cross Site Request Forgery (CSRF/XSRF) attacks using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

What is Cross Site Request Forgery (CSRF)? As usual, let’s check in with what OWASP says it is:

“A CSRF attack forces a logged-on victim’s browser to send a request to a vulnerable web application, which then performs the chosen action on behalf of the victim. The malicious code is often not on the attacked site. This is why it is called ‘Cross Site’. ” [from here] Additionally, they give several examples of the types of vulnerable sites including sites that “Authorize requests based only on credentials that are automatically submitted such as the session cookie if currently logged into the application, or ‘Remember me’ functionality if not logged into the application, or a Kerberos token if part of an Intranet participating in integrated logon with Active Directory”. Finally this statement is added: “Unfortunately, today, most web applications rely solely on automatically submitted credentials such as session cookies, basic authentication credentials, source IP addresses, SSL certificates, or Windows domain credentials.”

So, what does all this mean? It means that (most likely) if you aren’t protecting against CSRF, you are vulnerable to it. That’s a scary thought! Many developers don’t even know about the attack (though they should), yet they are vulnerable by default in many instances. It’s a devastating attack to many web applications. Let’s discuss in a bit of detail what it looks like. In my opinion, the easiest way to explain the attack is to walk through it in a series of steps.

1. Bob (User/Victim) logs in (or is already logged in) to “Vulnerable website X”. This website has contains some sort of e-commerce type functionality. It also allows you to store your credit card for future purchases.
2. Mary (Attacker) knows and uses website X and realizes that CSRF is a vulnerability in the application.
3. Mary crafts a bit of html and/or javascript and posts it to a forum/message board that Bob reads (any site on the internet).
The code might look something like this:


<img src="http://www.siteX.com/completePurchase.do?itemId=ABC123" />


4. Bob views the html and/or javascript by visiting the forum (though nothing visible shows up) and the code is executed. Bob has just purchased an item of the attacker's choosing without knowing it.

Ok, a few things to note about the sequence above.
a. The vulnerable site doesn't have to be e-commerce. It could be credit card related info, or adding a friend to your group. For the most part, it has to do with transactions. Usually, it's not a big deal on "view" type pages.
b. The forum/message board, while common, is not the only way to cause this. It could be done through an email, or any other number of attack vectors.
c. The actual attack here was fairly benign, but be certain, there are more nefarious attacks that exist, and are executed all the time.

Ok, so hopefully you are sufficiently concerned now based on the description above.

Where do we go from here? ....

So, now we understand what can happen if a site is vulnerable to CSRF (and most are), but what how do we solve that problem. Well, simply put, we have to have a way to know that the request is legitimate, meaning that the user intended to make the request. The most common mechanism in place today (that works) is the token. The token is a generic term that is used for implementations of the "synchronizer token pattern". There are several working implementations that use the token today, including Struts 1 and 2, Webwork, SpringMVC, and even OWASP's own CSRFGuard Project. However, since we're discussing the usage of ESAPI to solve the OWASP Top Ten, we'll cover how ESAPI does it in this article.

At this point, CSRF is actually pretty easy to solve. We know what the issue is, know how to solve it, and have a framework (ESAPI) that will help with the specifics. So, here are the steps we'll actually go through in order to protect our apps from CSRF attacks.
1. Generate new CSRF token and add it to user once on login and store user in http session.
2. On any forms or urls that should be protected, add the token as a parameter / hidden field.
3. On the server side for those protected actions, check that the submitted token matches the token from the user object in the session. (Assuming you've implemented this properly, a failure constitutes a security issue.)
4. On logout and session timeout, the user object is removed from the session and the session destroyed.

Now that we have the steps, we'll give a short snippet of code that shows each in action.

Step 1. Generate new CSRF token and add it to user once on login and store user in http session.
This code should be executed when the user logs into the application. This is done in the default ESAPI implementation, and it is stored as a member variable of the User object that gets stored in the session.


//this code is in the DefaultUser implementation of ESAPI

/** This user's CSRF token. */

private String csrfToken = resetCSRFToken();

...
public String resetCSRFToken() {

	csrfToken = ESAPI.randomizer().getRandomString(8, DefaultEncoder.CHAR_ALPHANUMERICS);

	return csrfToken;

}

Step 2. On any forms or urls that should be protected, add the token as a parameter / hidden field.
The addCSRFToken method below should be called for any url that is going to be rendered that needs CSRF protection. Alternatively if you are creating a form, or have another technique of rendering URLs (like c:url), then be sure to add a parameter or hidden field with the name "ctoken" and the value of DefaultHTTPUtilities.getCSRFToken(). That should do the work of adding the data to the url or form. We'll validate it in the next step.


//from HTTPUtilitiles interface
final static String CSRF_TOKEN_NAME = "ctoken";

//this code is from the DefaultHTTPUtilities implementation in ESAPI

public String addCSRFToken(String href) {

	User user = ESAPI.authenticator().getCurrentUser();

	if (user.isAnonymous()) {

		return href;

	}

	// if there are already parameters append with &, otherwise append with ?

	String token = CSRF_TOKEN_NAME + "=" + user.getCSRFToken();

	return href.indexOf( '?') != -1 ? href + "&" + token : href + "?" + token;

}

...

public String getCSRFToken() {

	User user = ESAPI.authenticator().getCurrentUser();

	if (user == null) return null;

	return user.getCSRFToken();

}

Step 3. On the server side for those protected actions, check that the submitted token matches the token from the user object in the session. (Assuming you've implemented this properly, a failure constitutes a security issue.)
Ensure that you call this method from your servlet or struts action or jsf controller, or whatever server side mechanism you're using to handle requests. This should be called on any request that you need to validate for CSRF protection. Notice that when the tokens do not match, it's considered a possible forged request.


//this code is from the DefaultHTTPUtilities implementation in ESAPI

public void verifyCSRFToken(HttpServletRequest request) throws IntrusionException {

	User user = ESAPI.authenticator().getCurrentUser();

	// check if user authenticated with this request - no CSRF protection required

	if( request.getAttribute(user.getCSRFToken()) != null ) {

		return;

	}

	String token = request.getParameter(CSRF_TOKEN_NAME);

	if ( !user.getCSRFToken().equals( token ) ) {

		throw new IntrusionException("Authentication failed", "Possibly forged HTTP request without proper CSRF token detected");

	}

}

Step 4. On logout and session timeout, the user object is removed from the session and the session destroyed.
In this step, logout is called. When that happens, note that the session is invalidated and the current user object is reset to be an anonymous user, thereby removing the reference to the current user and accordingly the csrf token.


//this code is in the DefaultUser implementation of ESAPI

public void logout() {

	ESAPI.httpUtilities().killCookie( ESAPI.currentRequest(), ESAPI.currentResponse(), HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME );

	HttpSession session = ESAPI.currentRequest().getSession(false);

	if (session != null) {

		removeSession(session);

		session.invalidate();

	}

	ESAPI.httpUtilities().killCookie(ESAPI.currentRequest(), ESAPI.currentResponse(), "JSESSIONID");

	loggedIn = false;

	logger.info(Logger.SECURITY_SUCCESS, "Logout successful" );

	ESAPI.authenticator().setCurrentUser(User.ANONYMOUS);

}

So there you have it. Not very complex, but solid protection against CSRF. In quick review, we covered what CSRF is, why it's a problem, and how to solve it using 4 simple steps (create token, add token to forms/urls, verify token server side, kill token on logout). There are a couple of additional notes I wanted to point out.

Note: In addition to resolving the CSRF issues in your application, you also need to resolve the XSS issues in your application (see The OWASP Top Ten and ESAPI - Part 2 - Cross Site Scripting (XSS)). If those still exist, the CSRF defenses can be circumvented.

For some additional background and information on CSRF, see the OWASP CSRF Prevention Cheat Sheet.

Well, that's it. Hope you've found this article helpful. Let me know if you have any questions or suggestions. Feel free to comment on techniques you are using to correct CSRF and if you've seen it as a large problem for your applications.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI - Part 1 - Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI - Part 2 - Injection Flaws
Part 3: The OWASP Top Ten and ESAPI - Part 3 - Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI - Part 4 - Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI - Part 6 - Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI - Part 7 - Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI - Part 8 - Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI - Part 9 - Insecure Communications
Part 10: The OWASP Top Ten and ESAPI - Part 10 - Failure to Restrict URL Access

Technorati Tags: , , , , , ,

The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference

No Gravatar

This article will describe how to protect your J2EE application from direct object reference (DOR) attacks using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

What is direct object reference (DOR)? Other than being a somewhat quirky, generic name … here’s what OWASP says it is:

“A direct object reference occurs when a developer exposes a reference to an internal implementation object, such as a file, directory, database record, or key, as a URL or form parameter. An attacker can manipulate direct object references to access other objects without authorization, unless an access control check is in place. ” [from here]

So, what does that mean? Well for most (not all) J2EE developers, it will mean database key references, so that’s what we’ll deal with here. However, the discussion is applicable no matter what your reference.

Consider the following database table called USERS.

ID FNAME LNAME
1 John Melton
2 Bill Smith
3 Susan Thomas
4 David Carter

Now, let’s say that this database table were queried in a normal application. Then, the results are presented on the page, and each record in the result list would probably have a link to more detail about each user, having their pictures, their list of friends, etc. This is the typical master-detail interaction and is prevalent in pretty much any web app, not just J2EE. But how do we get to the detail page? How do we pass along which user we want to see in detail from the “master” table to “detail” page? Well, we could start by using the first name, but that’s not unique, or we could use the last name, but same issue. We could include both, which is less likely to produce duplicates but it’s still possible. In most situations, what happens is each table in the database has a column setup as a unique identifier. Each record in the table will have a different ID. So, that’s what we use. Now, here’s what the url might look like to go view greater detail about Bill:

/users/viewDetail?id=2

Ok, great, so what we have is the identifier being passed in the url to represent Bill. That way when we get to the view detail code, we simply check the id that was passed in and pull up that record in detail and display the information.

So where’s the issue? Well, everything works fine in this instance b/c every user is able to see the detail, but let’s look at what this might look like for a bank, which is the classic DOR example. In a bank, all records for all users are stored in the same table (at least in our example), however each user can only view his or her account. They should not be able to simply pick a random account to view or manipulate. But what if the URL to my account looks like:

/accounts/viewDetail?id=3540

What would happen if I changed this to

/accounts/viewDetail?id=3541

If there’s no protection in place, I can see someone else’s account!

Well, this is the crux of the DOR problem. Any attacker can manipulate url or form parameters at will when they submit a request, which means this issue obviously applies to both GET and POST requests, as well as exposed parameters, hidden fields, etc. If it’s being sent from the client to the server, the client can alter it. That means when you use the ID as the reference, and that ID can be manipulated, the attacker can gain access to data that they should not have access to. The ID in this case is the direct reference (id) to the object (record in the table) that you are trying to access.

Where do we go from here? ….

Well, ok, that’s not super encouraging. We have an issue (that most people have never heard of) that is affecting most applications . Banking is the obvious example, but this could be a problem for many different types of applications. Take heart, there is a solution (actually there are two)! You have 2 options for how to properly deal with this issue when it exists in your application.

1. Use ESAPI’s AccessReferenceMap (or something similar)
2. Perform authorization on the view detail page
Bonus. Use both! (the only way to go for paranoid people like me)

Let’s discuss the basic concepts of each of the options.

AccessReferenceMap

The AccessReferenceMap is an interface for a map which has methods that allow you to add a “direct” reference (which generates an “indirect” reference), then retrieve an indirect reference using a direct reference, or retrieve a direct reference using an indirect reference.

Confused yet? Me too. Actually it’s quite simple. Let’s use a contrived (and insecure) example just to illustrate the concept (again, this simplified version is NOT secure).

Let’s say you have a table in the database with 4 records, and their id’s are 1,2,3,4. Now let’s say you have the situation above where you display all these records in a master table, and each row is a link to more detail about the individual record. Let’s say you want to hide these numbers and reference them on the UI as letters instead. The simple mapping would be 1=A, 2=B, etc… In this case, when you retrieve the data from the database, your ids are 1,2,3,4. However, when you show them on the screen, their ids are A,B,C,D. Finally from the detail page (after the user clicks the link), you would just lookup what C matches, find that it is 3, then retrieve that record from the DB and display it. It’s that simple.

Now, in practice, obviously a letter -> number matrix is too simple to be effective. What works better, as usual in computer science, is randomness. That’s why ESAPI already contains a class called RandomAccessReferenceMap. Here’s an example of how you might use it.


MyObject obj;	 	// generate your object
Collection coll; 	// holds objects for display in UI

//create ESAPI random access reference map
AccessReferenceMap map = new RandomAccessReferenceMap();

//get indirect reference using direct reference as seed input
String indirectReference = map.addDirectReference(obj.getId());

//set indirect reference for each object - requires your app object to have this method
obj.setIndirectReference(indirectReference);

//add object to display collection
coll.add(obj);

//store collection in request/session and forward to UI
...

As you can see the code is fairly simple. Beyond this, the only other code is when it is displayed on screen, you use the indirect reference to be the id that gets you to the view detail page. From the view detail page, you retrieve the id that was passed in, then iterate over the collection in memory until you find the object from the map matching the indirect reference and then retrieve the full data from the DB by mapping back to the original ID.

A couple notes here:
- If you get an id passed in that doesn’t match any in your collection, it means either the code is wrong, or the user has tampered with it, so it should be a security issue
- You’ll note my object has a method called setIndirectReference. All my value objects in my applications extend a base class with some helper methods, and this is one of them. This is obviously not required and there are many ways to accomplish the usage of the RandomAccessReferenceMap, but I build my apps knowing I’m going to use this technique, so it’s not a problem for me.

Per-Page Authorization

Per page authorization is another technique that has a similar goal to the AccessReferenceMap. The idea here is that you’ve already done the appropriate authorization on the master page. Again, for simplicity, let’s use the bank account example. Let’s say you have a checking and savings account with a particular bank, and both of those accounts show up on your “master” accounts page. The code has to check what you have access to (authorization) in order to only display the appropriate 2 accounts to you on that page.

Unfortunately, that’s where many applications stop. They assume since they’ve only given you 2 accounts to choose from, you’ll have to choose 1 of the 2. This doesn’t take tampering into account, however, and tampering can allow the attacker to input any account they choose.

What the per-page authorization says is that if and when the attacker tampers with the data sent to the detail page, it still shouldn’t be possible for him to see data that is not his. The code that brings up detail about a specific account should first include a check that you have access to that account (authorization). Again, if he doesn’t have access to that account, either the code is broken, or he is tampering and that is a security incident.

So, which option should I choose

Well, either or both. They are both viable options to solve the DOR problem, but I’ll try to give a couple of points about both that may sway you one direction or the other.

AccessReferenceMap
1. *May* not require an extra DB hit to do detail page authorization – depends on how you’ve coded it.
2. Shields actual IDs from end user. In case you ever have a vulnerability on another page, and haven’t protected for it properly, the attacker won’t know your IDs.
3. Requires a bit of extra coding and some extra information to pass around the application in order to maintain access to the reference maps.
4. Currently not very popular, so not very well understood yet.

Per-Page Authorization
1. *May* require an extra DB hit to do detail page authorization – depends on how you’ve coded it.
2. Exposes actual IDs from end user. In case you ever have a vulnerability on another page, and haven’t protected for it properly, the attacker could know your IDs.
3. Doesn’t requires extra coding or the passing of information around the application in order to maintain access to the reference maps.
4. Very well understood paradigm.

Well, there you have it. There’s really not that much to it. While direct object access is a significant issue in many of today’s applications, it can be fairly simply corrected. I’ve presented a couple of options that can be done separately or combined together as a solution. I like to use them both, but separately, they still do their job properly.

Just one final safety note. While I’ve only discussed these techniques in the context of database queries, whichever one or both that you choose should additionally be applied when referencing any sensitive internal resources, including files, internal objects, classes, etc.

Well, that’s it. Hope you’ve found this article helpful. Let me know if you have any questions or suggestions to improve any of my ideas.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Technorati Tags: , , , , ,

The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution

No Gravatar

This article will describe how to protect your J2EE application from malicious file execution attacks using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

So what exactly is malicious file execution? It could mean different things to different people. Here, I want to limit the discussion to the execution, either immediate or delayed, of files or file handles that can be manipulated in some way by user input. This is a fairly broad definition that can cover a few different situations. Let’s first discuss a few of the different types of issues that can come up. This collection is by no means exhaustive, but should give us decent coverage of the types of issues that arise when dealing with file input.

1. Included file name is partially or wholly determined by dynamic input (think dynamic include files)
2. File is uploaded and written to disk with “as is” (no validation of uploaded file – just write to disk)
3. File name to display or retrieve is partially or wholly determined by dynamic input
4. Command / data file is uploaded (think a batch process being kicked off with data from an uploaded spreadsheet)

So, what types of issues do these particular situations present us with. In general, an attacker can manipulate this process to gain increased privileges, access data for which they are not authorized and even execute code. Since these aren’t the only 4 examples of issues that exist, we won’t specifically delve into each issue in detail, but we’ll try to extract some common problems that are present in one or more of the scenarios listed above. This set of problems is related to common file upload / processing situations.

1. Missing or insufficient input validation – This is almost always true with file processing. This also is a broad topic, since it deals both with the file name and path, as well as the file contents. Many times, this could express itself as uploading a file as is and simply writing it out with a filename that is either the name of the file as uploaded, or a name specified by the user. This could cause issues like directory traversal (“../../etc/passwd” – overwriting the passwd file – sorry for the old cliche example), or overwriting other files in the filesystem (“../../jsps/login.jsp” – overwriting the login page). Something like this could allow the attacker to break the site significantly up to and including owning the site, and even the server it’s hosted on. While most file processing code I’ve seen is not bad enough to allow something like this, some of it is just that bad .. scary.

2. No virus scanning – This goes along with input validation to some extent, but if you are uploading a file that is going to be executed in any way at any time, it should be virus scanned. There are engines out there, even free ones, that you can call out to in order to scan the file. If the scan fails, the file should be deleted, and the incident should be logged as a security incident. At that point, the normal security incident response process in your organization can be executed.

3. No size checks – One of the simplest tasks you can perform that is often overlooked is to check the file size of the uploaded file. There is most likely a reasonable limit to the size of your accepted files. For instance, a spreadsheet would have to have quite a bit of data to be any more than a few MB, but an attacker could upload files of many times more than that to try and fill up the file system, or just hang processing on the server to block out other valid users.

4. Invalid file type processing – This task is a bit more difficult, but makes sense in many cases. If you are an image hosting site, there’s no reason to accept Word files. This should involve creating a whitelist of the types of files you will accept and then verifying that only those are uploaded. This does NOT mean file extension checks. Although these can be used as a superficial first test, they are trivial to change and provide no security assurance. Often times, this check will involve output encoding (see #7).

5. Giving too much control over file name input – This occurs when users are allowed to influence the final filename that is output to the filesystem. This could happen by allowing a user to type in the desired filename or by just accepting their filename and using that on the server side. However, it is much safer to generate the filename that is used to save the file to the filesystem. Generally, this would have some securely random string of characters, as well as the author, date, time, etc. If there is a specific requirement to accept input from the user as to what the filename should be, just ensure that the name given is validated against an acceptable whitelist before writing the file out.

6. Direct object reference (DOR) problems – While the DOR issue affects more than just filenames, it is relevant here so we’ll quickly discuss it. DOR is simply an issue where the actual filename is pointed to directly. This filename could be in a hidden field, stored in a cookie, or some other place that is not directly seen by the user on the screen. Typically the filename is taken directly and used to retrieve or execute the file. This could cause issues of broken authorization (attacker changes filename to access another user’s file), elevation of privileges (touching a file belonging to a user with higher privileges or the system user), or many other problems. This topic is covered in greater detail in the next article in the series.

7. No output encoding – This issue doesn’t always exist since not every filetype can be thought of in this way. The basic issue is when a file is not validated properly before being written out. There are several filetypes that are valid, that could have extra information in them. However, of those, there are some file types which can be read in, and then written out again to ensure the “bad stuff” is not still there. This does not apply to all “bad stuff” that can be contained in those files, nor does it apply to every file type, but it can be useful when the option is available, though it rarely if ever is used in many applications.

8. Not authorizing access – This issue exists because many applications contain reasonably appropriate authentication, but horrible if any authorization. Once a user is authenticated, many times they can perform any function in the application. The classic example of this is not restricting access to a certain page, let’s say the admin screen. The home page might not show the link, but if they type the link into the url bar, there’s nothing stopping them from getting there. Depending on the type of site, this could be especially harmful with file upload. Often times, only “trusted” people are expected to be able to upload files, but if the authorization is broken, it could allow anyone to upload files at will. Again, this depends on the type of site you have – it may be perfectly fine for everyone to upload files (like flickr or youtube).

Where do we go from here? ….

So, we’ve discussed lots of issues that can crop up when dealing with uploading files, so how does ESAPI and general best practices say we should deal with these issues? Let’s take them one by one.

1. Missing or insufficient input validation – As discussed in part 2 of this series, ESAPI makes it fairly simple to do proper input validation through the framework. The code is very simple, and extensible through the addition of new regular expressions. Here is an example of how ESAPI checks the filename of the uploaded file to verify that it is valid.


if (!ESAPI.validator().isValidFileName("upload", filename, allowedExtensions, false)) {
	throw new ValidationUploadException("Upload only simple filenames with the following extensions " + allowedExtensions, "Upload failed isValidFileName check");

}

2. No virus scanning – ESAPI does not directly support virus scanning through the base APIs, but several of the antivirus vendors support API access for Java. I’ve heard that there are also free AV tools that offer this feature as well.

3. No size checks – There is no built in support for this in ESAPI. However, several of the web frameworks do provide support for this. Additionally, most if not all file upload libraries also provide support for this. Lastly, it’s trivial to perform your own check even if your specific library does not support it directly. Just load the uploaded file into a file object and call the length() method on it to determine the size of the file in bytes. Here is what ESAPI uses to prevent large files. The following is a snippet:


ServletFileUpload upload = new ServletFileUpload(factory);

upload.setSizeMax(maxBytes);

4. Invalid file type processing – This task is supported by the input validation portion of ESAPI again. First, the filename could be validated by the application. Then, each input from the file that is processed could again be validated by the application. Think of processing a spreadsheet. The filename should first be tested, then not only each line, but each cell should be checked for validity before being used by the application.

5. Giving too much control over file name input – In order to at least partially solve this issue, ESAPI has the SafeFile object. This is a trivial extension to the java.io.File object that additionally performs checks of the file and directory names to check for unsafe characters. However, this is a blacklist check. It is likely that you could do a better job if you know what characters are allowed in your filenames and only allow those (whitelist), though the characters in the ESAPI blacklist should minimally be disallowed.

6. Direct object reference (DOR) problems – Again, this will be covered in greater detail in the next article, but here I will just mention that ESAPI does have a mechanism to hide DORs. This involves essentially creating a map of direct -> indirect references and then using the indirect references for display, then mapping back during the processing. Come back for the next article for more details on how this is actually done in code.

7. No output encoding – There is no built in support for this in ESAPI. However, there are ways of doing this that *may* work for different filetypes. The most obvious one is images. If an image is uploaded, you can open the file, load the contents into an image object, then save that object. This guarantees that the image is a valid object. Otherwise, loading the image will fail. (Note: this is the expected behavior, though there have been some defects that may cause this not to work – ensure your library version functions correctly here). It may also be possible to do this with the help of some 3rd party libraries depending on the file type you are processing.

8. Not authorizing access – ESAPI does have authorization coverage in the framework, but it deserves its’ own discussion. Actually, the last article in this series will cover restricting URL access which will discuss the authorization capabilities of ESAPI. Additionally, CSRF (Cross Site Request Forgery) protections can help deal with this issue as well, and this is also going to be covered in a later article in the series.

I’d like to mention a couple of other helpful things that are more systems management related when dealing with uploaded files.

- Use a safe base directory when saving your uploaded files that is outside the standard web directory that your site is served from. This will force your application to be the only thing that can access these files. That way, an attacker can’t drop a file in an accessible directory.

- Use the file-system access controls that are offered in your operating system and possibly your web/application server. Ensure that only the appropriate users have privileges and that they have the least privilege necessary to do their jobs. This is a necessary stopgap in case your other protections fail.

- Audit properly. This can’t be stressed enough. If you audit and log properly, and then *READ* those logs, then you can notice when strange behavior occurs. This can help you locate things that need to be resolved.

Hopefully this article has been useful in helping you recognize the types of issues related to file upload and some best practices for dealing with those. As in all the other articles, I recommend trying to be as safe as possible, and only having your app do what is necessary. If you don’t need to upload files, don’t do it. If you have to do it, spend time making sure it’s as safe as you can make it. Let me know if you have other suggestions or best practices you use with file upload.

Editorial Note: I realize it’s been quite a while since I posted any articles in this series. However, I plan to finish up the series in the next few months by posting an article every week or two now that I can spend a bit more time on it. I also realize that in the gap of time I had off, the new OWASP Top Ten (2010) has been released and it supercedes the 2007 list. However, all the issues in the 2007 list either still exist in the 2010 list, are covered by it, or are still issues that may not make that high of a ranking anymore, but are still important. For these reasons, and the fact that I’d already started using the 2007 list, I’ll finish up with the 2007 list. I may go back at the end and catch any new ones from the 2010 list if relevant.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Technorati Tags: , , , , , ,

The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws

No Gravatar

This article will describe how to protect your J2EE application from injection (SQL and others) attacks using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem

Now to discuss injection. Again, let’s begin the the definition of injection from OWASP:
“Injection flaws, particularly SQL injection, are common in web applications. Injection occurs when user-supplied data is sent to an interpreter as part of a command or query. The attacker’s hostile data tricks the interpreter into executing unintended commands or changing data.”

Here I should make a quick note about “input”. While the vast majority of attacks are usually due to malicious user-supplied input, often directly through the browser, this is not necessary for the attack to work. Dangerous (whether malicious or not) could come from a variety of sources, like the filesystem, or the database, or even other applications. The rule is, if you take in input, always understand it could be dangerous. OK, back to injection …

If you look at injection alongside XSS, you’ll notice that they are very similar types of vulnerabilities in spirit. Consider this working definition: “The application takes in input and without proper data validation or encoding, outputs that data to a destination where certain values or entities have special meaning”. This could be describing XSS or Injection. In the case of XSS, our output destination (we’ll use OWASP’s “interpreter” term from here on out) happens to be a browser. For injection, it could be a database, LDAP server, operating system or any other number of interpreters. Each of the interpreters has its’ own semantics and processing rules for what it understands and what symbols and characters have semantic meaning as input.

For the browser, for instance, the bold tag has semantic meaning, which results in making certain text bold-faced.

<b>bold-faced</b>

As for a SQL compliant database, the keyword SELECT has semantic meaning in that it performs a read of some portion of the database.


SELECT first_name, last_name FROM employees;

As we saw previously in the XSS article, it is possible for a user to insert (inject) data that will cause issues if the input is not properly validated and/or encoded (my strong suggestion is to do both). The same thing is true with injection attacks. If the input is not valid for the interpreter, or more specifically contains some commands that will be processed by the given interpreter, then the user can cause the interpreter to perform functions on the user’s behalf that were not intended to be allowed by the application.

Let’s take a classic SQL injection attack as an example to clarify the issue. Here’s some simple Java code creating a SQL string to perform an authentication check so that a user can login. Let’s assume the Java code gets the results back and tests to see if there are any results, and if so, allows the user to be authenticated.


String sqlString = "SELECT * FROM users WHERE fullname = '"
    + form.getFullName() + "' AND password = '" + form.getPassword() + "'";

So, let’s assume the user is presented with a simple login screen, and let’s also assume the user is benevolent. The user might enter something like John Melton for the username and 123pass for the password. That would create the following SQL string to be executed against the database after it is processed by Java (ie. this is what you would see as the SQL string if you watched it through the debugger, or printed it out after the values have been populated at runtime).


SELECT * FROM users WHERE username = 'John Melton' AND password = '123pass'

OK, so far, everything is great right? Sure, for those specific inputs no problem. Now, to pay homage to a good friend of mine, I’ll include his oft-quoted refrain – “The web wasn’t made for Irishmen”.

Let me explain that. For those who are unaware, many Irishmen have names like O’Brien or O’Connor. Note the apostrophe in the last name. Now, let’s show what the SQL string looks like after being processed now.


SELECT * FROM users WHERE username = 'Paul O'Malley' AND password = '789pass'

Are we still good? Nope, this time, we’re not so lucky. What will happen here is a SQLException will be thrown because the SQL cannot be processed by the database interpreter. The issue is in the extra apostrophe in the name. The apostrophe is used in SQL, among other reasons, to open and close a string representation. So, what the SQL interpreter sees in this case is that the username string is populated with Paul O and then closed, and the actual SQL string starts again, only <b> is not valid SQL syntax, so processing stops and an exception is thrown.

(Note: I’m using interpreter generically. In the cases I’m describing, it actually would get booted by the parser, but that’s quibbling :>. )

All right, now that we’ve covered the basic “it works” case and also seen there is a way to break it, how can we break it to our advantage if we wanted to attack the site? Let’s say an attacker sends these two crafted inputs.


Full Name: blah blah
Password: ' OR '1' = '1

Update: modified code above according to Ben’s comment below.

Now that’s a funny looking string to be entered in the password field – let’s see what the SQL string produced looks like.


SELECT * FROM users WHERE username = 'blah blah' AND password = ' ' OR '1' = '1'

What the above SQL actually does is returns all records from the users table that use the given username and password OR where 1 = 1, which is … EVERY RECORD!!!. This grants the attacker access to the application as an authenticated user. This was an actual issue in a real (fairly well-known at the time) web application many years ago. It would check the results that were returned and take the first one as the user to log in. In the case where they were being attacked and all records were returned, it took the first result, which like most other systems first user, was the admin account! Most decent sites have closed this issue on the login screen thankfully, but it is a very prevalent issue in systems across the world.

The above is a simple example of what can happen with SQL injection. The vast majority of reported issues with injection have to do with SQL injection. The others are not as popular, probably because they’re less common types of systems (b/c almost every app uses a DB) and SQL injection is so easy and prevalent, there’s no real driver for attackers to do anything else. Additionally, most of the sensitive data is likely stored in the DB anyhow, so we might as well attack it directly if possible.

Where do we go from here? ….

So, now that we see the problem, how do we fix it? Well there are essentially 2 reasonably reliable techniques as I see it. The first option has to do with using PreparedStatements with bound parameters, and the second option uses the ESAPI framework.

Update: From Jeff’s (the chair of OWASP) comment below, it should be clear that PreparedStatements and the ESAPI output encoding mechanisms are not mutually exclusive. They can be complementary and used together for increased assurance. It is a task left up to the development organization securing their app to make a decision over which option (or both) to choose. As with most choices, each option (PS, ESAPI, or both) has its’ advantages and disadvantages.

Note: with either technique, white-list input validation should be used since it’s relatively easy to do, and helps avoid so many types of problems. Additionally, standard security measures like least privilege for the user account connecting to the DB for your application should also be utilized.

Before getting into the detail of the 2 options, I want to point out that the ESAPI folks have put together another article called the SQL Injection Prevention Cheat Sheet and it is a great resource about this topic, specifically SQL injection.

PreparedStatements (with bound parameters)
——————
Those familiar with DB programming in java will recognize the 3 statement types in Java: Statement, PreparedStatement and CallableStatement. These 3 types represent varying levels of security. The standard Statement class is not a good idea – there are no security measures built-in and you are on your own if you try and use this class. As for the CallableStatement, it is used with stored procedures and functions. *Typically* stored procs are secure. However, it is very possible to make them insecure by not validating the input properly or even constructing dynamic sql within the procedure for execution. Finally, there is the PreparedStatement. When used properly (with a safe driver and bound variables), these are typically viewed as the most secure option.

There are 2 important things to remember about PreparedStatements when it comes to security.
1. SQL executed with PreparedStatements is only as safe as the drivers that implement the classes. The actual runtime class that implements the PreparedStatement interface is part of a 3rd party package. There are some out there that are generally thought to be safe, and some that aren’t. The most popular ones expectedly tend to be more respected (not necessarily earned, but true nonetheless). The only suggestion I can give here is that you can look at the code of popular open source drivers yourself and make up your mind about their safety. If you use a commercial driver, understand the support structure in case there is a security issue that must be resolved.
2. The code leveraging the PreparedStatements must use them properly. This involves the use of strongly typed bound parameters. This means that if you concatenate your SQL string together using dynamic input, the PreparedStatement does you no good. The safety comes into play when using the setXXX methods on the PreparedStatement class. The snippet below shows how to properly use dynamic input (which should already be validated) as input to the SQL string by doing parameter substitution. The setInt method below (if the driver is coded properly) should be DB specific and will escape any necessary characters for that DB to prevent breaking out of the interpreter and allowing the user to specify code that will be run by the DB.


myPrepStmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?");
myPrepStmt.setInt(1, validatedUserId);
...
//execute statement and get results

and a query with multiple input parameters looks very similar …


myPrepStmt = conn.prepareStatement
    ("SELECT name FROM users WHERE id = ? AND date_created >= ?");
myPrepStmt.setInt(1, validatedUserId);		//first param
myPrepStmt.setDate(2, validatedStartDate);	//second param
...
//execute statement and get results

As you can see, using the PreparedStatement can solve this issue, but only when used properly. One very important thing to note here is about ORM frameworks. Most of these frameworks *can* be used securely, but you have to know what you’re doing. Hibernate, for instance, can be used securely or insecurely depending on which classes you choose. Be sure to do your homework, read solid tutorials, pick good frameworks, and above all understand what you’re using when you let a framework do some of the work for you. OK, now on to our other option …

ESAPI
——————
ESAPI takes a similar approach to solving this issue, but the code will look slightly different. The approach is very simple, and boils down to escaping/encoding all dynamic input to the SQL statement using an appropriate encoder. For this section of the article, I relied heavily on the ESAPI section of the SQL Injection Prevention Cheat Sheet at OWASP, so it’s a worthwhile time to go read it if you haven’t already. Let’s look at one quick example to show how it works. We’ll modify the second query above to use ESAPI instead of PreparedStatements.


//ESAPI version of query
Codec ORACLE_CODEC = new OracleCodec();		//we're using oracle
String query = "SELECT name FROM users WHERE id = " +
   ESAPI.encoder().encodeForSQL( ORACLE_CODEC, validatedUserId)
   + " AND date_created >= '"
   + ESAPI.encoder().encodeForSQL( ORACLE_CODEC, validatedStartDate) +"'";
myStmt = conn.createStatement(query);
...
//execute statement and get results

As you can see above, all that we did was encoded the input data (already validated) for SQL by using the OracleCodec, since we are using the Oracle database for our application. This has some obvious drawbacks if you are using multiple databases, and can use the ORM features of cross-database query generation, but that is rare for many apps. Most applications know the 1 database they are going to be running on, and I would argue that’s a good thing from a security perspective because then you can better understand the security ins and outs of that one DB.

Looking at the code, it’s fairly simple to encode most anything – you just have to be diligent to do so. As for the other types of injection, you may have to get your hands dirty and write an encoder for your specific application, or you may not. You’ll just have to check what the ESAPI team has already done. Additionally, it might be possible to get on the mailing list and request a new codec. Certainly, if you have any that you’ve written, I’m sure the dev team would love to at least see them, and possibly include them – you could be helping others out!.

Clearly, using the ESAPI framework, it’s possible to safely and securely prevent injection from the DB as well as other types of interpreters if you use the framework properly.

In summary, I’ll say that while I think either of these techniques work from a purely technical perspective, there are a couple of things you should consider before implementing protection. First, PreparedStatements are far more prevalent in industry. They are a solid solution to the SQL injection problem, and are widely understood and available. They’ve also been very widely tested both for performance and security. Essentially, they are a known entity. However, they do not solve any of the other types of injection. The equivalent to PreparedStatements do not exist for XML or XPath injection or others. You’d have to handle them differently. As for ESAPI, it will also work well, and has been tested for security and performance, but not nearly as much. Additionally, it does not have the industry reach that PreparedStatements do. However, ESAPI has a solution for the other types of injection as well, and a clear model for implementing new encoding mechanisms for new interpreter types. You can even write your own custom encoders if you choose. No matter which you choose (or both), my hope is that you’ve seen there is a need to be responsible and protect resources from injection. These solutions make it fairly trivial to implement solid protection for applications against injection.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Update: Added inline comments referencing changes made regarding Jeff and Ben’s comments below.

Technorati Tags: , , , , , , , ,

The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)

No Gravatar

This article will describe how to protect your J2EE application from XSS using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

OK, so on to XSS. Here is a slightly modified definition of XSS from OWASP:
XSS flaws occur whenever an application takes untrusted (typically user supplied) data and sends it to a web browser without first validating or encoding that content. XSS allows attackers to execute script in the victim’s browser which can hijack user sessions, deface web sites, possibly introduce worms, etc.

As you can see, XSS essentially allows an attacker to splash whatever they want on the screen since the application doesn’t do any input validation or output encoding. This is not a big deal when you have benevolent users, but an attacker could, say, input some nasty JavaScript and cause quite a few problems. This is typically what happens – JavaScript is output and generally executes in the background so the user is unaware of what’s occurring.

In general there are 3 types of XSS:
1. Stored – The dangerous data is stored in a permanent data store and shown repeatedly on the site – think online forums. If an attacker were to save a forum comment that had an XSS exploit in it, that comment would then be displayed to anyone who visited the page, without requiring any further interaction from the attacker.
2. Reflected – The dangerous data is sent along with the URL typically, and is not stored in a data store but is displayed (reflected) back to the user, which launches the attack. If an attacker sent a URL in an email, and a user clicked on it b/c the site was “trusted”, say that user’s bank, but the site had an XSS exploit, the attacker could cause many issues up to and including processing transactions on behalf of the user at the bank site (more on this in a follow-on article).
3. DOM – This is the most recently named type of attack, and simply represents an entirely client side issue. While the previous 2 types of XSS have to do with the server outputting data to the browser, this has to do with the browser manipulating the DOM and data being moved in and out of context. This can result in an XSS attack if data is not properly validated or encoded. This type of XSS issue has become more prevalent with web 2.0 and the heavy proliferation of JavaScript frameworks being used to do both serious functionality and DOM manipulation in web pages.

XSS, by some accounts, is the most common vulnerability and definitely is one of the most dangerous in the wild. It is extremely prevalent due to a lack of education for the most part, but it can at times be tricky to solve correctly. There are essentially 2 options for how to deal with XSS. Both could be used individually to solve the problem entirely … in theory … but that would require detailed knowledge of every possible input/output vector both now and in the future. Since this is rarely feasible, it is recommended to use both approaches. These approaches are Input Validation and Output Encoding.

Input Validation
—————-
Input validation is simply that – checking each input for validity. This can mean many things, but in the typical and simplest case, it means to check the type and length of the data. For instance, if you are accepting a standard US zip code from a text box, you would know that the only valid type is a digit (0-9) and that the length should be 5, no more and no less. Not all cases are this simple, but many are similar.

Consider this example for what can go wrong. There is a simple search engine and on the page is the search box. A user types in a query only to find on the results page that his search terms are printed on the screen, something like – You searched for “free stuff”. That’s all well and good, but what happens when the user inputs a bit of JavaScript into the search box? If the application doesn’t handle the input/output properly, the screen will print the JavaScript out in all it’s glory, and it will get put inline in the web page response, and treated just as if the web page developer had put that bit of code in there. That’s where the problems come in – now how do we solve these issues?

Here’s an image from OWASP showing their architecture for input validation. The key here is that everything is validated, all input that doesn’t originate within the application (including user input, request headers, cookies, database data, ldap, really everything …).

ESAPI Input Validation

So how do we use this validation framework to actually validate our data. There are 2 basic types of methods in the validator interface that can be used. They are listed below:


getValidInput(java.lang.String context, java.lang.String input, java.lang.String type,
	int maxLength, boolean allowNull, ValidationErrorList errors)
isValidInput(java.lang.String context, java.lang.String input, java.lang.String type,
	int maxLength, boolean allowNull)

The first, getValidInput, returns canonicalized and validated input data along with a list of errors (ValidationErrorList) if any validation issues occurred. The second is similar, but does not return errors, and rather just returns a boolean as to whether or not the input is valid. Here are a couple real examples of these being used.


String validatedFirstName = ESAPI.validator().getValidInput("FirstName",
	myForm.getFirstName(), "FirstNameRegex", 255, false, errorList);
boolean isValidFirstName = ESAPI.validator().isValidInput("FirstName",
	myForm.getFirstName(), "FirstNameRegex", 255, false);

Both of the samples above deal with the first name field from a typical web form, but this could just as easily be a request header or parameter, or cookie value, or anything else.

In the end, there is great value in general in validating ALL of your application inputs. It will help solve the XSS issue, but will also solve other problems, including some we probably haven’t even thought up yet.

Output Encoding
—————-
On the flip side of input validation is output encoding (also known as “escaping”). Here’s a quick definition from OWASP: “Escaping” is a technique used to ensure that characters are treated as data, not as characters that are relevant to the interpreter’s parser. There are lots of different types of escaping, sometimes confusingly called output “encoding.” Some of these techniques define a special “escape” character, and other techniques have a more sophisticated syntax that involves several characters. Escaping is the primary means to make sure that untrusted data can’t be used to convey an injection attack. There is no harm in escaping data properly – it will still render in the browser properly. Escaping simply lets the interpreter know that the data is not intended to be executed, and therefore prevents attacks from working.

What does all of this mean to the developer? In order to prevent “bad” data from causing XSS issues on the screen when rendered, we can’t just out.println them to the screen – we have to “encode/escape” them. There are many libraries out now that do some form of encoding, most are minimal. c:out and jstl both do encoding – some of the struts tags, jsf, spring. All do some minimal encoding. However, ESAPI takes this to a different, but necessary level.

There are 2 issues with the previously mentioned frameworks when it comes to their encoding schemes. 1 – They don’t encode enough characters – they miss some things. 2 – They only encode for 1 context and miss the other 4. As mentioned in the cheat sheet, there are actually 5 output contexts for the browser:
1. HTML entity (this is the standard HTML output that the above frameworks at least partially handle)
2. HTML Attribute
3. JavaScript
4. CSS
5. URL

This image from OWASP shows their architecture for output validation. The important notion here is that before any data is output in the application, the context for output is considered, and the data is encoded.

ESAPI Output Encoding

All of these contexts have some special handling rules. I suggest you reference the cheat sheet in order to learn those. I’ll give a couple of simple examples here just for reference.

First, a simple example to output to an HTML entity.


//performing input validation
String cleanComment = ESAPI.validator().getValidInput("comment",
	request.getParameter("comment"), "CommentRegex", 300, false, errorList);

//check the errorList here ...
...

//performing output encoding for the HTML context
String safeOutput = ESAPI.encoder().encodeForHTML( cleanComment );

Now, an example of creating a URL that is safe for output.


//performing input validation
String cleanUserName = ESAPI.validator().getValidInput("userName",
	request.getParameter("userName"), "userNameRegex", 50, false, errorList);

//check the errorList here ...
...

//performing output encoding for the url context
String safeOutput = "/admin/findUser.do?name="
	+ ESAPI.encoder().encodeForURL(cleanUserName);

Above, you can see that is it very simple to encode output for a given context, as long as you know the context you’re going to. It does take discipline to use this throughout your application, but it will pay you back many-fold in rewards. Additionally, ESAPI does have tag libraries that wrap each of the output encoding mechanisms available for use.

One final note regarding output encoding: you should always explicitly set the character encoding for all your pages (ISO-8859-1 or UTF8 are popular choices).

As you can see, there is quite a bit to solving XSS. It can become tricky, especially in the instances where multiple contexts are involved, like trying to safely pass a parameter to a javascript function inside an HTML attribute handler event, but it is doable. The big takeaway should be that input validation and output encoding, while they do solve XSS, are in general excellent practices that should be exercised for ALL input to an application.

A final XSS note: A great reference for understanding what is occurring in XSS and how to protect against it is the OWASP XSS Prevention Cheat Sheet. Various references in this article drew from the info on this site.

Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access

Note: Article updated on 11/18 per Jim Manico’s catch of improper url output encoding since ESAPI’s url encoding is intended for parameter values, not the entire url. Also added input validation as Jim’s comment pointed out was missing.

Technorati Tags: , , , , ,

← Previous PageNext Page →