강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

apric0t님의 프로필 이미지
apric0t

작성한 질문수

리눅스 커널 해킹. A부터 Z까지

struct cred overwrite 기법

cred 구조체에 __randomize_layout이 적용된건가요?

작성

·

20

·

수정됨

0

cred 구조체 소스코드를 elixir를 통해 확인해보니 다음과 같았습니다. (실습 버전인 5.8.5 기준)

struct cred {
	atomic_t	usage;
#ifdef CONFIG_DEBUG_CREDENTIALS
	atomic_t	subscribers;	/* number of processes subscribed */
	void		*put_addr;
	unsigned	magic;
#define CRED_MAGIC	0x43736564
#define CRED_MAGIC_DEAD	0x44656144
#endif
	kuid_t		uid;		/* real UID of the task */
	kgid_t		gid;		/* real GID of the task */
	kuid_t		suid;		/* saved UID of the task */
	kgid_t		sgid;		/* saved GID of the task */
	kuid_t		euid;		/* effective UID of the task */
	kgid_t		egid;		/* effective GID of the task */
	kuid_t		fsuid;		/* UID for VFS ops */
	kgid_t		fsgid;		/* GID for VFS ops */
	unsigned	securebits;	/* SUID-less security management */
	kernel_cap_t	cap_inheritable; /* caps our children can inherit */
	kernel_cap_t	cap_permitted;	/* caps we're permitted */
	kernel_cap_t	cap_effective;	/* caps we can actually use */
	kernel_cap_t	cap_bset;	/* capability bounding set */
	kernel_cap_t	cap_ambient;	/* Ambient capability set */
#ifdef CONFIG_KEYS
	unsigned char	jit_keyring;	/* default keyring to attach requested
					 * keys to */
	struct key	*session_keyring; /* keyring inherited over fork */
	struct key	*process_keyring; /* keyring private to this process */
	struct key	*thread_keyring; /* keyring private to this thread */
	struct key	*request_key_auth; /* assumed request_key authority */
#endif
#ifdef CONFIG_SECURITY
	void		*security;	/* subjective LSM security */
#endif
	struct user_struct *user;	/* real user ID subscription */
	struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
	/* RCU deletion */
	union {
		int non_rcu;			/* Can we skip RCU deletion? */
		struct rcu_head	rcu;		/* RCU deletion hook */
	};
} __randomize_layout;

이 중 마지막 __randomize_layout 이 뭔지 찾아보니 커널에서 정의한 매크로이고 구조체의 순서를 랜덤화하는 일종의 보호 기법이라는 것을 알았습니다.

 

실습을 따라가보니 uid, gid, suid, sgid를 순서대로 덮기 때문에 현재 커널에서 이 보호 기법이 적용되지 않았다는 것을 알 수 있었습니다.

 

이 매크로의 정의 부분은 총 두 부분이고 다음과 같았습니다.

#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
#define __randomize_layout __attribute__((randomize_layout))
#define __no_randomize_layout __attribute__((no_randomize_layout))
/* This anon struct can add padding, so only enable it under randstruct. */
#define randomized_struct_fields_start	struct {
#define randomized_struct_fields_end	} __randomize_layout;
#endif
#ifndef __randomize_layout
# define __randomize_layout __designated_init
#endif

첫 번째 부분에서는 flag처럼 보이는 RANDSTRUCT_PLUGIN__CHECKER__ 에 cross reference(?)가 더이상 안돼서 확인은 못했습니다만, 이게 define 되어있으면 __randomize_layout 매크로를 정의하는 것 같아보입니다.

 

반대로 flag가 켜져있지 않아 첫 번째 부분에서 매크로 선언이 이뤄지지 않으면 두 번째 부분에서 __designated_init 으로 어쨌든 선언은 되는 것 같습니다.

 

마지막으로 __designated_init 의 선언 부분을 보면 다음과 같습니다.

#if __has_attribute(__designated_init__)
# define __designated_init              __attribute__((__designated_init__))
#else
# define __designated_init
#endif

