InfoGrab DocsInfoGrab Docs

인증

요약

완전한 커버리지를 확보하려면 DAST 분석기가 테스트 대상 애플리케이션에 인증해야 합니다. DAST에 인증이 필요한 이유는 다음과 같습니다. DAST job은 애플리케이션에 스스로 인증하며, 가장 일반적인 방식은 브라우저에서 로그인 폼을 채워 제출하는 것입니다.

완전한 커버리지를 확보하려면 DAST 분석기가 테스트 대상 애플리케이션에 인증해야 합니다. 이를 위해 DAST CI/CD job에서 인증 자격 증명과 인증 방법을 구성해야 합니다.

DAST에 인증이 필요한 이유는 다음과 같습니다.

  • 실제 공격을 시뮬레이션하고 공격자가 악용할 수 있는 취약점을 식별하기 위해서입니다.
  • 인증 후에만 보이는 사용자별 기능과 사용자 지정 동작을 테스트하기 위해서입니다.

DAST job은 애플리케이션에 스스로 인증하며, 가장 일반적인 방식은 브라우저에서 로그인 폼을 채워 제출하는 것입니다. 폼을 제출한 다음 DAST job은 인증이 성공했는지 확인합니다. 인증에 성공하면 DAST job은 작업을 계속하고, 대상 애플리케이션을 크롤링할 때 재사용할 수 있도록 자격 증명도 저장합니다. 성공하지 못하면 DAST job이 중지됩니다.

DAST가 지원하는 인증 방법은 다음과 같습니다.

  • 단일 단계 로그인 폼
  • 다단계 로그인 폼
  • 구성된 대상 URL 외부의 URL에 인증

인증 자격 증명을 선택할 때 유의할 사항은 다음과 같습니다.

  • 운영 시스템이나 운영 서버에 유효한 자격 증명, 또는 운영 데이터에 접근하는 데 쓰는 자격 증명은 사용하지 않습니다.
  • 운영 서버를 대상으로 인증된 스캔을 실행하지 않습니다. 인증된 스캔은 인증된 사용자가 할 수 있는 모든 기능을 수행할 수 있으며, 데이터 수정·삭제, 폼 제출, 링크 따라가기도 포함됩니다. 인증된 스캔은 운영 환경이 아닌 시스템이나 서버를 대상으로만 실행합니다.
  • DAST가 애플리케이션 전체를 테스트할 수 있는 자격 증명을 제공합니다.
  • 자격 증명에 만료일이 있으면 나중에 참고할 수 있도록 기록해 둡니다. 예를 들어 1Password 같은 비밀번호 관리자를 사용합니다.

다음 다이어그램은 인증의 여러 단계에서 인증 변수가 어떻게 사용되는지 보여 줍니다.

Mermaid 다이어그램 (34줄)
소스 코드 보기
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
    accTitle: Authentication variables
    accDescr: A sequence diagram showing authentication variables at different stages of authentication.
    participant DAST
    participant Browser
    participant Target
Note over DAST,Target: Initialization
DAST->>Browser: Initialize browser with proxy
DAST->>Browser: Navigate to DAST_AUTH_URL
Browser->>Target: Load initial page
Target-->>Browser: Return page content (may not contain login form)

Note over DAST,Target: Process before-login actions
DAST->>Browser: Click elements specified in DAST_AUTH_BEFORE_LOGIN_ACTIONS
Browser->>Target: Send click actions
Target-->>Browser: Render login form (modal/page)

Note over DAST,Target: Authentication
DAST->>Browser: Fill DAST_AUTH_USERNAME & DAST_AUTH_PASSWORD
DAST->>Browser: Click "submit"
Browser->>Target: Submit form
Target-->>Browser: Process authentication
Target-->>Browser: Set auth tokens

Note over DAST,Target: Process after-login actions (if specified)
DAST->>Browser: Execute DAST_AUTH_AFTER_LOGIN_ACTIONS
Browser->>Target: Actions after login but before login verification

Note over DAST,Target: Verification
DAST->>Browser: Check URL matches DAST_AUTH_SUCCESS_IF_AT_URL (if configured)
DAST->>Browser: Check element exists DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND (if configured)
DAST-&gt;&gt;Browser: Check login form absent DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM (default is true)</code></pre></details></div>

시작하기#

Note

분석기의 인증이 계속 작동하는지 주기적으로 확인해야 합니다. 애플리케이션이 변경되면서 시간이 지남에 따라 깨지는 경우가 많습니다.

DAST 인증 스캔을 실행하는 절차는 다음과 같습니다.

사전 요구 사항#

  • 스캔 중에 인증할 사용자의 사용자 이름과 비밀번호가 있습니다.
  • DAST가 애플리케이션에 인증할 수 있는지 확인하기 위해 알려진 문제를 확인했습니다.
  • 폼 인증을 사용한다면 그 사전 요구 사항을 충족했습니다.
  • 폼 인증 흐름에 시간 기반 일회용 비밀번호가 포함된다면 추가 사전 요구 사항을 충족했습니다.
  • 인증이 성공했는지 확인하는 방법을 검토했습니다.

폼 인증#

  • 애플리케이션 로그인 폼의 URL을 알고 있습니다. 또는 인증 URL에서 로그인 폼으로 이동하는 방법을 알고 있습니다(클릭으로 로그인 폼으로 이동 참고).
  • DAST가 각 값을 입력하는 데 사용하는 사용자 이름 HTML 필드와 비밀번호 HTML 필드의 선택자를 알고 있습니다.
  • 선택하면 로그인 폼을 제출하는 요소의 선택자를 알고 있습니다.

TOTP 인증#

히스토리
  • 스캐너 버전 6.9에서 도입되었습니다.
  • 테스트 사용자의 TOTP 등록에 사용하는 시크릿 키를 Base32로 인코딩한 값이 있습니다.
  • 인증 공급자가 다음 TOTP 구성(Google Authenticator와 동일)을 지원하는지 확인했습니다.
    • HMAC 알고리즘: SHA-1
    • 시간 간격: 30초
    • 토큰 길이: 6
  • DAST가 생성된 TOTP 토큰을 입력하는 데 사용하는 TOTP 필드의 선택자를 알고 있습니다.
  • TOTP 토큰을 비밀번호와 별도로 제출하는 경우, TOTP 토큰을 제출하는 요소의 선택자를 알고 있습니다.

사용 가능한 CI/CD 변수#

DAST 인증 CI/CD 변수 목록은 인증 변수를 참고합니다.

DAST CI/CD 변수 표는 Rake 태스크 bundle exec rake gitlab:dast_variables:compile_docs로 생성됩니다. 이 태스크는 lib/gitlab/security/dast_variables.rb에 정의된 변수 메타데이터를 사용합니다.

대상 웹사이트 업데이트#

CI/CD 변수 DAST_TARGET_URL로 정의하는 대상 웹사이트는 DAST가 애플리케이션 크롤링을 시작할 때 사용하는 URL입니다.

인증 스캔에서 최선의 크롤링 결과를 얻으려면 대상 웹사이트가 사용자 인증 후에만 접근할 수 있는 URL이어야 합니다. 보통은 사용자가 로그인한 다음 도착하는 페이지의 URL입니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com/dashboard/welcome"
    DAST_AUTH_URL: "https://example.com/login"

HTTP 인증 구성#

Basic Authentication 같은 HTTP 인증 스키마를 사용하려면 DAST_AUTH_TYPE 값을 basic-digest로 설정할 수 있습니다. Negotiate나 NTLM 같은 다른 스키마도 동작할 수 있지만, 현재 자동화된 테스트 커버리지가 없어 공식적으로 지원하지는 않습니다.

구성하려면 DAST job에 CI/CD 변수 DAST_AUTH_TYPE, DAST_AUTH_URL, DAST_AUTH_USERNAME, DAST_AUTH_PASSWORD를 정의해야 합니다. 고유한 로그인 URL이 없으면 DAST_AUTH_URL을 DAST_TARGET_URL과 같은 URL로 설정합니다.

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_TYPE: "basic-digest"
    DAST_AUTH_URL: "https://example.com"

DAST_AUTH_USERNAME과 DAST_AUTH_PASSWORD는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

단일 단계 로그인 폼 구성#

단일 단계 로그인 폼은 로그인 폼 요소가 모두 한 페이지에 있습니다. 구성하려면 DAST job에 CI/CD 변수 DAST_AUTH_URL, DAST_AUTH_USERNAME, DAST_AUTH_USERNAME_FIELD, DAST_AUTH_PASSWORD, DAST_AUTH_PASSWORD_FIELD, DAST_AUTH_SUBMIT_FIELD를 정의해야 합니다.

job 정의 YAML에 필드의 URL과 선택자를 설정합니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_USERNAME_FIELD: "css:[name=username]"
    DAST_AUTH_PASSWORD_FIELD: "css:[name=password]"
    DAST_AUTH_SUBMIT_FIELD: "css:button[type=submit]"

DAST_AUTH_USERNAME과 DAST_AUTH_PASSWORD는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

다단계 로그인 폼 구성#

다단계 로그인 폼은 페이지가 두 개입니다. 첫 페이지의 폼에는 사용자 이름과 다음 단계로 넘어가는 제출 버튼이 있습니다. 사용자 이름이 유효하면 다음 페이지의 두 번째 폼에 비밀번호와 폼 제출 버튼이 있습니다.

구성하려면 DAST job에 다음 CI/CD 변수를 정의해야 합니다.

  • DAST_AUTH_URL
  • DAST_AUTH_USERNAME
  • DAST_AUTH_USERNAME_FIELD
  • DAST_AUTH_FIRST_SUBMIT_FIELD
  • DAST_AUTH_PASSWORD
  • DAST_AUTH_PASSWORD_FIELD
  • DAST_AUTH_SUBMIT_FIELD.

