Sunday, August 10, 2008

Input Validation - Not That Important

When I bring up almost any category of web application injection attacks, most folks in the field almost instinctively begin talking about "input validation". Sure, input validation is important when it comes to detecting certain attacks, but encoding of user-driven data (either before you present that data to another user, or before you use that data to access various services) is actually a great deal more important for truly stopping almost any class of web application injection attack.

The Java variant of ESAPI has a wide variety of encoding functions depending on the need (called easily via ESAPI.encoder()).

Some of these include:

//when user-driven data is used
//as a javascript variable

String encodeForJavascript(String input);

//used when presenting user-driven
//
data inside of an HTML tag
String encodeForHTMLAttribute(String input);

//used for presenting user-driven
//data inside of an HTML body

String encodeForHTML(String input);

//used then presenting data
//as a vbscript variable

String encodeForVBScript(String input);

//used when accessing LDAP services
//with user-driven data

String encodeForLDAP(String input);
String encodeForDN(String input);

//XML centric encoding operations
String encodeForXPath(String input);
String encodeForXML(String input);
String encodeForXMLAttribute(String input);

//used when placing user-driven
//data within a url

String encodeForURL(String input) throws EncodingException;

While input validation is still crucial for a defense-in-depth application security coding practice; it's truly the encoding of user data that becomes your final and most important line of defense against XSS, SQL Injection (PreparedStements and binding of variables actually encoding user-driven data specific to each database vendor via the Java JDBC driver), LDAP injection, or any other class of injection attack.

8 comments:

Joshbw said...

Encoding is the best way to protect against injection based attacks, as it is always safest to make sure the content you are handing off elsewhere is well formed and safe (or even better, come up with systems that negate certain injection altogether- server side script and command injection are usually the result of poor design rather than input validation/output encoding) but I think it is probably better to not phrase things in the manner you did. Input validation is the best way to protect your own app and its logic, while output encoding/sanitization is the best way to protect components you communicate with (clients, other servers, the system you are one, etc).

Your specific use of injection attacks makes your intent pretty apparent to me (essentially we were saying the same thing) but I think phrasing things in terms of best method to protect a specific asset (your own app/logic, everyone else) rather than saying "Input Validation - Not that important" and providing a caveat that you are talking about injection would prevent folks from misreading your post and coming away with the idea that, well, input validation isn't that important.

As an example, if you had a shopping cart that could have items added via a get method you really need input validation. http://www.somestore.com/addcart.php?item=5&qty=8
Now you do need to worry about sql injection with the item, so using bindable queries for the database lookup is probably pretty important. Likely the resulting cart page will display the quantity somewhere, so you also want to do entity encoding to make sure that a reflective XSS isn't present. Essentially, protect against injections.

However, just as importantly you want to explicitly validate that quantity is a positive integer, so they don't pass to the application that they are buying -10,000 102" plasma TVs and need to charged $-1,000,000.

I like " Input Validation - Important for yourself; Output Encoding - Important for everyone else" even if the title is a bit longer.

Jim Manico said...

Josh, thank you for your comments.

Input Validation from a business functionality perspective, is indeed very important. But from a security perspective? I do not its as security-critical as most in the industry believe.

But I agree, my phrasing was sensationalistic to get your attention. :)

In your shopping cart example, verifying that the user can add item 5 to their shopping cart would be an access control issue - and the quantity confirmation would be a business logic rule. For example, you would probably want to signal an alarm if a user is purchasing 1000 wide screen TV's, while 1000 cheap computer screws might be acceptable. A static validation rule would not be enough.

And while I do agree that validating to a positive integer is important for business functionality, back end services should be ready to fail safely when bad data is submitted. Input validation alone is not enough and is often depended on, alone, to protect an application - in a way that establishes a poor risk posture.

But, I still do input validation. I just do not think it's as important as other application security principles.

Joshbw said...

Well you forget that I come originally from a world of client security, where clients are attacked through their input (things like buffer overflows and the like) and those attacks are significant.

For web applications denial of service is probably the most well known attack that comes from a lack of input validation (pass a sufficiently large XML file via webservice with DOM based parsing and it doesn't matter if the file is encoded properly, heck it tells you whether it is in the proper format, it will still take up too much memory, for example) but business logic validation can be just as damaging if less known, and can compromise the components of the TRIAD just as much as XSS or SQL Injection.

I would further argue that authorization based attacks are all an example of a lack of input validation, since in general whenever you recieve input, as a client or a server, you want to make sure the input is both in an expected form AND from an expected party. Some random binary sending your client window messages is as highly suspect as a random request to an admin page.

Jim Manico said...

I agree 100%. When receiving XML (or file upload) from a client, input validation is very crucial as you described. But I feel that if your system ever receives XML from a user, your architecture is off. I prefer XML transfer only via a environment with non-repudiation, such as client-side certs.

Also, many folks make the mistake of validating their xml data and data elements, but never encode before accessing a back-end service leaving them vulnerable to a large class of attacks.

You are also right on when it comes to File Upload services. Input validation is crucial - but very difficult. To get file upload validation correct - many steps are required - virus checking, size checking (in a separate thread) and content introspection, at least. Even better, design around file upload needs. It's almost impossible to get right.

When it comes to authorization attacks, I feel that account lockout, strong passwords, and secure user administration is more important than input validation.

Josh - I am being sensational here to get attention, I do admit. But I still believe that many professionals throw out "input validation" as the key to application security - and I feel it's over-hyped and that we need to look deeper.

Jim Manico said...

Josh posted a remarkable post on his blog relevant to this topic at http://www.analyticalengine.net/archives/58 - I recommend you take a look!

Anonymous said...

It was certainly interesting for me to read this article. Thank you for it. I like such themes and everything that is connected to this matter. I definitely want to read a bit more on that blog soon.

Anonymous said...

It is certainly interesting for me to read that blog. Thanks for it. I like such themes and anything connected to them. I would like to read a bit more on that blog soon.

w3c said...

Nice information, I really appreciate the way you presented.Thanks for sharing..

http://www.w3cvalidation.net/