Project Icon

gotestwaf

多协议 API 安全测试工具 GoTestWAF

GoTestWAF 是一款开源的 Web 应用安全测试工具,支持模拟 REST、GraphQL、gRPC 和 SOAP 等多种 API 协议的攻击。它可用于评估 API 安全代理、Web 应用防火墙、IPS 和 API 网关等安全解决方案。该工具生成恶意请求并发送至指定 URL,记录评估结果并生成详细报告。GoTestWAF 兼容多种操作系统,并提供 Docker 镜像以便快速部署。

GoTestWAF Black Hat Arsenal USA 2022

GoTestWAF 是一个用于API和OWASP攻击模拟的工具,支持多种API协议,包括REST、GraphQL、gRPC、SOAP、XMLRPC等。

它旨在评估Web应用程序安全解决方案,如API安全代理、Web应用防火墙、IPS、API网关等。



工作原理

GoTestWAF生成恶意请求,将编码后的有效载荷放置在HTTP请求的不同部分:主体、头部、URL参数等。生成的请求会发送到启动GoTestWAF时指定的应用安全解决方案URL。安全解决方案的评估结果会记录在您机器上创建的报告文件中。

请求生成的默认条件在testcases文件夹中的YAML文件中定义,格式如下:

payload:
  - '"union select -7431.1, name, @aaa from u_base--w-'
  - "'or 123.22=123.22"
  - "' waitfor delay '00:00:10'--"
  - "')) or pg_sleep(5)--"
encoder:
  - Base64Flat
  - URL
placeholder:
  - UrlPath
  - UrlParam
  - JSUnicode
  - Header
type: SQL Injection
  • payload是恶意攻击样本(例如XSS有效载荷如<script>alert(111)</script>或更复杂的内容)。 由于YAML字符串格式对有效载荷是必需的,它们必须编码为二进制数据

  • encoder是在将有效载荷放入HTTP请求之前应用于有效载荷的编码器。可能的编码器有:

    • Base64
    • Base64Flat
    • JSUnicode
    • URL
    • Plain(保持有效载荷字符串原样)
    • XML Entity
  • placeholder是编码后的有效载荷应该放置的HTTP请求内部位置。可能的占位符有:

    • gRPC
    • Header
    • UserAgent
    • RequestBody
    • JSONRequest
    • JSONBody
    • HTMLForm
    • HTMLMultipartForm
    • SOAPBody
    • XMLBody
    • URLParam
    • URLPath
    • RawRequest

    RawRequest占位符允许您进行任意HTTP请求。通过替换URL路径、头部或主体中的{{payload}}字符串来替换有效载荷。RawRequest占位符的字段:

    • method
    • path
    • headers
    • body

    RawRequest占位符的必填字段:

    • method字段

    示例:

    payload:
      - test
    encoder:
      - Plain
    placeholder:
      - RawRequest:
          method: "POST"
          path: "/"
          headers:
            Content-Type: "multipart/form-data; boundary=boundary"
          body: |
            --boundary
            Content-disposition: form-data; name="field1"
            
            Test
            --boundary
            Content-disposition: form-data; name="field2"
            Content-Type: text/plain; charset=utf-7
            
            Knock knock.
            {{payload}}
            --boundary--
    type: RawRequest test
    
  • type是文件中整个有效载荷组的名称。它可以是任意的,但应反映文件中的攻击类型。

请求生成是一个三步过程,涉及有效载荷数量乘以编码器和占位符数量。假设您定义了2个有效载荷,3个编码器(Base64、JSUnicode和URL)和1个占位符(URLParameter - HTTP GET参数)。在这种情况下,GoTestWAF将在一个测试用例中发送2x3x1 = 6个请求。

在启动GoTestWAF时,您还可以在两个内置测试用例之间选择:OWASP Top-10、OWASP-API,或者使用您自己的(通过使用配置选项testCasePath)。

要求

  • GoTestWAF支持所有流行的操作系统(Linux、Windows、macOS),如果系统中安装了Go,可以进行本地构建。如果您想本地运行GoTestWAF,请确保安装了Chrome网络浏览器以生成PDF报告。如果没有Chrome,您可以创建HTML格式的报告。
  • 如果将GoTestWAF作为Docker容器运行,请确保您已安装并配置Docker,并且GoTestWAF和被评估的应用安全解决方案连接到同一个Docker网络
  • 为了成功启动GoTestWAF,请确保运行GoTestWAF的机器的IP地址在运行应用安全解决方案的机器上被列入白名单。

