1. 웹이란?
• 웹(Web)
- 하이퍼텍스트(HyperText) 문서들이 인터넷(Internet)을 통해서 연결된 시스템
- 마치 거미줄(Web) 처럼 복잡하게 연결되었기 때문에 붙여진 이름


• 구성
- 통신 프로토콜 : HTTP(HyperText Transfer Protocol)
- 콘텐트 : 하이퍼텍스트 문서들
- 링크(Link, Hyperlink 혹은 참조)를 통해 다른 문서로 접근할 수 있는 문서
- 예) HTML(HyperText Markup Language) 문서
- 주소 체계 : URL(Uniform Resource Locator)


• 웹의 시작
- 정식 이름: 월드-와이드-웹(WWW: World Wide Web)
- 시작: 1989년 유럽 입자 물리 연구소(CERN)
- 전 세계 여러 대학과 연구기관에서 흩어져 일하는 물리학자들이 상호간의 신속한 정보 교환과 공동 연구를
위해 고안
- 소프트웨어 공학자인 팀 버너스 리(Tim Berners Lee) 등에 의해 제안
- 최초의 웹 페이지와 웹 서버


2. HTTP의 개념
- HTTP(HyperText Transfer Protocol) 통신 프로토콜
- 2대의 컴퓨터가 통신하는 경우 한 쪽은 클라이언트, 다른 한 쪽은 서버
- 예: 웹 브라우저가 클라이언트가 되어 서버로 요청 메시지를 보내고, 그 결과로 응답(Response) 메시지를전달 받음
- 클라이언트가 요청 메시지를 먼저 보내고, 그 결과로 응답 메시지를 전달

2.1 HTTP 요청 메시지
HTTP ‘요청 메시지’ 전송

GET 메소드의 구성

POST 메소드의 구성

• 구성요소 1 : 메소드(Method) - 서버가 수행해야 할 동작 정의
📘 HTTP 메서드 정리
| 메소드 | 내용 |
|---|
| GET | 서버가 자원을 전송해 줄 것을 요청 |
| POST | 요청 바디(Body)를 통해 클라이언트가 서버로 데이터 전송 |
| HEAD | 서버가 (자원 내용은 전송하지 않고) 헤더만 전송해 줄 것을 요청 |
| OPTIONS | 서버가 지원하는 메소드들 질의 |
| TRACE | 클라이언트가 보낸 요청을 그대로 반환 |
| PUT | 클라이언트가 서버의 지정한 URI로 자원을 전송 |
| DELETE | 서버의 자원을 삭제 |
| CONNECT | 프록시 터널링을 위해 예약된 메소드 |

• 구성요소 2 : 요청 URI
- 상대 경로 및 절대 경로(Absolute path)로 요청 가능

• 구성요소 3 : 프로토콜 버전 - HTTP 프로토콜을 이용하여 통신을 할 때 사용하는 버전 정의
🌐 HTTP 버전 정리
| 버전 | 내용 |
|---|
| HTTP/0.9 | 최초 정식 버전(1.0)의 이전 버전. GET 메서드만 지원하며 헤더가 없음. 현재는 사용되지 않음. |
| HTTP/1.0 | 1996년 5월 RFC1945로 정의된 최초의 정식 버전. 초기 버전이지만 아직도 많은 웹 서버가 지원함. |
| HTTP/1.1 | 1997년 1월 발표, 가장 일반적으로 사용되는 버전. 이후 RFC2616, RFC7230~RFC7235로 개정되어 가장 최신의 1.x 버전. |
| HTTP/2.0 | 2015년 5월 RFC7540으로 발표. HTTP/1.1과의 호환성을 유지하면서도 다중화, 헤더 압축 등으로 성능 개선을 목표로 개발됨. 여전히 HTTP/1.1이 더 많이 사용됨. |
• 구성요소 4 : 헤더 - 요청 시에 필요한 조건이나 특성 등을 나타내는 필드(Field)
📑 HTTP 헤더의 예
| 헤더 | 내용 |
|---|
| Host: www.infinitybooks.co.kr | 필드 이름: Host 필드 값: www.infinitybooks.co.kr 의미: 요청하는 호스트 정보 지정 |
| Content-Type: text/html | 필드 이름: Content-Type 필드 값: text/html 의미: 데이터의 타입 지정 |
| Keep-Alive: timeout=30, max=200 | 필드 이름: Keep-Alive 필드 값: timeout=30 및 max=200 의미: 세션 유지 정보 지정 |
• 구성요소 5 : 요청 바디(Body) - 클라이언트가 서버로 보내는 추가적인 데이터
- POST 메소드를 사용할 경우 추가됨
- 다양한 포맷의 데이터가 추가 가능
- 폼(form)에 기입한 이름 혹은 주소
- 첨부 파일과 같은 바이너리 파일(Binary File) 등
- 본문의 형식은 Content-Type 헤더에 따름
2.2 HTTP 응답 메시지
HTTP ‘응답 메시지’ 전송

