4 ms·
Indeed - this is one of the positives of Go, as all the dependencies get linked statically, giving nice portable "single binary" solutions. Grepping function n
by g_p 4y ago
Indeed - this is one of the positives of Go, as all the dependencies get linked statically, giving nice portable "single binary" solutions.
Grepping function names seems a reasonable approach, as long as you're not trying to detect something that is obfuscating its use of libssl (i.e. by mangling strings together).
It appears if you strip a binary, any definitive information about the libraries linked in statically is lost, beyond function names and argument combinations. I believe there are tools in IDA and similar, which can match functions based on their input argument types and name. That might help you match to a rough version of the upstream library, if parameters changed.
- tremon 4y agoUnsure why people keep referring to static linking as a positive in this thread? Downstream consumers of statically-linked binaries have no practical way to scan their systems for known-vulnerable versions of libraries, that seems a profoundly negative consequence to me.
- iso1631 4y agoIndeed, there are certainly good reasons to statically link programs, but this type of security issue is the complete opposite, it's a known drawback that you may accept in exchange for the other benefits of static linking
- Beltalowda 4y agoIn Go you can use "go version -m my-go-binary" and get a list of dependencies and other build information. For example (may wrap a bit ugly on HN): [~]% go version -m =godoc /home/belta/bin/godoc: go1.18.3 path golang.org/x/tools/cmd/godoc mod golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= dep github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= dep golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= dep golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= dep golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= build -compiler=gc build CGO_ENABLED=0 build GOARCH=amd64 build GOOS=linux build GOAMD64=v1 So scanning your binaries, if you want, is fairly easy. Other than that, this is the "Great Static vs. Dynamic Linking Debate", which has been done quite a few times. I have little desire to repeat it, but both approaches have their advantages and downsides, and with good tooling (like the above) I think many downsides of static linking can be managed quite well.
- tremon 4y agoThat's a great solution, actually. I'm not familiar with go, but I thought it compiled to native code and did not require a virtual machine at runtime. So is this metadata enforced/inserted by the compiler into the binary, or does it require specific build tooling that may or may not be available on end-user systems?
- Beltalowda 4y agoThe compiler adds it in the .go.buildinfo section; something like "objdump -sj .go.buildinfo" should also display it, kind of, but it needs a bit more parsing to display well. You need some tooling, but it's not horribly complex, and I think some kind of tooling would be unavoidable anyway. I think there's a lot of potential for better tooling here in the form of language support, package manager support, etc.
- wlonkly 4y agoUnfortunately that shows the Go libraries involved, but not the C libraries those Go libraries depend on (right?). So that might tell me that a Go program includes 'crypto', but not whether or not that 'crypto' linked in OpenSSL 1.1.1 or OpenSSL 3.x. So the static linking dependency analysis problem remains.
- Beltalowda 4y agocgo stuff gets dynamically linked by default, although you can link it statically (usually); the OpenSSL bindings for Go seem to support it, but almost no one uses these[1]. You're right that these don't show up, but in practice it's mostly a non-issue for the most part as cgo isn't used that often and purely statically linked cgo even less so, and when it is it's often in the form of e.g. go-sqlite3 where the SQLite version is tied to the module version. The problem is that "static linking" means "grab whatever is in /usr/lib/libfoo.a, whatever that may be". I'm not sure if there is a good way to solve this in a generic way that works everywhere, outside of keeping track of sums. [1]: https://pkg.go.dev/github.com/spacemonkeygo/openssl?tab=importedby https://pkg.go.dev/github.com/spacemonkeygo/openssl?tab=impo...