📄 2026.02.09 (Day 73) - 파일 업로드, 인증/인가, 파라미터 변조 취약점
1. 핵심 개념 정리
파일 업로드 취약점 심화
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 1 | WebShell 업로드 | jsp, jspx 등 실행 가능한 파일을 업로드하여 서버 제어 | 시스템 장악, 데이터 유출, 추가 공격의 거점 확보 |
| 2 | 파일명 무작위화 우회 | UUID로 파일명 변경해도 다운로드 경로로 직접 접근 | orgFileName 파라미터로 원본 확장자 유지 가능 |
| 3 | 업로드 경로 노출 | download.jsp에 filePath, fileName 파라미터로 실제 경로 노출 | 경로 추측 없이 정확한 WebShell 위치 파악 가능 |
| 4 | 확장자 필터링 우회 | .jsp, .jspx, .jspf 등 다양한 JSP 실행 가능 확장자 존재 | 단순 .jsp만 차단하면 .jspx로 우회 가능 |
| 5 | 직접 접근 경로 탐색 | /data/files/, /files/ 등 여러 경로 시도로 실행 가능 경로 발견 | 업로드 디렉토리가 웹 루트 내부에 있으면 직접 실행 가능 |
불충분한 인증 및 인가
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 6 | 인증 vs 인가 | 인증은 신원 확인, 인가는 권한 확인 | 로그인(인증)만으로는 부족, 각 작업마다 권한(인가) 검증 필요 |
| 7 | 프로세스 검증 누락 | 중간 단계를 건너뛰고 최종 단계 직접 접근 | 비밀글 비밀번호 확인 없이 view.jsp 직접 접근 |
| 8 | 권한 레벨 미검증 | 사용자 레벨 확인 없이 고급 자료 다운로드 허용 | 레벨 2 자료실인데 레벨 1 사용자가 URL로 직접 접근 |
| 9 | 파라미터 기반 인가 | 서버가 클라이언트 파라미터(권한, ID)를 신뢰하여 처리 | board=admin, author=admin 등 파라미터 조작으로 권한 우회 |
| 10 | 백엔드 검증 부재 | 프론트엔드에서만 검증, 서버는 요청을 그대로 신뢰 | Burp Suite로 요청 가로채서 파라미터 변조 |
파라미터 변조 공격
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 11 | Negative Injection | 음수 입력으로 로직 우회 또는 금액 증가 | 배팅액을 음수로 설정하여 지면 오히려 돈 증가 |
| 12 | Integer Overflow | int 범위(-21억~21억) 초과 시 값 반전 | 42억 입력 시 음수로 변환되는 현상 악용 |
| 13 | 가격 조작 | 클라이언트에서 전송하는 가격을 서버가 신뢰 | 실제 가격 대신 1원으로 변조하여 구매 |
| 14 | 수량 조작 | 재고 확인 없이 클라이언트 수량 신뢰 | count=-1000으로 설정하여 총액을 음수로 |
| 15 | 작성자 변조 | 게시글 작성 시 author 파라미터 조작 | author=admin으로 설정하여 관리자 글로 위장 |
2. 실습 내용 정리
실습 1-1: WebShell 업로드 및 직접 접근 (문제 5번)
목표: JSP WebShell을 업로드하고 여러 경로를 시도하여 실행
실습 환경:
- 대상 시스템: https://lab.eqst.co.kr:8440
- 업로드된 파일: 19f72501-bbb2-4b36-a71e-d94ed8679d1d.jsp
- 원본 파일명: test.jsp
실습 단계:
-
test.jsp — 기본 WebShell 동작 원리
- page import: java.io.*
- cmd 파라미터로 명령 수신
- Runtime.getRuntime().exec(cmd) 로 명령 실행
- 결과를 BufferedReader 로 읽어 출력
-
파일 업로드 후 다운로드 링크 확인
- 다운로드 URL 예시: https://lab.eqst.co.kr:8440/data/download.jsp?filePath=/files/qna/20260206/ &fileName=19f72501-bbb2-4b36-a71e-d94ed8679d1d.jsp &orgFileName=test.jsp
-
다양한 직접 접근 경로 시도
- 시도 1: /data/files/qna/20260206/test.jsp → 404 Not Found
- 시도 2: /files/qna/20260206/test.jsp → 404 Not Found
- 시도 3: /data/files/qna/20260206/19f72501-bbb2-4b36-a71e-d94ed8679d1d.jsp → 404 Not Found
- 시도 4: /files/qna/20260206/19f72501-bbb2-4b36-a71e-d94ed8679d1d.jsp → WebShell 실행 성공!
-
WebShell로 명령 실행
- ?cmd=whoami → 출력: tomcat
- ?cmd=ls -la /var/www/html → 웹 루트 디렉토리 목록 출력
- ?cmd=cat /etc/passwd → 시스템 사용자 목록 출력
확인 항목:
- 파일 업로드 시 확장자 검증 여부
- 업로드 디렉토리의 스크립트 실행 권한 설정
- 파일명 무작위화 적용 여부 (UUID 사용)
- 직접 접근 가능한 경로 존재 여부
보안 인사이트:
- 파일명을 UUID로 변경해도 경로가 예측 가능하면 무의미
- download.jsp의 파라미터에서 실제 저장 경로가 노출됨
- /files/ 디렉토리가 웹 루트 내부에 있어 직접 실행 가능
- 날짜 기반 디렉토리 구조(20260206)는 예측 가능
실습 1-2: .jspx 확장자 우회 (문제 6번)
목표: .jsp 필터링을 .jspx 확장자로 우회
실습 환경:
- 대상 시스템: https://lab.eqst.co.kr:8441
- 업로드된 파일: f9a28533-fbaf-4f7b-a5f0-e9c724033e42.jspx
- 원본 파일명: test.jspx
실습 단계:
-
test.jspx — JSPX 형식 WebShell 구조
- XML 기반 JSP 포맷
- jsp:root 태그 + jsp:scriptlet 태그로 명령 실행
- 동작 원리는 .jsp와 동일
-
파일 업로드 후 경로 확인
- 다운로드 URL에서 .jspx 확장자 그대로 저장된 것 확인
-
직접 접근 시도
- /data/files/qna/20260206/f9a28533-fbaf-4f7b-a5f0-e9c724033e42.jspx → WebShell 실행 성공!
Tomcat/JSP 서버에서 실행되는 확장자:
- .jsp — 기본 JSP 파일
- .jspx — XML 형식 JSP
- .jspf — JSP Fragment (포함 파일)
- .jsv — JSP Variant (일부 서버)
- .jsw — JSP Wrapper (일부 서버)
블랙리스트 필터링의 한계:
- .jsp만 차단하면 .jspx, .jspf로 우회 가능
- 대소문자 변형: .Jsp, .JSP, .JsP
- 더블 확장자: .jsp.txt (일부 서버에서 .jsp로 실행)
탐지 패턴:
- .jsp 외 다른 JSP 관련 확장자 업로드 시도
- XML 형식의 JSPX 파일 패턴 탐지
- 업로드된 파일 내 Runtime.getRuntime().exec() 패턴
방어 방법:
- 화이트리스트 방식: jpg, png, pdf만 허용
- 파일 내용(Magic Number) 검증
- 업로드 디렉토리에서 스크립트 실행 권한 제거
- 업로드 디렉토리를 웹 루트 외부에 배치
실습 2-1: 프로세스 검증 누락 - 비밀글 직접 접근
목표: 비밀번호 확인 단계를 건너뛰고 비밀글 직접 조회
정상 프로세스: write.jsp → list.jsp → viewcheckpw.jsp?id=1&pw=1234 → view.jsp?id=1
공격: view.jsp?id=1 직접 접근
실습 단계:
-
정상적인 비밀글 조회 프로세스
- GET /board/list.jsp
- GET /board/viewcheckpw.jsp?id=1
- POST /board/viewcheckpw.jsp (pw=1234)
- GET /board/view.jsp?id=1 (비밀번호 일치 시 리다이렉트)
-
공격 — 프로세스 우회
- 비밀번호 확인 없이 view.jsp 직접 접근
- 결과: 비밀글 내용 노출!
취약한 코드 구조 (view.jsp):
- request.getParameter(“id”) 로 게시글 ID 가져옴
- 문제: 비밀번호 확인 여부를 검증하지 않음
- 누구나 URL로 직접 접근 가능
안전한 코드 구조:
- viewcheckpw.jsp에서 비밀번호 확인 성공 시
- session.setAttribute(“verified_post_” + id, true) 저장
- view.jsp에서
- session.getAttribute(“verified_post_” + id) 확인
- null이거나 false면 viewcheckpw.jsp로 리다이렉트
- 조회 후 session.removeAttribute() 로 일회성 인증 처리
프로세스 검증 누락 유형:
- 은행 이체: 1단계 → 5단계 직접 접근 (2·3·4단계 우회)
- 결제: 장바구니 → 결제 완료 직접 접근 (결제 우회)
- 회원가입: 약관동의 → 가입완료 직접 접근 (본인인증 우회)
- 레벨 제한: 레벨1 → 레벨2 자료실 직접 접근 (권한 우회)
방어 원칙:
- 각 단계마다 이전 단계 완료 여부를 세션에서 검증
- 단순 URL 접근으로 중요 단계 우회 불가하도록 설계
- 최종 단계에서 전체 프로세스 재검증
- 민감 작업은 재인증(비밀번호 재입력) 필수
실습 2-2: 권한 레벨 미검증 - 고급 자료 무단 다운로드
목표: 레벨 1 사용자가 레벨 2 자료실 파일 다운로드
실습 단계:
- 정상 접근 — 레벨 1 계정으로 로그인
- 레벨 2 자료실 접근 시도 → “권한이 부족합니다” 메시지
- 공격 — 다운로드 URL 직접 입력
- GET /board/lv2/download?file=대외비문서.docx
- 결과: 파일 다운로드 성공! (권한 검증 없음)
취약한 코드 구조 (download.php):
- 로그인 여부만 확인 ( session[‘user_id’] 존재 여부)
- 문제: 사용자 레벨을 확인하지 않음
- 파일 경로를 클라이언트에서 받아 그대로 사용
안전한 코드 구조:
- 로그인 여부 확인
- 사용자 레벨 확인 ( user_level vs required_level 비교)
- 파일 경로 대신 파일 ID 사용 (경로 추측 방지)
- DB에서 파일별 요구 레벨 조회
- 다운로드 로그 기록
권한 검증이 필요한 시점:
- 페이지 접근 시 (list.jsp)
- 게시글 조회 시 (view.jsp)
- 파일 다운로드 시 (download.php)
- 수정/삭제 작업 시 (edit.jsp, delete.jsp)
- 각 단계마다 독립적으로 권한 검증 필요!
실습 3-1: Negative Injection - 음수 배팅 공격
목표: 배팅액을 음수로 설정하여 지면 오히려 돈이 증가하도록 조작
실습 환경:
- 초기 보유금액: 1,000,000원
- 배팅 시스템: 이기면 배팅액×2, 지면 배팅액 차감
- 취약점: 음수 입력 검증 부재
정상적인 배팅 로직:
- betting_amount = 10000원 배팅
- 승리: balance = balance + (betting_amount × 2) = 1,020,000원
- 패배: balance = balance - betting_amount = 990,000원
공격 — 음수 배팅:
- betting_amount = -10,000,000원
- 보유금액 확인: 1,000,000 >= -10,000,000 → True (통과!)
- 패배 시: balance = 1,000,000 - (-10,000,000) = 11,000,000원
- 결과: 지는 것이 이득! 1천만원 증가
Burp Suite 파라미터 변조:
- 정상 요청: amount=10000&game_id=123
- 변조 요청: amount=-10000000&game_id=123
취약한 코드 문제점:
- 문제 1: 음수 검증 없음
- 문제 2: 절댓값 비교 없음
- 문제 3: balance -= betting_amount 에서 음수 빼기 = 더하기
안전한 코드 구조:
- betting_amount <= 0 이면 400 에러 반환
- MAX_BET = 1,000,000 등 최대 배팅액 제한
- balance < betting_amount 이면 잔액 부족 에러
- 계산 결과 if balance < 0 이면 0으로 처리 + 보안 이벤트 로그
음수 입력 취약점이 발생하는 영역:
- 쇼핑몰 수량: count=-100 → 총액이 음수로
- 포인트 사용: point=-10000 → 포인트 증가
- 할인 쿠폰: discount=-5000 → 가격 증가
- 송금: amount=-1000000 → 받는 사람 돈 차감
실습 3-2: 파라미터 변조 - 작성자 조작 (쇼핑몰 12, 13번)
목표: 일반 사용자가 admin 계정으로 글 작성 및 삭제
공격 시나리오:
- 정상 글 작성: title=문의사항&content=배송은 언제?&author=user1
- 변조 글 작성: title=긴급공지&content=시스템 점검&author=admin&board=notice
- 결과: 일반 사용자가 admin 이름으로 공지사항 작성!
게시글 삭제 요청 변조:
- 변조: id=123&author=admin
- 서버가 author 파라미터를 신뢰하면 admin 글도 삭제 가능
취약한 코드 핵심 문제:
- $author = $_POST[‘author’] — 클라이언트 값을 그대로 사용
- $board = $_POST[‘board’] — 게시판 종류 검증 없음
- 일반 사용자가 board=notice 로 공지사항 작성 가능
안전한 코드 구조:
- 작성자는 세션에서 가져오기: $author = $_SESSION[‘user_id’]
- 클라이언트에서 받은 author 파라미터는 완전 무시
- 게시판 권한 매핑:
- notice → 관리자(레벨 9)만 허용
- qna, free → 로그인 사용자 허용
- 삭제 시 DB에서 게시글 작성자 조회 후 본인 여부 확인
- 모든 중요 작업 로그 기록
파라미터 변조 방지 원칙:
- author, role, level 등은 절대 파라미터로 받지 않음
- 세션 정보와 DB 정보 교차 검증
- 권한 변경 작업은 재인증 필수
- 클라이언트 JavaScript 검증은 우회 가능 → 서버에서만 검증
3. 취약점 비교 분석
인증 vs 인가 차이
| 구분 | 인증 (Authentication) | 인가 (Authorization) | 실무 적용 |
|---|---|---|---|
| 정의 | “당신은 누구인가?” | “당신은 무엇을 할 수 있는가?” | 둘 다 필수적으로 검증 |
| 검증 대상 | 신원 확인 (ID/PW) | 권한 확인 (Role, Level) | 각 요청마다 독립적으로 검증 |
| 예시 | 로그인 성공/실패 | 관리자 페이지 접근 가능/불가 | 로그인 후에도 매번 권한 확인 |
| 우회 시 영향 | 타인 계정 탈취 | 권한 없는 작업 수행 | 둘 다 치명적 |
파라미터 변조 유형별 비교
| 유형 | 변조 대상 | 공격 예시 | 영향 | 방어 방법 |
|---|---|---|---|---|
| 금액 조작 | price, amount | price=1 (실제 10000원) | 재정 손실 | 서버에서 가격 재계산 |
| 수량 조작 | count, quantity | count=-100 | 음수 총액 | 양수 검증, 재고 확인 |
| 권한 조작 | role, level, author | author=admin | 권한 탈취 | 세션에서만 가져오기 |
| 게시판 조작 | board, category | board=notice | 공지사항 도배 | 화이트리스트 + 권한 검증 |
4. 심화 분석
Integer Overflow 공격 원리
| 구분 | signed int | unsigned int | 오버플로우 결과 |
|---|---|---|---|
| 범위 | -2,147,483,648 ~ 2,147,483,647 | 0 ~ 4,294,967,295 | 범위 초과 시 반전 |
| 최댓값+1 | 2,147,483,647 + 1 = -2,147,483,648 | 4,294,967,295 + 1 = 0 | 양수 → 음수 |
| 최솟값-1 | -2,147,483,648 - 1 = 2,147,483,647 | 0 - 1 = 4,294,967,295 | 음수 → 양수 |
| 공격 활용 | 큰 양수 입력 → 음수로 변환 | - | 가격/수량 검증 우회 |
Integer Overflow 공격 시나리오:
- count = 2,147,483,647 입력
- total = 10000 × 2,147,483,647 = 21,474,836,470,000 (범위 초과)
- Overflow 발생 → 음수로 변환
- total < balance → 구매 성공
- balance -= (-음수) → balance 증가!
쇼핑몰 가격 계산 취약 시나리오
공격 시나리오 1 — 가격 조작:
- POST /purchase: id=61&count=1&price=1
- 실제 10,000원 상품을 1원에 구매
공격 시나리오 2 — 수량 음수:
- id=61&count=-100&price=10000
- total = 10000 × (-100) + 3000 = -997,000
- balance -= (-997,000) → balance 증가!
공격 시나리오 3 — Integer Overflow:
- id=61&count=2,147,483,647&price=10000
- total이 오버플로우로 음수 변환
안전한 구매 처리 흐름:
- count <= 0 이면 400 에러 반환
- MAX_COUNT 초과 시 에러 반환
- 가격은 DB에서 조회 (클라이언트 값 무시!)
- 재고 확인 (count > stock 이면 에러)
- total > MAX_SAFE_INT 이면 에러
- 잔액 확인
- 트랜잭션으로 재고 차감 + 잔액 차감 + 주문 기록 원자적 처리
5. 실무/보안 적용
보안 전문가 관점 - 파일 업로드 탐지 및 대응
| 단계/유형 | 탐지 포인트 | 로그 예시 | 대응 방안 |
|---|---|---|---|
| WebShell 업로드 | jsp, jspx, php 등 실행 파일 업로드 · Runtime.exec() 패턴 · Base64 인코딩된 악성 코드 | POST /upload with test.jsp | 파일 내용 검사(시그니처 기반) · 업로드 디렉토리 실행 권한 제거 · 웹 루트 외부 배치 |
| 직접 접근 시도 | /files/, /upload/ 경로 직접 요청 · UUID 파일명 스캔 패턴 · 날짜 기반 경로 추측 | GET /files/qna/20260206/*.jsp | 디렉토리 인덱싱 비활성화 · URL 접근 제어 · 다운로드는 download.php 경유만 허용 |
| 확장자 우회 | .jspx, .jspf, .php5 등 변형 · 더블 확장자 · 대소문자 변형 | Upload test.jspx | 화이트리스트 방식 · Magic Number 검증 · 모든 변형 확장자 차단 |
인증/인가 방어 체크리스트
권한 검증 데코레이터 활용 개념 (Django 예시):
- require_level(min_level) 데코레이터로 모든 뷰에 레벨 검증 자동화
- 로그인 확인 → 레벨 확인 → 미달 시 보안 이벤트 로그 기록 후 403 반환
- 사용 예시: @require_level(2) 로 레벨 2 이상만 접근 허용
PHP 프로세스 검증 핵심:
- is_secret 글 조회 시 session에 “verified_post_{id}” 존재 여부 확인
- 인증 시각 확인 (5분 이내만 유효)
- 미인증 시 비밀번호 확인 페이지로 리다이렉트
- 조회 후 session 속성 제거 (일회성 인증)
종합 보안 점검 체크리스트
파일 업로드 보안:
- 확장자 화이트리스트 적용 (jpg, png, pdf만)
- 파일 내용 Magic Number 검증
- 업로드 디렉토리 스크립트 실행 권한 제거
- 업로드 디렉토리를 웹 루트 외부에 배치
- 파일명 UUID로 무작위화
- 파일 크기 제한
- 바이러스 스캔 수행
인증/인가 보안:
- 모든 페이지에서 로그인 여부 확인
- 각 작업마다 권한 레벨 검증
- 프로세스 각 단계마다 이전 단계 완료 여부 확인
- 세션에 인증 상태 저장
- 중요 작업은 재인증 필수
- 권한 변경 시도 로그 기록
파라미터 변조 방지:
- 모든 금액/수량 입력값 양수 검증
- 가격은 서버에서 DB 조회 (클라이언트 값 무시)
- author, role, level은 세션에서만 가져오기
- Integer Overflow 방지 (범위 검증)
- 최소값/최대값 제한
- 화이트리스트 기반 파라미터 검증
6. 배운 점 및 인사이트
새로 알게 된 점
- 파일명 무작위화의 한계: UUID로 파일명을 변경해도 download.jsp의 파라미터에서 실제 경로가 노출되면 무의미하다. 파일 업로드 보안은 파일명 변경만으로는 부족하며, 실행 권한 제거와 웹 루트 외부 배치가 필수다.
- .jspx 확장자의 위험성: .jsp만 차단하면 .jspx, .jspf 등 다른 JSP 실행 가능 확장자로 우회할 수 있다. 블랙리스트 방식의 확장자 필터링은 항상 우회 가능성이 있으며, 화이트리스트 방식이 안전하다.
- 프로세스 검증 누락의 심각성: 비밀글 비밀번호 확인 단계를 건너뛰고 view.jsp에 직접 접근하는 것처럼, 각 단계마다 독립적인 검증이 없으면 중요 단계를 우회할 수 있다.
- Negative Injection의 교묘함: 배팅액을 음수로 설정하면 지는 것이 오히려 이득이 되는 상황이 발생한다. balance - (-10000000) = balance + 10000000처럼 음수 빼기가 더하기로 작용하는 것을 악용한 공격이다.
- 클라이언트 파라미터의 위험성: author, price, role 등 중요한 값을 클라이언트 파라미터로 받으면 Burp Suite로 쉽게 변조할 수 있다. 이런 값들은 반드시 세션이나 DB에서 가져와야 하며, 클라이언트 입력을 절대 신뢰하면 안 된다.
이전 학습과의 연결고리
- Path Traversal과 파일 업로드 연계: 이전에 학습한 Path Traversal로 시스템 파일을 읽었다면, 파일 업로드 취약점으로 WebShell을 올려 시스템을 완전히 장악할 수 있다.
- CSRF와 파라미터 변조: CSRF로 사용자를 속여 요청을 보내게 한 후, 파라미터 변조로 금액이나 권한을 조작하는 연계 공격이 가능하다.
- SQL Injection과 인증 우회: 이전 SQL Injection에서 OR 1=1 로 인증을 우회했다면, 이번에는 프로세스 검증 누락으로 중간 단계를 건너뛰는 방식이다.
실무 적용 아이디어
보안 전문가 관점:
- WebShell 탐지 시그니처 작성: Suricata/Snort에서 Runtime.getRuntime().exec(), eval(), system() 등 위험한 함수 호출 패턴을 탐지하는 룰 작성.
- 파라미터 변조 이상 징후 탐지: SIEM에서 동일 사용자가 짧은 시간 내 author 파라미터를 여러 번 변경하거나, 음수 금액/수량을 입력하는 패턴 탐지.
- 권한 상승 시도 모니터링: 일반 사용자가 admin 게시판에 글을 작성하거나, 레벨 1이 레벨 2 자료를 다운로드하는 시도를 실시간 탐지하여 알림.
개발자 관점:
- 파일 업로드 보안 강화: 업로드 디렉토리는 /var/uploads 같이 웹 루트 완전 외부에 배치하고, 다운로드는 download.php를 경유하여 파일 내용을 스트리밍.
- 모든 중요 값은 서버에서 결정: 가격, 작성자, 권한 등은 클라이언트 파라미터를 완전히 무시하고 서버의 세션과 DB에서만 가져오기.
- 프로세스 상태 관리: 은행 이체처럼 여러 단계를 거치는 작업은 세션에 step_completed 배열을 유지하여 각 단계 완료 여부를 추적.
7. Quick Reference
파일 업로드 보안 핵심 코드 패턴
파일 다운로드 안전 구조:
- 파일 ID로 DB 조회 (경로 직접 사용 금지)
- 권한 확인 (required_level vs user_level 비교)
- 웹 루트 외부 경로: /var/uploads/…
- os.path.realpath() 로 Path Traversal 방지
- 다운로드 로그 기록
구매 처리 안전 구조:
- count <= 0 또는 count > 1000 이면 에러
- 가격은 DB에서 조회 (클라이언트 값 무시!)
- 재고 확인
- 총액 오버플로우 검증 (total > MAX_SAFE_INT 이면 에러)
- 트랜잭션으로 원자적 처리
보안 검증 체크리스트
| 구분 | 검증 항목 | 검증 방법 | 실패 시 조치 |
|---|---|---|---|
| 파일 업로드 | 확장자, Magic Number, 크기 | 화이트리스트, 파일 헤더 검사 | 업로드 거부, 로그 기록 |
| 인증 | 로그인 여부, 세션 유효성 | 세션 존재 확인, 타임아웃 검증 | 로그인 페이지 리다이렉트 |
| 인가 | 권한 레벨, 본인 여부 | DB 레벨 조회, 작성자 확인 | 403 Forbidden, 접근 거부 |
| 파라미터 | 타입, 범위, 음수 여부 | 양수 검증, 최소/최대값 확인 | 400 Bad Request, 거부 |
8. 트러블슈팅
| 문제 | 원인 | 해결 방법 |
|---|---|---|
| WebShell 업로드 후 404 에러 | 실제 저장 경로와 접근 경로 불일치 | download.jsp 파라미터에서 정확한 경로 확인 · /data/files/, /files/ 등 여러 경로 시도 · 웹 서버 설정에서 Alias 확인 |
| .jsp 필터링으로 업로드 차단됨 | 블랙리스트에 .jsp만 등록 | .jspx, .jspf, .jsv 등 변형 확장자 시도 · 대소문자 변형 (.Jsp, .JSP) · Null Byte: .jsp%00.jpg |
| 비밀글을 직접 접근해도 보임 | view.jsp에서 비밀번호 확인 여부 미검증 | 세션에 verified_post_{id} 저장 · view.jsp에서 세션 확인 · 미인증 시 checkpw.jsp로 리다이렉트 |
| 일반 사용자가 admin 글 작성 가능 | author 파라미터를 서버가 신뢰 | author는 파라미터로 받지 않고 세션에서 가져오기 · $author = $_SESSION[‘user_id’] · 파라미터 author는 완전히 무시 |
| 음수 금액으로 돈 증가 | 음수 입력 검증 부재 | if amount <= 0: raise ValueError · 최소값 검증: amount > 0 · 계산 결과도 검증: if total < 0 |
Today’s Insight:
파일 업로드, 인증/인가, 파라미터 변조는 모두 서버가 클라이언트 입력을 신뢰하는 것에서 발생하는 취약점이다. 파일 업로드에서는 확장자와 파일명을, 인증/인가에서는 권한과 프로세스 단계를, 파라미터 변조에서는 가격과 수량을 클라이언트가 제공한다고 믿는 순간 공격에 노출된다. 보안의 핵심 원칙은 “클라이언트를 절대 신뢰하지 말라"는 것이다. 모든 중요한 값은 서버의 세션과 DB에서만 가져오고, 클라이언트는 단지 ID나 선택 사항만 전달하도록 설계해야 한다. 또한 각 단계, 각 요청마다 독립적으로 권한과 프로세스를 검증하여 어떤 단계도 건너뛸 수 없도록 해야 한다. 프론트엔드 검증은 사용자 편의를 위한 것일 뿐, 백엔드에서 모든 검증을 다시 수행하는 것이 필수다.