Java 原生实现代码沙箱之Java 程序安全控制(OJ判题系统第2期)——设计思路、实现步骤、代码实现

在看这一期之前,需要先看上一期的文章:

Java 原生实现代码沙箱(OJ判题系统第1期)——设计思路、实现步骤、代码实现-CSDN博客

Java 程序可能出现的异常情况

1、执行超时

占用时间资源,导致程序卡死,不释放资源:

/*** 无限睡眠(阻塞程序执行)*/
public class SleepError {public static void main(String[] args) throws InterruptedException {long ONE_HOUR = 60 * 60 * 1000L;Thread.sleep(ONE_HOUR);System.out.println("睡完了");}
}

2、占用内存

/*** 无限占用空间(浪费系统内存)*/
public class MemoryError {public static void main(String[] args) throws InterruptedException {List<byte[]> bytes = new ArrayList<>();while (true) {bytes.add(new byte[10000]);}}
}

3、读文件,文件信息泄露

/*** 读取服务器文件(文件信息泄露)*/
public class ReadFileError {public static void main(String[] args) throws InterruptedException, IOException {String userDir = System.getProperty("user.dir");String filePath = userDir + File.separator + "src/main/resources/application.yml";List<String> allLines = Files.readAllLines(Paths.get(filePath));System.out.println(String.join("\n", allLines));}
}

4、写文件,越权植入木马

/*** 向服务器写文件(植入危险程序)*/
public class WriteFileError {public static void main(String[] args) throws InterruptedException, IOException {String userDir = System.getProperty("user.dir");String filePath = userDir + File.separator + "src/main/resources/木马程序.bat";String errorProgram = "java -version 2>&1";Files.write(Paths.get(filePath), Arrays.asList(errorProgram));System.out.println("写木马成功,你完了哈哈");}
}

5、运行程序

