You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Glenn Nielsen <gl...@voyager.apg.more.net> on 2000/05/07 19:52:26 UTC

Tomcat SecurityManager proposal

        Proposal for implementing a SecurityManager for Tomcat 
                 
Use of a SecurityManager will require JDK1.2.

Create three new classes in org/apache/tomcat/loader:

        SecureAdaptiveClassLoader.java
        SecureAdaptiveServletLoader.java
        SecureNetworkClassLoader.java

These three classes will replace:

        AdaptiveClassLoader.java
        AdaptiveServletLoader.java
        NetworkClassLoader.java

at runtime if a SecurityManager is implemented.

This way the Secure versions can extend SecureClassLoader
instead of ClassLoader so that we can take full advantage
of the JDK1.2 SecurityManager.

Develop a SecurityManager to distribute with Tomcat as
org.apache.tomcat.loader.DefaultSecurityManager.

Add the following element to server.xml:

<SecurityManager className="class.of.custom.SecurityManager"/>

If the above element is in server.xml it well be instantiated
as the SecurityManager.  This will allow plugin replacement
of the org.apache.tomcat.loader.DefaultSecurityManager with
a custom SecurityManager.

Should the above element be added to server.dtd?

Once the DefaultSecurityManager and the three SecureClassLoaders
are implemented we can look into "TomcatPermissions" using the
AccessController and Permission classes.

I have modified org.apache.tomcat.startup.Tomcat to recognize
the SecurityManager element and have a stubbed version of
org.apache.tomcat.loader.DefaultSecurityManager.

Now I have to get busy on the Secure ClassLoaders and the
DefaultSecurityManager so that I don't get an AccessControlException
when starting Tomcat with a SecurityManager. :-)

Comments?

Regards,

Glenn
 
----------------------------------------------------------------------
Glenn Nielsen             glenn@more.net | /* Spelin donut madder    |
MOREnet System Programming               |  * if iz ina coment.      |
Missouri Research and Education Network  |  */                       |
----------------------------------------------------------------------

Re: Tomcat SecurityManager proposal

Posted by Costin Manolache <co...@costin.dnt.ro>.
> > > If for some reason you wanted to use a custom SecurityManager, then it could be
> > > configured in server.xml.
> >
> > No need I hope - it should be enough to use the right class loader.
> >
>
> It would be nice to leave that capability in, just in case.  How Permission
> is granted for file read/write access is somewhat limiting.  I am pretty
> sure it would require a custom SecurityManager to change that behaviour.

If you already have it - that's great. If you plan to write it - let's solve the
80% first :-)
I think the security desing in JDK1.2 allows you to do almost everything from
the policy file. The main problem is that you have to write the config file
before you start the JVM ( but you can reload it !).

IMHO it's ok to be hard to grant new permissions !!
This is one of the few places where "security by obscurity" will work :-)

The servlets should have minimal permissions. Even for database access,
probably you'll install the driver in the system classpath and grant it the
required network acceess and other permissions - the servlets will be able
to use it but still have no additional rights.


> > For testing - yes. Later, we should grant only a minimal set.
> > I have one somewhere, mostly accept on 8080, 8007,
> > some file access, creating class loaders and few other.
> >
> Could you forward that to me?

I'll have to find it first :-)

> > > BTW, in my testing it looks like the entire path to the classes directory has to
> > > be specified in the tomcat.policy file.  This could be be a pain if you want to
> > > use Security for JSP but allow all permissions for installed WAR files in WEB-INF.
> >
> > We can generate the policy file the same way we generate tomcat-apache.conf
>
> Hmmm...  thats an idea.  How about this?
>
> We configure a default Security Policy for webapps, and a default Security Policy
> for JSP in tomcat.policy, these defaults are sort of a virtual security policy
> that doesn't map to a real path where classes are loaded from.  And the class
> loader will not allow any classes to be loaded from these virtual directories.

I'm not sure I understand.

I was thinking of something very simple - all "special" rights can be in
a section of server.xml or in a separate file.
When tomcat starts ( with -generate.policy option ) , it will generate
a tomcat.policy containing the minimal set + the "special" rights.

