← 목록으로

OS Command Injection: 원리와 필터 우회

[Web] Web · 작성: 2026-07-20 03:10:34 · 수정: 2026-07-20 03:11:15 · 조회 8

애플리케이션이 사용자 입력을 그대로(혹은 살짝 가공해서) 셸 명령의 일부로 넘길 때 생기는 취약점이다. SQL Injection이 DB 쿼리 문법을 깨는 거라면, Command Injection은 셸 문법을 깬다.

기본 원리

// 취약한 코드
const { execSync } = require('child_process');
execSync('ping -c 1 ' + req.query.host);

host8.8.8.8; cat /etc/passwd를 넣으면 셸은 세미콜론을 명령 구분자로 해석해서 두 번째 명령을 그대로 실행한다.

셸 메타문자와 필터 우회

공격자가 흔히 쓰는 구분자는 세미콜론, 파이프, &&, ||, 백틱, $()다. 필터링이 특정 문자만 막으면 다른 문자로 우회한다.

8.8.8.8 | id
8.8.8.8 & id
8.8.8.8 $(id)

공백까지 막힌 필터라면 \${IFS}(Internal Field Separator)로 공백을 대체하기도 한다: cat\${IFS}/etc/passwd

근본적인 방어: 셸을 아예 거치지 않기

필터링·이스케이프는 우회 가능성이 항상 남는다. 진짜 방어는 셸 인터프리터 자체를 거치지 않는 API를 쓰는 것이다.

// 안전: 인자를 배열로 분리해서 넘기면 셸 파싱을 거치지 않는다
const { execFileSync } = require('child_process');
execFileSync('ping', ['-c', '1', req.query.host]);

execFile/spawn은 인자를 배열로 받아서 OS에 직접 프로세스 실행을 요청하기 때문에, host 값에 셸 메타문자가 들어있어도 그냥 하나의 인자 문자열로만 취급된다. 애초에 셸 파싱 단계 자체가 없어서 우회가 불가능하다.

추가 방어

Web 카테고리의 글 (9/11)

  1. SQL Injection: 원리, 탐지, 방어
  2. XSS (Cross-Site Scripting): Stored / Reflected / DOM 차이와 방어
  3. CSRF (Cross-Site Request Forgery): 원리와 방어
  4. IDOR / BOLA: 권한 검증이 빠졌을 때
  5. SSRF (Server-Side Request Forgery): 서버가 대신 요청하게 만들기
  6. 파일 업로드 취약점: 웹쉘로 이어지는 경로
  7. 안전하지 않은 역직렬화 (Insecure Deserialization)
  8. SSTI (Server-Side Template Injection): 원리와 탐지
  9. OS Command Injection: 원리와 필터 우회
  10. JWT 취약점: alg=none부터 알고리즘 컨퓨전까지
  11. Race Condition (TOCTOU) 취약점
← SSTI (Server-Side Template Injection): 원리와 탐지 JWT 취약점: alg=none부터 알고리즘 컨퓨전까지 →