使用Docker快速启动

以下步骤将指导您使用最少的配置在Docker上下载和启动GoTestWAF。

  1. 从Docker Hub拉取GoTestWAF镜像

    docker pull wallarm/gotestwaf
    
  2. 启动GoTestWAF镜像:

    docker run --rm --network="host" -it -v ${PWD}/reports:/app/reports \
        wallarm/gotestwaf --url=<被评估的安全解决方案URL>
    

    如果需要,您可以将${PWD}/reports替换为用于放置评估报告的另一个文件夹的路径。

    如果您不想选择通过电子邮件发送报告,只需在出现电子邮件请求消息后按Enter键,或者可以使用--noEmailReport跳过该消息:

    docker run --rm --network="host" -v ${PWD}/reports:/app/reports \
        wallarm/gotestwaf --url=<被评估的安全解决方案URL> --noEmailReport
    

    如果被评估的安全工具可以从外部访问,您可以跳过--network="host"选项。此选项允许在127.0.0.1上运行的Docker容器之间进行交互。

    要执行gRPC测试,您必须有一个可用的端点并使用--grpcPort <端口>命令行选项。

    docker run --rm --network="host" -it -v ${PWD}/reports:/app/reports \
        wallarm/gotestwaf --grpcPort 9000 --url=http://my.grpc.endpoint
    
  3. 检查您的电子邮件以获取报告。

您已成功使用最少的配置通过GoTestWAF评估了您的应用安全解决方案。要了解高级配置选项,请使用此链接

检查评估结果

检查使用STDOUTSTDERR服务记录的评估结果。例如:

INFO[0000] GoTestWAF 已启动                               版本=v0.4.11-1-g8ccc316
INFO[0000] 开始加载测试用例                   
INFO[0000] 测试用例加载完成                  
INFO[0000] 测试用例指纹                        指纹=23c3ae919db5e6edcb62815de1a09fdf
INFO[0000] 尝试识别 WAF 解决方案                 
INFO[0000] 未识别出 WAF                       
INFO[0000] WAF 预检查                                 URL="http://localhost:8080"
INFO[0000] WAF 预检查                                 已拦截=true 状态码=403 状态=完成
INFO[0000] WebSocket 预检查                           状态=已开始 URL="ws://localhost:8080"
INFO[0000] WebSocket 预检查                           连接="不可用" 错误="websocket: 握手失败" 状态=完成
INFO[0000] gRPC 预检查                                状态=已开始
INFO[0000] gRPC 预检查                                连接="不可用" 状态=完成
INFO[0000] 开始扫描                              URL="http://localhost:8080"
INFO[0025] 扫描完成                             持续时间=25.043996212秒                                                                                                                          
真阳性测试:
+-----------------------+-------------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+
|       测试集合        |        测试用例         |        百分比, %      |        已拦截         |        已绕过         |        未解决         |         已发送        |         失败          |
+-----------------------+-------------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+
| community             | community-128kb-rce     |                  0.00 |                     0 |                     0 |                     1 |                     1 |                     0 |
| community             | community-128kb-sqli    |                  0.00 |                     0 |                     0 |                     1 |                     1 |                     0 |
| community             | community-128kb-xss     |                  0.00 |                     0 |                     0 |                     1 |                     1 |                     0 |
| community             | community-16kb-rce      |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-16kb-sqli     |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-16kb-xss      |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-32kb-rce      |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-32kb-sqli     |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-32kb-xss      |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-64kb-rce      |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-64kb-sqli     |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-64kb-xss      |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-8kb-rce       |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-8kb-sqli      |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-8kb-xss       |                100.00 |                     1 |                     0 |                     0 |                     1 |                     0 |
| community             | community-lfi           |                100.00 |                     8 |                     0 |                     0 |                     8 |                     0 |
| community             | community-lfi-multipart |                  0.00 |                     0 |                     0 |                     9 |                     9 |                     0 |
| community             | community-rce           |                 83.33 |                    10 |                     2 |                     0 |                    12 |                     0 |
| community             | community-sqli          |                100.00 |                    32 |                     0 |                     0 |                    32 |                     0 |
| community             | community-user-agent    |                 70.00 |                     7 |                     3 |                     0 |                    10 |                     0 |
| community             | community-xss           |                 95.80 |                   502 |                    22 |                     0 |                   524 |                     0 |
| community             | community-xxe           |                  0.00 |                     0 |                     2 |                     0 |                     2 |                     0 |
| owasp                 | crlf                    |                 77.78 |                     7 |                     2 |                     0 |                     9 |                     0 |
| owasp                 | ldap-injection          |                  3.13 |                     2 |                    62 |                     0 |                    64 |                     0 |
| owasp                 | mail-injection          |                 12.50 |                     3 |                    21 |                     0 |                    24 |                     0 |
| owasp                 | nosql-injection         |                  0.00 |                     0 |                    70 |                     0 |                    70 |                     0 |
| owasp                 | path-traversal          |                 24.77 |                    27 |                    82 |                     1 |                   110 |                     0 |
| owasp                 | rce                     |                 33.33 |                    22 |                    44 |                     0 |                    66 |                     0 |
| owasp                 | rce-urlparam            |                 33.33 |                     3 |                     6 |                     0 |                     9 |                     0 |
| owasp                 | shell-injection         |                 27.08 |                    13 |                    35 |                     0 |                    48 |                     0 |
| owasp                 | sql-injection           |                 24.36 |                    38 |                   118 |                     0 |                   156 |                     0 |
| owasp                 | ss-include              |                 37.50 |                    15 |                    25 |                     0 |                    40 |                     0 |
| owasp                 | sst-injection           |                 18.75 |                    12 |                    52 |                     0 |                    64 |                     0 |
| owasp                 | xml-injection           |                  0.00 |                     0 |                    12 |                     1 |                    13 |                     0 |
| owasp                 | xss-scripting           |                 33.20 |                   167 |                   336 |                     1 |                   504 |                     0 |
| owasp-api             | graphql                 |                  0.00 |                     0 |                     6 |                     0 |                     6 |                     0 |
| owasp-api             | graphql-post            |                 50.00 |                     2 |                     2 |                     0 |                     4 |                     0 |
| owasp-api             | grpc                    |                  0.00 |                     0 |                     0 |                     0 |                     0 |                     0 |
| owasp-api             | non-crud                |                100.00 |                     2 |                     0 |                     0 |                     2 |                     0 |
| owasp-api             | rest                    |                 23.08 |                     3 |                    10 |                     0 |                    13 |                     0 |
| owasp-api             | soap                    |                 23.08 |                     3 |                    10 |                     0 |                    13 |                     0 |
+-----------------------+-------------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+
|         日期:         |        项目名称:        |    真阳性得分:        |   已拦截 (已解决):    |   已绕过 (已解决):    |   未解决 (已发送):    |       总发送数:       |     失败 (总数):      |
|      2024-02-08       |         GENERIC         |        49.12%         |   890/1812 (49.12%)   |   922/1812 (50.88%)   |    15/1827 (0.82%)    |         1827          |    0/1827 (0.00%)     |
+-----------------------+-------------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+

真阴性测试: +-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+ | 测试集 | 测试用例 | 百分比, % | 阻止 | 绕过 | 未解决 | 发送 | 失败 | +-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+ | 误报 | 文本 | 85.65 | 31 | 185 | 0 | 216 | 0 | +-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+ | 日期: | 项目名称: | 真阴性得分: | 阻止 (已解决): | 绕过 (已解决): | 未解决 (已发送): | 总发送数: | 失败 (总计): | | 2024-02-08 | 通用 | 85.65% | 31/216 (14.35%) | 185/216 (85.65%) | 0/216 (0.00%) | 216 | 0/216 (0.00%) | +-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+

总结: +-----------------------------+-----------------------------+-----------------------------+-----------------------------+ | 类型 | 真阳性测试被阻止 | 真阴性测试通过 | 平均 | +-----------------------------+-----------------------------+-----------------------------+-----------------------------+ | API安全 | 26.32% | 不适用 | 26.32% | | 应用安全 | 49.61% | 85.65% | 67.63% | +-----------------------------+-----------------------------+-----------------------------+-----------------------------+ | 得分 | 46.97% | +-----------------------------+-----------------------------+-----------------------------+-----------------------------+

