Merge pull request #19 from projectdiscovery/feature-server-fingerprint

adding server basic fingerprint based on server header
This commit is contained in:
bauthard 2020-06-06 16:02:11 +05:30 committed by GitHub
commit 6b52546be4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 30 deletions

View File

@ -54,6 +54,7 @@ func main() {
scanopts.StoreResponse = options.StoreResponse scanopts.StoreResponse = options.StoreResponse
scanopts.StoreResponseDirectory = options.StoreResponseDir scanopts.StoreResponseDirectory = options.StoreResponseDir
scanopts.Method = options.Method scanopts.Method = options.Method
scanopts.OutputServerHeader = options.OutputServerHeader
// Try to create output folder if it doesnt exist // Try to create output folder if it doesnt exist
if options.StoreResponse && options.StoreResponseDir != "" && options.StoreResponseDir != "." { if options.StoreResponse && options.StoreResponseDir != "" && options.StoreResponseDir != "." {
@ -79,7 +80,7 @@ func main() {
defer f.Close() defer f.Close()
} }
for r := range output { for r := range output {
if r.Error != nil { if r.err != nil {
continue continue
} }
row := r.str row := r.str
@ -176,6 +177,7 @@ type scanOptions struct {
OutputContentLength bool OutputContentLength bool
StoreResponse bool StoreResponse bool
StoreResponseDirectory string StoreResponseDirectory string
OutputServerHeader bool
} }
func analyze(hp *httpx.HTTPX, protocol string, domain string, port int, scanopts *scanOptions, output chan Result) { func analyze(hp *httpx.HTTPX, protocol string, domain string, port int, scanopts *scanOptions, output chan Result) {
@ -188,7 +190,7 @@ retry:
req, err := hp.NewRequest(scanopts.Method, URL) req, err := hp.NewRequest(scanopts.Method, URL)
if err != nil { if err != nil {
output <- Result{URL: URL, Error: err} output <- Result{URL: URL, err: err}
return return
} }
@ -196,7 +198,7 @@ retry:
resp, err := hp.Do(req) resp, err := hp.Do(req)
if err != nil { if err != nil {
output <- Result{URL: URL, Error: err} output <- Result{URL: URL, err: err}
if !retried { if !retried {
if protocol == "https" { if protocol == "https" {
protocol = "http" protocol = "http"
@ -236,6 +238,11 @@ retry:
builder.WriteString(fmt.Sprintf(" [%s]", title)) builder.WriteString(fmt.Sprintf(" [%s]", title))
} }
serverHeader := resp.GetHeader("Server")
if scanopts.OutputServerHeader {
builder.WriteString(fmt.Sprintf(" [%s]", serverHeader))
}
// check for virtual host // check for virtual host
isvhost := false isvhost := false
if scanopts.VHost { if scanopts.VHost {
@ -251,7 +258,7 @@ retry:
ioutil.WriteFile(responsePath, []byte(resp.Raw), 0644) ioutil.WriteFile(responsePath, []byte(resp.Raw), 0644)
} }
output <- Result{URL: fullURL, ContentLength: resp.ContentLength, StatusCode: resp.StatusCode, Title: title, str: builder.String(), VHost: isvhost} output <- Result{URL: fullURL, ContentLength: resp.ContentLength, StatusCode: resp.StatusCode, Title: title, str: builder.String(), VHost: isvhost, WebServer: serverHeader}
} }
// Result of a scan // Result of a scan
@ -261,8 +268,9 @@ type Result struct {
StatusCode int `json:"status-code"` StatusCode int `json:"status-code"`
Title string `json:"title"` Title string `json:"title"`
str string str string
Error error `json:"error"` err error
VHost bool `json:"vhost"` VHost bool `json:"vhost"`
WebServer string `json:"webserver"`
} }
// JSON the result // JSON the result

View File

@ -12,30 +12,31 @@ import (
// Options contains configuration options for chaos client. // Options contains configuration options for chaos client.
type Options struct { type Options struct {
RawRequestFile string RawRequestFile string
VHost bool VHost bool
Smuggling bool Smuggling bool
ExtractTitle bool ExtractTitle bool
StatusCode bool StatusCode bool
ContentLength bool ContentLength bool
Retries int Retries int
Threads int Threads int
Timeout int Timeout int
CustomHeaders customheader.CustomHeaders CustomHeaders customheader.CustomHeaders
CustomPorts customport.CustomPorts CustomPorts customport.CustomPorts
Output string Output string
FollowRedirects bool FollowRedirects bool
StoreResponse bool StoreResponse bool
StoreResponseDir string StoreResponseDir string
HttpProxy string HttpProxy string
SocksProxy string SocksProxy string
JSONOutput bool JSONOutput bool
InputFile string InputFile string
Method string Method string
Silent bool Silent bool
Version bool Version bool
Verbose bool Verbose bool
NoColor bool NoColor bool
OutputServerHeader bool
} }
// ParseOptions parses the command line options for application // ParseOptions parses the command line options for application
@ -63,6 +64,7 @@ func ParseOptions() *Options {
flag.BoolVar(&options.Version, "version", false, "Show version of httpx") flag.BoolVar(&options.Version, "version", false, "Show version of httpx")
flag.BoolVar(&options.Verbose, "verbose", false, "Verbose Mode") flag.BoolVar(&options.Verbose, "verbose", false, "Verbose Mode")
flag.BoolVar(&options.NoColor, "no-color", false, "No Color") flag.BoolVar(&options.NoColor, "no-color", false, "No Color")
flag.BoolVar(&options.OutputServerHeader, "web-server", false, "Prints out the Server header content")
flag.Parse() flag.Parse()
// Read the inputs and configure the logging // Read the inputs and configure the logging

View File

@ -85,6 +85,8 @@ func (h *HTTPX) Do(req *retryablehttp.Request) (*Response, error) {
return nil, err return nil, err
} }
resp.Headers = httpresp.Header.Clone()
rawresp, err := httputil.DumpResponse(httpresp, true) rawresp, err := httputil.DumpResponse(httpresp, true)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -1,5 +1,9 @@
package httpx package httpx
import (
"strings"
)
// Response contains the response to a server // Response contains the response to a server
type Response struct { type Response struct {
StatusCode int StatusCode int
@ -10,3 +14,13 @@ type Response struct {
Words int Words int
Lines int Lines int
} }
// GetHeader value
func (r *Response) GetHeader(name string) string {
v, ok := r.Headers[name]
if ok {
return strings.Join(v, " ")
}
return ""
}