You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@maven.apache.org by Bear Giles <bg...@coyotesong.com> on 2003/06/12 03:15:52 UTC

several security issues with maven

I've been struggling for the better part of the day to get maven
to work... and have identified several critical security issues in
the process.  N.B., these are so critical that many sysadmins will
not only allow maven, they'll disallow anything built with it!

(Standard stuff: maven 1.0.b9, binary release, standard
configuration since I've been unable to find any configuration files.)

...

The first issue is the practice of physically unpacking plugin jar
files in the $MAVEN_HOME/plugins directly.  This requires the
directory to be writable by the least privileged user who will run
maven - in practice this directory will almost always be
world-writable, perhaps with the sticky bit set.

Worse in this situation, maven simply loads every jar file in the
directory.  It does not read an externally defined (and protected)
list.

This is an extremely critical error - it means that maven will
normally be configured so any user can toss any jar file into that
directory and maven will unpack it and do whatever it does with
plugins.  If the directory is world-writable but doesn't have the
sticky bit set, any user could replace a standard jar file with
their own malicious one.

If you haven't turned ash white, hit the library and pick up the
issue of the Comm. of the ACM where (Kerrigan & Plauger?) discuss
their experiments with malicious compilers that insert their own
code.  The damage is far worse with java, since java.net is a
standard component and it is trivial for even an inexperienced
java programmer to write net-aware exploits.

Solution: $MAVEN_HOME/plugins must be treated like any other
system library directory - it must work with 0555 permissions.

In this case, the fix should actually be straightforward since the
   nonsense about unpacking the file to read its content with a
FileInputStream should be replaced with a java.util.jar.Jarile and
   a call to java.util.jar.JarEntry.getInputStream().

The caching is another issue... but at first glance I don't
understand why this would even be an issue - I'm not aware of any
other application that physically unpacks jar files like that.
It's not hard to open each jar file and cache the entries at
startup -- and hides it all behind a specialized classloader.

...

The second issue is more subtle.  When packages are downloaded,
they are put into the global $MAVEN_HOME/repository.

The GLOBAL repository.

The same issues crop up - the repository will need to be
world-writable, malicious jarfiles can be added (complete with
matching MD5 checksums), etc.

There's a standard solution to this - maven should cache files in
a per-user repository, not the global repository.  Or maven can
attempt to write to the global repository first, then quietly
fallover to the per-user repository if access is denied.

...

Other fixes.

For the sake of completeness, there is a workaround available...
but it's considered unacceptable by most sysadmins.  The solution
is to set the group of the $MAVEN_HOME/plugins and
$MAVEN_HOME/repository directories to some unique group, e.g.,
"maven", then set the "maven" script setgid "maven."  This would
allow maven to update these directories, while denying write
access to the average user.

(Another variant would set the "user" to "maven" and make the
script setuid).

This is unacceptable since it requires making a script setgid (or
setuid) - a big no-no in many circles.  We can't make the java
executable setgid without making the directories effectively
world-writable again.

...

Some code may follow, to illustrate possible solutions.

Bear


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


Re: several security issues with maven

Posted by Bear Giles <bg...@coyotesong.com>.
Answering one of my own questions (for the archive), the files are 
unpacked because MavenUtils.getProject() expects a java.io.File 
argument for a Betwixt parser.  I haven't used Betwixt, but I 
would expect there to be another method that takes an InputStream.

This suggests that the classloader object I included earlier could 
either provide special hooks for the project.xml and similar 
top-level files, returning InptuStreams that can be used by 
parsers, or the classloader can simply maintain some beanjars in 
the same package.  This would add something like

     }
     else if (name.equals("project.xml")) {
        BeanReader pbr = getProjectBeanReader();
        Project project =
           (Project) pbr.parse(jf.getInputStream(ze));
        ProjectBeans.add(project);
     }

There is also some information encoded into the directory 
structure, but it's not clear to me if that's an issue with the 
plugin jars.  If it is, the information can be easily cached 
somewhere.


Also, a bit of clarification on the motivations I was discussing 
last night.  The question I keep coming back to is "how do I know 
this?"  The more you know, the more you want to lock down 
everything. :-)


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


Re: several security issues with maven

Posted by Bear Giles <bg...@coyotesong.com>.
Florin Vancea wrote:
> Hello Bear, hello all,
> 
> IMHO, the final continuous build machine should be anyway a root-only
> machine (OK, root and the-same-root-person-as-a-common-user). The developer
> machine is also pretty much a developer-only machine, so there is little
> concern about some other user fiddling with the files.

To be honest, my concern isn't another user fiddling with the 
files.  That type of stuff is best handled administratively.

My concern is everyone you don't know about.  As maven is used by 
more projects, it becomes a more attractive target.  And that 
means you have to start worrying about more sophsticated 
attackers.  Forcing them to get root access to do any damage 
raises the barrier a bit, and keeping everything in the original 
jar files (vs. unpacking them) helps a bit more.

> If so, the problem is common to many
> other packages than only Maven.

Very few support plugin libraries to this extent.  Plugins are 
always problematic - system libraries have presumably had some 
amount of testing, etc.  But "plugins" are often lightweight, 
poorly tested code which is still run with high privilege.  That's 
scary - it's not as bad as Outlook's willingness to run arbitrary 
code from anyone who bothers to send some its way, but it's still 
pretty scary.


