Help us learn about your current experience with the documentation. Take the survey.

DAST 扫描故障排除

以下故障排除场景来自客户支持案例。如果您遇到此处未解决的问题,或者此处的信息无法解决您的问题,请创建支持工单。更多详情,请参阅 GitLab Support 页面。

当出现问题时

当 DAST 扫描出现问题时,如果您有特定的错误消息,请检查已知问题

否则,尝试通过回答以下问题来发现问题:

预期的结果是什么?

许多遇到 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。在正在扫描的应用程序的测试环境中关闭这些功能。
  • 它无法访问目标应用程序。确保 GitLab Runner 能够使用 DAST 配置中使用的 URL 访问应用程序。

您的应用程序如何工作?

了解您的应用程序如何工作对于找出 DAST 扫描为何无法正常工作至关重要。例如,以下情况 可能需要额外的配置设置。

  • 是否有隐藏元素的弹出模态框?
  • 加载的页面在特定时间后是否发生显著变化?
  • 应用程序加载速度特别慢或快吗?
  • 目标应用程序在加载时是否卡顿?
  • 应用程序是否根据客户端位置以不同方式工作?
  • 应用程序是单页应用吗?
  • 应用程序提交 HTML 表单,还是使用 JavaScript 和 AJAX?
  • 应用程序使用 websockets 吗?
  • 应用程序使用特定的 Web 框架吗?
  • 选择按钮是否在继续表单提交之前运行 JavaScript?速度快还是慢?
  • DAST 是否可能在元素或页面准备好之前选择或搜索元素?

DAST 在做什么?

日志记录仍然是了解 DAST 在做什么的最佳方式:

基于浏览器的分析器日志记录

分析器日志是帮助诊断扫描问题的最有用工具之一。分析器的不同部分可以以不同级别进行记录。

日志消息格式

日志消息的格式为 [时间] [日志级别] [日志模块] [消息] [附加属性]

例如,以下日志条目的级别为 INFO,属于 CRAWL 日志模块,消息为 Crawled path,附加属性为 nav_idpath

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

日志目标

日志要么发送到文件,要么发送到控制台(CI/CD 作业日志)。您可以使用 环境变量 DAST_LOG_CONFIG 配置控制台日志,使用 DAST_LOG_FILE_CONFIG 配置文件日志, 为每个目标配置接受不同的日志。

例如:

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

dast:
  variables:
    DAST_BROWSER_SCAN: "true"
    DAST_LOG_CONFIG: "auth:debug"                               # 控制台日志默认为 INFO 级别,记录 AUTH 模块的 DEBUG 级别日志
    DAST_LOG_FILE_CONFIG: "loglevel:debug,cache:warn"           # 文件日志默认为 DEBUG 级别,记录 CACHE 模块的 WARN 级别日志

默认情况下,文件日志名为 gl-dast-scan.log 的作业工件。 要配置此路径,请修改 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

作为使用 DAST_LOG_FILE_CONFIG 配置日志模块的更简单替代方案,您可以设置 SECURE_LOG_LEVEL

例如:

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

dast:
  variables:
    SECURE_LOG_LEVEL: "trace"
    # 等同于:
    # DAST_LOG_FILE_CONFIG: "loglevel:trace"
    # DAST_LOG_DEVTOOLS_CONFIG: "Default:messageAndBody,truncate:2000"
    # DAST_AUTH_REPORT: "true"

来自 DAST_LOG_FILE_CONFIGDAST_LOG_DEVTOOLS_CONFIGDAST_AUTH_REPORT 的设置会覆盖来自 SECURE_LOG_LEVEL 的设置。

示例 - 记录爬取的路径

将日志模块 CRAWL 设置为 DEBUG 以记录扫描爬取阶段发现的导航路径。这对于理解 DAST 是否正确爬取您的目标应用程序很有用。

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

dast:
  variables:
    DAST_LOG_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 日志记录

记录 DevTools 消息存在安全风险。输出包含用户名、密码和身份验证令牌等机密信息。 输出会上传到 GitLab 服务器,并且可能在作业日志中可见。

DAST 基于浏览器的扫描器使用 Chrome DevTools Protocol 协调 Chromium 浏览器。 记录 DevTools 消息有助于提供浏览器正在做什么的透明度。例如,如果选择按钮不起作用,DevTools 消息可能会显示原因是浏览器控制台日志中的 CORS 错误。 包含 DevTools 消息的日志可能非常大。因此,它应该仅在持续时间较短的作业上启用。

要记录所有 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 可用作值来表示所有域和消息。
    • 可以是域,例如 BrowserCSSPageNetwork
    • 可以是带消息的域,例如 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"

Chromium 日志

在 Chromium 崩溃的罕见情况下,将 Chromium 进程的 STDOUTSTDERR 写入日志可能很有帮助。 将环境变量 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 进行更改。例如,

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

dast:
  variables:
    DAST_PAGE_MAX_RESPONSE_SIZE_MB: "25"

爬取器无法到达预期页面

尝试禁用缓存

如果 DAST 错误地缓存了您的应用程序页面,可能导致 DAST 无法正确爬取您的应用程序。如果您看到某些页面爬取器意外找不到,请尝试设置 DAST_USE_CACHE: "false" 变量以查看是否有帮助。这可能会显著降低扫描性能。确保仅在绝对必要时禁用缓存。如果您有订阅,创建支持工单 以调查为什么缓存阻止了您网站的爬取。

直接指定目标路径

爬取器通常从定义的目标 URL 开始,并通过与站点交互来查找更多页面。但是,有两种方法可以直接指定爬取器开始的路径:

  • 使用 sitemap.xml:Sitemap 是一个明确定义的协议,用于指定网站中的页面。DAST 的爬取器在 <目标 URL>/sitemap.xml 查找 sitemap.xml 文件,并将所有指定的 URL 作为爬取器的起点。Sitemap Index 文件不受支持。
  • 使用 DAST_TARGET_PATHS:此配置变量允许为爬取器指定输入路径。示例:DAST_TARGET_PATHS: /,/page/1.html,/page/2.html

确保请求没有被阻止

默认情况下,DAST 只允许对目标 URL 的域进行请求。如果您的网站向目标域以外的域发出请求,请使用 DAST_SCOPE_ALLOW_HOSTS 指定此类主机。示例:“example.com” 向 “auth.example.com” 发出身份验证请求以续订身份验证令牌。由于该域不被允许,请求被阻止,爬取器无法找到新页面。