분석기 설정 사용자 정의

API(Fuzzing) 동작은 CI/CD 변수를 통해 변경될 수 있습니다.

API(Fuzzing) 구성 파일은 저장소의 .gitlab 디렉터리에 있어야 합니다.

경고: GitLab 보안 스캔 도구의 모든 사용자 정의는 기본 브랜치로 변경을 병합하기 전에 병합 요청에서 테스트되어야 합니다. 그렇게 하지 않으면 예기치 않은 결과가 발생할 수 있으며, 거짓 양성 케이스가 많아질 수 있습니다.

인증

인증은 헤더나 쿠키로 인증 토큰을 제공함으로써 처리됩니다. 토큰을 계산하거나 인증 흐름을 수행하는 스크립트를 제공할 수 있습니다.

HTTP 기본 인증

HTTP 기본 인증 은 HTTP 프로토콜에 내장된 인증 방법으로, 전송 계층 보안 (TLS)과 함께 사용됩니다.

비밀번호를 위한 CI/CD 변수 (예: TEST_API_PASSWORD)를 생성하여 마스킹된 상태로 설정하는 것이 좋습니다. GitLab 프로젝트 페이지의 설정 > CI/CD > 변수 섹션에서 CI/CD 변수를 생성할 수 있습니다. 마스킹된 변수에 대한 제한 사항으로 인해 비밀번호를 추가하기 전에 Base64로 인코딩해야 합니다.

마지막으로, .gitlab-ci.yml 파일에 두 개의 CI/CD 변수를 추가하세요:

  • FUZZAPI_HTTP_USERNAME: 인증을 위한 사용자 이름.
  • FUZZAPI_HTTP_PASSWORD_BASE64: 인증을 위해 Base64로 인코딩된 비밀번호.
stages:
    - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick-10
  FUZZAPI_HAR: test-api-recording.har
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_HTTP_USERNAME: testuser
  FUZZAPI_HTTP_PASSWORD_BASE64: $TEST_API_PASSWORD

API 퍼징 프로필

GitLab은 구성 파일 gitlab-api-fuzzing-config.yml을 제공합니다. 이 파일에는 특정 횟수의 테스트를 수행하는 여러 테스트 프로필이 포함되어 있습니다. 각 프로필의 실행 시간은 테스트 횟수가 증가함에 따라 증가합니다.

프로필 퍼징 테스트(매개변수당)
Quick-10 10
Medium-20 20
Medium-50 50
Long-100 100

오버라이드

API 퍼징은 요청에 특정 항목을 추가하거나 오버라이드하는 방법을 제공합니다. 예를 들어 다음과 같습니다:

  • 헤더
  • 쿠키
  • 쿼리 문자열
  • 폼 데이터
  • JSON 노드
  • XML 노드

이를 사용하여 의미 있는 버전 헤더, 인증 등을 삽입할 수 있습니다. 인증 섹션에 그러한 목적으로 오버라이드를 사용하는 예제가 포함되어 있습니다.

오버라이드는 각 오버라이드 유형이 JSON 객체에 의해 표시되는 JSON 문서를 사용합니다:

{
  "headers": {
    "header1": "value",
    "header2": "value"
  },
  "cookies": {
    "cookie1": "value",
    "cookie2": "value"
  },
  "query": {
    "query-string1": "value",
    "query-string2": "value"
  },
  "body-form": {
    "form-param1": "value",
    "form-param2": "value"
  },
  "body-json": {
    "json-path1": "value",
    "json-path2": "value"
  },
  "body-xml": {
    "xpath1": "value",
    "xpath2": "value"
  }
}

단일 헤더 설정 예시:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

헤더와 쿠키를 동시에 설정하는 예시:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  },
  "cookies": {
    "flags": "677"
  }
}

body-form 오버라이드 설정 사용 예:

{
  "body-form":  {
    "username": "john.doe"
  }
}

오버라이드 엔진은 요청 본문이 폼 데이터 콘텐츠만 있는 경우 body-form을 사용합니다.

body-json 오버라이드 설정 사용 예:

{
  "body-json":  {
    "$.credentials.access-token": "iddqd!42.$"
  }
}

객체 body-json의 각 JSON 속성 이름은 JSON Path 표현식으로 설정됩니다. JSON Path 표현식 $.credentials.access-token은 값 iddqd!42.$으로 오버라이드할 노드를 식별합니다. 오버라이드 엔진은 요청 본문이 JSON 콘텐츠만 있는 경우 body-json을 사용합니다.

