您现在的位置: 主页 > 上位机技术 > JAVA > 一种确保Java程序安全的简单方式
本文所属标签:
为本文创立个标签吧:

一种确保Java程序安全的简单方式

来源:网络整理 网络用户发布,如有版权联系网管删除 2018-07-23 

SecurityManager介绍

Java序列化漏洞利用中突出的一点是,一旦一个服务器端的Java应用程序被破解,那么下一步就是获取主机上的shell访问权限,这就是我们所熟知的远程代码执行(RCE)。

然而有趣的是,其实从Java 1.1开始,Java中就存在一种方式来限制代码执行,并能够防止远程代码执行,这就是SecurityManager。在启用SecurityManager之后,Java代码会在一个非常安全的沙盒中执行,而这能够防止远程代码执行。

java -Djava.security.manager com.example.Hello

这会以$JAVA_HOME/jre/lib/security/java.policy中的默认安全策略运行,在JDK 1.8中为如下内容:

// Standard extensions get all permissions by default

grant codeBase "file:$/*" {

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 dynamic ports

permission java.net.SocketPermission "localhost:0", "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";

以下面的代码举例:

package com.example

object Hello {

def main(args: Array[String]): Unit = {

val runtime = Runtime.getRuntime

val cwd = System.getProperty("user.dir")

val process = runtime.exec(s"$cwd/testscript.sh")

println("Process executed without security manager interference!")

}

策略文件

在启用安全管理器并使用一个额外的策略文件时,可以明确地启用或禁用执行特权:

// You can read user.dir

permission java.util.PropertyPermission "user.dir", "read";

// Gets access to the current user directory script

permission java.io.FilePermission "${user.dir}/testscript.sh", "execute";

permission java.util.PropertyPermission "scala.control.noTraceSuppression", "read";

你可以以下面的方式运行:

java -Djava.security.manager -Djava.security.policy=security.policy com.example.Hello

如果只注释掉FilePermission那一行,那么将会抛出一个异常。

到目前为止一切都比较顺利。但是,那只是对客户端一侧的applet启用了这个功能,此时在服务器端仍然是禁用状态。

这是为什么呢?其实,因为(可以查看上述代码)默认的SecurityManager将系统锁在了无用点上。为了使系统处于有用状态,它必须拥有一个自定义的java.security.policy文件。

问题分析

这种策略的实现中有几个问题。因为策略文件本身是过时了的,安全权限并未以任何一种逻辑顺序进行排序,且一些权限拥有通配符的选择功能而其他的则没有。你可以以白名单的形式只允许特定的行为,而不是直接拒绝。最坏的情况是,列表越长,那么程序将运行得越慢。这里有一个教程和权限列表,但是在实践中并不是特别有用,并且这份文档指南上一次的更新时间早在2002年。

当你有了不可信任的代码时,可以编写定制的SecurityManager,而这就是Scalatron所做的工作。

然而,如果我们要防止远程代码执行,那么我们需要一个通用目的的SecurityManager,其中它几乎允许所有事情,但是能够阻止在主机上运行的代码。这可能不是一个完美的防守,但是它将是深度防御策略中很重要的一部分。

事实上,已经有个人做了这一点。

pro-grade介绍

Josef Cacek 将pro-grade集成在一起,向Java文件中添加了一个“deny”选项和一个“allow”选项。Devoxx中有一个演讲以幻灯片和视频形式讲解了pro-grade。

现在,使用pro-grade进行前面的示例,下面的策略将会锁定所有执行权限:

priority "grant";

deny {

//https://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html#FilePermission permission java.io.FilePermission "<

>", "execute";

注意,这不是一个完整的解决方案。为了阻止代码工作,我猜想你还需要禁用其他几个权限,不过我还不清楚哪些权限是与此相关的。但是,这只是一个开始,为了廉价地确保服务器端的Java程序安全,还有很长的路要走。

使用Pro-grade很简单创建一个适当的策略。有一个策略生成器可以显示一个应用程序所需要的所有权限,且一个教程展示了创建它所需要的所有步骤,然后有一个权限调试器能够捕捉偏离的权限。

应用到你的项目中

你可以在prograde-example这里得到整个项目,并且可以从这里将pro-grade集成到你的项目中。此外,大多数人将需要Maven:

net.sourceforge.pro-grade

pro-grade

1.1.1

pro-grade真正有趣的地方是,它是一个透明的解决方案。虽然使用白名单策略是一种不错的方式,但是使用这种技术你可以将pro-grade添加到一个现有的、已经编译的项目目中,并且可以禁用脚本执行。

只需一些小小的修改,pro-grade就可以用来通知入侵(尤其是setSecurityManager和其他很少接触的地方),似乎在默默地矫正操作时也能够正常工作。你需要做的所有工作就是以一个SLF4J实现来实现PermissionDeniedListener。



              查看评论 回复



嵌入式交流网主页 > 上位机技术 > JAVA > 一种确保Java程序安全的简单方式
 一个 代码 策略

网站地图

围观()