Skip to content

Latest commit

 

History

History
218 lines (157 loc) · 9.3 KB

File metadata and controls

218 lines (157 loc) · 9.3 KB

⚠️ Disclaimer

The development of GlazGo has progressed significantly beyond the version previously uploaded to this GitHub repository.

At this time, the latest source code will not be shared publicly. Only compiled .exe releases will be made available for download through the official release section.

This approach allows for cleaner releases while development continues in a more experimental and evolving form.

Thanks for checking it out and supporting this early-stage project.

GlazGo Fuzzer v2.2.0

A web application fuzzer with a browser UI, written in Go. Point it at a request, mark the parts you want to vary with a keyword, and give each keyword a source of payloads.

No external dependencies: the UI, the built-in wordlists and the server all ship in one binary.

What it fuzzes

Any part of the request, at as many points at once as you like:

Position Example
url, path https://host/FUZZ, https://host/?q=FUZZ
method FUZZ /admin
header-name FUZZ: 127.0.0.1 — accepted-header discovery, 403 bypass
header-value X-Forwarded-For: FUZZ
cookie-name, cookie-value session=FUZZ
body user=admin&pass=FUZZ

Two ways to describe the request:

  • Structured — the usual URL, method, headers, cookies and body fields.
  • Raw — paste a request from Burp and put keywords anywhere in it. Header names keep the case you wrote. (Go sorts header names on the wire, so header order is not preserved.)

Both compile to the same raw request internally, so they behave identically. Preview request shows exactly what will be sent.

A payload in the Host header is delivered to the original target rather than being resolved as a hostname, which is what Host-header testing needs. A keyword in the URL's authority (https://FUZZ.example.com/) is treated as subdomain fuzzing and does move the connection.

Payload sources

Every source streams one payload at a time, so memory does not depend on how many payloads there are. A 10M-line wordlist runs in about 22MB of RSS.

Source Notes
Wordlist file Streamed line by line. Optionally pre-counted so progress can show a total.
Pasted payloads Typed straight into the page.
Built-in list Embedded in the binary: 403/401 bypass headers, cache-poisoning headers, loopback and internal address representations.
Number range from/to/step with optional zero padding. Generated, no file.
Brute force Every string over a character set within a length range. Generated, no file.
Mutations Variants of another source: extensions, prefixes, suffixes, case, backup suffixes (.bak, ~, .old, …), leet. One base word becomes K payloads at no memory cost.

With more than one fuzz point, choose how they combine:

  • Clusterbomb — every combination.
  • Pitchfork — sources advance in lockstep, for paired data such as user/password columns.

Each point has its own encoding: none, URL (minimal), URL (strict), double URL, or form. The minimal URL encoding leaves /, ., ?, & and existing %xx escapes alone, so directory wordlists work, but escapes spaces, # and the characters that would otherwise corrupt the request line.

Requirements

Go 1.21 or later. No other dependencies.

Build and run

go build -o glazgo ./cmd/glazgo
./glazgo

Then open http://127.0.0.1:5000/.

Flags:

Flag Default Meaning
-host 127.0.0.1 Address to bind.
-port 5000 Port to listen on.
-data data Directory for result logs.
-open off Open the UI in the default browser.

