XWiki, Log4J and Tomcat Security Manager: success (almost)
Hi there, Working to solve my SecurityExceptions running on a shared hosting, I tried to create a similar environment on my local Tomcat. The problem is not solved, but what I got so far may be useful for some XWiki users. After running "server.bat -security" I started getting errors related to Log4J already described by other threads on the mailing list archive, which I solved this way: 1. Take the log4j.properties from WEB-INF/lib/xwiki.jar and put it as WEB-INF/classes. The Servlet API specs state that WEB-INF/classes comes in the web app classpath before jar files placed in WEB-INF/lib. 2. Changed so the log file gets an absolute path under the web app context: log4j.appender.file.File=C:/java/apache-tomcat-5.5.23/webapps/xwiki/xwiki.log 3. The default security config don't let an application write to its own files, so I had to add to Tomcat calatina.polity grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "c:/java/apache-tomcat-5.5.23/webapps/xwiki/-", "read,write,delete"; }; And them when I start XWiki I get the same error I get from my hosting provider, that is: javax.servlet.ServletException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: access denied (java.io.FilePermission \WEB-INF\xwiki.cfg read) Note that you could have used System Properties in the policy file, such as: grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "${catalina.home}/webapps/xwiki/-", "read,write,delete"; }; And you could have specified a file path completely outside the context tree, which would be better from a security standpoint. Then I though: Why not adding a permission to "/WEB-INF/xwiki.cfg" so the (buggy) XWiki configuration file access code works as it would without a Security Manager? The changes to catalina.policy become: grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "${catalina.home}/webapps/xwiki/-", "read,write,delete"; permission java.io.FilePermission "/WEB-INF/xwiki.cfg", "read"; }; And the result is: javax.servlet.ServletException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3001 in 3: Cannot load store class com.xpn.xwiki.store.XWikiHibernateStore Wrapped Exception: access denied (java.io.FilePermission \WEB-INF\hibernate.cfg.xml read) Hey, XWiki reads the Hibernate configuration file the same way it reads it's own configuration file... I guess it shouldn't, but let's apply the same workaround: permission java.io.FilePermission "/WEB-INF/hibernate.cfg.xml", "read"; And then I get: com.xpn.xwiki.XWikiException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3202 in 3: Exception while reading document XWiki.XWikiPreferences Wrapped Exception: Could not create a DBCP pool com.xpn.xwiki.XWiki.getMainXWiki(XWiki.java:291) com.xpn.xwiki.XWiki.getXWiki(XWiki.java:383) com.xpn.xwiki.web.XWikiAction.execute(XWikiAction.java:96) My DBCP Pool config should be ok because the same local XWiki instance runs fine without a security manager. Probably I need something else (that is, not a java.io.FilePermission) to reach the local MySQL database. Hum, who knows using an embebed HSQLDB would be a workaround.... Digging into Tomcat logs, I found: java.net.SocketException: java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:3306 connect,resolve) at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:151) at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:280) at com.mysql.jdbc.Connection.createNewIO(Connection.java:1765) at com.mysql.jdbc.Connection.<init>(Connection.java:430) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:268) Which leads to a new permission: permission java.net.SocketPermission "127.0.0.1:3306", "connect, resolve"; And now to a different exception: com.xpn.xwiki.XWikiException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3202 in 3: Exception while reading document XWiki.XWikiPreferences Wrapped Exception: net.sf.ehcache.CacheException: Cannot configure CacheManager: jar:file:/C:/java/apache-tomcat-5.5.23/webapps/xwiki/WEB-INF/lib/xwiki.jar!/ehcache.xml:12: Could not set attribute "path". com.xpn.xwiki.XWiki.getMainXWiki(XWiki.java:291) com.xpn.xwiki.XWiki.getXWiki(XWiki.java:383) com.xpn.xwiki.web.XWikiAction.execute(XWikiAction.java:96) Another configuration file to migrate to WEB-INF/classes. Changed it so ehcache never uses disk: <ehcache> <!-- <diskStore path="java.io.tmpdir"/> --> <defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" <!-- diskPersistent="true" --> diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> </ehcache> And I got stuck to a reflection error inside Struts: javax.servlet.ServletException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3202 in 3: Exception while reading document XWiki.XWikiPreferences Wrapped Exception: access denied (java.lang.reflect.ReflectPermission suppressAccessChecks) org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:535) Well, I know a number of Struts applications that run in shared hosting plans. There should be a way out of this. But as I was already messing with catalina.polocy, I added: permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; And now finally XWiki starts fine. But when trying to create a new page: com.xpn.xwiki.XWikiException: Error number 3201 in 3: Exception while saving document Main.Teste do SandBox Wrapped Exception: Error number 3211 in 3: Exception while updating archive Main.Teste do SandBox Wrapped Exception: access denied (java.util.PropertyPermission user.name read) And here we go, more messing with catalina.policy: permission java.util.PropertyPermission "user.name", "read"; No I can create new pages inside the Wiki, and add Comments and files to the page. Looks like I found all it takes to run XWiki inside a Security Manager. Here's the final form of my aditions to catalina.policy: grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "${catalina.home}/webapps/xwiki/-", "read,write,delete"; permission java.io.FilePermission "/WEB-INF/xwiki.cfg", "read"; permission java.io.FilePermission "/WEB-INF/hibernate.cfg.xml", "read"; permission java.net.SocketPermission "127.0.0.1:3306", "connect, resolve"; permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; permission java.util.PropertyPermission "user.name", "read"; }; And dont' forget changes to lig4j.properties and ehcache.xml which had to be moved from WEB-INF/lib/xwiki.jar to WEB-INF/classes. The problem is, I'm almost sure my ISP will refuse to add [java.lang.reflect.ReflectPermission "suppressAccessChecks"]. Others should be fine. So I'd be very grateful if someone helps me making Struts not need this permission. []s, Fernando Lozano
Hi, This is great. Thanks for doing this. I don't understand why one must move log4j and ehcache configuration out of the jar. Anyway, log4j should be moved to WEB-INF/classes, for easy access to the logging configuration. I also don't understand why is the access restricted to WEB/INF... The configuration is usually there, right? Anyway, I think the latest version of the code does not need this, but I'm not sure. By the way, what version of XWiki are you using? Regarding log4j.appender.file.File, this is what should be done anyway, as I don't like having the log file right in the application directory. It should be in a directory for logs, either the one in tomcat, or the one for all system logs (on linux it's /var/log/). I always change the location to /tmp/xwiki.log. I don't know how can log4j be configured to use one of these directories regardless of the platform, since c:\ and tomcat-5.5.23 are very unstable properties to place in there. Regarding the username property, I think this is not needed, anyway, as we're using a default username now. I'll have to check. Regarding the reflection permissions, I think actually Velocity is responsible for this. I found http://issues.apache.org/jira/browse/VELTOOLS-66 stating that it cannot access classes defined in the container, only those included in JARs. We should find all the classes that are used directly and make a wrapper for them, as the wrapper would work fine, even if it does not do anything other than forwarding the call. On 7/30/07, Fernando Lozano <fernando.lozano@neki.com.br> wrote:
Hi there,
Working to solve my SecurityExceptions running on a shared hosting, I tried to create a similar environment on my local Tomcat. The problem is not solved, but what I got so far may be useful for some XWiki users.
After running "server.bat -security" I started getting errors related to Log4J already described by other threads on the mailing list archive, which I solved this way:
1. Take the log4j.properties from WEB-INF/lib/xwiki.jar and put it as WEB-INF/classes. The Servlet API specs state that WEB-INF/classes comes in the web app classpath before jar files placed in WEB-INF/lib.
2. Changed so the log file gets an absolute path under the web app context:
log4j.appender.file.File=C:/java/apache-tomcat-5.5.23/webapps/xwiki/xwiki.log
3. The default security config don't let an application write to its own files, so I had to add to Tomcat calatina.polity
grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "c:/java/apache-tomcat-5.5.23/webapps/xwiki/-", "read,write,delete"; };
And them when I start XWiki I get the same error I get from my hosting provider, that is:
javax.servlet.ServletException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: access denied (java.io.FilePermission \WEB-INF\xwiki.cfg read)
Note that you could have used System Properties in the policy file, such as:
grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "${catalina.home}/webapps/xwiki/-", "read,write,delete"; };
And you could have specified a file path completely outside the context tree, which would be better from a security standpoint.
Then I though: Why not adding a permission to "/WEB-INF/xwiki.cfg" so the (buggy) XWiki configuration file access code works as it would without a Security Manager?
The changes to catalina.policy become:
grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "${catalina.home}/webapps/xwiki/-", "read,write,delete"; permission java.io.FilePermission "/WEB-INF/xwiki.cfg", "read"; };
And the result is:
javax.servlet.ServletException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3001 in 3: Cannot load store class com.xpn.xwiki.store.XWikiHibernateStore Wrapped Exception: access denied (java.io.FilePermission \WEB-INF\hibernate.cfg.xml read)
Hey, XWiki reads the Hibernate configuration file the same way it reads it's own configuration file... I guess it shouldn't, but let's apply the same workaround:
permission java.io.FilePermission "/WEB-INF/hibernate.cfg.xml", "read";
And then I get:
com.xpn.xwiki.XWikiException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3202 in 3: Exception while reading document XWiki.XWikiPreferences Wrapped Exception: Could not create a DBCP pool com.xpn.xwiki.XWiki.getMainXWiki(XWiki.java:291) com.xpn.xwiki.XWiki.getXWiki(XWiki.java:383) com.xpn.xwiki.web.XWikiAction.execute(XWikiAction.java:96)
My DBCP Pool config should be ok because the same local XWiki instance runs fine without a security manager. Probably I need something else (that is, not a java.io.FilePermission) to reach the local MySQL database. Hum, who knows using an embebed HSQLDB would be a workaround....
Digging into Tomcat logs, I found:
java.net.SocketException: java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:3306 connect,resolve) at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:151) at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:280) at com.mysql.jdbc.Connection.createNewIO(Connection.java:1765) at com.mysql.jdbc.Connection.<init>(Connection.java:430) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:268)
Which leads to a new permission:
permission java.net.SocketPermission "127.0.0.1:3306", "connect, resolve";
And now to a different exception:
com.xpn.xwiki.XWikiException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3202 in 3: Exception while reading document XWiki.XWikiPreferences Wrapped Exception: net.sf.ehcache.CacheException: Cannot configure CacheManager: jar:file:/C:/java/apache-tomcat-5.5.23/webapps/xwiki/WEB-INF/lib/xwiki.jar!/ehcache.xml:12: Could not set attribute "path". com.xpn.xwiki.XWiki.getMainXWiki(XWiki.java:291) com.xpn.xwiki.XWiki.getXWiki(XWiki.java:383) com.xpn.xwiki.web.XWikiAction.execute(XWikiAction.java:96)
Another configuration file to migrate to WEB-INF/classes. Changed it so ehcache never uses disk:
<ehcache> <!-- <diskStore path="java.io.tmpdir"/> --> <defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" <!-- diskPersistent="true" --> diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> </ehcache>
And I got stuck to a reflection error inside Struts:
javax.servlet.ServletException: Error number 3 in 0: Could not initialize main XWiki context Wrapped Exception: Error number 3202 in 3: Exception while reading document XWiki.XWikiPreferences Wrapped Exception: access denied (java.lang.reflect.ReflectPermission suppressAccessChecks) org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:535)
Well, I know a number of Struts applications that run in shared hosting plans. There should be a way out of this.
But as I was already messing with catalina.polocy, I added:
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
And now finally XWiki starts fine.
But when trying to create a new page:
com.xpn.xwiki.XWikiException: Error number 3201 in 3: Exception while saving document Main.Teste do SandBox Wrapped Exception: Error number 3211 in 3: Exception while updating archive Main.Teste do SandBox Wrapped Exception: access denied (java.util.PropertyPermission user.name read)
And here we go, more messing with catalina.policy:
permission java.util.PropertyPermission "user.name", "read";
No I can create new pages inside the Wiki, and add Comments and files to the page. Looks like I found all it takes to run XWiki inside a Security Manager. Here's the final form of my aditions to catalina.policy:
grant codeBase "file:${catalina.home}/webapps/xwiki/-" { permission java.io.FilePermission "${catalina.home}/webapps/xwiki/-", "read,write,delete"; permission java.io.FilePermission "/WEB-INF/xwiki.cfg", "read"; permission java.io.FilePermission "/WEB-INF/hibernate.cfg.xml", "read"; permission java.net.SocketPermission "127.0.0.1:3306", "connect, resolve"; permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; permission java.util.PropertyPermission "user.name", "read"; };
And dont' forget changes to lig4j.properties and ehcache.xml which had to be moved from WEB-INF/lib/xwiki.jar to WEB-INF/classes.
The problem is, I'm almost sure my ISP will refuse to add [java.lang.reflect.ReflectPermission "suppressAccessChecks"]. Others should be fine. So I'd be very grateful if someone helps me making Struts not need this permission.
[]s, Fernando Lozano
Sergiu -- http://purl.org/net/sergiu
Hi Sergiu,
I don't understand why one must move log4j and ehcache configuration out of the jar. Anyway, log4j should be moved to WEB-INF/classes, for easy access to the logging configuration.
This is simply a packaging preference. You could edit log4j.properties inside xwiki.jar (any modern Zip tool such as 7-Zip will do this) but I prefer to have all configuration files I may want to change outside jars.
I also don't understand why is the access restricted to WEB/INF... The configuration is usually there, right? Anyway, I think the latest version of the code does not need this, but I'm not sure. By the way, what version of XWiki are you using?
I'm using 1.0. The access restriction for /WEB-INF solve a bug in the way XWiki looks for its own configuration files. The way it looks for, you get a SecurityException whenever the Web Container is running inside a SecurityManagerm such as when Tomcat is started with the "-security" flag. See my other post, where I provide a JSP page with a snipset of XWiki code and show you how it could be changed to work correctly with a security manager.
Regarding log4j.appender.file.File, this is what should be done anyway, as I don't like having the log file right in the application directory. It should be in a directory for logs, either the one in tomcat, or the one for all system logs (on linux it's /var/log/). I always change the location to /tmp/xwiki.log. I don't know how can log4j be configured to use one of these directories regardless of the platform, since c:\ and tomcat-5.5.23 are very unstable properties to place in there.
I tried to use system properties to point to the log file location, but this didn't work. So far I'm stuck with a system-dependent absolute pathname. :-(
Regarding the reflection permissions, I think actually Velocity is responsible for this. I found http://issues.apache.org/jira/browse/VELTOOLS-66 stating that it cannot access classes defined in the container, only those included in JARs. We should find all the classes that are used directly and make a wrapper for them, as the wrapper would work fine, even if it does not do anything other than forwarding the call.
See: http://struts.apache.org/2.0.6/docs/sunone-70.html http://forums.theplanet.com/lofiversion/index.php/charts/t35104.html http://garethevans.blogspot.com/2005/06/fun-with-tomcat-and-its-default.html Those state that Struts itself needs reflection permissions. And it looks like other popular frameworks like Hibernate and Spring also need it. Now my ISP state it cannot provide such a permission, because Java SE docs (See jdk-1_5_0-doc/docs/guide/security/permissions.html) states that: "|suppressAccessChecks: |/Extreme caution should be taken before granting this permission to code/ ... This is dangerous in that information (possibly confidential) and methods normally unavailable would be accessible to malicious code." To be honest, I don't think this would be a problem as most popular framework rely on it. As far as I know Java and other web environments, every installation of mod_php and mod_perl under Apache or IIS would be subject to the same risks. But I need arguments to convince my ISP, any help would be apreciated. My ISP also uses http://jira.xwiki.org/jira/browse/XWIKI-348 and http://www.xwiki.org/xwiki/bin/view/AdminGuide/InstallationTomcat as "proof" that XWiki can't run on shared hosting. :-( Maybe some XWiki developer can fix those docs so they don't state anymore that shared hosting is impossible, but instead that it just requires proper configuration, like any application would need when the Security Manager is on. []s, Fernando Lozano
Hi Sergiu, Just clarifing my previous message:
I also don't understand why is the access restricted to WEB/INF... The configuration is usually there, right? Anyway, I think the latest version of the code does not need this, but I'm not sure. By the way, what version of XWiki are you using?
I'm using 1.0. The access restriction for /WEB-INF solve a bug in the way XWiki looks for its own configuration files. The way it looks for, you get a SecurityException whenever the Web Container is running inside a SecurityManagerm such as when Tomcat is started with the "-security" flag. See my other post, where I provide a JSP page with a snipset of XWiki code and show you how it could be changed to work correctly with a security manager.
The access permissions for /WEB-INF don't "solve" the bug, but workround it. The code I provided in the other message is a real solution for the bug. Note that "/WEB-INF" is an absolute filesystem path that shouldn't exist in any real system. The problem is, the Java Security Manager throws a Security Exception *before* trying to access or cheching permissions on the real file system, so XWiki never gets a change to find out the path doesn't exist and it should try a web context relative path. My code snipet tries the web context relative path before trying an absolute filesystem path, so it won't get a SecurityException. []s, Fernando Lozano
Regarding log4j.appender.file.File, this is what should be done anyway, as I don't like having the log file right in the application directory. It should be in a directory for logs, either the one in tomcat, or the one for all system logs (on linux it's /var/log/). I always change the location to /tmp/xwiki.log. I don't know how can log4j be configured to use one of these directories regardless of the platform, since c:\ and tomcat-5.5.23 are very unstable properties to place in there.
I tried to use system properties to point to the log file location, but this didn't work. So far I'm stuck with a system-dependent absolute pathname. :-(
Regarding the reflection permissions, I think actually Velocity is responsible for this. I found http://issues.apache.org/jira/browse/VELTOOLS-66 stating that it cannot access classes defined in the container, only those included in JARs. We should find all the classes that are used directly and make a wrapper for them, as the wrapper would work fine, even if it does not do anything other than forwarding the call.
See:
http://struts.apache.org/2.0.6/docs/sunone-70.html http://forums.theplanet.com/lofiversion/index.php/charts/t35104.html http://garethevans.blogspot.com/2005/06/fun-with-tomcat-and-its-default.html
Those state that Struts itself needs reflection permissions. And it looks like other popular frameworks like Hibernate and Spring also need it.
Now my ISP state it cannot provide such a permission, because Java SE docs (See jdk-1_5_0-doc/docs/guide/security/permissions.html) states that:
"|suppressAccessChecks: |/Extreme caution should be taken before granting this permission to code/ ... This is dangerous in that information (possibly confidential) and methods normally unavailable would be accessible to malicious code."
To be honest, I don't think this would be a problem as most popular framework rely on it. As far as I know Java and other web environments, every installation of mod_php and mod_perl under Apache or IIS would be subject to the same risks. But I need arguments to convince my ISP, any help would be apreciated.
My ISP also uses http://jira.xwiki.org/jira/browse/XWIKI-348 and http://www.xwiki.org/xwiki/bin/view/AdminGuide/InstallationTomcat as "proof" that XWiki can't run on shared hosting. :-( Maybe some XWiki developer can fix those docs so they don't state anymore that shared hosting is impossible, but instead that it just requires proper configuration, like any application would need when the Security Manager is on.
[]s, Fernando Lozano
participants (2)
-
Fernando Lozano -
Sergiu Dumitriu