[하루한줄] CVE-2024-42642: Micron MX500 SSD Series 컨트롤러의 여러 취약점
URL
https://github.com/VL4DR/CVE-2024-42642/tree/main
Target
- SM2259 Firmware version M3CR046
Explain
유명 SSD 제조사 중 하나인 Micron의 MX500 SSD 컨트롤러에서 발견된 취약점의 세부 정보가 공개되었습니다.
MX500 시리즈는 Silicon-Motion사의 제품인 SM2259 컨트롤러는 ARC 아키텍쳐 기반의 4채널 SATA 6Gb/s 마이크로 컨트롤러를 탑재했습니다. 해당 컨트롤러에 탑재된 펌웨어 M3CR046 버전에서 세 가지 취약점이 발견되었는데, 세 취약점 모두 컨트롤러의 펌웨어 업데이트 메커니즘인 ATA PIO DOWNLOAD-MICROCODE (0x92)
에서 발생했습니다.
첫 번째 취약점은 ATA command Handler로 전송된 첫 번째 청크 크기가 섹터의 기본 크기인 0x200
보다 큰 경우에 발생합니다.
if ((g_blocks_copied == 0) && (lower_bound_fw_offset <= __next_offset)) {
curr_bytes_to_copy = (__next_offset - lower_bound_fw_offset) * 0x200;
some_index = 0x200 - (__next_offset - lower_bound_fw_offset) & 0xffff;
}
some_index
를 계산할 때 다음 청크가 위치한 오프셋(첫 청크이므로 해당 청크의 크기)인 __next_offset
과 lower_bound_fw_offset
연산값을 섹터 크기인 0x200에서 빼는데, 이때 lower_bound_fw_offset
은 다운로드 된 펌웨어 이미지가 존재하는 오프셋을 의미하며 0으로 하드코딩되어 있습니다. 따라서 next_offset
이 섹터 크기인 0x200보다 큰 경우 some_index
에서 integer underflow가 발생해 최대 0xFFFF
까지 더 큰 값이 될 수 있습니다.
if ((lower_bound_fw_offset <= __next_offset) &&
(current_offset < higher_bound_fw_offset)) {
r_maybe_some_efficient_data_transfer
(1,some_index * 0x200 + Ox40000000,
&g_download_buffer + (uint)g_blocks_copied * Ox200, curr_bytes_to_copy,0,1 );
g_blocks_copied = g_blocks_copied + (short)(curr_bytes_to_copy >> 9);
}
이후 다운로드 버퍼로 전송하는 로직에서 예상보다 큰 some_index
값을 이용해 src 주소를 계산하계 되어 예상치 못한 동작으로 이어질 수 있습니다.
두 번째 취약점은 펌웨어 이미지 크기 계산에서 발생합니다.
M3CR046 펌웨어 이미지의 크기는 0x242400 bytes(0x1212 sectors)이며, 해당 이미지 내부에는 펌웨어 업데이트 후 플래시 메모리에 기록되는 내부 펌웨어 이미지 3개가 각각 존재합니다. 각 이미지의 크기는 0xC0C00 bytes(0x606 sectors)이므로 0x606으로 하드코딩된 higher_bound_fw_offset
으로 업데이트 로직에서 해당 크기를 초과하는지 검사하는 과정을 수행합니다.
if ((g_blocks_copied == 0) && (lower_bound_fw_offset <= __next_offset)) {
curr_bytes_to_copy = (__next_offset - lower_bound_fw_offset) * 0x200;
some_index = 0x200 - (__next_offset - lower_bound_fw_offset) & 0xffff;
}
else {
curr_bytes_to_copy = 0x40000;
/* Exactly 0x200 blocks */
some_index = 0;
}
if (higher_bound_fw_offset <= __next_offset) {
curr_bytes_to_copy =
curr_bytes_to_copy + (__next_offset - higher_bound_fw_offset) * -0x200;
}
첫 번째 취약점의 if 분기 실행 조건인 첫 번째 청크가 아닌 경우, else 분기를 실행합니다.
이는 첫 번째 청크가 아니면서 현재 청크의 크기가 섹터 크기인 0x200보다 큰 경우 실행된다는 의미이며, 복사할 크기를 0x200섹터 크기(0x40000)만큼 지정합니다.
이후 펌웨어 이미지의 전체 크기가 higher_bound_fw_offset
(0x606)보다 큰 경우 0x606 * 0x200 bytes를 초과하는 바이트 수를 잘라내는 뺼셈 연산을 하는데, 이 과정에서 마지막으로 전달된 청크로 인해 __next_offset
값이 0x806보다 크면 integer underflow로 인해 curr_bytes_to_copy
가 예상보다 큰 값이 됩니다.
이는 첫 번째 취약점과 마찬가지로 다운로드 버퍼로 전송할 바이트 수를 계산할 때 overflow로 이어질 수 있습니다.
세 번째 취약점 또한 펌웨어 이미지 크기 계산에서 발생합니다.
M3CR046의 펌웨어 이미지 크기는 앞서 언급했듯이 0x242400 bytes(0x1212 sectors)입니다. 이 역시 전송된 이미지의 총 크기가 0x1212 섹터를 초과하는지 검사하는 과정이 존재합니다.
if ((current_offset != g_next_offset) || (__subcommand != g_last_subcommand)) {
g_next_offset = 0;
g_blocks_copied = 0;
DAT_ram_10005fe8 = 2;
current_offset = 2;
goto LAB_ram_80024b66;
}
__next_offset = g_blocks_to_transfer + current_offset & 0xffff; // (1) update __next_offset
g_next_offset = (ushort)(g_blocks_to_transfer + current_offset);
}
g_last_subcommand = bVar1;
}
puVar4 = &g_next_offset;
if (0x1212 < __next_offset) { // (2) updated __next_offset is less than 0x1212
g_next_offset = 0;
DAT_ram_10005fe8 = 3;
iVar3 = 3;
LAB_ram_80024e08:
g_blocks_copied = 0;
FUN_ram_00007b14(0x85,0,1,iVar3,0,0,0);
FUN_ram_80023480(4);
return;
}
정상적인 펌웨어 업데이트의 경우 __next_offset
이 0x1212보다 크면 (2)에서 상태코드를 재설정하고 오류를 반환합니다. 그러나 전송된 이미지의 총 크기가 0x1212 섹터를 초과하더라도, 다음에 처리할 ATA command가 충분히 큰 경우 __next_offset
이 (1)에서 재설정되어 (2)의 검사를 우회하고 데이터 전송 로직을 수행하도록 할 수 있습니다. 결과적으로 다운로드 버퍼를 넘어 buffer overflow를 트리거할 수 있습니다.
이 취약점은 앞선 두 사례와 달리 컨트롤러를 즉시 충돌시키지 않아 악용 가능성이 더 높습니다.
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.