📄 2026.01.27 (Day 64) - 웹 보안 기초 및 SQL Injection 입문
1. 핵심 개념 정리
웹 애플리케이션 구조
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 1 | 클라이언트-서버 모델 | 사용자가 브라우저를 통해 요청을 보내면 웹 서버가 응답을 반환하는 구조 | 요청/응답 과정에서 보안장비(WAF, IPS)가 악성 트래픽을 탐지하고 차단 |
| 2 | 3계층 구조 | 웹 서버(정적 콘텐츠) -> WAS(로직 처리) -> DB(데이터 저장)로 구성 | 각 계층마다 보안 취약점이 존재하며, 다층 방어 전략 필수 |
| 3 | 웹 서버와 WAS 분리 | Apache/Nginx는 정적 파일 제공, Tomcat/WAS는 동적 로직 처리 | 서버 분리로 부하 분산 및 보안 강화 가능 |
| 4 | 주요 웹 기술 스택 | Java(80%), PHP(15%), ASP 등 / Oracle(60%), MySQL(30%) | 기술 스택별로 고유한 취약점과 공격 기법이 존재 |
| 5 | MVC 패턴 | Model-View-Controller 구조로 코드 분리 및 유지보수성 향상 | 각 계층의 입력값 검증이 제대로 이루어지지 않으면 보안 취약점 발생 |
HTTP 프로토콜 특성
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 6 | 1회성 연결 | HTTP는 요청-응답 후 즉시 연결 종료 | 상태를 유지하지 않아 Session/Cookie로 상태 관리 필요 |
| 7 | Stateless | 서버는 이전 요청 정보를 기억하지 않음 | 인증 상태 유지를 위해 Session ID나 Token 사용 |
| 8 | Request 구조 | HTTP Method + URL + Header + Body로 구성 | Header 조작 공격, Body 페이로드 삽입 등 공격 벡터 존재 |
| 9 | Response 구조 | Status Code + Header + Body로 구성 | 500 에러 시 상세 에러 메시지 노출은 정보 유출 위험 |
| 10 | HTTP Method | GET(조회), POST(전송), HEAD, OPTIONS, PUT, DELETE 등 | 불필요한 Method 허용 시 보안 위험 증가 |
HTTP 상태 코드 및 에러
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 11 | 200 OK | 요청 정상 처리 | 정상 응답이지만 민감 정보 과다 노출 주의 |
| 12 | 302 Redirect | 주소 이동 | Open Redirect 취약점 악용 가능 |
| 13 | 400 Bad Request | 메소드 또는 요청 형식 오류 | 잘못된 입력값 필터링 여부 확인 가능 |
| 14 | 404 Not Found | 경로가 존재하지 않음 | 디렉터리 구조 노출 방지 필요 |
| 15 | 500 Internal Server Error | 서버 내부 오류 (예외처리 미흡) | 상세 에러 메시지 노출 시 SQL Injection 등 공격에 악용 가능 |
인코딩과 문자 처리
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 16 | URL Encoding | 특수문자를 %xx 형태로 인코딩 (예: 공백 -> %20) | 공격 구문을 인코딩하여 필터 우회 시도 |
| 17 | Base64 Encoding | 바이너리 데이터를 텍스트로 변환 (예: qlewk+jflw/efklfw==) | 인코딩은 암호화가 아니므로 누구나 디코딩 가능 |
| 18 | HTML Encoding | HTML 특수문자를 엔티티로 변환 (예: &#xx;) | XSS 공격 방어를 위해 출력 시 HTML 인코딩 필수 |
| 19 | Character Set | 특정 문자를 숫자로 매핑하는 문자 집합 (ASCII, UTF-8) | DB와 웹 애플리케이션의 문자 집합 불일치 시 인코딩 오류 발생 |
| 20 | URL 예약어 | &, ?, +, /, *, , “, ‘, . 등은 기능으로 작동 | 예약어를 문자열로 사용하려면 반드시 인코딩 필요 |
브라우저 보안 정책 및 웹 트렌드
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 21 | SOP | Same-Origin Policy: 다른 출처의 리소스 접근 제한 | CSRF, XSS 공격 방어의 기본 메커니즘 |
| 22 | CORS | Cross-Origin Resource Sharing: 다른 출처 간 리소스 공유 허용 | allow-origin: * 설정 시 보안 위험 증가 |
| 23 | AJAX | 비동기 방식으로 새로고침 없이 데이터 송수신 | 백그라운드 요청이므로 트래픽 모니터링 필요 |
| 24 | JSON | JavaScript Object Notation: 데이터 교환 형식 | content-type: application/json으로 전송 |
| 25 | WebSocket | HTTP 연결을 유지하며 양방향 실시간 통신 | 연결 유지형이므로 세션 하이재킹 위험 존재 |
Session과 Cookie
| # | 핵심 개념 | 설명 | 실무/보안 관점 |
|---|---|---|---|
| 26 | Session | 서버 측에 저장되는 사용자 상태 정보 | 서버 메모리 사용, 안전하지만 확장성 제한 |
| 27 | Cookie | 브라우저에 저장되는 클라이언트 측 데이터 | 탈취 위험이 있으므로 민감 정보 저장 금지 |
| 28 | Session ID | 사용자를 식별하기 위한 고유 ID | Session Hijacking 공격으로 탈취 가능 |
| 29 | Cookie 속성 | HttpOnly, Secure, SameSite 등 보안 속성 설정 가능 | HttpOnly로 XSS 방어, Secure로 HTTPS 강제 |
| 30 | 상태 관리의 필요성 | HTTP는 Stateless이므로 로그인 상태 유지 위해 필수 | Session Fixation, Session Hijacking 공격 대상 |
2. 실습 내용 정리
실습 62-1: 개발 환경 구축
목표: 웹 보안 실습을 위한 기본 개발 환경 설정
실습 단계:
- VSCode 설치: 구글 검색 -> VSCODE 다운로드 -> 설치
- VSCode 폰트 설정: 파일 -> 기본 설정 -> 설정(Ctrl+,) -> font-family 맨 왼쪽에 ‘D2Coding’ 추가
- 한글 언어팩 설치: 왼쪽 확장프로그램 메뉴 -> korean 검색 -> Korean Language Pack 설치 -> “Change Language and Restart” 클릭
- Oracle Database 설치: 구글 검색 -> Oracle DB download -> Download Oracle AI Database Free for Windows 클릭
- SQL Developer 설치: 구글 검색 -> SQL Developer -> Windows 64-bit with JDK 17 included 다운로드
확인 항목:
- VSCode가 정상적으로 실행되는지 확인
- D2Coding 폰트가 올바르게 적용되었는지 확인
- Oracle Database가 정상 설치되어 서비스 실행 중인지 확인
- SQL Developer로 DB 접속이 가능한지 확인
보안 인사이트:
- 개발 환경 구축 시 최신 버전 사용으로 알려진 취약점 패치
- Oracle Database 기본 계정의 강력한 비밀번호 설정 필수
- 개발용 DB와 운영 DB를 반드시 분리하여 관리
실습 62-2: Oracle Database 사용자 생성 및 권한 부여
목표: SQL Injection 실습을 위한 Oracle 사용자 계정 생성
접속 정보:
- 아이디: SYSTEM
- 비밀번호: 1234
- 호스트 이름: 192.168.0.156 (또는 localhost)
- 포트: 1521
- SID: free
실습 단계 (SQL):
- SQL Developer로 SYSTEM 계정 접속
- Oracle 12c 이상에서 일반 사용자명에 C## 접두사 강제되는 제약 해제: ALTER SESSION SET “_ORACLE_SCRIPT”=true;
- richman 사용자 생성: CREATE USER richman IDENTIFIED BY 1234;
- 권한 부여: GRANT connect, resource, dba TO richman;
- richman 계정으로 재접속하여 테이블 생성 준비
Oracle 사용자 생성 원리:
- Oracle 12c 이상에서는 일반 사용자명 앞에 C## 접두사를 강제함 (Container Database 개념)
- ALTER SESSION 명령으로 이 제약을 일시적으로 해제
- CREATE USER로 새 사용자 생성 및 비밀번호 설정
부여된 권한:
- connect: DB 접속 권한
- resource: 테이블, 시퀀스 등 객체 생성 권한
- dba: 관리자 권한 (실습용으로만 사용, 운영 환경에서는 절대 금지)
보안 고려사항:
- 실습 환경에서만 dba 권한 부여, 운영 환경에서는 최소 권한 원칙 적용
- 기본 비밀번호(1234) 사용 금지, 복잡한 비밀번호 설정 필수
- DBA 권한을 가진 웹 애플리케이션 계정은 즉시 점검 필요
- 계정 생성 로그 모니터링으로 비인가 계정 생성 탐지
실습 62-3: 테이블 생성 및 샘플 데이터 삽입
목표: SQL Injection 실습을 위한 friends 및 members 테이블 생성
실습 단계:
- friends 테이블 생성: name(VARCHAR2 20), address(VARCHAR2 10), age(NUMBER 2), hobby(VARCHAR2 10)
- friends 테이블에 20명 샘플 데이터 삽입 (이름, 주소, 나이, 취미)
- members 테이블 생성: name(VARCHAR2 20), user_id(VARCHAR2 20), password(VARCHAR2 30), email(VARCHAR2 50), phone(VARCHAR2 20)
- members 테이블에 20명 샘플 데이터 삽입 (이름, 아이디, 비밀번호, 이메일, 전화번호)
- 데이터 확인: SELECT * FROM friends; / SELECT * FROM members;
DB 구조:
friends 테이블: name(이름), address(거주 지역 - 서울/대구/부산/대전), age(나이), hobby(취미 - 축구/농구/야구/배구)
members 테이블: name(회원 이름), user_id(로그인 아이디), password(비밀번호 - 평문 저장은 실습용), email(이메일 주소), phone(전화번호)
보안 관점:
- 실제 운영 환경에서는 비밀번호를 평문으로 저장하지 않고 반드시 해시화(bcrypt, SHA-256 등) 필요
- 개인정보 암호화 의무 대상 데이터(주민번호, 비밀번호, 생체정보 등)는 암호화 저장 필수
실습 62-4: SQL SELECT 문 기초
목표: SQL SELECT 문법 이해 및 WHERE 조건절 활용
주요 쿼리 예시:
- 전체 데이터 조회: SELECT * FROM friends;
- 지역 조건: SELECT * FROM friends WHERE address = ‘서울’;
- 비교 연산자: SELECT * FROM friends WHERE age > 27;
- LIKE 패턴 매칭 (김씨 성): SELECT * FROM friends WHERE name LIKE ‘김%’;
- AND 조건 (서울+축구): SELECT * FROM friends WHERE address = ‘서울’ AND hobby = ‘축구’;
- OR 조건 (서울 또는 축구): SELECT * FROM friends WHERE address = ‘서울’ OR hobby = ‘축구’;
- 항상 참인 조건: SELECT * FROM friends WHERE ‘q’ = ‘q’; => 결과: 모든 데이터 조회
SQL 논리 연산자 진리표:
AND 연산자: T AND T -> T / T AND F -> F / F AND T -> F / F AND F -> F
OR 연산자: T OR T -> T / T OR F -> T / F OR T -> T / F OR F -> F
실무 적용:
- ‘q’=‘q’ 같은 항상 참인 조건은 SQL Injection 공격에 자주 사용됨
- WHERE 절의 논리 연산자 우선순위 이해 필수
보안 인사이트:
- LIKE 연산자와 % 와일드카드는 SQL Injection 공격 포인트로 자주 악용됨
- 항상 참인 조건(‘1’=‘1’, ‘q’=‘q’)을 삽입하여 인증 우회 시도 가능
- WHERE 절의 논리 연산 구조를 이해해야 공격 쿼리 분석 가능
실습 62-5: SQL Injection 기본 개념 및 인증 우회
목표: SQL Injection 공격 원리 이해 및 로그인 인증 우회 실습
정상적인 로그인 쿼리 구조:
- SELECT * FROM members WHERE user_id = ‘사용자입력’ AND password = ‘비밀번호입력’;
SQL Injection 공격 시나리오:
- 아이디 입력: leesy’ or ‘k’=‘k
- 비밀번호 입력: (아무거나)
- 실제 실행되는 쿼리: SELECT * FROM members WHERE user_id = ’leesy’ OR ‘k’=‘k’ AND password = ‘아무거나’;
- 논리 연산 우선순위(AND > OR)에 따라: user_id = ’leesy’ OR (‘k’=‘k’ AND password = ‘아무거나’) -> ‘k’=‘k’가 항상 참이므로 결과적으로 leesy 계정 조회됨
OR 조건만 사용:
- 아이디: ’ or ‘1’=‘1 / 비밀번호: (아무거나)
- 실제 쿼리: SELECT * FROM members WHERE user_id = ’’ OR ‘1’=‘1’ AND password = ‘아무거나’;
- 결과: 전체 회원 데이터 조회, 첫 번째 계정으로 로그인 성공
특정 계정 타겟팅 (주석 처리):
- 아이디: kimms’ –
- 실제 쿼리: SELECT * FROM members WHERE user_id = ‘kimms’ –’ AND password = ‘아무거나’;
- 주석 처리로 비밀번호 검증 우회, kimms 계정으로 로그인
SQL Injection 공격 메커니즘:
- 사용자 입력값이 SQL 쿼리에 직접 삽입됨 (Prepared Statement 미사용)
- 공격자가 입력란에 SQL 구문을 삽입하여 쿼리 구조 변경
- 의도하지 않은 데이터 조회, 인증 우회, 데이터 탈취 등 발생
공격 포인트 판별:
- 입력란에 싱글쿼트(’)를 입력했을 때 에러 발생하거나 동작이 이상하면 취약
- 에러 메시지가 상세하게 노출되면 쿼리 구조 파악 가능
로그인 인증 우회 공격 단계:
- 쿼리문 유추: SELECT * FROM members WHERE user_id = ‘입력값’ AND password = ‘입력값’
- 공격 포인트 확인: 입력란에 ’ 입력 시 에러 발생 여부 확인
- 제약사항 파악: 이 경우는 제약사항 없음 (기본 인증 우회)
- 공격 실행: 항상 참인 조건 삽입 또는 주석 처리
보안 고려사항:
취약점: 사용자 입력값을 쿼리에 직접 결합 (String Concatenation), 입력값 검증 및 필터링 미흡, SQL 주석 처리 문자 미차단
방어 방법:
- Prepared Statement (Parameterized Query) 사용 필수
- 입력값 화이트리스트 검증 (허용된 문자만 통과)
- ORM(Object-Relational Mapping) 프레임워크 활용
- 에러 메시지 상세 정보 노출 차단
3. 웹 기술 비교표
데이터 전송 형식 비교
| 항목 | Query String | JSON | XML | 실무 사용 사례 |
|---|---|---|---|---|
| 형식 | ?key1=value1&key2=value2 | {“key1”:“value1”} | key1 태그 방식 | Query String은 GET 요청, JSON은 API, XML은 레거시 시스템 |
| 가독성 | 낮음 (URL에 노출) | 높음 (구조화) | 중간 (태그 많음) | JSON이 가장 직관적이며 현대 API 표준 |
| 데이터 크기 | 제한적 (URL 길이 제한) | 중간 | 큼 (태그 오버헤드) | 대용량 데이터는 POST + JSON 사용 |
| 보안 | URL에 노출되어 위험 | HTTPS 사용 시 안전 | HTTPS 사용 시 안전 | Query String으로 민감 정보 전송 금지 |
HTTP Method 비교
| Method | 용도 | 멱등성 | 안전성 | 보안 고려사항 |
|---|---|---|---|---|
| GET | 리소스 조회 | O | O | URL에 데이터 노출, 민감 정보 전송 부적합 |
| POST | 리소스 생성/전송 | X | X | Body에 데이터 포함, CSRF 공격 대상 |
| HEAD | 응답 헤더만 조회 | O | O | 정보 수집 용도로 악용 가능 |
| OPTIONS | 사용 가능 메소드 확인 | O | O | CORS Pre-flight에 사용, 정보 노출 위험 |
| PUT | 리소스 전체 수정 | O | X | 불필요 시 비활성화 필요 |
| DELETE | 리소스 삭제 | O | X | 권한 검증 필수 |
4. 심화 분석
웹 애플리케이션 요청-응답 플로우
| 구분 | 클라이언트 측 | 네트워크 | 서버 측 | 보안 체크포인트 |
|---|---|---|---|---|
| 요청 생성 | 브라우저가 HTTP Request 생성 | 패킷 전송 | - | 클라이언트 측 검증은 우회 가능하므로 서버 검증 필수 |
| 보안장비 통과 | - | WAF, IPS 통과 | - | SQL Injection, XSS 등 공격 패턴 탐지 및 차단 |
| 웹 서버 처리 | - | - | Apache/Nginx 요청 수신 | 정적 파일 직접 제공, 동적 요청은 WAS로 전달 |
| WAS 로직 실행 | - | - | Tomcat 등 비즈니스 로직 실행 | 입력값 검증, 인증/인가 확인 |
| DB 쿼리 | - | - | DB 연결 및 쿼리 실행 | Prepared Statement 사용 여부, 권한 확인 |
| 응답 생성 | - | - | 웹 서버가 Response 생성 | 에러 메시지 필터링, 민감 정보 노출 차단 |
| 응답 수신 | 브라우저가 응답 렌더링 | 패킷 수신 | - | XSS 방어를 위한 Content-Type 검증 |
SQL Injection 방어 코드 원리
취약한 코드 예시:
- name = request.args.get(’name’)
- query = “SELECT * FROM friends WHERE name = ‘” + name + “’”
- 공격: name에 ’ or ‘1’=‘1 입력 시 모든 데이터 조회
안전한 코드 (Prepared Statement):
- query = “SELECT * FROM friends WHERE name = ?”
- result = db.execute(query, (name,))
- 입력값이 단순 문자열로 처리되어 공격 실패
5. 실무/보안 적용
보안 전문가 관점 - 웹 애플리케이션 보안 점검
| 단계/항목 | 점검 포인트 | 취약점 예시 | 대응 방안 |
|---|---|---|---|
| 입력값 검증 | 모든 사용자 입력값 검증, 특수문자 필터링, 길이 제한 | SQL Injection, XSS, Command Injection | 화이트리스트 방식 검증, Prepared Statement 사용, 입력값 이스케이프 처리 |
| 인증/인가 | 세션 관리, 비밀번호 강도, 권한 검증 | 인증 우회, 세션 하이재킹, 권한 상승 | 강력한 세션 ID 생성, HttpOnly/Secure 쿠키 설정, 비밀번호 해시화 (bcrypt) |
| 에러 처리 | 에러 메시지 노출, 디버그 모드, 스택 트레이스 | 정보 유출, 쿼리 구조 노출 | 일반화된 에러 페이지, 운영 환경에서 디버그 모드 비활성화, 상세 로그는 서버에만 저장 |
SQL 쿼리 보안 체크리스트
개발 단계:
- Prepared Statement 사용 여부 확인 (Java: PreparedStatement, Python: parameterized queries, PHP: PDO with placeholders)
- 입력값 화이트리스트 검증: 허용된 문자만 통과 (영문, 숫자, 일부 특수문자)
- 에러 메시지 필터링: 운영 환경에서 상세 에러 노출 차단, 사용자에게는 일반 메시지만 표시
- DB 계정 권한 최소화: SELECT, INSERT, UPDATE, DELETE만 허용, DROP/ALTER/CREATE 권한 제거
WAF 룰 예시 (SQL Injection 탐지)
ModSecurity WAF Rule 주요 항목:
- SQL Injection 키워드 탐지: union, select, insert, update, delete, drop, alter, create, exec, script
- 싱글쿼트 연속 출현 탐지: ’ or ‘, ’ and '
- 주석 기호 탐지: –, #, /*, */
- 항상 참인 조건 탐지: ‘1’=‘1’, ‘q’=‘q’, 1=1
6. 배운 점 및 인사이트
새로 알게 된 점
- 웹 애플리케이션의 3계층 구조: 웹 서버, WAS, DB로 이루어진 구조와 각 계층의 역할을 이해했습니다. 각 계층마다 보안 취약점이 존재하며, 다층 방어가 필요함을 깨달았습니다.
- HTTP의 Stateless 특성: HTTP는 1회성 연결이며 상태를 저장하지 않기 때문에 Session과 Cookie로 상태 관리를 해야 한다는 점을 배웠습니다.
- 인코딩과 암호화의 차이: 인코딩은 데이터 무결성 보장 목적이며 누구나 디코딩 가능한 반면, 암호화는 기밀성까지 보장하여 특정인만 복호화 가능함을 이해했습니다.
- SQL Injection의 기본 원리: 사용자 입력값이 쿼리에 직접 삽입되면 공격자가 쿼리 구조를 변경할 수 있으며, 특히 로그인 인증을 우회할 수 있다는 점을 실습으로 확인했습니다.
- 500 에러의 보안적 의미: Internal Server Error가 발생하면서 상세 에러 메시지가 노출되면, 공격자가 쿼리 구조를 파악하여 SQL Injection 공격에 악용할 수 있음을 깨달았습니다.
이전 학습과의 연결고리
- 네트워크 보안 지식 확장: 이전에 학습한 네트워크 계층별 보안이 웹 애플리케이션 레벨에서 어떻게 적용되는지 연결지어 이해할 수 있었습니다.
- SIEM 로그 분석 관점 연계: Wazuh, Splunk에서 웹 서버 로그를 분석할 때 어떤 패턴을 찾아야 하는지 구체적으로 알게 되었습니다. 특히 SQL Injection 시도는 URL에 특수문자나 SQL 키워드가 포함되므로 탐지 룰 작성 가능성을 확인했습니다.
- 컴플라이언스 관점: ISMS-P에서 요구하는 개인정보 보호 조치가 웹 애플리케이션에서 어떻게 구현되어야 하는지 연결하여 생각할 수 있었습니다.
실무 적용 아이디어
보안 전문가 관점:
- 웹 애플리케이션 보안 점검 체크리스트 작성: 입력값 검증, Prepared Statement 사용 여부, 에러 메시지 노출, DB 권한 등을 점검하는 체크리스트를 만들어 정기 점검에 활용할 수 있겠습니다.
- SIEM 탐지 룰 생성: 웹 로그에서 union, select, ‘or’, – 같은 SQL Injection 키워드가 포함된 요청을 탐지하는 Custom Rule을 Wazuh나 Splunk에 작성할 수 있겠습니다.
- WAF 룰셋 최적화: ModSecurity 같은 WAF에서 SQL Injection 패턴을 효과적으로 차단하는 룰을 연구하고, False Positive를 최소화하는 방안을 고민해야겠습니다.
7. Quick Reference
SQL 기본 명령어 모음
CRUD 기본 문법:
- 삽입: INSERT INTO 테이블명 VALUES (값1, 값2, 값3);
- 조회: SELECT * FROM 테이블명 WHERE 조건;
- 수정: UPDATE 테이블명 SET 컬럼1 = 값1 WHERE 조건;
- 삭제: DELETE FROM 테이블명 WHERE 조건;
조건절 연산자:
- WHERE 컬럼 = 값 (동등 비교)
- WHERE 컬럼 > 값 (크기 비교)
- WHERE 컬럼 LIKE ‘김%’ (패턴 매칭)
- WHERE 조건1 AND 조건2 (논리 AND)
- WHERE 조건1 OR 조건2 (논리 OR)
HTTP 핵심 개념 요약표
| 구분 | 항목 | 핵심 키워드 | 주요 내용 | 보안 적용 |
|---|---|---|---|---|
| Request | Method | GET, POST, HEAD, OPTIONS | 요청 방식 지정 | 불필요한 Method 비활성화 |
| Request | URL | 프로토콜://도메인:포트/경로?쿼리 | 리소스 위치 지정 | Query String에 민감 정보 포함 금지 |
| Request | Header | Cookie, Content-Type, User-Agent | 메타 정보 전달 | Header 조작 공격 주의 |
| Response | Status Code | 200, 302, 400, 404, 500 | 처리 결과 코드 | 500 에러 상세 정보 노출 차단 |
| Session | 상태 관리 | Session ID, Cookie | HTTP Stateless 보완 | Session Hijacking 방어 필요 |
SQL Injection 방어 체크리스트
개발 단계:
- 모든 DB 쿼리에 Prepared Statement 적용 확인
- 사용자 입력값 화이트리스트 검증 구현
- 에러 메시지 일반화 (상세 정보 노출 차단)
- ORM 프레임워크 활용 (가능한 경우)
인프라 단계:
- DB 계정 권한 최소화 (DBA 권한 제거)
- WAF 룰셋 적용 및 테스트
- 웹 로그 및 DB 쿼리 로그 수집
- SIEM에 SQL Injection 탐지 룰 생성
운영 단계:
- 정기 보안 점검 (입력란별 SQL Injection 테스트)
- 로그 모니터링 (이상 쿼리 패턴 탐지)
- 침해사고 대응 매뉴얼 수립
- 개발자 보안 교육 정기 실시
8. 트러블슈팅
| 문제 | 원인 | 해결 방법 |
|---|---|---|
| Oracle 사용자 생성 시 C## 에러 | Oracle 12c 이상에서 일반 사용자명에 C## 접두사 강제 | ALTER SESSION SET “_ORACLE_SCRIPT”=true; 실행 후 사용자 생성, 또는 C## 접두사를 포함한 이름 사용 |
| SQL Developer 접속 불가 | Oracle 서비스 미실행 또는 방화벽 차단 | 서비스 관리자에서 Oracle 서비스 실행 확인, 방화벽에서 1521 포트 허용, 호스트명을 localhost 또는 127.0.0.1로 변경 시도 |
| 싱글쿼트(’) 입력 시 에러 발생 | 입력값이 쿼리에 직접 삽입되어 쿼리 구조 파괴 | 이는 SQL Injection 취약점의 증거, Prepared Statement로 수정 필요 |
| WHERE 조건이 예상대로 동작하지 않음 | AND/OR 논리 연산자 우선순위 혼동 | AND가 OR보다 우선순위 높음, 괄호()로 명확히 우선순위 지정 |
Today’s Insight:
웹 애플리케이션 보안의 시작은 ‘사용자 입력을 절대 신뢰하지 말라’는 원칙에서 출발합니다. HTTP는 Stateless하고 1회성 연결이라는 특성 때문에 Session/Cookie로 상태를 관리해야 하며, 이 과정에서 다양한 보안 취약점이 발생할 수 있습니다. 특히 오늘 학습한 SQL Injection은 입력값이 쿼리에 직접 삽입될 때 발생하는 가장 치명적인 취약점 중 하나입니다. Prepared Statement 사용, 입력값 검증, 에러 메시지 필터링이라는 3가지 방어 원칙만 제대로 지켜도 대부분의 SQL Injection 공격을 차단할 수 있다는 점을 깨달았습니다.