Skip to content
This repository was archived by the owner on Jul 17, 2025. It is now read-only.

Commit ab04ffc

Browse files
committed
wordpress path traversal
1 parent e8b067c commit ab04ffc

4 files changed

Lines changed: 167 additions & 1 deletion

File tree

cmd/wordpress.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package cmd
2+
3+
import (
4+
"errors"
5+
6+
path "github.com/Method-Security/methodwebtest/internal/wordpress/path"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
// InitWordpressCommand initializes the apache command for the methodwebtest CLI.
11+
func (a *MethodWebTest) InitWordpressCommand() {
12+
wordpressCmd := &cobra.Command{
13+
Use: "wordpress",
14+
Short: "Perform wordpress specific injection tests against a target",
15+
Long: `Perform wordpress specific injection tests against a target`,
16+
}
17+
18+
wordpressCmd.PersistentFlags().StringSlice("targets", []string{}, "The URL of target")
19+
wordpressCmd.PersistentFlags().Int("timeout", 30, "Timeout per request (seconds)")
20+
wordpressCmd.PersistentFlags().Int("sleep", 0, "Sleep time between requests (seconds)")
21+
wordpressCmd.PersistentFlags().Int("retries", 0, "Number of attempts per credential pair")
22+
23+
// pathCmd holds the subcommands for path injection tests
24+
pathCmd := &cobra.Command{
25+
Use: "path",
26+
Short: "Perform path injection tests against a target",
27+
Long: `Perform path injection tests against a target`,
28+
}
29+
30+
traversalCmd := &cobra.Command{
31+
Use: "traversal",
32+
Short: "Perform a Wordpress specific path traversal for common file locations",
33+
Long: `Perform a Wordpress specific path traversal for common file locations`,
34+
Run: func(cmd *cobra.Command, args []string) {
35+
defer a.OutputSignal.PanicHandler(cmd.Context())
36+
37+
// Target flags
38+
targets, err := cmd.Flags().GetStringSlice("targets")
39+
if err != nil {
40+
a.OutputSignal.AddError(err)
41+
return
42+
}
43+
if len(targets) == 0 {
44+
a.OutputSignal.AddError(errors.New("no targets provided"))
45+
return
46+
}
47+
48+
// Configuration flags
49+
responseCodes, err := cmd.Flags().GetString("responsecodes")
50+
if err != nil {
51+
a.OutputSignal.AddError(err)
52+
return
53+
}
54+
ignoreBase, err := cmd.Flags().GetBool("ignorebasecontentmatch")
55+
if err != nil {
56+
a.OutputSignal.AddError(err)
57+
return
58+
}
59+
timeout, err := cmd.Flags().GetInt("timeout")
60+
if err != nil {
61+
a.OutputSignal.AddError(err)
62+
return
63+
}
64+
sleep, err := cmd.Flags().GetInt("sleep")
65+
if err != nil {
66+
a.OutputSignal.AddError(err)
67+
return
68+
}
69+
retries, err := cmd.Flags().GetInt("retries")
70+
if err != nil {
71+
a.OutputSignal.AddError(err)
72+
return
73+
}
74+
successfulOnly, err := cmd.Flags().GetBool("successfulonly")
75+
if err != nil {
76+
a.OutputSignal.AddError(err)
77+
return
78+
}
79+
threshold, err := cmd.Flags().GetFloat64("threshold")
80+
if err != nil {
81+
a.OutputSignal.AddError(err)
82+
return
83+
}
84+
85+
// Load configuration
86+
config := LoadPathTraversalConfig(targets, []string{}, []string{}, "", responseCodes, ignoreBase, timeout, sleep, retries, successfulOnly, threshold, nil)
87+
88+
// Generate report
89+
report := path.PerformWordpressPathTraversal(cmd.Context(), config)
90+
if len(report.Errors) > 0 {
91+
a.OutputSignal.Status = 1
92+
}
93+
a.OutputSignal.Content = report
94+
},
95+
}
96+
97+
traversalCmd.Flags().String("responsecodes", "200-299", "Response codes to consider as valid responses")
98+
traversalCmd.Flags().Bool("ignorebasecontentmatch", true, "Ignores valid responses with identical size and word length to the base path, typically signifying a web backend redirect")
99+
traversalCmd.Flags().Bool("successfulonly", false, "Only show successful attempts")
100+
traversalCmd.Flags().Float64("threshold", 0.10, "Threshold for a negitive finding that represents the percentage difference between the size of the response body in question and the baseline response (0.0 is an exact match, with .05 being a 5 percent difference)")
101+
102+
pathCmd.AddCommand(traversalCmd)
103+
104+
wordpressCmd.AddCommand(pathCmd)
105+
106+
a.RootCmd.AddCommand(wordpressCmd)
107+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package wordpress
2+
3+
import (
4+
"context"
5+
6+
methodwebtest "github.com/Method-Security/methodwebtest/generated/go"
7+
utils "github.com/Method-Security/methodwebtest/utils/engines"
8+
)
9+
10+
var commonExposedPaths = []string{
11+
"/xmlrpc.php", // Often exploited for brute-force attacks
12+
"/wp-config.php", // Contains database credentials and secrets
13+
"/wp-content/debug.log", // Can leak sensitive debug info
14+
"/wp-includes/", // Core WordPress files, can expose version info
15+
"/wp-json/", // REST API, potential user enumeration
16+
"/wp-json/wp/v2/users", // Enumerate users, especially admin usernames
17+
"/wp-json/wp/v2/settings", // Enumerate settings, potential sensitive information
18+
"/wp-json/wp/v2/revisions", // Enumerate revisions, potential sensitive information
19+
"/wp-cron.php", // Can be abused for DoS or forced execution
20+
"/readme.html", // Leaks WordPress version
21+
"/.htaccess", // Might expose security configurations
22+
"/.htpasswd", // Can leak password-protected directories
23+
"/license.txt", // Leaks installation details
24+
"/wp-admin/install.php", // Can be exposed on unconfigured sites
25+
"/wp-admin/admin-ajax.php", // Used in many plugins, potential data leaks
26+
"/wp-admin/admin-post.php", // Can expose admin-related operations
27+
"/wp-admin/setup-config.php", // Can be accessed if setup is incomplete
28+
"/wp-config.bak", // Backup of wp-config.php, may still have credentials
29+
"/wp-config.old", // Old versions often left after updates
30+
"/wp-content/uploads/db-backup.sql", // Database dump file, may contain sensitive data
31+
"/wp-content/uploads/error_log", // PHP error log, may expose system paths
32+
"/wp-sitemap.xml", // Can provide a list of indexed URLs for reconnaissance
33+
"/wp-content/plugins/wp-file-manager/lib/files/", // Misconfigured file manager plugin
34+
"/wp-admin/admin-ajax.php?action=revslider_show_image", // Revslider LFI vulnerability
35+
}
36+
37+
func PerformWordpressPathTraversal(ctx context.Context, config *methodwebtest.PathTraversalConfig) *methodwebtest.Report {
38+
config.Paths = commonExposedPaths
39+
engineConfig := methodwebtest.PathTraversalEngineConfig{
40+
Targets: config.Targets,
41+
Paths: config.Paths,
42+
PathFiles: []string{},
43+
ResponseCodes: config.ResponseCodes,
44+
IgnoreBaseContent: config.IgnoreBaseContent,
45+
Timeout: config.Timeout,
46+
Retries: config.Retries,
47+
Sleep: config.Sleep,
48+
SuccessfulOnly: config.SuccessfulOnly,
49+
Threshold: &config.Threshold,
50+
}
51+
report := utils.RunPathTraversalEngine(ctx, &engineConfig)
52+
report.Config = methodwebtest.NewEngineConfigFromPathTraversalEngineConfig(&engineConfig)
53+
return report
54+
}

main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ func main() {
1515
methodwebtest := cmd.NewMethodWebTest(version)
1616
methodwebtest.InitRootCommand()
1717
methodwebtest.InitGeneralCommand()
18-
methodwebtest.InitNginxCommand()
1918
methodwebtest.InitApacheCommand()
19+
methodwebtest.InitNginxCommand()
20+
methodwebtest.InitWordpressCommand()
2021

2122
if err := methodwebtest.RootCmd.Execute(); err != nil {
2223
os.Exit(1)

utils/engines/pathTraversal.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ func AnalyzeResponse(request methodwebtest.RequestInfo, validCodes map[int]bool,
129129
}
130130

131131
bodySize := len(*request.ResponseBody)
132+
if bodySize == 0 {
133+
return false
134+
}
135+
132136
wordCount := len(strings.Fields(*request.ResponseBody))
133137
if checkBaseContentMatch {
134138
if areSimilar(bodySize, baselineSize, threshold) && areSimilar(wordCount, baselineWords, threshold) {

0 commit comments

Comments
 (0)