Anyway... the attached file is a ClassLoader that scans the ToC of 
all of the jar files in a subdirectory, then loads the content on 
demand.  The "main" routine shows how to use the standard 
interface to load a class, a ResourceBundle, or an arbitrary 
resource (e.g., a .png image).

Something it doesn't yet support, but easily could, is a separate 
SecurityManager for plugin classes.  E.g., maybe the maven classes 
have net access, but the plugins don't.  (Or only specific ones 
do.)  Another possible idea is restricting the classes that can be 
loaded by the plugins, e.g., allowing them to load standard java.* 
  and javax.* libraries, but not others.

The same thing applies to all downloaded code - to me it makes a 
lot of sense to be able to set up rules in the build environment 
that say an automatically downloaded package can't download 
another package, it can't access the net at all, perhaps can't 
read or write any files outside of a sandbox, etc.  If you really 
need some of these packages, they should be deliberately bundled 
and installed in the regular classpath.

After this security manager is installed, you have some measure of 
protection even if somebody manages to corrupt an upstream 
package.  Your production environment may still get hosed, but 
your development environment should be protected from a rogue 
jarfile scribbling into others.

Re: several security issues with maven

Posted by Florin Vancea <fv...@maxiq.ro>.
Hello Bear, hello all,

IMHO, the final continuous build machine should be anyway a root-only
machine (OK, root and the-same-root-person-as-a-common-user). The developer
machine is also pretty much a developer-only machine, so there is little
concern about some other user fiddling with the files.

Are you thinking about some academic-like environment? (shared machines or
many accounts on the same machine) If so, the problem is common to many
other packages than only Maven. I guess there are a lot of development tools
that require in a form or other rights higher than the average admin would
be happy to grant (I've had my share with MS tools).

The new features like split and read-only installation can be however
helpful, and a little thought on security won't hurt, but the nature of the
development environment is different than the nature of a production one, at
least from the security point of view.

Florin



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


Re: several security issues with maven

Posted by Bear Giles <bg...@coyotesong.com>.
Attached is a quickie implementation of a class loader, if it will 
help.  I didn't touch resource URLs, but an approach I've used 
with a lot of success in the past is to use a form like

   jar:/path/to/jarfile?file/within/jarfile

That's easy to construct, easy to parse, unique, and not easily 
confused with standard URLs.

Something occured to me a few minutes ago - conceptually the 
entire retrieval subsection is another classloader.  In fact, it 
should be a SecureClassLoader - the SecurityManager could be use 
to restrict access to some upstream sites (e.g., you could disable 
access to a site you believe to have been compromised), local 
write access to the repository, etc.

In this case the classloader I mentioned above would disappear. 
Somewhere near the top of the program the new classloader would be 
specified, then everyone would just load files as usual.  The 
classloader (and security manager) would decide whether to 
download files, where to cache them, etc.  Everyone else would 
either see requests succeed or a ClassNotFoundException.

Brett Porter wrote:
> Already fixed in CVS for b10 - the whole maven installation can now be 
> read only and the plugins are expanded to ~/.maven/plugins

I guess I'm still confused why they're expanded at all.  Writing 
files is hard - how good is Java at guarding against symlink 
attacks, race conditions, etc.?

>> The second issue is more subtle.  When packages are downloaded,
>> they are put into the global $MAVEN_HOME/repository.
> 
> Define maven.repo.local in ~/build.properties and it will store it 
> wherever you choose. In b10, the default is ~/.maven/repository

What if you want that split behavior?  Or prohibiting downloading 
any file by an untrusted user - they need to ask a trusted user to 
retrieve upstream packages for them.

I guess I should cut to the chase - where's the formal security 
policy?   That would identify roles, rights, etc.

> I've found current CVS to be at least as stable as b9 if not more so, 
> and its easy to build with the bootstrap, so I'd recommend giving it a go.

I've been unable to get any snapshot to compile yet.  I didn't try 
to compile the current CVS head because I'm trying to rebuild and 
package other Apache packages and need to provide a provenance of 
all tools - whatever I use has to be recreatable by others, so a 
tagged CVS snapshot is okay, the "current contents" are not.

Running the binary package was a stopgap measure - self-compiling 
a tool from its own binary is very risky (see the CACM article for 
the gruesome details why), but it would allow me to proceed 
provisionally.

> Don't panic ;)

I wasn't panicked.  Pissed at having wasted hours, but not 
panicked. :-)

Re: several security issues with maven

Posted by Brett Porter <bp...@f2network.com.au>.
> The first issue is the practice of physically unpacking plugin jar
> files in the $MAVEN_HOME/plugins directly.  This requires the
> directory to be writable by the least privileged user who will run
> maven - in practice this directory will almost always be
> world-writable, perhaps with the sticky bit set.

Already fixed in CVS for b10 - the whole maven installation can now be 
read only and the plugins are expanded to ~/.maven/plugins

> The second issue is more subtle.  When packages are downloaded,
> they are put into the global $MAVEN_HOME/repository.

Define maven.repo.local in ~/build.properties and it will store it 
wherever you choose. In b10, the default is ~/.maven/repository

I've found current CVS to be at least as stable as b9 if not more so, 
and its easy to build with the bootstrap, so I'd recommend giving it a go.

Don't panic ;)

Cheers,
Brett

-- 
Web Developer
f2 network ~ everything essential
02 8596 4437


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