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 함수를 사용하여 이러한 권한을 비활성화하거나 폐기할 수 있다.
- 운영체제마다 권한을 제어하는 방식은 서로 다르다.