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

Commit 35c4db2

Browse files
Basic SSTI Detection (#36)
* basic ssti detection * fern revert * updated payload sig * updated SSTI > SSTIREFLECT
1 parent 554cb50 commit 35c4db2

5 files changed

Lines changed: 72 additions & 1 deletion

File tree

cmd/general.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ func (a *MethodWebTest) InitGeneralCommand() {
497497
}
498498

499499
multiCmd.Flags().String("method", "", "The HTTP method to use for the request")
500-
multiCmd.Flags().String("event", "", "The event to test: XSSALERT, SQLIBOOLEAN, SQLIESCAPE, SQLITIMEDELAY")
500+
multiCmd.Flags().String("event", "", "The event to test: XSSALERT, SQLIBOOLEAN, SQLIESCAPE, SQLITIMEDELAY, SSTIREFLECT")
501501
multiCmd.Flags().String("variabledata", "", "Base64 encoded Json string of variable names and base values to add to injects")
502502
multiCmd.Flags().String("injectionlocation", "", "The injection location to test: HEADER, PATH, QUERY, BODY, FORM, MULTIPART")
503503

fern/definition/request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ types:
3939
- SQLIESCAPE
4040
- SQLITIMEDELAY
4141
- XSSALERT
42+
- SSTIREFLECT
4243
EventType:
4344
union:
4445
HeaderEvent: HeaderEvent

generated/go/request.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ const (
366366
MultiEventSqliescape MultiEvent = "SQLIESCAPE"
367367
MultiEventSqlitimedelay MultiEvent = "SQLITIMEDELAY"
368368
MultiEventXssalert MultiEvent = "XSSALERT"
369+
MultiEventSstireflect MultiEvent = "SSTIREFLECT"
369370
)
370371

371372
func NewMultiEventFromString(s string) (MultiEvent, error) {
@@ -382,6 +383,8 @@ func NewMultiEventFromString(s string) (MultiEvent, error) {
382383
return MultiEventSqlitimedelay, nil
383384
case "XSSALERT":
384385
return MultiEventXssalert, nil
386+
case "SSTIREFLECT":
387+
return MultiEventSstireflect, nil
385388
}
386389
var t MultiEvent
387390
return "", fmt.Errorf("%s is not a valid %T", s, t)

internal/general/multi/moduleSelector.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
methodwebtest "github.com/Method-Security/methodwebtest/generated/go"
77
command "github.com/Method-Security/methodwebtest/internal/general/multi/command"
88
sqli "github.com/Method-Security/methodwebtest/internal/general/multi/sqli"
9+
ssti "github.com/Method-Security/methodwebtest/internal/general/multi/ssti"
910
xss "github.com/Method-Security/methodwebtest/internal/general/multi/xss"
1011
)
1112

@@ -28,5 +29,8 @@ func RunModuleSelector(ctx context.Context, config *methodwebtest.MultiInjection
2829
if config.EventType == methodwebtest.MultiEventCommandecho {
2930
return command.PerformCommandEchoInjection(ctx, config)
3031
}
32+
if config.EventType == methodwebtest.MultiEventSstireflect {
33+
return ssti.PerformSSTIReflectInjection(ctx, config)
34+
}
3135
return &methodwebtest.Report{Errors: []string{"No module found for event type"}}
3236
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package general
2+
3+
import (
4+
"context"
5+
"strings"
6+
7+
methodwebtest "github.com/Method-Security/methodwebtest/generated/go"
8+
utils "github.com/Method-Security/methodwebtest/utils/engines"
9+
)
10+
11+
var SSTIPayloads = []string{
12+
"${1337*42}",
13+
"{{1337*42}}",
14+
"<%= 1337 * 42 %>",
15+
"#{ 1337 * 42 }",
16+
"${{1337*42}}",
17+
}
18+
19+
func PerformSSTIReflectInjection(ctx context.Context, config *methodwebtest.MultiInjectionConfig) *methodwebtest.Report {
20+
generatedPayloads := utils.GenerateInjectionPayloads(SSTIPayloads, config.VariableData)
21+
22+
injectionConfig := methodwebtest.InjectionEngineConfig{
23+
Targets: config.Targets,
24+
Method: config.Method,
25+
Paths: []string{"/"},
26+
InjectedPayloads: generatedPayloads,
27+
InjectionLocation: config.InjectionLocation,
28+
EventType: methodwebtest.NewEventTypeFromMultiEvent(methodwebtest.MultiEventSstireflect),
29+
FollowRedirects: true,
30+
Timeout: config.Timeout,
31+
Retries: config.Retries,
32+
Sleep: config.Sleep,
33+
}
34+
35+
report := utils.RunMultiInjectionsEngine(ctx, &injectionConfig)
36+
checkForSSTIReflect(report)
37+
return report
38+
}
39+
40+
func checkForSSTIReflect(report *methodwebtest.Report) {
41+
for _, target := range report.Targets {
42+
if target.Attempts == nil {
43+
continue
44+
}
45+
for _, attempt := range target.Attempts {
46+
if attempt.Request == nil || attempt.Request.ResponseBody == nil {
47+
continue
48+
}
49+
finding := false
50+
if strings.Contains(*attempt.Request.ResponseBody, "56154") {
51+
finding = true
52+
}
53+
if !finding && attempt.Request.ResponseHeaders != nil {
54+
for _, headerValue := range attempt.Request.ResponseHeaders {
55+
if strings.Contains(headerValue, "56154") {
56+
finding = true
57+
}
58+
}
59+
}
60+
attempt.Finding = &finding
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)