[하루한줄] CVE-2024-24684/CVE-2024-24685/CVE-2024-24686: libigl의 off 파일 파싱 중 발생한 세 가지 Stack Overflow 취약점

URL

Target

  • libigl 2.5.0

Explain

libigl은 3D 지오메트리 처리에 사용되는 C++ 라이브러리로 게임 개발이나 3D 프린팅, 다양한 파일 포맷의 지오메트리 처리가 필요한 애플리케이션에서 사용되고 있습니다.

취약점은 off(object file format) 파일을 처리하는readOFF 함수에서 세 가지 Stack Overflow 발견되었습니다.

    IGL_INLINE bool igl::readOFF(
      FILE * off_file,
      std::vector<std::vector<Scalar > > & V,
      std::vector<std::vector<Index > > & F,
      std::vector<std::vector<Scalar > > & N,
      std::vector<std::vector<Scalar > > & C)
    
        ...
      // First line is always OFF
[0]   char header[1000];
        ...
[1]   if(fscanf(off_file,"%s\n",header)!=1
         || !(
           string(header).compare(0, OFF.length(), OFF)==0 ||
           string(header).compare(0, COFF.length(), COFF)==0 ||
           string(header).compare(0,NOFF.length(),NOFF)==0))
      {
           ...
      }
      ...
      return true;

CVE-2024-24684는 헤더 파싱 중 발생한 취약점으로 header 크기가 1000 byte로 고정되어 있지만 공격자가 파일 헤더 첫 줄에 1000 byte보다 큰 off 파일을 보낼 경우 Stack Overflow가 발생합니다.

template <typename Scalar, typename Index>
IGL_INLINE bool igl::readOFF(
  FILE * off_file,
  std::vector<std::vector<Scalar > > & V,
  std::vector<std::vector<Index > > & F,
  std::vector<std::vector<Scalar > > & N,
  std::vector<std::vector<Scalar > > & C)
{
    ...
  for(int i = 0;i<number_of_vertices;)
  {
[0] fgets(line, 1000, off_file);
    double x,y,z,nx,ny,nz;
[1] if(sscanf(line, "%lg %lg %lg %lg %lg %lg",&x,&y,&z,&nx,&ny,&nz)>= 3)
    {
      ...
    }else if(
[2]     fscanf(off_file,"%[#]",&tic_tac_toe)==1)
    {
[3]   char comment[1000];
[4]   fscanf(off_file,"%[^\n]",comment);
    }else
    {
        ...
    }
  }
  ...
  return true;
}

CVE-2024-24685는 off 파일의 vertex 파싱 중 발생한 취약점으로 [0]번에서 off 파일 한 줄을 읽고 vertex 좌표 형식일 경우 [1]번에서 좌표 데이터로 파싱 합니다.

만약, 좌표 형식이 아니라면 [2]번에서 주석(#) 여부를 확인하고 주석일 경우 [3][4]번을 통해 comment 배열에 저장합니다.

따라서, 공격자는 파일 헤더 이후 주석의 길이가 1000 byte보다 큰 off 파일을 보내 Stack Overflow 트리거 할 수 있습니다.

template <typename Scalar, typename Index>
IGL_INLINE bool igl::readOFF(
  FILE * off_file,
  std::vector<std::vector<Scalar > > & V,
  std::vector<std::vector<Index > > & F,
  std::vector<std::vector<Scalar > > & N,
  std::vector<std::vector<Scalar > > & C)

    ...
  // Read faces
  for(int i = 0;i<number_of_faces;)
  {
    std::vector<Index > face;
    int valence;
[0] if(fscanf(off_file,"%d",&valence)==1)
    {
        ...
    }else if(
[1]          fscanf(off_file,"%[#]",&tic_tac_toe)==1)
    {
[2]   char comment[1000];
[3]   fscanf(off_file,"%[^\n]",comment);
    }else
    {
        ...
  }
  fclose(off_file);
  return true;
}

CVE-2024-24686은 off 파일의 face 파싱 과정 중 발생한 취약점으로 [0]번에서 각 face를 이루는 vertex 개수를 확인합니다.

만약, 실패할 경우 [1]번에서 주석(#) 여부를 확인하고 주석일 경우 [2][3]번을 통해 comment 배열에 저장합니다.

따라서, 공격자는 vertex 파싱 이후 주석의 길이가 1000 byte보다 큰 off 파일을 보내 Stack Overflow 트리거 할 수 있습니다.

Reference