带有安全管理器的 Tomcat 9.0 在 Windows 上报告访问被拒绝

Posted

技术标签:

【中文标题】带有安全管理器的 Tomcat 9.0 在 Windows 上报告访问被拒绝【英文标题】:Tomcat 9.0 with security manager reports access denied on Windows 【发布时间】:2019-06-12 17:17:03 【问题描述】:

我在 Windows 10 上启动了 Tomcat 9.0:

-Djava.security.manager
-Djava.security.policy==C:\Program Files\Apache Software Foundation\Tomcat 9.0\conf\catalina.policy
-Djava.security.debug=access,failure

使用 org.apache.coyote.http11.Http11Nio2Protocol 类型的连接器并启用 ssl。

另外,我只有(我自己的)ROOT 应用程序正在运行,没有别的。

在我定义的 catalina.policy 中(用于第一次测试):

grant codeBase "file:$catalina.base/webapps/ROOT/-" 
  permission java.security.AllPermission;
;

当我现在检查 tomcat9-stderr.log 时,我发现了以下条目:

access: access denied ("java.util.PropertyPermission" "org.apache.juli.logging.UserDataHelper.CONFIG" "read")

java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Unknown Source)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPropertyAccess(Unknown Source)
at java.lang.System.getProperty(Unknown Source)
at org.apache.tomcat.util.log.UserDataHelper.<init>(UserDataHelper.java:57)
at org.apache.coyote.AbstractProcessor.<init>(AbstractProcessor.java:90)
at org.apache.coyote.http2.StreamProcessor.<init>(StreamProcessor.java:56)
at org.apache.coyote.http2.Http2UpgradeHandler.processStreamOnContainerThread(Http2UpgradeHandler.java:261)
at org.apache.coyote.http2.Http2UpgradeHandler.headersEnd(Http2UpgradeHandler.java:1356)
at org.apache.coyote.http2.Http2AsyncUpgradeHandler.headersEnd(Http2AsyncUpgradeHandler.java:37)
at org.apache.coyote.http2.Http2Parser.onHeadersComplete(Http2Parser.java:583)
at org.apache.coyote.http2.Http2Parser.readHeadersFrame(Http2Parser.java:272)
at org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.completed(Http2AsyncParser.java:167)
at org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.completed(Http2AsyncParser.java:85)
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$VectoredIOCompletionHandler.completed(Nio2Endpoint.java:1148)
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$VectoredIOCompletionHandler.completed(Nio2Endpoint.java:1117)
at org.apache.tomcat.util.net.SecureNio2Channel$2.completed(SecureNio2Channel.java:1047)
at org.apache.tomcat.util.net.SecureNio2Channel$2.completed(SecureNio2Channel.java:992)
at sun.nio.ch.Invoker.invokeUnchecked(Unknown Source)
at sun.nio.ch.Invoker$2.run(Unknown Source)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

access: domain that failed ProtectionDomain  null
 null
 <no principals>
 null

以及其中两个:

