코드 보안: 새로운 Github 코드 스캐닝 기능 평가

지난 주 Github는 Code Scanning의 첫 번째 공식 버전을 출시했습니다. 이를 통해 사용자는 소스 코드를 빠르게 스캔하여 취약점을 식별할 수 있습니다. 하지만 질문이 있습니다.

얼마나 신뢰할 수 있습니까?

이 게시물에서는 샘플 C 코드를 기반으로 이에 대한 답변을 제공하려고 합니다.

CodeQl을 사용하여 의도적으로 버그가 발생한 코드를 스캔한 다음 결과를 분석하여 도구의 성능을 확인합니다.

CodeQl 코드 스캐닝



Github 코드 스캐닝은 시맨틱 코드 분석 엔진인 CodeQl을 사용합니다. 코드에 대한 쿼리를 실행하여 잠재적인 위협과 잘못된 패턴을 식별합니다. 매우 다양한 언어(C/C++, Go, Java, JavaScript, Python 등)를 지원하며 코드를 빌드하는 데 사용할 수 있는 멋진 액션autobuild이 있습니다.

설정 방법



GitHub 리포지토리에서 CodeQl을 활성화하려면 official documentation 을 따르십시오.

VS Code 사용자라면 extension도 있습니다.

참조 환경



이 평가를 위해 표준 CodeQl 구성에서 시작한 다음 분석을 위한 소스 코드의 언어를 지정합니다: language: ['cpp'] 및 확장된 쿼리 세트: queries: +security-extended, security-and-quality .

name: "CodeQL"

on:
  push:
    branches: [main]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [main]
  schedule:
    - cron: '0 13 * * 3'

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        language: ['cpp']

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2
      with:
        fetch-depth: 2

    - run: git checkout HEAD^2
      if: ${{ github.event_name == 'pull_request' }}

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v1
      with:
        languages: ${{ matrix.language }}
        queries: +security-extended, security-and-quality

    - run: |
        make

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v1


참조 코드



나는 의도적으로 일부 특성과 오류를 포함하는 C 코드를 사용하고 있습니다. 참조 코드는 fuzzstation의 fuzzgoat 리포지토리이며 여기에는 4개의 주요 취약점이 포함되어 있습니다.
  • 해제 후 메모리 사용:

  • /******************************************************************************
    WARNING: Fuzzgoat Vulnerability
    
    The line of code below frees the memory block referenced by *top if
    the length of a JSON array is 0. The program attempts to use that memory
    block later in the program.
    Diff       - Added: free(*top);
    Payload    - An empty JSON array: []
    Input File - emptyArray
    Triggers   - Use after free in json_value_free()
    ******************************************************************************/
    
                   free(*top);
    /****** END vulnerable code **************************************************/
    


  • 유효하지 않은 해제 2개:

  •    switch (value->type)
          {
             case json_object:
    
                if (!value->u.object.length)
                {
                   settings->mem_free (value->u.object.values, settings->user_data);
                   break;
                }
    
    /******************************************************************************
      WARNING: Fuzzgoat Vulnerability
    
      The line of code below incorrectly decrements the value of 
      value->u.object.length, causing an invalid read when attempting to free the 
      memory space in the if-statement above.
      Diff       - [--value->u.object.length] --> [value->u.object.length--]
      Payload    - Any valid JSON object : {"":0}
      Input File - validObject
      Triggers   - Invalid free in the above if-statement
    ******************************************************************************/
    
                value = value->u.object.values [value->u.object.length--].value;
    /****** END vulnerable code **************************************************/
    
                continue;
    
             case json_string:
    
    /******************************************************************************
      WARNING: Fuzzgoat Vulnerability
    
      The code below decrements the pointer to the JSON string if the string
      is empty. After decrementing, the program tries to call mem_free on the
      pointer, which no longer references the JSON string.
      Diff       - Added: if (!value->u.string.length) value->u.string.ptr--;
      Payload    - An empty JSON string : ""
      Input File - emptyString
      Triggers   - Invalid free on decremented value->u.string.ptr
    ******************************************************************************/
    
                if (!value->u.string.length){
                  value->u.string.ptr--;
                }
    /****** END vulnerable code **************************************************/
    


  • Null 포인터 역참조:

  •   /******************************************************************************
      WARNING: Fuzzgoat Vulnerability
      The code below creates and dereferences a NULL pointer if the string
      is of length one.
      Diff       - Check for one byte string - create and dereference a NULL pointer
      Payload    - A JSON string of length one : "A"
      Input File - oneByteString
      Triggers   - NULL pointer dereference
    ******************************************************************************/
    
                if (value->u.string.length == 1) {
                  char *null_pointer = NULL;
                  printf ("%d", *null_pointer);
                }
    /****** END vulnerable code **************************************************/
    


    코드 분석 결과



    CodeQl의 결과입니다.

    알려진 취약점



    위의 분석에서 볼 수 있듯이 fuzzgoat에 의도적으로 도입된 취약점은 CodeQl에서 발견되지 않습니다.
    free 오류를 발견하기 어렵습니다.

    그러나 이것은 NULL 포인터 역참조에 대해서는 사실이 아닙니다! clang과 같은 다른 도구로 쉽게 잡을 수 있습니다.

    $ scan-build-8 make all
    scan-build: Using '/usr/lib/llvm-8/bin/clang' for static analysis
    /usr/share/clang/scan-build-8/bin/../libexec/ccc-analyzer -o fuzzgoat -I. main.c fuzzgoat.c -lm
    fuzzgoat.c:298:29: warning: Dereference of null pointer (loaded from variable 'null_pointer')
                  printf ("%d", *null_pointer);
                                ^~~~~~~~~~~~~
    


    새로운 발견



    한편, 실제 결과를 분석해 봅시다.

    CodeQl은 잠재적인 버퍼 오버플로를 찾을 수 있었는데 이는 중요한 취약점입니다.
    버퍼의 크기가 고정되어 있기 때문에 아마도 잘못된 긍정일 수 있지만 일반적으로 버퍼 쓰기 작업을 수행할 때 주의하는 것이 좋습니다.

    그 외에도 다른 발견은 다음과 같습니다.
  • 스위치에 enum 케이스가 없습니다.
  • 제대로 문서화되지 않은 큰 함수;
  • 확인 시간 사용 시간 파일 시스템 경쟁 조건.
  • 경로 표현에 통제되지 않은 데이터가 사용되었습니다.
  • 잠재적으로 초기화되지 않은 지역 변수입니다.

  • 이거 야!



    이 평가 후 저는 CodeQl이 코드 품질에 대한 통찰력을 얻기 위해 매일 사용하기에 좋은 도구라고 생각합니다. 사용 및 구성이 쉽고 GitHub 리포지토리에 빠르게 통합할 수 있으며 작은 실행 가능한 결과를 제공합니다.

    단점은 처리해야 할 숫자가 false positives 많을 수 있다는 것입니다.

    Twitter에서 저에게 연락하고 여러분의 생각을 알려주세요!

    Github에서 코드 스니펫을 찾을 수 있습니다.

    이 기사는 원래 myblog에 게시되었습니다. 이 게시물이 마음에 들고 다른 사람들이 좋아하는 것을 읽고 싶다면 거기로 가십시오!

    좋은 웹페이지 즐겨찾기