2. 권한상승 (setuid)
1) 권한상승 복습
▣ setuid
- 파일 소유자의 실행권한을 잠시 빌려오는 것.
▣ chmod
- SetUID : 4000
- SetGID : 2000
- Sticky-bit : 1000 (공용 디렉토리) -> tmp와 같은 디렉토리
▣ setuid가 걸렸는지 확인하기
- ls -al 명령어로 권한을 보면 s나 S로 확인이 가능.
- S : 파일 실행 권한이 없음.
- s : 파일 실행 권한이 있음.
▣ setuid를 왜 사용하는가? (하나의 예)
- 모든 사용자는 /usr/bin/passwd 파일로, 자신의 password를 변경할 수 있음.
- 그러나 password 변경은 /etc/shadow를 수정해야만 함.
- 이 때, 이 shadow 파일은 root만이 사용가능 하므로 잠시 root 의 권한을 빌려오는 용도로 사용.
2) 프로세스 ID
▣ Real user ID (RUID)
- 단순히 그냥 진짜 내 ID
- 부모의 user ID와 동일 (변경하지 않는 한)
- 프로세스를 시작하는 사용자를 결정하는데 사용
▣ Effective user ID (EUID)
- 이 프로그램의 권한 (실행중인 권한이라고 생각하면 편함)
- sys call과 실행파일에 Set User ID Bit로 설정
- 프로세스에 대한 권한을 결정.
- setuid로 걸어놓은 사용자의 ID값을 가짐
▣ Saved user ID (SUID)
- 이전 EUID를 복원하기 위한 저장소.
# Real group ID (RGID), Effective group ID (EGID) 도 동일하게 사용됨.
3) 실행원리
▣ /etc/passwd 이용 <- setuid가 root로 걸려있음.
- setuid는 EUID 값만을 변경
- passwd 실행 중 root의 권한으로 다른 일을 실행시킬 수 있음.
4) 권한변경 syscall
1. setuid : 프로세스의 ruid, euid, suid를 변경.
ex) setuid(500);
☞ 단 호출자가 root가 아닌 경우 대부분 ruid, euid 둘 다 바뀌지 않음.
☞ root가 아닌 일반계정 주제에 어떻게 권한을 줄 수 있겠니.... 라고 생각하자.
2. seteuid : 프로세스의 euid를 변경.
ex) seteuid(500);
3. setreuid : 프로세스의 ruid, euid를 변경.
ex) setreuid(500, 500);
☞ setuid와 다른 점은 suid를 변경하지 않는다는 것.
4. getuid : 프로세스의 Real UID를 반환.
ex) int uid = getuid();
5. geteuid : 프로세스의 Effective UID를 반환.
ex) int euid = geteuid();
5) 권한상승 실습
▣ 실습 1
#include <stdio.h> #include <unistd.h> int main() { printf("uid :: %d euid :: %d\n", getuid(), geteuid()); setuid(500); printf("uid :: %d euid :: %d\n", getuid(), geteuid()); return 0; }
- 파일 소유주 : root, 실행 : root = (0, 0) -> (500, 500)
- 파일 소유주 : root, 실행 : 일반계정(501) = (501, 501) -> (501, 501)
- 파일 소유주 : root, Set UID bit : root, 실행 : 일반계정(501) = (501, 0) -> (500, 500)
- 파일 소유주 : 일반계정(500), Set UID bit : 일반계정(500), 실행 : 일반계정(501) = (501, 500) -> (501, 500)
▣ 실습 2
#include <stdio.h> #include <unistd.h> int main() { int uid, euid; uid = getuid(); euid = geteuid(); printf("uid :: %d euid :: %d\n", uid, euid); setuid(euid); system("touch /root/i2sec"); system("id"); return 0; }
- 파일 소유주 : root, 실행 : 일반계정(500)
☞ (500, 500)
☞ touch는 권한 불가 (/root 디렉토리는 root계정만이 접근 가능)
☞ id는 500
- 파일 소유주 : root, Set UID bit : root, 실행 : 일반계정(500)
☞ (500, 0)
☞ touch를 통한 i2sec파일 생성
☞ id는 0 (root)
6) 마무리
▣ 일반계정으로 setuid(0)는 가능?
☞ 불가능
▣ Set UID bit 설정은 RUID, EUID, SUID 중 어느 것을 변경?
☞ EUID
▣ RUID, EUID, SUID는 각각 무엇인가?
☞ RUID : 현재 내 진짜 ID
☞ EUID : 현재 프로그램의 ID
☞ SUID : 저장소
▣ 아래 코드 실행 후 쉘은 누구의 계정?
- 소유주 : root
- Set UID bit : root
- 실행 : 일반 계정
#include <stdio.h> int main() { system("/bin/sh"); return 0; }
☞ RUID = 500, EUID = 0 인 상태
☞ 쉘은 실행되기 전 RUID와 EUID를 비교하는데 이 때 두 값이 다르면 해당 RUID로 쉘을 실행.
#include <stdio.h> int main() { setuid(0); system("/bin/sh"); return 0; }
☞ setuid(0); 함수를 통해 RUID == EUID == 0 이기 때문에 쉘을 root의 권한으로 실행시켜줌.
i2sec 대구지점 23기 수료생.
'해킹&보안 > 시스템해킹&보안' 카테고리의 다른 글
쉘 프로그래밍 (0) | 2017.03.16 |
---|---|
[D+5] Backdoor (백도어) (2) (0) | 2017.03.08 |
[D+4] Backdoor (백도어) (1) (0) | 2017.03.07 |
[D+2] 패스워드 크래킹 (2) (3) | 2017.03.05 |
[D+1] 패스워드 크래킹 (1) (0) | 2017.03.02 |