job 정의 YAML에 필드의 URL과 선택자를 설정합니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_USERNAME_FIELD: "css:[name=username]"
    DAST_AUTH_FIRST_SUBMIT_FIELD: "css:button[name=next]"
    DAST_AUTH_PASSWORD_FIELD: "css:[name=password]"
    DAST_AUTH_SUBMIT_FIELD: "css:button[type=submit]"

DAST_AUTH_USERNAME과 DAST_AUTH_PASSWORD는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

시간 기반 일회용 비밀번호(TOTP) 구성#

TOTP를 구성하려면 DAST job에 다음 CI/CD 변수를 정의해야 합니다.

  • DAST_AUTH_OTP_FIELD
  • DAST_AUTH_OTP_KEY

비밀번호를 제출한 다음 TOTP 토큰을 별도 폼으로 제출한다면 다음 변수도 정의해야 합니다.

  • DAST_AUTH_OTP_SUBMIT_FIELD

_FIELD 선택자 변수는 job 정의 YAML에 정의할 수 있습니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_USERNAME_FIELD: "css:[name=username]"
    DAST_AUTH_PASSWORD_FIELD: "css:[name=password]"
    DAST_AUTH_SUBMIT_FIELD: "css:button[type=submit]"
    DAST_AUTH_OTP_FIELD: "name:otp"
    DAST_AUTH_OTP_SUBMIT_FIELD: "css:input[type=submit]"

DAST_AUTH_OTP_KEY는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

Single Sign-On(SSO) 구성#

사용자가 애플리케이션에 로그인할 수 있으면 대부분의 경우 DAST도 로그인할 수 있으며, 애플리케이션이 Single Sign-On(SSO)을 사용해도 마찬가지입니다. SSO 솔루션을 사용하는 애플리케이션은 단일 단계 또는 다단계 로그인 폼 구성 가이드에 따라 DAST 인증을 구성합니다.

DAST는 사용자가 외부 ID 공급자(Identity Provider)의 사이트로 리디렉션되어 로그인하는 인증 프로세스를 지원합니다. SSO 인증 프로세스가 지원되는지 확인하려면 DAST 인증의 알려진 문제를 확인합니다.

Windows 통합 인증(Kerberos) 구성#

Windows 통합 인증(Kerberos)은 Windows 도메인 안에서 호스팅되는 사내 업무(line of business, LOB) 애플리케이션에 널리 쓰이는 인증 방식입니다. 사용자 컴퓨터의 로그인 정보를 사용해 별도 입력 요청 없이 인증합니다.

이 인증 방식을 구성하는 절차는 다음과 같습니다.

  1. IT·운영팀의 도움을 받아 필요한 정보를 수집합니다.
  2. .gitlab-ci.yml 파일에서 dast job 정의를 만들거나 업데이트합니다.
  3. 수집한 정보로 예시 krb5.conf 파일을 채웁니다.
  4. 필요한 job 변수를 설정합니다.
  5. 프로젝트 Settings 페이지에서 필요한 시크릿 변수를 설정합니다.
  6. 인증이 동작하는지 테스트하고 확인합니다.

IT·운영 부서의 도움을 받아 다음 정보를 수집합니다.

  • Windows 도메인 또는 Kerberos Realm 이름(EXAMPLE.COM처럼 이름에 마침표가 있어야 합니다)
  • Windows/Kerberos 도메인 컨트롤러의 호스트 이름
  • Kerberos의 경우 인증 서버 이름. Windows 도메인에서는 도메인 컨트롤러입니다.

krb5.conf 파일을 만듭니다.

[libdefaults]
  # Realm is another name for domain name
  default_realm = EXAMPLE.COM
  # These settings are not needed for Windows Domains
  # they support other Kerberos implementations
  kdc_timesync = 1
  ccache_type = 4
  forwardable = true
  proxiable = true
  rdns = false
  fcc-mit-ticketflags = true
[realms]
  EXAMPLE.COM = {
    # Domain controller or KDC
    kdc = kdc.example.com
    # Domain controller or admin server
    admin_server = kdc.example.com
  }
[domain_realm]
  # Mapping DNS domains to realms/Windows domain
  # DNS domains provided by DAST_AUTH_NEGOTIATE_DELEGATION
  # should also be represented here (but without the wildcard)
  .example.com = EXAMPLE.COM
  example.com = EXAMPLE.COM

이 구성은 DAST_AUTH_NEGOTIATE_DELEGATION 변수를 사용합니다. 이 변수는 통합 인증을 허용하는 데 필요한 다음 Chromium 정책을 설정합니다.

이 변수에 설정하는 값은 Windows 도메인이나 Kerberos realm에 연결된 DNS 도메인입니다. 다음과 같이 제공합니다.

  • 소문자와 대문자 양쪽으로 제공합니다.
  • 와일드카드 패턴과 도메인 이름만 있는 형태를 함께 제공합니다.

이 예시에서 Windows 도메인은 EXAMPLE.COM이고 DNS 도메인은 example.com입니다. 따라서 DAST_AUTH_NEGOTIATE_DELEGATION 값은 *.example.com,example.com,*.EXAMPLE.COM,EXAMPLE.COM이 됩니다.

이를 모두 job 정의로 모읍니다.

# This job will extend the dast job defined in
# the DAST template which must also be included.
dast:
  image:
    name: "$SECURE_ANALYZERS_PREFIX/dast:$DAST_VERSION$DAST_IMAGE_SUFFIX"
    docker:
      user: root
  variables:
    DAST_TARGET_URL: https://target.example.com
    DAST_AUTH_URL: https://target.example.com
    DAST_AUTH_TYPE: basic-digest
    DAST_AUTH_NEGOTIATE_DELEGATION: '*.example.com,example.com,*.EXAMPLE.COM,EXAMPLE.COM'
    # Not shown -- DAST_AUTH_USERNAME, DAST_AUTH_PASSWORD set via Settings -> CI -> Variables
  before_script:
    - KRB5_CONF='
[libdefaults]
  default_realm = EXAMPLE.COM
  kdc_timesync = 1
  ccache_type = 4
  forwardable = true
  proxiable = true
  rdns = false
  fcc-mit-ticketflags = true
[realms]
  EXAMPLE.COM = {
    kdc = ad1.example.com
    admin_server = ad1.example.com
  }
[domain_realm]
  .example.com = EXAMPLE.COM
  example.com = EXAMPLE.COM
'
    - cat "$KRB5_CONF" > /etc/krb5.conf
    - echo '$DAST_AUTH_PASSWORD' | kinit $DAST_AUTH_USERNAME
    - klist

예상 출력:

job 콘솔 출력에는 before 스크립트의 출력이 담깁니다. 인증에 성공하면 다음과 비슷하게 표시됩니다. 성공하지 못하면 스캔을 실행하지 않고 job이 실패해야 합니다.

Password for mike@EXAMPLE.COM:
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: mike@EXAMPLE.COM

Valid starting       Expires              Service principal
11/11/2024 21:50:50  11/12/2024 07:50:50  krbtgt/EXAMPLE.COM@EXAMPLE.COM
        renew until 11/12/2024 21:50:50

DAST 스캐너도 다음과 같이 출력하며, 이는 성공을 뜻합니다.

2024-11-08T17:03:09.226 INF AUTH  attempting to authenticate find_auth_fields="basic-digest"
2024-11-08T17:03:09.226 INF AUTH  loading login page LoginURL="https://target.example.com"
2024-11-08T17:03:10.619 INF AUTH  verifying if login attempt was successful true_when="HTTP status code < 400 and has authentication token and no login form found (auto-detected)"
2024-11-08T17:03:10.619 INF AUTH  requirement is satisfied, HTTP login request returned status code 200 want="HTTP status code < 400" url="https://target.example.com/"
2024-11-08T17:03:10.623 INF AUTH  requirement is satisfied, did not detect a login form want="no login form found (auto-detected)"
2024-11-08T17:03:10.623 INF AUTH  authentication token cookies names=""
2024-11-08T17:03:10.623 INF AUTH  authentication token storage events keys=""
2024-11-08T17:03:10.623 INF AUTH  requirement is satisfied, basic authentication detected want="has authentication token"
2024-11-08T17:03:11.230 INF AUTH  login attempt succeeded

클릭으로 로그인 폼으로 이동#

DAST_AUTH_BEFORE_LOGIN_ACTIONS를 정의해 DAST_AUTH_URL에서 클릭할 요소의 경로를 지정하면 DAST가 로그인 폼에 접근할 수 있습니다. 이 방법은 로그인 폼을 팝업(모달) 창으로 표시하거나 로그인 폼에 고유한 URL이 없는 애플리케이션에 적합합니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_BEFORE_LOGIN_ACTIONS: "css:.navigation-menu,css:.login-menu-item"

로그인 폼 제출 후 추가 작업 수행#

DAST_AUTH_AFTER_LOGIN_ACTIONS를 정의하면 로그인 폼을 제출한 다음 인증 정보를 기록하는 확인 단계 전에 수행할 작업 순서를 지정할 수 있습니다. "keep me signed in" 대화 상자를 넘어가는 데 사용할 수 있습니다.

작업 형식
요소 클릭 click(on=<selector>)
드롭다운에서 옵션 선택 select(option=<selector>)

작업은 쉼표로 구분합니다. 선택자에 대한 자세한 내용은 요소의 선택자 찾기를 참고합니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_AFTER_LOGIN_ACTIONS: "select(option=id:accept-yes),click(on=id:continue-button)"

로그아웃 URL 제외#