• 응답 메시지의 구성 : 5가지
- 구성요소 1 : 프로토콜 버전 - 서버가 사용하는 HTTP 버전
- 구성요소 2 와 3 : 상태 코드 및 상태 코드 설명
- 구성요소 4 : 응답 헤더 - 전달할 데이터의 형식과 길이 등의 메타 정보
- 구성요소 5 : 응답 바디 - 클라이언트의 요청에 대한 결과

📊 HTTP 응답 상태 코드
| 값의 범위 | 구분 | 내용 |
|---|
| 100~199 | 정보 전송 (Information) | 요청을 받아 처리가 계속되고 있음 (프로토콜 전환 등) |
| 200~299 | 성공 (Success) | 요청이 정상적으로 처리됨 200: OK 201: Created 202: Accepted 204: No content |
| 300~399 | 리다이렉션 (Redirection) | 요청을 처리하기 위해 클라이언트가 다른 URL로 이동해야 함 |
| 400~499 | 클라이언트 오류 (Client error) | 클라이언트 요청에 문제 발생 400: Bad request 401: Unauthorized 403: Forbidden 404: Not found |
| 500~599 | 서버 오류 (Server error) | 서버에서 오류 발생 500: Internal server error 501: Not implemented 503: Service unavailable |
• HTTP 의 특징
• HTTP는 비연결지향(Connectionless) 프로토콜
- 클라이언트가 요청을 서버에 보내면 서버는 클라이언트에게 요청에 맞는 응답을 보내고 접속을 끊는다
- 성능상 비효율적
- 클라이언트가 새로운 요청을 보낼 때마다 접속을 새로 해야 함
- 프로토콜 상의 개선
- HTTP/1.0 버전: 한 번의 접속으로 여러 개의 요청과 응답을 반복 가능
- HTTP/1.1 버전: 특정 시간동안 접속을 계속 열어두고(연결을 유지하고) 요청을 보낼 수 있도록 하는 기능 추가
→ Keep-alive 기본 사용 되었다
- 요청 헤더의 Keep-alive라는 필드 값 : ‘얼마 동안 접속을 열어 둘 것인가?
• HTTP는 상태 정보 유지안함(Stateless) 프로토콜
- ‘상태 정보’를 저장해야 할 경우에 대한 대안 : 쿠키와 세션
• 쿠키(Cookie):
- 클라이언트에 저장되는 키와 값이 들어있는 작은 데이터 파일
- 클라이언트의 상태 정보를 로컬에 저장했다가 참조
- 클라이언트의 컴퓨터에 작은 파일로 저장
- 응답메시지를 보낼 때 헤더에 Set-Cookie 값을 설정하면 클라이언트에 쿠키 생성됨
- 이름, 값, 경로 정보뿐 아니라 만료 날짜(쿠키 저장기간)가 설정됨
- 사용자마다 다르게 적절한 페이지를 보여줄 수 있음 ex) 쇼핑몰, 검색내역, “다시 보지 않기“ 팝업창 체크 등
- C:\Users\\AppData\Local\Google\Chrome\User Data\Default\Network\Cookies


