70 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 71be97294abf3657710a044157ebbc8a21489da3 Mon Sep 17 00:00:00 2001
 | |
| From: Oran Agra <oran@redislabs.com>
 | |
| Date: Wed, 9 Jun 2021 17:31:39 +0300
 | |
| Subject: [PATCH] Prevent unauthenticated client from easily consuming lots of
 | |
|  memory (CVE-2021-32675)
 | |
| 
 | |
| This change sets a low limit for multibulk and bulk length in the
 | |
| protocol for unauthenticated connections, so that they can't easily
 | |
| cause redis to allocate massive amounts of memory by sending just a few
 | |
| characters on the network.
 | |
| The new limits are 10 arguments of 16kb each (instead of 1m of 512mb)
 | |
| 
 | |
| (cherry picked from commit 3d221e81f3b680543e34942579af190b049ff283)
 | |
| ---
 | |
|  src/networking.c    |  8 ++++++++
 | |
|  tests/unit/auth.tcl | 16 ++++++++++++++++
 | |
|  2 files changed, 24 insertions(+)
 | |
| 
 | |
| diff --git a/src/networking.c b/src/networking.c
 | |
| index bfaded9b4d0..2b8588094d2 100644
 | |
| --- a/src/networking.c
 | |
| +++ b/src/networking.c
 | |
| @@ -1309,6 +1309,10 @@ int processMultibulkBuffer(client *c) {
 | |
|              addReplyError(c,"Protocol error: invalid multibulk length");
 | |
|              setProtocolError("invalid mbulk count",c);
 | |
|              return C_ERR;
 | |
| +        } else if (ll > 10 && server.requirepass && !c->authenticated) {
 | |
| +            addReplyError(c, "Protocol error: unauthenticated multibulk length");
 | |
| +            setProtocolError("unauth mbulk count", c);
 | |
| +            return C_ERR;
 | |
|          }
 | |
|  
 | |
|          c->qb_pos = (newline-c->querybuf)+2;
 | |
| @@ -1354,6 +1358,10 @@ int processMultibulkBuffer(client *c) {
 | |
|                  addReplyError(c,"Protocol error: invalid bulk length");
 | |
|                  setProtocolError("invalid bulk length",c);
 | |
|                  return C_ERR;
 | |
| +            } else if (ll > 16384 && server.requirepass && !c->authenticated) {
 | |
| +                addReplyError(c, "Protocol error: unauthenticated bulk length");
 | |
| +                setProtocolError("unauth bulk length", c);
 | |
| +                return C_ERR;
 | |
|              }
 | |
|  
 | |
|              c->qb_pos = newline-c->querybuf+2;
 | |
| diff --git a/tests/unit/auth.tcl b/tests/unit/auth.tcl
 | |
| index 633cda95c92..f5da728e845 100644
 | |
| --- a/tests/unit/auth.tcl
 | |
| +++ b/tests/unit/auth.tcl
 | |
| @@ -24,4 +24,20 @@ start_server {tags {"auth"} overrides {requirepass foobar}} {
 | |
|          r set foo 100
 | |
|          r incr foo
 | |
|      } {101}
 | |
| +
 | |
| +    test {For unauthenticated clients multibulk and bulk length are limited} {
 | |
| +        set rr [redis [srv "host"] [srv "port"] 0]
 | |
| +        $rr write "*100\r\n"
 | |
| +        $rr flush
 | |
| +        catch {[$rr read]} e
 | |
| +        assert_match {*unauthenticated multibulk length*} $e
 | |
| +        $rr close
 | |
| +
 | |
| +        set rr [redis [srv "host"] [srv "port"] 0]
 | |
| +        $rr write "*1\r\n\$100000000\r\n"
 | |
| +        $rr flush
 | |
| +        catch {[$rr read]} e
 | |
| +        assert_match {*unauthenticated bulk length*} $e
 | |
| +        $rr close
 | |
| +    }
 | |
|  }
 |