예를 들어, 본문이 다음 JSON으로 설정된 경우:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "non-valid-password"
    }
}

다음과 같이 변경됩니다:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "iddqd!42.$"
    }
}

body-xml 오버라이드 설정 예시입니다. 첫 번째 항목은 XML 속성을 오버라이드하고 두 번째 항목은 XML 요소를 오버라이드합니다:

{
  "body-xml" :  {
    "/credentials/@isEnabled": "true",
    "/credentials/access-token/text()" : "iddqd!42.$"
  }
}

객체 body-xml의 각 JSON 속성 이름은 XPath v2 표현식으로 설정됩니다. XPath 표현식 /credentials/@isEnabled은 값 true으로 오버라이드할 속성 노드를 식별합니다. XPath 표현식 /credentials/access-token/text()은 값을 iddqd!42.$으로 오버라이드할 요소 노드를 식별합니다. 오버라이드 엔진은 요청 본문이 XML 콘텐츠만 있는 경우 body-xml을 사용합니다.

예를 들어, 본문이 다음 XML로 설정된 경우:

<credentials isEnabled="false">
  <username>john.doe</username>
  <access-token>non-valid-password</access-token>
</credentials>

다음과 같이 변경됩니다:

<credentials isEnabled="true">
  <username>john.doe</username>
  <access-token>iddqd!42.$</access-token>
</credentials>

이 JSON 문서를 파일 또는 환경 변수로 제공할 수 있습니다. 또한 만료되는 값들을 지원하기 위해 일정 간격으로 실행할 수 있는 명령을 제공할 수 있습니다.

파일 사용

오버라이드 JSON을 파일로 제공하려면 FUZZAPI_OVERRIDES_FILE CI/CD 변수를 설정합니다. 경로는 작업의 현재 작업 디렉토리를 기준으로 상대적입니다.

다음은 예시 .gitlab-ci.yml입니다:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json

CI/CD 변수 사용

오버라이드 JSON을 CI/CD 변수로 제공하려면 FUZZAPI_OVERRIDES_ENV 변수를 사용합니다. 이를 사용하면 변수로 JSON을 제공하여 마스킹하고 보호할 수 있습니다.

다음은 예시 .gitlab-ci.yml입니다. FUZZAPI_OVERRIDES_ENV 변수가 JSON으로 직접 설정됩니다:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_ENV: '{"headers":{"X-API-Version":"2"}}'

다음은 예시 .gitlab-ci.yml입니다. SECRET_OVERRIDES 변수가 JSON을 제공합니다. 이는 UI에서 정의된 그룹 또는 인스턴스 레벨 CI/CD 변수입니다:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_ENV: $SECRET_OVERRIDES

명령 사용

만약 값이 생성되거나 만료되면 프로그램 또는 스크립트를 제공하여 API 퍼저가 지정된 간격으로 실행하도록 할 수 있습니다. 제공된 스크립트는 Python 3과 Bash가 설치된 Alpine Linux 컨테이너에서 실행됩니다.

FUZZAPI_OVERRIDES_CMD 환경 변수를 실행하려는 프로그램 또는 스크립트로 설정해야 합니다. 제공된 명령은 이전에 정의된대로 overrides JSON 파일을 생성합니다.

NodeJS나 Ruby와 같은 다른 스크립팅 런타임을 설치하거나, 재정의 명령에 대한 종속성을 설치해야 할 수 있습니다. 이 경우 FUZZAPI_PRE_SCRIPT를 해당 선행 조건을 제공하는 스크립트 파일 경로로 설정해야 합니다. FUZZAPI_PRE_SCRIPT에서 제공된 스크립트는 분석기가 시작되기 전에 한 번 실행됩니다.

참고: 권한을 사용해야 하는 작업을 수행할 때 sudo 명령을 사용하십시오. 예를 들어, sudo apk add nodejs.

Alpine Linux 패키지 관리 페이지를 확인하여 Alpine Linux 패키지를 설치하는 정보를 참조하십시오.

올바른 작동을 위해 세 가지 CI/CD 변수를 각각 제공해야 합니다:

  • FUZZAPI_OVERRIDES_FILE: 제공된 명령에 의해 생성된 파일.
  • FUZZAPI_OVERRIDES_CMD: 주기적으로 overrides JSON 파일을 생성하는 override 명령.
  • FUZZAPI_OVERRIDES_INTERVAL: 명령을 실행하는 간격(초).

선택 사항:

  • FUZZAPI_PRE_SCRIPT: 분석기가 시작되기 전에 런타임 또는 종속성을 설치하는 스크립트.

