Resource Injection 공격이란?
외부 입력 값을 검증하지 않고 시스템 자원에 대한 식별자로 사용하는 경우, 공격자는 입력 값을 조작하여 시스템이 보호하는 자원에 임의로 접근하거나 수정할 수 있고 잘못된 입력값으로 인해 시스템 자원 사이에 충돌을 불러 일으킬 수 있다.
포트 번호를 사용자로부터 입력받는 경우를 예로 들어보자.
[안전하지 않은 코드]
public void service() throws IOException {
int def = 1000;
ServerSocket = serverSocket ;
Properties props = new Properties();
String fildName = "file_list";
FileInputStream in = new FileInputStream(filename);
props.load(in)
// 외부에서 입력한 데이터 받음
String service = props.getProperty("Service No");
int port = Integer.parseInt(service);
// 외부에서 입력받은 값으로 소켓 생성
if (port != 0)
serverSocket = new ServerSocket(port + 3000);
else
serverSocket = new ServerSocket(def + 3000);
....
}
위 코드와 같이, 내부자원에 접근할 때 외부 입력 값을 식별자로 직접 사용하는 것은 Resource Injection 을 불러 일으킬 수 있다. 필수적으로 사용되어야 하는 부분이 있다면, 사용 가능한 리스트를 설정한 후 해당 범위 내에서 할당되도록 작성해야한다.
[안전한 코드]
public void service() throws IOException {
int def = 1000;
ServerSocket = serverSocket ;
Properties props = new Properties();
String fileName = "file_list";
FileInputStream in = new FileInputStream(filename);
String service = "";
if (in != null && in.available() > 0) {
props.load(in)
service = props.getProperty("Service No");
}
if ("".equals(service)) service = "8080";
int port = Integer.parseInt(service);
// Secure Coding (범위 설정)
switch(port) {
case 1:
port = 3001; break;
case 2:
port = 3002; break;
case 3:
port = 3003; break;
default:
port = 3000;
}
// 서버 소켓에 검사완료된 포트 할당
serverSocket = new ServerSocket(port + 3000);
....
}
다른 예시를 통해, 더 알아보자.
예를 들어, 사용자가 특정 파일을 다운받으려고 한다. 그 때, Resource Injection 공격이 어떻게 발생할 수 있는지 알아보자.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
response.setStatus(HttpServletResponse.SC_OK);
String filename = request.getParameter("filename");
File file = new File("./files/" + filename);
if(!file.isFile()) {
PrintWrite out = response.getWriter();
out.write("<script type='text/javascript'> alert('"+filename+"은 존재하지 않습니다.'); history.back(); </script>");
}else {
...
}
}
위 코드에서는 필터링 없이 사용자에 의해 입력된 파일명을 통해 다운로드 처리하고 있음을 알 수 있다.
이와 같이, 사용자의 입력에 대해 필터링을 하지 않는다면, 공격자가 다른 디렉토리에 접근하여 다른 파일들을 탈취가 할 수 있게 된다.
그렇기 때문에, 아래와 같이 몇 가지 필터링 과정을 거쳐줄 필요가 있다.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
response.setStatus(HttpServletResponse.SC_OK);
String rfilename = request.getParameter("filename");
// Secure Coding
int p = rfilename.lastIndexof(".") ;
String extension = rfileName.substring(p + 1);
String filename = rfilename.substring(0, p);
filename = filename.replaceAll("[./&\]",""); // 정규표현식을 이용
filename = filename + "." + extension ;
File file = new File("./files/" + filename);
if(!file.isFile()) { // 파일 없는 경우
PrintWrite out = response.getWriter();
out.write("<script type='text/javascript'> alert('"+filename+"은 존재하지 않습니다.'); history.back(); </script>");
}else {
...
}
}
Resource Injection 을 막기위해, replaceAll 메소드에 정규 표현식을 활용하여 몇 가지 특수문자들을 필터링 시켜주었다. 위 코드는 공격을 막기 위한 샘플 코드 일 뿐이므로, 더 안전한 방식을 구현하기 위해서는 추가적인 필터링이 필요하다.
참고 문헌
[1] 시큐어 코딩 보안 가이드 https://www.kisa.or.kr/public/laws/laws3_View.jsp?mode=view
[2] HttpServletRequest https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html
[3] HttpServletResponse https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html
'Web Security > Secure Coding' 카테고리의 다른 글
시큐어 코딩 (Open Redirect) (0) | 2021.07.30 |
---|---|
시큐어 코딩 (File upload vulnerability) (0) | 2021.07.30 |
시큐어 코딩 (Command Injection) (0) | 2021.07.29 |
시큐어 코딩 (Cross-Site Scripting) (0) | 2021.07.29 |
시큐어 코딩 (SQL Injection) (0) | 2021.07.28 |