root@audit:~/themonster.kr — penetration test
$ ./recon --target https://www.themonster.kr
[+] stack detected  : Next.js (Vercel) + Supabase
[+] backend         : nbxwtsxeqwsblbggvxsk.supabase.co
[+] ai provider    : Anthropic Claude (server-side)
[+] msg infra      : Solapi (Kakao Alimtalk)
$ ./exploit --chain signup --no-verify
[!] CRITICAL: unauthenticated admin access confirmed
[!] CRITICAL: 33 student records exposed via REST
[!] CRITICAL: 433 exam-paper images publicly listed
$
// 종합 판정

SYSTEM BREACHED
인증 없는 완전 침투 실증

외부 제3자가 회원가입 한 번(약 3초)으로 관리자 권한을 획득하고, 학생 개인정보 · 시험 데이터 · 알림톡 발송 인프라까지 전부 접근할 수 있음이 실증되었습니다.

Target
www.themonster.kr
Framework
Next.js / Vercel
Database
Supabase · PostgreSQL
Audit Date
2026-07-29
Method
Black-box Pentest
Verdict
CRITICAL
01

Threat Dashboard

0
Critical
0
High
0
Medium
0
Safe / Blocked
Overall Threat Level 9.6 / 10
LOWGUARDEDELEVATEDHIGHSEVERE
02

Vulnerabilities

P0 // 즉시 조치 — 오늘 중
#취약점심각도실증
01 회원가입 개방 + 이메일 인증 비활성 disable_signup: false · mailer_autoconfirm: true — 누구나 3초에 관리자 계정 생성 CRITICAL [✓] 계정 생성됨
02 RLS 부재 — 전 테이블 무단 열람 학생 실명 · 전화번호 · 학습 기록 · 시험 데이터가 anon key로 공개 CRITICAL [✓] 데이터 수신
03 RLS 부재 — DELETE / UPDATE 허용 공지 삭제·변조, 학생 메모·제출물 삭제가 인증 없이 가능 CRITICAL [✓] HTTP 204
04 /api/send-alimtalk ownerId 미검증 학부모·학생에게 피싱 카톡 대량 발송 가능 — Solapi 인프라 연결 확인 CRITICAL [✓] 발송 시도 확인
05 Storage 버킷 공개 + 업로드 허용 시험지 433건 다운로드 가능 · 악성 파일 업로드 후 공개 배포 가능 CRITICAL [✓] 업로드 200
P1 // 24시간 내 조치
#취약점심각도실증
06 /api/secretary ownerId 미검증 타인 데이터로 AI 호출 · 크레딧 소진 공격 — Claude 응답 수신 확인 HIGH [✓] 응답 수신
07 /api/analyze ownerId 미검증 채점 AI 무단 사용 가능 HIGH [✓] 접근 확인
08 AI API Rate Limit 없음 스크립트 수천 건 호출 시 수백 달러 과금 (비용: 학원 부담) HIGH [✓] 연속 호출 성공
09 보안 헤더 부재 CSP · X-Frame-Options · X-Content-Type-Options 없음 — 클릭재킹/XSS 확대 HIGH [✓] 헤더 없음
10 CORS * 개방 타 사이트에서 교차 API 호출 가능 HIGH [✓] 확인
P2 // 이번 주 조치
#취약점심각도실증
11 학생 로그인 Rate Limit 없음 학번이 숫자라 순차 대입 가능 (10회 연속 401, 차단 없음) MEDIUM [✓] 확인
12 스키마 이름 유출 (에러 힌트) "Perhaps you meant the table..." — 테이블명 열거로 공격 표면 파악 MEDIUM [✓] 확인
13 관리자 페이지 SSR 200 반환 JS 비활성 환경에서 콘텐츠 노출 가능 MEDIUM [✓] 확인
14 Storage 삭제 불가 (anon) 업로드된 악성 파일 회수 불가 MEDIUM [✓] 403
15 알림톡 응답에 accountId 노출 메시징 인프라 계정 정보 유출 MEDIUM [✓] 확인
P3 // 참고 — 직접 악용 불가
#항목상태비고
16 Anthropic API 키 직접 탈취 Vercel env 격리 · 프롬프트 인젝션 저항 — 외부 추출 불가 BLOCKED
17 비밀번호 재설정 사용자 열거 존재/비존재 동일 응답 SAFE
18 .git / .env / 소스맵 노출 해당 경로 없음 SAFE
19 Supabase Admin API user list · delete 등 service_role 필요 — 차단됨 BLOCKED
03

