2018-11-08 09:26:32 +00:00
|
|
|
package input
|
|
|
|
|
|
|
|
import (
|
2019-11-15 22:40:04 +00:00
|
|
|
"fmt"
|
|
|
|
|
2018-11-08 09:26:32 +00:00
|
|
|
"github.com/ffuf/ffuf/pkg/ffuf"
|
|
|
|
)
|
|
|
|
|
2019-11-10 21:30:54 +00:00
|
|
|
type MainInputProvider struct {
|
2019-11-15 22:40:04 +00:00
|
|
|
Providers []ffuf.InternalInputProvider
|
|
|
|
Config *ffuf.Config
|
|
|
|
position int
|
|
|
|
msbIterator int
|
2019-11-10 21:30:54 +00:00
|
|
|
}
|
|
|
|
|
2020-09-27 16:24:06 +00:00
|
|
|
func NewInputProvider(conf *ffuf.Config) (ffuf.InputProvider, ffuf.Multierror) {
|
2019-11-15 22:40:04 +00:00
|
|
|
validmode := false
|
2020-09-27 16:24:06 +00:00
|
|
|
errs := ffuf.NewMultierror()
|
2019-11-15 22:40:04 +00:00
|
|
|
for _, mode := range []string{"clusterbomb", "pitchfork"} {
|
|
|
|
if conf.InputMode == mode {
|
|
|
|
validmode = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !validmode {
|
2020-09-27 16:24:06 +00:00
|
|
|
errs.Add(fmt.Errorf("Input mode (-mode) %s not recognized", conf.InputMode))
|
|
|
|
return &MainInputProvider{}, errs
|
2019-11-15 22:40:04 +00:00
|
|
|
}
|
2020-09-27 16:24:06 +00:00
|
|
|
mainip := MainInputProvider{Config: conf, msbIterator: 0}
|
|
|
|
// Initialize the correct inputprovider
|
|
|
|
for _, v := range conf.InputProviders {
|
|
|
|
err := mainip.AddProvider(v)
|
|
|
|
if err != nil {
|
|
|
|
errs.Add(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &mainip, errs
|
2019-11-10 21:30:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *MainInputProvider) AddProvider(provider ffuf.InputProviderConfig) error {
|
|
|
|
if provider.Name == "command" {
|
|
|
|
newcomm, _ := NewCommandInput(provider.Keyword, provider.Value, i.Config)
|
|
|
|
i.Providers = append(i.Providers, newcomm)
|
2019-06-16 21:42:42 +00:00
|
|
|
} else {
|
|
|
|
// Default to wordlist
|
2019-11-10 21:30:54 +00:00
|
|
|
newwl, err := NewWordlistInput(provider.Keyword, provider.Value, i.Config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
i.Providers = append(i.Providers, newwl)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//Position will return the current position of progress
|
|
|
|
func (i *MainInputProvider) Position() int {
|
|
|
|
return i.position
|
|
|
|
}
|
|
|
|
|
|
|
|
//Next will increment the cursor position, and return a boolean telling if there's inputs left
|
|
|
|
func (i *MainInputProvider) Next() bool {
|
|
|
|
if i.position >= i.Total() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
i.position++
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-11-15 22:40:04 +00:00
|
|
|
//Value returns a map of inputs for keywords
|
2019-11-10 21:30:54 +00:00
|
|
|
func (i *MainInputProvider) Value() map[string][]byte {
|
2019-11-15 22:40:04 +00:00
|
|
|
retval := make(map[string][]byte)
|
|
|
|
if i.Config.InputMode == "clusterbomb" {
|
|
|
|
retval = i.clusterbombValue()
|
|
|
|
}
|
|
|
|
if i.Config.InputMode == "pitchfork" {
|
|
|
|
retval = i.pitchforkValue()
|
|
|
|
}
|
|
|
|
return retval
|
|
|
|
}
|
|
|
|
|
2019-12-31 12:19:27 +00:00
|
|
|
//Reset resets all the inputproviders and counters
|
|
|
|
func (i *MainInputProvider) Reset() {
|
|
|
|
for _, p := range i.Providers {
|
|
|
|
p.ResetPosition()
|
|
|
|
}
|
|
|
|
i.position = 0
|
|
|
|
i.msbIterator = 0
|
|
|
|
}
|
|
|
|
|
2019-11-15 22:40:04 +00:00
|
|
|
//pitchforkValue returns a map of keyword:value pairs including all inputs.
|
|
|
|
//This mode will iterate through wordlists in lockstep.
|
|
|
|
func (i *MainInputProvider) pitchforkValue() map[string][]byte {
|
2019-11-10 21:30:54 +00:00
|
|
|
values := make(map[string][]byte)
|
|
|
|
for _, p := range i.Providers {
|
|
|
|
if !p.Next() {
|
|
|
|
// Loop to beginning if the inputprovider has been exhausted
|
|
|
|
p.ResetPosition()
|
|
|
|
}
|
|
|
|
values[p.Keyword()] = p.Value()
|
2019-11-15 22:40:04 +00:00
|
|
|
p.IncrementPosition()
|
2019-11-10 21:30:54 +00:00
|
|
|
}
|
|
|
|
return values
|
|
|
|
}
|
|
|
|
|
2019-11-15 22:40:04 +00:00
|
|
|
//clusterbombValue returns map of keyword:value pairs including all inputs.
|
|
|
|
//this mode will iterate through all possible combinations.
|
|
|
|
func (i *MainInputProvider) clusterbombValue() map[string][]byte {
|
|
|
|
values := make(map[string][]byte)
|
|
|
|
// Should we signal the next InputProvider in the slice to increment
|
|
|
|
signalNext := false
|
|
|
|
first := true
|
|
|
|
for index, p := range i.Providers {
|
|
|
|
if signalNext {
|
|
|
|
p.IncrementPosition()
|
|
|
|
signalNext = false
|
|
|
|
}
|
|
|
|
if !p.Next() {
|
|
|
|
// No more inputs in this inputprovider
|
|
|
|
if index == i.msbIterator {
|
|
|
|
// Reset all previous wordlists and increment the msb counter
|
|
|
|
i.msbIterator += 1
|
|
|
|
i.clusterbombIteratorReset()
|
|
|
|
// Start again
|
|
|
|
return i.clusterbombValue()
|
|
|
|
}
|
|
|
|
p.ResetPosition()
|
|
|
|
signalNext = true
|
|
|
|
}
|
|
|
|
values[p.Keyword()] = p.Value()
|
|
|
|
if first {
|
|
|
|
p.IncrementPosition()
|
|
|
|
first = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return values
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *MainInputProvider) clusterbombIteratorReset() {
|
|
|
|
for index, p := range i.Providers {
|
|
|
|
if index < i.msbIterator {
|
|
|
|
p.ResetPosition()
|
|
|
|
}
|
|
|
|
if index == i.msbIterator {
|
|
|
|
p.IncrementPosition()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-10 21:30:54 +00:00
|
|
|
//Total returns the amount of input combinations available
|
|
|
|
func (i *MainInputProvider) Total() int {
|
2019-11-15 22:40:04 +00:00
|
|
|
count := 0
|
|
|
|
if i.Config.InputMode == "pitchfork" {
|
|
|
|
for _, p := range i.Providers {
|
|
|
|
if p.Total() > count {
|
|
|
|
count = p.Total()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if i.Config.InputMode == "clusterbomb" {
|
|
|
|
count = 1
|
|
|
|
for _, p := range i.Providers {
|
|
|
|
count = count * p.Total()
|
|
|
|
}
|
2019-06-16 21:42:42 +00:00
|
|
|
}
|
2019-11-10 21:30:54 +00:00
|
|
|
return count
|
2018-11-08 09:26:32 +00:00
|
|
|
}
|