인증 스캔 중에 DAST가 로그아웃 URL을 크롤링하면 사용자가 로그아웃되고, 남은 스캔은 인증되지 않은 상태로 진행됩니다. 따라서 CI/CD 변수 DAST_SCOPE_EXCLUDE_URLS로 로그아웃 URL을 제외하는 것이 좋습니다. DAST는 제외된 URL에 접근하지 않으므로 사용자가 로그인 상태를 유지합니다.

제공하는 URL은 절대 URL이거나, DAST_TARGET_URL의 기본 경로를 기준으로 한 URL 경로의 정규 표현식일 수 있습니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com/welcome/home"
    DAST_SCOPE_EXCLUDE_URLS: "https://example.com/logout,/user/.*/logout"

요소의 선택자 찾기#

선택자는 브라우저의 페이지에 표시되는 요소의 위치를 지정하기 위해 CI/CD 변수에서 사용합니다. 선택자의 형식은 type:search string입니다. DAST는 유형에 따라 검색 문자열로 선택자를 찾습니다.

선택자 유형 예시 설명
css css:.password-field 지정한 CSS 선택자를 가진 HTML 요소를 검색합니다. 성능을 위해 선택자는 가능한 한 구체적이어야 합니다.
id id:element 지정한 요소 ID를 가진 HTML 요소를 검색합니다.
name name:element 지정한 요소 이름을 가진 HTML 요소를 검색합니다.
xpath xpath://input[@id="my-button"]/a 지정한 XPath를 가진 HTML 요소를 검색합니다. XPath 검색은 다른 검색보다 성능이 낮을 것으로 예상됩니다.

Google Chrome으로 선택자 찾기#

Chrome DevTools의 요소 선택 도구는 선택자를 찾는 효과적인 방법입니다.

  1. Chrome을 열고 선택자를 찾으려는 페이지로 이동합니다. 예를 들어 사이트의 로그인 페이지입니다.
  2. macOS에서는 Command+Shift+C, Windows나 Linux에서는 Control+Shift+C 키보드 단축키로 Chrome DevTools에서 Elements 탭을 엽니다.
  3. Select an element in the page to select it 도구를 선택합니다. search-elements
  4. 선택자를 알고 싶은 페이지의 필드를 선택합니다.
  5. 도구가 활성화된 다음 세부 정보를 보려는 필드를 강조 표시합니다. highlight
  6. 강조 표시하면 선택자로 쓰기 좋은 속성을 포함해 요소의 세부 정보를 확인할 수 있습니다.

이 예시에서는 id="user_login"이 좋은 후보로 보입니다. DAST_AUTH_USERNAME_FIELD: "id:user_login"으로 설정하면 이 값을 DAST 사용자 이름 필드의 선택자로 사용할 수 있습니다.

올바른 선택자 선택#

선택자를 신중하게 고르면 애플리케이션이 변경되어도 견디는 스캔이 됩니다.

선택자는 다음 순서로 선호합니다.

  • id 필드. 이 필드는 보통 페이지에서 고유하고 거의 변경되지 않습니다.
  • name 필드. 이 필드는 보통 페이지에서 고유하고 거의 변경되지 않습니다.
  • 해당 필드에 특화된 class 값. 예를 들어 사용자 이름 필드의 username 클래스에 대한 선택자 "css:.username"입니다.
  • 필드에 특화된 데이터 속성의 존재. 예를 들어 사용자 이름 필드의 data-username 필드에 값이 있을 때의 선택자 "css:[data-username]"입니다.
  • 여러 class 계층 값. 예를 들어 username 클래스를 가진 요소가 여러 개인데 그중 하나만 login-form 클래스를 가진 요소 안에 중첩되어 있을 때의 선택자 "css:.login-form .username"입니다.

특정 필드를 찾는 선택자에서는 다음을 검색 대상으로 삼지 않습니다.

  • 동적으로 생성되는 id, name, attribute, class, value.
  • column-10, dark-grey 같은 일반적인 클래스 이름.
  • 다른 선택자 검색보다 성능이 낮은 XPath 검색.
  • css:*, xpath://*로 시작하는 것처럼 범위가 지정되지 않은 검색.

인증 성공 확인#

DAST가 로그인 폼을 제출한 다음 인증이 성공했는지 판단하는 확인 프로세스가 진행됩니다. 인증에 성공하지 못하면 스캔이 오류와 함께 중단됩니다.

로그인 폼을 제출한 다음, 아래 경우에는 인증이 성공하지 못한 것으로 판단합니다.

  • 로그인 제출 HTTP 응답의 상태 코드가 400 또는 500 계열입니다.
  • 확인 검사 중 하나라도 실패합니다.
  • 인증 과정에서 충분히 무작위한 값을 가진 인증 토큰이 설정되지 않습니다.

확인 검사#

확인 검사는 인증이 끝난 다음 브라우저 상태를 검사해 인증이 성공했는지 한 번 더 판단합니다.

확인 검사를 구성하지 않으면 DAST는 로그인 폼이 없는지 테스트합니다.

URL 기반 확인#

로그인 폼을 성공적으로 제출한 다음 브라우저 탭에 표시되는 URL을 DAST_AUTH_SUCCESS_IF_AT_URL로 정의합니다.

DAST는 확인 URL을 인증 후 브라우저의 URL과 비교합니다. 둘이 같지 않으면 인증이 성공하지 못한 것입니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_SUCCESS_IF_AT_URL: "https://example.com/user/welcome"

요소 존재 기반 확인#

로그인 폼을 성공적으로 제출한 다음 표시되는 페이지에서 하나 이상의 요소를 찾는 선택자를 DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND로 정의합니다. 요소를 찾지 못하면 인증이 성공하지 못한 것입니다. 로그인이 실패할 때 표시되는 페이지에서 이 선택자를 검색하면 요소가 없어야 합니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND: "css:.welcome-user"

로그인 폼 부재 기반 확인#

DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM을 "true"로 정의하면, 로그인 폼을 성공적으로 제출한 다음 표시되는 페이지에서 DAST가 로그인 폼을 검색합니다. 로그인 후에도 로그인 폼이 남아 있으면 인증이 성공하지 못한 것입니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM: "true"

인증 토큰#

DAST는 인증 과정에서 설정된 인증 토큰을 기록합니다. 인증 토큰은 DAST가 새 브라우저를 열 때 그 브라우저에 로드되므로, 사용자는 스캔 내내 로그인 상태를 유지할 수 있습니다.

토큰을 기록하기 위해 DAST는 인증 과정 전에 애플리케이션이 설정한 쿠키, 로컬 스토리지, 세션 스토리지 값의 스냅샷을 만듭니다. 인증 후에도 같은 작업을 수행하고, 그 차이로 어떤 값이 인증 과정에서 생성되었는지 판단합니다.

DAST는 충분히 "무작위"한 값으로 설정된 쿠키, 로컬 스토리지, 세션 스토리지 값을 인증 토큰으로 간주합니다. 예를 들어 sessionID=HVxzpS8GzMlPAc2e39uyIVzwACIuGe0H는 인증 토큰으로 보지만 ab_testing_group=A1은 그렇지 않습니다.

CI/CD 변수 DAST_AUTH_COOKIE_NAMES로 인증 쿠키의 이름을 지정하면 DAST가 사용하는 무작위성 검사를 건너뛸 수 있습니다. 이렇게 하면 인증 과정이 더 견고해질 뿐 아니라, 인증 토큰을 검사하는 취약점 검사의 정확도도 높아질 수 있습니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_COOKIE_NAMES: "sessionID,refreshToken"

알려진 문제#

  • 인증 흐름에 CAPTCHA가 포함되어 있으면 DAST는 이를 우회할 수 없습니다. 스캔 대상 애플리케이션의 테스트 환경에서 구성된 사용자에 대해 CAPTCHA를 끕니다.
  • DAST는 SMS나 생체 인식을 사용하는 일회용 비밀번호(OTP)로 인증할 수 없습니다. 스캔 대상 애플리케이션의 테스트 환경에서 구성된 사용자에 대해 이를 끄거나, 해당 사용자의 MFA 유형을 TOTP로 변경합니다.
  • DAST는 로그인 시 인증 토큰을 설정하지 않는 애플리케이션에 인증할 수 없습니다.
  • DAST는 사용자 이름, 비밀번호, 선택적 TOTP보다 많은 텍스트 입력을 요구하는 애플리케이션에 인증할 수 없습니다.

문제 해결#

로그는 인증 과정에서 DAST가 무엇을 하고 무엇을 기대하는지 보여 줍니다. 더 자세한 정보가 필요하면 인증 보고서를 구성합니다.

특정 오류 메시지나 상황에 대한 자세한 내용은 알려진 문제 상황을 참고합니다.

사용자 인증에는 브라우저 기반 분석기를 사용합니다. 고급 문제 해결은 브라우저 기반 문제 해결을 참고합니다.

로그 읽기#

DAST CI/CD job의 콘솔 출력은 AUTH 로그 모듈로 인증 과정에 대한 정보를 표시합니다. 예를 들어 다음 로그는 다단계 로그인 폼의 인증 실패를 보여 줍니다. 로그인 후 홈 페이지가 표시되어야 하는데 로그인 폼이 여전히 남아 있어 인증이 실패했습니다.

