mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 20:05:27 +00:00
Misc changes to headless
This commit is contained in:
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.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.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.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()
|
_ = set.Parse()
|
||||||
|
|
||||||
if cfgFile != "" {
|
if cfgFile != "" {
|
||||||
|
|||||||
@ -46,6 +46,10 @@ const (
|
|||||||
ActionWaitEvent
|
ActionWaitEvent
|
||||||
// ActionKeyboard performs a keyboard action event on a page.
|
// ActionKeyboard performs a keyboard action event on a page.
|
||||||
ActionKeyboard
|
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
|
// ActionStringToAction converts an action from string to internal representation
|
||||||
@ -69,6 +73,8 @@ var ActionStringToAction = map[string]ActionType{
|
|||||||
"setbody": ActionSetBody,
|
"setbody": ActionSetBody,
|
||||||
"waitevent": ActionWaitEvent,
|
"waitevent": ActionWaitEvent,
|
||||||
"keyboard": ActionKeyboard,
|
"keyboard": ActionKeyboard,
|
||||||
|
"debug": ActionDebug,
|
||||||
|
"sleep": ActionSleep,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActionToActionString converts an action from internal representation to string
|
// ActionToActionString converts an action from internal representation to string
|
||||||
@ -92,6 +98,8 @@ var ActionToActionString = map[ActionType]string{
|
|||||||
ActionSetBody: "setbody",
|
ActionSetBody: "setbody",
|
||||||
ActionWaitEvent: "waitevent",
|
ActionWaitEvent: "waitevent",
|
||||||
ActionKeyboard: "keyboard",
|
ActionKeyboard: "keyboard",
|
||||||
|
ActionDebug: "debug",
|
||||||
|
ActionSleep: "sleep",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action is an action taken by the browser to reach a navigation
|
// Action is an action taken by the browser to reach a navigation
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package engine
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-rod/rod"
|
"github.com/go-rod/rod"
|
||||||
"github.com/go-rod/rod/lib/proto"
|
"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.
|
// 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{})
|
page, err := i.engine.Page(proto.TargetCreateTarget{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
page = page.Timeout(timeout)
|
||||||
|
|
||||||
if i.browser.customAgent != "" {
|
if i.browser.customAgent != "" {
|
||||||
if userAgentErr := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: i.browser.customAgent}); userAgentErr != nil {
|
if userAgentErr := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: i.browser.customAgent}); userAgentErr != nil {
|
||||||
return nil, nil, userAgentErr
|
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)
|
err = p.ActionSetMethod(act, outData)
|
||||||
case ActionKeyboard:
|
case ActionKeyboard:
|
||||||
err = p.KeyboardAction(act, outData)
|
err = p.KeyboardAction(act, outData)
|
||||||
|
case ActionDebug:
|
||||||
|
err = p.DebugAction(act, outData)
|
||||||
|
case ActionSleep:
|
||||||
|
err = p.SleepAction(act, outData)
|
||||||
default:
|
default:
|
||||||
continue
|
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.
|
// selectorBy returns a selector from a representation.
|
||||||
func selectorBy(selector string) rod.SelectorType {
|
func selectorBy(selector string) rod.SelectorType {
|
||||||
switch selector {
|
switch selector {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -37,7 +38,7 @@ func TestActionNavigate(t *testing.T) {
|
|||||||
require.Nil(t, err, "could not parse URL")
|
require.Nil(t, err, "could not parse URL")
|
||||||
|
|
||||||
actions := []*Action{{ActionType: "navigate", Data: map[string]string{"url": "{{BaseURL}}"}}, {ActionType: "waitload"}}
|
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")
|
require.Nil(t, err, "could not run page actions")
|
||||||
defer page.Close()
|
defer page.Close()
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ func TestActionScript(t *testing.T) {
|
|||||||
{ActionType: "waitload"},
|
{ActionType: "waitload"},
|
||||||
{ActionType: "script", Name: "test", Data: map[string]string{"code": "window.test"}},
|
{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")
|
require.Nil(t, err, "could not run page actions")
|
||||||
defer page.Close()
|
defer page.Close()
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ func TestActionScript(t *testing.T) {
|
|||||||
{ActionType: "waitload"},
|
{ActionType: "waitload"},
|
||||||
{ActionType: "script", Name: "test", Data: map[string]string{"code": "window.test"}},
|
{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")
|
require.Nil(t, err, "could not run page actions")
|
||||||
defer page.Close()
|
defer page.Close()
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ func TestActionClick(t *testing.T) {
|
|||||||
{ActionType: "waitload"},
|
{ActionType: "waitload"},
|
||||||
{ActionType: "click", Data: map[string]string{"selector": "button"}}, // Use css selector for clicking
|
{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")
|
require.Nil(t, err, "could not run page actions")
|
||||||
defer page.Close()
|
defer page.Close()
|
||||||
|
|
||||||
@ -185,7 +186,7 @@ func TestActionRightClick(t *testing.T) {
|
|||||||
{ActionType: "waitload"},
|
{ActionType: "waitload"},
|
||||||
{ActionType: "rightclick", Data: map[string]string{"selector": "button"}}, // Use css selector for clicking
|
{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")
|
require.Nil(t, err, "could not run page actions")
|
||||||
defer page.Close()
|
defer page.Close()
|
||||||
|
|
||||||
@ -223,7 +224,7 @@ func TestActionTextInput(t *testing.T) {
|
|||||||
{ActionType: "waitload"},
|
{ActionType: "waitload"},
|
||||||
{ActionType: "text", Data: map[string]string{"selector": "input", "value": "test"}},
|
{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")
|
require.Nil(t, err, "could not run page actions")
|
||||||
defer page.Close()
|
defer page.Close()
|
||||||
|
|
||||||
@ -257,7 +258,7 @@ func TestActionHeadersChange(t *testing.T) {
|
|||||||
{ActionType: "navigate", Data: map[string]string{"url": "{{BaseURL}}"}},
|
{ActionType: "navigate", Data: map[string]string{"url": "{{BaseURL}}"}},
|
||||||
{ActionType: "waitload"},
|
{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")
|
require.Nil(t, err, "could not run page actions")
|
||||||
defer page.Close()
|
defer page.Close()
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package headless
|
|||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/projectdiscovery/gologger"
|
"github.com/projectdiscovery/gologger"
|
||||||
@ -28,7 +29,7 @@ func (r *Request) ExecuteWithResults(input string, metadata, previous output.Int
|
|||||||
r.options.Progress.DecrementRequests(1)
|
r.options.Progress.DecrementRequests(1)
|
||||||
return errors.Wrap(err, "could get html element")
|
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 {
|
if err != nil {
|
||||||
r.options.Output.Request(r.options.TemplateID, input, "headless", err)
|
r.options.Output.Request(r.options.TemplateID, input, "headless", err)
|
||||||
r.options.Progress.DecrementRequests(1)
|
r.options.Progress.DecrementRequests(1)
|
||||||
|
|||||||
@ -55,6 +55,8 @@ type Options struct {
|
|||||||
Retries int
|
Retries int
|
||||||
// Rate-Limit is the maximum number of requests per specified target
|
// Rate-Limit is the maximum number of requests per specified target
|
||||||
RateLimit int
|
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
|
// OfflineHTTP is a flag that specific offline processing of http response
|
||||||
// using same matchers/extractors from http protocol without the need
|
// using same matchers/extractors from http protocol without the need
|
||||||
// to send a new request, reading responses from a file.
|
// to send a new request, reading responses from a file.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user