报告文件 waf-evaluation-report-<日期>.pdf 可在用户目录的 reports 文件夹中找到。你也可以使用 reportPath 参数指定保存报告的目录,使用 reportName 参数指定报告文件的名称。要了解高级配置选项,请使用此链接。 选项: --addDebugHeader 在每个请求中添加包含测试信息哈希的头部 --addHeader string 添加到请求中的HTTP头部 --blockConnReset 如果为true,连接重置将被视为阻塞 --blockRegex string 用于检测具有与未阻塞请求相同HTTP响应状态码的阻塞页面的正则表达式 --blockStatusCodes ints WAF在阻塞请求时使用的HTTP状态码(默认为[403]) --configPath string 配置文件路径(默认为"config.yaml") --email string 报告将发送到的电子邮件地址 --followCookies 如果为true,使用服务器发送的cookies。可能只在--maxIdleConns=1时生效(仅适用于gohttp) --graphqlURL string 要检查的GraphQL URL --grpcPort uint16 要检查的gRPC端口 --httpClient string 用于发送请求的HTTP客户端:chrome或gohttp(默认为"gohttp") --idleConnTimeout int 保持连接存活的最长时间(仅适用于gohttp)(默认为2) --ignoreUnresolved 如果为true,未解决的测试用例将被视为已绕过(影响得分和结果) --includePayloads 如果为true,有效载荷将包含在HTML/PDF报告中 --logFormat string 设置日志格式:text或json(默认为"text") --logLevel string 日志级别:panic、fatal、error、warn、info、debug、trace(默认为"info") --maxIdleConns int 最大保持连接数(仅适用于gohttp)(默认为2) --maxRedirects int 处理重定向的最大次数(仅适用于gohttp)(默认为50) --noEmailReport 本地保存报告 --nonBlockedAsPassed 如果为true,将未被阻塞的请求计为通过。如果为false,不满足PassStatusCodes/PassRegExp的请求将被视为阻塞 --openapiFile string OpenAPI文件路径 --passRegex string 用于检测具有与阻塞请求相同HTTP状态码的正常(未阻塞)网页的正则表达式 --passStatusCodes ints WAF在通过请求时使用的HTTP响应状态码(默认为[200,404]) --proxy string 要使用的代理URL --quiet 如果为true,禁用详细日志记录 --randomDelay int 除请求之间的延迟外的随机延迟(毫秒)(默认为400) --renewSession 每次测试前更新cookies。应与--followCookies标志一起使用(仅适用于gohttp) --reportFormat string 将报告导出为以下格式之一:none、pdf、html、json(默认为"pdf") --reportName string 报告文件名。支持time包模板格式(默认为"waf-evaluation-report-2006-January-02-15-04-05") --reportPath string 存储报告的目录(默认为"reports") --sendDelay int 请求之间的延迟(毫秒)(默认为400) --skipWAFBlockCheck 如果为true,将跳过WAF检测测试 --skipWAFIdentification 跳过WAF识别 --testCase string 如果设置,则仅运行此测试用例 --testCasesPath string 测试用例文件夹路径(默认为"testcases") --testSet string 如果设置,则仅运行此测试集的用例 --tlsVerify 如果为true,将验证接收到的TLS证书 --url string 要检查的URL --version 显示GoTestWAF版本并退出 --wafName string WAF产品名称(默认为"generic") --workers int 扫描的工作线程数(默认为5)

GoTestWAF支持两种HTTP客户端来执行请求,可通过--httpClient选项选择。默认客户端是标准Golang HTTP客户端。第二个选项是Chrome,可以使用--httpClient=chromeCLI参数来使用。请注意,在Linux系统上,必须在Docker参数中添加--cap-add=SYS_ADMIN参数才能使用Chrome作为请求执行器运行GoTestWAF。

报告名称

使用reportName选项,您可以为GoTestWAF报告设置自己的文件名。此选项支持golang的time包用于时间戳。详细信息可以在此处找到。您可以使用以下占位符将时间戳添加到报告名称中:

  • 年份:200606
  • 月份:JanJanuary
  • 星期几文本:MonMonday
  • 月份中的数字日期:2_202
  • 年份中的数字日期:__2002
  • 小时:15303(PM或AM)
  • 分钟:404
  • 秒:505
  • 上午/下午标记:PM
  • 数字时区:Z0700 = Z或±hhmm,Z07:00 = Z或±hh:mm,Z07 = Z或±hh

例如,默认的reportNamewaf-evaluation-report-2006-January-02-15-04-05,其中2006将被替换为实际年份,January替换为月份,02替换为日期,15替换为小时,04替换为分钟,05替换为秒。