2022-11-16T13:43:02.000 INF AUTH  attempting to authenticate
2022-11-16T13:43:02.000 INF AUTH  loading login page LoginURL=https://example.com/login
2022-11-16T13:43:10.000 INF AUTH  multi-step authentication detected
2022-11-16T13:43:15.000 INF AUTH  verifying if user submit was successful true_when="HTTP status code < 400"
2022-11-16T13:43:15.000 INF AUTH  requirement is satisfied, no login HTTP message detected want="HTTP status code < 400"
2022-11-16T13:43:20.000 INF AUTH  verifying if login attempt was successful true_when="HTTP status code < 400 and has authentication token and no login form found (no element found when searching using selector css:[id=email] or css:[id=password] or css:[id=submit])"
2022-11-24T14:43:20.000 INF AUTH  requirement is satisfied, HTTP login request returned status code 200 url=https://example.com/user/login?error=invalid%20credentials want="HTTP status code < 400"
2022-11-16T13:43:21.000 INF AUTH  requirement is unsatisfied, login form was found want="no login form found (no element found when searching using selector css:[id=email] or css:[id=password] or css:[id=submit])"
2022-11-16T13:43:21.000 INF AUTH  login attempt failed error="authentication failed: failed to authenticate user"

인증 보고서 구성#

Warning

인증 보고서에는 로그인에 사용한 자격 증명 같은 민감한 정보가 포함될 수 있습니다.

인증 보고서는 인증 실패 원인을 파악하는 데 도움이 되도록 CI/CD job 아티팩트로 저장할 수 있습니다.

보고서에는 로그인 과정에서 수행된 단계, HTTP 요청과 응답, Document Object Model(DOM), 스크린샷이 담깁니다.

dast-auth-report

인증 디버그 보고서를 내보내는 예시 구성은 다음과 같습니다.

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_REPORT: "true"

알려진 문제 상황#

로그인 폼을 찾을 수 없음#

DAST가 로그인 페이지를 로드할 때 로그인 폼을 찾지 못했습니다. 인증 URL을 로드할 수 없는 경우가 많습니다. 로그에는 다음과 같은 치명적 오류가 기록됩니다.

2022-12-07T12:44:02.838 INF AUTH  loading login page LoginURL=[authentication URL]
2022-12-07T12:44:11.119 FTL MAIN  authentication failed: login form not found

권장 조치:

  • 인증 보고서를 생성해 HTTP 응답을 확인합니다.
  • 대상 애플리케이션 인증이 배포되어 실행 중인지 확인합니다.
  • DAST_AUTH_URL이 올바른지 확인합니다.
  • GitLab Runner가 DAST_AUTH_URL에 접근할 수 있는지 확인합니다.
  • DAST_AUTH_BEFORE_LOGIN_ACTIONS를 사용한다면 값이 유효한지 확인합니다.

스캔이 인증된 페이지를 크롤링하지 않음#

DAST가 인증 과정에서 잘못된 인증 토큰을 수집하면 스캔이 인증된 페이지를 크롤링할 수 없습니다. 쿠키와 스토리지 인증 토큰의 이름은 로그에 기록됩니다. 예시:

2022-11-24T14:42:31.492 INF AUTH  authentication token cookies names=["sessionID"]
2022-11-24T14:42:31.492 INF AUTH  authentication token storage events keys=["token"]

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷을 확인해 로그인이 예상대로 동작했는지 검증합니다.
  • 기록된 인증 토큰이 애플리케이션에서 사용하는 토큰인지 확인합니다.
  • 쿠키에 인증 토큰을 저장한다면 DAST_AUTH_COOKIE_NAMES로 인증 토큰 쿠키의 이름을 설정합니다.

선택자로 요소를 찾을 수 없음#

DAST가 사용자 이름, 비밀번호, 첫 번째 제출 버튼 또는 제출 버튼 요소를 찾지 못했습니다. 로그에는 다음과 같은 치명적 오류가 기록됩니다.

2022-12-07T13:14:11.545 FTL MAIN  authentication failed: unable to find elements with selector: css:#username

권장 조치:

  • 인증 보고서를 생성하고 Login page의 스크린샷으로 페이지가 올바르게 로드되었는지 검증합니다.
  • 브라우저에서 로그인 페이지를 로드해 DAST_AUTH_USERNAME_FIELD, DAST_AUTH_PASSWORD_FIELD, DAST_AUTH_FIRST_SUBMIT_FIELD, DAST_AUTH_SUBMIT_FIELD에 구성한 선택자가 올바른지 확인합니다.

사용자 인증 실패#

로그인 확인 검사가 실패해 DAST 인증이 실패했습니다. 로그에는 다음과 같은 치명적 오류가 기록됩니다.

2022-12-07T06:39:49.483 INF AUTH  verifying if login attempt was successful true_when="HTTP status code < 400 and has authentication token and no login form found (no element found when searching using selector css:[name=username] or css:[name=password] or css:button[type=\"submit\"])"
2022-12-07T06:39:49.484 INF AUTH  requirement is satisfied, HTTP login request returned status code 303 url=http://auth-manual:8090/login want="HTTP status code < 400"
2022-12-07T06:39:49.513 INF AUTH  requirement is unsatisfied, login form was found want="no login form found (no element found when searching using selector css:[name=username] or css:[name=password] or css:button[type=\"submit\"])"
2022-12-07T06:39:49.589 INF AUTH  login attempt failed error="authentication failed: failed to authenticate user"
2022-12-07T06:39:53.626 FTL MAIN  authentication failed: failed to authenticate user

권장 조치:

  • 로그에서 requirement is unsatisfied를 찾습니다. 해당 오류에 맞게 대응합니다.

요건 미충족, 로그인 폼 발견됨#

애플리케이션은 보통 사용자가 로그인하면 대시보드를 표시하고, 사용자 이름이나 비밀번호가 올바르지 않으면 오류 메시지와 함께 로그인 폼을 표시합니다.

이 오류는 사용자를 인증한 다음 표시된 페이지에서 DAST가 로그인 폼을 감지했을 때 발생하며, 로그인 시도가 실패했음을 뜻합니다.

2022-12-07T06:39:49.513 INF AUTH  requirement is unsatisfied, login form was found want="no login form found (no element found when searching using selector css:[name=username] or css:[name=password] or css:button[type=\"submit\"])"

권장 조치:

  • 사용한 사용자 이름과 비밀번호·인증 자격 증명이 올바른지 확인합니다.
  • 인증 보고서를 생성하고 Login submit의 Request가 올바른지 확인합니다.
  • 인증 보고서의 Login submit 요청과 응답이 비어 있을 수 있습니다. HTML 폼을 제출할 때처럼 전체 페이지를 다시 로드하는 요청이 없을 때 발생합니다. 웹소켓이나 AJAX로 로그인 폼을 제출할 때 발생합니다.
  • 사용자 인증 후 표시되는 페이지에 실제로 로그인 폼 선택자와 일치하는 요소가 있다면, 로그인 시도를 확인하는 다른 방법을 쓰도록 DAST_AUTH_SUCCESS_IF_AT_URL이나 DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND를 구성합니다.

요건 미충족, 선택자 결과 없음#

사용자 로그인 후 표시된 페이지에서 DAST가 DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND에 지정한 선택자와 일치하는 요소를 찾을 수 없습니다.

2022-12-07T06:39:33.239 INF AUTH  requirement is unsatisfied, searching DOM using selector returned no results want="has element css:[name=welcome]"

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷으로 예상한 페이지가 표시되는지 검증합니다.
  • DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND 선택자가 올바른지 확인합니다.

요건 미충족, 브라우저가 해당 URL에 없음#

사용자 로그인 후 표시된 페이지의 URL이 DAST_AUTH_SUCCESS_IF_AT_URL에 지정한 URL과 다른 것을 DAST가 감지했습니다.

2022-12-07T11:28:00.241 INF AUTH  requirement is unsatisfied, browser is not at URL browser_url="https://example.com/home" want="is at url https://example.com/user/dashboard"

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷으로 예상한 페이지가 표시되는지 검증합니다.
  • DAST_AUTH_SUCCESS_IF_AT_URL이 올바른지 확인합니다.

요건 미충족, HTTP 로그인 요청 상태 코드#

로그인 폼을 로드하거나 폼을 제출할 때의 HTTP 응답 상태 코드가 400(클라이언트 오류) 또는 500(서버 오류)이었습니다.

2022-12-07T06:39:53.626 INF AUTH  requirement is unsatisfied, HTTP login request returned status code 502 url="https://example.com/user/login" want="HTTP status code < 400"
  • 사용한 사용자 이름과 비밀번호·인증 자격 증명이 올바른지 확인합니다.
  • 인증 보고서를 생성하고 Login submit의 Request가 올바른지 확인합니다.
  • 대상 애플리케이션이 예상대로 동작하는지 확인합니다.

요건 미충족, 인증 토큰 없음#

DAST가 인증 과정에서 생성된 인증 토큰을 감지하지 못했습니다.

2022-12-07T11:25:29.010 INF AUTH  authentication token cookies names=[]
2022-12-07T11:25:29.010 INF AUTH  authentication token storage events keys=[]
2022-12-07T11:25:29.010 INF AUTH  requirement is unsatisfied, no basic authentication, cookie or storage event authentication token detected want="has authentication token"

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷으로 로그인이 예상대로 동작했는지 검증합니다.
  • 브라우저 개발자 도구로 로그인 중에 생성되는 쿠키와 로컬·세션 스토리지 객체를 조사합니다. 충분히 무작위한 값을 가진 인증 토큰이 생성되는지 확인합니다.
  • 쿠키에 인증 토큰을 저장한다면 DAST_AUTH_COOKIE_NAMES로 인증 토큰 쿠키의 이름을 설정합니다.

인증

GitLab v19.5
원문 보기

요약

완전한 커버리지를 확보하려면 DAST 분석기가 테스트 대상 애플리케이션에 인증해야 합니다. DAST에 인증이 필요한 이유는 다음과 같습니다. DAST job은 애플리케이션에 스스로 인증하며, 가장 일반적인 방식은 브라우저에서 로그인 폼을 채워 제출하는 것입니다.

