Java


The Java Platform Enterprise Edition (formerly J2EE) includes a range of technologies for Web application development. At the most basic level, Java provides the Servlet API (javax.servlet) for interaction between a Web server and Java components. A Java servlet is a Java class that runs inside a Web server and handles the construction of dynamic responses to HTTP requests. The Web server has a component called a servlet engine, or servlet container, that manages these servlets. A Web developer installs a servlet in a Web server's servlet container, and then tells the Web server which URLs and URL patterns that servlet should handle. When a servlet handles a request, it can generate any kind of response it wants; much like a CGI program can generate arbitrary responses. Servlets can also forward requests to other servlets, which allows some interesting application designs.

Servlets give you the same kind of basic functionality that Web server APIs provide (such as NSAPI and ISAPI). Even some of the more powerful customizations of proprietary APIs are possible, as the newer versions of the Servlet API allow developers to write filters, which can alter how the Web server handles every request and response.

There are important differences between servlet technology and the proprietary Web server APIs. First, the specification for the servlet interface is an open, published standard with a reference implementation. Therefore, nearly every Web server supports servlets in some form or another, which makes them an appealing technology for large projects. Because servlets are written in cross-platform Java, you can (in theory) take servlets written on one platform for one Web server and move them to a completely different platform with a completely different Web server. The use of Java also makes writing these Web server extensions much safer, as Java is not vulnerable to the same memory corruption issues as proprietary C/C++ APIs.

Most Java Web applications present a front end by using JavaServer Pages (JSP). JSP resembles other server-side scripting technologies, such as PHP or ASP, because you use it to embed Java code in HTML documents. However, JSP is a little different behind the scenes. When a Web server first receives a request for a JSP page, the Web server always compiles that page into a servlet. This servlet is then cached, and future requests for the original JSP page call that cached servlet. This behavior opens some interesting design possibilities; for example, you can forward requests from a servlet to a JSP page because JSP pages share the same characteristics as servlets.

Servlets and JSP represent the fundamental components of Java Web development. On top of this foundation is an entire industry of frameworks, technologies, and environments for developing and deploying Java applications. An entire book could be devoted to covering the security aspects of any of these popular frameworks in detail. However, for the sake of brevity, this chapter focuses on the core aspects of the Java architecture. These patterns should help you understand the basic issues and apply this knowledge to any framework you encounter.

SQL Injection

Database access is usually performed with Java Database Connectivity (JDBC) API using the java.sql and javax.sql packages. A Web application usually creates a Connection object, and then uses that object to create a Statement object. Statement and CallableStatement objects are often susceptible to SQL injection, whereas PreparedStatment is usually safe because it supports bound parameters. Typical vulnerable JDBC database code looks like the following:

Connection conn = null; conn = getDBConnection(); /* This wrapper sets up JDBC */ Statement stmt = conn.createStatement(); String query = "SELECT * FROM documents WHERE docid = "     + request.getParameter("docID"); ResultSet rs = stmt.executeQuery(query);


The Statement object supports three methods that initiate a database query: executeUpdate(), execute(), and executeQuery(). They are similar in that they take some form of SQL string as an argument processed by the database server. During a code review, you should search for all three and perform some general searches for SQL keywords because you'll also encounter custom frameworks and wrappers as well as alternative technology.

File Access

File access from within a servlet typically uses the java.io package, but it's important to keep your eyes open for other possible mechanisms. Java is an extensible language, and developers make use of different frameworks and wrappers. One useful technique is simply to search for the word "filename," which naturally tends to accompany file manipulation code. Another useful technique is searching for calls to getrealPath() and getPathTranslated(). These functions are used to turn a Web-based file path into a physical file path, which is a good indicator that the code is interacting directly with the underlying file system.

Here's an example of typical code used to write a file to the disk from within a servlet:

    String name = req.getParameter("name");     File tempDir = (File) getServletContext().         getAttribute( "javax.servlet.context.tempdir" );     // create a temporary file in that directory     File tempFile = File.createTempFile( name, ".tmp",                                          tempDir );     // write to file     FileWriter fw = new FileWriter( tempFile );


Shell Invocation

