웹 어플리케이션에서 많이 나타나는 취약점의 하나로 웹 사이트 관리자가 아닌 이가 웹 페이지에 악성 스크립트를 삽입할 수 이는 취약점이다. 주로 여러 사용자가 보게 되는 전자 게시판에 악성 스크립트가 담긴 글을 올리는 형태로 이루어진다. 이 취약점으로 해커가 사용자의 정보( 쿠키, 세션 등 )를 탈취하거나, 자옫ㅇ으로 비정상적인 기능을 수행하게 하거나 할 수 있다.
❑ 반사형( Reflected ) XSS
공격 스크립트가 삽입된 URL을 사용자가 쉽게 확인할 수 없도록 변형시킨 후 이메일이나 다른 웹 사이트 등에 클릭을 유도하도록 하는 방법
❑ 저장형( Stored ) XSS
스크립트를 웹 서버에 저장하여 일반 게시판 등에 공격자가 게시글에 스크립트를 삽입하여 사용자가 해당 페이지를 클릭하는 순간 스크립트가 실행되도록 하는 방법이다.
입력란에 다음 스크립트를 실행하면 아래 그림처럼 공격이 성공되는 것을 볼 수 있다.
<script>alert("XSS Test!!");</script>
- 취약점 점검 방법
✓ 게시판에 HTML 코드나 자바스크립트가 삽입 가능한지 확인한다.
✓ 사이트의 검색란에 HTML 코드나 자바스크립트가 삽입 가능한지 확인한다.
✓ 서버 에러 메시지를 조작하여 HTML 코드나 자바스크립트가 삽입 가능한지 확인한다.
- 대응조치
✓ 사용자용 게시판 등과 같은 매개체들에 사용자 입력값 검증루틴을 거친다.
✓ 어플리케이션 차원에서 HTTP 헤더, HTML, Javascript/VBScript, Flash, GIF/JPG, 쿠키, 쿼리 스트링, 폼 필드, 히든 필드 등의 모든 인자( Parameter )들에 대해 허용된 유형의 데이터만 입력할 수 있도록 한다.
웹 기반 소프트웨어로써 ( 기능적으로 ) 사용자 입력을 기반으로 동작하고, 종종 이면의 시스템과 상호작용하는 일체의 웹 기반 소프트웨어라고 한다. 즉, 사용자가 웹 사이트와 상호작용하여 로그인하든가 쇼핑이나 전자 금융거래를 한다면 그것이 바로 웹 어플리케이션이다.
- 웹 서버에 대해 알아야 할 것
웹 서버는 서버의 운영체제 위에서 돌아가는 한 뭉치의 소프트웨어일 뿐이며 웹 어플리케이션이 접근하는 것을 허용한다. 가장 대표적인 웹 서버는 윈도우 서버에서의 인터넷 정보 서비스( IIS )와 리눅스 서버에서의 아파치( HTTP )가 있다. 이러한 서버들은 일반적인 컴퓨터와 같은 디렉터리 구조를 갖고 있는데, 바로 그 곳에 웹 어플리케이션이 자리잡는다.
윈도우에서 IIS 웹 서버를 설치하면 C:/Inetpub/wwwroot 디렉터리에 설치되며, wwwroot 다음 응용 프로그램이 각각의 디렉터리를 가지며 그 속에 모든 중요한 웹 어플리케이션의 자원이 포함된다.
리눅스는 대개의 웹 어플리케이션이 /var/www/ 디렉터리에 위치한다. 리눅스 웹 서버에서는 다음과 같이 특별히 웹 해킹과 관련된 몇 개의 디렉터리가 있다.
❑ /ect/shadow : 이 파일에 시스템의 모든 사용자 비밀번호 해쉬 값이 저장된다.
❑ /usr/lib : 이 디렉터리에는 일반 사용자나 쉘 스크립트로 실행되지 않는 오브젝트 파일과 내부 바이너리
를 포함한다. 또한 응용 프로그램에서 사용하는 모든 의존성 데이터 역시 이 디렉터리에 있다.
❑ /var/* : 이 디렉터리에는 데이터베이스에 관련된 파일, 시스템 로그, 웹 어플리케이션 자체의 소스코드
가 있다.
❑ /bin : 이 디렉터리는 쉘, ls, grep 과 같은 프로그램은 물론이고 시스템이 동작하는 데 필요한 기본적이
고 중요한 실행 파일을 갖고 있다.
- HTTP에 대해 알아야 할 것
HTTP는 웹 어플리케이션과 상호 동작하고 통신하는 것으로 합의된 프로세스다. HTTP 프로토콜은 상태를 관리하지 않는 프로토콜이므로 이전의 요청 상황을 알지 못한다. 따라서 모든 클라이언트의 요청과 웹 어플리케이션의 응답은 완전히 새롭고 독립적인 사건일 뿐이다.
❍ HTTP 사이클
브라우저는 사용자가 입력한 값을 매개변수에 담아 요청으로 보내면 웹 서버는 제출된 요청이 지시하는 응답을 회신한다. 웹 어플리케이션은 매개변수 값에 근거하여 동작하기 때문에 해커가 웹 어플리케이션과 웹 서버를 공격할 때 악의적인 값을 입력하여 공격하는 가장 중요한 목표물이 된다.
❍ HTTP 헤더
❑ 웹 서버가 설정해서 클라이언트 브라우저에 보내주는 주요 헤더 정보
✓ Set-Cookie : 이 값은 사용자의 세션이 유지되도록 보장하기 위하여 가장 흔하게 클라이언트에 제
공하는 세션 식별자( 쿠키 )다.
✓ Content-Length : 이 값은 응답문의 바이트 단위 길이다.
✓ Location : 이 값은 응용프로그램이 사용자를 다른 페이지로 보낼 때 사용된다.
❑ 클라이언트 브라우저가 웹 서버에 보내는 주요 헤더 정보
✓ Cookie : 하나( 또는 여러 개 )의 쿠키는 사용자의 세션을 유지하기 위해 헤더에 담겨 서버로 되돌
려 보내진다. 이 쿠키의 헤더 값은 서버가 set-cookie로 발행한 헤더 값과 언제나 일치해
야한다. 이 값은 응용프로그램의 유효한 세션 값을 제공하므로 다른 응용프로그램 사용자
를 공격할 때 사용할 수 있다.
✓ Referrer : 이 헤더 값은 다른 웹 페이지를 요청할 때 이전에 열었던 페이지를 목록으로 만든다. 이
헤더 값은 곧 "마지막으로 방문한 페이지"를 뜻하며, 이 값은 쉽게 바꿀 수 있다.
❍ HTTP 상태 코드
❑ 100번대 : 웹 서버가 순수하게 정보를 알려주기 위한 것으로, 보통 웹 서버가 보충 응답을 보낼 것임을
나타낸다.
❑ 200번대 : 클라이언트의 요청이 성공적으로 접수되고 웹 서버가 처리한 다음 그 응답이 브라우저로 되
돌려 보내졌음을 뜻한다.
❑ 300번대 : 다른 페이지로 돌리는 경우 표시한다. 사용자가 웹 어플리케이션에 성공적으로 인증한 후에
브라우저를 안전한 페이지로 전달할 때 가장 많이 사용된다.
❑ 400번대 : 클라이언트로부터 온 요청에 오류가 있음을 나타낸다. 즉, 사용자가 보낸 요청을 웹 어플리케
DOS Stub Code는 필수 구성 요소가 아니기 때문에 DOS Stub Code가 없더라도 프로그램이 실행되는 데는 아무런 지장이 없다.
DOs Stub Code는 도스 모드에서 실행시켰을 때 실행되는 코드이며, 보통 "This Program must be run under Microsoft Windows"라는 메시지를 출력하고 종료되는 코드가 삽입된다. 또는 오브젝트 파일을 링킹할 때 STUB 옵션을 이용하여 원하는 스텁 코드를 삽입할 수 있다는 점 정도만 알아두면 된다.
- PE 만들기 1
PE 파일 제작의 첫번째 단계는 DOS Header를 만들기다.
Hex 에디터를 열고 64바이트의 새 파일을 생성한다. ( 필자는 HxD를 이용한다 )
[편집]-[바이트 삽입] 메뉴를 선택하고 64바이트를 생성한다.
[그림 1] 64 바이트 크기의 새로운 파일 생성
[그림 2]와 같이 처음 2 바이트 부분의 값을 "4D 5A"로 수정한다. 이는 DOS Header의 시그니처인 MZ를 의미한다.
[그림 2] DOS 시그니처 입력
[그림 3]과 같이 마지막 4바이트의 값을 0x40으로 설정한다. DOS Stub Code는 생략이 가능하기 때문에 생략하도록 한다. 즉, DOS Header 다음에 바로 PE Header가 온다. 그리고 기본적으로 리틀엔디안 방식이므로 40 00 00 00으로 입력해야 한다.
PE( Portable Executable )는 윈도우 운영체제에서 사용되는 실행파일, DLL, object 코드 등을 위한 파일형식이다. 이는 윈도우 로더가 실행 가능한 코드를 관리하는데 필요한 정보를 캡슐화한 데이터 구조체이다.
2. PE 구성요소
PE는 위와 같은 구조를 갖고 있으며, DOS stub은 PE 파일의 필수 구성요소가 아니기 때문에 생략이 가능하다.
- DOS Header
PE 파일은 DOS Header로 시작한다. 따라서 디스크 상에서는 파일의 첫 부분이 DOS header가 된다. 메모리 상에서 PE 파일은 ImageBase에서 시작하기 때문에 DOS header는 ImageBase에서 찾을 수 있다.
stud_PE 프로그램으로 Test.exe 파일을 열었을 때 확인할 수 있는 PE 헤더의 일부분이다.
실제로 해당 위치에 존재하는지 Immunity Debugger로 확인을 하면 다음과 같다.
00400000 번지에 MZ 문자가 찍혀있는 것을 볼 수 있다.
MZ는 DOS Header의 시그니처다. 이로써 메모리에 Image base에 DOS Header가 로드됨을 알 수 있다.
- DOS stub
윈도우용 어플리케이션을 도스 모드에서 실행시킨 경우 어플리케이션이 정상적으로 동작하지 않는다. 이러한 경우 윈도우는 어플리케이션 대신에 스텁 코드를 실행한다. 스텁 코드에는 DOS 모드에서 실행 가능한 프로그램이면 어느 것이나 삽입이 가능하다.
- PE Header
PE Header는 위와 같은 구조체로 정의되어 있다.
디스크 상이나 메모리 상에서 PE 헤더의 위치는 DOS Header에 있는 e_lfanew 값을 이용하여 계산할 수 있다. e_lfanew는 DOS Header구조체의 마지막에 위치한다.
e_lfanew에는 파일의 시작점에서부터 PE 헤더까지의 오프셋 값이 저장되어 있다.
Hex 에디터로 열어보게 되면 위와 같이 DOS Header 마지막에 e_lfanew 값이 들어 있고, 이 값과 DOS Header의 시작 주소를 더하면 PE Header를 찾을 수 있다.
- 섹션 테이블
섹션 테이블은 PE Header 바로 뒤에 위치한다. 즉, 섹션 테이블을 찾으려면 PE Header 시작 주소에서 PE Header 사이즈를 더해주면 된다.
PE 헤더는 PE 시그너처( 4바이트 고정 )와 File Header( 20바이트 고정 ) 그리고 Optional Header( 224바이트, 가변 )로 구성되어 있다. Option Header의 크기는 File Header에 저장되어 있다.
- 섹션 위치
각 섹션의 위치는 섹션 테이블에 저장된 섹션 헤더를 통해서 확인이 가능하다. 섹션 헤더에는 해당 섹션의 위치와 관련하여 Virtual Address라는 값과 PointerToRawData라는 값이 저장되어 있다. PointerToRawData는 디스크 상의 섹션의 위치를 가리키는 offset 값이고, VirtualAddress는 메모리 상에서의 section의 위치를 가리키는 offset 값이다.
Stud_PE로 Section Header를 보면 위와 같다.
.text 섹션의 RawOffset 값이 0x200임을 알 수 있다. 이는 디스크 상의 .text 섹션이 파일의 시작점으로부터 0x200 떨어진 곳에서 시작한다는 것을 의미한다.
마우스 오른쪽 클릭한 후 "GoTo Section Start"를 선택하면 .text 섹션의 시작 위치로 이동할 수 있다.
Cursor를 첫번째 바이트에 위치하고 하단 정보를 확인하면 Cursor offset이 앞서 살펴본 PointerToRawData 값과 같음을 확인할 수 있다. Virtual offset 값은 ImageBase 값인 0x400000에 Virtual offset 값인 0x1000을 더하면 된다.
Immunity Debugger로 보면 위와 같다.
* PE 파일은 디스크 상의 모습과 메모리 상의 모습이 거의 같다.
DOS Header에서 Section table까지의 구성은 디스크 상의 PE 파일이나 메모리 상의 PE 파일 모두 동일하다. 이는 디스크 상의 PE 파일이 메모리로 로드될 때 DOS Header부터 Section table까지는 그대로 로드됨을 의미한다. 차이가 발생하는 부분은 각 세션인데, 이는 alignment와 관련이 있다. alignment와 관련해서 기억해야 할 사실은 아래와 같다.
> 섹션들의 디스크 상의 정렬 단위와 메모리 상의 정렬단위가 다를 수 있다.
> 디스크 상의 정렬 단위와 메모리 상의 정렬 단위는 각각 Optional Header의 File Alignment와 Section Alignment에 저장된다.
" 후입선출( LIFO : Last In First Out ) 방식에 의해 정보를 관리하는 데이터 구조. 스택에는 TOP이라고 불리는 스택의 끝부분에서 데이터의 삽입과 삭제가 발생한다. 즉, 스택에 데이터를 삽입하면 TOP 위치에 정보가 위치한다. 그리고 스택에서 정보를 읽어오려 하면 스택의 TOP 위치에 있는 정보가 반환된다. 따라서 스택에는 가장 나중에 삽입된 정보가 가장 먼저 읽히는 특징이 있다. "
컴퓨터 메모리상의 스택은 프로그램의 함수 내에서 정의되는데, 함수 종료와 동시에 사라지는 자동 변수가 저장되고 함수가 호출될 때 함수 내 로컬 변수 등이 저장되는 곳이다. 스택에 저장된 로컬 변수는 함수가 실행되는 동안만 존재하며 함수 실행이 종료되면 해당 변수들도 사라진다.
- 힙
" 프로그램의 실행 중 필요한 기억 장소를 할당하기 위해 운영체제에 예약되어 있는 기억 장소 영역. 프로그램 실행 중에 데이터를 저장하기 위해 기억 장소를 요청하면 운영체제는 힙에 존재하는 기억 장소를 프로그램에 할당한다. 프로그램에서는 기억 장치가 더 이상 필요 없으면 할당받았던 기억 장소를 운영체제에 반납하는데, 이때 운영체제에서는 반납된 기억 장소를 다시 힙에 돌려준다. 힙에 대한 기억 장소는 포인터를 통해 동적으로 할당되거나 반환되며 연결 리스트, 트리, 그래프처럼 동적인 특성이 있는 데이터 구조에서 널리 사용된다. "
힙은 프로그램이 실행될 때까지 미리 알 수 없는 가변적인 양의 데이터를 저장하기 위해, 프로그램의 프로세스가 사용할 수 있도록 예약되어 있는 메인 메모리의 영역이다.
- 데이터 세그먼트
초기화된 데이터 세그먼트라고도 불리며, 초기화된 외부 변수나 static 변수 등이 저장되는 영역이다.
- BSS 세그먼트
초기화되지 않은 데이터 세그먼트라고도 불리며, 프로그램이 실행될 때 0이나 NULL 포인터로 초기화되는 영역이다.
- 텍스트 세그먼트
CPU에 의해 실행되는 머신 코드가 있는 영역으로, EIP가 다음에 실행하는 명령을 가리키고 있다.