완전한 커버리지를 확보하려면 DAST 분석기가 테스트 대상 애플리케이션에 인증해야 합니다. 이를 위해 DAST CI/CD job에서 인증 자격 증명과 인증 방법을 구성해야 합니다.

DAST에 인증이 필요한 이유는 다음과 같습니다.

  • 실제 공격을 시뮬레이션하고 공격자가 악용할 수 있는 취약점을 식별하기 위해서입니다.
  • 인증 후에만 보이는 사용자별 기능과 사용자 지정 동작을 테스트하기 위해서입니다.

DAST job은 애플리케이션에 스스로 인증하며, 가장 일반적인 방식은 브라우저에서 로그인 폼을 채워 제출하는 것입니다. 폼을 제출한 다음 DAST job은 인증이 성공했는지 확인합니다. 인증에 성공하면 DAST job은 작업을 계속하고, 대상 애플리케이션을 크롤링할 때 재사용할 수 있도록 자격 증명도 저장합니다. 성공하지 못하면 DAST job이 중지됩니다.

DAST가 지원하는 인증 방법은 다음과 같습니다.

  • 단일 단계 로그인 폼
  • 다단계 로그인 폼
  • 구성된 대상 URL 외부의 URL에 인증

인증 자격 증명을 선택할 때 유의할 사항은 다음과 같습니다.

  • 운영 시스템이나 운영 서버에 유효한 자격 증명, 또는 운영 데이터에 접근하는 데 쓰는 자격 증명은 사용하지 않습니다.
  • 운영 서버를 대상으로 인증된 스캔을 실행하지 않습니다. 인증된 스캔은 인증된 사용자가 할 수 있는 모든 기능을 수행할 수 있으며, 데이터 수정·삭제, 폼 제출, 링크 따라가기도 포함됩니다. 인증된 스캔은 운영 환경이 아닌 시스템이나 서버를 대상으로만 실행합니다.
  • DAST가 애플리케이션 전체를 테스트할 수 있는 자격 증명을 제공합니다.
  • 자격 증명에 만료일이 있으면 나중에 참고할 수 있도록 기록해 둡니다. 예를 들어 1Password 같은 비밀번호 관리자를 사용합니다.

다음 다이어그램은 인증의 여러 단계에서 인증 변수가 어떻게 사용되는지 보여 줍니다.

Mermaid 다이어그램 (34줄)
소스 코드 보기
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
    accTitle: Authentication variables
    accDescr: A sequence diagram showing authentication variables at different stages of authentication.
    participant DAST
    participant Browser
    participant Target
Note over DAST,Target: Initialization
DAST-&gt;&gt;Browser: Initialize browser with proxy
DAST-&gt;&gt;Browser: Navigate to DAST_AUTH_URL
Browser-&gt;&gt;Target: Load initial page
Target--&gt;&gt;Browser: Return page content (may not contain login form)

Note over DAST,Target: Process before-login actions
DAST-&gt;&gt;Browser: Click elements specified in DAST_AUTH_BEFORE_LOGIN_ACTIONS
Browser-&gt;&gt;Target: Send click actions
Target--&gt;&gt;Browser: Render login form (modal/page)

Note over DAST,Target: Authentication
DAST-&gt;&gt;Browser: Fill DAST_AUTH_USERNAME &amp; DAST_AUTH_PASSWORD
DAST-&gt;&gt;Browser: Click "submit"
Browser-&gt;&gt;Target: Submit form
Target--&gt;&gt;Browser: Process authentication
Target--&gt;&gt;Browser: Set auth tokens

Note over DAST,Target: Process after-login actions (if specified)
DAST-&gt;&gt;Browser: Execute DAST_AUTH_AFTER_LOGIN_ACTIONS
Browser-&gt;&gt;Target: Actions after login but before login verification

Note over DAST,Target: Verification
DAST-&gt;&gt;Browser: Check URL matches DAST_AUTH_SUCCESS_IF_AT_URL (if configured)
DAST-&gt;&gt;Browser: Check element exists DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND (if configured)
DAST-&gt;&gt;Browser: Check login form absent DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM (default is true)</code></pre></details></div>

시작하기#

Note

분석기의 인증이 계속 작동하는지 주기적으로 확인해야 합니다. 애플리케이션이 변경되면서 시간이 지남에 따라 깨지는 경우가 많습니다.

DAST 인증 스캔을 실행하는 절차는 다음과 같습니다.

사전 요구 사항#

  • 스캔 중에 인증할 사용자의 사용자 이름과 비밀번호가 있습니다.
  • DAST가 애플리케이션에 인증할 수 있는지 확인하기 위해 알려진 문제를 확인했습니다.
  • 폼 인증을 사용한다면 그 사전 요구 사항을 충족했습니다.
  • 폼 인증 흐름에 시간 기반 일회용 비밀번호가 포함된다면 추가 사전 요구 사항을 충족했습니다.
  • 인증이 성공했는지 확인하는 방법을 검토했습니다.

폼 인증#

  • 애플리케이션 로그인 폼의 URL을 알고 있습니다. 또는 인증 URL에서 로그인 폼으로 이동하는 방법을 알고 있습니다(클릭으로 로그인 폼으로 이동 참고).
  • DAST가 각 값을 입력하는 데 사용하는 사용자 이름 HTML 필드와 비밀번호 HTML 필드의 선택자를 알고 있습니다.
  • 선택하면 로그인 폼을 제출하는 요소의 선택자를 알고 있습니다.

TOTP 인증#

히스토리
  • 스캐너 버전 6.9에서 도입되었습니다.
  • 테스트 사용자의 TOTP 등록에 사용하는 시크릿 키를 Base32로 인코딩한 값이 있습니다.
  • 인증 공급자가 다음 TOTP 구성(Google Authenticator와 동일)을 지원하는지 확인했습니다.
    • HMAC 알고리즘: SHA-1
    • 시간 간격: 30초
    • 토큰 길이: 6
  • DAST가 생성된 TOTP 토큰을 입력하는 데 사용하는 TOTP 필드의 선택자를 알고 있습니다.
  • TOTP 토큰을 비밀번호와 별도로 제출하는 경우, TOTP 토큰을 제출하는 요소의 선택자를 알고 있습니다.

사용 가능한 CI/CD 변수#

DAST 인증 CI/CD 변수 목록은 인증 변수를 참고합니다.

DAST CI/CD 변수 표는 Rake 태스크 bundle exec rake gitlab:dast_variables:compile_docs로 생성됩니다. 이 태스크는 lib/gitlab/security/dast_variables.rb에 정의된 변수 메타데이터를 사용합니다.

대상 웹사이트 업데이트#

CI/CD 변수 DAST_TARGET_URL로 정의하는 대상 웹사이트는 DAST가 애플리케이션 크롤링을 시작할 때 사용하는 URL입니다.

인증 스캔에서 최선의 크롤링 결과를 얻으려면 대상 웹사이트가 사용자 인증 후에만 접근할 수 있는 URL이어야 합니다. 보통은 사용자가 로그인한 다음 도착하는 페이지의 URL입니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com/dashboard/welcome"
    DAST_AUTH_URL: "https://example.com/login"

HTTP 인증 구성#

Basic Authentication 같은 HTTP 인증 스키마를 사용하려면 DAST_AUTH_TYPE 값을 basic-digest로 설정할 수 있습니다. Negotiate나 NTLM 같은 다른 스키마도 동작할 수 있지만, 현재 자동화된 테스트 커버리지가 없어 공식적으로 지원하지는 않습니다.

구성하려면 DAST job에 CI/CD 변수 DAST_AUTH_TYPE, DAST_AUTH_URL, DAST_AUTH_USERNAME, DAST_AUTH_PASSWORD를 정의해야 합니다. 고유한 로그인 URL이 없으면 DAST_AUTH_URL을 DAST_TARGET_URL과 같은 URL로 설정합니다.

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_TYPE: "basic-digest"
    DAST_AUTH_URL: "https://example.com"

DAST_AUTH_USERNAME과 DAST_AUTH_PASSWORD는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

단일 단계 로그인 폼 구성#

단일 단계 로그인 폼은 로그인 폼 요소가 모두 한 페이지에 있습니다. 구성하려면 DAST job에 CI/CD 변수 DAST_AUTH_URL, DAST_AUTH_USERNAME, DAST_AUTH_USERNAME_FIELD, DAST_AUTH_PASSWORD, DAST_AUTH_PASSWORD_FIELD, DAST_AUTH_SUBMIT_FIELD를 정의해야 합니다.

job 정의 YAML에 필드의 URL과 선택자를 설정합니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_USERNAME_FIELD: "css:[name=username]"
    DAST_AUTH_PASSWORD_FIELD: "css:[name=password]"
    DAST_AUTH_SUBMIT_FIELD: "css:button[type=submit]"

DAST_AUTH_USERNAME과 DAST_AUTH_PASSWORD는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

다단계 로그인 폼 구성#

다단계 로그인 폼은 페이지가 두 개입니다. 첫 페이지의 폼에는 사용자 이름과 다음 단계로 넘어가는 제출 버튼이 있습니다. 사용자 이름이 유효하면 다음 페이지의 두 번째 폼에 비밀번호와 폼 제출 버튼이 있습니다.

구성하려면 DAST job에 다음 CI/CD 변수를 정의해야 합니다.

  • DAST_AUTH_URL
  • DAST_AUTH_USERNAME
  • DAST_AUTH_USERNAME_FIELD
  • DAST_AUTH_FIRST_SUBMIT_FIELD
  • DAST_AUTH_PASSWORD
  • DAST_AUTH_PASSWORD_FIELD
  • DAST_AUTH_SUBMIT_FIELD.