access: access denied ("java.lang.RuntimePermission" "accessClassInPackage.org.apache.tomcat.util.net")
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Unknown Source)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPackageAccess(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.apache.tomcat.util.net.SecureNio2Channel.flush(SecureNio2Channel.java:196)
at org.apache.tomcat.util.net.SecureNio2Channel.close(SecureNio2Channel.java:585)
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper.close(Nio2Endpoint.java:932)
at org.apache.coyote.http2.Http2UpgradeHandler.close(Http2UpgradeHandler.java:1010)
at org.apache.coyote.http2.Http2UpgradeHandler.upgradeDispatch(Http2UpgradeHandler.java:359)
at org.apache.coyote.http2.Http2AsyncUpgradeHandler.upgradeDispatch(Http2AsyncUpgradeHandler.java:37)
at org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.failed(Http2AsyncParser.java:240)
at org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.failed(Http2AsyncParser.java:85)
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$VectoredIOCompletionHandler.failed(Nio2Endpoint.java:1184)
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$VectoredIOCompletionHandler.failed(Nio2Endpoint.java:1117)
at org.apache.tomcat.util.net.SecureNio2Channel$2.failed(SecureNio2Channel.java:1055)
at org.apache.tomcat.util.net.SecureNio2Channel$2.completed(SecureNio2Channel.java:1049)
at org.apache.tomcat.util.net.SecureNio2Channel$2.completed(SecureNio2Channel.java:992)
at sun.nio.ch.Invoker.invokeUnchecked(Unknown Source)
at sun.nio.ch.Invoker$2.run(Unknown Source)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

access: domain that failed ProtectionDomain  null
null
<no principals>
null

所以我尝试添加

permission java.util.PropertyPermission "org.apache.juli.logging.UserDataHelper.CONFIG", "read";
permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.util.net";

在 catalina.policy 文件中的不同位置(对于 webapps/ROOT/、CATALINA 代码权限、WEB 应用程序权限)。

但所有这些都不会使两个访问被拒绝的消失。

所以我的问题是如何清理这两个拒绝访问?

更新 1

对于 accessClassInPackage.org.apache.tomcat.util.net 我想知道为什么会这样,因为 org.apache.tomcat.util.net 位于 Tomcat/lib/tomcat-coyote.jar 中,获得了以下权限:

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

更新 2

改变了

-Djava.security.policy=

-Djava.security.policy==

这让

access denied ("java.lang.RuntimePermission" "accessClassInPackage.org.apache.tomcat.util.net")

消失 - 这样只有 juli 日志记录仍然被拒绝。

更新 3

现在我得到了一个额外的异常:

access: access denied ("java.net.SocketPermission" "127.0.0.1:15484" "accept,resolve")
11-Feb-2019 14:46:43.895 SCHWERWIEGEND [https-openssl-nio2-443-exec-7] org.apache.tomcat.util.net.Nio2Endpoint$Nio2Acceptor.failed Socket accept failed
 java.security.AccessControlException: access denied ("java.net.SocketPermission" "127.0.0.1:15478" "accept,resolve")
    at java.security.AccessControlContext.checkPermission(Unknown Source)
    at java.security.AccessController.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkAccept(Unknown Source)
    at sun.nio.ch.WindowsAsynchronousServerSocketChannelImpl$AcceptTask$1.run(Unknown Source)
    at sun.nio.ch.WindowsAsynchronousServerSocketChannelImpl$AcceptTask$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.nio.ch.WindowsAsynchronousServerSocketChannelImpl$AcceptTask.finishAccept(Unknown Source)
    at sun.nio.ch.WindowsAsynchronousServerSocketChannelImpl$AcceptTask.completed(Unknown Source)
    at sun.nio.ch.Iocp$EventHandlerTask.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    at sun.misc.InnocuousThread.run(Unknown Source)

这很奇怪,因为

org.apache.tomcat.util.net.Nio2Endpoint

属于

tomcat/lib/tomcat-coyote.jar

应该没有限制

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

更奇怪的是这个后面是:

access: access allowed ("java.net.SocketPermission" "127.0.0.1:15485" "accept,resolve")

这让整个事情变得更加神秘。

顺便说一句。 UserDataHelper 似乎也是如此,除了访问被拒绝之外,还有允许访问。

【问题讨论】:

【参考方案1】:

在我们的应用程序中发现了类似的问题。 catalina 策略中的安全设置对代码没有任何影响;对我们来说更重要的是它是间歇性的。

我们对 catalina 调试模式进行了大量研究(这有助于通过 catalina 线程进行单步调试)。

我们通过将 server.xml 中的 Connector 更改为 org.apache.coyote.http11.Http11NioProtocol(NIO 的第一个版本,而不是 NIO2)解决了这个问题。

我们不知何故觉得 NIO2 在幕后创建多个异步线程时弄乱了安全策略。

More on NIO2 features here

【讨论】:

一些其他版本的 Tomcat 报告并修复了类似问题。 Tomcat 版本 6.0.29 -- bz.apache.org/bugzilla/show_bug.cgi?id=49209。 Tomcat 版本 8.0.47 – NIO 解决的问题 -- cca.gess.sg/docs/changelog.html & bz.apache.org/bugzilla/show_bug.cgi?id=61437

以上是关于带有安全管理器的 Tomcat 9.0 在 Windows 上报告访问被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 9.0 7 的两种开机启动方式与web页面管理

使用启用了安全管理器的 Tomcat 时,在类路径中找不到属性文件

在没有 Tomcat 管理器的情况下从 jenkins 自动部署战争文件

9.0对于java集合的迭代器的底层分析

记一次对Tomcat网页靶机提权实录

完全禁用任务管理器的 Win32 API 是啥? [关闭]