리눅스 커널의 원격 Stack Buffer Overflow 취약점
유형
Out-of-Bounds write
CWE-787
분석
TIPC 모듈의 모니터링 프레임워크에서 원격으로 Stack Buffer Overflow를 트리거할 수 있는 취약점이다.
TIPC의 모니터링 프레임워크는 동일한 인접 노드를 모니터링하기 위해 아래와 같은 구조체를 사용한다.
struct tipc_peer {
u32 addr;
struct tipc_mon_domain *domain;
struct hlist_node hash;
struct list_head list;
u8 applied;
u8 down_cnt;
bool is_up;
bool is_head;
bool is_local;
};
#define MAX_MON_DOMAIN 64
struct tipc_mon_domain {
u16 len;
u16 gen;
u16 ack_gen;
u16 member_cnt;
u64 up_map;
u32 members[MAX_MON_DOMAIN];
};
peer에서 tipc_mon_domain 구조체를 참조하는 형태.
TIPC에서 노드 간의 메세지는 헤더 필드인 LINK_PROTOCOL과 STATE_MSG로 나뉘는데 STATE_MSG 내의 도메인 레코드가 포함된 경우에 피어의 도메인 레코드를 업데이트하는 tipc_mon_rcv 함수에서 취약점이 발견되었다.
/* tipc_mon_rcv - process monitor domain event message
*
* @data: STATE_MSG body
* @dlen: STATE_MSG body size (taken from TIPC header)
*/
void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr,
struct tipc_mon_state *state, int bearer_id)
{
...
struct tipc_mon_domain *arrv_dom = data;
struct tipc_mon_domain dom_bef; [0]
...
/* Sanity check received domain record */ [1]
if (dlen < dom_rec_len(arrv_dom, 0)) [2]
return;
if (dlen != dom_rec_len(arrv_dom, new_member_cnt)) [3]
return;
if (dlen < new_dlen || arrv_dlen != new_dlen) [4]
return;
...
/* Drop duplicate unless we are waiting for a probe response */
if (!more(new_gen, state->peer_gen) && !probing) [5]
return;
...
/* Cache current domain record for later use */
dom_bef.member_cnt = 0;
dom = peer->domain;
if (dom) [6]
memcpy(&dom_bef, dom, dom->len); [7]
/* Transform and store received domain record */
if (!dom || (dom->len < new_dlen)) {
kfree(dom);
dom = kmalloc(new_dlen, GFP_ATOMIC); [8]
peer->domain = dom; [9]
if (!dom)
goto exit;
}
...
[1] 에서 메세지에 도메인 레코드가 포함되었는지 유효한 구조체인지를 확인하는 과정이 있다.
[2]~[3] 에서 dlen이 충분히 큰지 검사한다.
이때, new_member_cnt가 MAX_MON_DOMAIN보다 작거나 같은지 검사하지 않았다. 즉, 만족해야 할 최솟값만 넘었는지 확인했을 뿐 최댓값을 확인하지 않았다.
member_cnt와 members[] 필드가 포함된 tipc_mon_domain을 보내어 스택 버퍼 오버플로우가 트리거된다.
dom = {
len = 1072,
gen = 3,
ack_gen = 3,
member_cnt = 264;
up_map = 0xffffffffffffffff;
u32 members[264] = 0x1337...
};
만약 해커가 위와 같이 보낸다면 memcpy(&dom_bef, dom, dom->len); 에서 스택에 272바이트의 버퍼를 할당하고 1,072 바이트만큼 복사하게 된다.
따라서, new_member_cnt에 대한 최댓값 검사를 추가해야 한다.
/* Sanity check received domain record */
+ if (new_member_cnt > MAX_MON_DOMAIN) [0]
+ return;
if (dlen < dom_rec_len(arrv_dom, 0))
return;
if (dlen != dom_rec_len(arrv_dom, new_member_cnt))
참고
https://nvd.nist.gov/vuln/detail/cve-2022-0435#range-8956188
https://hackyboiz.github.io/2022/02/17/l0ch/2022-02-17/
https://blog.immunityinc.com/p/a-remote-stack-overflow-in-the-linux-kernel/
'보안 > 취약점 분석' 카테고리의 다른 글
CVE-2023–37734: Buffer-overflow in mp3_audio_converter (0) | 2023.08.11 |
---|---|
CVE-2017-17969: ZIP Shrink Heap Buffer Overflow (0) | 2023.08.11 |
CVE-2019-6498: GattLib 0.2 Stack Buffer Overflow (0) | 2023.08.08 |
CVE-2017-15048: Zoom Linux Client Stack-based Buffer Overflow (0) | 2023.08.08 |
CVE-2017-5375, CVE-2016-1960 (0) | 2023.08.02 |