job 정의 YAML에 필드의 URL과 선택자를 설정합니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_USERNAME_FIELD: "css:[name=username]"
    DAST_AUTH_FIRST_SUBMIT_FIELD: "css:button[name=next]"
    DAST_AUTH_PASSWORD_FIELD: "css:[name=password]"
    DAST_AUTH_SUBMIT_FIELD: "css:button[type=submit]"

DAST_AUTH_USERNAME과 DAST_AUTH_PASSWORD는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

시간 기반 일회용 비밀번호(TOTP) 구성#

TOTP를 구성하려면 DAST job에 다음 CI/CD 변수를 정의해야 합니다.

  • DAST_AUTH_OTP_FIELD
  • DAST_AUTH_OTP_KEY

비밀번호를 제출한 다음 TOTP 토큰을 별도 폼으로 제출한다면 다음 변수도 정의해야 합니다.

  • DAST_AUTH_OTP_SUBMIT_FIELD

_FIELD 선택자 변수는 job 정의 YAML에 정의할 수 있습니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_USERNAME_FIELD: "css:[name=username]"
    DAST_AUTH_PASSWORD_FIELD: "css:[name=password]"
    DAST_AUTH_SUBMIT_FIELD: "css:button[type=submit]"
    DAST_AUTH_OTP_FIELD: "name:otp"
    DAST_AUTH_OTP_SUBMIT_FIELD: "css:input[type=submit]"

DAST_AUTH_OTP_KEY는 보안 위험이 될 수 있으므로 YAML job 정의 파일에 정의하지 않습니다. 대신 GitLab UI에서 마스킹된 CI/CD 변수로 만듭니다. 자세한 내용은 사용자 지정 CI/CD 변수를 참고합니다.

Single Sign-On(SSO) 구성#

사용자가 애플리케이션에 로그인할 수 있으면 대부분의 경우 DAST도 로그인할 수 있으며, 애플리케이션이 Single Sign-On(SSO)을 사용해도 마찬가지입니다. SSO 솔루션을 사용하는 애플리케이션은 단일 단계 또는 다단계 로그인 폼 구성 가이드에 따라 DAST 인증을 구성합니다.

DAST는 사용자가 외부 ID 공급자(Identity Provider)의 사이트로 리디렉션되어 로그인하는 인증 프로세스를 지원합니다. SSO 인증 프로세스가 지원되는지 확인하려면 DAST 인증의 알려진 문제를 확인합니다.

Windows 통합 인증(Kerberos) 구성#

Windows 통합 인증(Kerberos)은 Windows 도메인 안에서 호스팅되는 사내 업무(line of business, LOB) 애플리케이션에 널리 쓰이는 인증 방식입니다. 사용자 컴퓨터의 로그인 정보를 사용해 별도 입력 요청 없이 인증합니다.

이 인증 방식을 구성하는 절차는 다음과 같습니다.

  1. IT·운영팀의 도움을 받아 필요한 정보를 수집합니다.
  2. .gitlab-ci.yml 파일에서 dast job 정의를 만들거나 업데이트합니다.
  3. 수집한 정보로 예시 krb5.conf 파일을 채웁니다.
  4. 필요한 job 변수를 설정합니다.
  5. 프로젝트 Settings 페이지에서 필요한 시크릿 변수를 설정합니다.
  6. 인증이 동작하는지 테스트하고 확인합니다.

IT·운영 부서의 도움을 받아 다음 정보를 수집합니다.

  • Windows 도메인 또는 Kerberos Realm 이름(EXAMPLE.COM처럼 이름에 마침표가 있어야 합니다)
  • Windows/Kerberos 도메인 컨트롤러의 호스트 이름
  • Kerberos의 경우 인증 서버 이름. Windows 도메인에서는 도메인 컨트롤러입니다.

krb5.conf 파일을 만듭니다.

[libdefaults]
  # Realm is another name for domain name
  default_realm = EXAMPLE.COM
  # These settings are not needed for Windows Domains
  # they support other Kerberos implementations
  kdc_timesync = 1
  ccache_type = 4
  forwardable = true
  proxiable = true
  rdns = false
  fcc-mit-ticketflags = true
[realms]
  EXAMPLE.COM = {
    # Domain controller or KDC
    kdc = kdc.example.com
    # Domain controller or admin server
    admin_server = kdc.example.com
  }
[domain_realm]
  # Mapping DNS domains to realms/Windows domain
  # DNS domains provided by DAST_AUTH_NEGOTIATE_DELEGATION
  # should also be represented here (but without the wildcard)
  .example.com = EXAMPLE.COM
  example.com = EXAMPLE.COM

이 구성은 DAST_AUTH_NEGOTIATE_DELEGATION 변수를 사용합니다. 이 변수는 통합 인증을 허용하는 데 필요한 다음 Chromium 정책을 설정합니다.

이 변수에 설정하는 값은 Windows 도메인이나 Kerberos realm에 연결된 DNS 도메인입니다. 다음과 같이 제공합니다.

  • 소문자와 대문자 양쪽으로 제공합니다.
  • 와일드카드 패턴과 도메인 이름만 있는 형태를 함께 제공합니다.

이 예시에서 Windows 도메인은 EXAMPLE.COM이고 DNS 도메인은 example.com입니다. 따라서 DAST_AUTH_NEGOTIATE_DELEGATION 값은 *.example.com,example.com,*.EXAMPLE.COM,EXAMPLE.COM이 됩니다.

이를 모두 job 정의로 모읍니다.

# This job will extend the dast job defined in
# the DAST template which must also be included.
dast:
  image:
    name: "$SECURE_ANALYZERS_PREFIX/dast:$DAST_VERSION$DAST_IMAGE_SUFFIX"
    docker:
      user: root
  variables:
    DAST_TARGET_URL: https://target.example.com
    DAST_AUTH_URL: https://target.example.com
    DAST_AUTH_TYPE: basic-digest
    DAST_AUTH_NEGOTIATE_DELEGATION: '*.example.com,example.com,*.EXAMPLE.COM,EXAMPLE.COM'
    # Not shown -- DAST_AUTH_USERNAME, DAST_AUTH_PASSWORD set via Settings -> CI -> Variables
  before_script:
    - KRB5_CONF='
[libdefaults]
  default_realm = EXAMPLE.COM
  kdc_timesync = 1
  ccache_type = 4
  forwardable = true
  proxiable = true
  rdns = false
  fcc-mit-ticketflags = true
[realms]
  EXAMPLE.COM = {
    kdc = ad1.example.com
    admin_server = ad1.example.com
  }
[domain_realm]
  .example.com = EXAMPLE.COM
  example.com = EXAMPLE.COM
'
    - cat "$KRB5_CONF" > /etc/krb5.conf
    - echo '$DAST_AUTH_PASSWORD' | kinit $DAST_AUTH_USERNAME
    - klist

예상 출력:

job 콘솔 출력에는 before 스크립트의 출력이 담깁니다. 인증에 성공하면 다음과 비슷하게 표시됩니다. 성공하지 못하면 스캔을 실행하지 않고 job이 실패해야 합니다.

Password for mike@EXAMPLE.COM:
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: mike@EXAMPLE.COM

Valid starting       Expires              Service principal
11/11/2024 21:50:50  11/12/2024 07:50:50  krbtgt/EXAMPLE.COM@EXAMPLE.COM
        renew until 11/12/2024 21:50:50

DAST 스캐너도 다음과 같이 출력하며, 이는 성공을 뜻합니다.

2024-11-08T17:03:09.226 INF AUTH  attempting to authenticate find_auth_fields="basic-digest"
2024-11-08T17:03:09.226 INF AUTH  loading login page LoginURL="https://target.example.com"
2024-11-08T17:03:10.619 INF AUTH  verifying if login attempt was successful true_when="HTTP status code < 400 and has authentication token and no login form found (auto-detected)"
2024-11-08T17:03:10.619 INF AUTH  requirement is satisfied, HTTP login request returned status code 200 want="HTTP status code < 400" url="https://target.example.com/"
2024-11-08T17:03:10.623 INF AUTH  requirement is satisfied, did not detect a login form want="no login form found (auto-detected)"
2024-11-08T17:03:10.623 INF AUTH  authentication token cookies names=""
2024-11-08T17:03:10.623 INF AUTH  authentication token storage events keys=""
2024-11-08T17:03:10.623 INF AUTH  requirement is satisfied, basic authentication detected want="has authentication token"
2024-11-08T17:03:11.230 INF AUTH  login attempt succeeded

클릭으로 로그인 폼으로 이동#

DAST_AUTH_BEFORE_LOGIN_ACTIONS를 정의해 DAST_AUTH_URL에서 클릭할 요소의 경로를 지정하면 DAST가 로그인 폼에 접근할 수 있습니다. 이 방법은 로그인 폼을 팝업(모달) 창으로 표시하거나 로그인 폼에 고유한 URL이 없는 애플리케이션에 적합합니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_BEFORE_LOGIN_ACTIONS: "css:.navigation-menu,css:.login-menu-item"

로그인 폼 제출 후 추가 작업 수행#

DAST_AUTH_AFTER_LOGIN_ACTIONS를 정의하면 로그인 폼을 제출한 다음 인증 정보를 기록하는 확인 단계 전에 수행할 작업 순서를 지정할 수 있습니다. "keep me signed in" 대화 상자를 넘어가는 데 사용할 수 있습니다.

작업 형식
요소 클릭 click(on=<selector>)
드롭다운에서 옵션 선택 select(option=<selector>)

작업은 쉼표로 구분합니다. 선택자에 대한 자세한 내용은 요소의 선택자 찾기를 참고합니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_URL: "https://example.com/login"
    DAST_AUTH_AFTER_LOGIN_ACTIONS: "select(option=id:accept-yes),click(on=id:continue-button)"

