From 979b407c156d89570cac7dccd7d91724b70416eb Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 4 Jul 2026 20:59:16 +0000 Subject: [PATCH] =?UTF-8?q?=EB=B3=B4=EC=95=88:=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=ED=83=90=EC=83=89=20=EB=B0=8F=20=EC=8B=AC=EB=B3=BC=EB=A6=AD=20?= =?UTF-8?q?=EB=A7=81=ED=81=AC=20=EC=9A=B0=ED=9A=8C=20=EC=B7=A8=EC=95=BD?= =?UTF-8?q?=EC=A0=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `html4tree/main.kt`의 루트 디렉터리(`topDir`) 검증 과정에서 `File.canonicalFile` 사용 시 심볼릭 링크가 자동 해석되어 이후의 `LinkOption.NOFOLLOW_LINKS` 검사가 무력화되는 문제를 수정했습니다. 이를 `File.absoluteFile`로 변경하여 심볼릭 링크 검증이 정상적으로 작동하도록 조치했습니다. --- .jules/sentinel.md | 5 +++++ CHANGELOG.md | 3 +++ src/main/kotlin/html4tree/main.kt | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 6c61284..88e0054 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -22,3 +22,8 @@ **Vulnerability:** Defense in Depth (CSP Missing) **Learning:** Even when inputs are properly escaped, statically generated HTML that displays file/directory structures should implement a Content Security Policy (CSP) to provide an extra layer of defense against potential XSS bypasses. **Prevention:** Include a strict CSP meta tag (e.g., `default-src 'none'; style-src 'unsafe-inline';`) in auto-generated HTML headers when external scripts or resources are not required. + +## 2024-07-04 - Symlink Check Bypass via canonicalFile +**Vulnerability:** The application was vulnerable to directory traversal/symlink attacks because `File.canonicalFile` automatically resolves symbolic links, bypassing subsequent checks that look for symlinks using `LinkOption.NOFOLLOW_LINKS`. +**Learning:** When trying to determine if a given path is a symlink (or trying to forbid symlink resolution), using `canonicalFile` beforehand defeats the purpose because it resolves symlinks to their real paths. `LinkOption.NOFOLLOW_LINKS` with `Files.isDirectory` fails to detect the symlink if the path passed in has already been canonicalized. +**Prevention:** Always use `File.absoluteFile` instead of `File.canonicalFile` when you need a full path but want to preserve symlinks so that they can be checked or rejected properly using `Files.isSymbolicLink` or `LinkOption.NOFOLLOW_LINKS`. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..850f19e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# 변경 사항 + +- `html4tree/main.kt`의 루트 디렉터리(`topDir`) 심볼릭 링크 검사 우회 취약점 수정. `File.canonicalFile`이 심볼릭 링크를 자동 해석하여 `LinkOption.NOFOLLOW_LINKS` 검사가 무력화되는 문제를 방지하기 위해 `File.absoluteFile`로 변경. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 2e2809f..013452c 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -23,7 +23,7 @@ fun main(args: Array) = Html4tree().main(args) fun go(topDir: String, maxLevel: Int) { require(topDir.isNotBlank()) - val top_dir = File(topDir).canonicalFile + val top_dir = File(topDir).absoluteFile require(Files.isDirectory(top_dir.toPath(), LinkOption.NOFOLLOW_LINKS)) { "Top directory must be an existing non-symlink directory" } val ll = LinkedList()