Skip to content

Commit eccd3d0

Browse files
committed
[FIXED] Check of maxpayload could be bypassed if size overruns int32
One could craft a PUB protocol to cause server to panic. This can happen if the size in the PUB protocol overruns an int32. (note that if authorization is enabled, the user would need to authenticate first, limiting the impact). Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
1 parent e83e0a7 commit eccd3d0

3 files changed

Lines changed: 29 additions & 2 deletions

File tree

server/client.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1567,11 +1567,13 @@ func (c *client) processPub(trace bool, arg []byte) error {
15671567
default:
15681568
return fmt.Errorf("processPub Parse Error: '%s'", arg)
15691569
}
1570+
// If number overruns an int64, parseSize() will have returned a negative value
15701571
if c.pa.size < 0 {
15711572
return fmt.Errorf("processPub Bad or Missing Size: '%s'", arg)
15721573
}
15731574
maxPayload := atomic.LoadInt32(&c.mpay)
1574-
if maxPayload != jwt.NoLimit && int32(c.pa.size) > maxPayload {
1575+
// Use int64() to avoid int32 overrun...
1576+
if maxPayload != jwt.NoLimit && int64(c.pa.size) > int64(maxPayload) {
15751577
c.maxPayloadViolation(c.pa.size, maxPayload)
15761578
return ErrMaxPayload
15771579
}

server/leafnode.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ func (c *client) processLeafMsgArgs(trace bool, arg []byte) error {
11931193
}
11941194
}
11951195
if c.pa.size < 0 {
1196-
return fmt.Errorf("processRoutedMsgArgs Bad or Missing Size: '%s'", args)
1196+
return fmt.Errorf("processLeafMsgArgs Bad or Missing Size: '%s'", args)
11971197
}
11981198

11991199
// Common ones processed after check for arg length

test/maxpayload_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,28 @@ func TestMaxPayload(t *testing.T) {
9797
}
9898
}
9999
}
100+
101+
func TestMaxPayloadOverrun(t *testing.T) {
102+
opts := DefaultTestOptions
103+
opts.Port = -1
104+
opts.MaxPayload = 10000
105+
s := RunServer(&opts)
106+
defer s.Shutdown()
107+
108+
// Overrun a int32
109+
c := createClientConn(t, "127.0.0.1", opts.Port)
110+
defer c.Close()
111+
112+
send, expect := setupConn(t, c)
113+
send("PUB foo 380571791000988\r\n")
114+
expect(errRe)
115+
116+
// Now overrun an int64, parseSize will have returned -1,
117+
// so we get disconnected.
118+
c = createClientConn(t, "127.0.0.1", opts.Port)
119+
defer c.Close()
120+
121+
send, _ = setupConn(t, c)
122+
send("PUB foo 18446744073709551615123\r\n")
123+
expectDisconnect(t, c)
124+
}

0 commit comments

Comments
 (0)