동적 require를 통한 Eval 주입 취약점

Eval Injection (Dynamic Require)

설명

동적으로 변수 값을 전달하여 require()를 사용할 경우, 사용자 입력이 직접적으로 동적 모듈 로딩에 사용되면 공격자가 의도하지 않은 자바스크립트 파일이나 악성 코드를 로드하여 실행시킬 수 있는 취약점이 발생합니다. 즉, 외부에서 전달되는 값이 파일 경로나 모듈 이름에 영향을 주면 공격자가 서버에서 접근하고 로드할 수 있는 모듈이나 파일을 선택하도록 유도할 수 있습니다.

잠재적 영향

  • 임의 코드 실행 (임의 코드 실행): 공격자가 악의적인 코드를 서버에서 실행할 수 있음
  • 민감 데이터 접근 (민감 데이터 노출): 공격자가 시스템이나 소스코드에 있는 중요한 정보에 접근할 수 있음
  • 서비스 무력화 (서비스 중단): 비정상적인 모듈을 불러와 서비스 장애를 발생시킬 수 있음

해결 방법

  • require에는 고정된 모듈 이름이나 신뢰할 수 있는 값만 전달하세요.
  • 동적으로 모듈이나 파일을 로드해야 한다면 허용 목록으로 선택 범위를 제한하세요.
  • 입력과 경로를 검증하고, 선택한 모듈을 통해 외부에 제공할 기능도 필요한 범위로 제한하세요.

예시

변경 전

javascript
function loadModule(moduleName) {
  // 사용자가 입력한 값을 그대로 require에 사용 (취약)
  return require(moduleName);
}

변경 후

javascript
function loadModule(moduleName) {
  // 미리 허용한 모듈 이름만 사용 (화이트리스트 적용)
  const allowedModules = ['fs', 'path'];
  if (!allowedModules.includes(moduleName)) {
    throw new Error('허용되지 않은 모듈입니다.');
  }
  return require(moduleName);
}

설명:

  • 변경 전: 사용자 입력인 moduleName을 그대로 require에 전달해 의도하지 않은 모듈을 로드할 수 있습니다.
  • 변경 후: 모듈 이름을 fs와 path로 제한해 다른 모듈이나 파일을 선택하지 못하게 합니다. 이 모듈로 수행할 파일 작업의 권한까지 제한하는 것은 아닙니다.

참조