-
Notifications
You must be signed in to change notification settings - Fork 965
Validate endpoint and dns in WireGuard config #24100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
c3193ab
to
f680371
Compare
Whoops - just noticed this:
Fixing now... |
6cc9717
to
3c8e4fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be bypassed with whitespace, see https://bravesoftware.slack.com/archives/C6R461GF4/p1718115100660649
dcee495
to
2e56d56
Compare
Fixed and added tests for those cases. Thanks @diracdeltas |
2e56d56
to
c2418b0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reject the entire config if it contains any unicode characters OR any #
- see https://bravesoftware.slack.com/archives/C6R461GF4/p1718182338474479 and https://bravesoftware.slack.com/archives/C6R461GF4/p1718215096342729 for test cases
c2418b0
to
36fa9e0
Compare
Updated to add these checks |
36fa9e0
to
ee0afea
Compare
ee0afea
to
6c651ee
Compare
6c651ee
to
d2b85ad
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++ 👍🏼
components/brave_vpn/common/wireguard/wireguard_utils_unittest.cc
Outdated
Show resolved
Hide resolved
d2b85ad
to
2da00ce
Compare
// Match our expected `DNS` field. | ||
absl::string_view input(config_str); | ||
while (match_count < 2 && | ||
re2::RE2::FindAndConsume(&input, R"((?m)^\s*DNS = 1\.1\.1\.1$)")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems a bit odd to me that we're using regex to validate things like ip address and hostnames since there are better tools for that in chromium. Wouldn't it be better to capture the field value and validate it using GURL, etc... ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think with GURL
you still have to add a schema. There's also net::HostPortPair
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With our code, we're hardcoding 1.1.1.1
as the DNS. Since that's the case, I think it's fine to do a text match like this. Unless we change the default, there's no need to validate (it's either right or wrong).
Hostname is a bit more complex. We could validate with GURL; but we just want to make sure the two expected domains are found in the domain for Endpoint
. Subdomain can have any value
// low ascii (excluding CR/LF), #, high ascii | ||
if (re2::RE2::PartialMatch( | ||
config_str, | ||
R"([\x00-\x09]|[\x0b-\x0c]|[\x0d-\x1f]|[\x23]|[\x7f-\xFF])")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above, shouldn't we be capturing the value and using existing utilities to validate their contents?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, there is a simple INI parser in chromium under chrome/common/ini_parser.h
, although this one wouldn´t handle multi entry for keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this, we just want to make sure none of these characters are in the config. It's not allowed
@@ -82,6 +143,30 @@ WireguardKeyPair GenerateNewX25519Keypair() { | |||
EncodeBase64(std::vector<uint8_t>(privkey, privkey + 32))); | |||
} | |||
|
|||
// See https://github.com/google/re2/wiki/Syntax for RE2 syntax | |||
bool IsValidConfig(const wchar_t* config) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you think it would be better to have base::wcstring_view config
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could - the COM interface that is calling this (IsValidConfig
) is in browser/brave_vpn/win/brave_vpn_wireguard_service/service/brave_wireguard_manager.cc
(see EnableVpn
).
I didn't want to put any casting logic in the method, just passing the raw config value to the validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
base::wcstring_view
won't require any casting here though. It will act just like wchar_t*
, but a little bit safer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried and ran into some casting issues 😦
// low ascii (excluding CR/LF), #, high ascii | ||
if (re2::RE2::PartialMatch( | ||
config_str, | ||
R"([\x00-\x09]|[\x0b-\x0c]|[\x0d-\x1f]|[\x23]|[\x7f-\xFF])")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this is the equivalent of base::IsStringASCII
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically this is making sure something is not in ASCII range 0 - 9, 11, 12, 14-31, 35 (#
), or 126+
10 and 13 allowed because config has CR (13) and LF (10)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect that's what base::IsStringASCII
checks for
https://source.chromium.org/chromium/chromium/src/+/main:base/strings/string_util_unittest.cc;l=595;drc=90cac1911508d3d682a67c97aa62483eb712f69a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would need to see what the masks evaluate to:
https://source.chromium.org/chromium/chromium/src/+/main:base/strings/string_util_impl_helpers.h;l=164-167;drc=90cac1911508d3d682a67c97aa62483eb712f69a
I think what we have is OK - but can look further if it's a blocker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to use a well tested existing utility than a regex if it has what we're looking for
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM % few comments
Created brave/brave-browser#39029 as a follow up |
Talking with reviewers- a better solution would be to not pass a config to the COM interface. Instead, only pass the required fields and then have the code generate the config (to avoid all these config parsing edge cases). Closing PR |
Fixes brave/brave-browser#37960
Submitter Checklist:
QA/Yes
orQA/No
;release-notes/include
orrelease-notes/exclude
;OS/...
) to the associated issuenpm run test -- brave_browser_tests
,npm run test -- brave_unit_tests
wikinpm run presubmit
wiki,npm run gn_check
,npm run tslint
git rebase master
(if needed)Reviewer Checklist:
gn
After-merge Checklist:
changes has landed on
Test Plan:
See brave/brave-browser#37960