로그아웃 URL 제외#

인증 스캔 중에 DAST가 로그아웃 URL을 크롤링하면 사용자가 로그아웃되고, 남은 스캔은 인증되지 않은 상태로 진행됩니다. 따라서 CI/CD 변수 DAST_SCOPE_EXCLUDE_URLS로 로그아웃 URL을 제외하는 것이 좋습니다. DAST는 제외된 URL에 접근하지 않으므로 사용자가 로그인 상태를 유지합니다.

제공하는 URL은 절대 URL이거나, DAST_TARGET_URL의 기본 경로를 기준으로 한 URL 경로의 정규 표현식일 수 있습니다. 예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com/welcome/home"
    DAST_SCOPE_EXCLUDE_URLS: "https://example.com/logout,/user/.*/logout"

요소의 선택자 찾기#

선택자는 브라우저의 페이지에 표시되는 요소의 위치를 지정하기 위해 CI/CD 변수에서 사용합니다. 선택자의 형식은 type:search string입니다. DAST는 유형에 따라 검색 문자열로 선택자를 찾습니다.

선택자 유형 예시 설명
css css:.password-field 지정한 CSS 선택자를 가진 HTML 요소를 검색합니다. 성능을 위해 선택자는 가능한 한 구체적이어야 합니다.
id id:element 지정한 요소 ID를 가진 HTML 요소를 검색합니다.
name name:element 지정한 요소 이름을 가진 HTML 요소를 검색합니다.
xpath xpath://input[@id="my-button"]/a 지정한 XPath를 가진 HTML 요소를 검색합니다. XPath 검색은 다른 검색보다 성능이 낮을 것으로 예상됩니다.

Google Chrome으로 선택자 찾기#

Chrome DevTools의 요소 선택 도구는 선택자를 찾는 효과적인 방법입니다.

  1. Chrome을 열고 선택자를 찾으려는 페이지로 이동합니다. 예를 들어 사이트의 로그인 페이지입니다.
  2. macOS에서는 Command+Shift+C, Windows나 Linux에서는 Control+Shift+C 키보드 단축키로 Chrome DevTools에서 Elements 탭을 엽니다.
  3. Select an element in the page to select it 도구를 선택합니다. search-elements
  4. 선택자를 알고 싶은 페이지의 필드를 선택합니다.
  5. 도구가 활성화된 다음 세부 정보를 보려는 필드를 강조 표시합니다. highlight
  6. 강조 표시하면 선택자로 쓰기 좋은 속성을 포함해 요소의 세부 정보를 확인할 수 있습니다.

이 예시에서는 id="user_login"이 좋은 후보로 보입니다. DAST_AUTH_USERNAME_FIELD: "id:user_login"으로 설정하면 이 값을 DAST 사용자 이름 필드의 선택자로 사용할 수 있습니다.

올바른 선택자 선택#

선택자를 신중하게 고르면 애플리케이션이 변경되어도 견디는 스캔이 됩니다.

선택자는 다음 순서로 선호합니다.

  • id 필드. 이 필드는 보통 페이지에서 고유하고 거의 변경되지 않습니다.
  • name 필드. 이 필드는 보통 페이지에서 고유하고 거의 변경되지 않습니다.
  • 해당 필드에 특화된 class 값. 예를 들어 사용자 이름 필드의 username 클래스에 대한 선택자 "css:.username"입니다.
  • 필드에 특화된 데이터 속성의 존재. 예를 들어 사용자 이름 필드의 data-username 필드에 값이 있을 때의 선택자 "css:[data-username]"입니다.
  • 여러 class 계층 값. 예를 들어 username 클래스를 가진 요소가 여러 개인데 그중 하나만 login-form 클래스를 가진 요소 안에 중첩되어 있을 때의 선택자 "css:.login-form .username"입니다.

특정 필드를 찾는 선택자에서는 다음을 검색 대상으로 삼지 않습니다.

  • 동적으로 생성되는 id, name, attribute, class, value.
  • column-10, dark-grey 같은 일반적인 클래스 이름.
  • 다른 선택자 검색보다 성능이 낮은 XPath 검색.
  • css:*, xpath://*로 시작하는 것처럼 범위가 지정되지 않은 검색.

인증 성공 확인#

DAST가 로그인 폼을 제출한 다음 인증이 성공했는지 판단하는 확인 프로세스가 진행됩니다. 인증에 성공하지 못하면 스캔이 오류와 함께 중단됩니다.

로그인 폼을 제출한 다음, 아래 경우에는 인증이 성공하지 못한 것으로 판단합니다.

  • 로그인 제출 HTTP 응답의 상태 코드가 400 또는 500 계열입니다.
  • 확인 검사 중 하나라도 실패합니다.
  • 인증 과정에서 충분히 무작위한 값을 가진 인증 토큰이 설정되지 않습니다.

확인 검사#

확인 검사는 인증이 끝난 다음 브라우저 상태를 검사해 인증이 성공했는지 한 번 더 판단합니다.

확인 검사를 구성하지 않으면 DAST는 로그인 폼이 없는지 테스트합니다.

URL 기반 확인#

로그인 폼을 성공적으로 제출한 다음 브라우저 탭에 표시되는 URL을 DAST_AUTH_SUCCESS_IF_AT_URL로 정의합니다.

DAST는 확인 URL을 인증 후 브라우저의 URL과 비교합니다. 둘이 같지 않으면 인증이 성공하지 못한 것입니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_SUCCESS_IF_AT_URL: "https://example.com/user/welcome"

요소 존재 기반 확인#

로그인 폼을 성공적으로 제출한 다음 표시되는 페이지에서 하나 이상의 요소를 찾는 선택자를 DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND로 정의합니다. 요소를 찾지 못하면 인증이 성공하지 못한 것입니다. 로그인이 실패할 때 표시되는 페이지에서 이 선택자를 검색하면 요소가 없어야 합니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND: "css:.welcome-user"

로그인 폼 부재 기반 확인#

DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM을 "true"로 정의하면, 로그인 폼을 성공적으로 제출한 다음 표시되는 페이지에서 DAST가 로그인 폼을 검색합니다. 로그인 후에도 로그인 폼이 남아 있으면 인증이 성공하지 못한 것입니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM: "true"

인증 토큰#

DAST는 인증 과정에서 설정된 인증 토큰을 기록합니다. 인증 토큰은 DAST가 새 브라우저를 열 때 그 브라우저에 로드되므로, 사용자는 스캔 내내 로그인 상태를 유지할 수 있습니다.

토큰을 기록하기 위해 DAST는 인증 과정 전에 애플리케이션이 설정한 쿠키, 로컬 스토리지, 세션 스토리지 값의 스냅샷을 만듭니다. 인증 후에도 같은 작업을 수행하고, 그 차이로 어떤 값이 인증 과정에서 생성되었는지 판단합니다.

DAST는 충분히 "무작위"한 값으로 설정된 쿠키, 로컬 스토리지, 세션 스토리지 값을 인증 토큰으로 간주합니다. 예를 들어 sessionID=HVxzpS8GzMlPAc2e39uyIVzwACIuGe0H는 인증 토큰으로 보지만 ab_testing_group=A1은 그렇지 않습니다.

CI/CD 변수 DAST_AUTH_COOKIE_NAMES로 인증 쿠키의 이름을 지정하면 DAST가 사용하는 무작위성 검사를 건너뛸 수 있습니다. 이렇게 하면 인증 과정이 더 견고해질 뿐 아니라, 인증 토큰을 검사하는 취약점 검사의 정확도도 높아질 수 있습니다.

예시:

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

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_COOKIE_NAMES: "sessionID,refreshToken"

알려진 문제#

  • 인증 흐름에 CAPTCHA가 포함되어 있으면 DAST는 이를 우회할 수 없습니다. 스캔 대상 애플리케이션의 테스트 환경에서 구성된 사용자에 대해 CAPTCHA를 끕니다.
  • DAST는 SMS나 생체 인식을 사용하는 일회용 비밀번호(OTP)로 인증할 수 없습니다. 스캔 대상 애플리케이션의 테스트 환경에서 구성된 사용자에 대해 이를 끄거나, 해당 사용자의 MFA 유형을 TOTP로 변경합니다.
  • DAST는 로그인 시 인증 토큰을 설정하지 않는 애플리케이션에 인증할 수 없습니다.
  • DAST는 사용자 이름, 비밀번호, 선택적 TOTP보다 많은 텍스트 입력을 요구하는 애플리케이션에 인증할 수 없습니다.

문제 해결#

로그는 인증 과정에서 DAST가 무엇을 하고 무엇을 기대하는지 보여 줍니다. 더 자세한 정보가 필요하면 인증 보고서를 구성합니다.

특정 오류 메시지나 상황에 대한 자세한 내용은 알려진 문제 상황을 참고합니다.

사용자 인증에는 브라우저 기반 분석기를 사용합니다. 고급 문제 해결은 브라우저 기반 문제 해결을 참고합니다.

로그 읽기#

DAST CI/CD job의 콘솔 출력은 AUTH 로그 모듈로 인증 과정에 대한 정보를 표시합니다. 예를 들어 다음 로그는 다단계 로그인 폼의 인증 실패를 보여 줍니다. 로그인 후 홈 페이지가 표시되어야 하는데 로그인 폼이 여전히 남아 있어 인증이 실패했습니다.

