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.pswp.cn/bicheng/80486.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80486.shtml
英文地址,請注明出處:http://en.pswp.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 | …