• 세션(Session):
- 서버는 일정 시간 동안 같은 클라이언트로부터 전달되는 요청들을 하나의 그룹으로
보고, 하나의 세션으로 식별함
- 클라이언트가 서버로 최초 요청을 보내면, 유일한 식별자(ID)인 세션 ID를 부여
- 서버의 메모리에 저장(객체) → 세션이 생길 때마다 서버의 리소스 차지

3. 하이퍼텍스트 및 URI
3.1 HTML 및 스크립트
• HTML 문서 생성
- 정적인(Static) 콘텐트 : 내용의 변경 없음 → 웹 서버는 파일을 읽어서 그 내용을 전송
- 동적(Dynamic) 콘텐트 : 사용자의 상황에 혹은 요청에 따라 내용이 달라짐
- 서버 사이드 스크립트 언어(SSL: Server-side Script Language)
- JSP(Java Server Page), ASP(Active Server Page), PHP(Personal Home Page) 등
- 웹 서버가 SSL로 작성된 페이지를 내부적으로 실행 → 실행 결과 HTML문서 전송
- 예) select.jsp라는 웹 페이지를 호출 : 입력 파라미터(parameter) id=100

• 클라이언트 사이드 스크립트 (CSL: Client-side Script Language)
- 정적 혹은 동적 방식으로 구해진 HTML 문서는 웹 브라우저로 전달
- 클라이언트인 웹 브라우저에서 실행되는 스크립트
- 동적으로 화면 내용을 만들거나 혹은 다양한 UI(User Interface) 제공
- JS(Java Script), VBS(Visual Basic Script) 등
- HTML 문서에 포함되어 동작

• 입력 파라미터의 전달
- GET 메소드 사용 : 보안적으로 권장되지 않음
- 요청 파라미터가 요청 URI에 포함 → 사용자에게 노출
- select.jsp?id=100
- POST 메소드 사용 : 보안적으로 우수
- 파라미터 정보가 요청 바디(Body)에 포함 → 사용자에게 노출되지 않음
- 주소창에 select.jsp로 노출되며, id=100은 요청바디(Body)에 포함
3.2 URI
- 인터넷의 특정 자원(Resource)에 접근하기 위해 사용하는 식별자

- URL은 URI의 하위 집합: www.infinitybooks.co.kr과 같이 특정 서버를 표시
→ 일반적으로 URI를 URL로 부른다
• URI 형식

- 스키마 이름 : 어떤 프로토콜을 사용할지 지정 (http, https, mailto, ws, file 등)
- 자격(인증) 정보 : 서버에서 자원을취득하는데 필요한사용자이름과패스워드등의자격(인증) 정보, 생략가능
- 서버의 호스트 이름(FQDN) 혹은 IP 주소
- 서버 포트 번호 : 네트워크의 포트 번호, 생략될 경우 기본 포트 번호 사용
- 계층적 파일 경로 : 요청하는 자원의 경로
- 질의 문자열(Query String) : 임의의 매개변수를 전달하기 위한 목적, 생략 가능
- 단편 식별자 : 취득한 자원에서 그 하위에 있는 특정 부분을 # 등으로 가리키는 것으로 선택 사항
• 퍼센트 인코딩
🧪 JavaScript: encodeURI() 사용 예
const uri = "https://mozilla.org/?x=шеллы";
const encoded = encodeURI(uri);
console.log(encoded);
try {
console.log(decodeURI(encoded));
} catch (e) {
console.error(e);
}
- URI에서 사용할 수 없는 문자를 표현할 때 사용되는 인코딩 방식
- URL 인코딩이라고도 함(RFC3986에 정의)
- 대상이 되는 문자는 바이트 단위로 나뉘어 16진수 형태로 표시
- 예외 : HTTP의 POST 메소드를 사용하여 웹 폼 문자열을 전송할 때 MIME의 Content-Type에 ‘application/xxxx-form-urlencoded’가 사용되면 공백이 ‘%20’이 아니라 ‘+’로 변경
🔡 URL 인코딩 예
| 문자 | 인코딩 값 |
|---|
= | %3D |
% | %25 |
| 공백 | %20 또는 + |
문맥에 따라 문자 ' '는 application/x-www-form-urlencoded 메시지에서 퍼센트 인코딩처럼 '+'로 변환되며, URL에서는 '%20'으로 변환됩니다.
4. 웹 취약점 정보 수집
• 웹 취약점 스캐너
- 웹 사이트의 취약점을 점검해주는 프로그램
- 점검 대상이 되는 웹 사이트의 문제점에 대한 해결 방안을 제시
- 오픈VAS(OpenVAS), 레티나 CS 커뮤니티(Retina CS Community), MBSA(Microsoft Baseline Security Analyzer) 등

