With so many APIs and frameworks out there, there are many different ways to accomplish the same task. The problem is that each way (or method) usually exhibits different behavior in the face of maliciousness. The challenge for us is to (1) find bad behavior in the APIs/frameworks we use, (2) apply fixes consistently, and (3) remember all of the ways things can go wrong. (1) is difficult but doable, (2) is more challenging, and (3) is arguably impossible for a person to do alone. The fact that APIs change frequently, even if changed for the better, often exacerbates the problem because it’s costly to go back and consistently make changes across existing applications.
An example: hidden form fields
Despite what some people/tools claim, hidden form fields are not inherently bad; they can be used in perfectly safe ways (think pagination, themes, etc.). It just so happens that they are often used insecurely because developers forget or don’t understand that (1) hidden fields are not truly hidden from the user and (2) hidden fields become part of the executable page context just like most other elements. Two common problems that crop up with hidden fields relate to:
- Client-side trust
- Cross-site scripting
If you decide to use a hidden field, you must assume that an attacker will view and modify its value (i.e., assume an attacker can control it). Because hidden fields exist client-side, they should never contain sensitive data or be the sole factor in making a server-side decision.
Enough background, the point of this post is to show that storing user controlled input in hidden fields can lead to cross-site scripting vulnerabilities depending on which J2EE API(s) is used. Let’s assume that we want to retrieve a parameter named “example” from the request (or bean form) and store it in a hidden field.
(A) The traditional way:
<input type=”hidden” name=”example” value=’<%= request.getParameter(”example”) %>’ />
(B) The Apache Struts html taglib way:
<html:hidden property=”example” name=”exampleForm” value=’<%= request.getParameter(”example”) %>’ />
(C) The traditional way combined with Apache Struts bean taglib way:
<input type=”hidden” name=”example” value=”<bean:write property=”example” name=”exampleForm” />” />
(D) A variant of the traditional way combined with Apache Struts bean taglib way:
<input type=”hidden” name=”example” value=”<bean:write property=”example” name=”exampleForm” filter=”false” />” />
(E) The JSTL way:
<input type=”hidden” name=”example” value=’<c:out value=”${param.example}” />’ />
(F) A variant of the JSTL way:
<input type=”hidden” name=”example” value=’<c:out value=”${param.example}” escapeXml=”false” />’ />
These six methods take the same request (or form bean) parameter and store its value in a hidden field named “example”. The interesting thing to note is that (A), (D), and (F) introduce cross-site scripting vulnerabilities and the others do not. That’s because by default, the html:hidden, bean:write taglibs, and JSTL core perform HTML output encoding. In (D) and (F), we turned HTML output encoding off by specifing filter=”false” and escapeXml=”false”, respectively.
Take home message
The point here is that APIs/frameworks behave differently. It’s important to understand how they differ and determine how they can be used securely. Once you do that, developers must use them consistently or things can get out of hand (or sloppy) very quickly; sloppiness usually always leads to bugs.
Using hidden form fields (as part of normal application flow) is just one area where coding consistency is important. Other mechanisms where achieving consistency is critical that immedidately come to mind are:
- Input validation routines
- Access control, identification, and authorization routines
- Dealing with errors and exceptions
- Logging
Achieving consistency
Three steps should be taken to start writing code in consistent ways:
- Decide and design if necessary how mechanisms will be used across the application
- Develop coding standards to document these decisions and make them available to your team
- Use static analysis tools to enforce the standards
Post a Comment