Phage is a security research tool for fuzzing and racing HTTP/3 (over QUIC)
servers, and for evolving HTTP/3-to-HTTP/1 request-smuggling desync vectors. It
implements the Quic-Fin-Sync race-condition primitive and layers an
evolutionary search on top of it.
Phage began as CyberArk Labs'
QuicDrawH3 (the Quic-Fin-Sync racing
client by Maor Abutbul), originally published in "Racing and Fuzzing
HTTP/3".
This fork adds phage.evo: a coverage-guided, quality-diverse evolutionary
engine that searches the H3 framing space for desyncs, with biology- and
physics-inspired search mechanisms. See docs/EVO.md.
- Phage
- Phage-UI
- Contributing
- Limitations
- Known issues
- License
- Credits
- Contact
- Implements the
Quic-Fin-Syncon HTTP3 (over QUIC), for race-condition testing. - Supports fuzzing multiple requests with the
FUZZand wordlist (-wargument) mechanisms. - Custom HTTP headers functionality (
-Hargument).- Note: Custom headers are converted to lowercase since we have seen issues with some server implementations.
- Supports SSLKEYLOGFILE (
-largument) for TLS decryption/inspection via packet analyzers such as Wireshark. - Based on aioquic (http3_client)
- aioquic is a library for the QUIC network protocol in Python.
- It features a minimal TLS 1.3 implementation, a QUIC stack, and an HTTP/3 stack.
Prerequisite:
- python >=3.9
- pip3
The easiest way to install Phage is to run:
pip install phageThe easiest way to install Phage-UI is to run:
pip install phage[ui]
phage-ui -hphage -hIf there are no wheels for your system or if you wish to build Phage from source.
Clone the repository:
git clone https://github.com/UncleJ4ck/Phage.git
python3 -m build
pip install .\dist\phage-<VERSION>.tar.gzInstall module dependencies. (You may prefer to do this within a Virtual Environment)
phage -hphage <https://http3_server.com/path>HTTP POST requests are determined by using the -d argument followed by
the HTTP POST data to be sent.
phage <https://http3_server.com/path> -d '{"key":"value"}'log secrets to a file, for use with Wireshark
To inspect the traffic in wireshark: Open Wireshark → Edit → Preferences → Protocols → TLS and set "(Pre)-Master-Secret log filename" to the full path of secrets.log
Using the verbose (-v) output will log (print) the request data to be
sent and the HTTP response content.
In the case of GET requests (no -d argument supplied), the request URL
(:path) will be logged (printed).
To use the same request multiple times (using the Quic-Fin-Sync /
single-packet), use the -tr/--total-requests argument.
Note: If a WORDLIST (-w) argument is specified, this argument
(-tr TOTAL_REQUESTS) is overridden by the wordlist number of lines.
phage <https://http3_server.com/path> -d '{"key":"value"}' -H 'Authorization: bearer eyJ...' -tr 12phage <https://http3_server.com/path> -d '{"key":"value"}' -H 'Authorization: bearer eyJ...' -H 'content-type: application/json' -l /m2a/ssl_key_log_file.log -tr 12Repeat the same request 12 times (-tr 12), use Quic-Fin-Sync, log (-l) TLS secrets, and print verbose (-v) output including HTTP response content
phage <https://http3_server.com/path> -d '{"key": "value"}' -H 'Authorization: bearer eyJ...' -H 'content-type: application/json' -l /m2a/ssl_key_log_file.log -tr 12 -vFuzzing in Phage is based on a simple concept, like other web fuzzers
(Ffuf,
Wfuzz), go over the data section
(-d), and replace any reference to the FUZZ keyword with the value
given in the wordlist (-w) as the payload.
To define fuzzing, use the wordlist (-w/--wordlist) argument with
the FUZZ keyword anywhere in the DATA (-d argument) section.
Note: If the payload (-d) does not include the FUZZ keyword, the
same data will be sent according to the number of lines in the
wordlist file.
Use Quic-Fin-Sync, go over the data section (-d), and replace any reference to the FUZZ keyword with the value given in the wordlist file (-w) as the payload
phage <https://http3_server.com/path> -w path/to/wordlist -d '{"example_key":"FUZZ"}'Phage-UI is an HTTP/3 request editor: a GUI for Phage's fuzzing and racing client.
The easiest way to install Phage-UI is to run:
pip install phage[ui]
phage-ui -hSend a basic request to an HTTP/3 server:
phage-ui https://example.comAdvanced Tab
The following options can be set by the advanced tab
Option Description
-l, --secrets-log TLS secrets file (for Wireshark)
-v, --verbose Verbose output
Results Tab:
To fuzz an HTTP/3 endpoint, you need:
- A wordlist file (
-w) - contains payloads to test (one per line) - The
FUZZkeyword in your data - gets replaced by each wordlist entry
phage-ui https://example.com -w path/to/wordlist -d '{"example_key":"FUZZ"}'The FUZZ keyword in {"example_key":"FUZZ"} will be replaced with
each line from your wordlist file.
Phage-UI parameters are imported to the UI.
Option Description
-d, --data HTTP POST data (use FUZZ for wordlist
substitution)
-H, --header Custom header (repeatable)
-b, --cookie Custom cookie header
-w, --wordlist Fuzzing wordlist file
-tr, --total-requests Number of concurrent requests (race testing)
-l, --secrets-log TLS secrets file (for Wireshark)
-v, --verbose Verbose output
Note: "copy-as-curl compatible" meaning common curl arguments (-d,-H,-b) are supported by Phage-UI.
We welcome contributions of all kinds to this repository. For instructions on how to get started and descriptions of our development workflows, please see our contributing guide
- The
Quic-Fin-Syncis mostly effective in POST requests (using the-dargument).- GET requests will benefit from the mechanism, but according to our tests, only a few requests "fit" on a single QUIC packet.
- The fuzzing mechanism (
FUZZand--wordlist/-w) only works in POST messages data or in the GET request URL (:path) argument. - Currently, the fuzzing mechanism only works once, meaning if the
data argument is supplied (
-d), we assume fuzzing on the POST data, supplying theFUZZkeyword in the URL (:path) will result in sending the URL (:path) as-is (including theFUZZkeyword). - We do not support multiple different domains in the current version. (For different paths, you can use the FUZZ keyword in the URL's path part)
- On DNS error - the following error returned: "socket.gaierror: [Errno 11001] getaddrinfo failed"
Copyright (c) 2025 CyberArk Software Ltd. All rights reserved This
repository is licensed under the Apache-2.0 License - see
LICENSE for more details.
Phage is a fork of CyberArk Labs'
QuicDrawH3, the Quic-Fin-Sync
racing client by Maor Abutbul, published in "Racing and Fuzzing
HTTP/3".
The phage.evo evolutionary engine and the HTTP/3-to-HTTP/1 downgrade
research are additions on top of that base.
Built on aioquic.
Open a GitHub issue for feature requests or bugs.



