Ajax Spidering 시 브라우저 엔진 별 성능 비교 🏁

ZAP의 AjaxSpider는 headless browser를 통해서 직접 브라우징하며 Spidering 하는 기능입니다. 기본적으로는 Firefox가 설정되어 있지만, 개인의 취향에 따라 Chrome, PhantomJS 등 여러가지 browser(headless or common)를 사용할 수 있습니다.

갑자기 궁금해졌습니다. 과연 누가 제일 빠르고 많이 잡아올까? 그래서 비교해보기로 마음먹었죠.

TLDR

  • firefox: Found 675 URLs
  • chrome: Found 382 URLs
  • phantomjs: Found 340 URLs

Winner is Firefox!

How to test

방법은 간단합니다. Security Crawl Maze 를 대상으로 AjaxSpidering을 진행하며 이 때 수집된 URL의 수를 비교합니다. 원래는 속도로 테스트하려고 했으나 별 차이가 없어서 수집할 수 있는 URL의 수를 가지고 비교하려고 합니다.

Automation - AjaxSpider Job

우선 Automation에서 AjaxSpider은 Job으로 지원하고 있고, Paramter를 통해 커스텀이 가능합니다.

- type: spiderAjax                   # The ajax spider - slower than the spider but handles modern apps well
    parameters:
      context:                         # String: Name of the context to spider, default: first context
      url:                             # String: Url to start spidering from, default: first context URL
      maxDuration:                     # Int: The max time in minutes the ajax spider will be allowed to run for, default: 0 unlimited
      maxCrawlDepth:                   # Int: The max depth that the crawler can reach, default: 10, 0 is unlimited
      numberOfBrowsers:                # Int: The number of browsers the spider will use, more will be faster but will use up more memory, default: 1
      browserId:                       # String: Browser Id to use, default: firefox-headless
      clickDefaultElems:               # Bool: When enabled only click the default element: 'a', 'button' and input, default: true
      clickElemsOnce:                  # Bool: When enabled only click each element once, default: true
      eventWait:                       # Int: The time in millseconds to wait after a client side event is fired, default: 1000
      maxCrawlStates:                  # Int: The maximum number of crawl states the crawler should crawl, default: 0 unlimited
      randomInputs:                    # Bool: When enabled random values will be entered into input element, default: true
      reloadWait:                      # Int: The time in millseconds to wait after the URL is loaded, default: 1000
    tests:
      - name: 'At least 100 URLs found'      # String: Name of the test, default: statistic + operator + value
        type: 'stats'                        # String: Type of test, only 'stats' is supported for now
        statistic: 'spiderAjax.urls.added'   # String: Name of an integer / long statistic, currently supported: 'spiderAjax.urls.added'
        operator: '>='                       # String ['==', '!=', '>=', '>', '<', '<=']: Operator used for testing
        value: 100                           # Int: Change this to the number of URLs you expect to find
        onFail: 'info'                       # String [warn, error, info]: Change this to 'warn' or 'error' for the test to take effect

Automation - YAML

저는 security crawl maze 페이지를 대상으로 테스트하기 위해 context job 하나와 실제 스캔을 진행할 ajaxSpider job을 준비했습니다.

---
env:
  contexts:
  - name: "Automated"
    urls:
    - "https://security-crawl-maze.app"
    includePaths:
    - "https://security-crawl-maze.app.*"
    excludePaths: []
    authentication:
      parameters: {}
      verification:
        method: "response"
        pollFrequency: 60
        pollUnits: "requests"
    sessionManagement:
      method: "cookie"
      parameters: {}
  parameters:
    failOnError: true
    failOnWarning: false
    progressToStdout: true
  vars: {}
jobs:
- parameters:
    context: "Automated"
    user: ""
    url: "https://security-crawl-maze.app"
    maxDuration: 0
    maxCrawlDepth: 0
    numberOfBrowsers: 1
    maxCrawlStates: 0
    eventWait: 1
    browserId: "firefox-headless"
    reloadWait: 1
    clickDefaultElems: true
    clickElemsOnce: true
    randomInputs: true
  name: "spiderAjax"
  type: "spiderAjax"

이 때 browserId 값을 가지고 browser를 변경할 수 있습니다.

  • firefox-headless
  • firefox
  • chrome-headless
  • chrome
  • phantomjs
  • etc…

Testing

GUI

ZAP의 Automation framework에서 yaml 파일을 로드하고 테스트해볼 수 있습니다.

CLI

만약 CLI로 테스팅 한다면 -autorun flag를 주어 yaml 파일을 로드 후 즉시 동작 시키도록 할 수 있습니다.

./zap.sh -cmd -autorun auto.yaml -daemon

API

/JSON/automation/action/runPlan/ API를 호출하여 지정한 yaml 파일을 로드하고 실행할 수 있습니다. GET/POST 모두 가능합니다.

POST http://localhost:8090/JSON/automation/action/runPlan/ HTTP/1.1
Host: localhost

filePath=auto.yaml

Raw Result

Firefox headless

phase 1

Job spiderAjax started
Job spiderAjax found 675 URLs
Job spiderAjax finished

phase 2

Job spiderAjax started
Job spiderAjax found 565 URLs
Job spiderAjax finished

Chrome headless

phase 1

Job spiderAjax started
Job spiderAjax found 353 URLs
Job spiderAjax finished

phase 2

Job spiderAjax started
Job spiderAjax found 382 URLs
Job spiderAjax finished

PhantomJS

phase 1

Job spiderAjax started
Job spiderAjax found 340 URLs
Job spiderAjax finished

phase 2

Job spiderAjax started
Job spiderAjax found 334 URLs
Job spiderAjax finished

HTML Unit

너무 느리고, 끝이 나질 않습니다. 사용 불가

Conclusion

예상은 했지만 Firefox가 궁합이 가장 좋았습니다. 아무래도 ZAP이 모질라와 인연이 깊기 때문에 동작 방식이나 구조에 능숙할거라 이런 결과가 나왔을 것 같네요. 테스트 대부분을 Automation framework를 통해 진행했는데 만약 처음 접하거나 낯설다면 이참에 한번 써보시면서 체득하는 것도 추천드려봅니다 😎