이 기사에서는 일반적인 명령 줄 주입 취약점을 피하기 위해 Node.js를 사용하여 시스템 명령을 올바르게 호출하는 방법을 배웁니다.
명령을 호출하는 데 종종 사용하는 방법은 가장 간단한 child_process.exec입니다. 매우 간단한 사용 패턴이 있습니다. 문자열 명령으로 전달하고 콜백 함수에 오류 또는 명령 처리 결과를 전달합니다.
다음은 child_process.exec을 통한 호출 시스템 명령의 매우 일반적인 예입니다.
코드 사본은 다음과 같습니다.
child_process.exec ( 'ls', function (err, data) {
Console.log (데이터);
});
그러나 호출하는 명령에 사용자가 제공 한 매개 변수를 추가해야 할 때 어떻게됩니까? 명백한 해결책은 사용자 입력을 명령으로 직접 문자하는 것입니다. 그러나 나의 수년간의 경험은 나에게 말한다 : 당신이 한 시스템에서 다른 시스템으로 연결된 문자열을 보낼 때, 언젠가 문제가있을 것이다.
코드 사본은 다음과 같습니다.
var path = "사용자 입력";
child_process.exec ( 'ls -l' + path, function (err, data) {
Console.log (데이터);
});
연결 문자열에 문제가있는 이유는 무엇입니까?
child_process.exec 엔진에서 "/bin/sh"실행이 호출되기 때문에. 대상 프로그램이 아닙니다. 보낸 명령은 방금 쉘을 실행하기 위해 새로운 "/bin/sh '프로세스로 전달됩니다. child_process.exec의 이름은 다소 오해의 소지가 있습니다. 이것은 프로그램이 아닌 bash 통역사입니다. 이는 모든 쉘 문자가 사용자가 입력 한 매개 변수가 직접 실행되면 치명적인 결과를 초래할 수 있음을 의미합니다.
코드 사본은 다음과 같습니다.
[PID 25170] execve ( "/bin/sh", [ "/bin/sh", "-c", "ls -l 사용자 입력"], [/ * 16 vars */]
예를 들어, 공격자는 세미콜론을 사용할 수 있습니다 ";" 명령을 종료하고 새 통화를 시작하려면 백 티크 또는 $ ()를 사용하여 하위 통과를 실행할 수 있습니다. 잠재적 인 학대도 많이 있습니다.
그렇다면 그것을 부르는 올바른 방법은 무엇입니까?
execfile / spawn
Spawn 및 Execfile은 다른 명령을 실행할 수 있고 추가 명령을 실행하지 않는 쉘 환경이 아닌 추가 배열 매개 변수를 사용합니다.
Execfile 및 Spawn을 사용하여 이전 예제를 수정하여 시스템 호출이 어떻게 다른지, 왜 명령 주입에 취약하지 않은지를 확인합시다.
child_process.execfile
코드 사본은 다음과 같습니다.
var child_process = require ( 'child_process');
var path = "."
child_process.execfile ( '/bin/ls', [ '-l', path], function (err, result) {
Console.log (결과)
});
실행 시스템 호출
코드 사본은 다음과 같습니다.
[PID 25565] execve ( "/bin/ls", [ "/bin/ls", "-l", "."], [/ * 16 vars */]
child_process.spawn
스폰 교체를 사용하는 예는 매우 유사합니다.
코드 사본은 다음과 같습니다.
var child_process = require ( 'child_process');
var path = "."
var ls = child_process.spawn ( '/bin/ls', [ '-l', path]))
ls.stdout.on ( 'data', function (data) {
console.log (data.toString ());
});
실행 시스템 호출
코드 사본은 다음과 같습니다.
[PID 26883] execve ( "/bin/ls", [ "/bin/ls", "-l", "."], [/ * 16 vars */
Spawn 또는 Execfile을 사용하는 경우 목표는 하나의 명령 (매개 변수) 만 실행하는 것입니다. 이것은 /bin /ls가 백티크 또는 파이프를 처리하는 방법을 모르기 때문에 사용자가 주입 된 명령을 실행할 수 없음을 의미합니다. /bin /bash가 설명하는 것은 해당 명령의 매개 변수입니다. 매개 변수를 사용하여 매개 변수를 SQL 쿼리로 전달하는 것과 비슷합니다.
그러나 경고도 있습니다. 스폰 또는 execfile을 사용하는 것이 항상 안전하지는 않습니다. 예를 들어, Running /Bin /찾기 및 사용자 입력 매개 변수를 전달하면 시스템이 여전히 갇히게 될 수 있습니다. Find 명령에는 임의 파일의 읽기/쓰기를 허용하는 몇 가지 옵션이 있습니다.
따라서 Node.js 실행 시스템 명령에 대한 지침은 다음과 같습니다.
child_process.exec 사용을 피하십시오. 특히 사용자가 입력 한 매개 변수를 포함 해야하는 경우 기억하십시오.
사용자가 매개 변수를 전달하도록하지 마십시오. 선택을 사용하는 것이 사용자가 문자열을 직접 입력하는 것보다 훨씬 낫습니다.
사용자가 매개 변수를 입력하도록 허용하는 경우 명령의 매개 변수를 광범위하게 참조하고 안전한 옵션을 결정하고 화이트리스트를 만듭니다.