이클립스에서 File Upload 취약점이 발생하는 원인 찾기

이클립스에서 File Upload 취약점이 발생하는 원인 찾기

[보안 취약점 진단 및 대응/openeg] - openeg File Upload

 

openeg File Upload

openeg File Upload (1) Kali Linux에서 http://victim:8080/openeg사이트로 이동하여 로그인 합니다.(test / test) (2) 로그인 후 게시글을 작성합니다. (파일업로드) (3) 게시글을 확인하고 개발자도구(F12)에서 소스

psjin230.tistory.com


[BoardController.java에서 원인 찾기]

(1) eclipse에서 Ctrl + Shift + R을 눌러 BoardController.Java를 검색합니다.

 

(2) 문제가 되는 부분을 확인합니다.

=> 업로드 파일의 크기와 개수를 제한하지 않았습니다.

=> 외부에서 접근 가능한 Web Root Directory 아래에 원본 파일명으로 저장하고 있습니다.

=> 따라서 이 코드는 File Upload 취약점이 존재합니다.

 

(3) 문제가 있는 코드를 수정합니다.

 

(4) 실행결과

(4)-1 서버에서 실행가능한 JSP 파일 업로드

JSP 파일 업로드
업로드 실패

=> JSP 파일은 업로드 가능한 파일 확장자에 정의되어있지 않기 때문에 업로드 되지 않습니다.

=> 확장자 기반으로 업로드 제한!

 

(4)-2 2M 이하의 이미지 업로드

2M 이하의 이미지 업로드
업로드 결과

=> 이미지 명은 출력되는데 이미지는 출력이 안되고 있습니다.

=> 이 이미지는 서버에 저장 되었을까?

=> c드라이브를 확인해보면 upload 파일이 없습니다.

 

파일이 정장될 디렉토리(C:\upload\files)를 만들어주고 다시 시도합니다.

디렉토리 확인

=> 여전히 사이트에는 출력되지 않지만, C:\upload\files 디렉토리를 확인해보면 사진이 저장되어 있음을 확인할 수 있습니다.

 

사이트 소스를 확인해보면 업로드 파일을 Web Root Directory 아래에서 원본 파일명으로 참조하고 있기 때문에 출력되지 않는 것입니다.

소스코드 확인

=> 업로드한 파일은 Web Root Directory 아래에 있는 것이 아니라 웹에서 접근할 수 없는 C:\upload\files 아래에 있습니다.

=> 이런 방식으로는 파일을 보여줄 수 없는데 어떻게 해야할까요?

 

Web Root Directory 서버 경로

=> Web Root Directory에 소스코드와 같은 파일(../files/dog.jpg)이 존재하지 않기 때문에 출력이 되지 않고 있습니다.

=> 지금 업로드한 파일(dog.jpg)은 다른경로에 저장되어 있습니다.

 

파일 업로드 취약점을 보완하면 업로드 파일을 외부에서 접근할 수 없는 경로에 원본 파일명이 아닌 다른 이름으로 저장되기 때문에 URL 주소를 통해서는 접근할 수 없습니다. 따라서 다운로드 기능이 필요합니다.

=> 다운로드 기능은 접근할 수 없는 경로의 파일을 읽어서 반환하는 것입니다. 

=> 사용자 브라우저에서 서버가 가지고 있는 파일들(c:/~/~)을 막 가져갈 수 없습니다. 시스템의 중요한 파일들을 가져갈 수 있기 때문에 안됩니다. 따라서 사용자가 요청을 하면 정해진 기준 디렉토리 안에 있는 것들만 가져갈 수 있습니다. 기준 디렉토리는 외부에서는 알 수 없고, 사용자가 URL을 통해 경로를 요청하면, 그 경로가 실제 서버의 디렉토리에 맵핑이 되어 그 안에 있는 파일을 읽어서 반환하는 형태입니다.

 

(5) 파일 다운로드 기능을 추가합니다.

[BoardController.java]

BoardController.java

[view.jsp]

view.jsp

=> 첨부했던 파일을 URL이 아닌 다운로드 기능을 이용해서 내려받도록 수정하였습니다.

 

(6) 실행결과

=> 업로드 했던 게시글을 새로고침하면 다음과 같이 이미지를 볼 수 있습니다.

=> idx=22에서 id는 파일이 저장된 위치를 가지고 있는 정보를 참조하고 있는 값입니다.

=> idx로 id 값을 통해 파일명을 받아왔는데 만약 저장된 원본파일명을 그냥 넣게 되면 어떻게 될까요? 

 

[추가] 다운로드 기능을 잘못 구현하는 경우

(7) 잘못 구현하는 경우를 보기 위해 BoardController.java와 view.jsp를 수정합니다.

view.jsp
BoardController.java

 

(8) 실행결과

=> 추가한 코드도 사진이 나오는 것을 볼 수 있습니다.

=> 첫번째 방식은 id를 넘겨줘서 id를 조회하여 저장된 경로 파일명을 가져와서 읽어내는 방식입니다.

=> 두번째 방식은 매개변수로 저장된 파일명을 넘겨줘서 파일명을 직접적으로 공개합니다.

 

두번째 방식에서 이미지 다운로드 경로를 아래와 같이 변경 후 브라우저를 통해 요청합니다.

http://victim:8080/openeg/board/download2.do?file=../../../../../../../../Windows/System32/drivers/etc/hosts

=> 다운로드 받은 파일을 메모장으로 열어보면 해당 서버의 hosts 파일 내용을 볼 수 있습니다. 

=> 다운로드 기능을 구현할 때, 구현한 이유는 파일이 웹에서 접근할 수 없는 경로이기 때문이었습니다. 또한 웹에서는 접근할 수 없는 경로가 어디인지 모릅니다. ../를 사용하면 그 경로의 상위 디렉토리로 이동할 수 있게 됩니다.(경로조작) 그리고 계속 사용하다보면 해당 디렉토리의 최상위 root 까지 도달할 수 있습니다. 즉, 시스템 디렉토리까지 접근이 가능해서 시스템을 제어할 수 있기 때문에 문제가 됩니다. 따라서 (7) 잘못 구현하는 경우는 굉장히 위험한 방식입니다.