mirror of https://github.com/daffainfo/nuclei.git
Misc changes to headless
parent
20c3ec0857
commit
8a40fac305
|
@ -84,6 +84,7 @@ based on templates offering massive extensibility and ease of use.`)
|
|||
set.BoolVarP(&options.Workflows, "workflows", "w", false, "Only run workflow templates with nuclei")
|
||||
set.IntVarP(&options.StatsInterval, "stats-interval", "si", 5, "Number of seconds between each stats line")
|
||||
set.BoolVar(&options.SystemResolvers, "system-resolvers", false, "Use system dns resolving as error fallback")
|
||||
set.IntVar(&options.PageTimeout, "page-timeout", 15, "Seconds to wait for each page in headless")
|
||||
_ = set.Parse()
|
||||
|
||||
if cfgFile != "" {
|
||||
|
|
|
@ -46,6 +46,10 @@ const (
|
|||
ActionWaitEvent
|
||||
// ActionKeyboard performs a keyboard action event on a page.
|
||||
ActionKeyboard
|
||||
// Action debug slows down headless and adds a sleep to each page.
|
||||
ActionDebug
|
||||
// ActionSleep executes a sleep for a specified duration
|
||||
ActionSleep
|
||||
)
|
||||
|
||||
// ActionStringToAction converts an action from string to internal representation
|
||||
|
@ -69,6 +73,8 @@ var ActionStringToAction = map[string]ActionType{
|
|||
"setbody": ActionSetBody,
|
||||
"waitevent": ActionWaitEvent,
|
||||
"keyboard": ActionKeyboard,
|
||||
"debug": ActionDebug,
|
||||
"sleep": ActionSleep,
|
||||
}
|
||||
|
||||
// ActionToActionString converts an action from internal representation to string
|
||||
|
@ -92,6 +98,8 @@ var ActionToActionString = map[ActionType]string{
|
|||
ActionSetBody: "setbody",
|
||||
ActionWaitEvent: "waitevent",
|
||||
ActionKeyboard: "keyboard",
|
||||
ActionDebug: "debug",
|
||||
ActionSleep: "sleep",
|
||||
}
|
||||
|
||||
// Action is an action taken by the browser to reach a navigation
|
||||
|
|
|
@ -2,6 +2,7 @@ package engine
|
|||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/go-rod/rod/lib/proto"
|
||||
|
@ -16,11 +17,13 @@ type Page struct {
|
|||
}
|
||||
|
||||
// Run runs a list of actions by creating a new page in the browser.
|
||||
func (i *Instance) Run(baseURL *url.URL, actions []*Action) (map[string]string, *Page, error) {
|
||||
func (i *Instance) Run(baseURL *url.URL, actions []*Action, timeout time.Duration) (map[string]string, *Page, error) {
|
||||
page, err := i.engine.Page(proto.TargetCreateTarget{})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
page = page.Timeout(timeout)
|
||||
|
||||
if i.browser.customAgent != "" {
|
||||
if userAgentErr := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: i.browser.customAgent}); userAgentErr != nil {
|
||||
return nil, nil, userAgentErr
|
||||
|
|
|
@ -63,6 +63,10 @@ func (p *Page) ExecuteActions(baseURL *url.URL, actions []*Action) (map[string]s
|
|||
err = p.ActionSetMethod(act, outData)
|
||||
case ActionKeyboard:
|
||||
err = p.KeyboardAction(act, outData)
|
||||
case ActionDebug:
|
||||
err = p.DebugAction(act, outData)
|
||||
case ActionSleep:
|
||||
err = p.SleepAction(act, outData)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
@ -467,6 +471,27 @@ func (p *Page) pageElementBy(data map[string]string) (*rod.Element, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// DebugAction enables debug action on a page.
|
||||
func (p *Page) DebugAction(act *Action, out map[string]string) error {
|
||||
p.instance.browser.engine.SlowMotion(5 * time.Second)
|
||||
p.instance.browser.engine.Trace(true)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SleepAction sleeps on the page for a specified duration
|
||||
func (p *Page) SleepAction(act *Action, out map[string]string) error {
|
||||
seconds := act.Data["duration"]
|
||||
if seconds == "" {
|
||||
seconds = "5"
|
||||
}
|
||||
parsed, err := strconv.Atoi(seconds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(time.Duration(parsed) * time.Second)
|
||||
return nil
|
||||
}
|
||||
|
||||
// selectorBy returns a selector from a representation.
|
||||
func selectorBy(selector string) rod.SelectorType {
|
||||
switch selector {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -37,7 +38,7 @@ func TestActionNavigate(t *testing.T) {
|
|||
require.Nil(t, err, "could not parse URL")
|
||||
|
||||
actions := []*Action{{ActionType: "navigate", Data: map[string]string{"url": "{{BaseURL}}"}}, {ActionType: "waitload"}}
|
||||
_, page, err := instance.Run(parsed, actions)
|
||||
_, page, err := instance.Run(parsed, actions, 20*time.Second)
|
||||
require.Nil(t, err, "could not run page actions")
|
||||
defer page.Close()
|
||||
|
||||
|
@ -73,7 +74,7 @@ func TestActionScript(t *testing.T) {
|
|||
{ActionType: "waitload"},
|
||||
{ActionType: "script", Name: "test", Data: map[string]string{"code": "window.test"}},
|
||||
}
|
||||
out, page, err := instance.Run(parsed, actions)
|
||||
out, page, err := instance.Run(parsed, actions, 20*time.Second)
|
||||
require.Nil(t, err, "could not run page actions")
|
||||
defer page.Close()
|
||||
|
||||
|
@ -102,7 +103,7 @@ func TestActionScript(t *testing.T) {
|
|||
{ActionType: "waitload"},
|
||||
{ActionType: "script", Name: "test", Data: map[string]string{"code": "window.test"}},
|
||||
}
|
||||
out, page, err := instance.Run(parsed, actions)
|
||||
out, page, err := instance.Run(parsed, actions, 20*time.Second)
|
||||
require.Nil(t, err, "could not run page actions")
|
||||
defer page.Close()
|
||||
|
||||
|
@ -139,7 +140,7 @@ func TestActionClick(t *testing.T) {
|
|||
{ActionType: "waitload"},
|
||||
{ActionType: "click", Data: map[string]string{"selector": "button"}}, // Use css selector for clicking
|
||||
}
|
||||
_, page, err := instance.Run(parsed, actions)
|
||||
_, page, err := instance.Run(parsed, actions, 20*time.Second)
|
||||
require.Nil(t, err, "could not run page actions")
|
||||
defer page.Close()
|
||||
|
||||
|
@ -185,7 +186,7 @@ func TestActionRightClick(t *testing.T) {
|
|||
{ActionType: "waitload"},
|
||||
{ActionType: "rightclick", Data: map[string]string{"selector": "button"}}, // Use css selector for clicking
|
||||
}
|
||||
_, page, err := instance.Run(parsed, actions)
|
||||
_, page, err := instance.Run(parsed, actions, 20*time.Second)
|
||||
require.Nil(t, err, "could not run page actions")
|
||||
defer page.Close()
|
||||
|
||||
|
@ -223,7 +224,7 @@ func TestActionTextInput(t *testing.T) {
|
|||
{ActionType: "waitload"},
|
||||
{ActionType: "text", Data: map[string]string{"selector": "input", "value": "test"}},
|
||||
}
|
||||
_, page, err := instance.Run(parsed, actions)
|
||||
_, page, err := instance.Run(parsed, actions, 20*time.Second)
|
||||
require.Nil(t, err, "could not run page actions")
|
||||
defer page.Close()
|
||||
|
||||
|
@ -257,7 +258,7 @@ func TestActionHeadersChange(t *testing.T) {
|
|||
{ActionType: "navigate", Data: map[string]string{"url": "{{BaseURL}}"}},
|
||||
{ActionType: "waitload"},
|
||||
}
|
||||
_, page, err := instance.Run(parsed, actions)
|
||||
_, page, err := instance.Run(parsed, actions, 20*time.Second)
|
||||
require.Nil(t, err, "could not run page actions")
|
||||
defer page.Close()
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package headless
|
|||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
|
@ -28,7 +29,7 @@ func (r *Request) ExecuteWithResults(input string, metadata, previous output.Int
|
|||
r.options.Progress.DecrementRequests(1)
|
||||
return errors.Wrap(err, "could get html element")
|
||||
}
|
||||
out, page, err := instance.Run(parsed, r.Steps)
|
||||
out, page, err := instance.Run(parsed, r.Steps, time.Duration(r.options.Options.PageTimeout)*time.Second)
|
||||
if err != nil {
|
||||
r.options.Output.Request(r.options.TemplateID, input, "headless", err)
|
||||
r.options.Progress.DecrementRequests(1)
|
||||
|
|
|
@ -55,6 +55,8 @@ type Options struct {
|
|||
Retries int
|
||||
// Rate-Limit is the maximum number of requests per specified target
|
||||
RateLimit int
|
||||
//`PageTimeout is the maximum time to wait for a page in seconds
|
||||
PageTimeout int
|
||||
// OfflineHTTP is a flag that specific offline processing of http response
|
||||
// using same matchers/extractors from http protocol without the need
|
||||
// to send a new request, reading responses from a file.
|
||||
|
|
Loading…
Reference in New Issue