Shell invocation is a seldom used feature of the Java runtime environment. Java programs can access this feature by calling the getruntime() method of java.lang.Runtime. This Runtime object supports a few overloaded versions of the exec() method. It's a true exec() system call and doesn't implicitly open a shell to interpret the supplied command. Developers often open the shell explicitly with the appropriate option to take a command from the command line (such as cmd /c in Windows). The following code could be vulnerable, depending on the amount of influence users wielded over the command variable:

    Runtime runtime = Runtime.getRuntime();     Process process = null;     try {       process = runtime.exec(command);


File Inclusion

Java servlets support a rich set of functionality for intraservlet coordination and communication, which is integral to integration with JSPs. When a servlet must transfer control to another servlet or JSP, it obtains a RequestDispatcher object first that facilitates control-flow transfer. RequestDisatcher objects expose two methods: include() and forward().

The forward() method is used when a servlet is done processing the request data and is ready to hand off control to another servlet or JSP. This situation is fairly common when presentation and business logic are well confined to separate components. A servlet might process the HTTP input, make several database calls, do some processing, and then fill out several variables attached to the request attributes. This servlet could then hand control over to a JSP page that knows how to take the variables in request attributes and turn them into stylish HTML content.

The include() method is more a mechanism for embedding code in a currently running JSP or servlet. It's used more often when you've divided code into manageable pieces and want to call one of those pieces in the right place to do its job. For example, you might have a layered menu system that dynamically draws itself based on XML configuration files. One way to render submenus from within the main menu page is to use include() to call the code that handles presenting the submenu on the main page.

As a code auditor, you should look for situations in which user-malleable input can make it into the arguments provided during creation of the RequestDispatcher for include() or forward(). This situation can lead to security issues of differing degrees, but even the capability to run existing files in the Web tree through the JSP compiler would probably end up being useful to clever attackers.

JSP File Inclusion

At first glance, JSP appears to be similar to ASP and PHP. HTML files are marked up with a scripting language, and they seem to more or less work in the same fashion. However, under the covers, JSP pages aren't being run through a script interpreter. Instead, they are compiled into servlets by the JSP engine the first time they're run. Because JSP pages are really servlets at a low level, they work elegantly with servlet mechanisms for forwarding and including. Java servlets and JSP code are essentially the same technology, so this section covers just a few JSP-specific commands that are a little different.

First, the oldest method for including files in JSP pages involves the JSP include directive, indicated like this:

<%@ include file="include.jsp" %>


This directive functions effectively like a server-side include (SSI) directive; it happens before the JSP code is compiled and runs, so it's a static process. There's essentially no risk of attackers manipulating this path at runtime.

The second, and far more interesting, method is the jsp:include element. It's close to the directive form but has a slightly different format:

<jsp:include page="include.jsp" />


This function works similarly to the RequestDispatcher.include() API servlets use to include other content. This inclusion is evaluated dynamically at runtime, so the risk of user manipulation exists. The following is an excerpt from a real-world application found to be vulnerable:

<jsp:include page='<%="browserActions/" +     request.getParameter("_actionPage") + ".jsp"%>'


By using a NUL-terminating byte and starting the parameter with directory traversal characters, it was possible to get the JSP compiler to parse any file in the Web tree. WEB-INF/web.xml is always a good candidate for this kind of attack, as it usually reveals some attack surface you would have missed otherwise.

The jsp:forward element works much like the RequestDispatcher.forward() function servlets. If you recall, include() is used to embed or include a servlet, JSP code, or file into the caller. The forward() function is used to hand control over for the other dynamic object to finish. The distinction isn't all that interesting, however, if any sort of user-malleable data is involved. Both require() and include() are good targets from that perspective.

Inline Evaluation

Java is a different type of language technology than the scripting engine based Web architectures. There's no immediate way for a Java program to dynamically construct source code and then have the Java virtual machine compile and run it on the fly. However, a number of Java technologies do provide different forms of dynamic code evaluation. They include scripting environments, such as BeanShell and Jython, and of course the JSP interpreter is a dynamic evaluation environment for JSP files. These capabilities, however, are much less susceptible to exploit than true interpreted scripting languages, such as ASP and PHP.

Cross-Site Scripting

The Java runtime provides the java.net.UrlEncoder.encode() method to escape special characters in URLs. JSP provides the additional capabilities required for filtering against cross-site scripting attacks. The response.encodeURL() method encodes URL output, and the <c:out> tag escapes XML (and thus HTML) metacharacters from output. Developers may get confused when using the <c> tags, however, because only the <c:out> tag performs escaping. For example, the following code fails to escape HTML output:

<table> <c:forEach var="item" items="${menu}"> <tr> <td>${item.name}</td> <td>${item.price}</td> </c:forEach> </table>


This code fragment is vulnerable to cross-site scripting attacks because the item.name and item.price variables are not explicitly handled. The following example handles these variables properly:

<table> <c:forEach var="item" items="${menu}"> <tr> <td><c:out value="${item.name}"/></td> <td><c:out value="${item.price}"/></td> </tr> </c:forEach> </table>


This example demonstrates the correct method for preventing cross-site scripting attackers. However, it's a bit less intuitive and many developers are unfamiliar with the approach. As an auditor, you need to watch for code similar to the vulnerable example, as it is a very common pattern in JSP pages.

Threading Issues

Most servlets are designed to handle multiple simultaneous threads calling into them at the same time. Typically, there's only one instantiation of the actual servlet object in memory, but a dozen threads might call its methods concurrently to handle requests. These concurrent calls can lead to security exposures if the servlet class is not completely thread safe.

Servlets can be written to handle only one client at a time. If the servlet implements the SingleThreadModel interface, the servlet container treats that servlet as unsafe for concurrent threads. Generally, Java developers discourage this practice, and it's not common. Therefore, a giant red flag is the use of instance variables in servlets. They are effectively like global variables in a multithreaded C program, and they should be used with extreme care. Consider the following code:

class MyServlet extends HttpServlet {     String account_number;     public void doGet(HttpServletRequest request,           HttpServletResponse response)     throws ServletException, IOException     {         account_number=request.getParameter("ID");         ...         if (authenticate_user(account_number) != USER_VALID)            kill_session_and_user_and_abort();         ...         display_account_history(account_number);     }     ... }


This code works fine in a single-threaded situation because it stores the account number in the account_number instance variable. It then checks whether that number is valid and aborts processing if user isn't authenticated. If user passes the authentication, the code displays details of the user's account. However, this code has an obvious race condition in a multithreaded environment, like a Web server. The account_number string can be changed by concurrently running calls to doGet() between actions, leading to situations in which valid users are booted out occasionally, and every now and then, someone sees someone else's account information.

Configuration

Servlets are mapped to a virtual Web tree in a configuration file, typically the web.xml file in the WEB-INF/ directory off the root of the Web tree. The information in this file is critical for performing security analysis, as it defines how servlets interact with the outside world. Although most of the information in the file is useful to code auditors, this section focuses on two important entries: servlets and servlet-mappings.

The web.xml file has a list of servlet entries, with each one listing a servlet in the application. This entry specifies the servlet's full class name and gives each servlet a manageable name used to reference it in other places in the configuration. This entry is also where servlet-specific configuration information and other options can be added. In their simplest form, servlet entries look like this:

<servlet>   <servlet-name>myserverbuddy</servlet-name>   <servlet-class>com.java.sun.popsicle.myserverbuddy   </servlet-class> </servlet> <servlet>   <servlet-name>evildoer</servlet-name>   <servlet-class>com.java.sun.popsicle.evildoer</servlet-class> </servlet>


The Web application defined by these servlet entries implements a list of servlets. The servlet-mapping entry associates a URL pattern with a servlet, as shown in these sample mappings:

<servlet-mapping>   <servlet-name>myserverbuddy</servlet-name>   <url-pattern>/buddy/*</url-pattern> </servlet-mapping> <servlet-mapping>   <servlet-name>evildoer</servlet-name>   <url-pattern>*.evl</url-pattern> </servlet-mapping>


Keep in mind that every servlet or JSP exposed to the Internet represents another attack surface and potential failure point. The best solution is to expose only what's necessary under the most restrictive conditions that make sense.




The Art of Software Security Assessment. Identifying and Preventing Software Vulnerabilities
The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities
ISBN: 0321444426
EAN: 2147483647
Year: 2004
Pages: 194

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net