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

debug/macho: panic on invalid dynamic symbol table command with overflowing #49792

Open
And-ZJ opened this issue Nov 25, 2021 · 2 comments
Open
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@And-ZJ
Copy link
Contributor

And-ZJ commented Nov 25, 2021

These days I'm learning how to fix this vulnerability CVE-2021-41771 at issue #48990 and CL355990.

I noticed that the variables hdr.Iundefsym and hdr.Nundefsym are read directly from the macho executable.

Therefore, based on the existing test files, I constructed a new test file, where hdr.Iundefsym=9, hdr.Nundefsym=0xFF_FF_FF_FF, the overflow after addition is 8, but uint32(len(f.Symtab.Syms))==11.

The judgment condition hdr.Iundefsym+hdr.Nundefsym > uint32(len(f.Symtab.Syms)) in the CL355990 can be bypassed due to integer addition overflow.

Therefore, panic will still occur when calling ImportedSymbols() method.

This seems to be the same level of security problem as CVE-2021-41771.

The new test file was provided in this zip file:
testdata.zip

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

$ go version
go version go1.17.3 windows/amd64

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\ZJ\AppData\Local\go-build
set GOENV=C:\Users\ZJ\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=E:\Code\Go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=E:\Code\Go
set GOPRIVATE=
set GOPROXY=https://goproxy.cn
set GOROOT=E:\Code\Go\go\go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=E:\Code\Go\go\go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.16.4
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=E:\Code\Go\go\go\src\go.mod
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -fmessage-length=0 -fdebug-prefix-map=C:\Users\ZJ\AppData\Local\Temp\go-build488652189=/tmp/go-bui
ld -gno-record-gcc-switches

What did you do?

Use the newly constructed test file and run the test in the debug/macho Directory:

func TestOpenBadDysymCmd2(t *testing.T) {
	f, err := openObscured("testdata/gcc-amd64-darwin-exec-with-bad-dysym-2.base64")
	if err == nil {
		f.ImportedSymbols()
		return
	}
	if _, ok := err.(*FormatError); !ok {
		t.Fatalf("opening invalid dynamic symbol table command file got %v, want FormatError", err)
	}
}

What did you expect to see?

Test PASS

What did you see instead?

panic: runtime error: slice bounds out of range [9:8] [recovered]
        panic: runtime error: slice bounds out of range [9:8]

goroutine 6 [running]:
testing.tRunner.func1.2({0x52c5a0, 0xc0000142b8})
        E:/Code/Go/go/go/src/testing/testing.go:1209 +0x24e
testing.tRunner.func1()
        E:/Code/Go/go/go/src/testing/testing.go:1212 +0x218
panic({0x52c5a0, 0xc0000142b8})
        E:/Code/Go/go/go/src/runtime/panic.go:1038 +0x215
debug/macho.(*File).ImportedSymbols(0x543ab6)
        E:/Code/Go/go/go/src/debug/macho/file.go:685 +0x1cb
debug/macho.TestOpenBadDysymCmd2(0xc00002fba0)
        E:/Code/Go/go/go/src/debug/macho/file_test.go:440 +0x8c
testing.tRunner(0xc00002fba0, 0x5454e0)
        E:/Code/Go/go/go/src/testing/testing.go:1259 +0x102
created by testing.(*T).Run
        E:/Code/Go/go/go/src/testing/testing.go:1306 +0x35a
@gopherbot
Copy link

Change https://golang.org/cl/367075 mentions this issue: debug/macho: prevent overflowing on invalid dynamic symbol table command

@And-ZJ
Copy link
Contributor Author

And-ZJ commented Nov 25, 2021

In CL367075, two test files are added to cover each check condition.

file hdr.Iundefsym hdr.Nundefsym
gcc-amd64-darwin-exec-with-bad-dysym.base64 9 0xFF
gcc-amd64-darwin-exec-with-bad-dysym-2.base64 (new) 9 0xFF_FF_FF_FF
gcc-amd64-darwin-exec-with-bad-dysym-3.base64 (new) 12 0xFF

Print the err variable in the test case to verify that the three cases are covered.

=== RUN   TestOpenBadDysymCmd
    file_test.go:434: number of undefined symbols after index in dynamic symbol table command is greater than symbol table length (264 > 11) in record at byte 0x428
    file_test.go:434: number of undefined symbols after index in dynamic symbol table command is overflow (9 + 4294967295) in record at byte 0x428
    file_test.go:434: undefined symbols index in dynamic symbol table command is greater than symbol table length (12 > 11) in record at byte 0x428
--- PASS: TestOpenBadDysymCmd (0.00s)
PASS

@seankhliao seankhliao added the NeedsFix The path to resolution is known, but the work has not been done. label Nov 25, 2021
@seankhliao seankhliao added this to the Unplanned milestone Aug 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

3 participants