본문으로 바로가기

[D+3] Setuid (권한상승)

category 해킹&보안/시스템해킹&보안 2017. 3. 6. 19:20
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

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