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 |