背景:
在最近一个项目中,需要在java平台上调用Linux命令,实现对Linux系统的操作。
命令参数注入说明
比如获取某个目录下面的文件信息,Linux命令如下:
ls /opt/test 其中/opt/test是传入的参数值
传入的参数如果不经过校验就很危险了,就像SQL注入一样,原子弹爆炸。
比如:
cd /opt;rm -rf /* 其中/opt;rm -rf /* 为参数传入值
这实际上被 ; 分割成两个语句了。有人说用单引号 '参数值' 把参数值阔起来就可以了,实际上是不行的,如下:
cd '/opt';rm -rf '/*' 其中参数值为:/opt';rm -rf '/*
其也是被 ; 分割成两个命令了,因此我们需要在参数这一层做校验,防止非法字符
非法字符列表(包括但不局限于)
字符 | 功能描述 | Unix | Windows |
| | 管道:连接上个指令的标准输出,作为下个指令的标准输入 | \| | ^| |
; | 连续指令服务 | \; | ^; |
& | 后台运行 | \& | ^& |
$ | 变量替换 | \$ | ^$ |
> | 重定向输入 | \> | ^> |
< | 目标文件内容发送到命令中 | \< | ^< |
` | 返回当前执行结果 | \` | ^` |
\ | 作为连接符号用,或者转义用 | \\ | ^\ |
! | 执行上一条shell命令 | \! | ^! |
解决方案-设置参数值白名单
java实现如下:
/**
* 检测参数是否合法
* @param params 参数
* @return
*/
private static boolean paramsIsSafe(List<String> params){
if(CollectionUtils.isEmpty(params)){
return false;
}
for (String param : params) {
String safeParam = getSafeParam(param);
if(safeParam.length()!=param.length()){
return false;
}
}
return true;
}
/**
* 返回合法的参数
* @param param 参数
* @return
*/
private static String getSafeParam(String param)
{
StringBuilder safeParam = new StringBuilder();
String whiteCharList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-=[]\\',./ ~@#%^*()_+\"{}:?";
char[] safeParamChars = param.toCharArray();
for (char safeParamChar : safeParamChars) {
int whiteListIndex = whiteCharList.indexOf(safeParamChar);
if (-1 == whiteListIndex) {
return safeParam.toString();
}
safeParam.append(whiteCharList.charAt(whiteListIndex));
}
return safeParam.toString();
}
完成!
如有帮助望多多支持,你的赞赏使我最大的支持