Hacker News new | ask | show | jobs
by g_p 1330 days 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.

1 comments

Unsure 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.
In 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.

That'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?
The 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.

Unfortunately 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.

cgo 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=impo...

Indeed, 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