DNZ-Leaked-Password: 1, so it can ask for a new password. The password is compared on the node, so no
login waits on a network or an outside service.
It is off by default, and it is a DNZ Proxy feature: Traefik and Caddy can’t read a
request’s body without a plugin. They pass logins on unchecked, and the route dialog and the proxy’s warnings
say so.
Turn it on
1
Open the route
In the route dialog, under Stop attacks, turn on Leaked password checks.
2
Name the login path
The paths, and below them, where logins are posted, such as
/login.3
Name the password's field
A form’s name (
password, user[password]), or a JSON key (password, or user.password for one
inside an object). password unless you say otherwise.4
Read the header in your application
When
DNZ-Leaked-Password: 1 arrives on a login that succeeds, ask the user for a new password.POST to such a path, with a form or JSON body, is read. Every other request on the route costs one
check of a setting the node already holds.
What a match does
- The request goes on to your application with
DNZ-Leaked-Password: 1. The body reaches it byte for byte, whatever the check finds. - An event: filter the WAF page’s events by Leaked password. It shows the address, path and time, never the password.
- A counter: Leaked passwords at the top of the WAF page, and in Prometheus.
{ "field": "leakedPassword", "op": "exists" }). A visit a rule acted on shows under that rule’s name in the
events, and still counts. Saving such a rule is refused while a node too old to read it serves a proxy that
would run it, naming the node.
The password stays in the visit
The password is read from the body, hashed with SHA-1 and looked up, and the node forgets it. It is never logged, stored, put in a note or event, or sent anywhere. Reports from the node carry only counts. Your application gets the body as usual.What isn’t checked
The login goes on unchanged, without the header, when:- the body is over 16 KiB, compressed, or sent with
Expect: 100-continue; - it takes over a second to arrive (the check has waited that long, and what has come goes on followed by the rest, as it comes);
- it can’t be parsed, doesn’t hold the field, or the field isn’t a string;
- it isn’t a form or JSON (a
multipart/form-datalogin); - the node has no filter yet, or runs a version too old to check. The WAF page and the route dialog name such nodes.
The filter
The node holds a compact, read-only binary fuse filter with 16-bit fingerprints: about 2.3 bytes per password, three memory reads per lookup, and one wrong match in 65,536 lookups. No password or hash can be read back out of it. It comes from DNZ: nodes never reach the internet for it, and only the nodes of a proxy with a route that has the check on get it. They keep a copy on disk for when DNZ is away. Turn off the last such route and each of them frees its memory and removes the file.The default list
The 100,000 passwords seen most often in Have I Been Pwned’s Pwned Passwords, as the UK’s National Cyber Security Centre published them. It catches what attackers try first, not every leaked password. The leader downloads the one file, at a fixed version and checked against its hash, when the first route turns the check on, or when you press Download, and again each time you add or remove your own list. Only the filter is kept (about 230 KiB on each node). No password list is in DNZ or its releases.Your own list
A file with one password or one SHA-1 hash per line (HASH:count too) is added to the default list: both are
checked, in one filter. The page, the CLI and the API list what the filter holds, each list with its passwords and
the total, where a password in both counts once. The two together may hold up to 20 million different passwords,
which take about 45 MiB on each node with the check on, and building that takes DNZ about 440 MiB for as long as it
lasts. Over the limit the file is refused with the numbers, and the filter in use stays.
Without internet access, or with GitHub out of reach, a file is the whole filter. To get both once DNZ can reach it,
upload the same file again: DNZ doesn’t have it any more, so it can’t do that by itself. On a server that never
reaches the internet, add the default list’s lines to your own file.
See what it does
Proxy → WAF → Leaked passwords shows what the filter holds, its size, last update and terms, the routes with the check on and what each node serving them checked.proxy_waf_leaked_passwords; supplying a list is left to people.