Java安全管理器SecurityManager入门介绍(2)

// Finally, install a security manager if requested String s = System.getProperty("java.security.manager"); if (s != null) { SecurityManager sm = null; if ("".equals(s) || "default".equals(s)) { sm = new java.lang.SecurityManager(); } else { try { sm = (SecurityManager)loader.loadClass(s).newInstance(); } catch (IllegalAccessException e) { } catch (InstantiationException e) { } catch (ClassNotFoundException e) { } catch (ClassCastException e) { } } if (sm != null) { System.setSecurityManager(sm); } else { throw new InternalError( "Could not create SecurityManager: " + s); } }

  可以发现将会创建一个默认的SecurityManager;

五、配置文件简单解释 5.1 配置基本原则

  在启用安全管理器的时候,配置遵循以下基本原则:

没有配置的权限表示没有。

只能配置有什么权限,不能配置禁止做什么。

同一种权限可多次配置,取并集。

统一资源的多种权限可用逗号分割。

5.2 默认配置文件解释

  第一部分授权:

grant codeBase "file:${{java.ext.dirs}}/*" { permission java.security.AllPermission; };

  授权基于路径在"file:${{java.ext.dirs}}/*"的class和jar包,所有权限。

  第二部分授权:

grant { permission java.lang.RuntimePermission "stopThread"; …… }

  这是细粒度的授权,对某些资源的操作进行授权。具体不再解释,可以查看javadoc。如RuntimePermission的可授权操作经查看javadoc如下:

权限目标名称权限所允许的操作允许此权限所带来的风险
createClassLoader   创建类加载器   授予该权限极其危险。能够实例化自己的类加载器的恶意应用程序可能会在系统中装载自己的恶意类。这些新加载的类可能被类加载器置于任意保护域中,从而自动将该域的权限授予这些类。  
getClassLoader   类加载器的获取(即调用类的类加载器)   这将授予攻击者得到具体类的加载器的权限。这很危险,由于攻击者能够访问类的类加载器,所以攻击者能够加载其他可用于该类加载器的类。通常攻击者不具备这些类的访问权限。  
setContextClassLoader   线程使用的上下文类加载器的设置   在需要查找可能不存在于系统类加载器中的资源时,系统代码和扩展部分会使用上下文类加载器。授予 setContextClassLoader 权限将允许代码改变特定线程(包括系统线程)使用的上下文类加载器。  
enableContextClassLoaderOverride   线程上下文类加载器方法的子类实现   在需要查找可能不存在于系统类加载器中的资源时,系统代码和扩展部分会使用上下文类加载器。授予 enableContextClassLoaderOverride 权限将允许线程的子类重写某些方法,这些方法用于得到或设置特定线程的上下文类加载器。  
setSecurityManager   设置安全管理器(可能会替换现有的)   安全管理器是允许应用程序实现安全策略的类。授予 setSecurityManager 权限将通过安装一个不同的、可能限制更少的安全管理器,来允许代码改变所用的安全管理器,因此可跳过原有安全管理器所强制执行的某些检查。  
createSecurityManager   创建新的安全管理器   授予代码对受保护的、敏感方法的访问权,可能会泄露有关其他类或执行堆栈的信息。  
getenv.{variable name}   读取指定环境变量的值   此权限允许代码读取特定环境变量的值或确定它是否存在。如果该变量含有机密数据,则这项授权是很危险的。  
exitVM.{exit status}   暂停带有指定退出状态的 Java 虚拟机   此权限允许攻击者通过自动强制暂停虚拟机来发起一次拒绝服务攻击。注意:自动为那些从应用程序类路径加载的全部代码授予 "exitVM.*" 权限,从而使这些应用程序能够自行中止。此外,"exitVM" 权限等于 "exitVM.*"。  
shutdownHooks   虚拟机关闭钩子 (hook) 的注册与取消   此权限允许攻击者注册一个妨碍虚拟机正常关闭的恶意关闭钩子 (hook)。  
setFactory   设置由 ServerSocket 或 Socket 使用的套接字工厂,或 URL 使用的流处理程序工厂   此权限允许代码设置套接字、服务器套接字、流处理程序或 RMI 套接字工厂的实际实现。攻击者可能设置错误的实现,从而破坏数据流。  
setIO   System.out、System.in 和 System.err 的设置   此权限允许改变标准系统流的值。攻击者可以改变 System.in 来监视和窃取用户输入,或将 System.err 设置为 "null" OutputStream,从而隐藏发送到 System.err 的所有错误信息。  
modifyThread   修改线程,例如通过调用线程的 interrupt、stop、suspend、resume、setDaemon、setPriority、setName 和 setUncaughtExceptionHandler 方法   此权限允许攻击者修改系统中任意线程的行为。  
stopThread   通过调用线程的 stop 方法停止线程   如果系统已授予代码访问该线程的权限,则此权限允许代码停止系统中的任何线程。此权限会造成一定的危险,因为该代码可能通过中止现有的线程来破坏系统。  
modifyThreadGroup   修改线程组,例如通过调用 ThreadGroup 的 destroy、getParent、resume、setDaemon、setMaxPriority、stop 和 suspend 方法   此权限允许攻击者创建线程组并设置它们的运行优先级。  
getProtectionDomain   获取类的 ProtectionDomain   此权限允许代码获得特定代码源的安全策略信息。虽然获得安全策略信息并不足以危及系统安全,但这确实会给攻击者提供了能够更好地定位攻击目标的其他信息,例如本地文件名称等。  
getFileSystemAttributes   获取文件系统属性   此权限允许代码获得文件系统信息(如调用者可用的磁盘使用量或磁盘空间)。这存在潜在危险,因为它泄露了关于系统硬件配置的信息以及一些关于调用者写入文件特权的信息。  
readFileDescriptor   读取文件描述符   此权限允许代码读取与文件描述符读取相关的特定文件。如果该文件包含机密数据,则此操作非常危险。  
writeFileDescriptor   写入文件描述符   此权限允许代码写入与描述符相关的特定文件。此权限很危险,因为它可能允许恶意代码传播病毒,或者至少也会填满整个磁盘。  
loadLibrary.{库名}   动态链接指定的库   允许 applet 具有加载本机代码库的权限是危险的,因为 Java 安全架构并未设计成可以防止恶意行为,并且也无法在本机代码的级别上防止恶意行为。  
accessClassInPackage.{包名}   当类加载器调用 SecurityManager 的checkPackageAccess 方法时,通过类加载器的 loadClass 方法访问指定的包   此权限允许代码访问它们通常无法访问的那些包中的类。恶意代码可能利用这些类帮助它们实现破坏系统安全的企图。  
defineClassInPackage.{包名}   当类加载器调用 SecurityManager 的 checkPackageDefinition 方法时,通过类加载器的 defineClass 方法定义指定的包中的类。   此权限允许代码在特定包中定义类。这样做很危险,因为具有此权限的恶意代码可能在受信任的包中定义恶意类,比如 java.security 或 java.lang。  
accessDeclaredMembers   访问类的已声明成员   此权限允许代码查询类的公共、受保护、默认(包)访问和私有的字段和/或方法。尽管代码可以访问私有和受保护字段和方法名称,但它不能访问私有/受保护字段数据并且不能调用任何私有方法。此外,恶意代码可能使用该信息来更好地定位攻击目标。而且,它可以调用类中的任意公共方法和/或访问公共字段。如果代码不能用这些方法和字段将对象强制转换为类/接口,那么它通常无法调用这些方法和/或访问该字段,而这可能很危险。  
queuePrintJob   打印作业请求的开始   这可能向打印机输出敏感信息,或者只是浪费纸张。  
getStackTrace   获取另一个线程的堆栈追踪信息。   此权限允许获取另一个线程的堆栈追踪信息。此操作可能允许执行恶意代码监视线程并发现应用程序中的弱点。  
setDefaultUncaughtExceptionHandler   在线程由于未捕获的异常而突然终止时,设置将要使用的默认处理程序   此权限允许攻击者注册恶意的未捕获异常处理程序,可能会妨碍线程的终止  
Preferences   表示得到 java.util.prefs.Preferences 的访问权所需的权限。java.util.prefs.Preferences 实现了用户或系统的根,这反过来又允许获取或更新 Preferences 持久内部存储中的操作。   如果运行此代码的用户具有足够的读/写内部存储的 OS 特权,则此权限就允许用户读/写优先级内部存储。实际的内部存储可能位于传统的文件系统目录中或注册表中,这取决于平台 OS。  
5.3 可配置项详解

  当批量配置的时候,有三种模式:

directory/ 表示directory目录下的所有.class文件,不包括.jar文件

directory/* 表示directory目录下的所有的.class及.jar文件

directory/- 表示directory目录下的所有的.class及.jar文件,包括子目录

  可以通过${}来引用系统属性,如:

"file:${{java.ext.dirs}}/*"

六、问题解决

  当出现关于安全管理的报错的时候,基本有两种方式来解决。

6.1 取消安全管理器

  一般情况下都是无意启动安全管理器,所以这时候只需要把安全管理器进行关闭,去掉启动参数即可。

6.2 增加相应权限

  若因为没有权限报错,则报错信息中会有请求的权限和请求什么权限,如下:

Exception in thread "main" java.security.AccessControlException: access denied (java.io.FilePermission E:\pack\a\a.txt write)

  上面例子,请求资源E:\pack\a\a.txt,的FilePermission的写权限没有,因此被拒绝。

  也可以开放所有权限:

grant { permission java.security.AllPermission; };

  这一篇简单介绍Java的安全管理器,后面会对其进行详细介绍,不过了解这些对一般应用已经足够了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/084bb0c357acee9dd1b5358ca7880ee2.html