-
Notifications
You must be signed in to change notification settings - Fork 893
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
Strip xorigin navigation referrers instead of spoofing #1767
Conversation
currently building on MacOS. thanks for making a test page. adding @bridiver for review |
on https://fmarier.github.io/brave-testing/referrer-spoofing.html:
|
i made a test page for subresource referer: https://jsfiddle.net/r4ygLsup/ expected result with spoofing:
I got the expected results on current stable release. with this PR:
not sure if the difference is due to this PR or changed sometime before EDIT: tried this with cf71d56 reverted and got the same result as on stable |
I was cheating for that one since I looked at the Apache access log :)
but your idea of looking at I updated my test page to include that and also the |
Using my updated test page, the three test cases are as expected in my branch:
and as expected on current release, beta and dev:
|
I added two more test cases to my test page to cover same-origin iframes and cross-origin iframes, as leaked via
Now that I think of it, should cross-origin iframes be spoofed or truncated? They're not top-level navigations, but aren't navigations too? |
In other words, do we agree that the expected values I put down on https://fmarier.github.io/brave-testing/referrer-spoofing.html are correct after this patch is applied? The only difference with current release is that anything that's expected to be blank on the test page is currently spoofed without my patch. |
@fmarier i agree https://fmarier.github.io/brave-testing/referrer-spoofing.html shows the correct values with this patch. however the first test case in https://jsfiddle.net/yg29vnLt/ is still confusing me (i updated the jsfiddle to have better labels); instead of showing no referrer, it shows |
You're right, that makes no sense. I will dig into that test case. |
@diracdeltas I made a simplified version of your jsfiddle which still exhibits the same issue: https://jsfiddle.net/06oh25xy/ As far as I can tell, the problem is that the test case in jsfiddle is different when we spoof v. strip. When we strip the referrer, it's no longer not a single iframe, but rather an iframe within a same-origin iframe. On release (spoofing), when loading https://jsfiddle.net/06oh25xy/ I see this in the devtools:
With my patch (stripping), I see the following instead:
In fact, we can tell visually that we're not getting the same payload. This is the result iframe without my patch: and this is the same result iframe with my patch: (notice the extra "tab" bar) |
@fmarier interesting! are you saying the site inserts an extra iframe when the referer is stripped out? that's definitely not a bug with this patch then |
Indeed. This is what it looks like on the jsfiddle site,
and this is what it looks like without a referrer:
|
I'd suggest to (a) at least expand current scenarios with checking same-origin vs cross-origin (b) if we have enough time, add a test against not clearing referrer for resource requests and a test against proper value in the HTTP referrer header |
ba29220
to
0079463
Compare
a1874d9
to
a017a26
Compare
} | ||
} | ||
|
||
std::string last_referrer(const GURL& url) const { |
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.
nit: this getter looks like a propery, this is slightly misleading. I'd suggest to rename last_referrer_
-> last_referrers_
and last_referrer() -> GetLastReferrer()
|
||
std::string last_referrer(const GURL& url) const { | ||
base::AutoLock auto_lock(last_referrer_lock_); | ||
std::map<GURL, std::string>::const_iterator pos = |
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.
const auto pos
std::map<GURL, std::string>::const_iterator pos = | ||
last_referrer_.find(url); | ||
if (pos == last_referrer_.end()) { | ||
return "(missing)"; // Fail test if we haven't seen this URL before. |
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.
you can just use FAIL() << "Diagnostic message";
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.
That's indeed much better. In this case it doesn't actually compile if I use FAIL()
because it's inside a function with a non-void return value.
@@ -499,8 +563,13 @@ IN_PROC_BROWSER_TEST_F(BraveContentSettingsObserverBrowserTest, AllowReferrer) { | |||
|
|||
EXPECT_STREQ(ExecScriptGetStr(kReferrerScript, | |||
contents()).c_str(), ""); | |||
EXPECT_EQ(last_referrer(url()), ""); |
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 would use EXPECT_TRUE(last_referrer(url()).empty());
@@ -499,8 +563,13 @@ IN_PROC_BROWSER_TEST_F(BraveContentSettingsObserverBrowserTest, AllowReferrer) { | |||
|
|||
EXPECT_STREQ(ExecScriptGetStr(kReferrerScript, | |||
contents()).c_str(), ""); | |||
EXPECT_EQ(last_referrer(url()), ""); | |||
EXPECT_EQ(ExecScriptGetStr(create_image_script(), 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.
expected argument typically comes first, actual - second
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.
Thanks that's good to know.
I think it will leave them as they are right now because the whole file seems to be doing it wrong and fixing it everywhere would bloat my PR quite a bit.
EXPECT_EQ(last_referrer(url()), ""); | ||
EXPECT_EQ(ExecScriptGetStr(create_image_script(), contents()), | ||
image_url().spec()); | ||
EXPECT_EQ(last_referrer(image_url()), image_url().GetOrigin().spec()); |
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.
maybe we can add some comments about what is going on here
@fmarier Good job 👍 LGTM with small nits |
Fixes brave/brave-browser#3422.
Submitter Checklist:
npm test brave_unit_tests && npm test brave_browser_tests
) onnpm run lint
)git rebase master
(if needed).git rebase -i
to squash commits (if needed).Test Plan:
This can be manually tested using https://fmarier.github.io/brave-testing/referrer-spoofing.html.
Reviewer Checklist: