[운영체제보안]Set-UID

cloudbread·2025년 12월 9일

보안

목록 보기
5/7

1. Real User ID (UID)와 Effective User ID (EUID)

- 1) Real User ID (UID)

  • 프로세스를 실행한 원래 사용자를 나타낸다.
  • 사용자가 어떤 파이을 실행하더라도 UID는 바뀌지 않는다.
uid_t getuid(void);
  • 현재 프로세스의 실제 사용자 ID 반환
    - 2) Effective User ID (EUID)
  • 프로세스가 권한을 확인할 때 사용하는 실제 권한 ID
  • 어떤 파일이 setuid bit가 설정되어 있을 경우 실행시 EUID가 파일 소유자의 UID로 번경
uid_t geteuid(void);
  • 현재 프로세스의 효과적 사용자 ID를 반환한다.
    - 3) euid 변경 함수
int seteuid(uid_t uid);
  • 프로세스의 effective UID만 변경한다.
  • 실 UID와 saved set-user-ID는 변경되지 않는다.
  • 주로 root 또는 setuid 프로그램에서 권한 상승/반납을 일시적으로 제어할 때 사용된다.
  • 4) uid 변경함수
int setuid(uid_t uid);
  • effetUID만 변경하는 것이 아니라, 권한이 있는 프로세스는 다음도 모드 변경한다
  • real UID, effective UID, saved set-user-ID

2. Invoking Programs

  • 프로그램 내부에서 외부 명령을 호출하는 것
  • SET-UID 프로그램은 일반 사용자 입력을 처리하지만 실행 권한은 Root일 수 있다.
  • 즉, 사용자가 입력한 값이 외부 명령으로 직접 사용되면, 공격자가 이를 악용하여 임의의 명령을 root 권한으로 실행할 수 있다.
  • Attack : 사용자에게 외부 명령에 전달될 입력 데이터를 제공하도록 요구하는 경우가 많다. 명령을 제대로 호출하지 않으면, 사용자가 제공한 입력 데이터가 명령 이름으로 해석 될 수 있다.
int main (int argc, char *argv[])
{
   char *cat = "/bin/cat";

   if (argc < 2){
           printf("Please type a file name.\n");
           return 1;
   }

   char *command = malloc(strlen(cat) + strlen(argv[1]) + 2);
   sprintf(command, "%s %s", cat, argv[1]);
   system(command);

   return 0;
}
  • root-owned Set-UID이면, 프로그램이 실행하는 모든 외부 명령은 root 권한으로 수행된다.
  • 이 프로그램을 이용해 다른 명령을 root 권한으로 실행할 수 있는가? => 가능하다 !
  • 이런 상황을 막기 위해서는 세미콜론이 있으면 엉터리 입력이라고 에러 처리를 해주면 된다.
  • 루트 권한으로 명령을 하나만 실행하게 하려면, execve를 사용하면 된다.

3. 실습 환경

  • Ubuntu 16.04에서 /bin/sh -> bin/dash
  • dash는 set-uid 프로그램 내부에서 실행되면 보안 대응책을 적용한다.
  • set-UID 프로그램이 dash를 실행하면, dash는 위험한 상호이라고 판단하여 권한을 RUID로 낮춰버린다.
  • 내부 명령은 root 권한을 못가진다.
  • 따라서 실습환경은 다음을 따른다.
sudo ln -sf /bin/zsh /bin/sh
sudo ln -sf /bin/dash /bin/sh

4. execve()로 프로그램을 안전하게 실행하는 이유

  • execve(v[0], v, 0)
  • v[0] : 실행할 프로그램 이름 => 프로그램이 직접 지정 , 사용자 입력이 아님
  • v : 프로그램에 전달할 인자 목록 => 이 중에는 사용자 입력이 포함될 수 있음
  • system()은 내부적으로 문자열 전체를 셸에서 실행하므로, 사용자 입력이 명령으로 변질될 위험이 있다.
  • 반면, execve()는 사용자 입력이 ";rm -fr/"라고 해도 그냥 파일 이름으로 처리된다. 명령으로 해석되지 않는다.
  • system()은 fork->exec->/bin/sh 실행
  • execve()은 현재 프로세스를 완전히 교체
  • execlp(), execvp(), execvpe()는 셀처럼 동작하여 위험하다.

5. 다른 언어에서도 동일한 위험이 존재

  • Perl: open()이 셸을 통해 명령을 실행할 수 있음
  • PHP: system(), exec()등 URL 파라미터가 셸로 직접 전달될 위험

6. Principle of Isolation

  • 코드와 데이터를 섞지 않는다.
  • 이 원칙을 위반할 때 발생하는 공격 사례
    • system()을 통한 임의 코드 실행
    • XSS : 공격자가 악성 스크립트를 웹 페이지에 주입하여 다른 사용자의 브라우저에서 실행되도록 만드는 공격기법
    • SQL injection : 공격자가 입력 값을 조작하여 애플리케이션이 의도하지 않은 SQL 쿼리를 실행하도록 만드는 기법
    • 버퍼 오버플로우 공격

7. Principle of Least Privilege (최소 권한 원칙)

  • 특권을 필요로 하는 프로그램은 그 작업을 수행하는 데 필요한 최소한의 권한만 부여받아야 한다.
  • 프로그램이 특권을 더 이상 필요로 하지 않는 경우, 해당 권한은 일시적으로 또는 영구적으로 비활성화해야 한다.
  • Linux에서는 seteuid와 setuid 함수를 사용하여 이러한 권한을 비활성화하거나 폐기할 수 있다.
  • 운영체제마다 권한을 제어하는 방식은 서로 다르다.
profile
잡다한거 다 공부중....

0개의 댓글