InfoGrab DocsInfoGrab Docs

DAST 스캔 문제 해결

요약

다음 문제 해결 시나리오는 고객 지원 사례에서 수집한 것입니다. DAST 스캔에 문제가 발생한 경우: 그 외의 경우에는 다음 항목을 확인하며 문제를 찾아봅니다: DAST를 처음 설정할 때 다음과 같은 문제가 발생할 수 있습니다.

다음 문제 해결 시나리오는 고객 지원 사례에서 수집한 것입니다. 여기에서 다루지 않는 문제가 발생하거나 여기의 정보로 문제가 해결되지 않으면 지원 티켓을 생성합니다. 자세한 내용은 GitLab 지원 페이지를 참고합니다.

문제가 발생했을 때#

DAST 스캔에 문제가 발생한 경우:

  • DAST를 처음 설정하는 경우 DAST 설정을 확인합니다.
  • 특정 오류 메시지가 표시되는 경우 알려진 문제를 확인합니다.

그 외의 경우에는 다음 항목을 확인하며 문제를 찾아봅니다:

DAST 설정#

DAST를 처음 설정할 때 다음과 같은 문제가 발생할 수 있습니다.

구성 유효성 검사 실패: 필수 필드 URL이 설정되지 않음#

대상 URL을 정의하지 않고 DAST 템플릿을 포함하면 구성 유효성 검사 단계에서 파이프라인이 다음 오류와 함께 실패합니다:

ERR MAIN  configuration validation failed error="the required field URL was not set"

이 오류는 DAST가 어떤 URL을 스캔해야 하는지 모른다는 뜻입니다. 이 문제를 해결하려면 다음 방법 중 하나로 대상 URL을 정의합니다:

  • .gitlab-ci.yml 파일에 DAST_TARGET_URL CI/CD 변수를 설정합니다:

    stages:
      - dast
    
    include:
      - template: Security/DAST.gitlab-ci.yml
    
    dast:
      variables:
        DAST_TARGET_URL: "https://example.com"
    
  • 프로젝트 루트에 environment_url.txt 파일을 생성하고 대상 URL을 추가합니다. 동적 환경의 애플리케이션을 테스트할 때 이 방법을 사용합니다.

러너가 대상 애플리케이션에 연결할 수 없음#

러너가 대상 애플리케이션에 도달할 수 없으면 DAST 스캔이 연결 오류와 함께 실패합니다. 이는 주로 네트워크 구성이나 방화벽 문제로 발생합니다.

