Ref#
Vulnerables#
SSRF#
远程下载 SSRF#
halo-1.4.9/src/main/java/run/halo/app/theme/ZipThemeFetcher.java
@Override
public ThemeProperty fetch(Object source) {
final var themeZipLink = source.toString();
// build http request
final var request = HttpRequest.newBuilder()
.uri(URI.create(themeZipLink))
.timeout(Duration.ofMinutes(2))
.GET()
.build();
try {
// request from remote
log.info("Fetching theme from {}", themeZipLink);
var inputStreamResponse =
httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream());
var inputStream = inputStreamResponse.body();
// unzip zip archive
try (var zipInputStream = new ZipInputStream(inputStream)) {
var tempDirectory = FileUtils.createTempDirectory();
log.info("Unzipping theme {} to {}", themeZipLink, tempDirectory);
unzip(zipInputStream, tempDirectory);
// resolve theme property
return ThemePropertyScanner.INSTANCE.fetchThemeProperty(tempDirectory)
.orElseThrow(() -> new ThemePropertyMissingException("主题配置文件缺失!请确认后重试。"));
}
} catch (InterruptedException | IOException e) {
throw new RuntimeException("主题拉取失败!(" + e.getMessage() + ")", e);
}
}当下载的目标文件是 .zip 文件时, 处理函数没有任何检查逻辑, 直接将参数转成 url 后下载
run.halo.app.theme.ZipThemeFetcher#fetchrun.halo.app.theme.ThemeFetcherComposite#fetchrun.halo.app.service.impl.ThemeServiceImpl#fetchrun.halo.app.controller.admin.api.ThemeController#fetchTheme
@PostMapping("fetching")
@ApiOperation("Fetches a new theme")
public ThemeProperty fetchTheme(@RequestParam("uri") String uri) {
return themeService.fetch(uri);
}整个处理过程也毫无验证逻辑
POST /api/admin/themes/fetching?uri=http://127.0.0.1:port/name.zip HTTP/1.1
{}漏洞危险性轻微