가이드라인

명령 주입(Command Injection)

우선 명령 주입 그 자체에 대해 살펴보겠습니다. 실제 공격이 어떻게 이루어지는지 쉽게 이해할 수 있도록 몇 가지 사례를 중심으로 다룰 예정입니다. 간단히 복습하자면, 명령 주입 취약점은 다음 함수처럼 사용자 입력값이 운영 체제 명령의 일부로 사용될 때 발생합니다.

let ip = request.params.ipAddress;

system("ping " + ip);

사용자가 IP 주소로 `8.8.8.8`을 입력하면, 실행되는 명령은 `ping 8.8.8.8`이 되어 예상대로 작동합니다. 하지만 사용자가 `8.8.8.8 && ls /etc/`를 입력하면, 이 명령은 단순히 IP 8.8.8.8에 핑을 보내는 것에 그치지 않고 `/etc/` 폴더에 대해 `ls` 명령까지 실행하게 됩니다.

완화 방법

명령 주입 공격의 심각성을 고려할 때, 시스템 명령을 다룰 때 반드시 스스로에게 물어봐야 할 중요한 질문들이 있습니다.

  • 정말로 해당 명령을 호출해야 하나요? 가장 좋은 방어책은 시스템 명령을 아예 호출하지 않는 것입니다.
  • 시스템 명령을 사용하지 않고도 동일한 효과를 낼 수 있는 라이브러리나 바인딩이 있나요?
  • 명령어 자체에 데이터를 포함하는 대신 표준 입력(Standard In)을 통해 데이터를 전달할 수 있나요?

이러한 방법이 불가능하다면, 매개변수화(parameterization)가 중요합니다.

예시

실제 적용 사례를 이해하기 쉽게 다양한 언어로 된 몇 가지 예시를 살펴보겠습니다.

매개변수화를 사용하지 않으면 명령 주입 공격에 취약합니다.

string folder = "/tmp/ && ifconfig";
string cmd =  "\"ls " + folder +"\"";

// 보안 취약: `ls`와 `ifconfig` 명령을 모두 실행함
System.Diagnostics.Process.Start("bash", "-c " + cmd);

C# - 보안 적용

명령을 매개변수 목록으로 제공하면 명령이 매개변수화되어 명령 주입으로부터 보호됩니다.

string folder = "/tmp/ && ifconfig";
List<string> arguments = new List<string>() {"-c", "ls", folder}; 

// 보안 적용: ifconfig 명령을 실행하지 않음
System.Diagnostics.Process.Start("bash", arguments);

Java - 취약함

매개변수화를 사용하지 않으면 명령 주입 공격에 취약합니다.

String folder = "/tmp/ && ifconfig";

// 보안 취약: `ls`와 `ifconfig` 명령을 모두 실행함
ProcessBuilder b = new ProcessBuilder("bash -c ls " + folder);

Process p = pb.start();

Java - 보안 적용

명령을 매개변수 목록으로 제공하면 명령이 매개변수화되어 명령 주입으로부터 보호됩니다.

String folder = "/tmp/ && ifconfig";

// 보안 적용: ifconfig 명령을 실행하지 않음
ProcessBuilder b = new ProcessBuilder("bash", "-c", "ls", folder);

Process p = pb.start();

Javascript - 보안 취약

매개변수화를 사용하지 않으면 명령 주입 공격에 취약합니다.

const { exec } = require("child_process");

const folder = "/tmp/ && ifconfig";

// 보안 취약: `ls`와 `ifconfig` 명령을 모두 실행함
const ls = exec("bash -c ls " + folder, (error, stdout, stderr) => {
     console.log(`stdout: ${stdout}`);
});

Javascript - 보안 적용

const { spawn } = require("child_process");

const folder = "/tmp/ && ifconfig";

// 안전함: ifconfig 명령을 실행하지 않음
const ls = spawn("bash", ["-c", "ls", folder]);

ls.stdout.on("data", data => {
    console.log(`stdout: ${data}`);
});

Python - 보안 취약

매개변수화를 사용하지 않으면 명령 주입(Command Injection) 공격에 취약합니다.‍

import subprocess

folder = "/tmp/ && ifconfig"

# 보안 취약: `ls`와 `ifconfig` 명령을 모두 실행함
subprocess.run("bash -c ls " + folder, shell=True)

Python - 보안 적용

명령어를 매개변수 목록으로 제공하면 매개변수화가 이루어져 명령 주입 공격으로부터 보호됩니다.
‍

import subprocess

folder = "/tmp/ && ifconfig"

# 안전함: ifconfig 명령을 실행하지 않음
subprocess.run(["bash", "-c", "ls", folder])

‍

태그라인

실무에 바로 적용하는 보안 코딩

OWASP Top 10과 같은 소프트웨어 취약점을 이해하고 완화하기 위한 보안 코딩 가이드라인을 살펴보고, 실제 앱 시뮬레이션을 통해 실습할 수 있는 가이드형 교육 미션을 시작해 보세요.

추가 가이드라인
데모 예약하기