mirror of
https://github.com/projectdiscovery/httpx.git
synced 2024-09-11 17:46:08 +03:00
Merge pull request #19 from projectdiscovery/feature-server-fingerprint
adding server basic fingerprint based on server header
This commit is contained in:
commit
6b52546be4
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 ""
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user