From 5adbcc0aff2fc1c765287c1768aeb8391a1662f2 Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Wed, 26 Feb 2025 21:20:54 -0500 Subject: [PATCH] [O] Protect against path traversal --- src/main/java/ext/Ext.kt | 2 ++ src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/ext/Ext.kt b/src/main/java/ext/Ext.kt index 2c3c28d1..c7278dcc 100644 --- a/src/main/java/ext/Ext.kt +++ b/src/main/java/ext/Ext.kt @@ -19,6 +19,7 @@ import org.springframework.http.HttpHeaders import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity.BodyBuilder import org.springframework.web.bind.annotation.* +import java.io.File import java.lang.reflect.Field import java.nio.charset.StandardCharsets import java.nio.file.Path @@ -235,6 +236,7 @@ fun Lock.maybeLock(block: () -> T) = if (tryLock()) try { block() } finally fun path(part1: Str, vararg parts: Str) = Path.of(part1, *parts) fun Str.path() = Path.of(this) operator fun Path.div(part: Str) = resolve(part) +operator fun File.div(fileName: Str) = File(this, fileName) fun Str.ensureEndingSlash() = if (endsWith('/')) this else "$this/" fun T.logger() = LoggerFactory.getLogger(this::class.java) diff --git a/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt b/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt index 253976bc..cc9a3967 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt @@ -175,10 +175,12 @@ class Maimai2( SUCCESS } + val photoDir = UploadUserPhotoHandler.uploadDir.toFile().canonicalFile + @API("my-photo") suspend fun myPhoto(@RP token: Str) = us.jwt.auth(token) { u -> val find = "${u.ghostCard.extId}-" - UploadUserPhotoHandler.uploadDir.toFile().listFiles() + photoDir.listFiles() ?.map { it.name } ?.filter { it.startsWith(find) } ?.sorted() @@ -187,8 +189,9 @@ class Maimai2( @API("my-photo/{fileName}", produces = [MediaType.IMAGE_JPEG_VALUE]) suspend fun myPhoto(@RP token: Str, @PV fileName: Str) = us.jwt.auth(token) { u -> - if (!fileName.startsWith("${u.ghostCard.extId}-")) (403 - "Not your photo") - val f = (UploadUserPhotoHandler.uploadDir / fileName).toFile() + val f = (photoDir / fileName) + if (!f.canonicalFile.startsWith(photoDir)) (403 - "Never gonna give you up") + if (!f.name.startsWith("${u.ghostCard.extId}-")) (403 - "Not your photo") if (!f.exists()) (404 - "Photo not found") f.readBytes() }