DAST는 지정한 URL을 사용해 애플리케이션에 연결해야 합니다:

  • DAST_TARGET_URL 또는 DAST_AUTH_URL에 포트 번호가 포함된 경우, 러너가 해당 포트에 액세스할 수 있어야 합니다.
  • URL에 포트를 지정하지 않으면 DAST는 표준 포트를 사용합니다:
    • HTTP URL에는 80 포트(예: http://example.com).
    • HTTPS URL에는 443 포트(예: https://example.com).

연결 문제의 일반적인 원인은 다음과 같습니다:

  • HTTP와 HTTPS 콘텐츠 혼용. 애플리케이션이 HTTP와 HTTPS를 모두 사용할 수 있습니다. 예를 들어 대상 URL이 http://example.com인데 사이트가 https://example.com에서 리소스를 로드하는 경우, 러너가 두 포트에 모두 액세스할 수 있어야 합니다.
  • 사용자 지정 포트. 애플리케이션이 비표준 포트에서 실행되는 경우 DAST_TARGET_URL에 포트를 포함합니다. 예를 들어 https://example.com:8443입니다.
  • 방화벽 규칙. 애플리케이션이 방화벽 뒤에 있는 경우 러너의 IP 주소에서 오는 트래픽을 허용하도록 규칙을 구성합니다.
  • 내부 및 외부 네트워크. 러너는 애플리케이션에 도달할 수 있는 네트워크에 있어야 합니다. 예를 들어 내부 네트워크의 스테이징 환경에서 테스트하는 경우 같은 네트워크의 러너를 사용합니다.

대상 연결 문제#

DAST는 스캔을 시작하기 전에 대상 URL에 도달할 수 있는지 확인합니다. 대상 URL에 도달할 수 없으면 DAST는 문제 진단에 도움이 되는 상세한 오류 메시지를 출력합니다. 기본적으로 DAST는 최대 60초까지 2초마다 연결을 재시도합니다. DAST_TARGET_CHECK_TIMEOUT으로 DAST가 연결을 재시도하는 시점을 구성할 수 있습니다.

연결 문제가 발생하는 경우:

  1. DAST_TARGET_URL 구성을 확인합니다.

    • 호스트 이름, 포트, 프로토콜에 오타가 없는지 확인합니다.
    • URL에 프로토콜(http:// 또는 https://)이 포함되어 있는지 확인합니다.
    • 포트 번호가 애플리케이션이 실행 중인 포트와 일치하는지 확인합니다.
  2. 러너에서 연결을 테스트합니다.

    • 연결 테스트: curl --verbose "http://your-target-url:port"
    • DNS 확인 검사: nslookup your-hostname.com
    • 포트 개방 여부 확인: nc -zv your-hostname.com port
  3. 애플리케이션이 실행 중인지 확인합니다.

    • 애플리케이션이 정상적으로 시작되었는지 확인합니다.
    • 애플리케이션 로그에서 시작 오류를 검토합니다.
    • 데이터베이스와 API를 포함한 모든 의존성을 사용할 수 있는지 확인합니다.
  4. 네트워크 및 방화벽 구성을 확인합니다.

    • 방화벽 규칙이 필요한 포트의 트래픽을 허용하는지 확인합니다.
    • 내부 애플리케이션의 경우 러너가 내부 DNS 서버에 액세스할 수 있는지 확인합니다.
  5. 애플리케이션이 시작되거나 정상 상태가 되기까지 오래 걸리는 경우 타임아웃을 늘립니다:

       variables:
         DAST_TARGET_CHECK_TIMEOUT: "5m"  # Wait up to 5 minutes
    

DNS 조회 실패#

DNS lookup failed와 같은 오류가 표시될 수 있습니다. 이는 다음과 같은 이유로 DAST가 제공된 호스트 이름의 서버 주소를 찾을 수 없을 때 발생합니다:

  • DAST_TARGET_URL의 호스트 이름에 오타가 있거나 잘못되었습니다.
  • 도메인이 등록되지 않았거나 존재하지 않습니다.
  • 네트워크 또는 러너 환경에 DNS 확인 문제가 있습니다.

연결 거부됨#

connection refused라는 오류가 표시될 수 있습니다. 이는 보통 서버는 존재하지만 다음과 같은 경우에 발생합니다:

  • 애플리케이션이 아직 시작을 완료하지 않았습니다.
  • 애플리케이션이 지정한 포트와 다른 포트에서 실행 중입니다.
  • 방화벽이 러너와 애플리케이션 사이의 연결을 차단하고 있습니다.
  • 애플리케이션이 충돌했거나 시작에 실패했습니다.

대상이 HTTP 5xx 오류로 응답#

대상 애플리케이션이 HTTP 5xx 오류로 응답할 수 있습니다. 이는 애플리케이션에 도달할 수는 있지만 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout 같은 서버 오류로 응답할 때 발생합니다.

다음과 같은 경우에 서버 오류가 표시될 수 있습니다:

  • 애플리케이션이 시작 중이며 아직 완전히 준비되지 않았습니다.
  • 애플리케이션에 구성 오류가 있습니다.
  • 데이터베이스와 API 같은 필수 의존성을 사용할 수 없습니다.

예상 결과#

DAST 스캔에서 문제를 겪는 많은 사용자는 스캐너가 무엇을 해야 한다고 생각하는지에 대해 상위 수준에서 명확한 생각을 가지고 있습니다. 예를 들어 특정 페이지를 스캔하지 않는다거나, 페이지의 버튼을 선택하지 않는다는 것입니다.

해결책을 찾는 범위를 좁히려면 가능한 한 문제를 분리해 봅니다. 예를 들어 DAST가 특정 페이지를 스캔하지 않는 상황을 생각해 봅니다. DAST가 그 페이지를 어디에서 찾아야 했는지, 거기에 도달하기까지 어떤 경로를 거쳤는지, 참조 페이지에 DAST가 선택해야 했지만 선택하지 않은 요소가 있었는지 확인합니다.

사람이 달성할 수 있는 결과인지 확인#

사람이 애플리케이션을 수동으로 탐색할 수 없다면 DAST도 애플리케이션을 스캔할 수 없습니다.

예상하는 결과를 알고 있다면, 사용 중인 컴퓨터의 브라우저로 그 결과를 수동으로 재현해 봅니다. 예를 들어 다음과 같이 진행합니다:

  • 새 시크릿/개인 브라우저 창을 엽니다.
  • 개발자 도구를 엽니다. 콘솔의 오류 메시지를 계속 확인합니다.
    • Chrome: View -> Developer -> Developer Tools.
    • Firefox: Tools -> Browser Tools -> Web Developer Tools.
  • 인증하는 경우:
    • DAST_AUTH_URL로 이동합니다.
    • DAST_AUTH_USERNAME_FIELD에 DAST_AUTH_USERNAME을 입력합니다.
    • DAST_AUTH_PASSWORD_FIELD에 DAST_AUTH_PASSWORD를 입력합니다.
    • DAST_AUTH_SUBMIT_FIELD를 선택합니다.
  • 링크를 선택하고 폼을 채웁니다. 올바르게 스캔되지 않는 페이지로 이동합니다.
  • 애플리케이션의 동작을 관찰합니다. 자동 스캐너에 문제를 일으킬 수 있는 요소가 있는지 살펴봅니다.

DAST가 작동하지 않는 원인#

다음과 같은 경우 DAST가 올바르게 스캔할 수 없습니다:

  • CAPTCHA가 있는 경우. 스캔 대상 애플리케이션의 테스트 환경에서는 CAPTCHA를 끕니다.
  • 대상 애플리케이션에 액세스할 수 없는 경우. DAST 구성에 사용한 URL로 GitLab Runner가 애플리케이션에 액세스할 수 있어야 합니다.

애플리케이션의 작동 방식#

DAST 스캔이 작동하지 않는 이유를 파악하려면 애플리케이션이 어떻게 작동하는지 이해하는 것이 매우 중요합니다. 예를 들어 다음과 같은 상황에서는 추가 구성 설정이 필요할 수 있습니다.

  • 요소를 가리는 팝업 대화 상자가 있는지 확인합니다.
  • 로드된 페이지가 일정 시간이 지난 뒤 크게 바뀌는지 확인합니다.
  • 애플리케이션의 로드 속도가 특히 느리거나 빠른지 확인합니다.
  • 대상 애플리케이션이 로드 중에 끊기듯 움직이는지 확인합니다.
  • 애플리케이션이 클라이언트의 위치에 따라 다르게 작동하는지 확인합니다.
  • 애플리케이션이 단일 페이지 애플리케이션인지 확인합니다.
  • 애플리케이션이 HTML 폼을 제출하는지, 아니면 JavaScript와 AJAX를 사용하는지 확인합니다.
  • 애플리케이션이 웹소켓을 사용하는지 확인합니다.
  • 애플리케이션이 특정 웹 프레임워크를 사용하는지 확인합니다.
  • 버튼을 선택하면 폼 제출을 계속하기 전에 JavaScript가 실행되는지, 그리고 그 속도가 빠른지 느린지 확인합니다.
  • DAST가 요소나 페이지가 준비되기 전에 요소를 선택하거나 검색할 가능성이 있는지 확인합니다.

DAST가 수행하는 작업#

히스토리
  • 간결한 로그가 GitLab 18.3에 도입되었습니다.

job 콘솔(CI/CD job 로그)은 DAST가 수행하는 작업을 간결하게 요약해 보여줍니다. 더 상세한 진단 정보가 필요하면 로그 파일을 구성해 세분화된 출력을 생성할 수 있습니다.

다음 로깅 옵션을 사용할 수 있습니다:

  • 진단 로그. 분석기가 무엇을 하고 있는지 파악하는 데 유용합니다.
  • Chromium DevTools 로깅. DAST와 Chromium 사이의 통신을 확인하는 데 유용합니다.
  • Chromium 로그. Chromium이 예기치 않게 충돌할 때 오류를 기록하는 데 유용합니다.

진단 로그#

분석기 로그 파일로 스캔 문제를 진단합니다. 분석기의 여러 부분을 서로 다른 레벨로 기록할 수 있습니다.

로그 메시지 형식#

로그 메시지의 형식은 [time] [log level] [log module] [message] [additional properties]입니다.

예를 들어 다음 로그 항목은 레벨이 INFO이고, CRAWL 로그 모듈에 속하며, 메시지는 Crawled path이고, 추가 속성으로 nav_id와 path를 가집니다.

2021-04-21T00:34:04.000 INF CRAWL Crawled path nav_id=0cc7fd path="LoadURL [https://my.site.com:8090]"

로그 대상#

로그는 로그 파일 아티팩트로 전송됩니다. 환경 변수 DAST_LOG_FILE_CONFIG를 사용해 각 대상이 서로 다른 로그를 받도록 구성할 수 있습니다. 예를 들어 다음과 같습니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_BROWSER_SCAN: "true"
    DAST_LOG_FILE_CONFIG: "loglevel:debug,cache:warn"           # file log defaults to DEBUG level, logs CACHE module at WARN

기본적으로 파일 로그는 gl-dast-scan.log라는 job 아티팩트입니다. 이 경로를 구성하려면 DAST_LOG_FILE_PATH CI/CD 변수를 수정합니다.

로그 레벨#

구성할 수 있는 로그 레벨은 다음과 같습니다:

로그 모듈 구성 요소 개요 추가 정보
TRACE 기능의 특정하고 종종 노이즈가 많은 내부 동작에 사용됩니다.
DEBUG 기능의 내부 동작을 설명합니다. 진단 목적으로 사용됩니다.
INFO 스캔의 상위 수준 흐름과 결과를 설명합니다. 지정하지 않으면 기본 레벨입니다.
WARN DAST가 복구하여 스캔을 계속하는 오류 상황을 설명합니다.
FATAL/ERROR/PANIC 종료 전 복구할 수 없는 오류를 설명합니다.

로그 모듈#

LOGLEVEL은 로그 대상의 기본 로그 레벨을 구성합니다. 다음 모듈 중 하나라도 구성되어 있으면 DAST는 기본 로그 레벨보다 해당 모듈의 로그 레벨을 우선 적용합니다.

로깅을 구성할 수 있는 모듈은 다음과 같습니다:

로그 모듈 구성 요소 개요
ACTIV 활성 공격에 사용됩니다.
AUTH 인증된 스캔 생성에 사용됩니다.
BPOOL 크롤링을 위해 대여되는 브라우저 집합입니다.
BROWS 브라우저의 상태나 페이지를 쿼리하는 데 사용됩니다.
CACHE 캐시된 HTTP 리소스의 캐시 히트와 미스를 보고하는 데 사용됩니다.
CHROM Chrome DevTools 메시지를 기록하는 데 사용됩니다.
CONFG 분석기 구성을 기록하는 데 사용됩니다.
CONTA DevTools 메시지에서 HTTP 요청과 응답의 일부를 수집하는 컨테이너에 사용됩니다.
CRAWL 핵심 크롤러 알고리즘에 사용됩니다.
CRWLG 크롤 그래프 생성기에 사용됩니다.
DATAB 내부 데이터베이스에 데이터를 영속화하는 데 사용됩니다.
LEASE 브라우저 풀에 추가할 브라우저를 생성하는 데 사용됩니다.
MAIN 크롤러의 주 이벤트 루프 흐름에 사용됩니다.
NAVDB 탐색 항목을 저장하는 영속화 메커니즘에 사용됩니다.
REGEX 정규 표현식 실행 시 성능 통계를 기록하는 데 사용됩니다.
REPT 보고서 생성에 사용됩니다.
STAT 스캔 실행 중 일반 통계에 사용됩니다.
VLDFN 취약점 정의를 로드하고 파싱하는 데 사용됩니다.
WEBGW 활성 검사 실행 시 대상 애플리케이션으로 전송되는 메시지를 기록하는 데 사용됩니다.
SCOPE 범위 관리와 관련된 메시지를 기록하는 데 사용됩니다.

SECURE_LOG_LEVEL#

히스토리
  • GitLab 17.11에서 도입되었습니다.

DAST_LOG_FILE_CONFIG로 로그 모듈을 구성하는 방법의 더 단순한 대안으로 SECURE_LOG_LEVEL을 설정할 수 있습니다:

  • 지원되는 로그 레벨 중 하나로 설정합니다. 이렇게 하면 지정한 레벨이 모든 모듈에 대해 로그 파일의 기본 로그 레벨이 됩니다.
  • debug 또는 trace로 설정하면 인증 보고서가 활성화됩니다.
  • trace로 설정하면 DevTools 로깅이 활성화됩니다.

예를 들어 다음과 같습니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    SECURE_LOG_LEVEL: "trace"
    # is equivalent to:
    # DAST_LOG_FILE_CONFIG: "loglevel:trace"
    # DAST_LOG_DEVTOOLS_CONFIG: "Default:messageAndBody,truncate:2000"
    # DAST_AUTH_REPORT: "true"

DAST_LOG_FILE_CONFIG, DAST_LOG_DEVTOOLS_CONFIG, DAST_AUTH_REPORT의 설정은 SECURE_LOG_LEVEL의 설정을 재정의합니다.

예시 - 크롤링된 경로 기록#

스캔의 크롤 단계에서 발견된 탐색 경로를 로그 파일에 기록하려면 로그 파일 모듈 CRAWL을 DEBUG로 설정합니다. 이는 DAST가 대상 애플리케이션을 올바르게 크롤링하고 있는지 파악하는 데 유용합니다.

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_FILE_CONFIG: "crawl:debug"

예를 들어 다음 출력은 https://example.com 페이지를 크롤링하는 동안 네 개의 앵커 링크가 발견되었음을 보여줍니다.

2022-11-17T11:18:05.578 DBG CRAWL executing step nav_id=6ec647d8255c729160dd31cb124e6f89 path="LoadURL [https://example.com]" step=1
...
2022-11-17T11:18:11.900 DBG CRAWL found new navigations browser_id=2243909820020928961 nav_count=4 nav_id=6ec647d8255c729160dd31cb124e6f89 of=1 step=1
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page1.html]" nav=bd458cc1fc2d7c6fb984464b6d968866 parent_nav=6ec647d8255c729160dd31cb124e6f89
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page2.html]" nav=6dcb25f9f9ece3ee0071ac2e3166d8e6 parent_nav=6ec647d8255c729160dd31cb124e6f89
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page3.html]" nav=89efbb0c6154d6c6d85a63b61a7cdc6f parent_nav=6ec647d8255c729160dd31cb124e6f89
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page4.html]" nav=f29b4f4e0bdee70f5255de7fc080f04d parent_nav=6ec647d8255c729160dd31cb124e6f89

