Skip to content

Commit 211ecfc

Browse files
fix(conn): detect and drop HTTP requests in connection (#2765)
Co-authored-by: hulk <[email protected]>
1 parent b8b969d commit 211ecfc

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/server/redis_connection.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,17 @@ void Connection::ExecuteCommands(std::deque<CommandTokens> *to_process_cmds) {
385385

386386
auto cmd_s = Server::LookupAndCreateCommand(cmd_tokens.front());
387387
if (!cmd_s.IsOK()) {
388+
auto cmd_name = cmd_tokens.front();
389+
if (util::EqualICase(cmd_name, "host:") || util::EqualICase(cmd_name, "post")) {
390+
LOG(WARNING) << "A likely HTTP request is detected in the RESP connection, indicating a potential "
391+
"Cross-Protocol Scripting attack. Connection aborted.";
392+
EnableFlag(kCloseAsync);
393+
return;
394+
}
388395
if (is_multi_exec) multi_error_ = true;
389396
Reply(redis::Error(
390397
{Status::NotOK,
391-
fmt::format("unknown command `{}`, with args beginning with: {}", cmd_tokens.front(),
398+
fmt::format("unknown command `{}`, with args beginning with: {}", cmd_name,
392399
util::StringJoin(nonstd::span(cmd_tokens.begin() + 1, cmd_tokens.end()),
393400
[](const auto &v) -> decltype(auto) { return fmt::format("`{}`", v); }))}));
394401
continue;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package connection
21+
22+
import (
23+
"fmt"
24+
"net/http"
25+
"testing"
26+
27+
"github.com/apache/kvrocks/tests/gocase/util"
28+
"github.com/stretchr/testify/require"
29+
)
30+
31+
func TestConnection(t *testing.T) {
32+
srv := util.StartServer(t, map[string]string{})
33+
defer srv.Close()
34+
35+
t.Run("HTTP requests will be dropped", func(t *testing.T) {
36+
_, err := http.Get(fmt.Sprintf("http://%s", srv.HostPort())) //nolint:bodyclose
37+
require.Error(t, err)
38+
require.True(t, srv.LogFileMatches(t, "HTTP request.*Connection aborted"), "should contain HTTP drop log")
39+
40+
c := srv.NewTCPClient()
41+
err = c.Write("GET / HTTP/1.1\r\nHOST: example.com\r\n")
42+
require.NoError(t, err)
43+
_, err = c.ReadLine()
44+
require.Error(t, err)
45+
})
46+
}

0 commit comments

Comments
 (0)