You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Scott Christley <Sc...@oracle.com> on 2001/01/17 19:54:18 UTC

denial of service attack

I must apologize first by saying that I originally found this bug with
Jserv not Tomcat, but those of you who are familiar with Tomcat
internals can probably tell fairly quickly if this would still be an
issue.

=====
This bug deals with an out of memory condition within Jserv which is
more a design/security issue.  The scenario is that when a session is
created by a servlet; memory is allocated by the JVM for that session
and stays allocated until these two conditions occur 1) the servlet
invalidates the session or the session timeout is reached which
invalidates the session and 2) JVM garbage collection returns that
allocated memory back to the heap.

The reason this is a design/security issue is because any normal Java
Servlet application can be used for a denial of service attack.  The
Java Servlet specification encourages applications to use sessions if
they wish to maintain state.  A hacker can easily discover if any
application is a Java Servlet which uses sessions by checking to see if
the JSESSIONID cookie is defined; if the hacker finds one then a simple
program can be used to increase the memory usage on the server and crash
the JVM.

while (server is still up)
   send an HTTP request to the servlet URL which creates the session

The timeout variable and the maximum java heap size are the only two
ways that the application can attempt to avoid this attack; by setting a
short timeout and a large heap size, one can hope that there is a
sufficient span to handle all of the requests (i.e. the timeout kicks in
before the memory has max'ed out).  But there are problems with this:

* Set a timeout too short and normal users get their session invalidated
before they are able to complete normal usage of the application.
* Java heap size reserves memory which cannot be swapped out (on solaris
at least), so a large heap size puts a strain on the server's memory.
* The hacker can always deploy additional clients to generate more
concurrent requests.
=====

I have been writing stress tests for Jserv, Tomcat, and our own servlet
engine; when I brought this issue up with the developers here, I
essentially got my hand slapped (*sigh*) and told "application
developers must deal with this, it is not the servlet engines
responsibility".  Which I think is a highly unfortunate answer because
HttpSession is a core servlet API and telling developers that they
cannot use it and should use an alternate mechansim, just seems wrong to
me.  So, I figured I would post a message to this list for discussion.

I did have an idea for how this issue can be resolved; I've not totally
thought it through, but it may be a good start.

=====
Given a parameter (num_of_sessions) which is the maximum number of new
sessions.
Given a parameter (time_period) which is a time interval.

Implement a verification such that maximum number of new sessions that
can be created from the same client within a time interval.  This would
require that you maintain a creation date and client identifier with
each session.

if (creating a new session)
{
   session_count = 0
   Loop through set of sessions for that client
   {
      /* Was this session created within the time period */
      if ((current_date - creation_date_of_session) > time_period)
         ++session_count;
   }
   if ((session_count + 1) > num_of_sessions)
      /* Good possibility we are being attacked */
   else
     /* create the new session */
}
=====

Presumably default values could be given to the num_of_session and
time_period parameters which still allow the problem user (somebody
opening up multiple browser windows, stoppng/starting browser, etc) to
gain access to the application, yet small enough to prevent the JVM from
consuming large amounts of memory before the attack is discovered.  Once
an attack is discovered, the servlet engine could be proactive and
delete all of the sessions created by the client to free up the memory,
log messages, etc.

cheers
Scott

/* Thankfully Oracle doesn't speak for me, nor vice-versa */



RE: denial of service attack

Posted by Tomas Rokicki <ro...@instantis.com>.
What's a client?  For instance, if it's truly an attack, it would be
trivial to spoof IP addresses.  And with entire corporations behind
NAT firewalls, simply setting the number of sessions per IP addresses
to a `small' number would not work.

Or, are you saying, don't initiate a session until the client
authenticates himself?  That's great, except it still breaks for
things like account creation sequences.

Which can be implemented with hidden fields instead of sessions or
some such . . .

-tom

-----Original Message-----
From: Scott Christley [mailto:Scott.Christley@oracle.com]
Sent: Wednesday, January 17, 2001 10:54 AM
To: tomcat-dev@jakarta.apache.org
Subject: denial of service attack



I must apologize first by saying that I originally found this bug with
Jserv not Tomcat, but those of you who are familiar with Tomcat
internals can probably tell fairly quickly if this would still be an
issue.

=====
This bug deals with an out of memory condition within Jserv which is
more a design/security issue.  The scenario is that when a session is
created by a servlet; memory is allocated by the JVM for that session
and stays allocated until these two conditions occur 1) the servlet
invalidates the session or the session timeout is reached which
invalidates the session and 2) JVM garbage collection returns that
allocated memory back to the heap.

The reason this is a design/security issue is because any normal Java
Servlet application can be used for a denial of service attack.  The
Java Servlet specification encourages applications to use sessions if
they wish to maintain state.  A hacker can easily discover if any
application is a Java Servlet which uses sessions by checking to see if
the JSESSIONID cookie is defined; if the hacker finds one then a simple
program can be used to increase the memory usage on the server and crash
the JVM.

while (server is still up)
   send an HTTP request to the servlet URL which creates the session

The timeout variable and the maximum java heap size are the only two
ways that the application can attempt to avoid this attack; by setting a
short timeout and a large heap size, one can hope that there is a
sufficient span to handle all of the requests (i.e. the timeout kicks in
before the memory has max'ed out).  But there are problems with this:

* Set a timeout too short and normal users get their session invalidated
before they are able to complete normal usage of the application.
* Java heap size reserves memory which cannot be swapped out (on solaris
at least), so a large heap size puts a strain on the server's memory.
* The hacker can always deploy additional clients to generate more
concurrent requests.
=====

I have been writing stress tests for Jserv, Tomcat, and our own servlet
engine; when I brought this issue up with the developers here, I
essentially got my hand slapped (*sigh*) and told "application
developers must deal with this, it is not the servlet engines
responsibility".  Which I think is a highly unfortunate answer because
HttpSession is a core servlet API and telling developers that they
cannot use it and should use an alternate mechansim, just seems wrong to
me.  So, I figured I would post a message to this list for discussion.

I did have an idea for how this issue can be resolved; I've not totally
thought it through, but it may be a good start.

=====
Given a parameter (num_of_sessions) which is the maximum number of new
sessions.
Given a parameter (time_period) which is a time interval.

Implement a verification such that maximum number of new sessions that
can be created from the same client within a time interval.  This would
require that you maintain a creation date and client identifier with
each session.

if (creating a new session)
{
   session_count = 0
   Loop through set of sessions for that client
   {
      /* Was this session created within the time period */
      if ((current_date - creation_date_of_session) > time_period)
         ++session_count;
   }
   if ((session_count + 1) > num_of_sessions)
      /* Good possibility we are being attacked */
   else
     /* create the new session */
}
=====

Presumably default values could be given to the num_of_session and
time_period parameters which still allow the problem user (somebody
opening up multiple browser windows, stoppng/starting browser, etc) to
gain access to the application, yet small enough to prevent the JVM from
consuming large amounts of memory before the attack is discovered.  Once
an attack is discovered, the servlet engine could be proactive and
delete all of the sessions created by the client to free up the memory,
log messages, etc.

cheers
Scott

/* Thankfully Oracle doesn't speak for me, nor vice-versa */



---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, email: tomcat-dev-help@jakarta.apache.org



RE: denial of service attack

Posted by Tal Dayan <ta...@zapta.com>.
You proposal is based on determination that the request is 'from the same
client'. What is your definition for a 'client' and how do you determine if
two requests are form the same client ?


Tal

> -----Original Message-----
> From: Scott Christley [mailto:Scott.Christley@oracle.com]
> Sent: Wednesday, January 17, 2001 10:54 AM
> To: tomcat-dev@jakarta.apache.org
> Subject: denial of service attack
>
>
>
> I must apologize first by saying that I originally found this bug with
> Jserv not Tomcat, but those of you who are familiar with Tomcat
> internals can probably tell fairly quickly if this would still be an
> issue.
>
> =====
> This bug deals with an out of memory condition within Jserv which is
> more a design/security issue.  The scenario is that when a session is
> created by a servlet; memory is allocated by the JVM for that session
> and stays allocated until these two conditions occur 1) the servlet
> invalidates the session or the session timeout is reached which
> invalidates the session and 2) JVM garbage collection returns that
> allocated memory back to the heap.
>
> The reason this is a design/security issue is because any normal Java
> Servlet application can be used for a denial of service attack.  The
> Java Servlet specification encourages applications to use sessions if
> they wish to maintain state.  A hacker can easily discover if any
> application is a Java Servlet which uses sessions by checking to see if
> the JSESSIONID cookie is defined; if the hacker finds one then a simple
> program can be used to increase the memory usage on the server and crash
> the JVM.
>
> while (server is still up)
>    send an HTTP request to the servlet URL which creates the session
>
> The timeout variable and the maximum java heap size are the only two
> ways that the application can attempt to avoid this attack; by setting a
> short timeout and a large heap size, one can hope that there is a
> sufficient span to handle all of the requests (i.e. the timeout kicks in
> before the memory has max'ed out).  But there are problems with this:
>
> * Set a timeout too short and normal users get their session invalidated
> before they are able to complete normal usage of the application.
> * Java heap size reserves memory which cannot be swapped out (on solaris
> at least), so a large heap size puts a strain on the server's memory.
> * The hacker can always deploy additional clients to generate more
> concurrent requests.
> =====
>
> I have been writing stress tests for Jserv, Tomcat, and our own servlet
> engine; when I brought this issue up with the developers here, I
> essentially got my hand slapped (*sigh*) and told "application
> developers must deal with this, it is not the servlet engines
> responsibility".  Which I think is a highly unfortunate answer because
> HttpSession is a core servlet API and telling developers that they
> cannot use it and should use an alternate mechansim, just seems wrong to
> me.  So, I figured I would post a message to this list for discussion.
>
> I did have an idea for how this issue can be resolved; I've not totally
> thought it through, but it may be a good start.
>
> =====
> Given a parameter (num_of_sessions) which is the maximum number of new
> sessions.
> Given a parameter (time_period) which is a time interval.
>
> Implement a verification such that maximum number of new sessions that
> can be created from the same client within a time interval.  This would
> require that you maintain a creation date and client identifier with
> each session.
>
> if (creating a new session)
> {
>    session_count = 0
>    Loop through set of sessions for that client
>    {
>       /* Was this session created within the time period */
>       if ((current_date - creation_date_of_session) > time_period)
>          ++session_count;
>    }
>    if ((session_count + 1) > num_of_sessions)
>       /* Good possibility we are being attacked */
>    else
>      /* create the new session */
> }
> =====
>
> Presumably default values could be given to the num_of_session and
> time_period parameters which still allow the problem user (somebody
> opening up multiple browser windows, stoppng/starting browser, etc) to
> gain access to the application, yet small enough to prevent the JVM from
> consuming large amounts of memory before the attack is discovered.  Once
> an attack is discovered, the servlet engine could be proactive and
> delete all of the sessions created by the client to free up the memory,
> log messages, etc.
>
> cheers
> Scott
>
> /* Thankfully Oracle doesn't speak for me, nor vice-versa */
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
> For additional commands, email: tomcat-dev-help@jakarta.apache.org
>
>


Re: denial of service attack

Posted by Kief Morris <ki...@bitbull.com>.
Scott Christley typed the following on 10:54 AM 1/17/2001 -0800
>I must apologize first by saying that I originally found this bug with
>Jserv not Tomcat, but those of you who are familiar with Tomcat
>internals can probably tell fairly quickly if this would still be an
>issue.

It could potentially be an issue, but can be controlled to some extent.
The PersistentManager class I have submitted for Tomcat 4 offers
a bit more control. I can offer a few comments on Tomcat 4 with and
without this class.

The nature of the possible attack, as I understand it, is that a bad guy
can make a rapid series of requests to the web app, causing the generation
of a large number of session objects thereby eating up available memory.

The current StandardSession implementation has a parameter called
maxActiveSessions which, if set (it's disabled by default), limits the number
of sessions which the server will create. A request which tries to create
any sessions after the limit is reached throws an IllegalStateException.

This isn't ideal for the user experience, but if it is set according to the
likely session memory usage and the heap size, it should occur just before
memory runs out, so it's better than the alternative.

PersistentManager, which would be an optional replacement for
StandardSession, allows you to have sessions swapped out of memory 
(to a file or DB most likely) based on configurable parameters: idle time
and the number of active sessions. Sessions over a certain number would
be swapped out, as would sessions idle for a configurable time.

The caveat on this is that there is a danger of thrashing when the site
is very active - sessions could be constantly swapped in and out of memory,
exacerbating performance problems. So there is an option to set a minimum
idle time - sessions which are idle for less than this time won't be swapped
out even if there are more than maxActiveSessions in memory. This 
effectively turns maxActiveSessions into a soft limit rather than a hard limit.

>I did have an idea for how this issue can be resolved; I've not totally
>thought it through, but it may be a good start.
>
>=====
>Given a parameter (num_of_sessions) which is the maximum number of new
>sessions.
>Given a parameter (time_period) which is a time interval.
>
>Implement a verification such that maximum number of new sessions that
>can be created from the same client within a time interval.  This would
>require that you maintain a creation date and client identifier with
>each session.

As Tomas pointed out, identifying a client is problematic: the entire purpose
of using the cookie is to get around the difficulty in reliably identifying a client.
Perhaps this could be done on a system-wide level instead - limit the number
of new sessions created in a certain time period.

I tend to think that the PersistentManager options I outlined above can be used
to prevent this attack if configured correctly. maxActiveSessions can be
set as a hard limit to keep the active sessions to a number which can be 
safely supported by the heap size. This doesn't prevent an attacker from
eating up most of the available sessions and creating a bad situation for
legitimate users, but it should avoid an outright system crash. 


Kief