It will know all the paths anyway, so it'll be very simple.

( of course - that can be implemented later, after everything else is
working and we have all the knowledge we need.)


> This way the tomcat.policy file can remain static, configured with default
> policies for WEB-INF and JSP, but on a case by case basis the policies for
> a specific webapp or JSP path can be overridden with custom policies.

Do we need multiple policies ? We only need write access to the temp dir,
granted to WEB-INF and to the directory where JSP generates files.
( and read to the context home, of course )

Costin




Re: Tomcat SecurityManager proposal

Posted by Glenn Nielsen <gl...@voyager.apg.more.net>.
Costin Manolache wrote:
> 
> > I didn't realize that NetworkClassLoader was deprecated.
> > Will this SecurityManger code need to be migrated into Catalina eventually?
> 
> I hope it will be reuseable code. Catalina is very different from an architecture
> point of view ( night and day ?), but the security policy should be similar.
> 
Ok.  I won't worry about making it pretty while testing this with Tomcat 3.1.
There are some opportunities to share code between the AdapativeClassLoader
and SecureAdaptiveClassLoader.  Like the code that actually loads the byte codes.

> Of course, since Catalina doesn't have Facades and can't isolate the
> servlet from the container - it will be more difficult to prevent nasty
> code. As someone said - security is a process, you can't just "fix" it.

Amen
 
> ( that's one of the "night and day" aspects )
> 
> > -Djava.security.manager -Djava.security.policy==${TOMCAT_HOME}/conf/tomcat.policy
> 
> The only trick is to have AdaptiveClass loader use the right defineClass() !
> 

Easy, just test with getSecurityManager() to see if one is installed.  Already
implemented.

> > If for some reason you wanted to use a custom SecurityManager, then it could be
> > configured in server.xml.
> 
> No need I hope - it should be enough to use the right class loader.
>

It would be nice to leave that capability in, just in case.  How Permission
is granted for file read/write access is somewhat limiting.  I am pretty
sure it would require a custom SecurityManager to change that behaviour.
 
> > > > This way the Secure versions can extend SecureClassLoader
> > > > instead of ClassLoader so that we can take full advantage
> > > > of the JDK1.2 SecurityManager.
> > >
> > > I don't think you need all that.
> > >
> > > AFAIK, it's enough to use the defineClass() method that takes a
> > > ProtectionDomain as parameter ( using the normal class loader ).
> > >
> >
> > The SecureAdaptiveClassLoader has to extend SecureClassLoader.
> > And then call the final defineClass() method in SecureClassLoader
> > and pass it a CodeSource Object.  The defineClass method that
> > accepts a CodeSource object is not defined for the normal
> > ClassLoader.
> 
> Are you sure ? There is a defineClass() that takes an extra
> ProtectionDomain parameter - and you can pass the CodeSource
> as part of the ProtectionDomain.  AFAIK it should have the
> same effect.
> 
> Well, it's not that important - if you got it working with SecureClassLoader
> it's fine, and probably it's easier that way.
> 

I am pretty sure, the Secure class loading is already working by extending 
SecureClassLoader.  The defineClass() method you can pass a ProtectionDomain 
to is used when you want to change the permissions for a specific CodeSource
to something different than what was in the security policy file.

> > // Tomcat gets all permissions
> > grant codeBase "file:/usr/local/kinetic/tomcat/lib/-" {
> >         permission java.security.AllPermission;
> > };
> 
> For testing - yes. Later, we should grant only a minimal set.
> I have one somewhere, mostly accept on 8080, 8007,
> some file access, creating class loaders and few other.
> 
Could you forward that to me?

> > BTW, in my testing it looks like the entire path to the classes directory has to
> > be specified in the tomcat.policy file.  This could be be a pain if you want to
> > use Security for JSP but allow all permissions for installed WAR files in WEB-INF.
> 
> We can generate the policy file the same way we generate tomcat-apache.conf

Hmmm...  thats an idea.  How about this?

We configure a default Security Policy for webapps, and a default Security Policy
for JSP in tomcat.policy, these defaults are sort of a virtual security policy
that doesn't map to a real path where classes are loaded from.  And the class
loader will not allow any classes to be loaded from these virtual directories.

file://default/tomcat/webapps/ProtectionDomain

and

file://default/tomcat/jasper/ProtectionDomain

Then the classloader will check to see if a ProtectionDomain exists for a
CodeSource, if it does, it uses it.  If there isn't a protection domain,
it gets the default protection domain from the defaults above, then uses 
that when calling defineClass().

This way the tomcat.policy file can remain static, configured with default
policies for WEB-INF and JSP, but on a case by case basis the policies for
a specific webapp or JSP path can be overridden with custom policies.

> 
> > Find where the AccessControlException is being caught, and generate
> > a concise error message to return back to the browser and log to
> > a tomcat log.  Or we could generate the servlet UnavailableException
> > to prevent the servlet/jsp from attempting to run in the future.
> >
> > Add parameters to the SecurityManager element of server.xml to specify
> > what paths/classes and permissions to use for dynamically setting up
> > ProtectionDomains using SecureAdaptiveClassLoader.
> >
> > Modify Jasper so that JSP's use the SecureAdaptiveClassLoader and honor
> > the tomcat.policy file.
> 
> Let me know if you need help :-)
> 