• Acunetix
데모(Trial) 버전

메인 화면

스캔 시작
- 크롤링(Crawling): 시작 주소 페이지에 연결된 링크들을 이용하여 연결된 홈페이지들을 모두 검사하는 방법

점검 대상 사이트 정보 입력(IP/PW)

취약점 검사 결과

5. 웹 취약점 및 보안 대책
OWASP(The Open Web Application Security Project)
- 비영리 국제 단체, 웹 서버 보안과 관련하여 공신력 있는 기관
- https://www.owasp.org
- OWASP TOP 10
- 웹 관련 보안 취약점 중 많이 발생하고 영향도가 큰 이슈 10가지 선정

5.1 SQL 인젝션
- 데이터베이스와 관련된 보안 취약점: 사용자가 입력하는 입력 값에 대한 유효성을 검증하지 않고
그대로 사용할 때 발생 가능
- SQL 질의(Query)가 악의적으로 변조(악용) → 사용자 인증을 우회하거나 데이터베이스에 저장된 데이터가
변조되거나 파괴될 수 있음

보안 대책 1 : 매개변수 바인딩 기법 사용
🔐 매개변수 사용 예
| 항목 | 내용 |
|---|
| 매개변수 사용 | SELECT * FROM member WHERE ID = ? AND PW = ? 사용자가 입력한 ID와 PW 값은 별도의 매개변수로 전달 |
⚠️ 취약한 코드 (SQL Injection 위험)
from sqlalchemy.orm import Session
from models import Member
def find_by_name(name: str, session: Session):
query = f"SELECT * FROM members WHERE name = '{name}'"
return session.execute(query).fetchall()
위 코드는 사용자 입력값을 직접 SQL 쿼리에 삽입하므로 SQL Injection 공격에 취약합니다.
✅ 안전한 코드 (Parameter Binding 사용)
from sqlalchemy.orm import Session
from models import Member
def find_by_name(name: str, session: Session):
query = "SELECT * FROM members WHERE name = :name"
return session.execute(query, {"name": name}).fetchall()
위 코드는 SQLAlchemy의 parameter binding을 사용하여 SQL Injection 공격을 방지합니다.
보안 대책 2 : 입력 값에 대한 특수문자 검증
- 사용자 입력에서 특수문자
(' " / \ (공백 space) ; : -- # 등)가 포함되어 있는지 검사
- 허용되지 않은 문자열이나 문자가 포함된 경우에는 제거
- MS SQL Server와 Oracle에서 주석문 :
--
- MySQL의 주석문 :
#
🧹 사용자 입력 값에서 특수문자 제거 후 문자열 조합
String name = request.getProperty("user");
if (name != null && !"".equals(name)) {
name = name.replaceAll("/", "");
name = name.replaceAll("\\\\", "");
name = name.replaceAll("\\.", "");
name = name.replaceAll("&", "");
name = name + "-report";
}
입력값 name에서 /, \, ., & 특수문자를 제거하고, "report"를 뒤에 붙여 처리합니다.
보안과 무결성 확보를 위한 전처리 방식입니다.
5.2 경로 조작
- 사용자가 입력하는 입력 값에 대한 유효성을 검증하지 않고 그대로 사용할 때 발생할 수 있는 서버
시스템 자원 접근에 대한 보안 취약점
- 사용자가 접근해서는 안 되는 서버의 중요 파일을 내려받거나 혹은 삭제(상대경로 활용)
- 보안 대책 : 입력 값 특수문자
(‘, “, /, \, ;, :, --, +, 공백) 검사, 해당 문자 제거

5.3 위험한 형식 파일 업로드
- 유효성 점검의 대상이 사용자가 업로드 하려는 파일
- 웹 셸(Web Shell) : 사용자가 올린 파일이 웹 서버에서 실행되면서 보안 공격자가 외부에서 웹
서버를 통해 서버를 원격 조종 하게 하는 파일
- 파일 확장자 :
.asp, .jsp, .php 등
- 지속적으로 다양한 보안 공격 시도가 가능해짐

보안 대책
- 화이트리스트 방식의 허용된 확장자(.jpg, .doc 등)만 업로드 허용
- 서버에 파일을 저장할 때 파일 이름과 경로를 임의의 문자열로 변경하여 저장
- 파일 저장 경로가 웹 서버의 문서 디렉터리 아래가 아니라 전혀 다른 곳으로 설정
c:\apache/htdocs → d:\file_root
- 파일이 서버에서 실행될 수 없도록 실행 속성을 제거
5.4 크로스사이트 스크립트(XSS: Cross-Site Script)
- 웹 브라우저에서 사용자가 입력하는 입력 값에 대한 유효성을 검증하지 않고 그대로 웹 서버로
전송했을 때 발생할 수 있는 보안 취약점
- 악성 스크립트를 웹 서버에 저장 → 같은 웹 서버에 접속한 다른 사용자들에게 배포되어 추가 보안 사고 발생
- 일반적으로 자바스크립트에서 주로 발생
- VB 스크립트, ActiveX 등 클라이언트에서 실행되는 동적 데이터를 생성하는 모든 언어에서 발생 가능
- 보안 대책 : 사용자 입력 값에 대한 특수문자 검증
🔒 XSS 대비 문자열 대체
| 원본 문자(기호) | 대체 문자열 |
|---|
< | < |
> | > |
' | & |
" | " |

5.5 적절한 인증 없는 중요 기능 허용
🔐 인증 점검 로직 비교
안전하지 않은 코드
- 인증 점검 로직이 없이 비즈니스 로직을 호출함
<%
……
ShowAccountInfo();
……
%>
인증 점검이 포함된 안전한 코드
- 인증 점검 로직을 먼저 호출한 다음 비즈니스 로직을 호출함
<%
……
if (CheckAuthentication()) { // 🔴 인증 여부 확인
ShowAccountInfo();
} else {
// 인증 오류 처리
// ex) 로그인 페이지로 리다이렉트
……
}
……
%>
🔴 CheckAuthentication() : 인증 여부를 판단하는 핵심 함수로, 반드시 먼저 호출해야 함.
5.6 부적절한 인가
적절한 인가(Authorization)
인가 :
- 사용자의 자원에 대한 접근 또는 사용을 허용하는 과정
- 로그인에 성공한 사용자가 어떠한 행위를 하려 할 때 이것을 허용할지 결정
- 어떤 객체를 대상으로 어떤 사용자/그룹에게 어떤 권한을 부여할지 결정(설계)
- ex) guest로 로그인했음에도 불구하고 관리자의 기능을 정상적으로 수행하면 안됨