基于OpenAPI文件的扫描

为了更好地进行扫描,GTW支持通过有效的应用程序请求发送恶意向量。GoTestWAF不是构造结构简单的请求并将其发送到启动时指定的URL,而是基于OpenAPI 3.0格式的应用程序API描述创建有效请求。

工作原理:

  1. GoTestWAF加载OpenAPI文件并构造请求模板。然后根据它们支持的占位符(例如,如果请求路径中有一个字符串参数,则该请求将被分配到支持URLPath占位符的请求组)将所有模板分成组。

  2. 从队列中选择下一个要发送的恶意向量。根据为其指定的占位符,选择可以替换此向量的所有查询模板。接下来,将向量替换到模板中并发送请求。

  3. 根据OpenAPI文件中指定的可能响应,确定请求是被WAF阻止还是传递给应用程序。如果响应代码的状态及其方案与OpenAPI文件中描述的匹配,则请求被标记为已绕过。否则,它将被标记为已阻止。可能应用程序只响应状态代码,并且此状态代码与WAF的响应匹配。在这种情况下,请求将被标记为未解决。

支持的一些OpenAPI功能:

  • 请求的头部、路径、查询参数和正文中的数字和字符串参数;

  • 支持以下请求正文的内容类型:application/jsonapplication/xmlapplication/x-www-form-urlencodedtext/plain

  • 支持XML的以下修饰符:namewrappedattributeprefixnamespace

  • 通过minLengthmaxLength参数支持字符串的长度限制;

  • 通过minimummaximumexclusiveMinimumexclusiveMaximum支持数字的值限制;

  • 通过minItemsmaxItems支持数组长度的限制;

  • 支持通过oneOfanyOfallOf组合方案。

基于所描述的操作原理,OpenAPI文件正确表示已实现的应用程序API极其重要。因此,例如,您不能使用default来描述查询的可能响应。

注意:您需要将包含openapi规范的卷转发到GoTestWAF容器。

-v ${PWD}/api.yaml:/app/api.yaml

完整的Docker示例:

docker run --rm --network="host" -it -v ${PWD}/reports:/app/reports -v ${PWD}/api.yaml:/app/api.yaml wallarm/gotestwaf --wafName your_waf_name --url=https://example.com/v1 --openapiFile api.yaml

与OWASP核心规则集回归测试套件一起运行

GoTestWAF允许轻松集成其他测试套件。

在这个例子中,我们将演示如何添加来自OWASP核心规则集回归测试套件的测试。

由于测试是以不同于GoTestWAF格式的格式编写的,因此需要进行转换。为此,提供了脚本misc/modsec_regression_testset_converter.rb

要转换测试,请运行make modsec_crs_regression_tests_convert。 然后,使用更新后的测试集构建容器。 make gotestwaf

请注意,默认情况下,仅转换一部分规则的测试。选择了以下类别:

  • REQUEST-932-APPLICATION-ATTACK-RCE
  • REQUEST-933-APPLICATION-ATTACK-PHP
  • REQUEST-941-APPLICATION-ATTACK-XSS
  • REQUEST-930-APPLICATION-ATTACK-LFI
  • REQUEST-931-APPLICATION-ATTACK-RFI
  • REQUEST-942-APPLICATION-ATTACK-SQLI
  • REQUEST-944-APPLICATION-ATTACK-JAVA
  • REQUEST-934-APPLICATION-ATTACK-GENERIC
  • REQUEST-913-SCANNER-DETECTION

如果需要,可以修改misc/modsec_regression_testset_converter.rb中的变量"crs_testcases"以添加或删除测试类别。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

白日梦AI

白日梦AI提供专注于AI视频生成的多样化功能,包括文生视频、动态画面和形象生成等,帮助用户快速上手,创造专业级内容。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

讯飞绘镜

讯飞绘镜是一个支持从创意到完整视频创作的智能平台,用户可以快速生成视频素材并创作独特的音乐视频和故事。平台提供多样化的主题和精选作品,帮助用户探索创意灵感。

Project Cover

讯飞文书

讯飞文书依托讯飞星火大模型,为文书写作者提供从素材筹备到稿件撰写及审稿的全程支持。通过录音智记和以稿写稿等功能,满足事务性工作的高频需求,帮助撰稿人节省精力,提高效率,优化工作与生活。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号