기록 목록자료실
Filesystem Signed Upload Endpoint 관찰 기록
humanpchumanpc ·
06-1051
요약
* /storage/{path} GET·PUT Endpoint 발견
* Laravel FilesystemServiceProvider 자동 등록 기능 확인
* 즉시 악용 가능한 공개 업로드 취약점은 확인되지 않음
* Signed URL 기반 접근 제어 확인
* GitHub Issue #52 등록 및 설계 검토 요청
* local · modules · plugins 의 serve=true 구성 재검토
* GET|HEAD /storage/{path} 제거
* PUT /storage/{path} 제거
* 주요 공개 API 및 화면 정상 동작 검증 완료
G7 운영 환경의 엔드포인트 노출 상태를 점검하던 중 흥미로운 라우트 하나를 발견했다.
바로 /storage/{path} Endpoint이다.
처음에는 일반적인 파일 제공용 Endpoint라고 생각했지만, 라우트 목록을 확인해 보니 GET·HEAD 뿐 아니라 PUT 요청도 처리하고 있었다.
그래서 이 경로가 어떤 방식으로 동작하는지 추가로 확인해 보았다.
조사 결과 이 Endpoint는 프로젝트에서 직접 만든 기능이 아니었다.
Laravel Framework 내부의 FilesystemServiceProvider가 자동으로 등록하는 기능이었다.
따라서 G7 고유 기능이라기보다 Laravel Filesystem 기능의 일부에 가깝다.
가장 먼저 확인한 것은 공개 업로드 가능 여부였다.
결론부터 말하면 현재 상태를 "무인증 임의 업로드 취약점"으로 판단하지는 않았다.
PUT 요청이 수행되려면 단순히 URL에 접근하는 것만으로는 부족했다.
요청에는 upload=true 값이 포함되어야 하며, Laravel이 생성한 유효한 Relative Signed URL 검증도 통과해야 했다.
즉 아무나 임의 파일을 업로드할 수 있는 구조는 아니었다.
다만 운영 환경을 확인하는 과정에서 몇 가지 흥미로운 점을 발견했다.
당시 local, modules, plugins 디스크 모두 serve=true 상태로 설정되어 있었다.
그런데 실제 라우트 목록에서는 plugins 디스크 기준의 storage route만 노출되는 것으로 보였다.
여러 디스크가 동일한 /storage 경로를 공유하는 현재 구조가 의도된 것인지 궁금해졌다.
또 하나 눈에 띈 점은 Signed URL 검증 이후의 동작이었다.
검증을 통과하면 특정 리소스 전용 API라기보다 범용 파일 쓰기 경로처럼 동작한다.
관찰 결과는 다음과 같았다.
* 기존 파일 덮어쓰기 가능
* 하위 경로 저장 가능
* 애플리케이션 레벨 MIME 검증 확인 못함
* 애플리케이션 레벨 확장자 제한 확인 못함
* 애플리케이션 레벨 감사 로그 확인 못함
반면 Flysystem은 ../ 경로 이탈 시도를 정상적으로 차단하고 있었다.
이번 확인 과정에서 가장 궁금했던 부분은 실제 사용 여부였다.
코드를 검색해 보았지만 Signed Upload URL을 발급하는 명확한 사용처는 찾지 못했다.
실사용 여부와 현재 구조의 설계 의도를 확인하기 위해 GitHub Issue #52를 등록하여 검토를 요청하였다.
추가 조사 결과 현재 운영 환경에서는 해당 Signed Storage Endpoint의 실제 사용처를 확인하지 못했다.
이에 따라 local · modules · plugins 디스크의 serve=true 구성을 재검토하였고, filesystem serving을 비활성화하여 Laravel이 자동 등록하던 다음 라우트를 제거하였다.
* GET|HEAD /storage/{path}
* PUT /storage/{path}
변경 후 route inventory에서 해당 Endpoint가 제거된 것을 확인했으며, 주요 공개 API와 화면 동작에는 영향이 없음을 검증하였다.
이번 사례는 취약점 발견이라기보다 framework 기본 기능에 의해 노출된 범용 Signed Upload Endpoint를 관찰하고, 동작을 분석한 뒤, 설계 의도를 검토하고, 실제 사용되지 않는 노출 표면을 축소한 운영 기록에 가깝다.
또한 해당 과정에서 GitHub Issue #52를 통해 업스트림 프로젝트에 설계 검토를 요청하였으며, 운영 중인 환경에서는 해당 Endpoint를 제거하여 노출 표면을 축소하였다.
결과적으로 이번 작업은 다음 흐름으로 정리할 수 있다.
Production Endpoint Audit
→ Framework 동작 분석
→ GitHub Issue #52 등록
→ 운영 환경 Hardening
→ 검증 완료
댓글과 작업 영역을 나중에 불러옵니다
필요할 때 댓글과 작업 영역을 불러옵니다. 댓글 0개
