fix: 【漏洞】修复HttpClientUtil.java的漏洞

This commit is contained in:
tjlygdx
2026-06-10 15:19:08 +08:00
parent 227b77b327
commit 466d7a5f2c

View File

@@ -5,6 +5,7 @@ import lombok.Data;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
@@ -38,6 +39,9 @@ import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.regex.Matcher;
@@ -395,14 +399,14 @@ public class HttpClientUtil {
}
throw new Exception(msg);
}
String fileName = extractFileName(response, url);
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
String fileName = normalizeDownloadFileName(extractFileName(response, url));
String suffix = extractSuffix(fileName);
String tranName = UUID.randomUUID().toString() + "." + suffix;
name.put("fileName", fileName);
name.put("tranName", tranName);
File localFile = new File(path + tranName);
Path localFile = resolveDownloadPath(path, tranName);
try (InputStream is = response.getEntity().getContent();
FileOutputStream outputStream = new FileOutputStream(localFile)) {
OutputStream outputStream = Files.newOutputStream(localFile)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
@@ -417,15 +421,26 @@ public class HttpClientUtil {
}
private static String extractFileName(HttpResponse response, String url) {
url = URLDecoder.decode(url);
String fileName = "";
String disposition = response.getHeaders("Content-Disposition").toString();
if (disposition != null) {
int filenameIndex = disposition.indexOf("filename=");
if (filenameIndex > 0) {
fileName = disposition.substring(filenameIndex + 9)
.replaceAll("\"", "") // 去除引号
.trim();
url = URLDecoder.decode(url, StandardCharsets.UTF_8);
String fileName = StringUtils.EMPTY;
Header dispositionHeader = response.getFirstHeader("Content-Disposition");
if (dispositionHeader != null && StringUtils.isNotBlank(dispositionHeader.getValue())) {
String disposition = dispositionHeader.getValue();
int filenameStarIndex = disposition.indexOf("filename*=");
if (filenameStarIndex >= 0) {
fileName = disposition.substring(filenameStarIndex + 10).trim();
int charsetIndex = fileName.indexOf("''");
if (charsetIndex >= 0) {
fileName = fileName.substring(charsetIndex + 2);
}
fileName = URLDecoder.decode(fileName.replace("\"", "").trim(), StandardCharsets.UTF_8);
} else {
int filenameIndex = disposition.indexOf("filename=");
if (filenameIndex >= 0) {
fileName = disposition.substring(filenameIndex + 9)
.replace("\"", "")
.trim();
}
}
}
if (fileName.isEmpty()) {
@@ -434,12 +449,43 @@ public class HttpClientUtil {
? url.substring(url.lastIndexOf('/') + 1)
: "download_" + System.currentTimeMillis();
}
if (fileName.trim().isEmpty()) {
fileName = "download_" + System.currentTimeMillis();
}
return fileName;
}
private static String normalizeDownloadFileName(String fileName) {
String normalizedFileName = StringUtils.trimToEmpty(fileName);
if (normalizedFileName.isEmpty()) {
normalizedFileName = "download_" + System.currentTimeMillis();
}
int separatorIndex = Math.max(normalizedFileName.lastIndexOf('/'), normalizedFileName.lastIndexOf('\\'));
if (separatorIndex >= 0) {
normalizedFileName = normalizedFileName.substring(separatorIndex + 1);
}
if (normalizedFileName.isEmpty()) {
normalizedFileName = "download_" + System.currentTimeMillis();
}
FileUtils.validateUploadFilename(normalizedFileName);
return normalizedFileName;
}
private static String extractSuffix(String fileName) {
int suffixIndex = fileName.lastIndexOf(".");
if (suffixIndex < 0 || suffixIndex == fileName.length() - 1) {
return "bin";
}
return fileName.substring(suffixIndex + 1);
}
private static Path resolveDownloadPath(String path, String fileName) {
FileUtils.validateUploadFilename(fileName);
Path directory = Paths.get(path).toAbsolutePath().normalize();
Path target = directory.resolve(fileName).normalize();
if (!target.startsWith(directory)) {
DEException.throwException("invalid download path");
}
return target;
}
public static byte[] downloadBytes(String url) {
HttpClientConfig config = new HttpClientConfig();
return HttpClientUtil.downFromRemote(url, config);