Block-gateway-attacks-via-websockets.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. From: csagan5 <32685696+csagan5@users.noreply.github.com>
  2. Date: Tue, 28 Jul 2020 12:28:58 +0200
  3. Subject: Block gateway attacks via websockets
  4. ---
  5. services/network/public/cpp/features.cc | 2 +-
  6. .../renderer/core/loader/base_fetch_context.h | 1 +
  7. .../core/loader/frame_fetch_context.cc | 18 +++++++++++++
  8. .../core/loader/frame_fetch_context.h | 1 +
  9. .../core/loader/worker_fetch_context.cc | 19 +++++++++++++
  10. .../core/loader/worker_fetch_context.h | 1 +
  11. .../background_fetch_manager.cc | 2 --
  12. .../websockets/websocket_channel_impl.cc | 5 ++++
  13. .../modules/websockets/websocket_common.cc | 27 +++++++++++++++++++
  14. .../modules/websockets/websocket_common.h | 4 +++
  15. 10 files changed, 77 insertions(+), 3 deletions(-)
  16. diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc
  17. --- a/services/network/public/cpp/features.cc
  18. +++ b/services/network/public/cpp/features.cc
  19. @@ -125,7 +125,7 @@ const base::Feature kCrossOriginIsolated{"CrossOriginIsolated",
  20. //
  21. // https://wicg.github.io/cors-rfc1918/#integration-fetch
  22. const base::Feature kBlockInsecurePrivateNetworkRequests{
  23. - "BlockInsecurePrivateNetworkRequests", base::FEATURE_DISABLED_BY_DEFAULT};
  24. + "BlockInsecurePrivateNetworkRequests", base::FEATURE_ENABLED_BY_DEFAULT};
  25. // Enables or defaults splittup up server (not proxy) entries in the
  26. // HttpAuthCache.
  27. diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h
  28. --- a/third_party/blink/renderer/core/loader/base_fetch_context.h
  29. +++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
  30. @@ -66,6 +66,7 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
  31. virtual PreviewsResourceLoadingHints* GetPreviewsResourceLoadingHints()
  32. const = 0;
  33. virtual bool ShouldBlockWebSocketByMixedContentCheck(const KURL&) const = 0;
  34. + virtual bool ShouldBlockGateWayAttacks(network::mojom::IPAddressSpace requestor_space, const KURL&) const = 0;
  35. virtual std::unique_ptr<WebSocketHandshakeThrottle>
  36. CreateWebSocketHandshakeThrottle() = 0;
  37. diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
  38. --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
  39. +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
  40. @@ -746,6 +746,24 @@ bool FrameFetchContext::ShouldBlockRequestByInspector(const KURL& url) const {
  41. return should_block_request;
  42. }
  43. +bool FrameFetchContext::ShouldBlockGateWayAttacks(network::mojom::IPAddressSpace requestor_space, const KURL& request_url) const {
  44. + // TODO(mkwst): This only checks explicit IP addresses. We'll have to move
  45. + // all this up to //net and //content in order to have any real impact on
  46. + // gateway attacks. That turns out to be a TON of work (crbug.com/378566).
  47. + network::mojom::IPAddressSpace target_space =
  48. + network::mojom::IPAddressSpace::kPublic;
  49. + if (network_utils::IsReservedIPAddress(request_url.Host()))
  50. + target_space = network::mojom::IPAddressSpace::kPrivate;
  51. + if (SecurityOrigin::Create(request_url)->IsLocalhost())
  52. + target_space = network::mojom::IPAddressSpace::kLocal;
  53. +
  54. + bool is_external_request = requestor_space > target_space;
  55. + if (is_external_request)
  56. + return true;
  57. +
  58. + return false;
  59. +}
  60. +
  61. void FrameFetchContext::DispatchDidBlockRequest(
  62. const ResourceRequest& resource_request,
  63. const FetchInitiatorInfo& fetch_initiator_info,
  64. diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
  65. --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
  66. +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
  67. @@ -154,6 +154,7 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
  68. bool ShouldBlockWebSocketByMixedContentCheck(const KURL&) const override;
  69. std::unique_ptr<WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle()
  70. override;
  71. + bool ShouldBlockGateWayAttacks(network::mojom::IPAddressSpace requestor_space, const KURL&) const override;
  72. bool ShouldBlockFetchByMixedContentCheck(
  73. mojom::blink::RequestContextType request_context,
  74. const base::Optional<ResourceRequest::RedirectInfo>& redirect_info,
  75. diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
  76. --- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
  77. +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
  78. @@ -25,6 +25,7 @@
  79. #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
  80. #include "third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h"
  81. #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
  82. +#include "third_party/blink/renderer/platform/network/network_utils.h"
  83. #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
  84. #include "third_party/blink/renderer/platform/supplementable.h"
  85. #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
  86. @@ -96,6 +97,24 @@ bool WorkerFetchContext::ShouldBlockRequestByInspector(const KURL& url) const {
  87. return should_block_request;
  88. }
  89. +bool WorkerFetchContext::ShouldBlockGateWayAttacks(network::mojom::IPAddressSpace requestor_space, const KURL& request_url) const {
  90. + // TODO(mkwst): This only checks explicit IP addresses. We'll have to move
  91. + // all this up to //net and //content in order to have any real impact on
  92. + // gateway attacks. That turns out to be a TON of work (crbug.com/378566).
  93. + network::mojom::IPAddressSpace target_space =
  94. + network::mojom::IPAddressSpace::kPublic;
  95. + if (network_utils::IsReservedIPAddress(request_url.Host()))
  96. + target_space = network::mojom::IPAddressSpace::kPrivate;
  97. + if (SecurityOrigin::Create(request_url)->IsLocalhost())
  98. + target_space = network::mojom::IPAddressSpace::kLocal;
  99. +
  100. + bool is_external_request = requestor_space > target_space;
  101. + if (is_external_request)
  102. + return true;
  103. +
  104. + return false;
  105. +}
  106. +
  107. void WorkerFetchContext::DispatchDidBlockRequest(
  108. const ResourceRequest& resource_request,
  109. const FetchInitiatorInfo& fetch_initiator_info,
  110. diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h
  111. --- a/third_party/blink/renderer/core/loader/worker_fetch_context.h
  112. +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
  113. @@ -62,6 +62,7 @@ class WorkerFetchContext final : public BaseFetchContext {
  114. bool ShouldBlockWebSocketByMixedContentCheck(const KURL&) const override;
  115. std::unique_ptr<WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle()
  116. override;
  117. + bool ShouldBlockGateWayAttacks(network::mojom::IPAddressSpace requestor_space, const KURL&) const override;
  118. bool ShouldBlockFetchByMixedContentCheck(
  119. mojom::blink::RequestContextType request_context,
  120. const base::Optional<ResourceRequest::RedirectInfo>& redirect_info,
  121. diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
  122. --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
  123. +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
  124. @@ -106,7 +106,6 @@ bool ShouldBlockDanglingMarkup(const KURL& request_url) {
  125. bool ShouldBlockGateWayAttacks(ExecutionContext* execution_context,
  126. const KURL& request_url) {
  127. - if (RuntimeEnabledFeatures::CorsRFC1918Enabled()) {
  128. network::mojom::IPAddressSpace requestor_space =
  129. execution_context->AddressSpace();
  130. @@ -123,7 +122,6 @@ bool ShouldBlockGateWayAttacks(ExecutionContext* execution_context,
  131. bool is_external_request = requestor_space > target_space;
  132. if (is_external_request)
  133. return true;
  134. - }
  135. return false;
  136. }
  137. diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
  138. --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
  139. +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
  140. @@ -202,6 +202,11 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) {
  141. return false;
  142. }
  143. + if (GetBaseFetchContext()->ShouldBlockGateWayAttacks(execution_context_->AddressSpace(), url)) {
  144. + has_initiated_opening_handshake_ = false;
  145. + return false;
  146. + }
  147. +
  148. if (auto* scheduler = execution_context_->GetScheduler()) {
  149. feature_handle_for_scheduler_ = scheduler->RegisterFeature(
  150. SchedulingPolicy::Feature::kWebSocket,
  151. diff --git a/third_party/blink/renderer/modules/websockets/websocket_common.cc b/third_party/blink/renderer/modules/websockets/websocket_common.cc
  152. --- a/third_party/blink/renderer/modules/websockets/websocket_common.cc
  153. +++ b/third_party/blink/renderer/modules/websockets/websocket_common.cc
  154. @@ -87,6 +87,15 @@ WebSocketCommon::ConnectResult WebSocketCommon::Connect(
  155. return ConnectResult::kException;
  156. }
  157. + network::mojom::IPAddressSpace requestor_space =
  158. + execution_context->AddressSpace();
  159. + if (ShouldBlockGateWayAttacks(requestor_space, url_)) {
  160. + state_ = kClosed;
  161. + exception_state.ThrowSecurityError(
  162. + "Access to this address is not allowed.");
  163. + return ConnectResult::kException;
  164. + }
  165. +
  166. if (!execution_context->GetContentSecurityPolicyForCurrentWorld()
  167. ->AllowConnectToSource(url_, url_, RedirectStatus::kNoRedirect)) {
  168. state_ = kClosed;
  169. @@ -135,6 +144,24 @@ WebSocketCommon::ConnectResult WebSocketCommon::Connect(
  170. return ConnectResult::kSuccess;
  171. }
  172. +bool WebSocketCommon::ShouldBlockGateWayAttacks(network::mojom::IPAddressSpace requestor_space, const KURL& request_url) const {
  173. + // TODO(mkwst): This only checks explicit IP addresses. We'll have to move
  174. + // all this up to //net and //content in order to have any real impact on
  175. + // gateway attacks. That turns out to be a TON of work (crbug.com/378566).
  176. + network::mojom::IPAddressSpace target_space =
  177. + network::mojom::IPAddressSpace::kPublic;
  178. + if (network_utils::IsReservedIPAddress(request_url.Host()))
  179. + target_space = network::mojom::IPAddressSpace::kPrivate;
  180. + if (SecurityOrigin::Create(request_url)->IsLocalhost())
  181. + target_space = network::mojom::IPAddressSpace::kLocal;
  182. +
  183. + bool is_external_request = requestor_space > target_space;
  184. + if (is_external_request)
  185. + return true;
  186. +
  187. + return false;
  188. +}
  189. +
  190. void WebSocketCommon::CloseInternal(int code,
  191. const String& reason,
  192. WebSocketChannel* channel,
  193. diff --git a/third_party/blink/renderer/modules/websockets/websocket_common.h b/third_party/blink/renderer/modules/websockets/websocket_common.h
  194. --- a/third_party/blink/renderer/modules/websockets/websocket_common.h
  195. +++ b/third_party/blink/renderer/modules/websockets/websocket_common.h
  196. @@ -10,6 +10,8 @@
  197. #include <memory>
  198. #include "base/macros.h"
  199. +#include "services/network/public/mojom/ip_address_space.mojom.h"
  200. +#include "third_party/blink/renderer/platform/network/network_utils.h"
  201. #include "third_party/blink/renderer/modules/modules_export.h"
  202. #include "third_party/blink/renderer/platform/weborigin/kurl.h"
  203. #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
  204. @@ -53,6 +55,8 @@ class MODULES_EXPORT WebSocketCommon {
  205. void SetState(State state) { state_ = state; }
  206. const KURL& Url() const { return url_; }
  207. + bool ShouldBlockGateWayAttacks(network::mojom::IPAddressSpace requestor_space, const KURL& url) const;
  208. +
  209. // The following methods are public for testing.
  210. // Returns true if |protocol| is a valid WebSocket subprotocol name.
  211. --
  212. 2.17.1