Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploitable DoS Condition in Golang Hashmap #41674

Closed
TheRook opened this issue Sep 28, 2020 · 3 comments
Closed

Exploitable DoS Condition in Golang Hashmap #41674

TheRook opened this issue Sep 28, 2020 · 3 comments

Comments

@TheRook
Copy link

@TheRook TheRook commented Sep 28, 2020

What version of Go are you using (go version)?

go version go1.14.6 linux/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
GO111MODULE=""
GOARCH="amd64"
GOBIN="/home/mike/golang/go/bin"
GOCACHE="/home/mike/.cache/go-build"
GOENV="/home/mike/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/mike/golang"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/mike/golang/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/mike/golang/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build421285071=/tmp/go-build -gno-record-gcc-switches"

What did you do?

We used hashmap in a legitimate way that on any language would be a TOCTOU-oddity that would not be exploitable in any way. The key in the hashmap isn't attacker controlled so there is no exploitable condition in concurrent access, also as a penetration tester I can tell you first hand that TOCTOU issues are not commonly exploited in the wild. However, the exploitable condition is that concurrent hashmap access is detected at runtime but not kept internally consistent.

A hacker revealed an exploitable condition in Golang Hashmap that only occurs at runtime. It appears as though golang has a bit of an allergy and dramatically overreacts. It is interesting that Golang has concurrency detection routine, but instead of using this lock to help - it was used to introduce instability into the runtime application.

DoS conditions are quite valuable to an attacker, and ARE exploited in the wild. Think about it, a pentester or other adversary needs to know a lot about an application to exploit a TOCTOU - but only needs to know one thing to exploit a DoS condition.

An adversary can force two goroutines accessing the same hashmap at the same time to produce the following error:

fatal error: concurrent map read and map write

goroutine 1 [running]:
runtime.throw(0x747ebe, 0x21)
/home/mike/golang/go/src/runtime/panic.go:1116 +0x72 fp=0xc000173850 sp=0xc000173820 pc=0x433fd2
runtime.mapaccess2(0x6e5a20, 0xc0000a63c0, 0xc0001738c8, 0x0, 0x0)
/home/mike/golang/go/src/runtime/map.go:469 +0x258 fp=0xc000173890 sp=0xc000173850 pc=0x40fdd8
main.connectionUpdate(0xc0000a63c0, 0x22451acd, 0xd, 0xc000a13180, 0x4)
/home/mike/share/Niagara/tcp.go:38 +0x5a fp=0xc000173900 sp=0xc000173890 pc=0x5b7a2a
main.Arroyo(0xc0000a63c0, 0x78b1c0, 0xc000122058, 0xc0001241e0, 0xc000124240, 0xc00008e052, 0x5, 0x208d, 0x64, 0xc0009f6080, ...)
/home/mike/share/Niagara/main.go:482 +0x1e0c fp=0xc000173c28 sp=0xc000173900 pc=0x5b63ec
main.main()

fatal error: concurrent map read and map write

goroutine 1 [running]:
runtime.throw(0x747ebe, 0x21)
/home/mike/golang/go/src/runtime/panic.go:1116 +0x72 fp=0xc000173850 sp=0xc000173820 pc=0x433fd2
runtime.mapaccess2(0x6e5a20, 0xc0000a63c0, 0xc0001738c8, 0x0, 0x0)
/home/mike/golang/go/src/runtime/map.go:469 +0x258 fp=0xc000173890 sp=0xc000173850 pc=0x40fdd8
main.connectionUpdate(0xc0000a63c0, 0x22451acd, 0xd, 0xc000a13180, 0x4)
/home/mike/share/Niagara/tcp.go:38 +0x5a fp=0xc000173900 sp=0xc000173890 pc=0x5b7a2a
main.Arroyo(0xc0000a63c0, 0x78b1c0, 0xc000122058, 0xc0001241e0, 0xc000124240, 0xc00008e052, 0x5, 0x208d, 0x64, 0xc0009f6080, ...)
/home/mike/share/Niagara/main.go:482 +0x1e0c fp=0xc000173c28 sp=0xc000173900 pc=0x5b63ec
main.main()

What did you expect to see?

For my application to run.

As a user I need my intentions honored, and my application to function without committing suicide in production. If you have a mutex to detect TOCTOU issues - then you can take out this lock on access. Killing the application as a mistaken effort to avoid a class of vulnerabilities that is uncommon and difficult to exploit is most unfortunate.

This bug got upgraded from nothing to a critical-risk DoS.

What did you see instead?

An exploitable DoS condition, plain and simple. Linus Torvalds has a good point about preserving the user intention and this is the central point of his impassioned posts. As a golang user who doesn't have someone like Torvalds on my side to fight for my wellbeing, I feel like I'm being utterly trolled by a uncaring platform.

@seankhliao
Copy link
Contributor

@seankhliao seankhliao commented Sep 28, 2020

fatal error: concurrent map read and map write

go maps are not safe for concurrent use, use a lock or other synchronization primitive

see https://golang.org/doc/faq#atomic_maps

@randall77
Copy link
Contributor

@randall77 randall77 commented Sep 28, 2020

Killing the application on a racy access to a map is intentional. It's not to avoid TOCTOU issues. That's up to the application. It's because concurrent access can lead to a corrupted internal state; see #13062 for an example. We'd rather have the application crash with a sensible error like "concurrent map read and map write" instead of something nonsensical like "runtime: unexpected fault address" somewhere deep in the map implementation.

@davecheney
Copy link
Contributor

@davecheney davecheney commented Sep 28, 2020

A go application with a race condition is considered to contain undefined behaviour and proper execution is not guarantee.

Have you tried running your program under the race detector? See https://blog.golang.org/race-detector .

Closing as answered.

@davecheney davecheney closed this Sep 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.