diff options
Diffstat (limited to 'internal/ipc/ipc.go')
| -rw-r--r-- | internal/ipc/ipc.go | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/internal/ipc/ipc.go b/internal/ipc/ipc.go index 7d81473..270b8e4 100644 --- a/internal/ipc/ipc.go +++ b/internal/ipc/ipc.go @@ -38,6 +38,16 @@ type Request struct { // turn (Sniper-style - see proxy.Intrude). Payloads []string `json:"payloads,omitempty"` + // For "intrude": optional Go regexps evaluated against each result's + // response bytes. GrepMatch flags whether it matched at all; + // GrepExtract additionally captures text (first submatch if the + // pattern has a capturing group, else the whole match) into the + // result. Either or both may be empty to skip that check. Compiled + // and validated once, server-side, before the attack starts - a bad + // pattern fails the same way a bad marker or empty payload set does. + GrepMatch string `json:"grep_match,omitempty"` + GrepExtract string `json:"grep_extract,omitempty"` + // For "rules_save": add (Rule.ID == 0) or update (Rule.ID != 0) a // match-and-replace rule. For "rules_delete"/"rules_toggle": RuleID // (and RuleEnabled for toggle) identify the target. @@ -72,13 +82,15 @@ type StatusMsg struct { // IntrudeResultMsg is one completed Intruder attack request. type IntrudeResultMsg struct { - Position int `json:"position"` - Payload string `json:"payload"` - EntryID int64 `json:"entry_id"` - StatusCode int `json:"status_code"` - RespSize int `json:"resp_size"` - Duration time.Duration `json:"duration"` - Error string `json:"error,omitempty"` + Position int `json:"position"` + Payload string `json:"payload"` + EntryID int64 `json:"entry_id"` + StatusCode int `json:"status_code"` + RespSize int `json:"resp_size"` + Duration time.Duration `json:"duration"` + Error string `json:"error,omitempty"` + GrepMatch bool `json:"grep_match,omitempty"` + GrepExtract string `json:"grep_extract,omitempty"` } // EntryDetail is a full history entry, raw bytes included. @@ -307,18 +319,22 @@ func Subscribe(path string) (<-chan store.Summary, func() error, error) { // Intrude starts a Sniper attack (see proxy.Intrude): template must // contain at least one §marked§ position, fuzzed in turn through -// payloads. Unlike Subscribe's live feed, no result is ever dropped for -// a slow consumer - each one is the attack's actual data, not a -// notification with the real thing recoverable elsewhere. A setup error -// (bad markers, empty payload set, too many requests) is returned -// directly rather than through the channel. The returned channel closes -// when the attack finishes or the connection is closed early. -func Intrude(path, scheme, host string, template []byte, payloads []string) (<-chan IntrudeResultMsg, func() error, error) { +// payloads. grepMatch/grepExtract are optional Go regexps evaluated +// server-side against each result's response bytes (empty string +// disables either check) - see IntrudeResultMsg. Unlike Subscribe's live +// feed, no result is ever dropped for a slow consumer - each one is the +// attack's actual data, not a notification with the real thing +// recoverable elsewhere. A setup error (bad markers, empty payload set, +// too many requests, an unparseable grep regexp) is returned directly +// rather than through the channel. The returned channel closes when the +// attack finishes or the connection is closed early. +func Intrude(path, scheme, host string, template []byte, payloads []string, grepMatch, grepExtract string) (<-chan IntrudeResultMsg, func() error, error) { conn, err := net.Dial("unix", path) if err != nil { return nil, nil, fmt.Errorf("dial %s: %w", path, err) } - if err := json.NewEncoder(conn).Encode(Request{Type: "intrude", Scheme: scheme, Host: host, Raw: template, Payloads: payloads}); err != nil { + req := Request{Type: "intrude", Scheme: scheme, Host: host, Raw: template, Payloads: payloads, GrepMatch: grepMatch, GrepExtract: grepExtract} + if err := json.NewEncoder(conn).Encode(req); err != nil { conn.Close() return nil, nil, err } |