Title: [264394] trunk
Revision
264394
Author
lmo...@igalia.com
Date
2020-07-15 06:48:26 -0700 (Wed, 15 Jul 2020)

Log Message

[SOUP] Artificial delay to WebSocket connection to mitigate port scanning attacks
https://bugs.webkit.org/show_bug.cgi?id=214293

Reviewed by Carlos Garcia Campos.

Source/WebKit:

r264306 added an artificial delay when NetworkSocketStream closed due
to closed ports but Soup-based ports use another code path and were
still returning immediately.

SOUP WebSocket errors do not distinguish closed ports separately, so
this commit checks for connections that finished with NOT_WEBSOCKET
errors.

Covered by existing tests.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::randomClosedPortDelay): Move the delay
calculation here to be shared between the different code paths.
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkSocketStream.cpp:
(WebKit::NetworkSocketStream::didFailSocketStream): Use the shared
delay.
(WebKit::randomDelay): Deleted.
* NetworkProcess/soup/WebSocketTaskSoup.cpp:
(WebKit::WebSocketTask::WebSocketTask): Add a oneShot timer with
random duration when failing to connect to something that is not a
WebSocket.
(WebKit::WebSocketTask::delayFailTimerFired):

LayoutTests:

Add glib-specific baseline due to SOUP messages.

* platform/glib/TestExpectations:
* platform/glib/http/tests/websocket/tests/hybi/closed-port-delay-expected.txt: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (264393 => 264394)


--- trunk/LayoutTests/ChangeLog	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/LayoutTests/ChangeLog	2020-07-15 13:48:26 UTC (rev 264394)
@@ -1,3 +1,15 @@
+2020-07-15  Lauro Moura  <lmo...@igalia.com>
+
+        [SOUP] Artificial delay to WebSocket connection to mitigate port scanning attacks
+        https://bugs.webkit.org/show_bug.cgi?id=214293
+
+        Reviewed by Carlos Garcia Campos.
+
+        Add glib-specific baseline due to SOUP messages.
+
+        * platform/glib/TestExpectations:
+        * platform/glib/http/tests/websocket/tests/hybi/closed-port-delay-expected.txt: Added.
+
 2020-07-15  Alicia Boya GarcĂ­a  <ab...@igalia.com>
 
         [MSE][GStreamer] Unreviewed micro gardening: imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-negative.html

Modified: trunk/LayoutTests/platform/glib/TestExpectations (264393 => 264394)


--- trunk/LayoutTests/platform/glib/TestExpectations	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/LayoutTests/platform/glib/TestExpectations	2020-07-15 13:48:26 UTC (rev 264394)
@@ -362,8 +362,6 @@
 # SOUP-related bugs
 #////////////////////////////////////////////////////////////////////////////////////////
 
-webkit.org/b/214293 http/tests/websocket/tests/hybi/closed-port-delay.html [ Failure ]
-
 #////////////////////////////////////////////////////////////////////////////////////////
 # End of SOUP-related bugs
 #////////////////////////////////////////////////////////////////////////////////////////

Added: trunk/LayoutTests/platform/glib/http/tests/websocket/tests/hybi/closed-port-delay-expected.txt (0 => 264394)


--- trunk/LayoutTests/platform/glib/http/tests/websocket/tests/hybi/closed-port-delay-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/glib/http/tests/websocket/tests/hybi/closed-port-delay-expected.txt	2020-07-15 13:48:26 UTC (rev 264394)
@@ -0,0 +1,13 @@
+CONSOLE MESSAGE: The server did not accept the WebSocket handshake.
+CONSOLE MESSAGE: The server did not accept the WebSocket handshake.
+CONSOLE MESSAGE: The server did not accept the WebSocket handshake.
+Tests that WebSocket close report is delayed to mitigate port scanning attacks.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Successfully delayed reporting of closed WebSocket connection
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Modified: trunk/Source/WebKit/ChangeLog (264393 => 264394)


--- trunk/Source/WebKit/ChangeLog	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/Source/WebKit/ChangeLog	2020-07-15 13:48:26 UTC (rev 264394)
@@ -1,3 +1,34 @@
+2020-07-15  Lauro Moura  <lmo...@igalia.com>
+
+        [SOUP] Artificial delay to WebSocket connection to mitigate port scanning attacks
+        https://bugs.webkit.org/show_bug.cgi?id=214293
+
+        Reviewed by Carlos Garcia Campos.
+
+        r264306 added an artificial delay when NetworkSocketStream closed due
+        to closed ports but Soup-based ports use another code path and were
+        still returning immediately.
+
+        SOUP WebSocket errors do not distinguish closed ports separately, so
+        this commit checks for connections that finished with NOT_WEBSOCKET
+        errors.
+
+        Covered by existing tests.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::randomClosedPortDelay): Move the delay
+        calculation here to be shared between the different code paths.
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkSocketStream.cpp:
+        (WebKit::NetworkSocketStream::didFailSocketStream): Use the shared
+        delay.
+        (WebKit::randomDelay): Deleted.
+        * NetworkProcess/soup/WebSocketTaskSoup.cpp:
+        (WebKit::WebSocketTask::WebSocketTask): Add a oneShot timer with
+        random duration when failing to connect to something that is not a
+        WebSocket.
+        (WebKit::WebSocketTask::delayFailTimerFired):
+
 2020-07-14  Per Arne Vollan  <pvol...@apple.com>
 
         [iOS] Add missing messages to message filter in WebContent sandbox

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (264393 => 264394)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2020-07-15 13:48:26 UTC (rev 264394)
@@ -2777,6 +2777,13 @@
     completionHandler();
 }
 