경고: Alpine Linux에서 스크립트를 실행하려면 먼저 chmod 명령을 사용하여 실행 권한을 설정해야 합니다. 예를 들어, 모든 사람에 대해 script.py의 실행 권한을 설정하려면 다음 명령을 사용하십시오: sudo chmod a+x script.py. 필요한 경우 이미 실행 권한이 설정된 script.py를 버전 관리할 수 있습니다.

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
  FUZZAPI_OVERRIDES_CMD: renew_token.py
  FUZZAPI_OVERRIDES_INTERVAL: 300

오버라이드 디버깅

기본적으로 오버라이드 명령의 출력은 숨겨집니다. 오버라이드 명령이 비정상적인 종료 코드를 반환하면 해당 명령이 작업 출력의 일부로 표시됩니다. 선택적으로 FUZZAPI_OVERRIDES_CMD_VERBOSE 변수를 어떤 값이든 설정하여 오버라이드 명령 출력을 생성될 때 표시할 수 있습니다. 이것은 오버라이드 스크립트를 테스트할 때 유용하지만 테스트 속도를 늦출 수 있으므로 이후에 비활성화해야 합니다.

또한 스크립트에서 작업이 완료되거나 실패한 후 수집되는 로그 파일에 메시지를 작성할 수도 있습니다. 로그 파일은 특정 위치에 생성되고 특정한 명명 규칙을 따라야 합니다.

일반적인 작업 실행 중 스크립트가 예기치 않게 실패할 때에 대비하여 오버라이드 스크립트에 기본 로깅을 추가하는 것이 유용합니다. 로그 파일은 작업의 아티팩트로 자동으로 포함되어 있어 작업이 완료된 후에 다운로드할 수 있습니다.

우리의 예시에 따라서, 환경 변수인 FUZZAPI_OVERRIDES_CMDrenew_token.py를 제공했습니다. 스크립트에 대해 두 가지 주목할 점이 있습니다:

  • 로그 파일은 환경 변수 CI_PROJECT_DIR이 지시하는 위치에 저장됩니다.
  • 로그 파일 이름은 gl-*.log과 일치해야 합니다.
#!/usr/bin/env python

# Overrides 명령의 예시

# 오버라이드 명령은 사용할 새 값으로 오버라이드 JSON 파일을 업데이트할 수 있습니다. 
# 이것은 테스트 중에 만료될 인증 토큰을 업데이트하는 훌륭한 방법입니다.

import logging
import json
import os
import requests
import backoff

# [1] 로그 파일을 env 변수 CI_PROJECT_DIR에 저장
working_directory = os.environ.get('CI_PROJECT_DIR')
overrides_file_name = os.environ.get('FUZZAPI_OVERRIDES_FILE', 'api-fuzzing-overrides.json')
overrides_file_path = os.path.join(working_directory, overrides_file_name)

# [2] 파일 이름은 패턴과 일치해야 합니다: gl-*.log
log_file_path = os.path.join(working_directory, 'gl-user-overrides.log')

# 로거 설정
logging.basicConfig(filename=log_file_path, level=logging.DEBUG)

# 일시적인 오류의 경우 재시도하기 위해 `backoff` 데코레이터를 사용
@backoff.on_exception(backoff.expo,
                      (requests.exceptions.Timeout,
                       requests.exceptions.ConnectionError),
                       max_time=30)
def get_auth_response():
    authorization_url = 'https://authorization.service/api/get_api_token'
    return requests.get(
        f'{authorization_url}',
        auth=(os.environ.get('AUTH_USER'), os.environ.get('AUTH_PWD'))
    )

# 우리의 예시에서는 액세스 토큰이 특정 endpoint로부터 검색됩니다
try:

    # http 요청 수행, 응답 예시:
    # { "Token" : "abcdefghijklmn" }
    response = get_auth_response()

    # 요청이 성공적인지 확인합니다. `requests.exceptions.HTTPError`를 발생시킬 수 있습니다.
    response.raise_for_status()

    # JSON 데이터 가져오기
    response_body = response.json()

# 필요한 경우 특정 예외를 잡을 수 있습니다
# requests.ConnectionError                  : 네트워크 연결 오류
# requests.HTTPError                        : HTTP 요청이 비정상적인 상태 코드를 반환했습니다. [Response.raise_for_status()]
# requests.ConnectTimeout                   : 원격 서버에 연결하려는 동안 요청이 시간 초과되었습니다.
# requests.ReadTimeout                      : 서버가 주어진 시간 동안 데이터를 보내지 않았습니다.
# requests.TooManyRedirects                 : 최대 리다이렉션 횟수를 초과하는 요청
# requests.exceptions.RequestException      : Requests와 관련된 예외 모두
except json.JSONDecodeError as json_decode_error:
    # JSON 응답 디코드와 관련된 오류 기록
    logging.error(f'Error, JSON 응답 디코딩 중 실패. 오류 메시지: {json_decode_error}')
    raise
