From e4af91516fb4fb52e2dd5c8c7439f4c49835eb5a Mon Sep 17 00:00:00 2001 From: Henry Barreto Date: Mon, 2 Dec 2024 18:11:21 -0300 Subject: [PATCH] chore(agent,pkg): migrate from libxcrypt to yescrypt-go --- agent/Dockerfile | 11 +--- agent/Dockerfile.amd64 | 10 +--- agent/Dockerfile.arm32v6 | 10 +--- agent/Dockerfile.arm32v7 | 10 +--- agent/Dockerfile.arm64v8 | 10 +--- agent/Dockerfile.i386 | 10 +--- agent/Dockerfile.test | 11 +--- agent/go.mod | 3 +- agent/go.sum | 2 + api/go.mod | 2 +- cli/go.mod | 2 +- go.mod | 3 +- pkg/agent/pkg/yescrypt/yescript.go | 26 ---------- pkg/agent/pkg/yescrypt/yescrypt.go | 18 +++++++ pkg/agent/pkg/yescrypt/yescrypt_test.go | 68 +++++++++++++++++++++++++ ssh/go.mod | 2 +- tests/go.mod | 2 +- 17 files changed, 103 insertions(+), 97 deletions(-) delete mode 100644 pkg/agent/pkg/yescrypt/yescript.go create mode 100644 pkg/agent/pkg/yescrypt/yescrypt.go create mode 100644 pkg/agent/pkg/yescrypt/yescrypt_test.go diff --git a/agent/Dockerfile b/agent/Dockerfile index 6c2b540bac6..ae2730e9abc 100644 --- a/agent/Dockerfile +++ b/agent/Dockerfile @@ -3,16 +3,7 @@ FROM golang:1.22.6-alpine3.19 AS base ARG GOPROXY -RUN apk add --update git ca-certificates build-base bash util-linux setpriv perl xz linux-headers - -# We are using libxcrypt to support yescrypt password hashing method -# Since libxcrypt package is not available in Alpine, so we need to build libxcrypt from source code -RUN wget -q https://github.com/besser82/libxcrypt/releases/download/v4.4.36/libxcrypt-4.4.36.tar.xz && \ - tar xvf libxcrypt-4.4.36.tar.xz && cd libxcrypt-4.4.36 && \ - ./configure --prefix /usr && make -j$(nproc) && make install && \ - cd .. && rm -rf libxcrypt-4.4.36* - -RUN ln -sf /bin/bash /bin/sh +RUN apk add --update ca-certificates util-linux setpriv WORKDIR $GOPATH/src/github.com/shellhub-io/shellhub diff --git a/agent/Dockerfile.amd64 b/agent/Dockerfile.amd64 index a452ed2e200..c0bc019ec63 100644 --- a/agent/Dockerfile.amd64 +++ b/agent/Dockerfile.amd64 @@ -2,14 +2,7 @@ FROM golang:1.22.6-alpine3.19 ARG SHELLHUB_VERSION=latest -RUN apk add --update git ca-certificates util-linux build-base bash setpriv perl xz linux-headers - -# We are using libxcrypt to support yescrypt password hashing method -# Since libxcrypt package is not available in Alpine, so we need to build libxcrypt from source code -RUN wget -q https://github.com/besser82/libxcrypt/releases/download/v4.4.36/libxcrypt-4.4.36.tar.xz && \ - tar xvf libxcrypt-4.4.36.tar.xz && cd libxcrypt-4.4.36 && \ - ./configure --prefix /usr && make -j$(nproc) && make install && \ - cd .. && rm -rf libxcrypt-4.4.36* +RUN apk add --update ca-certificates util-linux setpriv WORKDIR $GOPATH/src/github.com/shellhub-io/shellhub @@ -37,7 +30,6 @@ COPY --from=0 /usr/bin/nsenter /usr/bin/ COPY --from=0 /usr/bin/setpriv /usr/bin/ COPY --from=0 /usr/lib/libcap-ng.so.* /usr/lib/ COPY --from=0 /lib/ld-musl-x86_64.so.1 /lib/ -COPY --from=0 /usr/lib/libcrypt.so* /usr/lib/ COPY --from=0 /go/src/github.com/shellhub-io/shellhub/agent/agent /bin/agent ENTRYPOINT ["/bin/agent"] diff --git a/agent/Dockerfile.arm32v6 b/agent/Dockerfile.arm32v6 index cd916271c55..b1e3186ef4e 100644 --- a/agent/Dockerfile.arm32v6 +++ b/agent/Dockerfile.arm32v6 @@ -4,14 +4,7 @@ FROM arm32v6/golang:1.22.6-alpine3.19 ARG SHELLHUB_VERSION=latest -RUN apk add --update git ca-certificates util-linux build-base bash setpriv perl xz linux-headers - -# We are using libxcrypt to support yescrypt password hashing method -# Since libxcrypt package is not available in Alpine, so we need to build libxcrypt from source code -RUN wget -q https://github.com/besser82/libxcrypt/releases/download/v4.4.36/libxcrypt-4.4.36.tar.xz && \ - tar xvf libxcrypt-4.4.36.tar.xz && cd libxcrypt-4.4.36 && \ - ./configure --prefix /usr && make -j$(nproc) && make install && \ - cd .. && rm -rf libxcrypt-4.4.36* +RUN apk add --update ca-certificates util-linux setpriv WORKDIR $GOPATH/src/github.com/shellhub-io/shellhub @@ -39,7 +32,6 @@ COPY --from=0 /usr/bin/nsenter /usr/bin/ COPY --from=0 /usr/bin/setpriv /usr/bin/ COPY --from=0 /usr/lib/libcap-ng.so.* /usr/lib/ COPY --from=0 /lib/ld-musl-armhf.so.1 /lib/ -COPY --from=0 /usr/lib/libcrypt.so* /usr/lib/ COPY --from=0 /go/src/github.com/shellhub-io/shellhub/agent/agent /bin/agent ENTRYPOINT ["/bin/agent"] diff --git a/agent/Dockerfile.arm32v7 b/agent/Dockerfile.arm32v7 index 66f9af65f43..63b195965c2 100644 --- a/agent/Dockerfile.arm32v7 +++ b/agent/Dockerfile.arm32v7 @@ -4,14 +4,7 @@ FROM arm32v7/golang:1.22.6-alpine3.19 ARG SHELLHUB_VERSION=latest -RUN apk add --update git ca-certificates util-linux build-base bash setpriv perl xz linux-headers - -# We are using libxcrypt to support yescrypt password hashing method -# Since libxcrypt package is not available in Alpine, so we need to build libxcrypt from source code -RUN wget -q https://github.com/besser82/libxcrypt/releases/download/v4.4.36/libxcrypt-4.4.36.tar.xz && \ - tar xvf libxcrypt-4.4.36.tar.xz && cd libxcrypt-4.4.36 && \ - ./configure --prefix /usr && make -j$(nproc) && make install && \ - cd .. && rm -rf libxcrypt-4.4.36* +RUN apk add --update ca-certificates util-linux setpriv WORKDIR $GOPATH/src/github.com/shellhub-io/shellhub @@ -39,7 +32,6 @@ COPY --from=0 /usr/bin/nsenter /usr/bin/ COPY --from=0 /usr/bin/setpriv /usr/bin/ COPY --from=0 /usr/lib/libcap-ng.so.* /usr/lib/ COPY --from=0 /lib/ld-musl-armhf.so.1 /lib/ -COPY --from=0 /usr/lib/libcrypt.so* /usr/lib/ COPY --from=0 /go/src/github.com/shellhub-io/shellhub/agent/agent /bin/agent ENTRYPOINT ["/bin/agent"] diff --git a/agent/Dockerfile.arm64v8 b/agent/Dockerfile.arm64v8 index a72568cb51d..ae4dfd256b6 100644 --- a/agent/Dockerfile.arm64v8 +++ b/agent/Dockerfile.arm64v8 @@ -4,14 +4,7 @@ FROM arm64v8/golang:1.22.6-alpine3.19 ARG SHELLHUB_VERSION=latest -RUN apk add --update git ca-certificates util-linux build-base bash setpriv perl xz linux-headers - -# We are using libxcrypt to support yescrypt password hashing method -# Since libxcrypt package is not available in Alpine, so we need to build libxcrypt from source code -RUN wget -q https://github.com/besser82/libxcrypt/releases/download/v4.4.36/libxcrypt-4.4.36.tar.xz && \ - tar xvf libxcrypt-4.4.36.tar.xz && cd libxcrypt-4.4.36 && \ - ./configure --prefix /usr && make -j$(nproc) && make install && \ - cd .. && rm -rf libxcrypt-4.4.36* +RUN apk add --update ca-certificates util-linux setpriv WORKDIR $GOPATH/src/github.com/shellhub-io/shellhub @@ -39,7 +32,6 @@ COPY --from=0 /usr/bin/nsenter /usr/bin/ COPY --from=0 /usr/bin/setpriv /usr/bin/ COPY --from=0 /usr/lib/libcap-ng.so.* /usr/lib/ COPY --from=0 /lib/ld-musl-aarch64.so.1 /lib/ -COPY --from=0 /usr/lib/libcrypt.so* /usr/lib/ COPY --from=0 /go/src/github.com/shellhub-io/shellhub/agent/agent /bin/agent ENTRYPOINT ["/bin/agent"] diff --git a/agent/Dockerfile.i386 b/agent/Dockerfile.i386 index 62d97728a51..c7cd3ee9376 100644 --- a/agent/Dockerfile.i386 +++ b/agent/Dockerfile.i386 @@ -2,14 +2,7 @@ FROM golang:1.22.6-alpine3.19 ARG SHELLHUB_VERSION=latest -RUN apk add --update git ca-certificates util-linux build-base bash setpriv perl xz linux-headers - -# We are using libxcrypt to support yescrypt password hashing method -# Since libxcrypt package is not available in Alpine, so we need to build libxcrypt from source code -RUN wget -q https://github.com/besser82/libxcrypt/releases/download/v4.4.36/libxcrypt-4.4.36.tar.xz && \ - tar xvf libxcrypt-4.4.36.tar.xz && cd libxcrypt-4.4.36 && \ - ./configure --prefix /usr && make -j$(nproc) && make install && \ - cd .. && rm -rf libxcrypt-4.4.36* +RUN apk add --update ca-certificates util-linux setpriv WORKDIR $GOPATH/src/github.com/shellhub-io/shellhub @@ -37,7 +30,6 @@ COPY --from=0 /usr/bin/nsenter /usr/bin/ COPY --from=0 /usr/bin/setpriv /usr/bin/ COPY --from=0 /usr/lib/libcap-ng.so.* /usr/lib/ COPY --from=0 /lib/ld-musl-*.so.1 /lib/ -COPY --from=0 /usr/lib/libcrypt.so* /usr/lib/ COPY --from=0 /go/src/github.com/shellhub-io/shellhub/agent/agent /bin/agent ENTRYPOINT ["/bin/agent"] diff --git a/agent/Dockerfile.test b/agent/Dockerfile.test index bd15b67ddfe..00187c2863e 100644 --- a/agent/Dockerfile.test +++ b/agent/Dockerfile.test @@ -2,16 +2,7 @@ FROM golang:1.22.6-alpine3.19 ARG GOPROXY -RUN apk add --update git ca-certificates util-linux build-base bash setpriv perl xz linux-headers - -RUN apk add openssh - -# We are using libxcrypt to support yescrypt password hashing method -# Since libxcrypt package is not available in Alpine, so we need to build libxcrypt from source code -RUN wget -q https://github.com/besser82/libxcrypt/releases/download/v4.4.36/libxcrypt-4.4.36.tar.xz && \ - tar xvf libxcrypt-4.4.36.tar.xz && cd libxcrypt-4.4.36 && \ - ./configure --prefix /usr && make -j$(nproc) && make install && \ - cd .. && rm -rf libxcrypt-4.4.36* +RUN apk add --update ca-certificates util-linux setpriv bash openssh RUN ln -sf /bin/bash /bin/sh diff --git a/agent/go.mod b/agent/go.mod index 1cf717de022..4619bbdefc1 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -1,6 +1,6 @@ module github.com/shellhub-io/shellhub/agent -go 1.21 +go 1.22.4 require ( github.com/Masterminds/semver v1.5.0 @@ -45,6 +45,7 @@ require ( github.com/moby/docker-image-spec v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/openwall/yescrypt-go v1.0.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/sftp v1.13.5 // indirect github.com/sethvargo/go-envconfig v0.9.0 // indirect diff --git a/agent/go.sum b/agent/go.sum index 8bf3791048c..a7eb5e3a2ef 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -84,6 +84,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/openwall/yescrypt-go v1.0.0 h1:jsGk48zkFvtUjGVOhYPGh+CS595JmTRcKnpggK2AON4= +github.com/openwall/yescrypt-go v1.0.0/go.mod h1:e6CWtFizUEOUttaOjeVMiv1lJaJie3mfOtLJ9CCD6sA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go= diff --git a/api/go.mod b/api/go.mod index 807c50dff57..6984e439fb6 100644 --- a/api/go.mod +++ b/api/go.mod @@ -1,6 +1,6 @@ module github.com/shellhub-io/shellhub/api -go 1.22 +go 1.22.4 toolchain go1.22.5 diff --git a/cli/go.mod b/cli/go.mod index bb8380bf06f..6742ac2de88 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -1,6 +1,6 @@ module github.com/shellhub-io/shellhub/cli -go 1.22 +go 1.22.4 toolchain go1.22.8 diff --git a/go.mod b/go.mod index 9f418fec432..fb99717bc38 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/shellhub-io/shellhub -go 1.21 +go 1.22.4 require ( github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 @@ -22,6 +22,7 @@ require ( github.com/labstack/echo/v4 v4.10.2 github.com/mattn/go-shellwords v1.0.12 github.com/mholt/archiver/v4 v4.0.0-alpha.8 + github.com/openwall/yescrypt-go v1.0.0 github.com/oschwald/geoip2-golang v1.8.0 github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.5 diff --git a/pkg/agent/pkg/yescrypt/yescript.go b/pkg/agent/pkg/yescrypt/yescript.go deleted file mode 100644 index b6df9adccf6..00000000000 --- a/pkg/agent/pkg/yescrypt/yescript.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build !without_cgo -// +build !without_cgo - -package yescrypt - -/* -#cgo LDFLAGS: -lcrypt -#include -#include -*/ -import "C" -import "unsafe" - -// Verify verifies a yescrypt hash against a given key. -func Verify(key, hash string) bool { - cdata := C.struct_crypt_data{} - ckey := C.CString(key) - chash := C.CString(hash) - - out := C.crypt_r(ckey, chash, &cdata) - - C.free(unsafe.Pointer(ckey)) - C.free(unsafe.Pointer(chash)) - - return C.GoString(out) == hash -} diff --git a/pkg/agent/pkg/yescrypt/yescrypt.go b/pkg/agent/pkg/yescrypt/yescrypt.go new file mode 100644 index 00000000000..355b42eed48 --- /dev/null +++ b/pkg/agent/pkg/yescrypt/yescrypt.go @@ -0,0 +1,18 @@ +package yescrypt + +import ( + yescrypt "github.com/openwall/yescrypt-go" + log "github.com/sirupsen/logrus" +) + +// Verify verifies a yescrypt hash against a given key. +func Verify(password, hash string) bool { + hashed, err := yescrypt.Hash([]byte(password), []byte(hash)) + if err != nil { + log.WithError(err).Debug("failed to hash the password for comparison") + + return false + } + + return hash == string(hashed) +} diff --git a/pkg/agent/pkg/yescrypt/yescrypt_test.go b/pkg/agent/pkg/yescrypt/yescrypt_test.go new file mode 100644 index 00000000000..8c468526301 --- /dev/null +++ b/pkg/agent/pkg/yescrypt/yescrypt_test.go @@ -0,0 +1,68 @@ +package yescrypt + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/openwall/yescrypt-go" + "github.com/stretchr/testify/assert" +) + +func FuzzVerify(f *testing.F) { + const settings = "$y$j9T$AAt9R641xPvCI9nXw1HHW/" + + for i := 0; i < 100; i++ { + v, err := rand.Int(rand.Reader, big.NewInt(64)) + assert.NoError(f, err) + + password := make([]byte, v.Int64()) + _, err = rand.Read(password) + assert.NoError(f, err) + + hash, err := yescrypt.Hash(password, []byte(settings)) + assert.NoError(f, err) + + f.Add(string(password), string(hash)) + } + + f.Fuzz(func(t *testing.T, a string, b string) { + assert.True(f, Verify(a, b)) + }) +} + +func TestVeirfy(t *testing.T) { + cases := []struct { + description string + password string + hash string + expected bool + }{ + { + description: "invalid password", + password: "invalid", + hash: "$y$j9T$AAt9R641xPvCI9nXw1HHW/$nCv3bckjDEC9Q5ahIEpyXVNGZhySye/ZdjxNxTY5ttB", + expected: false, + }, + { + description: "invalid hash", + password: "password", + hash: "invalid", + expected: false, + }, + { + description: "valid", + password: "password", + hash: "$y$j9T$AAt9R641xPvCI9nXw1HHW/$nCv3bckjDEC9Q5ahIEpyXVNGZhySye/ZdjxNxTY5ttB", + expected: true, + }, + } + + for _, test := range cases { + t.Run(test.description, func(tt *testing.T) { + result := Verify(test.password, test.hash) + + assert.Equal(tt, test.expected, result) + }) + } +} diff --git a/ssh/go.mod b/ssh/go.mod index ca45cc2f06b..708f763c1b3 100644 --- a/ssh/go.mod +++ b/ssh/go.mod @@ -1,6 +1,6 @@ module github.com/shellhub-io/shellhub/ssh -go 1.21 +go 1.22.4 require ( github.com/Masterminds/semver v1.5.0 diff --git a/tests/go.mod b/tests/go.mod index 28425fa0b8a..6b73dfa25cc 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -1,6 +1,6 @@ module github.com/shellhub-io/shellhub/tests -go 1.21 +go 1.22.4 require ( github.com/bramvdbogaerde/go-scp v1.4.0