첨부는 했지만 어떻게 동작하는건지 잘 모르겠어서 여기부터 이해가 안됐습니다...

 

제 질문은 다음과 같습니다.

 

  1. 구조체 멤버 랜덤화가 적용되어야 할 것 같은데 강의자님께서 일부러 커널을 빌드할 때 소스코드를 수정하신건가요?

  2. 아니라면 __designated_init__ 이 없기 때문에 빈 매크로가 할당된 것 같은데, 이게 어떤 플래그이며 어떻게 키고 끌 수 있는건가요?

  3. 커널 소스코드를 확인할 때 RANDSTRUCT_PLUGIN__CHECKER__ 같이 더 이상 cross reference가 불가능한 경우는 어떻게 값을 확인할 수 있나요?

  4. 정작 __randoimze_layout 이 붙었을 때 어떻게 메모리 레이아웃을 변경하는지에 대한 로직은 못찾았는데, 이런 부분은 어디서 확인할 수 있을까요?

  5. 강의자님 경험상 대회나 리얼월드 커널에서 구조체 멤버 랜덤화가 잘 적용되어있는 편인가요?

 

질문이 길어졌는데, 답변주시면 큰 도움이 될 것 같습니다. 감사합니다.

답변 1

0

안녕하세요, 인프런 AI 인턴입니다.
apric0t님께서 질문해 주신 내용을 바탕으로 몇 가지 사항을 설명드리겠습니다.

  1. 구조체 멤버 랜덤화 적용 여부: 특정 설정이나 플래그가 활성화되어 있어야 구조체 멤버의 랜덤화가 활성화됩니다. 만약 실습과정에서 구조체 멤버의 순서가 고정되어 있다면, 관련 설정이 활성화되지 않았을 가능성이 큽니다. 강의자가 커널을 빌드할 때 이러한 설정을 비활성화한 것일 수 있습니다.

  2. __designated_init 매크로: __designated_init__은 GCC의 속성(Attribute) 중 하나로, 다양한 조건에서 초기화를 도움주는 속성일 수 있습니다. 이 속성이 없는 경우 빈 매크로가 되며, 활성화 여부는 주로 컴파일러의 플래그나 설정에 의해 결정됩니다. 특정 속성을 활성화하기 위해서는 컴파일 시 특정 플래그를 사용해야 할 수도 있습니다. 이 관련 정보는 커널의 컴파일러 플래그 문서에서 확인할 수 있습니다.

  3. RANDSTRUCT_PLUGIN__CHECKER__: 기본적으로 이러한 매크로는 커널 빌드시 설정에 의존합니다. 커널의 Makefile이나 빌드 스크립트를 확인하면서 관련 옵션이 포함되어 있는지 검토해 보세요. 만약 소스코드 상에 cross reference가 불가능한 매크로가 있으면, 해당 기능이나 플러그인이 활성화되지 않은 상태일 가능성이 큽니다.

  4. 메모리 레이아웃 변경 로직: __randomize_layout의 실제 로직은 일반적으로 컴파일러 확장을 통해 구현됩니다. 그것의 실질적인 동작은 커널의 빌드 시스템 및 컴파일러에 내장되어 있을 수 있으며, 관련 코드 또는 컴파일러 문서를 확인하는 것이 필요합니다. 자세한 동작은 GCC나 클랭(Clang) 등의 컴파일러 관련 문서에서 확인할 수 있습니다.

  5. 대회나 리얼월드에서의 적용 여부: 구조체 멤버 랜덤화는 보안 상의 이유로 점차 많이 도입되고 있는 추세입니다. 다양한 보안 대책의 일환으로 사용되며, 리얼월드에서도 점점 더 많이 사용되고 있습니다. 하지만 이 또한 환경이나 설정에 따라 다를 수 있습니다.

추가적으로 도움이 필요하시다면, Stack Overflow를 통한 질의응답 또는 관련 커뮤니티에서의 활동이 큰 도움이 될 수 있습니다. 좋은 질문 감사합니다.

apric0t님의 프로필 이미지
apric0t

작성한 질문수

질문하기