Chapter1. HTTP 동작원리
가. HTML(Hypertext Markup Language)
HTML은 웹 문서를 작성하는 표준 마크업(Markup Language)이다. HTML은 여러 태그로 구성되어 있는데 이러한 태그를 사용해서 개발자가 원하는 형태의 문서 / 그림을 구성할 수 있다. HTML에서 사용하는 명령어를 태그(Tag)라고 하며, 괄호 '<', '>'를 사용하여 태그를 구성한다.
아래의 예제 코드를 통해 HTML의 구조를 살펴보자. HTML 문서는 최상위 태그로 <html>을 사용한다. 하위에는 문서를 정의하는 데이터를 포함하는 <head>태그와 문서의 내용을 작성하는 <body>태그가 올 수 있다.
HTML 파일의 확장자는 *.html 또는 *.htm을 사용한다. html 또는 htm파일을 웹 브라우저에서 로딩하면 웹 페이지를 확인할 수 있다.
<html>
<head>
문서를 정의하는 데이터가 위치함
</head>
<body>
문서에 표시되는 내용이 위치함
</body>
</html>
나. HTTP (Hypertext Transfer Protocol)
HTTP는 웹 서버와 클라이언트(웹 브라우저) 간에 문서 / 데이터를 교환하기 위한 통신 규약(프로토콜)을 의미한다. 즉, HTML 문서와 같은 자원(리소스)을 처리하는 프로토콜(protocol)로 웹 서버와 클라이언트 간 데이터 교환의 기초가 된다. 다른 말로는 요청(Request) 및 응답(Response) 프로토콜로 표현이 가능하다.
예를 들어, 사용자가 웹 브라우저를 통해 인터넷에 접속하면 HTTP를 이용해서 데이터를 요청하고, 웹 서버는 사용자의 요청을 받아서 처리한 정보를 응답한다. HTTP에 대한 보다 세부적인 내용은 IETF사트에서 확인할 수 있다. HTTP 특징에 대해 간략히 살펴보면 다음과 같다.
1) 비연결지향 (Connectionless)
클라이언트가 HTTP 요청(request)을 서버로 보내면, 서버는 클라이언트 요청에 맞는 응답(response)을 보내고 접속을 끝는다. 즉, 클라이언트와 서버가 계속해서 연결되어 있는 상태가 아니라는 것이다.
2) 상태정보 유지안함(Stateless)
클라이언트와 서버와의 통신이 끝나면 상태 정보는 유지하지 않는 것이다. 클라이언트의 요청을 독립적인 트랜잭션으로 보기 때문에 서버는 이전에 클라이언트의 요청을 항상 해석해야 한다.
이러한 구조적인 한계로 인해 서버는 쿠키와 세션을 사용해서 클라이언트를 식별하게 된다. 예를 들어, 우리가 네이버 웹 사이트를 이용할 때 로그인을 한 번 해두면 별도의 재 인증 과정 없이 메일 / 블로그 /카페를 사용할 수 있는 것이다. (세션 타임아웃이라는 설정으로 일정 시간이 지나면 자동 로그아웃이 되도록 설정할 수 있다.)
나-1) 쿠키(Cookie)와 세션(Session)
쿠키(Cookie)는 클라이언트에 저장되는 키와 값들의 작은 데이터 조각을 의미하며, 이름 / 값 / 만료 날짜 / 경로 등의 정보가 포함되어 있다. 일정 시간동안 데이터를 저장할 수 있으며, 클라이언트의 상태 정보를 로컬에 저장하고 참조한다. 쿠키는 아래와 같은 원리로 생성 및 사용된다.
1) 클라이언트가 브라우저로 웹 페이지에 접속
2) 서버는 클라이언트가 요청한 웹 페이지를 처리하고 쿠키를 클라이언트에 파일로 저장
3) 클라이언트는 서버에 재요청 시 쿠키정보를 호라용해서 서버에 전달
4) 서버는 클라이언트의 쿠키를 활용하여 상태 정보를 유지할 수 있도록 처리
익스플로러 기준으로 인터넷 옵션 - 일반 - 검색기록 - 설정 - 임시 인터넷 파일 - 파일 보기를 클릭하면 PC에 저장되어 있는 쿠키 파일들을 확인할 수 있다.
세션은 쿠키와 다르게 서버의 메모리에 저장되는 정보이다. 일정 시간동안 웹 브라우저를 통해 들어오는 요청을 하나의 상태로 보고 유지하는 기술이다. 즉 사용자가 웹 브라우저를 통해 사이트에 접속하게 되면 브라우저를 종료할 때까지 로그인 유지와 같은 상태가 지속된다. 세션은 아래와 같은 원리로 생성 및 사용된다.
1) 클라이언트가 서버의 웹 페이지에서 로그인 시도
2) 서버는 클라이언트가 요청한 로그인 정보가 맞을 경우, 서버 메모리에 세션ID를 생성하고 클라이언트의 ID와 매핑된 정보를 저장
3) 클라이언트는 세션ID를 쿠키로 저장
4) 클라이언트가 요청할 때마다 서버는 쿠키정보를 확인하고 세션ID와 매핑되는 ID를 사용자로 인증
나-2) 히든 필드(Hidden Field)
히든 필드는 사용자가 보거나 수정할 수 없도록 개발자가 웹페이지의 폼(Form)을 통해 데이터를 전송한다. 입력된 데이터는 GET 또는 POST 메소드를 통해 웹 서버에 전달된다. 다음은 DVWA File Upload실습페이지에서 최대 파일업로드 사이즈를 100000으로 제한하기 위해 폼의 히든 필드를 사용한 사례이다.
<form enctype=\"miltipart/form-data\" action=\"#\" method=\"POST\">
<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"100000\" />
</form>
히든 필드는 인증 시에도 세션 관리를 위해 사용한다. 다음은 DVWA의 CSRF 실습에서 "dvwa/includes/ dvwaPage.inc.php" 파일 내 tokenField() 함수를 정의하여 세션토큰 값을 반환 시 히든 필드를 사용한 사례이다.
function tokenField() { # Return a field for the(CSRF) token
return "<input type="hidden" name="user_token" value="{$_SESSION["session_token"]}" />";
}
이처럼 쿠키와 세션 뿐만 아니라 히든 필드를 통해 로그인에 대한 인증 값을 유지할 수 있다.
다. URI / URL / URN
1. URI(Uniform Resource Identifier)
URI는 인터넷에 존재하는 리소스를 고유하게 식별하고 위치를 지정하는 표기법(규약)이다. URI는 URL과 URN을 모두 포함하는 개념이다.
2. URL(Uniform Resource Locator)
URL은 인터넷 상 가용한 자원에 대해 문자(열)로 표현하는 것을 의미한다. 일반적으로 웹의 경우에 클라이언트가 서버로 HTTP 프로토콜을 통해 접속하기 위한 경로로 이해할 수 있다.
<scheme>:<scheme-specific-part>
scheme은 프로토콜의 종류를 의미하며, 프로토콜에 따라 URL 표기 방식이 달라진다.
예를 들어 FTP의 경우 "ftp://id:pass@host:port/path"의 형태로 표현이 가능하다.
웹의 경우 "http://host:port/path?query"와 같이 표현이 가능하다.
HTTP의 경우 웹 브라우저의 주소가 URL이라고 생각하면 된다.
3. URN(Uniform Resource Name)
URN은 지속적이면서 특정 위치의 독립적인 자원을 가리키는 지시자이다.
라. HTTP 메시지
1. 요청(Request) 메시지
클라이언트와 서버는 HTTP 프로토콜을 사용하는데 데이터를 패킷 단위로 나눠서 통신을 한다. 다음은 BurpSuite를 통해 DVWA의 Blind SQL Injectionn 공격 패킷을 캡쳐한 내용이다. 요청(Request) 메시지는 크게 (1) Request Line, (2) Reqeust Headers, (3) Message Body로 구성되어 있다.
1-가) Reqeust Line
Request Line은 HTTP 메소드, 클라이언트가 요청하는 Request URI, HTTP 버전으로 구성되어 있다. HTTP 메소드는 키워드 또는 메시지와 같은 개념으로 클라이언트가 웹서버에게 사용자 요청을 하기 위해 요청 목적이나 종류를 알리는 수단을 의미한다.
메소드 종류에는 GET, POST, HEAD, PUT, DELETE, TRACE, OPTIONS, CONNECT 등이 있다.
POST > Method
/dvwa/vulnerabilities/sqli_blind/ > Request URI
HTTP/1.1 > HTTP 버전
1-나) Request Headers
HTTP에서 Header는 General, Request, Entity의 3가지로 구분한다.
General Header: 요청과 응답 모두에 적용되지만 바디에서 최종적으로 전송되는 데이터와는 관련이 없는 헤더
Request Header: 패치될 리소스나 클라이언트 자체에 대한 자세한 정보를 포함하는 헤더
Entity Header: 컨텐츠 길이나 MIME 타입과 같이 엔티티 바디에 대한 자세한 정보를 포함하는 헤더
Request Header는 클라이언트 요청 및 클라이언트 자체에 대한 추가 정보를 웹 서버에 전달할 수 있게 한다. 요청 패킷의 주요 Request Header 내용은 다음과 같다.
- Host: 클라이언트가 요청한 서버 정보
- User-Agent: 클라이언트 브라우저의 이름, 버전
- Accept: 클라이언트가 허용할 수 있는 파일 형식(MIME_TYPE)
- Referrer: 현재 페이지가 어떤 웹 페이지에서 요청되었는지에 대한 정보
- Accept-Encoding: 클라이언트가 인식할 수 있는 인코딩 형식
- Accept-Language: 클라이언트가 익신할 수 있는 언어
1-다) Message Body
HTTP 메소드가 POST인 경우 HTTP Body 영역에 데이터를 넣어서 전송한다. GET 메소드는 URL에 데이터를 실어서 전달하기 때문에 HTTP Body 영역에는 아무것도 존재하지 않게 된다.
2. 응답(Response) 메시지
응답(Response) 메시지 또한 요청(Request)과 유사한 구조를 가지고 있으며 크게 (1) Status Line, (2) Response Header, (3) Message Body로 구성되어 ㅣㅇㅆ다.
2-가) Status Line
Status Line은 HTTP 버전(HTTP Version), 상태 코드(Status Code), 이유 구문(Reason Phase) 3가지로 구성되어 있다.
HTTP 버전은 현재까지 1.0, 1.1, 2.0으로 구분된다.
Status Code는 3자리의 정수로 구성된 결과 코드이며, HTTP 요청에 대한 응답의 결과가 모두 코드로 사전에 정의되어 있다.
이유 구문은 사용자가 이해할 수 있도록 상태 코드에 대한 간단한 설명이 기술되어 있다.
2-나) Response Header
Response Header는 서버가 Status Line에 없는 응답에 대한 추가적인 정보를 전달한다. 즉, Request-URI에 의해 식별되는 추가적으로 접근을 하고자 하는 자원과 서버에 대한 정보를 제공한다.
Accept-Ranges: bytes
서버가 자원에 대해 범위 요청을 수락할 수 있는데, 바이트(bytes) 단위의 범위 요청을 수락한다.
ETag: "307-55c9d62936140-gzip"
ETag는 요청한 변화에 대한 Entity 태그의 현재 값을 제공하며, HTTP 컨텐츠 변경 유무를 검사하는데 사용한다. Entity-tag는 다음과 같이 요청된 값을 고유 형태로 표시한다.
예를 들어, 클라이언트가 동일 URL로 재요청을 할 경우 ETag 값을 요청헤더에 포함시켜서 전송하고, 서버는 수신한 ETag 값과 현재 값을 비교하여 유효성을 검사한다. ETag가 동일하면 기존 데이터 변동이 없음을 알리는 HTTP 304를 반환하고, 동일하지 않을 경우 전체 응답을 전송한다.
Vary: Accept-Encoding
Vary는 클라이언트와 서버 사이의 캐싱을 위해 필요한 필드이다. 클라이언트가 서버에 데이터를 요청 시 중간의 캐시에 저장된 기존 데이터를 반환함으로써 서버의 성능 부하를 줄일 수 있다. 여기서 Vary 는 캐시에 저장된 기존 데이터를 반환할지 여부를 결정하는 역할을 수행한다. 예를 들어, 클라이언트의 요청의 Accept-Encoding이 gzip으로 반영 되어 있다고 가정하자. 서버에서 이를 수신 시 기존 캐쉬에 gzip이 저장되어 있으면 캐쉬에서 Accept-Encoding을 반환하고,그렇지 않을 경우 서버 측에서 처리하게 된다.
마. HTTP 관련 언어 / 기술
1. 자바스크립트(Javascript)
자바스크립트는 웹 페이지와 상호작용할 수 있도록 만들어진 스크립트 언어이다.
2. CSS(Cascading Style Sheets)
CSS 는 HTML, XML과 같은 문서의 스타일을 꾸미기 위해 사용하는 스타일시트 언어이다. HTML로는 웹 페이지의 뼈대를 만들고, CSS는 문서를 예쁘게 꾸며주는 역할을 한다.
일반적으로 HTML문서는 LINK 태그를 사용해서 CSS 파일을 읽어들인다. (HTML 문서 뿐만 아니라 PHP/ASP/JSP 등의 서버 사이드 스크립트 언어에서도 CSS를 로드할 수 있다.) LINK 태그는 HTML 내 외부 문서와의 연결을 지정하는 태그이다.
(1)사용자가 웹 브라우저에서 HTML 파일을 요청하면, (2) HTML 문서는 LINK 태그에 정의되어 있는 CSS 파일을 읽어와서 HTML 문서의 구조를 스타일링하고, (3) 결과를 사용자 웹 브라우저에 보여준다.
3. XML(eXtensible Markup Language)
4. HTML5
5. PHP(Hypertext Preprocessor PHP)
6. ASP(Active Server Page) / ASP.NET
ASP는 마이크로소프트가 인터넷 정보 서비스에서 개발한 언어로, 동적 웹 페이지 생성 용도로 사용하기 위한 서버 사이드 스크립트 언어이다.
7.JSP(Java Server Page)
JSP는 자바(Java)언어를 기반으로 하는 서버 사이드 스크립트 언어이다.
자바 언어를 기반으로 하기 때문에 자바 라이브러리를 가져다 쓸 수 있다. JSP 는 HTML 에 자바 코드를 포함시켜 동적인 웹 페이지를 구성할 수 있다.
클라이언트가 웹 브라우저에서 JSP를 요청하면 자바 서블릿(Servlet) 파일로 변환되며 웹 애플리케이션 서버에서 동작되면서 필요한 기능들을 처리하여 클라이언트에 응답 값을 반환한다.
1) 클라이언트가 웹 브라우저로 서버에 Book.jsp 파일을 요청
2) 서버는 JSP 컨테이너에 처리를 요청하고 JSP 컨테이너는 Book.jsp 파일을 찾아서 로드
3) JSP 컨테이너가 Book.jsp 파일을 자바 서블릿(Servlet) 파일인 BookServlet.java 파일로 변환
4) BookServlet.java 파일을 실행 가능한 BookServlet.class 파일로 컴파일
5) 메모리에 BookServlet.class 파일을 적재하고 실행 결과를 서버로 반환
6) 서버는 클라이언트의 웹 브라우저가 인식할 수 있는 페이지를 구성해서 응답
클라이언트가 웹 브라우저에서 JSP 파일을 요청하면 파싱 / 컴파일 로딩 등의 과정을 거쳐서 서버는 클라이언트가 요청한 웹 페이지 결과를 반환한다.
바. 웹 서버 / WAS / DB 의 이해
웹 서버(Web Server)란 사용자가 웹 브라우저 등을 통해 HTTP(S)와 같은 프로토콜로 데이터를 요청했을 때, 데이터를 처리한 다음 사용자에게 결과를 HTML 형태로 응답해주는 역할을 한다.
웹 서버는 PHP, JSP, ASP와 같은 서버 사이드 언어를 지원하며, 데이터베이스와의 연동을 통해 데이터를 조회하고 수정한다.
웹 서버에서 서버 사이드 언어를 지원할 수 있도록 도와주는 Apache, nginx, Java, WebtoB, IIS 등의 웹 애플리케이션이 필요하다.
웹 서버는 정적인 데이터를 처리하고 WAS(Web Application Server)는 동적인 데이터를 처리하도록 하는 것이 처리 속도면에서 효율적이. 주로 WEB 서버는 캐시 기능이나 프록시 기능 등 웹 클라이언트와 직접 연관된 일을 처리하고, WAS는 애플리케이션과 관련된 기능 및 데이터베이스와의 통신을 수행한다.
웹 브라우저 <-> 웹 서버 <-> WAS <-> 데이터베이스/애플리케이션
기능적인 목적뿐만 아니라 보안적인 측면에서도 웹 서버와 WAS를 분리하는 것이 좋다.
웹 서버에 웹쉘 업로드 등의 침해가 내부 시스템 영역으로 확장되는 것을 방지할 수 있기 때문이다.