沙箱Java代码

本文详细介绍了如何为Java应用程序设置代码沙箱,包括安全经理的使用、权限管理、策略规定、签名代码以及特权代码的概念,以确保代码在受限环境中安全运行。
摘要由CSDN通过智能技术生成

在上一篇文章中,我们研究了如何保护移动Java代码 。 这样做的一种选择是在笼子或沙箱中运行代码。

这篇文章探讨了如何为Java应用程序设置这样的沙箱。

安全经理

Java中支持沙箱的安全性设施是java.lang.SecurityManager

默认情况下,Java在没有SecurityManager情况下运行,因此您应在应用程序中添加代码以启用以下代码:

System.setSecurityManager(new SecurityManager());

您可以使用标准的SecurityManager或后代。

SecurityManager有许多checkXXX()方法,这些方法都转发给checkPermission(permission, context) 。 此方法要求AccessController进行实际工作(请参见下文)。

[ checkXXX()方法是Java 1.1遗物 。]

如果允许请求的访问,则checkPermission()安静地返回。 如果被拒绝,则抛出java.lang.SecurityException

实现沙箱的代码应在执行敏感操作之前调用checkXXX方法:

SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
  Permission permission = ...;
  securityManager.checkPermission(permission);
}

JRE包含许多地方的代码。

权限

权限表示对系统资源的访问。

为了允许这种访问,必须向尝试访问的代码显式授予相应的许可(请参见下文)。

权限源自java.security.Permission 。 它们有一个名称和一个可选的操作列表(以逗号分隔的字符串值形式)。

Java附带了许多预定义的权限,例如FilePermission 。 您还可以添加自己的权限

以下是read文件/home/remon/thesis.pdf的权限:

Permission readPermission = new java.io.FilePermission(
    '/home/remon/thesis.pdf', 'read');

您可以通过授予代码权限AllPermission来执行任何事情。 这与不使用SecurityManager运行它具有相同的效果。

政策规定

使用策略 授予权限。 策略负责确定代码是否有权执行安全敏感的操作。

AccessController查阅Policy以查看是否授予了Permission

在任何给定时间只能使用一个Policy对象。 应用程序代码可以将Policy子类化以提供自定义实现

Policy默认实现使用配置文件加载授权。 有一个系统范围的策略文件和一个(可选)用户策略文件

您可以使用PolicyTool程序创建其他策略配置文件。 每个配置文件都必须使用UTF-8编码。

默认情况下,根本不授予代码任何权限。 每个grant语句都会添加一些权限。 授予的权限无法撤消。

以下策略片断授予代码,从起源/home/remon/code/目录read权限的文件/home/remon/thesis.pdf

grant codeBase 'file:/home/remon/code/-' {
    permission java.io.FilePermission '/home/remon/thesis.pdf',
        'read';
};

请注意, codeBase的部分是URL ,因此,即使在Windows系统上,也应始终使用正斜杠。

带尾随/ codeBase匹配指定目录中的所有类文件(不是JAR文件)。 带有尾随/* codeBase匹配该目录中包含的所有文件(类和JAR文件)。 带有尾随/- codeBase匹配目录中的所有文件(类和JAR文件),并递归匹配该目录中包含的子目录中的所有文件。

对于Windows系统上文件权限中的路径,您需要使用双反斜杠( \\ ),因为\是转义字符:

grant codeBase 'file:/C:/Users/remon/code/-' {
    permission java.io.FilePermission
        'C:\\Users\\remon\\thesis.pdf', 'read';
};

为了获得更大的灵活性,您可以编写带有可变部分的赠款。 我们已经看到了codeBase通配符。 您也可以替换系统属性

grant codeBase 'file:/${user.home}/code/-' {
    permission java.io.FilePermission
        '${user.home}${/}thesis.pdf', 'read';
};

注意
${/}替换为系统的路径分隔符。 无需在 codeBase ,因为这是一个URL。

签名码

当然,我们应该确保我们使用的代码是签名的 ,以便我们知道它实际上是我们认为来自的人。

我们可以使用signedBy子句在策略中测试签名:

keystore 'my.keystore';
grant signedBy 'signer.alias', codeBase ... {
  ...
};

这一政策片段使用的密钥库别名为my.keystore来查找公钥证书与别名signer.alias

然后,它验证执行代码已由与找到的证书中的公钥相对应的私钥签名。

只能有一个keystore条目。

codeBasesignedBy子句的组合指定了ProtectionDomain 。 同一ProtectionDomain中的所有类都具有相同的权限。

特权代码

每当尝试进行资源访问时,堆栈上的所有代码必须具有该资源访问的权限,除非堆栈上的某些代码已标记为privileged

将代码标记为特权可使一段受信任的代码临时允许访问比直接调用它的代码更多的资源。 换句话说,安全系统将所有呼叫者视为来自发出特权呼叫的类的ProtectionDomain的所有呼叫者,但仅在特权呼叫的持续时间内。

您可以通过在AccessController.doPrivileged()调用中运行代码来使代码具有特权:

AccessController.doPrivileged(new PrivilegedAction() {
  public Object run() {
    // ...privileged code goes here...
    return null; 
  }
});

组装沙箱

现在我们有了组装沙箱所需的所有零件:

  1. 安装SecurityManager
  2. 签名应用程序罐
  3. 授予我们签名的所有代码AllPermission
  4. 在移动代码可能调用的地方添加权限检查
  5. 权限检查doPrivileged()块后运行代码

我在GitHub上创建了一个简单的示例。

参考: 安全软件开发博客中来自我们JCG合作伙伴 Remon Sinnema的Java代码沙盒

翻译自: https://www.javacodegeeks.com/2012/11/sandboxing-java-code.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值