2022-11-16T13:43:02.000 INF AUTH  attempting to authenticate
2022-11-16T13:43:02.000 INF AUTH  loading login page LoginURL=https://example.com/login
2022-11-16T13:43:10.000 INF AUTH  multi-step authentication detected
2022-11-16T13:43:15.000 INF AUTH  verifying if user submit was successful true_when="HTTP status code < 400"
2022-11-16T13:43:15.000 INF AUTH  requirement is satisfied, no login HTTP message detected want="HTTP status code < 400"
2022-11-16T13:43:20.000 INF AUTH  verifying if login attempt was successful true_when="HTTP status code < 400 and has authentication token and no login form found (no element found when searching using selector css:[id=email] or css:[id=password] or css:[id=submit])"
2022-11-24T14:43:20.000 INF AUTH  requirement is satisfied, HTTP login request returned status code 200 url=https://example.com/user/login?error=invalid%20credentials want="HTTP status code < 400"
2022-11-16T13:43:21.000 INF AUTH  requirement is unsatisfied, login form was found want="no login form found (no element found when searching using selector css:[id=email] or css:[id=password] or css:[id=submit])"
2022-11-16T13:43:21.000 INF AUTH  login attempt failed error="authentication failed: failed to authenticate user"

인증 보고서 구성#

Warning

인증 보고서에는 로그인에 사용한 자격 증명 같은 민감한 정보가 포함될 수 있습니다.

인증 보고서는 인증 실패 원인을 파악하는 데 도움이 되도록 CI/CD job 아티팩트로 저장할 수 있습니다.

보고서에는 로그인 과정에서 수행된 단계, HTTP 요청과 응답, Document Object Model(DOM), 스크린샷이 담깁니다.

dast-auth-report

인증 디버그 보고서를 내보내는 예시 구성은 다음과 같습니다.

dast:
  variables:
    DAST_TARGET_URL: "https://example.com"
    DAST_AUTH_REPORT: "true"

알려진 문제 상황#

로그인 폼을 찾을 수 없음#

DAST가 로그인 페이지를 로드할 때 로그인 폼을 찾지 못했습니다. 인증 URL을 로드할 수 없는 경우가 많습니다. 로그에는 다음과 같은 치명적 오류가 기록됩니다.

2022-12-07T12:44:02.838 INF AUTH  loading login page LoginURL=[authentication URL]
2022-12-07T12:44:11.119 FTL MAIN  authentication failed: login form not found

권장 조치:

  • 인증 보고서를 생성해 HTTP 응답을 확인합니다.
  • 대상 애플리케이션 인증이 배포되어 실행 중인지 확인합니다.
  • DAST_AUTH_URL이 올바른지 확인합니다.
  • GitLab Runner가 DAST_AUTH_URL에 접근할 수 있는지 확인합니다.
  • DAST_AUTH_BEFORE_LOGIN_ACTIONS를 사용한다면 값이 유효한지 확인합니다.

스캔이 인증된 페이지를 크롤링하지 않음#

DAST가 인증 과정에서 잘못된 인증 토큰을 수집하면 스캔이 인증된 페이지를 크롤링할 수 없습니다. 쿠키와 스토리지 인증 토큰의 이름은 로그에 기록됩니다. 예시:

2022-11-24T14:42:31.492 INF AUTH  authentication token cookies names=["sessionID"]
2022-11-24T14:42:31.492 INF AUTH  authentication token storage events keys=["token"]

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷을 확인해 로그인이 예상대로 동작했는지 검증합니다.
  • 기록된 인증 토큰이 애플리케이션에서 사용하는 토큰인지 확인합니다.
  • 쿠키에 인증 토큰을 저장한다면 DAST_AUTH_COOKIE_NAMES로 인증 토큰 쿠키의 이름을 설정합니다.

선택자로 요소를 찾을 수 없음#

DAST가 사용자 이름, 비밀번호, 첫 번째 제출 버튼 또는 제출 버튼 요소를 찾지 못했습니다. 로그에는 다음과 같은 치명적 오류가 기록됩니다.

2022-12-07T13:14:11.545 FTL MAIN  authentication failed: unable to find elements with selector: css:#username

권장 조치:

  • 인증 보고서를 생성하고 Login page의 스크린샷으로 페이지가 올바르게 로드되었는지 검증합니다.
  • 브라우저에서 로그인 페이지를 로드해 DAST_AUTH_USERNAME_FIELD, DAST_AUTH_PASSWORD_FIELD, DAST_AUTH_FIRST_SUBMIT_FIELD, DAST_AUTH_SUBMIT_FIELD에 구성한 선택자가 올바른지 확인합니다.

사용자 인증 실패#

로그인 확인 검사가 실패해 DAST 인증이 실패했습니다. 로그에는 다음과 같은 치명적 오류가 기록됩니다.

2022-12-07T06:39:49.483 INF AUTH  verifying if login attempt was successful true_when="HTTP status code < 400 and has authentication token and no login form found (no element found when searching using selector css:[name=username] or css:[name=password] or css:button[type=\"submit\"])"
2022-12-07T06:39:49.484 INF AUTH  requirement is satisfied, HTTP login request returned status code 303 url=http://auth-manual:8090/login want="HTTP status code < 400"
2022-12-07T06:39:49.513 INF AUTH  requirement is unsatisfied, login form was found want="no login form found (no element found when searching using selector css:[name=username] or css:[name=password] or css:button[type=\"submit\"])"
2022-12-07T06:39:49.589 INF AUTH  login attempt failed error="authentication failed: failed to authenticate user"
2022-12-07T06:39:53.626 FTL MAIN  authentication failed: failed to authenticate user

권장 조치:

  • 로그에서 requirement is unsatisfied를 찾습니다. 해당 오류에 맞게 대응합니다.

요건 미충족, 로그인 폼 발견됨#

애플리케이션은 보통 사용자가 로그인하면 대시보드를 표시하고, 사용자 이름이나 비밀번호가 올바르지 않으면 오류 메시지와 함께 로그인 폼을 표시합니다.

이 오류는 사용자를 인증한 다음 표시된 페이지에서 DAST가 로그인 폼을 감지했을 때 발생하며, 로그인 시도가 실패했음을 뜻합니다.

2022-12-07T06:39:49.513 INF AUTH  requirement is unsatisfied, login form was found want="no login form found (no element found when searching using selector css:[name=username] or css:[name=password] or css:button[type=\"submit\"])"

권장 조치:

  • 사용한 사용자 이름과 비밀번호·인증 자격 증명이 올바른지 확인합니다.
  • 인증 보고서를 생성하고 Login submit의 Request가 올바른지 확인합니다.
  • 인증 보고서의 Login submit 요청과 응답이 비어 있을 수 있습니다. HTML 폼을 제출할 때처럼 전체 페이지를 다시 로드하는 요청이 없을 때 발생합니다. 웹소켓이나 AJAX로 로그인 폼을 제출할 때 발생합니다.
  • 사용자 인증 후 표시되는 페이지에 실제로 로그인 폼 선택자와 일치하는 요소가 있다면, 로그인 시도를 확인하는 다른 방법을 쓰도록 DAST_AUTH_SUCCESS_IF_AT_URL이나 DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND를 구성합니다.

요건 미충족, 선택자 결과 없음#

사용자 로그인 후 표시된 페이지에서 DAST가 DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND에 지정한 선택자와 일치하는 요소를 찾을 수 없습니다.

2022-12-07T06:39:33.239 INF AUTH  requirement is unsatisfied, searching DOM using selector returned no results want="has element css:[name=welcome]"

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷으로 예상한 페이지가 표시되는지 검증합니다.
  • DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND 선택자가 올바른지 확인합니다.

요건 미충족, 브라우저가 해당 URL에 없음#

사용자 로그인 후 표시된 페이지의 URL이 DAST_AUTH_SUCCESS_IF_AT_URL에 지정한 URL과 다른 것을 DAST가 감지했습니다.

2022-12-07T11:28:00.241 INF AUTH  requirement is unsatisfied, browser is not at URL browser_url="https://example.com/home" want="is at url https://example.com/user/dashboard"

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷으로 예상한 페이지가 표시되는지 검증합니다.
  • DAST_AUTH_SUCCESS_IF_AT_URL이 올바른지 확인합니다.

요건 미충족, HTTP 로그인 요청 상태 코드#

로그인 폼을 로드하거나 폼을 제출할 때의 HTTP 응답 상태 코드가 400(클라이언트 오류) 또는 500(서버 오류)이었습니다.

2022-12-07T06:39:53.626 INF AUTH  requirement is unsatisfied, HTTP login request returned status code 502 url="https://example.com/user/login" want="HTTP status code < 400"
  • 사용한 사용자 이름과 비밀번호·인증 자격 증명이 올바른지 확인합니다.
  • 인증 보고서를 생성하고 Login submit의 Request가 올바른지 확인합니다.
  • 대상 애플리케이션이 예상대로 동작하는지 확인합니다.

요건 미충족, 인증 토큰 없음#

DAST가 인증 과정에서 생성된 인증 토큰을 감지하지 못했습니다.

2022-12-07T11:25:29.010 INF AUTH  authentication token cookies names=[]
2022-12-07T11:25:29.010 INF AUTH  authentication token storage events keys=[]
2022-12-07T11:25:29.010 INF AUTH  requirement is unsatisfied, no basic authentication, cookie or storage event authentication token detected want="has authentication token"

권장 조치:

  • 인증 보고서를 생성하고 Login submit의 스크린샷으로 로그인이 예상대로 동작했는지 검증합니다.
  • 브라우저 개발자 도구로 로그인 중에 생성되는 쿠키와 로컬·세션 스토리지 객체를 조사합니다. 충분히 무작위한 값을 가진 인증 토큰이 생성되는지 확인합니다.
  • 쿠키에 인증 토큰을 저장한다면 DAST_AUTH_COOKIE_NAMES로 인증 토큰 쿠키의 이름을 설정합니다.