The server binds loopback by default, and rejects cross-origin POST /api/*. The API can send requests from this machine and read local files, so think before using -host 0.0.0.0: there is no authentication.

Settings

Setting Meaning
Concurrent requests Size of the worker pool. Also sizes the connection pool.
Timeout Per-request timeout in milliseconds.
Rate limit Cap on requests per second across all workers. 0 is unlimited.
Per-worker delay Sleep after each request, per worker. The effective rate is roughly concurrency ÷ delay, which is why the rate limit exists.
Auto-pause after N failures Pauses the run after N consecutive failures so a dead target does not burn through a wordlist. -1 disables it.
Keep results per status Retention buffer per status code. Counters are unaffected. Adjustable during a run.
Calibration probes How many "cannot exist" requests are sent to learn the not-found response.
Proxy e.g. http://127.0.0.1:8080 to route through Burp.
Skip TLS verification For targets with self-signed certificates.
Follow redirects Off by default: a redirect is usually the finding.
Allow HTTP/2 Negotiate h2 over TLS.
Accept gzip Off by default so response lengths stay comparable between requests.
Match / Filter rules Narrow what is listed and logged. Counts always cover every request.

Reading the results

A directory run against a real target sends thousands of requests and gets one answer thousands of times. Two things deal with that without any configuration:

Auto-calibration. Before the run, GlazGo asks the target for a few paths that cannot exist and learns what it says. Responses matching that fingerprint are hidden. In a verified run of 40,004 requests this reduced the list to the 4 real pages.

It declines rather than guess. If the probe responses disagree — a page carrying a timestamp, a CSRF token, or genuinely random content — it reports "calibration inconclusive" and filters nothing, because a wrong fingerprint silently buries real findings. It never hides failed requests, and everything it does hide is still counted and still grouped. Switch it off with the checkbox.

Grouping. Identical responses collapse into one row: ×40,000 · 404 · len 88 · words 6. The count is kept server-side, so it stays true for results already dropped from the display buffer. "Show these" drills into a group.

The results table

Sortable on every column — click a header: request number, status, length, Δ against the baseline, words, lines, response time, content type, page title, payload, and whether the payload was reflected in the response body. Only the visible rows exist in the page, so a 50,000-row run scrolls as smoothly as a 50-row one.

title and reflected are the two most useful triage columns: the title tells you what a discovered page actually is, and reflection is how parameters and injection candidates surface.

Filtering

Quick filters above the table apply instantly to what is already retained, in both directions:

Field Accepts
Status, Length, Words, Time 200, 400-499, 4xx, >1024, <=512, and ! to exclude — !404
Payload, Title substring, ! to exclude

A field holding only exclusions means "everything except those". The status tabs above (All · 200 (4) · 404 (40,000)) narrow to one status in a click.

Two separate limits, which behave differently:

  • Show per status is a display cap. It applies instantly and changes nothing on the server.
  • Keep per status is server-side retention. Lowering it drops the oldest immediately; raising it applies only to results from that point on — anything already dropped is gone.

Rules

The Match and Filter columns on the Fuzzer tab decide what is kept and written to disk for the whole run, on status, length, words, lines, time, and regexes on title and body. A result must satisfy every Match rule and is dropped if it satisfies any Filter rule. Failed requests are always kept, so an unreachable target is never filtered into looking like a target with no findings.

Body regex sees the first 64KB of a response, since bodies are never stored.

Export

CSV, JSON, JSONL, or a plain list of URLs, covering what is retained with the rules and calibration already applied. The URL list feeds straight into another tool.

Logs

Written to <data>/<host>/<status>.txt, plus errors.txt for failures. GET runs log the bare URL so the files stay usable as input to other tools. Hidden results are not logged — that is the point of hiding them — but they are always counted and grouped.

A failure writing the logs is reported while the run is going, and Ctrl+C stops the run and flushes the buffer before exiting.

Layout

cmd/glazgo          entry point and flags
internal/server     HTTP API, embedded UI (web/)
internal/engine     worker pool, run state, pacing
internal/httpx      request template, substitution, encoding, client
internal/payload    payload sources, generators, combination modes
internal/store      result buffer, counters, log writer
internal/cli        console output

The UI lives in internal/server/web as ordinary HTML, CSS and JavaScript, embedded at build time. Edit it there.

The Windows icon comes from cmd/glazgo/glazgo_windows_amd64.syso. To regenerate it from glazgo.rc / glazgo.ico, run rsrc in cmd/glazgo and keep the _windows_amd64 suffix, or non-Windows builds will fail to link it.

Tests

go test ./...

The concurrency work matters here, so prefer the race detector (it needs cgo and a C compiler):

go test -race ./...

License

MIT — see the LICENSE file.