🔐 인증·인가 점검 로직 비교
안전하지 않은 코드
<%
……
if (CheckAuthentication()) {
ShowAdminInfo();
} else {
// 인증 오류 처리
}
……
%>
인증과 인가 점검이 포함된 안전한 코드
- 인증 → 인가 순으로 점검 후 비즈니스 로직을 호출함
<%
……
if (CheckAuthentication()) { // 🔴 인증 여부 확인
if (CheckAuthorization()) { // 🔵 인가 여부 확인
ShowAdminInfo();
} else {
// 인가 오류 처리
}
} else {
// 인증 오류 처리
}
……
%>
🔴 CheckAuthentication() : 사용자의 로그인 여부를 확인
🔵 CheckAuthorization() : 권한이 있는 사용자만 접근 가능하도록 제한
5.7 중요 정보 평문 저장/전송과 취약한 암호화 알고리즘 사용
- 파일, 데이터베이스 또는 메모리에 중요 데이터(주민번호, 여권번호 등) 저장
→ 반드시 암호화해서 저장해야 됨

🔐 파일 저장 시 암호화 여부 비교
안전하지 않은 코드
- 파일에 중요한 데이터를 저장할 때 암호화하지 않고 저장함
<%
……
file.write(password);
……
%>
암호화를 적용한 안전한 코드
- 파일에 중요한 데이터를 저장할 때 암호화하여 저장함
<%
……
file.write(EncryptString(password));
……
%>
🔒 EncryptString() : 민감한 데이터를 암호화하는 함수로, 저장 전 반드시 적용해야 함
안전한 암호화 알고리즘
🔐 안전한 암호화 알고리즘 (암호화 알고리즘 검증기준 Ver 2.0)
| 분류 | 안전한 알고리즘 | 키 길이 |
|---|
| 대칭키(블록 암호) | ARIA | 128 / 192 / 256 |
| SEED | 128 |
| 비대칭키(공개키) | RSA | 2048 / 3072 |
| 해시 함수 | SHA-2 | 224 / 256 / 384 / 512 (해시 결과 크기) |
※ 해시 함수는 '키 길이'가 아니라 해시 결과의 크기를 뜻함.
• 인터넷 등과 같은 통신 채널을 통해서 민감한 정보 전송
→ 반드시 암호화해서 전송(SSL/TLS) (스니핑 대비)

