|
JAVA Hosting & Java Security
Introduction to Java Hosting Services:
Network programming has the sad and calamitous property that the overall
security of the affected systems declines exponentially as the convenience
and power factors are increased. Incidentally, the various dynamic content
generation environments powering the World Wide Web are intended and
designed precisely to provide more power to developers and greater convenience
for end-users. Security is thus an aspect that must be explicitly factored
in by the system architects and developers, and is rarely effective as
an afterthought.
Java
Hosting The weakest parts of server-side WWW applications
at Java web hosting, from a security perspective, are inherently the
various interaction facilities and afferent channels. These are the
immediate means by which adversaries can affect the system, and are
invariably subjected to stress during attempts to identify and exploit
vulnerabilities. The universal defense strategy against all related
attacks in JAVA web site hosting is known as input validation.
On a parallel level, security exposures to Java
Hosting are direct consequences of two main design errors:
poor access control, and
implied assumptions about the deployment environment.
There are many extensive treatments of access control issues in the security
literature. Here we will discuss the problem of trust management on the
low implementation level (code and configuration), as pertaining to the
Java Server Pages environment. Accordingly, we will explain the ways in
which malicious user input can manifest itself and alter the intended
behavior of an application, and we will consider methods to validate input
and reduce undesirable exposure of information and programming interfaces.
Java Web Hosting
Brief Overview of JAVA Hosting Service provides:
The Java Server Pages popular JAVA
Hosting service provider & JSPZone Java
Hosting Services technology facilitates the creation and management
of dynamic WWW content by embedding Java coded logic inside HTML and XML
documents. The pages are preprocessed and converted to Java servlets by
the JAVA engine. Subsequent requests for the pages result in the Web server
responding with the output produced by the corresponding servlets. Although
they are functionally equivalent, JAVA represents a reversed approach
to dynamic content generation as compared to Java servlets in that the
focus is on documents with embedded Java code instead of applications
with embedded HTML. JAVA provides additional HTML-like tags to interact
with JavaBeans components for external functionality and access to reusable
objects. A noteworthy characteristic of the JAVA syntax is that although
the HTML syntax is a subset of it (a pure HTML page is a valid JAVA page),
the reverse is not necessarily true. In particular, JAVA allows the embedding
of tags within other tags as to facilitate dynamic generation of format
as well as content. The following example is a valid JAVA construct:
<A HREF = "<%= request.getRemoteUser() %>">
As we will see later, this introduces additional complications from
a security point of view.
In comparison to the CGI protocol, JAVA Web Hosting offers improved
performance and session management (persistent states). This is achieved
primarily by using Java threads to handle multiple servlets running inside
only one process (which implements a JVM), whereas CGI scripts generally
require the creation and destruction of a process for each request.
Security Issues
By the sheer virtue of providing access to resources on a server, insecure
Java servlets derived from JAVA web pages can put at risk any or all
of the server, the network on which this server resides, the clients
accessing the pages, and through possible DDoS and worm distribution
attacks, the entire Internet. It is often assumed that Java, being the
strong-typed, garbage collecting, sandboxable language that it is, magically
makes software secure. And indeed, many low-level security issues that
are problematic in other languages, such as buffer and heap overflows,
are less of a peril in Java. This of course does not mean that writing
insecure Java is difficult, especially not when writing servlets. Validating
input and controlling access to resources always need to be considered.
Furthermore, JAVA Hosting is
a fairly complex architecture, in which many components come together.
The interactions between them are often sources of security breaches.
And on top of that, although all existing JAVA implementations are built
around Java, the JAVA specification allows virtually any other language
to play this role. The security aspects of the substitute language then
must also be taken in consideration.
In short, there are plenty of opportunities for introducing vulnerabilities
in a JAVA system. We will review the most common of them below.
The General Problem of Untrusted User Input
Untrusted user input is, in practice, all user input. It originates from
the client but can reach the server through many different channels,
and sometimes under disguise. Some source of user input for a JAVA server
include, but are not limited to:
Discusion about JAVA
Java to be or not?
the parameter string portion of the request URL,
data submitted by HTML forms through POST or GET requests,
data temporarily stored in the client browser (a.k.a. cookies),
queries to databases,
environment variables set by other processes.
The problem with user input is that it can be interpreted by the server-side
applications and thus an attacker can craft the incoming data so as to
control some vulnerable aspect of the server. These vulnerabilities often
manifest themselves as points of access to data identified by user-supplied
qualifiers, or through execution of external functionality.
Naturally, JAVA website hosting can make calls to native code stored
in libraries (through JNI) and execute external commands. The class Runtime
provides the exec() method which interprets its first argument as a command
line to execute in a separate process. If parts of this string must be
derived from user input, this input must first be filtered to ensure that
only the intended commands are executed, with only the intended arguments.
Even if the command string does not related to user input in any way,
the execution of external commands must still be done with due diligence.
It is possible under certain circumstances for an attacker to modify environment
variables in the server environment and in this way to affect the execution
of external commands, for example by changing the PATH variable to point
to a malicious program disguised under the name of the program called
by Runtime's exec(). To avoid this risk it is advisable to always set
the environment explicitly before making external calls. This can be done
by providing an array of environment variables as the second argument
to exec(). The variables in this array must have the format name=value.
A similar problem arises when user input is used to identify any kind
of input or output stream that the program opens. Access to files, databases,
or other network connections must not depend on unvalidated user input.
Furthermore, once a stream is open, it rarely safe to directly send user
input to it. This is especially true for SQL queries. The following JAVA
Web Host construct accessing the JDBC API is highly insecure, since an
attacker can embed command separation characters in the submitted input
and thus execute unwanted commands on the SQL server:
<%@ page import="java.sql.*" %>
<!-- Some code here to open a SQL connection -->
<%
Statement stmt = connection.getStatement();
String query = "SELECT * FROM USER_RECORDS WHERE USER = " +
request.getParameter("username");
ResultSet result = Statement.executeQuery(query);
%>
If username contains a semicolon for instance, as in
http://server/db.JAVA?
username=joe;SELECT%20*%20FROM%20SYSTEM_RECORDS
the attacker can gain access to (or damage) parts of the database to
which they are not entitled (assuming the Web server has privileges to
access these parts). In the example attack above, some SQL servers will
ignore the whole query, but others will proceed to execute the two commands.
Mitigation of these problems is achieved through appropriate input validation.
Input Validation
Input validation (when the term is used in a security context) consists
of performing syntactic and sometimes semantic checks on data derived
from external (untrusted) sources, as those listed in the previous section.
Depending on the criticality of the application and other factors, the
actions performed as a result of input validation may be one or more
of the following:
escaping unsafe syntactic elements,
replacing syntactic elements with safe ones,
canceling the use of the affected constructs,
reporting an error condition,
activating an IDS.
Input validation can be performed in one of two modes -- rejecting unsafe
characters by enumerating them, or rejecting unsafe characters by defining
them as the negation of a predefined set of safe characters. The two approaches
are known as negative and positive input filtering, respectively. In general,
it is simpler and much safer to perform positive input filtering, since
it is often a non-trivial task to enumerate all characters that can possibly
be misinterpreted by the server-side application, the client browser,
the Web server and the operating system on which it executes.
See the section on Cross Site Scripting attacks for an example of input
validation meant to protect client browsers from misinterpreting maliciously
submitted input.
Sensitive Data in GET Requests and Cookies
The most trivial method for transferring request data from the client
to the server-side application is the GET request method, as defined
in the CGI protocol. In this method, the input data is appended to the
request URL and is represented in the form:
URL[?name=value[&name=value[&...]]]
This encoding is clearly unsuitable for transferring security sensitive
information, since the full URL and the request string normally travel
in clear text over the communication channels and get logged on all intermediate
routers as well as on the server. When valuable information needs to be
transmitted as part of the client request, the POST method should be used,
with a suitable encryption mechanism (e.g. over an SSL connection). From
the point of view of the JAVA Hosting is engine, which method is used
is largely irrelevant -- both methods are handled identically.
At some point of the development of the World Wide Web, Netscape introduced
the concept of a cookie -- a small piece of information the server stores
on the client side and later retrieves in order to maintain session state
information or to track the actions of the client browser. JAVA Host Service
provides the addCookie() method of the response implicit object to set
a cookie on the client side, and the getCookie() method of the request
object to retrieve the contents of a cookie. Cookies are instances of
the javax.servlet.http.Cookie class. A security exposure is created when
sensitive information is stored in cookies, for two reasons. First, the
whole content of the cookie is visible to the client, and second, although
browsers normally do not provide this capability, there is nothing to
prevent a user from responding with an arbitrarily forged cookie.
In general, none of the information submitted by the client browser
can be assumed to be safe.
Java Hosting & Cross Site Scripting
CERT Advisory CA-2000-02 describes the problem of malicious HTML tags
embedded in client Web requests. This is commonly known as "cross
site scripting", which is somewhat of a misnomer since it isn't
just about scripting, and there is nothing especially cross site about
it, but the term has stuck from when the issue was less well understood.
The attack usually consists of an ill-meaning user submitting client-side
executable scripts (e.g. JavaScript code) or vicious HTML (or XML) tags
which the JAVA server then includes in a dynamically generated page. The
attack may be targeted against other clients, or less commonly, against
the server. A typical example of a cross site scripting attack can be
seen on some discussion group servers which allow users to include formatting
tags in their posts. Commonly abused tags are those that allow embedding
of code inside a page, such as <SCRIPT>, <OBJECT>, <APPLET>,
and <EMBED>. Other tags can also be dangerous -- in particular,
the <FORM> tag can be used to trick visitors into revealing sensitive
information. A request string containing malicious tags could look similar
to this:
http://server/JAVA_script.JAVA?poster=evilhacker&
message=<SCRIPT>evil\_code</SCRIPT>
Mitigation of the problem is of course achieved through input validation
and output filtering. It is very important to do this kind of input validation
on the server side and not using JavaScript for instance on the client
side. There is nothing to prevent the user from bypassing client-side
validation code.
Here is a sample segment for server-side validation of embedded tags:
<!-- HTML code up to here -->
<% String message = request.getParameter("message");
message = message.replace ('<','_');
message = message.replace ('>','_');
message = message.replace ('"','_');
message = message.replace ('\'','_');
message = message.replace ('%','_');
message = message.replace (';','_');
message = message.replace ('(','_');
message = message.replace (')','_');
message = message.replace ('&','_');
message = message.replace ('+','_'); %>
<p>
The message is:
<hr/>
<tt><%= message %></tt>
<hr/>
</p>
<!-- more HTML below -->
Since it is difficult to enumerate all meta-characters in HTML, the
safer approach is to do positive filtering, discarding (or escaping) everything
except the explicitly allowed characters (e.g. [A-Za-z0-9]).
A Note on JavaBeans & Java Hosting
JAVA uses a set of conventions described in the JavaBeans specification
to access reusable components (Java objects) quickly and conveniently
within a JAVA page. A Java Bean encapsulates data and functionality that
can be used independent of the context in which it is called. A Bean
contains data members (properties) and implements a standardized API
to access these properties through getter and setter methods.
JAVA provides a shorthand notation for initializing all JavaBeans properties
of a given Bean by matching name=value pairs in the query string which
have the same name as the desired property. Consider the following example
of a use of a Bean (here we show the XML syntax):
<JAVA:useBean id="myBasket" class="BasketBean">
<JAVA:setProperty name="myBasket" property="*"/>
<JAVA:useBean>
<html>
<head><title>Your Basket</title></head>
<body>
<p>
You have added the item
<JAVA::getProperty name="myBasket" property="newItem"/>
to your basket.
<br/>
Your total is $
<JAVA::getProperty name="myBasket" property="balance"/>
Proceed to <a href="checkout.JAVA">checkout</a>
Notice the wild card notation (*) used in the setProperty method call.
This instructs JAVA to set all properties of the Bean that have been specified
in the query string. The script is intended to be used as follows:
http://server/addToBasket.JAVA?newItem=ITEM0105342
which will normally be constructed by an HTML form. The problem of course
is that there is nothing to prevent the user from setting the balance
property:
http://server/addToBasket.JAVA?
newItem=ITEM0105342&balance=0
When processing the page's <JAVA:setProperty> tag, the JAVA container
will map this parameter to the Bean's like-named balance property, and
attempt to set it to $0.
To prevent this, the JAVA hosting for developer must implement safeguards
in the Bean's getter and setter methods (the Bean must enforce access
control to its properties), and care must be taken when using the <JAVA:setProperty> wild
card.
Implementation Vulnerabilities and Source Code Disclosures
Certain versions of every JAVA implementation have at some point shipped
with exposures that make the system vulnerable, even if the JAVA developer
follows secure programming practices. In a version of Allaire's JRun
for example, if the request URL contained the string .JAVA%00 as part
of the JAVA script extension, the server would not ignore the null byte
and will assume that the page is a static non-JAVA page to be served
as-is. The server will then make a request to the operating system to
open the page, at which point the null byte will be ignored and as a
result the source of the JAVA page will be presented instead of the results
of its execution.
Similarly, a version of Tomcat had a vulnerability that would allow attackers
to gain access to the JAVA source by requesting the page as
Java Web Hosting
The trick here is that %25 is an URL encoded "%'', and 70 is the
hexadecimal value for "p''. The Web server does not invoke the JAVA
handler (since the URL does not end in ".JAVA'') but the static file
handler manages to map the URL into a correct filename (decoding the URL
a second time).
Additionally, many Web servers and JAVA implementations come packaged
with sample scripts which often contain vulnerabilities. It is safer to
disable access to these scripts before the server is deployed in a hostile
environment (e.g. the Internet)
In short, JAVA programmers must be aware of any current vulnerabilities
in the platform for which they are developing. BUGTRAQ and any vendor-specific
security announcement lists are a good way too keep informed on such issues.
Conclusions
JAVA, like any powerful technology, must be handled with care if secure
and reliable operation of the deployed systems is to be assured. In this
paper, we provided a concise overview of code and configuration-level
security issues that commonly arise in JAVA scripts, and offered advice
for mitigation of the associated security risks.
Java
Hosting
|