/*** 运行其他程序(比如危险木马)*/
public class RunFileError {public static void main(String[] args) throws InterruptedException, IOException {String userDir = System.getProperty("user.dir");String filePath = userDir + File.separator + "src/main/resources/木马程序.bat";Process process = Runtime.getRuntime().exec(filePath);process.waitFor();// 分批获取进程的正常输出BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));// 逐行读取String compileOutputLine;while ((compileOutputLine = bufferedReader.readLine()) != null) {System.out.println(compileOutputLine);}System.out.println("执行异常程序成功");}
}

Java 程序安全控制

1、超时控制

private static final long TIME_OUT = 5000L; // 定义超时时间为5000毫秒(5秒)// 启动一个新线程进行超时控制
new Thread(() -> {try {// 让当前线程休眠TIME_OUT指定的时间Thread.sleep(TIME_OUT);// 超时后打印消息System.out.println("超时了,中断");// 终止运行中的进程runProcess.destroy();} catch (InterruptedException e) {// 如果线程在休眠期间被中断,抛出RuntimeExceptionthrow new RuntimeException(e);}
}).start(); // 启动线程

2、限制资源分配

我们不能让每个 java 进程的执行占用的 JVM 最大堆内存空间都和系统默认的一致(鱼皮的 JVM 默认最大占用 8G 内存),实际上应该更小(执行用户的题目代码也不需要这么多),比 如说 256MB。在启动 Java 程序时,可以指定 JVM 的参数: -Xmx256m(最大堆空间大小) 示例命令如下:

String runCmd = String.format("java -Xmx256m -Dfile.encoding=UTF-8 -cp %s Main %s", userCodeParentPath, inputArgs);

 小知识 - 常用 JVM 启动参数

1. 内存相关参数:
  • -Xms: 设置 JVM 的初始堆内存大小。
  • -Xmx: 设置 JVM 的最大堆内存大小。
  • -Xss: 设置每个线程的栈大小。
  • -XX:MaxMetaspaceSize: 设置 Metaspace(元空间)的最大大小。
  • -XX:MaxDirectMemorySize: 设置直接内存(Direct Memory)的最大大小。
2. 垃圾回收相关参数:
  • -XX:+UseSerialGC: 使用串行垃圾回收器。
  • -XX:+UseParallelGC: 使用并行垃圾回收器。
  • -XX:+UseConcMarkSweepGC: 使用 CMS(并发标记清除)垃圾回收器。
  • -XX:+UseG1GC: 使用 G1 垃圾回收器。
3. 线程相关参数:
  • -XX:ParallelGCThreads: 设置并行垃圾回收使用的线程数。
  • -XX:ConcGCThreads: 设置并发垃圾回收使用的线程数。
  • -Xss 或 -XX:ThreadStackSize: 设置每个线程的栈大小。注意:-Xss 和 -XX:ThreadStackSize 是等效的。
4. JIT 编译器相关参数:
  • -XX:TieredCompilation: 启用分层编译模式。
  • -XX:TieredStopAtLevel: 设置 JIT 编译器停止编译的层次。
5. 其他资源限制参数:
  • -XX:MaxRAM: 设置 JVM 可以使用的最大物理内存。

说明:

  • -Xss 和 -XX:ThreadStackSize 都用于设置线程的栈大小,通常情况下两者是等效的。
  • -XX:MaxRAM 参数在较新的 JDK 版本中引入,用于自动配置 JVM 的内存使用。

3、限制代码 - 黑白名单

先初始化字典树,插入禁用词:

 private static final List<String> blackList = Arrays.asList("Files", "exec");private static final WordTree WORD_TREE;static {// 初始化字典树WORD_TREE = new WordTree();WORD_TREE.addWords(blackList);}

 校验用户代码是否包含禁用词:

  //  校验代码中是否包含黑名单中的命令FoundWord foundWord = WORD_TREE.matchWord(code);if (foundWord != null) {System.out.println("包含禁止词:" + foundWord.getFoundWord());return null;}

限制权限 - Java 安全管理器

Java 安全管理器(Security Manager)是 Java 提供的保护 JVM、Java 安全的机制,可以实 现更严格的资源和操作限制。

 1.所有权限放开

/*** 默认安全管理器*/
public class DefaultSecurityManager extends SecurityManager {// 检查所有的权限@Overridepublic void checkPermission(Permission perm) {System.out.println("默认不做任何限制");System.out.println(perm);
//        super.checkPermission(perm);}
}

2.所有权限拒绝

/*** 禁用所有权限安全管理器*/
public class DenySecurityManager extends SecurityManager {// 检查所有的权限@Overridepublic void checkPermission(Permission perm) {throw new SecurityException("权限异常:" + perm.toString());}
}

3.限制权限

public class MySecurityManager extends SecurityManager {// 检查所有的权限@Overridepublic void checkPermission(Permission perm) {
//        super.checkPermission(perm);}// 检测程序是否可执行文件@Overridepublic void checkExec(String cmd) {throw new SecurityException("checkExec 权限异常:" + cmd);}// 检测程序是否允许读文件@Overridepublic void checkRead(String file) {System.out.println(file);if (file.contains("C:\\code\\yuoj-code-sandbox")) {return;}
//        throw new SecurityException("checkRead 权限异常:" + file);}// 检测程序是否允许写文件@Overridepublic void checkWrite(String file) {
//        throw new SecurityException("checkWrite 权限异常:" + file);}// 检测程序是否允许删除文件@Overridepublic void checkDelete(String file) {
//        throw new SecurityException("checkDelete 权限异常:" + file);}// 检测程序是否允许连接网络@Overridepublic void checkConnect(String host, int port) {
//        throw new SecurityException("checkConnect 权限异常:" + host + ":" + port);}
}

测试:

/*** 测试安全管理器*/
public class TestSecurityManager {public static void main(String[] args) {System.setSecurityManager(new MySecurityManager());FileUtil.writeString("aa", "aaa", Charset.defaultCharset());}
}

在运行java程序时,指定安全管理器的路径、安全管理器的名称:

private static final String SECURITY_MANAGER_PATH = "C:\\code\\code-sandbox\\src\\main\\resources\\security";private static final String SECURITY_MANAGER_CLASS_NAME = "MySecurityManager";String runCmd = String.format("java -Xmx256m -Dfile.encoding=UTF-8 -cp %s;%s -Djava.security.manager=%s Main %s", userCodeParentPath, SECURITY_MANAGER_PATH, SECURITY_MANAGER_CLASS_NAME, inputArgs);

至此,第二期结束,但是安全管理器有一定缺点:

1. 如果要做比较严格的权限限制,需要自己去判断哪些文件、包名需要允许读写。粒度太细 了,难以精细化控制。

2. 安全管理器本身也是 Java 代码,也有可能存在漏洞。本质上还是程序层面的限制,没深 入系统的层面。

所以下一期我们来讲一下,代码沙箱 Docker 实现

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/80486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常见的降维算法

作业&#xff1a; 自由作业&#xff1a;探索下什么时候用到降维&#xff1f;降维的主要应用&#xff1f;或者让ai给你出题&#xff0c;群里的同学互相学习下。可以考虑对比下在某些特定数据集上t-sne的可视化和pca可视化的区别。 一、什么时候用到降维&#xff1f; 降维通常…

理解Yocto项目中`${D}`作为模拟目标系统根文件结构的临时目录

在Yocto项目中,理解${D}作为模拟目标系统根文件结构的临时目录,可以通过以下具象化的比喻和结构解析来把握其核心逻辑: 一、沙盒模型:构建系统的“实验场地” ${D}的作用类似于建筑师在施工前搭建的1:1实体模型。它完全模仿目标设备的文件系统布局(如/usr/bin、/etc等目录…

第十课认识约数

课堂学习&#xff1a; 情景引入&#xff1a; 今天我们来认识一下数学中的约数关系&#xff0c;上节课我们了解完倍数之后就已经对约数有了基本的概念&#xff01; 我们按照是否有余数&#xff0c;可以把他们分成两类 在整数除法中&#xff0c;如果商是整数没有余数&#x…

【Vue】vuex的getters mapState mapGetters mapMutations mapActions的使用

目录 一、getters 二、 mapState 三、 mapGetters 四、 mapMutations 五、 mapActions 学到这儿来个小总结&#xff1a;四个map方法的使用 总结不易~ 本章节对我有很大的收获&#xff0c; 希望对你也是&#xff01;&#xff01;&#xff01; 本节素材已上传至Gitee&…

html object标签介绍(用于嵌入外部资源通用标签)(已不推荐使用deprecated,建议使用img、video、audio标签)

文章目录 HTML <object> 标签详解基本语法与核心属性关键属性解析1. **data**2. **type**3. **width & height**4. **name** 嵌入不同类型的资源1. **嵌入图像**2. **嵌入音频**3. **嵌入视频**4. **嵌入 PDF** 参数传递与回退内容**参数&#xff08;<param>&a…

警备,TRO风向预警,In-N-Out Burgers维权风暴来袭

本案是TME律所代理的5月首案&#xff0c;传奇连锁快餐品牌In-N-Out Burgers委托维权&#xff01; 案件基本情况&#xff1a; 起诉时间&#xff1a;2025-5-1 案件号&#xff1a;25-cv-04767 品牌&#xff1a;In-N-Out 原告&#xff1a;In-N-Out Burgers 原告律所&#xff…

数据结构算法习题通关:树遍历 / 哈夫曼 / 拓扑 / 哈希 / Dijkstra 全解析

已知一棵二叉树先序遍历和中序遍历分别为 ABDEGCFH 和 DBGEACHF&#xff0c;请画出这个二叉树的逻辑结构并写出后序遍历的序列。 先序遍历&#xff1a;ABDEGCFH 中序遍历&#xff1a;DBGEACHF 先序遍历看出根为A&#xff0c;左子树DBGE&#xff0c;右子树CHF A的左子树 再…

C++GO语言微服务和服务发现

目录 01 03-go-micro简介 02 04-服务发现的简单认识 03 05-consul的安装 04 06-consul常用的命令 05 07-注册服务到consul并验证 06 08-consul健康检查 07 09-consul结合grpc使用-上&#xff08;只实现grpc远程调用&#xff09; 08 10-consul结合grpc使用-中&#xff08…

HDFS 常用基础命令详解——快速上手分布式文件系统

简介&#xff1a; 本文面向刚接触 Hadoop HDFS&#xff08;Hadoop 分布式文件系统&#xff09;的读者&#xff0c;结合 CSDN 博客风格&#xff0c;系统梳理最常用的 HDFS 客户端命令&#xff0c;并配以示例和注意事项&#xff0c;帮助你在开发和运维中快速掌握 HDFS 的文件管理…

VUE CLI - 使用VUE脚手架创建前端项目工程

前言 前端从这里开始&#xff0c;本文将介绍如何使用VUE脚手架创建前端工程项目 1.预准备&#xff08;编辑器和管理器&#xff09; 编辑器&#xff1a;推荐使用Vscode&#xff0c;WebStorm&#xff0c;或者Hbuilder&#xff08;适合刚开始练手使用&#xff09;&#xff0c;个…

make和makefile的使用,以及写一个简单的进度条程序

1.自动化构建-make/makefile 1.1 背景 一个工程文件中的文件不计其数&#xff0c;其按类型、功能、模块放在若干目录中&#xff0c;makefile定义了一系列规则来指定哪些文件需要先编译&#xff0c;哪些文件需要后编译&#xff0c;哪些文件需要重新编译&#xff0c;甚至于过呢…

数据结构中的栈与队列:原理、实现与应用

前言&#xff1a;栈和队列是计算机科学中两种最基础的线性数据结构&#xff0c;它们的独特操作规则和广泛的应用场景使其成为每一位开发者必须掌握的核心知识。本文将通过生活案例、代码实现和实际应用场景&#xff0c;带您深入理解这两种数据结构的精髓。 1.栈&#xff08;Sta…

如何选择自己喜欢的cms

选择内容管理系统cms what is cms1.whatcms.org2.IsItWP.com4.Wappalyzer5.https://builtwith.com/6.https://w3techs.com/7. https://www.netcraft.com/8.onewebtool.com如何在不使用 CMS 检测器的情况下手动检测 CMS 结论 在开始构建自己的数字足迹之前&#xff0c;大多数人会…

SDC命令详解:使用all_outputs命令进行查询

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html all_outputs命令用于创建一个输出端口对象集合&#xff0c;关于设计对象和集合的更详细介绍&#xff0c;可以参考下面的博客。 Synopsys&#xff1a;设计对象https://chenzhang.blog.csdn…

vue 中的ref

vue 中的ref vue 中的ref 1. ​​ref​​ ** 的基本作用** 在 Vue 中&#xff0c;ref 是用来获取 DOM 元素或者组件实例的一种方式。对于 <el-form> 组件&#xff0c;通过 ref 可以获取到该表单组件的实例&#xff0c;进而调用表单组件提供的各种方法和访问其属性。 …

数据库版本控制工具--flyway

一. 什么是Flyway Flyway 是一款开源的数据库迁移工具。它采用简单直观的方式管理数据库变更&#xff0c;通过版本化的迁移脚本确保数据库结构的一致性和可重复性。无论是开发环境、测试环境还是生产环境&#xff0c;Flyway 都能确保数据库变更按照预期顺序执行&#xff0c;避…

C++使用PoDoFo库处理PDF文件

&#x1f4da; PoDoFo 简介 PoDoFo 是一个用 C 编写的自由开源库&#xff0c;专用于 读取、写入和操作 PDF 文件。它适用于需要程序化处理 PDF 文件的应用程序&#xff0c;比如批量生成、修改、合并、提取元数据、绘图等。 &#x1f31f; 核心特点 特性说明&#x1f4c4; P…

论文分享➲ arXiv2025 | TTRL: Test-Time Reinforcement Learning

TTRL: Test-Time Reinforcement Learning TTRL&#xff1a;测试时强化学习 https://github.com/PRIME-RL/TTRL &#x1f4d6;导读&#xff1a;本篇博客有&#x1f9a5;精读版、&#x1f407;速读版及&#x1f914;思考三部分&#xff1b;精读版是全文的翻译&#xff0c;篇幅较…

dify插件接入fastmcp示例

文章目录 1. 使用python完成mcp服务1.1 准备环境&#xff08;python安装fastmcp&#xff09;1.2 mcp服务端示例代码1.3 启动mcp服务端 2. dify接入2.1 安装MCP SSE和 Agent 策略&#xff08;支持 MCP 工具&#xff09; 插件2.2 dify agent插件配置mcp:2.3 mcp服务配置&#xff…

Linux 挖矿木马排查命令清单

Linux 挖矿木马排查命令清单 1. 系统资源使用情况检查 # 查看CPU、内存使用情况 top -c# 检查CPU占用最高的进程 ps aux --sort-%cpu# 查找可疑进程名 ps -ef | grep -i miner\|cpu\|GPU\|xmr# 检查网络连接情况 lsof -i2. 可疑进程和隐藏进程检查 # 检查僵尸进程 ps -ef | …