Use-After-Free 취약점 개요
메모리 할당 후 해제된 메모리를 사용하여 발생하는 메모리 손상 취약점(free했으면서 쓰는거) -> 주로 힙에서 발생
힙 영역 중 사용하지 않는 공간은 이중 연결리스트로 관리
+) 이중 연결리스트가 뭐냐면 연결리스트에 원래는 next노드만 참조하도록 되어있는데 선형노드로 해서 pre노드도 참조할 수 있도록 한거
prev | data | next |
이렇게..
매칭은 firt-fit으로 된다(그냥 돌다가 젤 처음에 마주하는데에 매칭)
문제는 free 후에 재할당 해서 사용시에 이전에 사용했던 크기랑 동일한거로 메모리를 할당할 때 발생 -> 원래 객체가 아닌 다른 데이터가 해당 메모리 공간 쓰고 읽으면 임의의 코드 실행 유발
리눅스 커널에서는 동적 메모리 할당 시 주로 메모리 블록 재활용해서 성능 높이고자 함 -> SLUB 할당자 사용 -> 효율 강주로 heap spary 공격 가능
+) 리눅스 커널에서 메모리 할당 시스템인 SLAB에서 큐를 제외해서 간단히 만든게 SLUB
CVE-2024-1086 취약점 분석
리눅스 커널 내 리눅스 패킷 필터링 및 NAT(network adress translation) 프레임워크인 netfilter의 nf_talbes 구성 요소에서 UAF 발생 -> exploit -> 로컬 권한 상승
발생 이유: nf_hook_slow()함수에서 이중 메모리 해제
1) CVE-2024-1086: 취약점 원인
리눅스 커널 entfilter 모듈에서 발생한 double free취약점, 특정 조작된 조건에서 네트워크 패킷을 처리할 UAF나 double free유발함
문제 발생 함수: nf_hook_slow, nft_verdict_init()
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
const struct nf_hook_entries *e, unsigned int s) {
unsigned int verdict;
int ret;
for (; s < e->num_hook_entries; s++) {
verdict = nf_hook_entry_hookfn(&e->hooks[s], skb, state);
switch (verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
break;
case NF_DROP:
kfree_skb(skb);
ret = NF_DROP_GETERR(verdict);
if (ret == 0)
ret = -EPERM;
return ret;
case NF_QUEUE:
ret = nf_queue(skb, state, s, verdict);
if (ret == 1)
continue;
return ret;
default:
return 0;
}
}
return 1;
}
▲nf_hook_slow()
사용자 및 관리자가 생성한 패킷 처리 규칙을 이용해 패킷에 대한 평가 반복문 안에서 진행
590번 라인: verdict(패킷 처리 결과)값 얻은 후 해당 값과 NF_VERDICT_MASK 매크로 값으로 패킷 처리
static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
struct nft_data_desc *desc, const struct nlattr *nla) {
switch (data->verdict.code) {
default:
switch (data->verdict.code & NF_VERDICT_MASK) {
case NF_ACCEPT:
case NF_DROP:
break;
default:
return -EINVAL;
}
▲nft_verdict_init()
패킷 처리
패킷 처리에 사용될 값인 data->verdict.code는 규칙 설정에 대한 리턴 값으로 설정 가능
이 리턴 값에 0xFFFF0000설정 시 취약점 발생함
가장 안쪽 스위치문의 연산을 하면 0xFFFF0000 & 0xFFFF0000이 돼서 0x00000000이 됨 -> 패킷 버림 -> kfree_skb()함수로 패킷 해제 -> NF_DROP_GETERR()함수에서 공격자가 설정한 verdict(0xFFFF0000)에 따라 return 값은 -65535 -> 패킷 처리의 값인 return으로 1반환 -> NF_ACCEPT로 해석됨
=긍정적인 드롭에러 발생해서 NF_ACCEPT난다로 혼동
case NF_DROP:
kfree_skb(skb);
ret = NF_DROP_GETERR(verdict);
if (ret == 0)
ret = -EPERM;
return ret;
▲nf_hook_slow()함수 내 메모리 해제 후 NT_DROP_GETERR()처리
kfree_skb()로 해제되었던 패킷이 NF_ACCEPT반환 처리로 다시 처리되어 skb참조 남음 (UAF)
NF_ACCEPT 마치고 skb 해제 (double free)
2) CVE-2024-1086:PoC 분석
int main() {
int *exploit_status;
exploit_status = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*exploit_status = EXPLOIT_STAT_RUNNING;
if (fork() == 0) {
int shell_stdin_fd;
int shell_stdout_fd;
signal(SIGINT, signal_handler_sleep);
shell_stdin_fd = dup(STDIN_FILENO);
shell_stdout_fd = dup(STDOUT_FILENO);
#if CONFIG_REDIRECT_LOG
setup_log("exp.log");
#endif
setup_env();
privesc_flh_bypass_no_time(shell_stdin_fd, shell_stdout_fd); //PoC의 본체: 실행 시 로컬 권한 상승
*exploit_status = EXPLOIT_STAT_FINISHED;
sleep(9999);
}
SPINLOCK(*exploit_status == EXPLOIT_STAT_RUNNING);
return 0;
}
▲CVE-2024-1086 PoC main() flow
PoC 내 Main 함수 실행 순서 1. exploit_status 포인터 변수 선언 후 메모리 맵핑 2. fork()호출로 자식 프로세스 생성 및 설정 3. exploit 실행 4. 부모 프로세스 설정 |
PoC분석하면 free double처럼 안보이고 일반 메모리 할당 형식처럼 보여짐 -> 리눅스 메모리 해제 변수 refcount때문
메모리 해제 시에 저 값이 1에서 0되는데 이중 해제 되면 의도치 않은 거라 1 0 1 이렇게 커널 패닉 발생
어쨌든 공격자가 메모리를 free시켰는데 참조는 아직 유지되어서(UAF) 이걸 다시 해제할때(Double free) 문제가 생겨 메모리 구조 파악 및 로컬권한 상승됨
패킷 전송될때 규칙 있는데 규칙의 결과를 0xFFFF0000으로 설정하고 이거때매 nftables에서 NF_DROP연산이랑 같이 NF_ACCEPT로 해석돼서 긍정적인 drop error 동작이 발생한다.
그러고 나서 패킷 프래그멘테이션해서 넣도록 할 수 있는데 ipfrag_time이 9999라 재조립 안되고 큐에만 있을 수도 있음 -> 해제된 skb가 아직 큐에 있어서 double free상태 유도가 가능하다.
그러고 나서PTE 스프레이하고 큐에 있는 조각난 IP 패킷 전송하면 ip_id가 이전이랑 동일한 값으로 설정되니까 패킷 재조립 시도할 때 skb가 두번째 해제가 된다.
물리적 메모리 스캔 단계
PMD와 PTE의 이중 할당 설정 완료 -> KSMA 가능
KSMA란?
Kernel Space Mirroring Attack은 컴퓨터 시스템에서 커널 공간의 데이터를 악의적으로 조작하거나 거울처럼 복사하여 비정상적인 동작을 유발하는 공격 기법
커널과 사용자 공간간의 보안 경계를 무력화하거나 커널 메모리 무결성을 훼손함으로써 악성코드 실행 및 데이터 탈취가 가능해짐
- 커널 공간 접근 권한 획득
- 메모리 미러링: 커널 메모리 영역을 복사 및 미러링 해서 시스템이 처리하는 중요한 데이터를 실시간으로 감시 및 변조
- 악성 코드 실행 및 데이터 변조
그럼 대응은 어케..
취약점의 원인은 리눅스 커널의 내장 모듈 중 하나인 netfilter의 nft_verdict_init(), nf_hook_slow()함수에서 긍정적인drop error가 나서임 -> 업데이트 하거나 트리거 사용못하도록 설정값을 변경
대응방안
1) 일반 사용자의 네임스페이스 생성 권한 제거: netfilter 모듈 접근을 제한하게 됨
2) nftables 접근 권한 통제: 규칙 생성하고 접근하는 것을 제한
'학회_공부해요 > 기술_스터디' 카테고리의 다른 글
[Plainbit] LogLayer: 개발자를 위한 혁신적인 통합 로깅 라이브러리 (1) | 2025.01.26 |
---|---|
[이스트시큐리티] 업무 협조 요청 메일을 위장하여 유포 중인 악성코드 주의! (0) | 2025.01.21 |
[CVE 취약점 분석] CVE-2024-7029 (0) | 2024.11.26 |
[Virus Bulletin] Nexus Android banking botnet – compromising C&C panels and dissecting mobile AppInjects (2) | 2024.11.18 |
[CIO KOREA] 트럼프는 반도체 지원 법안을 폐지할까? (6) | 2024.11.12 |