본문 바로가기
컴퓨터보안/웹서버

커맨드 인젝션 (Command Injection)

by 데이빗제이2 2024. 5. 21.

1. 커맨드 인젝션이란?

커맨드 인젝션은 악의적인 사용자가 시스템 명령어를 실행하도록 프로그램에 입력을 전달하여 시스템을 공격하는 기법입니다. 이는 사용자가 입력한 값이 검증되지 않고 시스템 명령어로 실행될 때 발생합니다. 주요 특징은 다음과 같습니다:

  • 간단하지만 치명적인 공격: 시스템 명령어를 통해 전체 시스템 제어를 시도할 수 있어 매우 치명적입니다.
  • 개발자의 입력 검사 필요: 개발자는 반드시 사용자 입력을 철저히 검사하고, 가능하다면 system 함수를 사용하지 않아야 합니다.

2. 커맨드 인젝션 예제

@app.route('/ping')
def ping():
    ip = request.args.get('ip')
    return os.system(f'ping -c 3 {ip}')

위 코드는 URL 쿼리를 통해 전달되는 ip 값을 ping 명령어의 인자로 전달합니다. 사용자가 127.0.0.1을 입력하면 의도한 대로 작동하지만, 악의적인 사용자가 명령어를 조작할 수 있습니다.

3. 명령어 및 메타 문자 설명

  • ping: 네트워크 유틸리티로 특정 IP 주소로 ICMP 에코 요청을 보내 해당 호스트와의 네트워크 연결 상태를 확인합니다.
  • -c: ping 명령어의 옵션으로, 보낼 패킷 수를 지정합니다. 예: -c 3은 3개의 패킷을 보냅니다.
  • 1.1.1.1: 타겟 IP 주소 예시.
  • id: 시스템의 사용자 및 그룹 정보를 출력합니다.

