Pattern with leading and trailing * is a substring match
high
shExpMatch(host, "*example.com*") or shExpMatch(url, "*abc*") is true for any string that contains the characters anywhere. Over url this includes query strings an attacker controls; over host it includes look-alike domains.
Why it matters
A glob that starts and ends with * is a contains-test. shExpMatch(url, "*example.com*")
matches http://evil.test/?r=example.com; whoever controls a link controls the query
string, so the branch (typically DIRECT) is reachable for any destination. Over host,
*abc* matches abc.test, xyzabc.example and example.com.abc-attacker.test.
Patterns that contain :// or end in /* are anchored at the scheme or path boundary and
are not flagged. The grade is capped at C because the bypass is externally triggerable
without any control over DNS or the network.
How to fix
Anchor the pattern: use host with "*.example.com" / host == "example.com", or a URL pattern with scheme and path boundaries ("http://www.example.com/*").
Examples
Bad
function FindProxyForURL(url, host) {
if (shExpMatch(url, "*example.com*")) {
return "DIRECT";
}
return "PROXY proxy.corp.example:8080";
}
Open bad example in checkerGood
function FindProxyForURL(url, host) {
if (host == "example.com" || shExpMatch(host, "*.example.com")) {
return "DIRECT";
}
return "PROXY proxy.corp.example:8080";
}
Open good example in checkerRelated rules
- Hostname pattern applied to url instead of host PAC-C001
- Trailing * in a host pattern matches attacker-controlled suffixes PAC-X002
- Port matched as a substring of the URL PAC-X008