+static constexpr auto delayMax = 100_ms;
+static constexpr auto delayMin = 10_ms;
+Seconds NetworkProcess::randomClosedPortDelay()
+{
+    return delayMin + Seconds::fromMilliseconds(static_cast<double>(cryptographicallyRandomNumber())) % delayMax;
+}
+
 void NetworkProcess::hasAppBoundSession(PAL::SessionID sessionID, CompletionHandler<void(bool)>&& completionHandler) const
 {
     bool result = false;

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (264393 => 264394)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2020-07-15 13:48:26 UTC (rev 264394)
@@ -353,6 +353,8 @@
     void resetServiceWorkerFetchTimeoutForTesting(CompletionHandler<void()>&&);
     Seconds serviceWorkerFetchTimeout() const { return m_serviceWorkerFetchTimeout; }
 
+    static Seconds randomClosedPortDelay();
+
     void cookieAcceptPolicyChanged(WebCore::HTTPCookieAcceptPolicy);
     void hasAppBoundSession(PAL::SessionID, CompletionHandler<void(bool)>&&) const;
     void clearAppBoundSession(PAL::SessionID, CompletionHandler<void()>&&);

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp (264393 => 264394)


--- trunk/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp	2020-07-15 13:48:26 UTC (rev 264394)
@@ -103,15 +103,8 @@
     send(Messages::WebSocketStream::DidUpdateBufferedAmount(amount));
 }
 
-static constexpr auto delayMax = 100_ms;
-static constexpr auto delayMin = 10_ms;
 static constexpr auto closedPortErrorCode = 61;
 
-static Seconds randomDelay()
-{
-    return delayMin + Seconds::fromMilliseconds(static_cast<double>(cryptographicallyRandomNumber())) % delayMax;
-}
-
 void NetworkSocketStream::sendDelayedFailMessage()
 {
     send(Messages::WebSocketStream::DidFailSocketStream(m_closedPortError));
@@ -123,7 +116,7 @@
     
     if (error.errorCode() == closedPortErrorCode) {
         m_closedPortError = error;
-        m_delayFailTimer.startOneShot(randomDelay());
+        m_delayFailTimer.startOneShot(NetworkProcess::randomClosedPortDelay());
     } else
         send(Messages::WebSocketStream::DidFailSocketStream(error));
 }

Modified: trunk/Source/WebKit/NetworkProcess/soup/WebSocketTaskSoup.cpp (264393 => 264394)


--- trunk/Source/WebKit/NetworkProcess/soup/WebSocketTaskSoup.cpp	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/Source/WebKit/NetworkProcess/soup/WebSocketTaskSoup.cpp	2020-07-15 13:48:26 UTC (rev 264394)
@@ -32,6 +32,7 @@
 #include <WebCore/ResourceRequest.h>
 #include <WebCore/ResourceResponse.h>
 #include <WebCore/WebSocketChannel.h>
+#include <wtf/RunLoop.h>
 #include <wtf/glib/GUniquePtr.h>
 #include <wtf/text/StringBuilder.h>
 
@@ -41,6 +42,7 @@
     : m_channel(channel)
     , m_handshakeMessage(msg)
     , m_cancellable(adoptGRef(g_cancellable_new()))
+    , m_delayFailTimer(RunLoop::main(), this, &WebSocketTask::delayFailTimerFired)
 {
     auto protocolList = protocol.split(',');
     GUniquePtr<char*> protocols;
@@ -63,6 +65,14 @@
             if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
                 return;
             auto* task = static_cast<WebSocketTask*>(userData);
+            if (g_error_matches(error.get(), SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET)
+                && task->m_handshakeMessage
+                && (task->m_handshakeMessage->status_code == SOUP_STATUS_CANT_CONNECT
+                    || task->m_handshakeMessage->status_code == SOUP_STATUS_CANT_CONNECT_PROXY)) {
+                task->m_delayErrorMessage = String::fromUTF8(error->message);
+                task->m_delayFailTimer.startOneShot(NetworkProcess::randomClosedPortDelay());
+                return;
+            }
             if (connection)
                 task->didConnect(WTFMove(connection));
             else
@@ -240,4 +250,9 @@
 {
 }
 
+void WebSocketTask::delayFailTimerFired()
+{
+    didFail(m_delayErrorMessage);
+}
+
 } // namespace WebKit

Modified: trunk/Source/WebKit/NetworkProcess/soup/WebSocketTaskSoup.h (264393 => 264394)


--- trunk/Source/WebKit/NetworkProcess/soup/WebSocketTaskSoup.h	2020-07-15 13:05:02 UTC (rev 264393)
+++ trunk/Source/WebKit/NetworkProcess/soup/WebSocketTaskSoup.h	2020-07-15 13:48:26 UTC (rev 264394)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include <libsoup/soup.h>
+#include <wtf/RunLoop.h>
 #include <wtf/glib/GRefPtr.h>
 
 namespace IPC {
@@ -52,6 +53,7 @@
     void didConnect(GRefPtr<SoupWebsocketConnection>&&);
     void didFail(const String&);
     void didClose(unsigned short code, const String& reason);
+    void delayFailTimerFired();
 
     String acceptedExtensions() const;
 
@@ -65,6 +67,8 @@
     GRefPtr<GCancellable> m_cancellable;
     bool m_receivedDidFail { false };
     bool m_receivedDidClose { false };
+    String m_delayErrorMessage;
+    RunLoop::Timer<WebSocketTask> m_delayFailTimer;
 };
 
 } // namespace WebKit
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to