촉촉한초코칩

Command Injection 취약점 본문

Study/CVE 및 취약점

Command Injection 취약점

햄친구베이컨 2022. 9. 11. 14:10

Command Injection

  • 시스템 해킹 관점의 명령 주입 취약점
  • ;, &&, ||, < 등 메타 문자를 사용하여 엔터를 한 번만 눌러도 여러 명령어를 실행할 수 있다. 
  • 사용자의 입력을 필터링하지 않을 때, 사용자가 의도하는 명령을 추가적으로 삽입하여 호스트 운영 체제(OS)에서 임의의 명령을 실행할 수 있다. 
    시스템에서 사용자의 입력이 system() 함수의 인자로 사용되거나 에서는 사용자 제공 데이터(서버에 전달하는 양식, 쿠키, HTTP 헤더 등)가 시스템 쉘에 전달될 때 입력을 검사하지 않으면 문제가 된다. 
    system() 함수 원형 : int system(const char* command) 

→ 인자인 command를 시스템에 명령어로 바로 전달한다. 

command_injection.c 파일을 실행하면 첫 번째 인자값에 해당하는 cat 명령어로 파일을 읽는다. 

하지만 command를 필터링하는 과정이 없기 때문에 ;을 사용해서 command를 추가할 수 있다.

" " 를 사용하여 하나의 문자열로 전송한다 .

"Hacking.txt; cat Hacking_JJack.txt"로 한 번에 인자를 보내주면 Hacking_JJack.txt 파일도 읽게 된다. 

더보기

