Add TLS SNI Support (#441)

* add SNI support to ffuf

* remove change to keywordPresent

* Update CONTRIBUTORS.md

* Update CHANGELOG.md
This commit is contained in:
Samuel Erb 2021-05-13 16:46:29 -04:00 committed by GitHub
parent ee0705e224
commit 5ad06815cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 20 additions and 5 deletions

View File

@ -1,6 +1,7 @@
## Changelog ## Changelog
- master - master
- New - New
- Added a CLI flag to specify TLS SNI value
- Changed - Changed
- Fixed an issue where output file was created regardless of `-or` - Fixed an issue where output file was created regardless of `-or`

View File

@ -10,6 +10,7 @@
* [Damian89](https://github.com/Damian89) * [Damian89](https://github.com/Damian89)
* [Daviey](https://github.com/Daviey) * [Daviey](https://github.com/Daviey)
* [delic](https://github.com/delic) * [delic](https://github.com/delic)
* [erbbysam](https://github.com/erbbysam)
* [eur0pa](https://github.com/eur0pa) * [eur0pa](https://github.com/eur0pa)
* [fabiobauer](https://github.com/fabiobauer) * [fabiobauer](https://github.com/fabiobauer)
* [fang0654](https://github.com/fang0654) * [fang0654](https://github.com/fang0654)

View File

@ -171,6 +171,7 @@ HTTP OPTIONS:
-recursion-depth Maximum recursion depth. (default: 0) -recursion-depth Maximum recursion depth. (default: 0)
-recursion-strategy Recursion strategy: "default" for a redirect based, and "greedy" to recurse on all matches (default: default) -recursion-strategy Recursion strategy: "default" for a redirect based, and "greedy" to recurse on all matches (default: default)
-replay-proxy Replay matched requests using this proxy. -replay-proxy Replay matched requests using this proxy.
-sni Target TLS SNI, does not support FUZZ keyword
-timeout HTTP request timeout in seconds. (default: 10) -timeout HTTP request timeout in seconds. (default: 10)
-u Target URL -u Target URL
-x Proxy URL (SOCKS5 or HTTP). For example: http://127.0.0.1:8080 or socks5://127.0.0.1:8080 -x Proxy URL (SOCKS5 or HTTP). For example: http://127.0.0.1:8080 or socks5://127.0.0.1:8080

View File

@ -54,7 +54,7 @@ func Usage() {
Description: "Options controlling the HTTP request and its parts.", Description: "Options controlling the HTTP request and its parts.",
Flags: make([]UsageFlag, 0), Flags: make([]UsageFlag, 0),
Hidden: false, Hidden: false,
ExpectedFlags: []string{"H", "X", "b", "d", "r", "u", "recursion", "recursion-depth", "recursion-strategy", "replay-proxy", "timeout", "ignore-body", "x"}, ExpectedFlags: []string{"H", "X", "b", "d", "r", "u", "recursion", "recursion-depth", "recursion-strategy", "replay-proxy", "timeout", "ignore-body", "x", "sni"},
} }
u_general := UsageSection{ u_general := UsageSection{
Name: "GENERAL OPTIONS", Name: "GENERAL OPTIONS",

10
main.go
View File

@ -4,16 +4,17 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"log"
"os"
"strings"
"github.com/ffuf/ffuf/pkg/ffuf" "github.com/ffuf/ffuf/pkg/ffuf"
"github.com/ffuf/ffuf/pkg/filter" "github.com/ffuf/ffuf/pkg/filter"
"github.com/ffuf/ffuf/pkg/input" "github.com/ffuf/ffuf/pkg/input"
"github.com/ffuf/ffuf/pkg/interactive" "github.com/ffuf/ffuf/pkg/interactive"
"github.com/ffuf/ffuf/pkg/output" "github.com/ffuf/ffuf/pkg/output"
"github.com/ffuf/ffuf/pkg/runner" "github.com/ffuf/ffuf/pkg/runner"
"io/ioutil"
"log"
"os"
"strings"
) )
type multiStringFlag []string type multiStringFlag []string
@ -96,6 +97,7 @@ func ParseFlags(opts *ffuf.ConfigOptions) *ffuf.ConfigOptions {
flag.StringVar(&opts.HTTP.ReplayProxyURL, "replay-proxy", opts.HTTP.ReplayProxyURL, "Replay matched requests using this proxy.") flag.StringVar(&opts.HTTP.ReplayProxyURL, "replay-proxy", opts.HTTP.ReplayProxyURL, "Replay matched requests using this proxy.")
flag.StringVar(&opts.HTTP.RecursionStrategy, "recursion-strategy", opts.HTTP.RecursionStrategy, "Recursion strategy: \"default\" for a redirect based, and \"greedy\" to recurse on all matches") flag.StringVar(&opts.HTTP.RecursionStrategy, "recursion-strategy", opts.HTTP.RecursionStrategy, "Recursion strategy: \"default\" for a redirect based, and \"greedy\" to recurse on all matches")
flag.StringVar(&opts.HTTP.URL, "u", opts.HTTP.URL, "Target URL") flag.StringVar(&opts.HTTP.URL, "u", opts.HTTP.URL, "Target URL")
flag.StringVar(&opts.HTTP.SNI, "sni", opts.HTTP.SNI, "Target TLS SNI, does not support FUZZ keyword")
flag.StringVar(&opts.Input.Extensions, "e", opts.Input.Extensions, "Comma separated list of extensions. Extends FUZZ keyword.") flag.StringVar(&opts.Input.Extensions, "e", opts.Input.Extensions, "Comma separated list of extensions. Extends FUZZ keyword.")
flag.StringVar(&opts.Input.InputMode, "mode", opts.Input.InputMode, "Multi-wordlist operation mode. Available modes: clusterbomb, pitchfork") flag.StringVar(&opts.Input.InputMode, "mode", opts.Input.InputMode, "Multi-wordlist operation mode. Available modes: clusterbomb, pitchfork")
flag.StringVar(&opts.Input.InputShell, "input-shell", opts.Input.InputShell, "Shell to be used for running command") flag.StringVar(&opts.Input.InputShell, "input-shell", opts.Input.InputShell, "Shell to be used for running command")

View File

@ -43,6 +43,7 @@ type Config struct {
RecursionDepth int `json:"recursion_depth"` RecursionDepth int `json:"recursion_depth"`
RecursionStrategy string `json:"recursion_strategy"` RecursionStrategy string `json:"recursion_strategy"`
ReplayProxyURL string `json:"replayproxyurl"` ReplayProxyURL string `json:"replayproxyurl"`
SNI string `json:"sni"`
StopOn403 bool `json:"stop_403"` StopOn403 bool `json:"stop_403"`
StopOnAll bool `json:"stop_all"` StopOnAll bool `json:"stop_all"`
StopOnErrors bool `json:"stop_errors"` StopOnErrors bool `json:"stop_errors"`
@ -88,6 +89,7 @@ func NewConfig(ctx context.Context, cancel context.CancelFunc) Config {
conf.Recursion = false conf.Recursion = false
conf.RecursionDepth = 0 conf.RecursionDepth = 0
conf.RecursionStrategy = "default" conf.RecursionStrategy = "default"
conf.SNI = ""
conf.StopOn403 = false conf.StopOn403 = false
conf.StopOnAll = false conf.StopOnAll = false
conf.StopOnErrors = false conf.StopOnErrors = false

View File

@ -37,6 +37,7 @@ type HTTPOptions struct {
RecursionDepth int RecursionDepth int
RecursionStrategy string RecursionStrategy string
ReplayProxyURL string ReplayProxyURL string
SNI string
Timeout int Timeout int
URL string URL string
} }
@ -129,6 +130,7 @@ func NewConfigOptions() *ConfigOptions {
c.HTTP.RecursionStrategy = "default" c.HTTP.RecursionStrategy = "default"
c.HTTP.ReplayProxyURL = "" c.HTTP.ReplayProxyURL = ""
c.HTTP.Timeout = 10 c.HTTP.Timeout = 10
c.HTTP.SNI = ""
c.HTTP.URL = "" c.HTTP.URL = ""
c.Input.DirSearchCompat = false c.Input.DirSearchCompat = false
c.Input.Extensions = "" c.Input.Extensions = ""
@ -249,6 +251,11 @@ func ConfigFromOptions(parseOpts *ConfigOptions, ctx context.Context, cancel con
conf.Url = parseOpts.HTTP.URL conf.Url = parseOpts.HTTP.URL
} }
// Prepare SNI
if parseOpts.HTTP.SNI != "" {
conf.SNI = parseOpts.HTTP.SNI
}
//Prepare headers and make canonical //Prepare headers and make canonical
for _, v := range parseOpts.HTTP.Headers { for _, v := range parseOpts.HTTP.Headers {
hs := strings.SplitN(v, ":", 2) hs := strings.SplitN(v, ":", 2)

View File

@ -58,6 +58,7 @@ func NewSimpleRunner(conf *ffuf.Config, replay bool) ffuf.RunnerProvider {
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
Renegotiation: tls.RenegotiateOnceAsClient, Renegotiation: tls.RenegotiateOnceAsClient,
ServerName: conf.SNI,
}, },
}} }}