운영체제 명령어 주입
OS Command Injection
설명
운영체제 명령어 주입은 애플리케이션이 사용자 입력을 검증하지 않은 채 운영체제 명령으로 실행할 때 발생합니다. Go에서는 os/exec를 사용할 때 쉘(sh, bash 등)을 호출하거나, StdinPipe()로 쉘에 문자열을 써 넣는 패턴에서 특히 위험합니다. 사용자가 제공한 값에 쉘 메타문자(;, &&, |, $, ``, > 등)나 추가 명령을 섞으면, 원래 의도와 다른 시스템 명령이 실행될 수 있습니다. 공격자는 URL 파라미터, 쿠키, 요청 본문 등의 입력을 통해 명령어를 삽입하거나 이어붙여 임의의 코드 실행, 파일 삭제, 권한 상승 등을 시도할 수 있습니다. 예를 들어 "name; rm -rf /" 같은 입력을 쉘로 전달하면, 세미콜론 뒤의 명령까지 연달아 실행될 수 있습니다.
잠재적 영향
임의 명령 실행: 공격자가 서버에서 원하는 시스템 명령을 실행해 애플리케이션 제어를 탈취할 수 있음.
권한 상승: 취약한 프로세스 권한을 악용해 관리자(root) 권한 획득 시도 가능.
데이터 유출/변조: 시스템 파일 읽기·수정, 환경변수 노출 등을 통해 민감정보가 유출되거나 무단 변경될 수 있음.
서비스 거부(DoS): 무한 루프/고부하 명령 실행으로 자원을 고갈시켜 서비스 중단을 유발할 수 있음.
해결 방법
쉘을 우회한 실행: exec.Command("프로그램", "arg1", "arg2")처럼 인자를 분리해 전달하고, exec.Command("sh","-c", ...)나 bash에 StdinPipe()로 스크립트를 쓰는 패턴은 피합니다.
허용 목록(Allowlist): 실행 가능한 프로그램과 서브커맨드, 옵션을 코드에 고정하고, 외부 입력은 제한된 자리(예: ID, 파일 키)로만 사용합니다.
입력 검증: 꼭 입력을 인자에 넣어야 한다면 화이트리스트 기반 검증(예: ^[A-Za-z0-9._-]+$)을 적용하고, 쉘 메타문자(;, &, |, $, ``, > 등)를 차단합니다.
필요 시 인코딩/이스케이프: 불가피하게 쉘을 거쳐야 하는 경로라면 shellescape.Quote 같은 안전한 이스케이프를 적용하고 추가 명령이 연결되지 않도록 합니다.
최소 권한: 외부 명령을 저권한 사용자로 실행하고, 파일·디렉터리 접근권한을 최소화합니다.
타임아웃/리소스 제한: Context와 ulimit 등으로 실행 시간과 자원을 제한합니다.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드: 취약한 코드는 bash를 실행한 뒤 StdinPipe()에 사용자 입력을 그대로 씁니다. 사용자가 ;, &&, |, $( ) 같은 쉘 메타문자를 포함하면 원래 의도 외의 추가 명령이 실행될 수 있어 임의 명령 실행, 파일 삭제, 권한 상승 등이 가능합니다.
안전한 코드: 개선된 코드는 쉘을 사용하지 않고 exec.CommandContext로 프로그램과 인자를 분리해 전달합니다. 실행 가능한 명령은 허용 목록으로 제한하고, 불가피하게 인자로 사용자 입력을 넣는 경우 화이트리스트 정규식으로 검증합니다. 또한 타임아웃(Context)으로 실행 시간을 제한해 오남용을 줄입니다.
참조
Last updated