java基础系列--SecurityManager入门(转)
转载作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/yiwangzhibujian/p/6207212.html
一、文章的目的
这是一篇对Java安全管理器入门的文章,目的是简单了解什么是SecurityManager,对管理器进行简单配置,解决简单问题。
比如在阅读源码的时候,发现这样的代码,想了解是做什么的:
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkWrite(name);
}
亦或者在本机运行正常,在服务器运行报错,想解决问题:
Exception in thread "main" java.security.AccessControlException: access denied (java.lang.RuntimePermission createSecurityManager)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)
at java.security.AccessController.checkPermission(AccessController.java:549)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.<init>(SecurityManager.java:282)
at xia.study._01Thread.ThreadTest.creatThread1(ThreadTest.java:18)
at xia.study._01Thread.ThreadTest.main(ThreadTest.java:13)
这时候具备一些SecurityManager的基础知识还是有必要的。
二、SecurityManager应用场景
当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。
三、管理器配置文件
3.1 默认配置文件
默认的安全管理器配置文件是 $JAVA_HOME/jre/lib/security/java.policy,即当未指定配置文件时,将会使用该配置。内容如下:
// Standard extensions get all permissions by default grant codeBase "file:${{java.ext.dirs}}/*" {
permission java.security.AllPermission;
}; // default permissions granted to all domains grant {
// Allows any thread to stop itself using the java.lang.Thread.stop()
// method that takes no argument.
// Note that this permission is granted by default only to remain
// backwards compatible.
// It is strongly recommended that you either remove this permission
// from this policy file or further restrict it to code sources
// that you specify, because Thread.stop() is potentially unsafe.
// See the API specification of java.lang.Thread.stop() for more
// information.
permission java.lang.RuntimePermission "stopThread"; // allows anyone to listen on un-privileged ports
permission java.net.SocketPermission "localhost:1024-", "listen"; // "standard" properies that can be read by anyone permission java.util.PropertyPermission "java.version", "read";
permission java.util.PropertyPermission "java.vendor", "read";
permission java.util.PropertyPermission "java.vendor.url", "read";
permission java.util.PropertyPermission "java.class.version", "read";
permission java.util.PropertyPermission "os.name", "read";
permission java.util.PropertyPermission "os.version", "read";
permission java.util.PropertyPermission "os.arch", "read";
permission java.util.PropertyPermission "file.separator", "read";
permission java.util.PropertyPermission "path.separator", "read";
permission java.util.PropertyPermission "line.separator", "read"; permission java.util.PropertyPermission "java.specification.version", "read";
permission java.util.PropertyPermission "java.specification.vendor", "read";
permission java.util.PropertyPermission "java.specification.name", "read"; permission java.util.PropertyPermission "java.vm.specification.version", "read";
permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
permission java.util.PropertyPermission "java.vm.specification.name", "read";
permission java.util.PropertyPermission "java.vm.version", "read";
permission java.util.PropertyPermission "java.vm.vendor", "read";
permission java.util.PropertyPermission "java.vm.name", "read";
};
3.2 配置文件详解
详解见第五部分,此处知道有这个配置文件即可。
四、启动安全管理器
启动安全管理有两种方式,建议使用启动参数方式。
4.1 启动参数方式
启动程序的时候通过附加参数启动安全管理器:
-Djava.security.manager
若要同时指定配置文件的位置那么示例如下:
-Djava.security.manager -Djava.security.policy="E:/java.policy"
4.2 编码方式启动
也可以通过编码方式启动,不过不建议:
System.setSecurityManager(new SecurityManager());
通过参数启动,本质上也是通过编码启动,不过参数启动使用灵活,项目启动源码如下(sun.misc.Launcher):
// 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基础系列--SecurityManager入门(转)的更多相关文章
- Java基础系列--HashMap(JDK1.8)
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10022092.html Java基础系列-HashMap 1.8 概述 HashMap是 ...
- 夯实Java基础系列1:Java面向对象三大特性(基础篇)
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 [https://github.com/h2pl/Java-Tutorial](https: ...
- 夯实Java基础系列3:一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!
目录 目录 string基础 Java String 类 创建字符串 StringDemo.java 文件代码: String基本用法 创建String对象的常用方法 String中常用的方法,用法如 ...
- 夯实Java基础系列4:一文了解final关键字的特性、使用方法,以及实现原理
目录 final使用 final变量 final修饰基本数据类型变量和引用 final类 final关键字的知识点 final关键字的最佳实践 final的用法 关于空白final final内存分配 ...
- 夯实Java基础系列5:Java文件和Java包结构
目录 Java中的包概念 包的作用 package 的目录结构 设置 CLASSPATH 系统变量 常用jar包 java软件包的类型 dt.jar rt.jar *.java文件的奥秘 *.Java ...
- 夯实Java基础系列6:一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别!
目录 抽象类介绍 为什么要用抽象类 一个抽象类小故事 一个抽象类小游戏 接口介绍 接口与类相似点: 接口与类的区别: 接口特性 抽象类和接口的区别 接口的使用: 接口最佳实践:设计模式中的工厂模式 接 ...
- 夯实Java基础系列7:一文读懂Java 代码块和执行顺序
目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...
- 夯实Java基础系列9:深入理解Class类和Object类
目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); register ...
- 夯实Java基础系列10:深入理解Java中的异常体系
目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调 ...
随机推荐
- WEB 小案例 -- 网上书城(二)
寒假结束了,自己的颓废时间同样结束了,早该继续写博客了,尽管我的格式以及内容由于各种原因老被卡,但必须坚持写下去!!! 上次我们对于本案例的数据库部分进行了阐述,这次主要接着上次的内容分享本案例的翻页 ...
- 解决VC6下调不出MSDN的问题!
原文:http://www.programfan.com/blog/article.asp?id=1524http://blog.programfan.com/trackback.asp?id=15 ...
- Redis相关指令文档
连接控制 QUIT 关闭连接 AUTH (仅限启用时)简单的密码验证 适合全体类型的命令 EXISTS key 判断一个键是否存在;存在返回 1;否则返回0; DEL key 删除某个key,或是一系 ...
- free 或delete后指针怎么样了
free()和delete()只是把指针所指向的内存释放掉,但是并没有把指针本身删除,也没有把指针置为NULL; #include<iostream> using namespace st ...
- Exynos4412交叉编译环境搭建
Exynos4412交叉编译环境搭建 交叉编译:在PC机(x86平台)上开发程序,在ARM板上运行,提高开发.编译速度. 环境: Tiny4412SDK1506开发板 需要软件: arm-linux- ...
- 1.17学习jquery权威指南
1.ajax方面(东西比较杂,很多相关于.net挂钩的服务器端接触没有实际操作,全部放进来,或许以后当作demo使用) ¥(“body”).load("text.txt"); ...
- 【BZOJ4816】数字表格(莫比乌斯反演)
[BZOJ4816]数字表格(莫比乌斯反演) 题面 BZOJ 求 \[\prod_{i=1}^n\prod_{j=1}^mf[gcd(i,j)]\] 题解 忽然不知道这个要怎么表示... 就写成这样吧 ...
- Bzoj4869: [Shoi2017]相逢是问候
题面 传送门 Sol 摆定理 \[ a^b\equiv \begin{cases} a^{b\%\phi(p)}~~~~~~~~~~~gcd(a,p)=1\\ a^b~~~~~~~~~~~~~~~~~ ...
- [HNOI2014]米特运输
显然知道一个节点就可以推出整棵树 然而直接乘会爆longlong 所以考虑取log 最后排序算众数即可 # include <stdio.h> # include <stdlib.h ...
- iOS9 HTTP 网络访问问题
今天升级Xcode 7.0 发现网络访问失败.输出错误信息 The resource could not be loaded because the App Transport Security po ...