From 655eb06b438e4abd4a4b81391443ffa70e0eedc1 Mon Sep 17 00:00:00 2001 From: terrorbyte Date: Fri, 16 May 2025 15:58:56 -0600 Subject: [PATCH 1/5] Add SemVer constraint wrapper and add framework test files --- framework.go | 22 ++++++++++++++++++++++ framework_test.go | 34 ++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ 4 files changed, 59 insertions(+) create mode 100644 framework_test.go diff --git a/framework.go b/framework.go index ea02fc3..51f83f3 100644 --- a/framework.go +++ b/framework.go @@ -71,6 +71,7 @@ import ( "sync/atomic" "time" + "github.com/Masterminds/semver" "github.com/vulncheck-oss/go-exploit/c2" "github.com/vulncheck-oss/go-exploit/c2/channel" "github.com/vulncheck-oss/go-exploit/cli" @@ -428,6 +429,27 @@ func StoreVersion(conf *config.Config, version string) { db.UpdateVerified(conf.Product, true, version, conf.Rhost, conf.Rport) } +// Compare a version to a semantic version constraint using the [Masterminds semver constraints](https://github.com/Masterminds/semver?tab=readme-ov-file#checking-version-constraints). +// Provide a version string and a constraint and if the semver is within the constraint a boolean +// response of whether the version is constrained or not will occur. Any errors from the constraint +// or version will propagate through the framework errors and the value will be false. +func CheckSemVer(version string, constraint string) bool { + c, err := semver.NewConstraint(constraint) + if err != nil { + output.PrintfFrameworkError("Invalid constraint: %s", err.Error()) + + return false + } + v, err := semver.NewVersion(version) + if err != nil { + output.PrintfFrameworkError("Invalid version: %s", err.Error()) + + return false + } + + return c.Check(v) +} + // modify godebug to re-enable old cipher suites that were removed in 1.22. This does have implications for our // client fingerprint, and we should consider how to improve/fix that in the future. We also should be respectful // of other disabling this feature, so we will check for it before re-enabling it. diff --git a/framework_test.go b/framework_test.go new file mode 100644 index 0000000..0c79c48 --- /dev/null +++ b/framework_test.go @@ -0,0 +1,34 @@ +package exploit_test + +import ( + "testing" + + "github.com/vulncheck-oss/go-exploit" +) + +func TestCheckSemVer_Full(t *testing.T) { + if !exploit.CheckSemVer("1.0.0", "<= 1.0.0") { + t.Error("Constraint should have passed") + } + if exploit.CheckSemVer("1.0.0", "> 1.0.0") { + t.Error("Constraint should not have passed") + } +} + +func TestCheckSemVer_BadVersion(t *testing.T) { + if exploit.CheckSemVer("uwu", "<= 1.0.0") { + t.Error("Version was invalid, should not have passed") + } + if exploit.CheckSemVer("1.0.0 ", "<= 1.0.0") { + t.Error("Version was invalid, should not have passed") + } +} + +func TestCheckSemVer_BadConstraint(t *testing.T) { + if exploit.CheckSemVer("1.0.0", "<== 1.0.0") { + t.Error("Constraint was invalid, should not have passed") + } + if exploit.CheckSemVer("1.0.0", "xp") { + t.Error("Constraint was invalid, should not have passed") + } +} diff --git a/go.mod b/go.mod index 023522b..16b33de 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( ) require ( + github.com/Masterminds/semver v1.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/go.sum b/go.sum index 28329c7..c3320b9 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= From 71fc158dbb772aa0bc1fd2742560be79f94e5dd0 Mon Sep 17 00:00:00 2001 From: lobsterjerusalem Date: Mon, 19 May 2025 15:13:20 -0600 Subject: [PATCH 2/5] Added wrappers with file serve --- wrappers/wrappers.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 wrappers/wrappers.go diff --git a/wrappers/wrappers.go b/wrappers/wrappers.go new file mode 100644 index 0000000..be0bcaa --- /dev/null +++ b/wrappers/wrappers.go @@ -0,0 +1,32 @@ +package wrappers + +import( + "github.com/vulncheck-oss/go-exploit/config" + "github.com/vulncheck-oss/go-exploit/output" + "github.com/vulncheck-oss/go-exploit/c2/channel" + "github.com/vulncheck-oss/go-exploit/c2/httpservefile" +) + +// A collection of wrappers/helper functions that have otherwise no place to go and may need to be in their own packages +// to avoid certain import cycle errors. + +// Helper function for use within exploits to reduce the overall amount of boilerplate when setting up a file server to host a dynamically generated file. +func HTTPServeFileInitAndRunWithFile(conf *config.Config, fileName string, routeName string, data[]byte) bool { + httpServer := httpservefile.GetInstance() + + if httpServer.HTTPAddr == "" { + httpServer.HTTPAddr = conf.Lhost + } + + if !httpServer.Init(&channel.Channel{HTTPAddr: httpServer.HTTPAddr, HTTPPort: httpServer.HTTPPort}) { + output.PrintFrameworkError("Could not start http server") + + return false + } + + httpServer.AddFile(fileName, routeName, data) + + go httpServer.Run(conf.C2Timeout) + + return true +} From eeb8cafd89f81a15c4c7e2d12a993385b41e1ca6 Mon Sep 17 00:00:00 2001 From: lobsterjerusalem Date: Mon, 19 May 2025 15:23:52 -0600 Subject: [PATCH 3/5] Added expanded version checking wrapper --- wrappers/wrappers.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/wrappers/wrappers.go b/wrappers/wrappers.go index be0bcaa..9e685b1 100644 --- a/wrappers/wrappers.go +++ b/wrappers/wrappers.go @@ -1,8 +1,13 @@ package wrappers import( + "regexp" + "net/http" + + "github.com/vulncheck-oss/go-exploit" "github.com/vulncheck-oss/go-exploit/config" "github.com/vulncheck-oss/go-exploit/output" + "github.com/vulncheck-oss/go-exploit/protocol" "github.com/vulncheck-oss/go-exploit/c2/channel" "github.com/vulncheck-oss/go-exploit/c2/httpservefile" ) @@ -30,3 +35,36 @@ func HTTPServeFileInitAndRunWithFile(conf *config.Config, fileName string, route return true } + +// This removes generic version checking boiler plate that works in a great deal of cases. +// Of course it will not work in every case but that is not the point. +func SimpleVersionCheck(conf *config.Config, rePattern string, versionConstraint string) exploit.VersionCheckType { + url := protocol.GenerateURL(conf.Rhost, conf.Rport, conf.SSL, "/") + resp, body, ok := protocol.HTTPGetCache(url) + if !ok || resp == nil { + return exploit.Unknown + } + + if resp.StatusCode != http.StatusOK { + output.PrintfFrameworkError("Version check failed: Unexpected response code during initial GET request: %d", resp.StatusCode) + + return exploit.Unknown + } + + matches := regexp.MustCompile(rePattern).FindStringSubmatch(body) + if len(matches) < 2 { + output.PrintFrameworkError("Version check failed: No matches found for the provided pattern") + + return exploit.Unknown + } + + exploit.StoreVersion(conf, matches[1]) + + if exploit.CheckSemVer(matches[1], versionConstraint) { + return exploit.Vulnerable + } + + output.PrintFrameworkError("Version did not match the constraint") + + return exploit.NotVulnerable +} From 76a7b3088a0c123fce3752503e5c972e910f8e2c Mon Sep 17 00:00:00 2001 From: lobsterjerusalem Date: Mon, 19 May 2025 15:43:59 -0600 Subject: [PATCH 4/5] removed output line --- wrappers/wrappers.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/wrappers/wrappers.go b/wrappers/wrappers.go index 9e685b1..671c096 100644 --- a/wrappers/wrappers.go +++ b/wrappers/wrappers.go @@ -64,7 +64,5 @@ func SimpleVersionCheck(conf *config.Config, rePattern string, versionConstraint return exploit.Vulnerable } - output.PrintFrameworkError("Version did not match the constraint") - return exploit.NotVulnerable } From bd4a50f585a9f5e054f8f0e2eea31cd42b6ee7ec Mon Sep 17 00:00:00 2001 From: lobsterjerusalem Date: Wed, 4 Jun 2025 12:10:28 -0600 Subject: [PATCH 5/5] added endpoint param --- wrappers/wrappers.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wrappers/wrappers.go b/wrappers/wrappers.go index 671c096..6750629 100644 --- a/wrappers/wrappers.go +++ b/wrappers/wrappers.go @@ -38,8 +38,8 @@ func HTTPServeFileInitAndRunWithFile(conf *config.Config, fileName string, route // This removes generic version checking boiler plate that works in a great deal of cases. // Of course it will not work in every case but that is not the point. -func SimpleVersionCheck(conf *config.Config, rePattern string, versionConstraint string) exploit.VersionCheckType { - url := protocol.GenerateURL(conf.Rhost, conf.Rport, conf.SSL, "/") +func SimpleVersionCheck(conf *config.Config, rePattern string, versionConstraint string, endpoint string) exploit.VersionCheckType { + url := protocol.GenerateURL(conf.Rhost, conf.Rport, conf.SSL, endpoint) resp, body, ok := protocol.HTTPGetCache(url) if !ok || resp == nil { return exploit.Unknown