Security/System & Network

[System/Network] 리눅스 SetUID 취약점을 악용한 백도어 공격 및 탐지 우회

min8282 2025. 2. 10. 21:14

1. 개요

리눅스 시스템에서 SetUID를 악용하여 Local Backdoor를 생성하고 root 권한을 탈취하는 과정을 실습해 보았다. 이 과정에서 공격자는 특정 바이너리를 이용해 관리자 권한을 획득하고, 이를 숨겨 탐지를 우회할 수도 있다.


2. 전제조건

  • 이미 관리자 권한을 탈취하여 기본적인 정보 수집이 완료된 상태
  • 일반 사용자 계정(gildong)이 정상적으로 존재
  • SetUID를 활용할 수 있는 환경

3. 공격 실습 - Rootkit 활용

3.1. 일반 사용자 계정(gildong) 생성

먼저 터미널을 2개를 열고 왼쪽은 루트 계정으로 로그인하고 adduser 명령어를 사용해서 gildong이라는 계정을 생성한다.

오른쪽 터미널로 넘어와서 gildong 계정으로 로그인을 한다.


3.2. Local Backdoor 생성 및 권한 상승

/home/gildong 경로 와서 backdoor 프로그램을 작성하고 컴파일하면 backdoor 파일이 생성된다.

 

백도어 코드는 다음과 같다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
        setuid(0);
        setgid(0);
        system("/bin/sh");
}

 

이제 백도어 실행 파일의 권한을 4755로 변경한다.

파일 권한을 4755로 변경하는 이유)
SetUID를 설정하면 실행 파일이 root 권한으로 실행되므로, 일반 사용자도 이를 통해 백도어를 실행하고 권한을 상승시킬 수 있다.

 

이제 gildong으로 로그인 된 터미널에서 /home/gildong 경로에 리스트 목록을 보면 백도어 프로그램이 있는 것을 볼 수 있다. 현재 id를 검색하니 아직까진 gildong으로 출력된다.

gildong 계정으로는 현재 디렉터리(/hoem/gildong)에서 새로운 디렉터리를 만들 수 없지만,

backdoor 파일을 실행하니 #(root) shell 모드로 변경된다. id를 확인해 보니 root 계정인 것을 확인할 수 있고, /gildonghome이라는 디렉터리를 만들 수 있다.

다시 루트 터미널로 가서 루트 폴더(/)에서 리스트 목록을 확인해 보니 gildonghome 디렉터리가 루트 계정으로 만들어진 게 보인다.

 

즉, 현재는 전제조건으로 관리자 계정을 탈취한 상태로, 백도어 프로그램을 만들고 권한이 없는 일반 사용자가 백도어 프로그램을 실행시켜 관리자 권한으로 폴더를 만든 상태다. 

 

여기까지  특수 권한을 설정해 놓고 실행만 하면 일반 사용자에서 관리자로 변경이 된 상태를 봤다.


3.3. Backdoor 숨기기

1) 위장할 파일 찾기

SetUID가 설정된 root 소유 파일을 검색:

find / -user root -perm -4000

지금처럼 SetUID가 설정된 root 소유 파일을 find 명령어로 검색하게 되면 우리가 만든 backdoor 프로그램도 같이 발견이 된다. 즉, 쉽게 노출이 되기 때문에 우리는 검색된 파일 목록 중에서 /usr/sbin/pppd 파일로 위장을 시킬 것이다. (공격자 입장)

*실제 관리자나 보안 담당자들은 초기에 특수 권한이 있는 파일들의 목록을 해시 값으로 변환시켜 가지고 있다가 일정 시간마다 현재 목록의 해시 값과 비교하는 스케쥴링을 통해 관리한다.

*pppd 파일은 현재 잘 사용하지 않는 파일이면서 관리자 권한을 가진 파일이기 때문에 위장 파일로 선정됐다.

 

현재는 관리자 계정을 탈취한 상태이니 pppd 파일을 실행결과를 확인할 수 있다. 이젠 백도어 프로그램 실행 결과를 pppd 파일 실행 결과와 똑같이 만들어 위장할 것이다.


2. Backdoor 파일 생성 및 위장

다시 /home/gildong 경로로 이동해서 backdoor.c 파일 출력 결과를 pppd처럼 나오게 내용을 수정한다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
        char exec[100];
        setuid(0);
        setgid(0);
        sprint(exec, "%s 2>/dev/null", argv[1]);
        system("/bin/sh");

        printf("./pppd: The remote system is required to authenticate itself\n");
        printf("./pppd: but I couldn't find any suitable secret (password) for it to use to do so.\n");

}

3. 컴파일 후 권한 재설정

수정한 backdoor.c 파일을 다시 컴파일해서 backexec 파일을 생성했다.

새로 생성한 backexec 파일의 권한을 4755로 변경하고 실행시켰더니 pppd를 실행시켰을 때와 결과가 똑같이 나오게 됐다.


4. 정상 파일을 backdoor로 변환

실습을 위해 기존 pppd 파일은 /usr/sbin/pppd.bak로 백업하고, 컴파일된 백도어 파일은 /usr/sbin/pppd로 변경한다. /usr/sbin의 파일 목록을 확인해 보면 pppd 파일이 정상적으로 존재한다. 하지만, 현재 이 파일은 pppd로 위장한 백도어 프로그램 backexec이다.


3.4. Backdoor 실행 확인

gildong 계정의 터미널로 돌아와서 백도어 프로그램이 있는 /usr/sbin 폴더로 이동하고, pppd 파일을 실행시킨다. 이때, whoami 명령어도 작성하여 출력 값을 확인했다. whoami의 결과는 root와 기존 pppd 파일의 실행결과가 나온다. 다시 말해 pppd 파일을 실행시키면 관리자 권한으로 셸을 사용할 수 있는 것이다.

 

이번에는 백도어 프로그램을 사용해서 관리자 권한으로 testhome이라는 디렉터리를 만들었다. ls -l 명령어는 현재 디렉터리 내부 파일 목록을 조회하는 명령어인데 현재 디렉터리에는 /testhome은 없다. ls -ld 명령어는 디렉터리 자체 정보를 조회하는 명령어로 출력 결과가 존재하는 것으로 확인됐다.

 

실제 관리자 계정의 루트에서 파일 목록을 확인해 보면 testhome 폴더가 생성된 것을 볼 수 있다.

 

마찬가지로 이번에는 현재 셸의 id를 확인해 봤더니 root 인 것을 볼 수 있었다.


결론

SetUID를 활용하여 일반 사용자(gildong) 계정에서 root 권한을 탈취했고, 정상적인 바이너리(/usr/sbin/pppd)를 백도어로 위장하여 탐지 우회를 해봤다. 이런 백도어 공격은 해시값 비교를 통해 탐지가 가능하므로, 보안 관제에서는 주기적인 검사가 필요하다.

 

보안 관점에서의 대응 방안으로는

  1. SetUID 설정된 파일 주기적 점검
  2. 의심스러운 바이너리 해시값 비교
  3. 정상적인 시스템 파일 변경 모니터링
  4. SetUID가 불필요한 파일은 권한 제거

등이 있다.