Just answering questions and bouncing around ideas for the SecurityManager 
design helps. :-)

Thanks

Glenn

----------------------------------------------------------------------
Glenn Nielsen             glenn@more.net | /* Spelin donut madder    |
MOREnet System Programming               |  * if iz ina coment.      |
Missouri Research and Education Network  |  */                       |
----------------------------------------------------------------------

Re: Tomcat SecurityManager proposal

Posted by Costin Manolache <co...@costin.dnt.ro>.
> I didn't realize that NetworkClassLoader was deprecated.
> Will this SecurityManger code need to be migrated into Catalina eventually?

I hope it will be reuseable code. Catalina is very different from an architecture
point of view ( night and day ?), but the security policy should be similar.

Of course, since Catalina doesn't have Facades and can't isolate the
servlet from the container - it will be more difficult to prevent nasty
code. As someone said - security is a process, you can't just "fix" it.

( that's one of the "night and day" aspects )


> -Djava.security.manager -Djava.security.policy==${TOMCAT_HOME}/conf/tomcat.policy

The only trick is to have AdaptiveClass loader use the right defineClass() !

> If for some reason you wanted to use a custom SecurityManager, then it could be
> configured in server.xml.

No need I hope - it should be enough to use the right class loader.

> > > This way the Secure versions can extend SecureClassLoader
> > > instead of ClassLoader so that we can take full advantage
> > > of the JDK1.2 SecurityManager.
> >
> > I don't think you need all that.
> >
> > AFAIK, it's enough to use the defineClass() method that takes a
> > ProtectionDomain as parameter ( using the normal class loader ).
> >
>
> The SecureAdaptiveClassLoader has to extend SecureClassLoader.
> And then call the final defineClass() method in SecureClassLoader
> and pass it a CodeSource Object.  The defineClass method that
> accepts a CodeSource object is not defined for the normal
> ClassLoader.

Are you sure ? There is a defineClass() that takes an extra
ProtectionDomain parameter - and you can pass the CodeSource
as part of the ProtectionDomain.  AFAIK it should have the
same effect.

Well, it's not that important - if you got it working with SecureClassLoader
it's fine, and probably it's easier that way.

> // Tomcat gets all permissions
> grant codeBase "file:/usr/local/kinetic/tomcat/lib/-" {
>         permission java.security.AllPermission;
> };

For testing - yes. Later, we should grant only a minimal set.
I have one somewhere, mostly accept on 8080, 8007,
some file access, creating class loaders and few other.


> BTW, in my testing it looks like the entire path to the classes directory has to
> be specified in the tomcat.policy file.  This could be be a pain if you want to
> use Security for JSP but allow all permissions for installed WAR files in WEB-INF.

We can generate the policy file the same way we generate tomcat-apache.conf


> Find where the AccessControlException is being caught, and generate
> a concise error message to return back to the browser and log to
> a tomcat log.  Or we could generate the servlet UnavailableException
> to prevent the servlet/jsp from attempting to run in the future.
>
> Add parameters to the SecurityManager element of server.xml to specify
> what paths/classes and permissions to use for dynamically setting up
> ProtectionDomains using SecureAdaptiveClassLoader.
>
> Modify Jasper so that JSP's use the SecureAdaptiveClassLoader and honor
> the tomcat.policy file.

Let me know if you need help :-)