Chromium DevTools 로깅#

Warning

DevTools 메시지를 기록하는 것은 보안 위험입니다. 출력에는 사용자 이름, 비밀번호, 인증 토큰 같은 시크릿이 포함됩니다. 출력은 GitLab 서버에 업로드되며 job 로그에서 보일 수 있습니다.

DAST 브라우저 기반 스캐너는 Chrome DevTools 프로토콜을 사용해 Chromium 브라우저를 제어합니다. DevTools 메시지를 기록하면 브라우저가 무엇을 하고 있는지 투명하게 파악할 수 있습니다. 예를 들어 버튼 선택이 동작하지 않는 경우, DevTools 메시지에서 브라우저 콘솔 로그의 CORS 오류가 원인임을 확인할 수 있습니다. DevTools 메시지가 포함된 로그는 크기가 매우 커질 수 있습니다. 따라서 실행 시간이 짧은 job에서만 활성화해야 합니다.

모든 DevTools 메시지를 기록하려면 CHROM 로그 모듈을 trace로 설정하고 로깅 레벨을 구성합니다. 다음은 DevTools 로그의 예시입니다:

2022-12-05T06:27:24.280 TRC CHROM event received    {"method":"Fetch.requestPaused","params":{"requestId":"interception-job-3.0","request":{"url":"http://auth-auto:8090/font-awesome.min.css","method":"GET","headers":{"Accept":"text/css,*/*;q=0.1","Referer":"http://auth-auto:8090/login.html","User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/105.0.5195.102 Safari/537.36"},"initialPriority":"VeryHigh","referrerPolicy":"strict-origin-when-cross-origin"},"frameId":"A706468B01C2FFAA2EB6ED365FF95889","resourceType":"Stylesheet","networkId":"39.3"}} method=Fetch.requestPaused
2022-12-05T06:27:24.280 TRC CHROM request sent      {"id":47,"method":"Fetch.continueRequest","params":{"requestId":"interception-job-3.0","headers":[{"name":"Accept","value":"text/css,*/*;q=0.1"},{"name":"Referer","value":"http://auth-auto:8090/login.html"},{"name":"User-Agent","value":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/105.0.5195.102 Safari/537.36"}]}} id=47 method=Fetch.continueRequest
2022-12-05T06:27:24.281 TRC CHROM response received {"id":47,"result":{}} id=47 method=Fetch.continueRequest

DevTools 로그 레벨 사용자 지정#

Chrome DevTools 요청, 응답, 이벤트는 도메인별로 네임스페이스가 지정됩니다. DAST는 각 도메인과 메시지를 포함한 각 도메인에 서로 다른 로깅 구성을 지정할 수 있게 합니다. 환경 변수 DAST_LOG_DEVTOOLS_CONFIG는 세미콜론으로 구분된 로깅 구성 목록을 받습니다. 로깅 구성은 [domain/message]:[what-to-log][,truncate:[max-message-size]] 구조로 선언합니다.

  • domain/message는 기록 대상을 지정합니다.
    • Default를 값으로 사용하면 모든 도메인과 메시지를 의미합니다.
    • 도메인을 지정할 수 있습니다(예: Browser, CSS, Page, Network).
    • 메시지를 포함한 도메인을 지정할 수 있습니다(예: Network.responseReceived).
    • 여러 구성이 해당되는 경우 가장 구체적인 구성이 적용됩니다.
  • what-to-log는 기록 여부와 기록 내용을 지정합니다.
    • message는 메시지를 수신했다는 사실만 기록하고 메시지 내용은 기록하지 않습니다.
    • messageAndBody는 메시지 내용과 함께 메시지를 기록합니다. truncate와 함께 사용하는 것을 권장합니다.
    • suppress는 메시지를 기록하지 않습니다. 노이즈가 많은 도메인과 메시지를 숨기는 데 사용합니다.
  • truncate는 출력되는 메시지의 크기를 제한하는 선택적 구성입니다.

예시 - 모든 DevTools 메시지 기록#

어디에서 시작해야 할지 확실하지 않을 때 모든 것을 기록하는 데 사용합니다.

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_FILE_CONFIG: "chrom:trace"
    DAST_LOG_DEVTOOLS_CONFIG: "Default:messageAndBody,truncate:2000"

예시 - HTTP 메시지 기록#

리소스가 올바르게 로드되지 않을 때 유용합니다. HTTP 메시지 이벤트와 함께 요청을 계속할지 실패 처리할지에 대한 결정도 기록됩니다. 브라우저 콘솔의 오류도 함께 기록됩니다.

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_FILE_CONFIG: "chrom:trace"
    DAST_LOG_DEVTOOLS_CONFIG: "Default:suppress;Fetch:messageAndBody,truncate:2000;Network:messageAndBody,truncate:2000;Log:messageAndBody,truncate:2000;Console:messageAndBody,truncate:2000"

job 콘솔 출력 재정의#

기본적으로 job 콘솔에는 DAST 활동의 간결한 요약이 표시됩니다. 전체 진단 로그를 job 콘솔에 출력하려면 DAST_FF_DIAGNOSTIC_JOB_OUTPUT과 DAST_LOG_CONFIG 변수를 모두 설정합니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_FF_DIAGNOSTIC_JOB_OUTPUT: "true"
    DAST_LOG_CONFIG: "crawl:debug"                               # console log defaults to INFO level, logs AUTH module at DEBUG

이슈 552171은 GitLab 19.0에서 이 옵션을 제거할 것을 제안합니다.

Chromium 로그#

드물게 Chromium이 충돌하는 경우, Chromium 프로세스의 STDOUT과 STDERR를 로그에 기록하면 도움이 될 수 있습니다. 환경 변수 DAST_LOG_BROWSER_OUTPUT을 true로 설정하면 이 목적을 달성할 수 있습니다.

DAST는 많은 Chromium 프로세스를 시작하고 중지합니다. DAST는 각 프로세스의 출력을 로그 모듈 LEASE와 로그 레벨 INFO로 모든 로그 대상에 전송합니다.

예를 들어 다음과 같습니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_BROWSER_OUTPUT: "true"

알려진 문제#

로그에 response body exceeds allowed size가 포함됨#

기본적으로 DAST는 HTTP 응답 본문이 10 MB 이하인 HTTP 요청을 처리합니다. 그렇지 않으면 DAST가 응답을 차단하며, 이로 인해 스캔이 실패할 수 있습니다. 이 제약은 스캔 중 메모리 사용량을 줄이기 위한 것입니다.

다음은 DAST가 https://example.com/large.js에 있는 JavaScript 파일의 크기가 제한을 초과해 차단한 로그 예시입니다:

2022-12-05T06:28:43.093 WRN BROWS response body exceeds allowed size allowed_size_bytes=1000000 browser_id=752944257619431212 nav_id=ae23afe2acbce2c537657a9112926f1a of=1 request_id=interception-job-2.0 response_size_bytes=9333408 step=1 url=https://example.com/large.js
2022-12-05T06:28:58.104 WRN CONTA request failed, attempting to continue scan error=net::ERR_BLOCKED_BY_RESPONSE index=0 requestID=38.2 url=https://example.com/large.js

이는 DAST_PAGE_MAX_RESPONSE_SIZE_MB 구성으로 변경할 수 있습니다. 예를 들어 다음과 같습니다.

dast:
  variables:
    DAST_PAGE_MAX_RESPONSE_SIZE_MB: "25"

크롤러가 예상 페이지에 도달하지 않음#

캐시 비활성화 시도#

DAST가 애플리케이션 페이지를 잘못 캐시하면 DAST가 애플리케이션을 제대로 크롤링하지 못할 수 있습니다. 크롤러가 일부 페이지를 예상과 달리 찾지 못하는 것이 보이면 DAST_USE_CACHE: "false" 변수를 설정해 도움이 되는지 확인합니다. 이 설정은 스캔 성능을 크게 떨어뜨릴 수 있습니다. 반드시 필요한 경우에만 캐시를 비활성화합니다. 구독이 있는 경우 지원 티켓을 생성해 캐시가 웹사이트 크롤링을 막는 이유를 조사합니다.

대상 경로 직접 지정#

크롤러는 일반적으로 정의된 대상 URL에서 시작해 사이트와 상호작용하며 추가 페이지를 찾습니다. 다만 크롤러가 시작할 경로를 직접 지정하는 방법이 두 가지 있습니다:

  • sitemap.xml 사용: 사이트맵은 웹사이트의 페이지를 지정하는 잘 정의된 프로토콜입니다. DAST 크롤러는 <target URL>/sitemap.xml에서 sitemap.xml 파일을 찾고, 지정된 모든 URL을 크롤러의 시작점으로 사용합니다. 사이트맵 인덱스 파일은 지원되지 않습니다.
  • DAST_TARGET_PATHS 사용: 이 구성 변수로 크롤러의 입력 경로를 지정할 수 있습니다. 예시: DAST_TARGET_PATHS: /,/page/1.html,/page/2.html.

요청이 차단되지 않는지 확인#

기본적으로 DAST는 대상 URL 도메인으로의 요청만 허용합니다. 웹사이트가 대상 이외의 도메인으로 요청을 보내는 경우 DAST_SCOPE_ALLOW_HOSTS로 해당 호스트를 지정합니다. 예시: "example.com"이 인증 토큰을 갱신하기 위해 "auth.example.com"으로 인증 요청을 보냅니다. 해당 도메인이 허용되지 않으므로 요청이 차단되고 크롤러는 새 페이지를 찾지 못합니다.

최대 액션 수와 크롤러 시간 초과#

크롤러에는 활동량과 대상 사이트에서 소요하는 시간에 기본 제한이 있습니다:

  1. 기본적으로 크롤러는 10,000개의 액션을 처리합니다. 액션은 링크 선택이나 폼 작성일 수 있습니다. 크롤러가 이 제한을 초과하면 디버그 수준 로그 not adding navigation as it exceeds max actions가 표시됩니다.
  2. 기본적으로 크롤러는 최대 24시간 동안 실행됩니다. 이 시간 제한을 초과하면 트레이스 수준 로그 crawl complete, timed out이 표시됩니다.

크롤러가 이 제한 중 하나에 도달하면 스캐너가 중지되며 대상 웹사이트를 완전히 커버할 수 없습니다. 따라서 이러한 제한을 초과했다는 것은 스캔 중 문제가 있었음을 나타내며 최적화 기회가 될 수 있습니다.

애플리케이션에 구조는 비슷하지만 페이지마다 데이터가 다른 템플릿 기반 페이지가 있거나 URL 패턴(예: /products/item-123, /products/item-456, /products/item-789)이 눈에 띈다면, 그룹화된 URL을 구성해 보안 커버리지를 유지하면서 스캔 시간을 줄입니다.

그룹화된 URL은 제품 페이지가 많은 전자상거래 사이트, 콘텐츠 기반 사이트, 검색 인터페이스 (예: /search?q=term&page=1, /search?q=term&page=2)에 적합합니다.

스캔 시간 관리에 대한 자세한 내용은 스캔 시간 관리를 참고합니다. 다른 전략이 적합하지 않고 대상 사이트가 방대하다면 크롤러 시간 초과(DAST_CRAWL_TIMEOUT)나 최대 액션 수(DAST_CRAWL_MAX_ACTIONS)를 늘립니다.

DAST 스캔 문제 해결

GitLab v19.5
원문 보기

요약

다음 문제 해결 시나리오는 고객 지원 사례에서 수집한 것입니다. DAST 스캔에 문제가 발생한 경우: 그 외의 경우에는 다음 항목을 확인하며 문제를 찾아봅니다: DAST를 처음 설정할 때 다음과 같은 문제가 발생할 수 있습니다.

다음 문제 해결 시나리오는 고객 지원 사례에서 수집한 것입니다. 여기에서 다루지 않는 문제가 발생하거나 여기의 정보로 문제가 해결되지 않으면 지원 티켓을 생성합니다. 자세한 내용은 GitLab 지원 페이지를 참고합니다.

문제가 발생했을 때#

DAST 스캔에 문제가 발생한 경우:

  • DAST를 처음 설정하는 경우 DAST 설정을 확인합니다.
  • 특정 오류 메시지가 표시되는 경우 알려진 문제를 확인합니다.

그 외의 경우에는 다음 항목을 확인하며 문제를 찾아봅니다:

DAST 설정#

DAST를 처음 설정할 때 다음과 같은 문제가 발생할 수 있습니다.

구성 유효성 검사 실패: 필수 필드 URL이 설정되지 않음#

대상 URL을 정의하지 않고 DAST 템플릿을 포함하면 구성 유효성 검사 단계에서 파이프라인이 다음 오류와 함께 실패합니다:

ERR MAIN  configuration validation failed error="the required field URL was not set"

이 오류는 DAST가 어떤 URL을 스캔해야 하는지 모른다는 뜻입니다. 이 문제를 해결하려면 다음 방법 중 하나로 대상 URL을 정의합니다:

  • .gitlab-ci.yml 파일에 DAST_TARGET_URL CI/CD 변수를 설정합니다:

    stages:
      - dast
    
    include:
      - template: Security/DAST.gitlab-ci.yml
    
    dast:
      variables:
        DAST_TARGET_URL: "https://example.com"
    
  • 프로젝트 루트에 environment_url.txt 파일을 생성하고 대상 URL을 추가합니다. 동적 환경의 애플리케이션을 테스트할 때 이 방법을 사용합니다.

러너가 대상 애플리케이션에 연결할 수 없음#

러너가 대상 애플리케이션에 도달할 수 없으면 DAST 스캔이 연결 오류와 함께 실패합니다. 이는 주로 네트워크 구성이나 방화벽 문제로 발생합니다.

DAST는 지정한 URL을 사용해 애플리케이션에 연결해야 합니다:

  • DAST_TARGET_URL 또는 DAST_AUTH_URL에 포트 번호가 포함된 경우, 러너가 해당 포트에 액세스할 수 있어야 합니다.
  • URL에 포트를 지정하지 않으면 DAST는 표준 포트를 사용합니다:
    • HTTP URL에는 80 포트(예: http://example.com).
    • HTTPS URL에는 443 포트(예: https://example.com).

연결 문제의 일반적인 원인은 다음과 같습니다:

  • HTTP와 HTTPS 콘텐츠 혼용. 애플리케이션이 HTTP와 HTTPS를 모두 사용할 수 있습니다. 예를 들어 대상 URL이 http://example.com인데 사이트가 https://example.com에서 리소스를 로드하는 경우, 러너가 두 포트에 모두 액세스할 수 있어야 합니다.
  • 사용자 지정 포트. 애플리케이션이 비표준 포트에서 실행되는 경우 DAST_TARGET_URL에 포트를 포함합니다. 예를 들어 https://example.com:8443입니다.
  • 방화벽 규칙. 애플리케이션이 방화벽 뒤에 있는 경우 러너의 IP 주소에서 오는 트래픽을 허용하도록 규칙을 구성합니다.
  • 내부 및 외부 네트워크. 러너는 애플리케이션에 도달할 수 있는 네트워크에 있어야 합니다. 예를 들어 내부 네트워크의 스테이징 환경에서 테스트하는 경우 같은 네트워크의 러너를 사용합니다.

대상 연결 문제#

DAST는 스캔을 시작하기 전에 대상 URL에 도달할 수 있는지 확인합니다. 대상 URL에 도달할 수 없으면 DAST는 문제 진단에 도움이 되는 상세한 오류 메시지를 출력합니다. 기본적으로 DAST는 최대 60초까지 2초마다 연결을 재시도합니다. DAST_TARGET_CHECK_TIMEOUT으로 DAST가 연결을 재시도하는 시점을 구성할 수 있습니다.

연결 문제가 발생하는 경우:

  1. DAST_TARGET_URL 구성을 확인합니다.

    • 호스트 이름, 포트, 프로토콜에 오타가 없는지 확인합니다.
    • URL에 프로토콜(http:// 또는 https://)이 포함되어 있는지 확인합니다.
    • 포트 번호가 애플리케이션이 실행 중인 포트와 일치하는지 확인합니다.
  2. 러너에서 연결을 테스트합니다.

    • 연결 테스트: curl --verbose "http://your-target-url:port"
    • DNS 확인 검사: nslookup your-hostname.com
    • 포트 개방 여부 확인: nc -zv your-hostname.com port
  3. 애플리케이션이 실행 중인지 확인합니다.

    • 애플리케이션이 정상적으로 시작되었는지 확인합니다.
    • 애플리케이션 로그에서 시작 오류를 검토합니다.
    • 데이터베이스와 API를 포함한 모든 의존성을 사용할 수 있는지 확인합니다.
  4. 네트워크 및 방화벽 구성을 확인합니다.

    • 방화벽 규칙이 필요한 포트의 트래픽을 허용하는지 확인합니다.
    • 내부 애플리케이션의 경우 러너가 내부 DNS 서버에 액세스할 수 있는지 확인합니다.
  5. 애플리케이션이 시작되거나 정상 상태가 되기까지 오래 걸리는 경우 타임아웃을 늘립니다:

       variables:
         DAST_TARGET_CHECK_TIMEOUT: "5m"  # Wait up to 5 minutes
    

DNS 조회 실패#

DNS lookup failed와 같은 오류가 표시될 수 있습니다. 이는 다음과 같은 이유로 DAST가 제공된 호스트 이름의 서버 주소를 찾을 수 없을 때 발생합니다:

  • DAST_TARGET_URL의 호스트 이름에 오타가 있거나 잘못되었습니다.
  • 도메인이 등록되지 않았거나 존재하지 않습니다.
  • 네트워크 또는 러너 환경에 DNS 확인 문제가 있습니다.

연결 거부됨#

connection refused라는 오류가 표시될 수 있습니다. 이는 보통 서버는 존재하지만 다음과 같은 경우에 발생합니다:

  • 애플리케이션이 아직 시작을 완료하지 않았습니다.
  • 애플리케이션이 지정한 포트와 다른 포트에서 실행 중입니다.
  • 방화벽이 러너와 애플리케이션 사이의 연결을 차단하고 있습니다.
  • 애플리케이션이 충돌했거나 시작에 실패했습니다.

대상이 HTTP 5xx 오류로 응답#

대상 애플리케이션이 HTTP 5xx 오류로 응답할 수 있습니다. 이는 애플리케이션에 도달할 수는 있지만 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout 같은 서버 오류로 응답할 때 발생합니다.

다음과 같은 경우에 서버 오류가 표시될 수 있습니다:

  • 애플리케이션이 시작 중이며 아직 완전히 준비되지 않았습니다.
  • 애플리케이션에 구성 오류가 있습니다.
  • 데이터베이스와 API 같은 필수 의존성을 사용할 수 없습니다.

예상 결과#

DAST 스캔에서 문제를 겪는 많은 사용자는 스캐너가 무엇을 해야 한다고 생각하는지에 대해 상위 수준에서 명확한 생각을 가지고 있습니다. 예를 들어 특정 페이지를 스캔하지 않는다거나, 페이지의 버튼을 선택하지 않는다는 것입니다.

해결책을 찾는 범위를 좁히려면 가능한 한 문제를 분리해 봅니다. 예를 들어 DAST가 특정 페이지를 스캔하지 않는 상황을 생각해 봅니다. DAST가 그 페이지를 어디에서 찾아야 했는지, 거기에 도달하기까지 어떤 경로를 거쳤는지, 참조 페이지에 DAST가 선택해야 했지만 선택하지 않은 요소가 있었는지 확인합니다.

사람이 달성할 수 있는 결과인지 확인#

사람이 애플리케이션을 수동으로 탐색할 수 없다면 DAST도 애플리케이션을 스캔할 수 없습니다.

예상하는 결과를 알고 있다면, 사용 중인 컴퓨터의 브라우저로 그 결과를 수동으로 재현해 봅니다. 예를 들어 다음과 같이 진행합니다:

  • 새 시크릿/개인 브라우저 창을 엽니다.
  • 개발자 도구를 엽니다. 콘솔의 오류 메시지를 계속 확인합니다.
    • Chrome: View -> Developer -> Developer Tools.
    • Firefox: Tools -> Browser Tools -> Web Developer Tools.
  • 인증하는 경우:
    • DAST_AUTH_URL로 이동합니다.
    • DAST_AUTH_USERNAME_FIELD에 DAST_AUTH_USERNAME을 입력합니다.
    • DAST_AUTH_PASSWORD_FIELD에 DAST_AUTH_PASSWORD를 입력합니다.
    • DAST_AUTH_SUBMIT_FIELD를 선택합니다.
  • 링크를 선택하고 폼을 채웁니다. 올바르게 스캔되지 않는 페이지로 이동합니다.
  • 애플리케이션의 동작을 관찰합니다. 자동 스캐너에 문제를 일으킬 수 있는 요소가 있는지 살펴봅니다.

DAST가 작동하지 않는 원인#

다음과 같은 경우 DAST가 올바르게 스캔할 수 없습니다:

  • CAPTCHA가 있는 경우. 스캔 대상 애플리케이션의 테스트 환경에서는 CAPTCHA를 끕니다.
  • 대상 애플리케이션에 액세스할 수 없는 경우. DAST 구성에 사용한 URL로 GitLab Runner가 애플리케이션에 액세스할 수 있어야 합니다.

애플리케이션의 작동 방식#

DAST 스캔이 작동하지 않는 이유를 파악하려면 애플리케이션이 어떻게 작동하는지 이해하는 것이 매우 중요합니다. 예를 들어 다음과 같은 상황에서는 추가 구성 설정이 필요할 수 있습니다.

  • 요소를 가리는 팝업 대화 상자가 있는지 확인합니다.
  • 로드된 페이지가 일정 시간이 지난 뒤 크게 바뀌는지 확인합니다.
  • 애플리케이션의 로드 속도가 특히 느리거나 빠른지 확인합니다.
  • 대상 애플리케이션이 로드 중에 끊기듯 움직이는지 확인합니다.
  • 애플리케이션이 클라이언트의 위치에 따라 다르게 작동하는지 확인합니다.
  • 애플리케이션이 단일 페이지 애플리케이션인지 확인합니다.
  • 애플리케이션이 HTML 폼을 제출하는지, 아니면 JavaScript와 AJAX를 사용하는지 확인합니다.
  • 애플리케이션이 웹소켓을 사용하는지 확인합니다.
  • 애플리케이션이 특정 웹 프레임워크를 사용하는지 확인합니다.
  • 버튼을 선택하면 폼 제출을 계속하기 전에 JavaScript가 실행되는지, 그리고 그 속도가 빠른지 느린지 확인합니다.
  • DAST가 요소나 페이지가 준비되기 전에 요소를 선택하거나 검색할 가능성이 있는지 확인합니다.

DAST가 수행하는 작업#

히스토리
  • 간결한 로그가 GitLab 18.3에 도입되었습니다.

job 콘솔(CI/CD job 로그)은 DAST가 수행하는 작업을 간결하게 요약해 보여줍니다. 더 상세한 진단 정보가 필요하면 로그 파일을 구성해 세분화된 출력을 생성할 수 있습니다.

다음 로깅 옵션을 사용할 수 있습니다:

  • 진단 로그. 분석기가 무엇을 하고 있는지 파악하는 데 유용합니다.
  • Chromium DevTools 로깅. DAST와 Chromium 사이의 통신을 확인하는 데 유용합니다.
  • Chromium 로그. Chromium이 예기치 않게 충돌할 때 오류를 기록하는 데 유용합니다.

진단 로그#

분석기 로그 파일로 스캔 문제를 진단합니다. 분석기의 여러 부분을 서로 다른 레벨로 기록할 수 있습니다.

로그 메시지 형식#

로그 메시지의 형식은 [time] [log level] [log module] [message] [additional properties]입니다.

예를 들어 다음 로그 항목은 레벨이 INFO이고, CRAWL 로그 모듈에 속하며, 메시지는 Crawled path이고, 추가 속성으로 nav_id와 path를 가집니다.

2021-04-21T00:34:04.000 INF CRAWL Crawled path nav_id=0cc7fd path="LoadURL [https://my.site.com:8090]"

로그 대상#

로그는 로그 파일 아티팩트로 전송됩니다. 환경 변수 DAST_LOG_FILE_CONFIG를 사용해 각 대상이 서로 다른 로그를 받도록 구성할 수 있습니다. 예를 들어 다음과 같습니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_BROWSER_SCAN: "true"
    DAST_LOG_FILE_CONFIG: "loglevel:debug,cache:warn"           # file log defaults to DEBUG level, logs CACHE module at WARN

기본적으로 파일 로그는 gl-dast-scan.log라는 job 아티팩트입니다. 이 경로를 구성하려면 DAST_LOG_FILE_PATH CI/CD 변수를 수정합니다.

로그 레벨#

구성할 수 있는 로그 레벨은 다음과 같습니다:

로그 모듈 구성 요소 개요 추가 정보
TRACE 기능의 특정하고 종종 노이즈가 많은 내부 동작에 사용됩니다.
DEBUG 기능의 내부 동작을 설명합니다. 진단 목적으로 사용됩니다.
INFO 스캔의 상위 수준 흐름과 결과를 설명합니다. 지정하지 않으면 기본 레벨입니다.
WARN DAST가 복구하여 스캔을 계속하는 오류 상황을 설명합니다.
FATAL/ERROR/PANIC 종료 전 복구할 수 없는 오류를 설명합니다.

로그 모듈#

LOGLEVEL은 로그 대상의 기본 로그 레벨을 구성합니다. 다음 모듈 중 하나라도 구성되어 있으면 DAST는 기본 로그 레벨보다 해당 모듈의 로그 레벨을 우선 적용합니다.

로깅을 구성할 수 있는 모듈은 다음과 같습니다:

로그 모듈 구성 요소 개요
ACTIV 활성 공격에 사용됩니다.
AUTH 인증된 스캔 생성에 사용됩니다.
BPOOL 크롤링을 위해 대여되는 브라우저 집합입니다.
BROWS 브라우저의 상태나 페이지를 쿼리하는 데 사용됩니다.
CACHE 캐시된 HTTP 리소스의 캐시 히트와 미스를 보고하는 데 사용됩니다.
CHROM Chrome DevTools 메시지를 기록하는 데 사용됩니다.
CONFG 분석기 구성을 기록하는 데 사용됩니다.
CONTA DevTools 메시지에서 HTTP 요청과 응답의 일부를 수집하는 컨테이너에 사용됩니다.
CRAWL 핵심 크롤러 알고리즘에 사용됩니다.
CRWLG 크롤 그래프 생성기에 사용됩니다.
DATAB 내부 데이터베이스에 데이터를 영속화하는 데 사용됩니다.
LEASE 브라우저 풀에 추가할 브라우저를 생성하는 데 사용됩니다.
MAIN 크롤러의 주 이벤트 루프 흐름에 사용됩니다.
NAVDB 탐색 항목을 저장하는 영속화 메커니즘에 사용됩니다.
REGEX 정규 표현식 실행 시 성능 통계를 기록하는 데 사용됩니다.
REPT 보고서 생성에 사용됩니다.
STAT 스캔 실행 중 일반 통계에 사용됩니다.
VLDFN 취약점 정의를 로드하고 파싱하는 데 사용됩니다.
WEBGW 활성 검사 실행 시 대상 애플리케이션으로 전송되는 메시지를 기록하는 데 사용됩니다.
SCOPE 범위 관리와 관련된 메시지를 기록하는 데 사용됩니다.

SECURE_LOG_LEVEL#

히스토리
  • GitLab 17.11에서 도입되었습니다.

DAST_LOG_FILE_CONFIG로 로그 모듈을 구성하는 방법의 더 단순한 대안으로 SECURE_LOG_LEVEL을 설정할 수 있습니다:

  • 지원되는 로그 레벨 중 하나로 설정합니다. 이렇게 하면 지정한 레벨이 모든 모듈에 대해 로그 파일의 기본 로그 레벨이 됩니다.
  • debug 또는 trace로 설정하면 인증 보고서가 활성화됩니다.
  • trace로 설정하면 DevTools 로깅이 활성화됩니다.

예를 들어 다음과 같습니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    SECURE_LOG_LEVEL: "trace"
    # is equivalent to:
    # DAST_LOG_FILE_CONFIG: "loglevel:trace"
    # DAST_LOG_DEVTOOLS_CONFIG: "Default:messageAndBody,truncate:2000"
    # DAST_AUTH_REPORT: "true"

DAST_LOG_FILE_CONFIG, DAST_LOG_DEVTOOLS_CONFIG, DAST_AUTH_REPORT의 설정은 SECURE_LOG_LEVEL의 설정을 재정의합니다.

예시 - 크롤링된 경로 기록#

스캔의 크롤 단계에서 발견된 탐색 경로를 로그 파일에 기록하려면 로그 파일 모듈 CRAWL을 DEBUG로 설정합니다. 이는 DAST가 대상 애플리케이션을 올바르게 크롤링하고 있는지 파악하는 데 유용합니다.

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_FILE_CONFIG: "crawl:debug"

예를 들어 다음 출력은 https://example.com 페이지를 크롤링하는 동안 네 개의 앵커 링크가 발견되었음을 보여줍니다.

2022-11-17T11:18:05.578 DBG CRAWL executing step nav_id=6ec647d8255c729160dd31cb124e6f89 path="LoadURL [https://example.com]" step=1
...
2022-11-17T11:18:11.900 DBG CRAWL found new navigations browser_id=2243909820020928961 nav_count=4 nav_id=6ec647d8255c729160dd31cb124e6f89 of=1 step=1
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page1.html]" nav=bd458cc1fc2d7c6fb984464b6d968866 parent_nav=6ec647d8255c729160dd31cb124e6f89
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page2.html]" nav=6dcb25f9f9ece3ee0071ac2e3166d8e6 parent_nav=6ec647d8255c729160dd31cb124e6f89
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page3.html]" nav=89efbb0c6154d6c6d85a63b61a7cdc6f parent_nav=6ec647d8255c729160dd31cb124e6f89
2022-11-17T11:18:11.901 DBG CRAWL adding navigation action="LeftClick [a href=/page4.html]" nav=f29b4f4e0bdee70f5255de7fc080f04d parent_nav=6ec647d8255c729160dd31cb124e6f89

Chromium DevTools 로깅#

Warning

DevTools 메시지를 기록하는 것은 보안 위험입니다. 출력에는 사용자 이름, 비밀번호, 인증 토큰 같은 시크릿이 포함됩니다. 출력은 GitLab 서버에 업로드되며 job 로그에서 보일 수 있습니다.

DAST 브라우저 기반 스캐너는 Chrome DevTools 프로토콜을 사용해 Chromium 브라우저를 제어합니다. DevTools 메시지를 기록하면 브라우저가 무엇을 하고 있는지 투명하게 파악할 수 있습니다. 예를 들어 버튼 선택이 동작하지 않는 경우, DevTools 메시지에서 브라우저 콘솔 로그의 CORS 오류가 원인임을 확인할 수 있습니다. DevTools 메시지가 포함된 로그는 크기가 매우 커질 수 있습니다. 따라서 실행 시간이 짧은 job에서만 활성화해야 합니다.

모든 DevTools 메시지를 기록하려면 CHROM 로그 모듈을 trace로 설정하고 로깅 레벨을 구성합니다. 다음은 DevTools 로그의 예시입니다:

2022-12-05T06:27:24.280 TRC CHROM event received    {"method":"Fetch.requestPaused","params":{"requestId":"interception-job-3.0","request":{"url":"http://auth-auto:8090/font-awesome.min.css","method":"GET","headers":{"Accept":"text/css,*/*;q=0.1","Referer":"http://auth-auto:8090/login.html","User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/105.0.5195.102 Safari/537.36"},"initialPriority":"VeryHigh","referrerPolicy":"strict-origin-when-cross-origin"},"frameId":"A706468B01C2FFAA2EB6ED365FF95889","resourceType":"Stylesheet","networkId":"39.3"}} method=Fetch.requestPaused
2022-12-05T06:27:24.280 TRC CHROM request sent      {"id":47,"method":"Fetch.continueRequest","params":{"requestId":"interception-job-3.0","headers":[{"name":"Accept","value":"text/css,*/*;q=0.1"},{"name":"Referer","value":"http://auth-auto:8090/login.html"},{"name":"User-Agent","value":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/105.0.5195.102 Safari/537.36"}]}} id=47 method=Fetch.continueRequest
2022-12-05T06:27:24.281 TRC CHROM response received {"id":47,"result":{}} id=47 method=Fetch.continueRequest

DevTools 로그 레벨 사용자 지정#

Chrome DevTools 요청, 응답, 이벤트는 도메인별로 네임스페이스가 지정됩니다. DAST는 각 도메인과 메시지를 포함한 각 도메인에 서로 다른 로깅 구성을 지정할 수 있게 합니다. 환경 변수 DAST_LOG_DEVTOOLS_CONFIG는 세미콜론으로 구분된 로깅 구성 목록을 받습니다. 로깅 구성은 [domain/message]:[what-to-log][,truncate:[max-message-size]] 구조로 선언합니다.

  • domain/message는 기록 대상을 지정합니다.
    • Default를 값으로 사용하면 모든 도메인과 메시지를 의미합니다.
    • 도메인을 지정할 수 있습니다(예: Browser, CSS, Page, Network).
    • 메시지를 포함한 도메인을 지정할 수 있습니다(예: Network.responseReceived).
    • 여러 구성이 해당되는 경우 가장 구체적인 구성이 적용됩니다.
  • what-to-log는 기록 여부와 기록 내용을 지정합니다.
    • message는 메시지를 수신했다는 사실만 기록하고 메시지 내용은 기록하지 않습니다.
    • messageAndBody는 메시지 내용과 함께 메시지를 기록합니다. truncate와 함께 사용하는 것을 권장합니다.
    • suppress는 메시지를 기록하지 않습니다. 노이즈가 많은 도메인과 메시지를 숨기는 데 사용합니다.
  • truncate는 출력되는 메시지의 크기를 제한하는 선택적 구성입니다.

예시 - 모든 DevTools 메시지 기록#

어디에서 시작해야 할지 확실하지 않을 때 모든 것을 기록하는 데 사용합니다.

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_FILE_CONFIG: "chrom:trace"
    DAST_LOG_DEVTOOLS_CONFIG: "Default:messageAndBody,truncate:2000"

예시 - HTTP 메시지 기록#

리소스가 올바르게 로드되지 않을 때 유용합니다. HTTP 메시지 이벤트와 함께 요청을 계속할지 실패 처리할지에 대한 결정도 기록됩니다. 브라우저 콘솔의 오류도 함께 기록됩니다.

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_FILE_CONFIG: "chrom:trace"
    DAST_LOG_DEVTOOLS_CONFIG: "Default:suppress;Fetch:messageAndBody,truncate:2000;Network:messageAndBody,truncate:2000;Log:messageAndBody,truncate:2000;Console:messageAndBody,truncate:2000"

job 콘솔 출력 재정의#

기본적으로 job 콘솔에는 DAST 활동의 간결한 요약이 표시됩니다. 전체 진단 로그를 job 콘솔에 출력하려면 DAST_FF_DIAGNOSTIC_JOB_OUTPUT과 DAST_LOG_CONFIG 변수를 모두 설정합니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_FF_DIAGNOSTIC_JOB_OUTPUT: "true"
    DAST_LOG_CONFIG: "crawl:debug"                               # console log defaults to INFO level, logs AUTH module at DEBUG

이슈 552171은 GitLab 19.0에서 이 옵션을 제거할 것을 제안합니다.

Chromium 로그#

드물게 Chromium이 충돌하는 경우, Chromium 프로세스의 STDOUT과 STDERR를 로그에 기록하면 도움이 될 수 있습니다. 환경 변수 DAST_LOG_BROWSER_OUTPUT을 true로 설정하면 이 목적을 달성할 수 있습니다.

DAST는 많은 Chromium 프로세스를 시작하고 중지합니다. DAST는 각 프로세스의 출력을 로그 모듈 LEASE와 로그 레벨 INFO로 모든 로그 대상에 전송합니다.

예를 들어 다음과 같습니다:

include:
  - template: DAST.gitlab-ci.yml

dast:
  variables:
    DAST_LOG_BROWSER_OUTPUT: "true"

알려진 문제#

로그에 response body exceeds allowed size가 포함됨#

기본적으로 DAST는 HTTP 응답 본문이 10 MB 이하인 HTTP 요청을 처리합니다. 그렇지 않으면 DAST가 응답을 차단하며, 이로 인해 스캔이 실패할 수 있습니다. 이 제약은 스캔 중 메모리 사용량을 줄이기 위한 것입니다.

다음은 DAST가 https://example.com/large.js에 있는 JavaScript 파일의 크기가 제한을 초과해 차단한 로그 예시입니다:

2022-12-05T06:28:43.093 WRN BROWS response body exceeds allowed size allowed_size_bytes=1000000 browser_id=752944257619431212 nav_id=ae23afe2acbce2c537657a9112926f1a of=1 request_id=interception-job-2.0 response_size_bytes=9333408 step=1 url=https://example.com/large.js
2022-12-05T06:28:58.104 WRN CONTA request failed, attempting to continue scan error=net::ERR_BLOCKED_BY_RESPONSE index=0 requestID=38.2 url=https://example.com/large.js

이는 DAST_PAGE_MAX_RESPONSE_SIZE_MB 구성으로 변경할 수 있습니다. 예를 들어 다음과 같습니다.

dast:
  variables:
    DAST_PAGE_MAX_RESPONSE_SIZE_MB: "25"

크롤러가 예상 페이지에 도달하지 않음#

캐시 비활성화 시도#

DAST가 애플리케이션 페이지를 잘못 캐시하면 DAST가 애플리케이션을 제대로 크롤링하지 못할 수 있습니다. 크롤러가 일부 페이지를 예상과 달리 찾지 못하는 것이 보이면 DAST_USE_CACHE: "false" 변수를 설정해 도움이 되는지 확인합니다. 이 설정은 스캔 성능을 크게 떨어뜨릴 수 있습니다. 반드시 필요한 경우에만 캐시를 비활성화합니다. 구독이 있는 경우 지원 티켓을 생성해 캐시가 웹사이트 크롤링을 막는 이유를 조사합니다.

대상 경로 직접 지정#

크롤러는 일반적으로 정의된 대상 URL에서 시작해 사이트와 상호작용하며 추가 페이지를 찾습니다. 다만 크롤러가 시작할 경로를 직접 지정하는 방법이 두 가지 있습니다:

  • sitemap.xml 사용: 사이트맵은 웹사이트의 페이지를 지정하는 잘 정의된 프로토콜입니다. DAST 크롤러는 <target URL>/sitemap.xml에서 sitemap.xml 파일을 찾고, 지정된 모든 URL을 크롤러의 시작점으로 사용합니다. 사이트맵 인덱스 파일은 지원되지 않습니다.
  • DAST_TARGET_PATHS 사용: 이 구성 변수로 크롤러의 입력 경로를 지정할 수 있습니다. 예시: DAST_TARGET_PATHS: /,/page/1.html,/page/2.html.

요청이 차단되지 않는지 확인#

기본적으로 DAST는 대상 URL 도메인으로의 요청만 허용합니다. 웹사이트가 대상 이외의 도메인으로 요청을 보내는 경우 DAST_SCOPE_ALLOW_HOSTS로 해당 호스트를 지정합니다. 예시: "example.com"이 인증 토큰을 갱신하기 위해 "auth.example.com"으로 인증 요청을 보냅니다. 해당 도메인이 허용되지 않으므로 요청이 차단되고 크롤러는 새 페이지를 찾지 못합니다.

최대 액션 수와 크롤러 시간 초과#

크롤러에는 활동량과 대상 사이트에서 소요하는 시간에 기본 제한이 있습니다:

  1. 기본적으로 크롤러는 10,000개의 액션을 처리합니다. 액션은 링크 선택이나 폼 작성일 수 있습니다. 크롤러가 이 제한을 초과하면 디버그 수준 로그 not adding navigation as it exceeds max actions가 표시됩니다.
  2. 기본적으로 크롤러는 최대 24시간 동안 실행됩니다. 이 시간 제한을 초과하면 트레이스 수준 로그 crawl complete, timed out이 표시됩니다.

크롤러가 이 제한 중 하나에 도달하면 스캐너가 중지되며 대상 웹사이트를 완전히 커버할 수 없습니다. 따라서 이러한 제한을 초과했다는 것은 스캔 중 문제가 있었음을 나타내며 최적화 기회가 될 수 있습니다.

애플리케이션에 구조는 비슷하지만 페이지마다 데이터가 다른 템플릿 기반 페이지가 있거나 URL 패턴(예: /products/item-123, /products/item-456, /products/item-789)이 눈에 띈다면, 그룹화된 URL을 구성해 보안 커버리지를 유지하면서 스캔 시간을 줄입니다.

그룹화된 URL은 제품 페이지가 많은 전자상거래 사이트, 콘텐츠 기반 사이트, 검색 인터페이스 (예: /search?q=term&page=1, /search?q=term&page=2)에 적합합니다.

스캔 시간 관리에 대한 자세한 내용은 스캔 시간 관리를 참고합니다. 다른 전략이 적합하지 않고 대상 사이트가 방대하다면 크롤러 시간 초과(DAST_CRAWL_TIMEOUT)나 최대 액션 수(DAST_CRAWL_MAX_ACTIONS)를 늘립니다.