설명
명령어 주입 취약점은 사용자의 입력값이 검증 없이 운영 체제 명령어로 실행될 때 발생합니다. Node.js의 child_process.exec와 execSync는 셸을 사용합니다. spawn과 spawnSync는 기본적으로 셸을 사용하지 않지만, shell: true를 설정하거나 아래처럼 sh -c에 입력을 넘기면 공격자가 셸 명령을 삽입할 수 있습니다. 실행 파일이나 인자를 사용자가 선택하는 경우에도 허용할 동작을 제한해야 합니다.
잠재적 영향
- 애플리케이션 프로세스의 권한으로 의도하지 않은 명령이 실행될 수 있습니다.
- 데이터 유출 및 변조 (중요 파일 접근이나 데이터 삭제)
- 서비스 마비 (DoS, 시스템 장애 등)
해결 방법
- 사용자 입력을 명령 문자열로 실행하지 말고, 고정된 실행 파일과 검증한 인자 배열을 사용하세요.
- 입력으로 동작을 선택해야 한다면 허용 목록으로 제한하세요.
sh -c처럼 입력을 다시 코드로 해석하는 인터프리터 호출을 피하고, 실행 파일의 위치와PATH를 신뢰할 수 있게 관리하세요.
예시
변경 전
javascript
const {spawnSync} = require('child_process');
function runCommand(userInput) {
// 취약: 사용자가 입력한 명령어를 직접 실행
spawnSync('sh', ['-c', userInput]);
}
변경 후
javascript
const {spawnSync} = require('child_process');
function runCommandSafe(userInput) {
// 안전: 입력값을 미리 정의된 명령에만 사용
const allowedCommands = ['ls', 'pwd'];
if (!allowedCommands.includes(userInput)) {
throw new Error('허용되지 않은 명령어입니다.');
}
spawnSync(userInput, []);
}
설명:
- 변경 전:
userInput을sh -c에 전달해 셸 명령으로 실행합니다. - 변경 후: 입력을
ls와pwd로 제한하고 셸 없이 실행합니다. 이 이름이 의도한 실행 파일로 해석되도록 신뢰할 수 있는PATH를 사용해야 합니다.