strncpy() 함수 (참고 : https://www.ibm.com/docs/ko/i/7.3?topic=functions-strncpy-copy-strings)

#include <string.h>
char *strncpy(char *string1, const char *string2, size_t count);
  • string2를 string1로 복사한다. 
  • count가 string2 길이 이하이면, 널 문자는 복사된 string1에 추가되지 않는다. 
    만약 count가 string2의 길이보다 큰 경우, string1에는 count 길이 까지 널 문자로 채워진다.
  • string1에 대한 포인터를 리턴한다. 

 

strncat() 함수 (참고 : https://www.ibm.com/docs/ko/i/7.3?topic=functions-strncat-concatenate-strings)

#include <string.h>
char *strncat(char *string1, const char *string2, size_t count);
  • string2에 있는 문자열 count개를 string1에 추가한다. 
  • count가 string2 길이보다 크면 count 대신 string2 길이를 사용한다. 
  • 널로 끝나느 스트링에서 작동한다. 
    함수에 대한 스트링 인수는 스트링 끝에 널 문자를 포함해야 한다.
  • 결합된 스트링에 대한 포인터를 리턴한다. (string1)

 

파일에 SetUID가 설정되어 있으면 일반 사용자는 해당 파일의 소유자 권한을 가지게 된다.

이때 command_injection.c 파일이 root 사용자에 SetUID가 설정되어 있다면 root 권한의 쉘도 가질 수 있게 된다.

만약, 여기서 rm -rf / 명령을 내린다면 시스템의 모든 파일을 강제로 삭제하게 된다. 

 

Christmas CTF 2020, oil system 문제

파일의 이름을 사용자가 입력할 수 있고, Out of Bounds(OOB)* 취약점을 이용하여 리턴값을 조작하도록 만든 문제이다. 하지만 의도하지 않게 Command Injection으로도 풀리게 되었다. 

아래 부분이 파일명을 필터링하는 함수이다.

//qword_4120 값을 검사하여 소문자 알파벳 이외의 값이 들어오면 오류 메시지를 출력하고 -1을 반환한다. 
unsigned __int64 sub_166B() {
    unsigned __int64 result; // rax
    __int64 v1; // rsi

    //qword_4120 값을 갱신하는 호출 (사용자 입력을 받거나 특정 데이터를 처리함)
    result = sub_11D0(&qword_4120); 
    if ( result > 0 )  {
    	//소문자 알파벳 범위 검사 (소문자가 아닐 경우 오류 처리를 수행하는 코드이다.)
    	//char 타입을 사용하여 qword_4120 값을 문자로 변환한 후, (문자 1개만 검사)
        //'a'~'z' 범위를 벗어난 문자가 입력되었는지 확인한다.
        //96 : ``, 97 : a, 122 : z        
        if ( (char)qword_4120 <= 96 ||  //96 (`) 이하인 경우
             //unsigned__int8로 변환하고 result에 저장, char로 변환하고 122(z)보다 큰 지 체크         
             (result = (unsigned __int8)qword_4120, (char)qword_4120 > 122) ) {
            //입력된 문자를 unsigned_int 형식으로 저장한다.
            v1 = (unsigned int)(char)qword_4120;  
            //입력된 문자를 출력하는 함수를 호출한다.
            sub_1200("\n %c \n");  
            //메시지와 함께 v1 값을 출력한다. 
            sub_11A0("\n Only lower case Alphabets are allowed", v1);  
            //에러 코드를 반환한다. 
            result = sub_12C0(0xFFFFFFFFLL);  
        }  
    }  
    return result;  
}

영문 소문자(a-z) 이외의 사용자 입력이 들어오면 종료하도록 하지만, 모든 입력을 검사하는 것이 아닌 첫 문자만 검사한다. 

따라서 a;sh 등의 입력으로 쉘을 실행할 수 있게 된다. 

더보기

OOB (Ou of Bounds)

  • 프로그램이 메모리의 허용되지 않는 영역에 접근하거나 데이터를 쓰는 경우 발생한다. 
  • 공격 방식
    • 데이터 손상 : 공격자는 메모리의 허용되지 않은 위치에 데이터를 덮어쓰거나 읽을 수 있어 프로그램의 예기치않은 공격을 유발한다.
    • 코드 실행 : 악의적인 코드를 함수 포인터, 리턴 주소 등 중요한 메모리 위치에 덮어 쓰면, 공격자는 임의의 코드 실행이 가능해진다.
    • 서비스 거부 (DoS) : 프로그램이 예상치 못한 데이터를 처리하거나 크래시를 일으켜 서비스가 중단될 수 있다.  

 

Command Injection은 꼭 명령어로만 공격 가능한 것이 아닌, 스크립트가 실행될 때도 공격을 수행할 수 있다.

Cisco HyperFlex에서 3가지 취약점이 발견되었는데 그 중 CVSS 점수가 9.8로 가장 높은 취약점이 Command Injection이다.

사용자에게 계정 정보를 입력받을 때, 파이썬 스크립트를 활용해 계정 정보를 해시화하는 작업을 수행한다. 

python -c 
"import crypt; 
 print(crypt.crypt(\"OUR_PASS\", \"$6$$\"));"
#crypt 모듈을 사용하여 암호화된 해시를 생성한다. 
#"%6%%"은 솔트(Salt) 값으로, SHA_512 알고리즘을 뜻한다.
#SHA-512 알고리즘을 사용하여 OUR_PASS 문자열을 해시한다.

패스워드 필드에 아래와 같은 스크립트를 삽입하면 시스템을 재부팅시킬 수도 있다. 

123", "$6$$"));import os;os.system("reboot");print(crypt.crypt("
#코드 인젝션 공격을 시도하는 공격이다.
#os 모듈을 가져와 os.system("reboot")을 실행하여 시스템을 재부팅한다. 
#이후에 crypt 실행을 시도한다.

 

Command Injection을 막는 방법

  • 사용자의 입력에는 허용된 명령어 또는 허용된 문자만 사용하도록 한다.
  • 문자열의 길이 제한
  • && & || | ; $ < > \ ! 등의 문자를 블랙리스트에 포함하여 실행시키지 못하도록 해야 한다. 
  • 프로세스에게 작업에 필요한 최소한의 권한만 제공하도록 하여 사용자가 명령을 주입할 수 있는 경우에도 권한이 제한되도록 해야 한다.