except requests.exceptions.RequestException as requests_error:
    # `Requests` 관련 예외 기록
    logging.error(f'Error, HTTP 요청 수행 중 실패. 오류 메시지: {requests_error}')
    raise
except Exception as e:
    # 다른 모든 오류 기록
    logging.error(f'Error, 테스트 중 알 수 없는 오류 발생. 오류 메시지: {e}')
    raise

# 오버라이드 파일 내용 보유 객체 계산
# 요청에서 가져온 데이터를 사용합니다
overrides_data = {
    "headers": {
        "Authorization": f"Token {response_body['Token']}"
    }
}

# 파일 오버라이드 계산에 대한 로그 항목
logging.info("오버라이드 파일 생성: %s" % overrides_file_path)

# 파일 오버라이드를 시도합니다
try:
    if os.path.exists(overrides_file_path):
        os.unlink(overrides_file_path)

    # 파일을 업데이트된 딕셔너리로 덮어씁니다
    with open(overrides_file_path, "wb+") as fd:
        fd.write(json.dumps(overrides_data).encode('utf-8'))
except Exception as e:
    # 다른 모든 오류 기록
    logging.error(f'Error, 파일 {overrides_file_path} 덮어쓰기 중 알 수 없는 오류 발생. 오류 메시지: {e}')
    raise

# 오버라이드가 성공적으로 완료되었음을 알리는 로그
logging.info("오버라이드 파일이 업데이트되었습니다")

# end

오버라이드 명령 예의 Python 스크립트는 backoff 라이브러리에 의존합니다. Python 스크립트를 실행하기 전에 해당 라이브러리가 설치되어 있는지 확인하려면 FUZZAPI_PRE_SCRIPT를 오버라이드 명령의 종속성을 설치하는 스크립트로 설정해야 합니다. 예시로, 다음 스크립트 user-pre-scan-set-up.sh:

#!/bin/bash

# user-pre-scan-set-up.sh
# Python 종속성 설치 보장

echo "**** python 종속성 설치 ****"

sudo pip3 install --no-cache --upgrade --break-system-packages \
    requests \
    backoff

echo "**** python 종속성 설치됨 ****"

# end

FUZZAPI_PRE_SCRIPT를 새로운 user-pre-scan-set-up.sh 스크립트로 설정하도록 구성을 업데이트해야 합니다. 예를 들어:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_PRE_SCRIPT: user-pre-scan-set-up.sh
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
  FUZZAPI_OVERRIDES_CMD: renew_token.py
  FUZZAPI_OVERRIDES_INTERVAL: 300

이전 예에서 user-pre-scan-set-up.sh 스크립트를 사용하여 이후에 오버라이드 명령에서 사용할 새로운 런타임 또는 애플리케이션을 설치할 수 있습니다.

경로 제외하기

API를 테스트할 때는 특정 경로를 제외하는 것이 유용할 수 있습니다. 예를 들어, 인증 서비스나 API의 이전 버전을 테스트에서 제외할 수 있습니다. 경로를 제외하려면 .gitlab-ci.yml 파일에서 FUZZAPI_EXCLUDE_PATHS CI/CD 변수를 사용하면 됩니다. 여러 경로를 제외하려면 ; 문자로 항목을 구분합니다. 제공된 경로에는 단일 문자 와일드카드 ?와 여러 문자 와일드카드 *를 사용할 수 있습니다.

경로가 제외되었는지 확인하려면 작업 출력의 테스트된 작업(Reviewed Operations)제외된 작업(Excluded Operations) 부분을 확인합니다. 테스트된 작업(Reviewed Operations)에는 제외된 경로가 나열되어서는 안 됩니다.

2021-05-27 21:51:08 [INF] API Fuzzing: --[ 테스트된 작업(Reviewed Operations) ]---------------------
2021-05-27 21:51:08 [INF] API Fuzzing: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: --[ 제외된 작업(Excluded Operations) ]-------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------

경로 제외 예제

이 예제에서는 /auth 리소스를 제외합니다. 이는 하위 리소스(/auth/child)는 제외하지 않습니다.

variables:
  FUZZAPI_EXCLUDE_PATHS: /auth