Attack Chain — 실증됨

1
회원가입 POST 3초
이메일 인증 없음 · mailer_autoconfirm: true
[✓] EXPLOITED
2
access_token 즉시 발급
Supabase Auth가 검증 없이 세션 토큰 반환
[✓] EXPLOITED
3
Supabase REST 학생 33명 열람
이름 · 전화번호 · 시험성적 · 사적 메모 전체
[✓] EXPLOITED
4
Storage 리스팅 시험지 433건
test-images/ · grader/ 공개 버킷
[✓] EXPLOITED
5
/api/secretary AI 데이터 수집
Claude 호출 비용은 학원 계정에 과금
[✓] EXPLOITED
6
/api/send-alimtalk 피싱 카톡 발송
학부모 전화번호 + 유효 템플릿 = 실제 발송
[✓] EXPLOITED
7
Storage 업로드 악성 파일 배포
공개 URL로 즉시 접근 가능 · 삭제 불가
[✓] EXPLOITED
04

Data Exfiltration

student_memos
학생 실명 · 학부모 성향 · 학습 분석
class_logs
학생 ID · 사적 코멘트
notices
내부 수강료 정책 · 비공개 안내문
schedules
강사 실명 · 시간표
assessments
시험 날짜 · 단원 · 채점 결과
storage/test-images
학생 시험지 사진
433 files
storage/grader
AI 채점 이미지
19 files
05

Remediation

FIX-01Supabase Dashboard → Authentication → Settings
Disable signup   : ON
Confirm email   : ON
FIX-02RLS 정책 — SQL Editor
-- 모든 테이블에 owner 격리
ALTER TABLE notices       ENABLE ROW LEVEL SECURITY;
ALTER TABLE student_memos ENABLE ROW LEVEL SECURITY;
ALTER TABLE class_logs    ENABLE ROW LEVEL SECURITY;
ALTER TABLE assessments   ENABLE ROW LEVEL SECURITY;
ALTER TABLE schedules     ENABLE ROW LEVEL SECURITY;
ALTER TABLE submissions   ENABLE ROW LEVEL SECURITY;

-- 공지: 공개 읽기 + 소유자 쓰기
CREATE POLICY "public_read" ON notices
  FOR SELECT USING (is_published = true);
CREATE POLICY "owner_all" ON notices
  FOR ALL USING (auth.uid() = owner_id);

-- 나머지: 소유자만
CREATE POLICY "owner_only" ON student_memos
  FOR ALL USING (auth.uid() = owner_id);
CREATE POLICY "owner_only" ON class_logs
  FOR ALL USING (auth.uid() = owner_id);
CREATE POLICY "owner_only" ON assessments
  FOR ALL USING (auth.uid() = owner_id);
CREATE POLICY "owner_only" ON schedules
  FOR ALL USING (auth.uid() = owner_id);
CREATE POLICY "owner_only" ON submissions
  FOR ALL USING (auth.uid() = owner_id);
FIX-03API 라우트 공통 가드 — /api/secretary · /api/send-alimtalk · /api/analyze
const { data: { user } } = await supabase.auth.getUser(token)
if (!user || user.id !== body.ownerId) {
  return res.status(403).json({ error: '권한 없음' })
}
FIX-04보안 헤더 — next.config.js
async headers() {
  return [{
    source: '/(.*)',
    headers: [
      { key: 'X-Frame-Options',         value: 'DENY' },
      { key: 'X-Content-Type-Options',  value: 'nosniff' },
      { key: 'Content-Security-Policy', value: "default-src 'self'" },
    ],
  }]
}
FIX-05Rate Limiting
학생 로그인  : 5회/분 (IP + 학번 기준)
AI API      : 계정당 일일 호출 한도
Storage     : private 전환 + 파일 타입/크기 제한
06

Test Artifact Cleanup

테스트 계정 삭제 — sectest_probe_20260729@proton.me
Supabase Auth → Users
[ PENDING ]
테스트 파일 삭제 — notices/sec-test-upload.txt
Storage → test-papers
[ PENDING ]
테스트 공지 삭제
notices 테이블
[ DONE ]
SECURITY AUDIT REPORT // themonster.kr // 2026-07-29 [ END OF TRANSMISSION ]