java-sec-code中命令注入
不安全的写法(由于我这里使用的是idea搭建的环境,原本命令执行的sh -c 无法运行,后续的输出也会产生乱码,修改部分代码,以便能更好的显示出效果,linux下使用docker木有问题
)
//需要导入的库文件
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@GetMapping("/codeinject")
public String codeInject(String filepath) throws IOException {
String[] cmdList = new String[]{"cmd.exe", "/c", "dir", filepath};
ProcessBuilder builder = new ProcessBuilder(cmdList);
builder.environment().put("LC_ALL", "GBK");
builder.redirectErrorStream(true);
Process process = builder.start();
//return WebUtils.convertStreamToString(process.getInputStream());
try (InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"))) {
String line;
StringBuilder output = new StringBuilder();
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
return output.toString();
}
}
当用户访问codeinject
路由时,服务端会获取filepath参数内容并进行拼接,创建外部进程执行拼接后的命令,并将输出字符转换为字符串进行输出,由于程序并未对用户输入进行过滤,导致命令注入的产生。
复现 这里filepath后面的参数需要url编码,使用hackbar编码即可
windows下
http://127.0.0.1:8080/codeinject?filepath=D%3A%5Calibaba%26%26ipconfig
http://192.168.2.5:8080/codeinject?filepath=/tmp;cat /etc/passwd
host
位置(个人认为这个位置不会产生命令注入,请求包中host用来指定请求的目标服务器,如果修改为127.0.0.1:8080|ipconfig或者127.0.0.1:8080&ipconfig等形式,连正常的http连接都建立不了,更不要说后续的漏洞利用了,这里只是个人的粗鄙之见,还希望大佬不吝赐教,至于别的博文提供的192.168.2.5;id && pwd linux和windows下均无法复现
)
代码
@GetMapping("/codeinject/host")
public String codeInjectHost(HttpServletRequest request) throws IOException {
String host = request.getHeader("host");
logger.info(host);
String[] cmdList = new String[]{"cmd.exe", "/c", "curl", host};
ProcessBuilder builder = new ProcessBuilder(cmdList);
builder.redirectErrorStream(true);
Process process = builder.start();
try (InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"))) {
String line;
StringBuilder output = new StringBuilder();
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
return output.toString();
}
}
简单地说,网站获取用户请求的host的属性值,然后进行拼接,命令执行,但是由于host属性值的特殊性,host无法添加特殊字符&|
,无法利用
安全代码
@GetMapping("/codeinject/sec")
public String codeInjectSec(String filepath) throws IOException {
String filterFilePath = SecurityUtil.cmdFilter(filepath);
if (null == filterFilePath) {
return "Bad boy. I got u.";
}
String[] cmdList = new String[]{"cmd.exe", "/c", "dir", filepath};
ProcessBuilder builder = new ProcessBuilder(cmdList);
builder.redirectErrorStream(true);
Process process = builder.start();
try (InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"))) {
String line;
StringBuilder output = new StringBuilder();
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
return output.toString();
}
}
private static final Pattern FILTER_PATTERN = Pattern.compile("^[a-zA-Z0-9_/\\.-]+$");
public static String cmdFilter(String input) {
if (!FILTER_PATTERN.matcher(input).matches()) {
return null;
}
return input;
}
这里使用正则表达式进行匹配,是否只包含字母、数字、下划线、斜杠、点或破折号,如果是,则进行命令拼接运行,否则返回Bad boy. I got u
windows下
如果为D:\
存在冒号,反斜杠,不符合要求,会输出Bad boy. I got u
linux如果为/tmp
只有斜杠和小写字母,符合要求,拼接运行
如果为/tmp;cat /etc/passwd
则会因为出现分号的原因输出Bad boy. I got u
如果需要在windows下查看结果 需要将正则修改为
^[a-zA-Z0-9_/\\\\.-]+$