Costin


Re: Tomcat SecurityManager proposal

Posted by Glenn Nielsen <gl...@voyager.apg.more.net>.
Costin Manolache wrote:
> 
> Glenn Nielsen wrote:
> 
> >         Proposal for implementing a SecurityManager for Tomcat
> >
> > Use of a SecurityManager will require JDK1.2.
> 
> +1 - that doesn't means tomcat will no longer run on 1.1, just that
> you'll need 1.2 to take advantage of policy based security ( since this
> is
> a 1.2 feature ).
> 

Yes, using Tomcat with a SecurityManagar will require 1.2, but if you
don't need a SecurityManager you can still run Tomcat under 1.1.

> > Create three new classes in org/apache/tomcat/loader:
> >
> >         SecureAdaptiveClassLoader.java
> >         SecureAdaptiveServletLoader.java
> >         SecureNetworkClassLoader.java
> 
> NetworkClassLoader is not used ( most testing is done with Adaptive ).
> It also doesn't have reloading support - so probably a better idea would
> be
> to just remove it.
> 
> > These three classes will replace:
> >
> >         AdaptiveClassLoader.java
> >         AdaptiveServletLoader.java
> >         NetworkClassLoader.java
> 
> Not replace - can be used instead of !!
> ( the default config will still use the 1.1 version, you'll have
> to edit server.xml if you want to use the secure version )
> 

I didn't realize that NetworkClassLoader was deprecated.
Will this SecurityManger code need to be migrated into Catalina eventually?

So at runtime, use of a SecurityManager will cause the SecureAdaptiveServletLoader
and SecureAdaptiveClassLoader to be used instead of the 1.1 versions of 
the AdaptiveSevletLoader and AdaptiveClassLoader.

I found out a SecurityManager can be implemented without changing server.xml
if you want to use the System java.lang.SecurityManager.  Just add these options
when starting Tomcat:

-Djava.security.manager -Djava.security.policy==${TOMCAT_HOME}/conf/tomcat.policy

With the above, we can ignore the default java.policy files and just use a custom
policy file in the tomcat conf directory.

If for some reason you wanted to use a custom SecurityManager, then it could be
configured in server.xml.


> > This way the Secure versions can extend SecureClassLoader
> > instead of ClassLoader so that we can take full advantage
> > of the JDK1.2 SecurityManager.
> 
> I don't think you need all that.
> 
> AFAIK, it's enough to use the defineClass() method that takes a
> ProtectionDomain as parameter ( using the normal class loader ).
>

The SecureAdaptiveClassLoader has to extend SecureClassLoader.
And then call the final defineClass() method in SecureClassLoader
and pass it a CodeSource Object.  The defineClass method that
accepts a CodeSource object is not defined for the normal
ClassLoader.

> > Develop a SecurityManager to distribute with Tomcat as
> > org.apache.tomcat.loader.DefaultSecurityManager.
> 
> Why is this needed ?
> A sample security.policy should be enough for most cases.
> 

Probably not, I will use the system java.lang.SecurityManager for now.

> The only "special" thing may be a TomcatPermission and a
> check that will allow a servlet to access internal objects, but that
> doesn't require SecurityManager.
> 
> > Now I have to get busy on the Secure ClassLoaders and the
> > DefaultSecurityManager so that I don't get an AccessControlException
> > when starting Tomcat with a SecurityManager. :-)
> 
> Try first with just a simple policy and just use the class loader with
> the long version of defineClass. That's the hardest part.
> 

Ok, I have an implementation of the SecureAdaptiveServletLoader and
SecureAdaptiveClassLoader that respects the tomcat.policy file.

Here is the tomcat.policy file I am testing with:

------------------------------------------------------------------------------
// Standard extensions get all permissions by default

grant codeBase "file:${java.home}/lib/ext/-" {
        permission java.security.AllPermission;
};

// Tomcat gets all permissions
grant codeBase "file:/usr/local/kinetic/tomcat/lib/-" {
        permission java.security.AllPermission;
};

// Give the examples servlet classes all permissions
grant codeBase "file:/local/kinetic/tomcat/webapps/examples/WEB-INF/classes/-" {
        permission java.security.AllPermission;
};

// default permissions granted to all domains

grant {
	...
}
------------------------------------------------------------------------------

If I remove the above grant for webapps/examples, an AccessControlException is
generated, but somewhere that Exception is being caught and the servlet runs
anyway.

BTW, in my testing it looks like the entire path to the classes directory has to 
be specified in the tomcat.policy file.  This could be be a pain if you want to
use Security for JSP but allow all permissions for installed WAR files in WEB-INF.

We can probably get around that by adding some Security parameters for the 
SecurityManager server.xml element, then pass a ProtectionDomain to defineClass()
to dynamically setup permissions for classes in WEB-INF.

I tested it with JSP, but Jasper is using the system ClassLoader and always
generates an AccessControlException.

Looks like the first goal of getting Tomcat to honor a java policy file
has been completed.

Here are my ideas of what to work on next:

Find where the AccessControlException is being caught, and generate
a concise error message to return back to the browser and log to
a tomcat log.  Or we could generate the servlet UnavailableException
to prevent the servlet/jsp from attempting to run in the future.

Add parameters to the SecurityManager element of server.xml to specify
what paths/classes and permissions to use for dynamically setting up
ProtectionDomains using SecureAdaptiveClassLoader.

Modify Jasper so that JSP's use the SecureAdaptiveClassLoader and honor
the tomcat.policy file.

Comments?  Suggestions?

Glenn

----------------------------------------------------------------------
Glenn Nielsen             glenn@more.net | /* Spelin donut madder    |
MOREnet System Programming               |  * if iz ina coment.      |
Missouri Research and Education Network  |  */                       |
----------------------------------------------------------------------

Re: Tomcat SecurityManager proposal

Posted by Costin Manolache <co...@costin.dnt.ro>.
Glenn Nielsen wrote:

>         Proposal for implementing a SecurityManager for Tomcat
>
> Use of a SecurityManager will require JDK1.2.

+1 - that doesn't means tomcat will no longer run on 1.1, just that
you'll need 1.2 to take advantage of policy based security ( since this
is
a 1.2 feature ).


> Create three new classes in org/apache/tomcat/loader:
>
>         SecureAdaptiveClassLoader.java
>         SecureAdaptiveServletLoader.java
>         SecureNetworkClassLoader.java

NetworkClassLoader is not used ( most testing is done with Adaptive ).
It also doesn't have reloading support - so probably a better idea would
be
to just remove it.


> These three classes will replace:
>
>         AdaptiveClassLoader.java
>         AdaptiveServletLoader.java
>         NetworkClassLoader.java

Not replace - can be used instead of !!
( the default config will still use the 1.1 version, you'll have
to edit server.xml if you want to use the secure version )


> This way the Secure versions can extend SecureClassLoader
> instead of ClassLoader so that we can take full advantage
> of the JDK1.2 SecurityManager.

I don't think you need all that.

AFAIK, it's enough to use the defineClass() method that takes a
ProtectionDomain as parameter ( using the normal class loader ).

> Develop a SecurityManager to distribute with Tomcat as
> org.apache.tomcat.loader.DefaultSecurityManager.

Why is this needed ?
A sample security.policy should be enough for most cases.

The only "special" thing may be a TomcatPermission and a
check that will allow a servlet to access internal objects, but that
doesn't require SecurityManager.


> Now I have to get busy on the Secure ClassLoaders and the
> DefaultSecurityManager so that I don't get an AccessControlException
> when starting Tomcat with a SecurityManager. :-)

Try first with just a simple policy and just use the class loader with
the long version of defineClass. That's the hardest part.

Costin