일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Security
- 운영체제
- 배경 그림
- link layer
- FIFO
- OSI 7계층
- protection
- Waterfall
- OWASP
- SDLC
- 메카님
- unity
- Trap
- MAC
- stride
- polymorphism
- DSP
- AINCAA
- DP
- 컴퓨터 네트워크
- frequency-domain spectrum analysis
- 게임개발
- 게임 개발
- information hiding
- Unity #Indie Game
- 유니티
- 유스케이스
- MLFQ
- SJF
- STCF
- Today
- Total
다양한 기록
Set-UID Privileged Program 본문
Password Dilemma
/etc/shadow ...
=> -rw-r----- root shadow
루트 권한이 있어야만 쓰기가 가능
하지만 일반 유저도 비밀번호를 바꾸고 싶을 수 있음
Two-Tier Approach
운영체제에서 파인-그레인드 액세스 컨트롤 구현 시 과도하게 복잡해짐
OS는 세분화된 접근 제어를 위해 확장에 의존
권한이 있는 프로그램이 그러한 확장: set-uid 프로그램, 데몬
타입
- Deamon in Linux (Services in MS Windows)
- Set-Programs
Set-UID Concept
- 유저가 프로그램을 오너 권한으로 실행하도록 허가
RUID (Real) : 프로세스의 실제 오너 아이디
EUID (Effective) : 권한을 나타내는 아이디
RUID는 su 명령 사용 시 바뀜
EUID는 Set-UID 프로그램 사용 시 바뀜
영구적으로 상승되면 안됨
실행 끝나면 권한 반납
sudo chmod 4755 mycat
=> mycat 권한이 -rwsr-xr-x 가 됨
/*
- rwx r-x r-x 1 user_a user_a ….. a.exe
- rw- r- - r- - 1 user_a user_a ….. file2
- rws r-x r-x 1 user_b user_b ….. program
- rw- r- - r- - 1 user_b user_b …. file1
*/
// user_a ruid 25
// user_b ruid 17
// a.exe에서 program exec
...;
// read/write file1
...;
i = getruid();
setuid(i);
...;
// read/write file2
''';
a.exe에서 exec => set-uid 프로그램이니 user_b의 권한으로 program 실행됨
file1을 읽는 시점: euid가 17
file2를 읽는 시점: euid가 ruid인 25로 바뀌어 있음
=> I/O 다 됨
다른 예시
컴퓨터를 처음 켰을 때의 프로세스?
init
이건 커널이 다 만들어 주고, 이후의 프로세스는 init에서 포크 및 이그젝을 통해 생성
init -fe> gettty -e> login -~~setgid, setid .., exec> shell
* 포크 특징: 호출은 하나지만 리턴은 두개 .. 새 pid가 생성됨
exec은 차일드가 함
* Set-UID라고 다 루트가 되는게 아니라 오너가 루트여야 함
왜 Set-UID가 sudo보다 안전한가
Set-UID 프로그램은 일반 유저의 권한을 상승시키는데,
sudo가 직접적으로 권한을 상승시키는 거랑은 다름
할 일이 정해진 애한테 그 일만 시킬 수 있음
근데 /bin/sh나 vi을 set-uid 프로그램으로 만들면 위험함
안전하다고 해봐야 공격은 계속 일어남
슈퍼맨의 예시
북쪽으로 가서 왼쪽으로 가라 => 지구의 반대편에서 명령을 받으면?
북쪽으로 가서 서쪽으로 가라 => 얼마나 가라고 안했고 나침반이 고장나 있을 수도 있음
Set-UID 프로그램에 대한 공격은 4가지
1. User Inputs => 버퍼 오버플로우
2. System Inputs that can be controlled by users => 레이스 컨디션
3. Environment Variables => 환경 변수
4. Non-privileged Process Controlled by User => 권한 누수
Attacks via User Inputs
버퍼 오버플로우 (scanf ..)
포맷 스트링 취약점 (printf 인자에 %n..)
chsh .. 디폴트 쉘 바꾸는 커맨드
공격자가 이상한 입력을 주면?
chsh -s "/user/bin/zsh\n myroot:???:0:0:Backdoor:/home:/bin/bash"
이런 명령을 넣어버리면 디폴트 쉘을 바꾸고 새 줄을 추가하는데 uid가 0임 => 루트 탈취
Attacks via System Inputs
레이스 컨디션
권한이 없는 파일의 권한이 있는 파일로의 심볼릭 링크,
world writable folder에 쓰기 (sticky bit)
Attacks via Environmental Variable
printenv, env 명령으로 환경 변수 볼 수 있는데
PATH가 존재함
커맨드 실행 시 명령어를 패스에 써진 순서대로 찾음
다른 폴더에 심어진 악성코드 실행의 가능성 존재
system("bin/sh"); 가 system("ls")같은 명령보다 더 안전 (절대 경로)
Capability Leaking
권한을 낮췄는데 권한이 누수될 수도 있음
fd = open("/etc/zzz", O_RDWR | O_APPEND);
if( fd == -1 ) {
printf("Can not open /etc/zzz\n");
exit(0);
}
printf("fd is %d\n", fd);
setuid(getuid());
v[0] = "/bin/sh"; v[1] = 0;
execve(v[0], v, 0);
여기 있는 문제점: fd close 안했음
실행하면 fd는 기본적으론 3이 될 거고(표준 입/출/에러 이후) 이후 쉘이 실행됨
exec으로 실행되면 fd까지 상속받는데, 해당 fd를 통해 파일에 값을 쓰는게 가능함
해당 파일에 액세스가 제한되어 있어도 가능
=> Capability Leaking
해결법: exec 전에 close 해라
User Identity
getuid => ruid
geteuid => euid
setuid => euid
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;
}
gcc -o catall catall.c
sudo chown root catall
sudo chmod 4755 catall
catall "aa;/bin/sh"
/bin/cat: aa: No such file or directory
#
#
....
root shell!
command가 위에 처럼 되면?
system이 /bin/sh를 실행해버림
그런데 Set-UID 프로그램이라 루트 권한으로 쉘이 켜짐
=> 루트 쉘 탈취
방어법
1. 쉘을 dash 쉘 남기고 다 제거 .. euid ruid 비교해서 다르면 ruid 기반으로 쉘을 띄움
2. 아니면 execve 쓰기
execve를 쓰면 코드와 데이터가 명백히 분리함
코드와 데이터가 명백하게 분리되는게 안전함
* execlp, execv, execvp는 시스템 콜 아님
...
Principle of Isolation (격리의 원칙)
: Don't mix code and data
* Attacks due to violation od this principle
system()
XSS
SQL injection
Buffer Overflow attacks
Principle of Least Privilege (최소 권한의 원칙)
Set-UID 프로그램을 최소한으로 해야 함
꼭 필요한 경우에만 권한을 높여주고 끝나면 내리기 .. setuid( getuid() )
권한이 있는 프로그램은 어쩔 수 없이 필요함 (패스워드 변경 같이)
어쨌든 권한은 필요
1. setuid
2. sudo
3. capability
'운영체제보안' 카테고리의 다른 글
Buffer Overflow Attack (0) | 2024.10.22 |
---|---|
Kernel / user mode, kernel mode (0) | 2024.10.14 |
리눅스 매뉴얼, 커맨드 (0) | 2024.10.14 |
User Authentication (0) | 2024.10.14 |
Running Command with Privilege (0) | 2024.10.12 |