Skip to content

Commit

Permalink
Add WebUI Untrusted Frame Validation
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon-T committed Jan 16, 2025
1 parent 7c17675 commit 31db77d
Show file tree
Hide file tree
Showing 20 changed files with 616 additions and 575 deletions.
35 changes: 35 additions & 0 deletions chromium_src/ios/web/public/web_state.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2025 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#ifndef BRAVE_CHROMIUM_SRC_IOS_WEB_PUBLIC_WEB_STATE_H_
#define BRAVE_CHROMIUM_SRC_IOS_WEB_PUBLIC_WEB_STATE_H_

#define callbacks_ \
callbacks_; \
\
public: \
template <typename Interface> \
void AddUntrustedInterface( \
const GURL& url, \
base::RepeatingCallback<void(mojo::PendingReceiver<Interface>)> \
callback) { \
CHECK(!url.is_empty()); \
untrusted_callbacks_[url].emplace( \
std::string(Interface::Name_), \
base::BindRepeating(&WrapCallback<Interface>, std::move(callback))); \
} \
bool HasUntrustedInterface(const GURL& url, \
const std::string& interface_name); \
void BindUntrustedInterface(const GURL& url, \
mojo::GenericPendingReceiver receiver); \
\
private: \
std::map<GURL, std::map<std::string, Callback>> untrusted_callbacks_

#include "src/ios/web/public/web_state.h" // IWYU pragma: export

#undef callbacks_

#endif // BRAVE_CHROMIUM_SRC_IOS_WEB_PUBLIC_WEB_STATE_H_
19 changes: 19 additions & 0 deletions chromium_src/ios/web/web_state/ui/crw_wk_ui_handler.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2025 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "ios/web/public/web_client.h"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability-completeness"

#define IsAppSpecificURL(URL) \
IsAppSpecificURL(URL) && \
self.mojoFacade->IsWebUIMessageAllowedForFrame(frame, origin, &prompt)

#include "src/ios/web/web_state/ui/crw_wk_ui_handler.mm"

#undef IsAppSpecificURL

#pragma clang diagnostic pop
37 changes: 37 additions & 0 deletions chromium_src/ios/web/web_state/web_state.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2025 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "src/ios/web/web_state/web_state.mm"

namespace web {
bool WebState::InterfaceBinder::HasUntrustedInterface(
const GURL& url,
const std::string& interface_name) {
DCHECK(!url.is_empty());
DCHECK(!interface_name.empty());
if (auto it = untrusted_callbacks_.find(url);
it != untrusted_callbacks_.end()) {
return it->second.find(interface_name) != it->second.end();
}
return false;
}

void WebState::InterfaceBinder::BindUntrustedInterface(
const GURL& url,
mojo::GenericPendingReceiver receiver) {
DCHECK(!url.is_empty());
DCHECK(receiver.is_valid());
if (auto it = untrusted_callbacks_.find(url);
it != untrusted_callbacks_.end()) {
if (auto jt = it->second.find(*receiver.interface_name());
jt != it->second.end()) {
jt->second.Run(&receiver);

GetWebClient()->BindInterfaceReceiverFromMainFrame(web_state_,
std::move(receiver));
}
}
}
} // namespace web
2 changes: 0 additions & 2 deletions chromium_src/ios/web/webui/DEPS
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
include_rules = [
"+ios/components/webui/web_ui_url_constants.h",
"+ios/chrome/browser/shared/model/url/chrome_url_constants.h",
"+brave/ios/browser/ui/webui/brave_url_data_source_ios.h",
]
23 changes: 23 additions & 0 deletions chromium_src/ios/web/webui/mojo_facade.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2025 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#ifndef BRAVE_CHROMIUM_SRC_IOS_WEB_WEBUI_MOJO_FACADE_H_
#define BRAVE_CHROMIUM_SRC_IOS_WEB_WEBUI_MOJO_FACADE_H_

#include <WebKit/WebKit.h>

#include "url/gurl.h"

#define HandleMojoMessage \
Dummy(); \
bool IsWebUIMessageAllowedForFrame(WKFrameInfo* frame, const GURL& origin, \
NSString** prompt); \
std::string HandleMojoMessage

