CVE-2026-33398

CVE-2026-33398

Area
Web / AppSec
Credit
Public Attribution
Credit Note
공동 공개 귀속 · Amemoyoi: Finder · HuajiHD: Reporter
CVSS
7.1
CVSS Source
CNA / Vendor
CVSS Vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
CWE
CWE-285
Impact
Information Disclosure
Key Finding
일반 화면에서 숨겨진 글이 인용 API에서는 권한 검사 없이 반환되어 게시물 본문이 노출됐습니다.
Published
Jun 2, 2026
Score Note
Severity
High
Status
Public
Target
NamelessMC · Forum quote API
일반 주제 화면은 403을 반환했지만 같은 세션으로 /forum/get_quotes를 호출하면 숨겨진 글 본문이 반환됐습니다. 두 읽기 경로의 권한 검사를 대조한 기록입니다.
Taegu Ha · NamelessMC · CWE-285 · CVSS 7.1
2026년 6월 2일 공개 · NamelessMC 2.2.5에서 수정 · 공식 기록

한눈에 보기

🔎
숨김 포럼의 topic·post ID를 quote API에 직접 전달하면, 일반 열람 경로의 권한 검사가 적용되지 않아 숨겨진 게시물 본문이 quote 응답으로 반환됐습니다.
구분
확인 내용
프로젝트·컴포넌트
NamelessMC quote API · get_quotes.php
공격 입력
열람 권한이 없는 숨김 topic·post ID
필요 조건
숨김 포럼을 볼 수 없지만 quote endpoint를 호출할 수 있는 사용자
취약 지점
일반 포럼 보기 경로와 quote 경로 사이의 permission check 불일치
검증 결과
숨김 게시물의 quote text가 응답에 포함되는 것을 확인
영향
비공개 forum content의 confidentiality 침해
수정 원칙
forum·topic permission 판정을 중앙화하고 모든 조회 경로에 동일 적용

공격 흐름

검증 결론: 일반 화면에서는 숨겨진 게시물이 quote 전용 경로에서 반환되어, 객체 조회 이후의 권한 검사가 빠진 IDOR형 정보 노출을 확인했습니다.

취약점 개요

NamelessMC의 포럼 글은 공개 포럼뿐 아니라 비공개·직원 전용 포럼에도 저장됩니다. 정상 주제 화면은 현재 사용자가 포럼과 주제를 볼 수 있는지 검사하지만, 인용문을 가져오는 별도 endpoint는 로그인 여부만 확인한 뒤 요청자가 보낸 post ID로 본문을 읽었습니다.
같은 저권한 계정으로 정상 화면과 인용 endpoint를 비교했습니다. 정상 화면은 접근을 거부했지만 인용 endpoint는 숨겨진 글의 내용을 JSON 응답에 포함했습니다. 로그인했다는 사실과 특정 글을 볼 권한은 별개인데 두 조건이 하나로 취급된 문제였습니다.
공격자가 제어하는 값
post 쿼리의 게시물 ID
취약 경로
modules/Forum/pages/forum/get_quotes.php
대조 경로
modules/Forum/pages/forum/view_topic.php
영향
숨김·비공개·직원용 게시물 본문 열람

조사 대상

포럼처럼 같은 객체를 여러 화면에서 읽는 애플리케이션에서는 object-level authorization이 모든 경로에 같은 방식으로 적용되는지 먼저 봤습니다. 특히 자동완성, 미리보기, 인용, export처럼 본 화면을 보조하는 endpoint를 따로 추적했습니다.
get_quotes.php는 세션 로그인만 확인한 뒤 Forum::getIndividualPost()를 호출했습니다. 반면 view_topic.php에는 포럼 공개 여부와 view_other_topics 같은 권한 검사가 있었습니다. backend helper도 호출자의 권한을 자체적으로 확인하지 않았습니다.
같은 사용자가 정상 화면에서 볼 수 없는 게시물을 보조 endpoint로는 읽을 수 있는가?

원인 분석

문제의 핵심은 SQL이나 ID 예측 가능성 자체가 아니었습니다. post ID가 서버에서 정상적으로 존재하는 글을 가리키더라도, 해당 사용자가 그 글의 상위 포럼과 주제를 볼 수 있는지 확인하는 단계가 빠져 있었습니다.
인용 endpoint와 정상 주제 화면은 마지막에 같은 게시물 데이터를 읽지만 보안 문맥이 달랐습니다. 정상 화면은 Forum::forumExist()와 권한 정보를 거친 반면 인용 endpoint는 로그인 상태만 보증했습니다. 따라서 backend helper가 안전하다고 가정한 보조 경로에서 권한 경계가 사라졌습니다.
get_quotes.php · 조사 당시 핵심 흐름을 단순화한 발췌
if (!$user->isLoggedIn()) { die(); } $post_id = Input::get('post'); $post = $forum->getIndividualPost($post_id); return $post->post_content; // forum visibility / view_other_topics 확인 없음
입력에서 영향까지의 경로
  1. 저권한 사용자가 로그인합니다.
  1. 공격자가 post ID를 지정해 인용 endpoint를 호출합니다.
  1. endpoint는 로그인 상태만 확인합니다.
  1. helper가 권한 문맥 없이 게시물 레코드를 반환합니다.
  1. 숨겨진 글의 본문이 응답에 포함됩니다.

