[시큐어 코딩] #5 위험한 형식 파일 업로드 :: 잡다한 프로그래밍
반응형

1. 위험한 형식 파일 업로드 정의

서버측에서 실행될 수 있는 스크립트파일(asp, jsp, php 파일 등)이 업로드 가능하고, 이 파일을 공격자가 웹을 통해 직접 실행 시킬 수 있는 경우 공격자는 스크립트 파일을 업로드하고, 이 파일을 통해 시스템 내부 명령어를 실행하거나 외부와 연결하여 시스템을 제어할 수 있다.

예를들어 다음과 같은 게시판에 악성 파일을 업로드하고 서버내에서 실행시키면 서버에 영향을 줄 수 있다.

2. 안전한 코딩기법

  • 업로드하는 파일 타입과 크기를 제한하고, 업로드 디렉터리를 웹서버와 분리하여 설정한다.
  • 허용된 확장자만 업로드되도록하고, 확장자도 대소문자 구분 없이 처리하도록 한다.
  • 공격자의 웹을 통한 직접 접근을 차단한다. 또한 파일 실행 여부를 설정할 수 있는 경우, 실행 속성을 제거한다.

3. 예시

사용자가 업로드하는 파일의 유효성을 검사하지 않으면, 위험한 유형의 파일을 공격자가 업로드하거나 전송할 수 있다.

public void upload(HttpServletRequest request) throws ServletException {
    MultipartHttpServletRequest mrequest = (MultipartHttpServletRequest) request;
    String next = (String) mrequest.getFileNames().next();
        MultipartFile file =  mrequest.getFile(next);
    // MultipartFile로부터 file을 얻음
    String filename = file.getOriginalFilename();
    // upload 파일에 대한 확장자 체크하지 않음
    File uploadDir = new File("/app/webapp/data/upload/notice");
        String uploadFilePath = uploadDir.getAbsolutePath()+"/" + fileName;
}

 

다음은 업로드 파일의 크기를 제한하고, doc, hwp, pdf, xls 확장자만 저장을 허용하며, 업로드 파일의 디렉터리 위치를 다큐먼트 루트의 밖에 위치시키는 방법이다.

public void upload(HttpServletRequest request) throws ServletException {
    MultipartHttpServletRequest mrequest = (MultipartHttpServletRequest) request;
    String next = (String) mrequest.getFileNames().next();
        MultipartFile file =  mrequest.getFile(next);
    if(file == null)
      return;
      
    //업로드 파일 크기를 제한한다
    int size = file.getSize();
    if(size > MAX_FILE_SIZE) throw new ServletException("에러");
    
    // MultipartFile로 부터 file을 얻음
    String fileName = file.getOriginalFilename().toLowerCase();
    
    // 업로드 파일의 확장자를 체크한다.
    if(fileName != null)
    {
    	if(fileName.endsWith(".doc") || fileName.endsWith(".hwp") 
        || fileName.endsWith(".pdf") || fileName.endsWith(".wls"))
        {
        	파일업로드함
        }
        else throw new ServletException("에러");
    }
    
    //업로드 파일의 디렉터리 위치는 다큐먼트 루트의 밖에 위치시킨다.
    File uploadDir = new File("/app/webapp/data/upload/notice");
    String uploadFilePath = uploadDir.getAbsolutePath()+"/" + fileName;
}

 

4. 추가적인방법

  • 웹 서버 내부 디렉토리에 실행권한을 주지 않는다. 즉 서버 내부에 파일을 실행할 수 없게하여 공격으로부터 대비한다
  • 파일이름 및 확장자를 암호화(난수화) 하여 저장한다. DB에 암호화된 파일명, 원래의 파일명, 파일크기, 확장자 등 정보를 저장한다면 사용자에게 원래의 파일명으로 화면에 뿌려주되 파일명은 암호회되어있어서 사용자는 직접적으로 접근할 수 없다. DB에 원래 파일명을 적어놓으므로 복호화 과정이 필요없어서 해쉬를 사용해도 괜찮을 것 같음(추측)
반응형

+ Recent posts