4. 메타 문자 설명 및 예제

  • ;: 명령어 구분자. 앞 명령어의 성공 여부와 관계없이 다음 명령어를 실행.
    예: ping -c 3 1.1.1.1 ; id
  • &&: 논리적 AND. 앞 명령어가 성공해야 다음 명령어를 실행.
    예: ping -c 3 1.1.1.1 && id
  • |: 파이프. 앞 명령어의 출력을 다음 명령어의 입력으로 전달.
    예: ping -c 3 1.1.1.1 | id
  • ` ``: 명령어 치환. 안에 들어있는 명령어를 실행한 결과로 치환.
    예: echo `echo theori`
  • $(): 명령어 치환. 안에 들어있는 명령어를 실행한 결과로 치환.
    예: echo $(echo theori)

5. Command Injection 실습 예제

  • ping -c 3 1.1.1.1 ; id: ping 명령어 뒤에 id 명령어를 실행해 사용자의 정보를 확인합니다.
  • ping -c 3 1.1.1.1 && id: ping 명령어가 성공하면 id 명령어를 실행합니다.
  • ping -c 3 1.1.1.1 | id: ping 명령어의 출력을 id 명령어의 입력으로 전달합니다.

6. 취약한 코드에서 파일 읽기

@app.route('/ping')
def ping():
    ip = request.args.get('ip')
    return os.system(f'ping -c 3 "{ip}"')

위 코드에서 "/flag" 파일을 읽기 위한 입력값 예제:

  • ' || cat /flag.txt #
  • " & cat /home/flag.txt"
  • ; cat /flag#
  • "; cat /fl*; "

7. Q&A 정리

Q1. 커맨드 인젝션 설명으로 올바른 것

인젝션의 종류 중 하나로, 시스템 명령어에 대한 인젝션을 의미합니다. 단순하지만 매우 치명적인 공격으로 이어질 수 있으며, 개발자는 사용자의 입력을 반드시 검사하고 되도록 system 함수의 사용을 자제해야 합니다.

Q2. Command Injection 발생 코드에서 "/flag" 파일 읽기

@app.route('/ping')
def ping():
    ip = request.args.get('ip')
    return os.system(f'ping -c 3 "{ip}"')

위 코드에서 "/flag" 파일을 읽기 위한 입력값 예제:

  • ' || cat /flag.txt # - 작은따옴표와 해시 기호가 ping 명령어의 일부로 처리됩니다.
  • " & cat /home/flag.txt" - 큰따옴표와 &가 ping 명령어의 일부로 처리됩니다.
  • ; cat /flag# - 세미콜론과 해시 기호가 ping 명령어의 일부로 처리됩니다.
  • "; cat /fl*; " - 올바른 입력 예제로, ping 명령어가 끝난 후 cat /fl* 명령어가 실행됩니다.

왜 첫 세 가지 예제가 틀렸는가?

코드에서 ip 입력값은 다음과 같이 전달됩니다:

os.system(f'ping -c 3 "{ip}"')

따라서 ip에 어떤 값을 넣어도 실제로 실행되는 명령어는 항상 ping -c 3 "입력값" 형식입니다.

1. ' || cat /flag.txt #

이 입력값을 넣으면 실제로 실행되는 명령어는 다음과 같습니다:

ping -c 3 "' || cat /flag.txt #"

여기서 작은따옴표 '와 해시 기호 #는 따옴표 내에 있으므로, ping 명령어의 일부로 처리됩니다. 이 경우 cat /flag.txt 명령어는 실행되지 않습니다.

2. " & cat /home/flag.txt"

이 입력값을 넣으면 실제로 실행되는 명령어는 다음과 같습니다:

ping -c 3 "" & cat /home/flag.txt""

여기서 " 문자는 ping 명령어의 인자로 처리되고, &는 파이프의 일부분으로 해석됩니다. 그러나 ping 명령어의 인자로 전달된 문자열 내의 &는 제대로 명령어를 구분하지 못합니다.

3. ; cat /flag#

이 입력값을 넣으면 실제로 실행되는 명령어는 다음과 같습니다:

ping -c 3 "; cat /flag#"

여기서 ;와 #는 큰따옴표 내에 있으므로, ping 명령어의 일부로 처리됩니다. 이 경우 cat /flag 명령어는 실행되지 않습니다.

왜 마지막 예제가 맞는가?

4. "; cat /fl*; "

이 입력값을 넣으면 실제로 실행되는 명령어는 다음과 같습니다:

ping -c 3 ""; cat /fl*; "

여기서 ";는 ping 명령어의 끝을 표시하고, cat /fl*; 명령어를 별도로 실행합니다. 마지막의 "는 두 번째 명령어의 끝을 표시합니다. 이로 인해 실제로 cat /fl* 명령어가 실행되며, /flag 파일의 내용을 읽어올 수 있습니다.

따라서, 올바른 입력값 예제는 마지막의 "; cat /fl*; "입니다.

Q3. 메타 문자와 설명 짝짓기

  • ` ``: 명령어 치환
  • ;: 명령어 구분자
  • |: 파이프
  • $(): 명령어 치환

추가 내용: Command Injection 방어 방법

  • 입력값 검증: 사용자 입력값을 철저히 검증하고 허용된 값만 수용합니다.
  • 화이트리스트 사용: 허용된 명령어 및 인자만 사용합니다.
  • 파라미터화된 명령어 사용: 파라미터화된 API를 사용해 명령어와 데이터를 분리합니다.
  • 권한 제한: 애플리케이션이 실행하는 명령어의 권한을 최소화합니다.

마무리

커맨드 인젝션은 단순하지만 매우 치명적인 공격으로, 시스템 명령어를 잘못 사용하면 발생할 수 있습니다. 개발자는 이를 예방하기 위해 사용자 입력을 철저히 검증하고, 가능한 system 함수를 사용하지 않도록 해야 합니다.

 

'컴퓨터보안 > 웹서버' 카테고리의 다른 글

서버 관련 정리(간단히)  (0) 2024.05.23
서버 관련 정리(자세히)  (0) 2024.05.23
NoSQL Injection 기법 정리(MongoDB)  (0) 2024.05.20
NoSQL Injection  (0) 2024.05.20
ServerSide: SQL Injection  (0) 2024.05.16