2022-09-19 01:13:59 +05:30
|
|
|
package runner
|
|
|
|
|
|
|
|
|
|
import (
|
2022-10-29 07:51:43 +05:30
|
|
|
"bytes"
|
|
|
|
|
"crypto/sha1"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"io"
|
2022-09-19 01:13:59 +05:30
|
|
|
_ "net/http/pprof"
|
2022-10-29 07:51:43 +05:30
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
2022-09-19 01:13:59 +05:30
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
2022-10-29 07:51:43 +05:30
|
|
|
"github.com/klauspost/compress/zlib"
|
2022-09-19 01:13:59 +05:30
|
|
|
"github.com/projectdiscovery/gologger"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v2/internal/runner/nucleicloud"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/loader"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/core"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
2022-11-09 14:18:56 +01:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs"
|
2022-12-21 22:48:43 +05:30
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
2022-09-19 01:13:59 +05:30
|
|
|
"go.uber.org/atomic"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// runStandardEnumeration runs standard enumeration
|
|
|
|
|
func (r *Runner) runStandardEnumeration(executerOpts protocols.ExecuterOptions, store *loader.Store, engine *core.Engine) (*atomic.Bool, error) {
|
|
|
|
|
if r.options.AutomaticScan {
|
|
|
|
|
return r.executeSmartWorkflowInput(executerOpts, store, engine)
|
|
|
|
|
}
|
|
|
|
|
return r.executeTemplatesInput(store, engine)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// runCloudEnumeration runs cloud based enumeration
|
2022-12-21 22:48:43 +05:30
|
|
|
func (r *Runner) runCloudEnumeration(store *loader.Store, cloudTemplates, cloudTargets []string, nostore bool, limit int) (*atomic.Bool, error) {
|
|
|
|
|
count := &atomic.Int64{}
|
2022-09-19 01:13:59 +05:30
|
|
|
now := time.Now()
|
|
|
|
|
defer func() {
|
2022-12-21 22:48:43 +05:30
|
|
|
gologger.Info().Msgf("Scan execution took %s and found %d results", time.Since(now), count.Load())
|
2022-09-19 01:13:59 +05:30
|
|
|
}()
|
|
|
|
|
results := &atomic.Bool{}
|
|
|
|
|
|
2022-10-29 07:51:43 +05:30
|
|
|
// TODO: Add payload file and workflow support for private templates
|
|
|
|
|
catalogChecksums := nucleicloud.ReadCatalogChecksum()
|
|
|
|
|
|
2022-12-07 22:28:45 +05:30
|
|
|
targets := make([]string, 0, r.hmapInputProvider.Count())
|
2022-11-09 14:18:56 +01:00
|
|
|
r.hmapInputProvider.Scan(func(value *contextargs.MetaInput) bool {
|
2022-12-07 22:28:45 +05:30
|
|
|
targets = append(targets, value.Input)
|
2022-10-20 17:23:00 +05:30
|
|
|
return true
|
2022-09-19 01:13:59 +05:30
|
|
|
})
|
|
|
|
|
templates := make([]string, 0, len(store.Templates()))
|
2022-10-29 07:51:43 +05:30
|
|
|
privateTemplates := make(map[string]string)
|
|
|
|
|
|
2022-09-19 01:13:59 +05:30
|
|
|
for _, template := range store.Templates() {
|
2022-10-29 07:51:43 +05:30
|
|
|
data, _ := os.ReadFile(template.Path)
|
|
|
|
|
h := sha1.New()
|
|
|
|
|
_, _ = io.Copy(h, bytes.NewReader(data))
|
|
|
|
|
newhash := hex.EncodeToString(h.Sum(nil))
|
|
|
|
|
|
|
|
|
|
templateRelativePath := getTemplateRelativePath(template.Path)
|
|
|
|
|
if hash, ok := catalogChecksums[templateRelativePath]; ok || newhash == hash {
|
|
|
|
|
templates = append(templates, templateRelativePath)
|
|
|
|
|
} else {
|
|
|
|
|
privateTemplates[filepath.Base(template.Path)] = gzipBase64EncodeData(data)
|
|
|
|
|
}
|
2022-09-19 01:13:59 +05:30
|
|
|
}
|
2022-10-29 07:51:43 +05:30
|
|
|
|
2022-10-22 04:06:52 +05:30
|
|
|
taskID, err := r.cloudClient.AddScan(&nucleicloud.AddScanRequest{
|
2022-10-29 07:51:43 +05:30
|
|
|
RawTargets: targets,
|
|
|
|
|
PublicTemplates: templates,
|
2022-12-21 22:48:43 +05:30
|
|
|
CloudTargets: cloudTargets,
|
|
|
|
|
CloudTemplates: cloudTemplates,
|
2022-10-29 07:51:43 +05:30
|
|
|
PrivateTemplates: privateTemplates,
|
|
|
|
|
IsTemporary: nostore,
|
2022-12-21 22:48:43 +05:30
|
|
|
Filtering: getCloudFilteringFromOptions(r.options),
|
2022-09-19 01:13:59 +05:30
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return results, err
|
|
|
|
|
}
|
2022-12-21 22:48:43 +05:30
|
|
|
gologger.Info().Msgf("Created task with ID: %d", taskID)
|
|
|
|
|
if nostore {
|
|
|
|
|
gologger.Info().Msgf("Cloud scan storage: disabled")
|
|
|
|
|
}
|
2022-09-19 01:13:59 +05:30
|
|
|
time.Sleep(3 * time.Second)
|
|
|
|
|
|
2022-12-21 22:48:43 +05:30
|
|
|
err = r.cloudClient.GetResults(taskID, true, limit, func(re *output.ResultEvent) {
|
2022-09-19 08:38:52 +02:00
|
|
|
results.CompareAndSwap(false, true)
|
2022-12-21 22:48:43 +05:30
|
|
|
_ = count.Inc()
|
2022-09-19 01:13:59 +05:30
|
|
|
|
|
|
|
|
if outputErr := r.output.Write(re); outputErr != nil {
|
|
|
|
|
gologger.Warning().Msgf("Could not write output: %s", err)
|
|
|
|
|
}
|
|
|
|
|
if r.issuesClient != nil {
|
|
|
|
|
if err := r.issuesClient.CreateIssue(re); err != nil {
|
|
|
|
|
gologger.Warning().Msgf("Could not create issue on tracker: %s", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-21 22:48:43 +05:30
|
|
|
})
|
2022-09-19 01:13:59 +05:30
|
|
|
return results, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getTemplateRelativePath(templatePath string) string {
|
|
|
|
|
splitted := strings.SplitN(templatePath, "nuclei-templates", 2)
|
|
|
|
|
if len(splitted) < 2 {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return strings.TrimPrefix(splitted[1], "/")
|
|
|
|
|
}
|
2022-10-29 07:51:43 +05:30
|
|
|
|
|
|
|
|
func gzipBase64EncodeData(data []byte) string {
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
writer, _ := zlib.NewWriterLevel(&buf, zlib.BestCompression)
|
|
|
|
|
_, _ = writer.Write(data)
|
|
|
|
|
_ = writer.Close()
|
|
|
|
|
encoded := base64.StdEncoding.EncodeToString(buf.Bytes())
|
|
|
|
|
return encoded
|
|
|
|
|
}
|
2022-12-21 22:48:43 +05:30
|
|
|
|
|
|
|
|
func getCloudFilteringFromOptions(options *types.Options) *nucleicloud.AddScanRequestConfiguration {
|
|
|
|
|
return &nucleicloud.AddScanRequestConfiguration{
|
|
|
|
|
Authors: options.Authors,
|
|
|
|
|
Tags: options.Tags,
|
|
|
|
|
ExcludeTags: options.ExcludeTags,
|
|
|
|
|
IncludeTags: options.IncludeTags,
|
|
|
|
|
IncludeIds: options.IncludeIds,
|
|
|
|
|
ExcludeIds: options.ExcludeIds,
|
|
|
|
|
IncludeTemplates: options.IncludeTemplates,
|
|
|
|
|
ExcludedTemplates: options.ExcludedTemplates,
|
|
|
|
|
ExcludeMatchers: options.ExcludeMatchers,
|
|
|
|
|
Severities: options.Severities,
|
|
|
|
|
ExcludeSeverities: options.ExcludeSeverities,
|
|
|
|
|
Protocols: options.Protocols,
|
|
|
|
|
ExcludeProtocols: options.ExcludeProtocols,
|
|
|
|
|
IncludeConditions: options.IncludeConditions,
|
|
|
|
|
}
|
|
|
|
|
}
|