/auth와 하위 리소스(/auth/child)를 제외하려면 와일드카드를 사용합니다.

variables:
  FUZZAPI_EXCLUDE_PATHS: /auth*

여러 경로를 제외하려면 ; 문자를 사용합니다. 이 예에서는 /auth*/v1/*를 제외합니다.

variables:
  FUZZAPI_EXCLUDE_PATHS: /auth*;/v1/*

매개변수 제외하기

API를 테스트하는 동안 매개변수(쿼리 문자열, 헤더 또는 본문 요소)를 제외하고 싶을 수 있습니다. 매개변수가 항상 실패를 유발하거나 테스트를 늦추는 경우, 또는 다른 이유로 인해 제외해야 할 수 있습니다. 매개변수를 제외하려면 다음 중 하나의 변수를 사용할 수 있습니다: FUZZAPI_EXCLUDE_PARAMETER_ENV 또는 FUZZAPI_EXCLUDE_PARAMETER_FILE.

FUZZAPI_EXCLUDE_PARAMETER_ENV은 제외된 매개변수를 포함하는 JSON 문자열을 제공합니다. 이것은 JSON이 짧고 자주 변경되지 않는 경우에 적합합니다. 다른 옵션은 FUZZAPI_EXCLUDE_PARAMETER_FILE 변수를 사용하는 것입니다. 이 변수는 저장소에 체크인할 수 있는 파일 경로로 설정되며, 다른 작업에서 아티팩트로 생성되거나 FUZZAPI_PRE_SCRIPT를 사용하여 미리 스크립트에서 생성할 수 있습니다.

JSON 문서를 사용하여 매개변수 제외하기

JSON 문서에는 제외해야 할 매개변수를 식별하기 위해 특정 속성을 사용하는 JSON 객체가 포함됩니다. 스캔 프로세스 중에 특정 매개변수를 제외하려면 다음 속성을 제공할 수 있습니다:

  • headers: 특정 헤더를 제외하려면 이 속성을 사용합니다. 속성 값은 제외할 헤더 이름의 배열입니다. 이름은 대소문자를 구분하지 않습니다.
  • cookies: 특정 쿠키를 제외하려면 이 속성을 사용합니다. 속성 값은 제외할 쿠키 이름의 배열입니다. 이름은 대소문자를 구분합니다.
  • query: 쿼리 문자열에서 특정 필드를 제외하려면 이 속성을 사용합니다. 속성 값은 제외할 쿼리 문자열의 필드 이름의 배열입니다. 이름은 대소문자를 구분합니다.
  • body-form: application/x-www-form-urlencoded 미디어 유형을 사용하는 요청에서 본문의 특정 필드를 제외하려면 이 속성을 사용합니다. 속성 값은 본문에서 제외할 필드 이름의 배열입니다. 이름은 대소문자를 구분합니다.
  • body-json: application/json 미디어 유형을 사용하는 요청에서 특정 JSON 노드를 제외하려면 이 속성을 사용합니다. 속성 값은 JSON Path 표현식의 배열입니다.
  • body-xml: application/xml 미디어 유형을 사용하는 요청에서 특정 XML 노드를 제외하려면 이 속성을 사용합니다. 속성 값은 XPath v2 표현식의 배열입니다.

다음 JSON 문서는 매개변수를 제외하기 위한 기대되는 구조의 예제입니다.

{
  "headers": [
    "header1",
    "header2"
  ],
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "query": [
    "쿼리-문자열1",
    "쿼리-문자열2"
  ],
  "body-form": [
    "form-param1",
    "form-param2"
  ],
  "body-json": [
    "json-path-expression-1",
    "json-path-expression-2"
  ],
  "body-xml" : [
    "xpath-expression-1",
    "xpath-expression-2"
  ]
}

예제

특정 헤더 제외하기

Upgrade-Insecure-Requests 헤더를 제외하려면 header 속성의 값을 헤더 이름으로 하는 배열로 설정합니다: [ "Upgrade-Insecure-Requests" ]. 예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "headers": [ "Upgrade-Insecure-Requests" ]
}

헤더 이름은 대소문자를 가리지 않으므로 UPGRADE-INSECURE-REQUESTS 헤더 이름은 Upgrade-Insecure-Requests와 동등합니다.

헤더와 두 개의 쿠키 제외하기

Authorization 헤더와 PHPSESSIDcsrftoken 쿠키를 제외하려면, headers 속성의 값을 헤더 이름 배열로 [ "Authorization" ] 설정하고 cookies 속성의 값은 쿠키 이름 배열로 [ "PHPSESSID", "csrftoken" ] 설정합니다. 예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "headers": [ "Authorization" ],
  "cookies": [ "PHPSESSID", "csrftoken" ]
}

body-form 매개변수 제외하기

application/x-www-form-urlencoded를 사용하는 요청에서 password 필드를 제외하려면 body-form 속성의 값을 필드 이름인 [ "password" ]이 들어있는 배열로 설정하세요. 예를 들어, JSON 문서는 다음과 같이 보입니다.

{
  "body-form":  [ "password" ]
}

요청이 content type application/x-www-form-urlencoded를 사용할 때 body-form을 사용하여 제외 매개변수를 설정합니다.

JSON Path를 사용하여 특정 JSON 노드 제외하기

루트 객체에서 schema 속성을 제외하려면, body-json 속성의 값에 JSON Path 표현인 [ "$.schema" ]이 들어있는 배열로 설정하세요.

JSON Path 표현은 특별한 구문을 사용하여 JSON 노드를 식별합니다. $는 JSON 문서의 루트를 나타내고, .은 현재 객체를 나타냅니다(우리의 경우 루트 객체). 그리고 schema는 속성 이름을 나타냅니다. 따라서, JSON path 표현 $.schema은 루트 객체의 schema 속성을 나타냅니다. 예를 들어, JSON 문서는 다음과 같이 보입니다.

{
  "body-json": [ "$.schema" ]
}

요청이 content type application/json을 사용할 때 body-json을 사용하여 제외 매개변수를 설정합니다. 각 body-json 항목은 JSON Path 표현이어야 합니다. JSON Path에서 $, *, . 등의 문자에는 특별한 의미가 있습니다.

JSON Path를 사용하여 여러 JSON 노드 제외하기

루트 수준의 users 배열의 각 항목에서 password 속성을 제외하려면, body-json 속성의 값을 JSON Path 표현인 [ "$.users[*].paswword" ]이 들어있는 배열로 설정하세요.

JSON Path 표현은 $로 루트 노드를 참조하고, .으로 현재 노드를 참조합니다. 그런 다음 users를 사용하여 속성을 참조하고, 배열에서 인덱스를 감싸는 [] 문자를 사용하여 숫자 대신 *을 사용하여 특정 인덱스를 지정합니다. 인덱스 참조 이후, 배열에서 선택한 인덱스를 나타내는 .이 나오고, password와 같은 속성 이름 앞에 옵니다.

예를 들어, JSON 문서는 다음과 같이 보입니다.

{
  "body-json": [ "$.users[*].paswword" ]
}

요청이 content type application/json을 사용할 때 body-json을 사용하여 제외 매개변수를 설정합니다. 각 body-json 항목은 JSON Path 표현이어야 합니다. JSON Path에서 $, *, . 등의 문자에는 특별한 의미가 있습니다.

XML 속성 제외하기

루트 요소 credentials에 있는 isEnabled라는 속성을 제외하려면, body-xml 속성의 값에 XPath 표현인 [ "/credentials/@isEnabled" ]이 들어있는 배열로 설정하세요.

XPath 표현 /credentials/@isEnabled은 XML 문서의 루트를 나타내는 /로 시작하고, 일치해야 하는 요소의 이름을 나타내는 credentials가 이어집니다. 이전 XML 요소의 노드를 참조하는데 /를 사용하고, 속성 이름 isEnable 앞에 @ 문자가 있음을 나타냅니다.

예를 들어, JSON 문서는 다음과 같이 보입니다.

{
  "body-xml": [
    "/credentials/@isEnabled"
  ]
}

요청이 content type application/xml을 사용할 때 body-xml을 사용하여 제외 매개변수를 설정합니다. 각 body-xml 항목은 XPath v2 표현이어야 합니다. XPath 표현에서 @, /, :, [, ] 등의 문자에는 특별한 의미가 있습니다.

XML 요소의 텍스트 제외하기

루트 노드 credentials에 포함된 username 요소의 텍스트를 제외하려면, body-xml 속성의 값에 XPath 표현인 [ "/credentials/username/text()" ]이 들어있는 배열로 설정하세요.

XPath 표현 /credentials/username/text()에서 첫 번째 문자 /은 XML 루트 노드를 나타내고, 다음은 XML 요소의 이름 credentials를 나타낸다. 비슷하게, 문자 /는 현재 요소를 참조하며, 다음 XML 요소의 이름 username이 옵니다. 마지막 부분에는 현재 요소를 참조하며, text()라는 XPath 함수를 사용하여 현재 요소의 텍스트를 식별합니다.

예를 들어, JSON 문서는 다음과 같습니다.

{
  "body-xml": [
    "/credentials/username/text()"
  ]
}

요청이 content type application/xml을 사용할 때 body-xml을 사용하여 제외 매개변수를 설정합니다. 각 body-xml 항목은 XPath v2 표현이어야 합니다. XPath 표현에서 @, /, :, [, ] 등의 문자에는 특별한 의미가 있습니다.

XML 요소 제외하기

루트 노드 credentials에 포함된 username 요소를 제외하려면, body-xml 속성의 값에 XPath 표현인 [ "/credentials/username" ]이 들어있는 배열로 설정하세요.

XPath 표현 /credentials/username에서 첫 번째 문자 /는 XML 루트 노드를 나타내며, 그 후에 XML 요소의 이름 credentials가 나옵니다. 비슷하게, 문자 /는 현재 요소를 참조하며, 다음에 XML 요소의 이름 username이 옵니다.

예를 들어, JSON 문서는 다음과 같이 보입니다.

{
  "body-xml": [
    "/credentials/username"
  ]
}

요청이 content type application/xml을 사용할 때 body-xml을 사용하여 제외 매개변수를 설정합니다. 각 body-xml 항목은 XPath v2 표현이어야 합니다. XPath 표현에서 @, /, :, [, ] 등의 문자에는 특별한 의미가 있습니다.

네임스페이스가 포함된 XML 노드 제외하기

네임스페이스 s에 정의된 XML 요소인 login을 제외하려면, body-xml 속성의 값에 XPath 표현인 [ "/credentials/s:login" ]이 들어있는 배열로 설정하세요.

XPath 표현 /credentials/s:login에서 첫 번째 문자 /은 XML 루트 노드를 나타내며, 그 후에 XML 요소의 이름 credentials가 나옵니다. 비슷하게, 문자 /는 현재 요소를 참조하며, 다음에 XML 요소의 이름 s:login이 옵니다. 이름에는 :가 포함되어 있는데, 이 문자는 네임스페이스와 노드 이름을 구분합니다.

네임스페이스 이름은 요청 본문의 일부인 XML 문서에 정의되어 있어야 합니다. 네임스페이스는 명세 문서 HAR, OpenAPI, 또는 Postman Collection 파일에서 확인할 수 있습니다.

{
  "body-xml": [
    "/credentials/s:login"
  ]
}

요청이 content type application/xml을 사용할 때 body-xml을 사용하여 제외 매개변수를 설정합니다. 각 body-xml 항목은 XPath v2 표현이어야 합니다. XPath 표현에서 @, /, :, [, ] 등의 문자에는 특별한 의미가 있습니다.

JSON 문자열 사용하기

제외 JSON 문서를 제공하려면 변수 FUZZAPI_EXCLUDE_PARAMETER_ENV에 JSON 문자열을 설정하십시오. 다음 예제에서 .gitlab-ci.yml 파일에서 FUZZAPI_EXCLUDE_PARAMETER_ENV 변수는 JSON 문자열로 설정됩니다.

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_EXCLUDE_PARAMETER_ENV: '{ "headers": [ "Upgrade-Insecure-Requests" ] }'

파일 사용하기

제외 JSON 문서를 제공하려면 변수 FUZZAPI_EXCLUDE_PARAMETER_FILE에 JSON 파일 경로를 설정하십시오. 파일 경로는 작업 디렉토리를 기준으로 상대적입니다. 다음 예제에서 .gitlab-ci.yml 파일에서 FUZZAPI_EXCLUDE_PARAMETER_FILE 변수는 JSON 파일 경로로 설정됩니다.

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_EXCLUDE_PARAMETER_FILE: api-fuzzing-exclude-parameters.json

api-fuzzing-exclude-parameters.json제외 매개변수 문서 구조를 따르는 JSON 문서입니다.

URL 제외하기

경로별로 제외하는 대신, FUZZAPI_EXCLUDE_URLS CI/CD 변수를 사용하여 URL의 다른 구성 요소별로 필터링할 수 있습니다. 이 변수는 .gitlab-ci.yml 파일에서 설정할 수 있습니다. 이 변수는 쉼표(,)로 구분된 여러 값을 저장할 수 있습니다. 각 값은 정규 표현식입니다. 각 항목은 정규 표현식이므로, .*와 같은 항목은 모든 것과 일치하는 정규 표현식이므로 모든 URL을 제외시킵니다.

작업 출력에서 FUZZAPI_EXCLUDE_URLS에서 제공된 정규 표현식과 일치하는 URL이 있는지 확인할 수 있습니다. 일치 작업은 제외된 작업 섹션에 나열됩니다. 제외된 작업에 나열된 작업은 테스트된 작업 섹션에 나열되어서는 안됩니다. 예를 들어 다음 작업 출력 부분:

2021-05-27 21:51:08 [INF] API Fuzzing: --[ 테스트된 작업 ]-------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: --[ 제외된 작업 ]-----------------------
2021-05-27 21:51:08 [INF] API Fuzzing: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------

참고: FUZZAPI_EXCLUDE_URLS의 각 값은 정규 표현식입니다. ., *, $와 같은 문자는 정규 표현식에서 특별한 의미를 가지고 있습니다.

예제

URL 및 하위 리소스 제외하기

다음 예에서 URL http://target/api/auth와 해당 하위 리소스를 제외합니다.

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: http://target/api/auth

두 URL 제외 및 해당 하위 리소스 허용하기

http://target/api/buyhttp://target/api/sell URL을 제외하되, 하위 리소스를 검색할 수 있도록 허용하는 예입니다. 예를 들어: http://target/api/buy/toy 또는 http://target/api/sell/chair. , 문자로 구분된 두 개의 정규표현식을 사용하고 있으므로 http://target/api/buy/$,http://target/api/sell/$ 값을 사용합니다. 이 값은 각각 쉼표(,) 문자로 구분된 두 개의 정규식을 포함하고 있어서 http://target/api/buy$http://target/api/sell$을 포함합니다. 각 정규식에서 끝에 있는 $ 문자는 일치하는 URL이 어디에서 끝나야 하는지를 나타냅니다.

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: http://target/api/buy/$,http://target/api/sell/$

두 URL 및 하위 리소스 제외하기

http://target/api/buyhttp://target/api/sell, 이와 그 하위 리소스를 제외합니다. 여러 URL을 제공하려면 , 문자를 사용합니다.

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: http://target/api/buy,http://target/api/sell

정규 표현식을 사용하여 URL 제외하기

사용 가능한 모든 버전(v3, v4 등)의 https://target/api/v1/user/createhttps://target/api/v2/user/create를 정확하게 제외하기 위해 https://target/api/v.*/user/create$를 사용하면 됩니다. 이전의 정규 표현식에서:

  • .는 모든 문자를 나타냅니다.
  • *는 0번 이상 나타남을 의미합니다.
  • $는 URL이 그 위치에서 끝나야 함을 나타냅니다.
stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: https://target/api/v.*/user/create$

헤더 퍼징

테크놀로지 스택에서 발생하는 많은 거짓 양성으로 인해 헤더 퍼징은 기본적으로 비활성화되어 있습니다. 헤더 퍼징을 활성화하려면 퍼징에 포함할 헤더 목록을 지정해야 합니다.

기본 구성 파일의 각 프로필에는 GeneralFuzzingCheck 항목이 있습니다. 이 체크는 헤더 퍼징을 수행합니다. 구성 섹션에서 HeaderFuzzingHeaders 설정을 변경하여 헤더 퍼징을 활성화해야 합니다.

이 스니펫은 헤더 퍼징이 비활성화된 Quick-10 프로필의 기본 구성을 보여줍니다.

- Name: Quick-10
  DefaultProfile: Empty
  Routes:
  - Route: *Route0
    Checks:
    - Name: FormBodyFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: false
        Headers:
    - Name: JsonFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
    - Name: XmlFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true

HeaderFuzzing은 헤더 퍼징을 켜고 끄는 부울 값입니다. 기본 설정은 꺼져 있는 false입니다. 헤더 퍼징을 활성화하려면 이 설정을 true로 변경하세요.

    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: true
        Headers:

Headers는 퍼징할 헤더의 목록입니다. 나열된 헤더만 퍼징됩니다. API에서 사용하는 헤더를 퍼징하려면 사용하는 헤더에 해당하는 항목을 - Name: HeaderName 구문을 사용하여 추가하세요. 예를 들어 X-Custom이라는 사용자 지정 헤더를 퍼징하려면 - Name: X-Custom를 추가하세요.

    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: true
        Headers:
          - Name: X-Custom

이제 X-Custom 헤더를 퍼징하는 구성을 갖추게 되었습니다. 추가 헤더를 나열하려면 동일한 방법을 사용하세요.

    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: true
        Headers:
          - Name: X-Custom
          - Name: X-AnotherHeader

이 구성을 필요한 만큼 각 프로필에 반복하세요.