#include "src/ios/web/webui/mojo_facade.h" // IWYU pragma: export

#undef HandleMojoMessage

#endif // BRAVE_CHROMIUM_SRC_IOS_WEB_WEBUI_MOJO_FACADE_H_
51 changes: 51 additions & 0 deletions chromium_src/ios/web/webui/mojo_facade.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2025 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "src/ios/web/webui/mojo_facade.mm"

namespace web {
bool MojoFacade::IsWebUIMessageAllowedForFrame(WKFrameInfo* frame,
const GURL& origin,
NSString** prompt) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
CHECK(prompt && *prompt);

auto name_and_args =
GetMessageNameAndArguments(base::SysNSStringToUTF8(*prompt));

// If the scheme is untrusted
if (name_and_args.name == "Mojo.bindInterface" &&
origin.scheme() == "chrome-untrusted") {
const base::Value::Dict& args = name_and_args.args;
const std::string* interface_name = args.FindString("interfaceName");
CHECK(interface_name);

// Check if the requested interface is registered
bool can_bind_interface =
web_state_->GetInterfaceBinderForMainFrame()->HasUntrustedInterface(
origin, *interface_name);

if (can_bind_interface) {
std::optional<int> pipe_id = args.FindInt("requestHandle");
CHECK(pipe_id.has_value());

mojo::ScopedMessagePipeHandle pipe = TakePipeFromId(*pipe_id);
CHECK(pipe.is_valid());
web_state_->GetInterfaceBinderForMainFrame()->BindUntrustedInterface(
origin,
mojo::GenericPendingReceiver(*interface_name, std::move(pipe)));

// Set the prompt to invalid, so that HandleMojoMessage will do nothing.
*prompt = @"{\"name\":\"Mojo.invalidInterface\",\"args\":{}}";
}
}

return true;
}

std::string MojoFacade::Dummy() {
return "";
}
} // namespace web
51 changes: 0 additions & 51 deletions chromium_src/ios/web/webui/web_ui_ios_data_source_impl.h

This file was deleted.

118 changes: 0 additions & 118 deletions chromium_src/ios/web/webui/web_ui_ios_data_source_impl.mm

This file was deleted.

2 changes: 2 additions & 0 deletions ios/browser/brave_web_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
#ifndef BRAVE_IOS_BROWSER_BRAVE_WEB_CLIENT_H_
#define BRAVE_IOS_BROWSER_BRAVE_WEB_CLIENT_H_

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/functional/callback_forward.h"
#include "ios/chrome/browser/web/model/chrome_web_client.h"

class BraveWebClient : public ChromeWebClient {
Expand Down
4 changes: 4 additions & 0 deletions ios/browser/brave_web_client.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
#import "brave/ios/browser/brave_web_client.h"

#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/strings/sys_string_conversions.h"
#include "brave/components/constants/url_constants.h"
#include "brave/ios/browser/brave_web_main_parts.h"
#include "ios/chrome/browser/shared/model/url/chrome_url_constants.h"
#include "ios/components/webui/web_ui_url_constants.h"
#import "ios/public/provider/chrome/browser/url_rewriters/url_rewriters_api.h"
#import "ios/web/public/navigation/browser_url_rewriter.h"
#include "ios/web/public/thread/web_thread.h"
#include "net/base/apple/url_conversions.h"
#include "url/gurl.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
Expand Down
5 changes: 1 addition & 4 deletions ios/browser/ui/webui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ import("//mojo/public/tools/bindings/mojom.gni")

source_set("webui") {
sources = [
"brave_url_data_source_ios.h",
"brave_url_data_source_ios.mm",
"brave_web_ui_controller_factory.h",
"brave_web_ui_controller_factory.mm",
"brave_webui_data_source.h",
"brave_webui_data_source.mm",
"brave_webui_source.h",
"brave_webui_source.mm",
]
Expand All @@ -23,6 +19,7 @@ source_set("webui") {
"//brave/components/constants",
"//brave/components/webui",
"//brave/ios/browser/ui/webui/ads",
"//brave/ios/browser/ui/webui/public",
"//brave/ios/browser/ui/webui/skus",
"//components/prefs",
"//components/profile_metrics",
Expand Down
Loading

0 comments on commit 31db77d

Please sign in to comment.