재현 및 검증

숨겨진 포럼에 식별 가능한 TOP SECRET 문자열을 넣은 게시물을 만들고, 접근 권한이 없는 일반 회원 세션을 준비했습니다. 동일한 쿠키를 사용해 정상 주제 URL과 인용 endpoint를 순서대로 호출했습니다.
이 비교는 인증 실패나 세션 오류를 배제하기 위한 것이었습니다. 정상 공개 게시물의 인용이 동작하는 것도 확인해 endpoint 자체가 깨진 것이 아니라, 숨겨진 객체에 대한 필터만 빠졌음을 구분했습니다.
$ curl -i -b member.cookie /forum/topic/2 $ curl -i -b member.cookie '/forum/get_quotes?post=2'
검사
입력·조건
관찰
의미
정상 화면
일반 회원 → 숨긴 topic
403 Forbidden
계정에 숨긴 포럼 권한이 없음
공개 대조군
일반 회원 → 공개 post 인용
200과 공개 본문
세션과 endpoint가 정상
취약 경로
일반 회원 → 숨긴 post 인용
200TOP SECRET
객체 권한 없이 본문 반환
같은 일반 회원 세션에서 관찰한 응답
> GET /forum/topic/2 < HTTP/1.1 403 Forbidden > GET /forum/get_quotes?post=2 < HTTP/1.1 200 OK < ... TOP SECRET ...

판단 변화

로그인 검사

처음에는 endpoint가 isLoggedIn()을 확인하므로 보호된 경로처럼 보였습니다. 하지만 이 검사는 누가 호출했는지만 확인할 뿐, 그 사용자가 요청한 post를 볼 수 있는지는 말해주지 않습니다. 판단 기준을 endpoint 인증 여부에서 객체 단위 권한 검사 여부로 바꿨습니다.

ID 열거

게시물 ID를 순차적으로 대입할 수 있다는 사실만으로는 취약점이 아닐 수 있습니다. 그래서 ID 예측 가능성을 주장하기보다, 존재를 이미 아는 특정 숨김 게시물 하나를 정상 화면과 보조 endpoint에서 대조해 권한 차이를 증명했습니다.

영향 범위

확인한 응답은 게시물 본문 읽기였습니다. 글 수정이나 관리자 권한 획득으로 확대하지 않았습니다. 공개 기록의 공동 기여도 그대로 유지해 이 페이지 역시 단독 발견으로 표현하지 않았습니다.

영향과 수정

저권한 인증 사용자는 post ID를 지정해 자신에게 보이지 않는 포럼의 게시물 내용을 읽을 수 있었습니다. staff-only 토론이나 비공개 포럼에 민감한 내용이 있을 경우 기밀성에 직접 영향을 줍니다.

확인한 범위

  • 동일 세션에서 정상 화면은 403, 인용 endpoint는 본문 반환
  • 숨김 게시물의 텍스트 노출
  • 인증된 저권한 사용자에게서 재현

제외한 범위

  • 비인증 원격 접근
  • 게시물 변경·삭제
  • 관리자 권한 상승

수정

2.2.5에서는 인용할 게시물을 반환하기 전에 정상 주제 보기와 동등한 forum/topic 권한을 확인하도록 수정됐습니다. 보조 endpoint가 backend helper의 반환값을 그대로 신뢰하지 않게 하는 것이 핵심입니다.

분석 기준과 증거 보존

항목
최종 감사 결과
소스 기준
NamelessMC checkout ba6d81b77cd21358da091ea2941dd965ad7ae3b1
원본 검증
일반 forum view와 quote endpoint의 권한 경로 비교, 숨김 post ID 직접 요청과 응답 확인
GitHub 보존 상태
Public 저장소 main의 감사 commit c04cacf; evidence 6개와 root manifest.json에 size·SHA-256 고정
무결성
사례별 SHA256SUMS 검증 통과, root manifest의 모든 file hash와 실제 파일 일치, README 상대 링크 확인 완료
보존 경계·제약
원본 작업 session, 인증 cookie와 계정 정보는 제외
감사 완료
2026-08-23 · Docker/로컬 원본 대조 후 GitHub push 완료

관련 파일

2026-08-23 최종 감사

공개 advisory 원문과 CVE 레코드, 조사한 세 소스 파일을 그대로 두었습니다. 파일은 당시 흐름을 다시 대조할 때 사용합니다.

느낀 점

권한 검사는 로그인 화면이나 controller 입구에 한 번 존재한다고 끝나지 않았습니다. 동일한 객체를 읽는 모든 경로가 같은 정책을 적용하는지가 더 중요했습니다. 이후 웹 애플리케이션을 볼 때 본 화면보다 인용, 미리보기, export처럼 짧은 보조 endpoint를 먼저 비교하게 됐습니다.
또한 재현을 ‘비밀 글이 보였다’로 끝내지 않고 같은 쿠키로 403과 200을 나란히 남긴 것이 설명력을 크게 높였습니다. 대조군 하나가 인증 문제, 데이터 준비 문제, 권한 문제를 분리해 주었습니다.