🔐 평문 vs 암호화 통신 비교
| 구분 | 안전하지 않은 코드 / 평문으로 통신 | 안전한 코드 / 암호화하여 통신 |
|---|
| 서버 | java<br>Socket s = new ServerSocket(8899).accept();<br> | java<br>SSLServerSocketFactory f = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();<br>SSLServerSocket s = (SSLServerSocket) f.createServerSocket(8899);<br> |
| 클라이언트 | java<br>Socket s = new Socket(server_ip, 8899);<br> | java<br>SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();<br>SSLSocket s = (SSLSocket) f.createSocket(server_ip, 8899);<br> |
🔐 평문 전송은 도청 및 정보 유출 위험이 있으며, SSL을 사용한 암호화 통신으로 반드시 보호해야 함.
5.8 부적절한 오류 처리
오류 메시지를 통한 정보 노출
- 웹서버의 종류
- 스택 트레이스를 통한 내부 로직 정보
- 데이터베이스 종류
- 운영체제 종류

노출된 오류 메세지의 예
🔐 예외 처리 시 메시지 출력 방식 비교
| 구분 | 안전하지 않은 코드 / 필요 없는 오류 메시지 내용까지 출력 | 안전한 코드 / 최소한의 오류 메세지 내용만 출력 |
|---|
| 예외 처리 방식 | java<br>catch(Exception e) {<br> e.printStackTrace();<br>} | java<br>catch(Exception e) {<br> System.out.println("내부 오류가 발생하였습니다");<br>} |
⚠️ printStackTrace()는 시스템 내부 정보까지 노출될 수 있어 보안상 위험.
✅ 사용자에게는 최소한의 메시지만 제공하고, 상세 정보는 로그에만 기록하도록 구성해야 함.
오류 상황 대응 부재와 부적절한 예외 처리
- 공격자는 일부러 오류상황 또는 예외 상황을 발생시킴
→ 오류 처리 로직이 없거나 적절하지 않으면 해당 취약점을 통해 공격 시도
🔐 예외 처리 로직 유무 비교
| 구분 | 안전하지 않은 코드 / 오류 처리 로직이 없음 | 안전한 코드 / 적절한 오류 처리 로직이 있음 |
|---|
| 예외 처리 누락 여부 | java<br>catch(Exception e) {<br>}<br> | java<br>catch(Exception e) {<br> System.out.println("내부 오류가 발생하였습니다");<br> // 예외 처리 로직<br>} |
⚠️ 예외를 무시하면 문제의 원인을 파악하거나 정상적인 복구가 어려움
✅ 예외 로그 출력과 함께 처리 로직을 반드시 작성해야 함
6. 웹 서버의 계정 관리
개요
웹 서버의 보안 중요성
- 웹 서버의 역할 : 각 기업들의 중요 정보를 접근하기 위한 진입점, 실제 서비스를 제공하는 서비스 주체
보안 공격자들의 공격 대상이 되는 보안 취약점
- 웹 서버 자체가 가지고 있는 약점
- 웹 서버가 동적 콘텐트를 만드는 부분
- 클라이언트 사이트에서 실행되는 스크립트 등
대표적인 웹 서버
- 아파치(Apache) 웹 서버
- 제조사 : 비영리 단체인 아파치 소프트웨어 재단
- IIS(Internet Information Services)
6.1 웹 서비스는 최소 권한 사용자로 운영되어야 한다
- 웹 서버는 아직 알려지지 않은 보안 취약점으로 공격 당할 가능성 존재
- 웹 서버를 실행시키는 운영체제 상의 사용자는 최소 권한을 가져야 한다
- 탈취 당하더라도 권한이 없어 시스템 설정을 변경할 수 없음
- Apache : 환경 설정 파일 httpd.conf의 사용자 그룹에 root가 아닌 다른 사용자 계정을 사용
(예: apache 라는 사용자 및 그룹)
- IIS : 서비스 관리자에서 IIS 서비스를 시작하는 계정을 새로 추가한 사용자로 재지정
(예: IIS_NOBODY라는 새로 생성한 사용자 계정)


7. 웹 서버의 파일 관리
7.1 디렉터리 검색은 막아야 한다
디렉터리 검색(Directory listing)
- 웹 브라우저가 웹 서버로 디렉터리의 정보를 요청했을 때 디렉터리 내의 모든 파일 목록을 보여주는 기능
- 디렉터리에 index.htm과 같은 기본 문서가 없을 경우, 기본 동작으로 보여줌
- 보안 위험성
- 외부의 보안 공격자가 내부 디렉터리의 내용을 확인
- 서버의 내부 구조 및 백업 파일 혹은 소스 파일들이 공개

대응책
- Apache : 환경 설정 파일 httpd.conf에 설정되어 있는 디렉터리 검색 기능 제거
- Options Indexes라는 부분에서 Indexes를 제거
🔐 Apache 설정에서 Indexes 옵션 제거
제거 전 설정
<Directory>
Options Indexes FollowSymLinks AllowOverride None
Order allow, deny
Allow from all
</Directory>
제거 후 설정
<Directory>
Options FollowSymLinks AllowOverride None
Order allow, deny
Allow from all
</Directory>
⚠️ Indexes 옵션이 설정되어 있으면 디렉터리 내 파일 목록이 노출될 수 있음
✅ Indexes 옵션 제거를 통해 디렉터리 리스팅을 차단해야 함
- IIS : IIS 관리자 화면에서 ‘디렉터리 검색’ 을 ‘사용 안 함’으로 설정

7.2 불필요하게 설치된 파일을 제거하라
- 불필요하게 설치된 파일
- 웹 서버를 설치할 때 기본적으로 제공되는 매뉴얼 파일 및 예제 스크립트 파일 등
- 매뉴얼 파일과 예제 스크립트 등은 웹 서버의 정보 및 운영체제에 대한 정보 제공
- 아파치 웹 서버
- 설치 디렉터리 바로 밑에 있는 매뉴얼 파일
( /htdocs/manual 혹은 /manual ) 등
- IIS 5.0 혹은 IIS 6.0의 경우
- 예제 스크립트 파일들
C:\inetpubs\iissamples
C:\winnt\help\iishelp
C:\Program files\common files\system\msadc\sample 등
- ☞ IIS 7.0 이상에서는 위의 예제 파일들이 기본적으로 제공되지 않음
8. 웹 서버의 서비스 관리
8.1 파일 업로드 및 다운로드의 최대 크기를 설정하라
- 파일 최대 크기 설정의 필요성
- 부주의한 사용자 혹은 악의적 사용자에 의해 서비스 중지
- 소수의 대용량 사용자 때문에 다른 사용자들의 피해 발생(시스템이 느려짐)
- 보안 공격자에 의해 내부의 중요 자료가 대량으로 외부로 유출될 가능성
- Apache:
httpd.conf의 각 디렉터리 내에 LimitRequestBody 설정(최대 파일 크기 지정)
<Directory>
LimitRequestBody 5242880
</Directory>
- IIS: (7.0 환경) 설정 파일 applicationhost.config에 있는 속성 값
%windir%\system32\inetsrv\config\applicationhost.config
<system.webServer>
<asp>
<limits bufferingLimit="5242880" maxRequestEntityAllowed="5242880"/>
</asp>
</system.webServer>
8.2 IIS의 WebDAV 서비스를 비활성화하라
- WebDAV(Web Distributed Authoring and Versioning) 및 관리 필요성
- 웹 상에서 여러 명의 사용자가 공동 개발을 지원하기 위해 제안된 국제 표준
- 철저하게 관리되지 않으면 보안 공격자의 손쉬운 공격 대상
- 악의적인 요청으로 인증 우회 혹은 버퍼 오버플로우 오류를 통한 관리자 권한 획득 등
- 비활성화 방법(7.0 기준): ISAPI 및 CGI 제한을 선택 → WebDAV 서비스 제거


9. 웹 서버의 로그 관리
IIS에서의 로그 관리
- 개요 : IIS 관리 도구에서 설정이 가능
- 로그 파일의 롤오버 : 로그 파일이 일정 크기에 도달했을 때 새로운 로그 파일을 생성하도록 설정
- 매 시간, 일, 주 혹은 월 단위 → 보안적 중요성 및 로그 발생 양에 따라 결정
- (예) 중요하고 서비스 양이 많은 경우, 대용량의 로그가 생성되므로 매시간마다 새로운 로그 파일을 생성하도록 설정
- 로그 정보는 보안 감사 및 보안 공격에 대한 분석의 용도로 활용
- 기본 로그 파일 저장 포맷 : W3C 형식

W3C 형식의 구성 요소
- 날짜와 시간
- 서버 IP, HTTP 접근 방법(
GET 또는 POST 등), 접근 URL, 서버 포트
- 클라이언트 IP, 클라이언트의 웹 브라우저
- 실행 결과 코드
- 서버에서 클라이언트로 전송한 데이터 크기
- 클라이언트에서 서버로 전송한 데이터의 크기 및 처리 소요 시간
W3C 형식 로그의 예
2014-07-25 12:21:31 날짜와 시간
192.168.104.191 서버 IP
GET HTTP 요청(접근) 메소드(GET 또는 POST 등)
/ 요청 URL
80 서버 포트
192.168.104.1 클라이언트 IP

아파치에서의 로그 관리
- 로그의 형식 설정
- 아파치환경설정파일
httpd.conf파일에서지정된Combined 로그형식(Combined Log Format, 결합된 로그형식)
📄 Apache 로그 포맷에서 사용되는 예약어 정리
| 항목 | 설명 |
|---|
%h | 접속한 클라이언트 IP |
%l | 클라이언트의 사용자 이름 |
%u | 인증이 요청된 원격 사용자 이름 |
%t | 요청한 시간과 날짜 (영어권 표준 시간과 날짜 포맷) |
"%r" | HTTP 접근 방법(GET 또는 POST 등)을 포함한 요청의 첫 라인 |
%>s | HTTP 상태 코드 |
%b | HTTP 헤더를 제외하고 전송된 바이트 수 |
"%{Referer}i" | 요청한 URL이 참조되거나 링크된 URL |
"%{User-Agent}i" | 접속한 클라이언트의 OS 및 브라우저 버전 등 |
%T | 요청을 처리하는 데 걸린 시간(초) |