Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package config

import (
"bytes"
"flag"
"fmt"
"strings"
"text/template"

"github.com/vulncheck-oss/go-exploit/c2"
"github.com/vulncheck-oss/go-exploit/c2/shelltunnel"
Expand Down Expand Up @@ -316,6 +318,49 @@ func (conf *Config) GetBoolFlag(name string) bool {
return *value
}

// Apply the configuration settings to a Go text template. This will take
// the `Config` struct and apply it to a `text/template`, allowing for
// strings to be built directly from the already set configuration
// variables.
//
// s := conf.ApplyTemplate(`CVE: {{.CVE}} - {{.Product}}`)
// output.PrintStatus(s) // Output: CVE: CVE-2024-1337 - OFBiz
//
// Flags that are user defined with CreateStringFlag and other types are
// directly accessible from their map values, for example if a command line
// argument is added with conf.CreateStringFlag("output", "do output",
// "instructions") it will be accessible via the following ApplyTemplate
// call:
//
// conf.ApplyTemplate(`Output flag {{.StringFlagsMap.output}}`)
//
// This function only returns the processed string and if a templating
// error occurs the function emits a framework error and sets the string to
// an empty string. This makes it harder to process any dynamic content and
// properly catch errors, but simplifies the return value to only provide a
// string.
//
// This should not be used with potentially attacker controlled input.
//
// Some Config types might be complex and will require usage of range
// components of text/template, follow the package docs if necessary.
func (conf *Config) ApplyTemplate(name string) string {
t, err := template.New("config-string-template").Parse(name)
if err != nil {
output.PrintfFrameworkError("Could not create template: %s", err.Error())

return ""
}
var buf bytes.Buffer
if err := t.Execute(&buf, conf); err != nil {
output.PrintfFrameworkError("Could not apply template: %s", err.Error())

return ""
}

return buf.String()
}

// Disable automatic start of c2 servers. Manually starting is required after
// this function is called. This is useful when you have an exploit that
// may have multiple stages and you are guaranteed to not need the C2
Expand Down
25 changes: 25 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,28 @@ func TestExternalDefaultFlags(t *testing.T) {
t.Error("Unexpected GetBoolFlag results")
}
}

func TestApplyTemplate(t *testing.T) {
conf := config.NewRemoteExploit(
config.ImplementedFeatures{AssetDetection: true, VersionScanning: true, Exploitation: true},
config.CodeExecution, []c2.Impl{}, "Apache", []string{"OFBiz"},
[]string{"cpe:2.3:a:apache:ofbiz"}, "CVE-2024-45507", "HTTP", 80)

conf.CreateStringFlag("teststring2", "default!", "string usage")
conf.CreateUintFlag("testuint2", 99, "uint usage")
conf.CreateIntFlag("testint2", 300, "int usage")
conf.CreateBoolFlag("testbool2", true, "bool usage")

s := conf.ApplyTemplate("{{.CVE}} {{.StringFlagsMap.teststring2}} {{.UintFlagsMap.testuint2}} {{.IntFlagsMap.testint2}} {{.BoolFlagsMap.testbool2}}")
if s == "" {
t.Error("Template returned error")
}
s = conf.ApplyTemplate("{{.CVE}} {{.StringFlagsMap.teststring2}} {{.UintFlagsMap.testuint2}} {{.IntFlagsMap.testint2}} {{.BoolFlagsMap.testbool2}}")
if s == "" {
t.Error("Template returned error")
}

if s != "CVE-2024-45507 default! 99 300 true" {
t.Errorf("'%s' unexpected", s)
}
}