adding http pipeline check

This commit is contained in:
Mzack9999 2020-08-27 12:01:21 +02:00
parent a21f098b5b
commit 7091206e27
2 changed files with 80 additions and 0 deletions

View File

@ -97,6 +97,10 @@ func main() {
scanopts.OutputContentLength = options.ContentLength
scanopts.StoreResponse = options.StoreResponse
scanopts.StoreResponseDirectory = options.StoreResponseDir
// Set default verb to GET if none is chosen
if scanopts.Method == "" && options.Method == "" {
options.Method = "GET"
}
if options.Method != "" {
scanopts.Method = options.Method
}
@ -112,6 +116,7 @@ func main() {
scanopts.OutputContentType = options.OutputContentType
scanopts.RequestBody = options.RequestBody
scanopts.Unsafe = options.Unsafe
scanopts.Pipeline = options.Pipeline
// Try to create output folder if it doesnt exist
if options.StoreResponse && !fileutil.FolderExists(options.StoreResponseDir) {
@ -298,6 +303,7 @@ type scanOptions struct {
OutputContentType bool
RequestBody string
Unsafe bool
Pipeline bool
}
func analyze(hp *httpx.HTTPX, protocol string, domain string, port int, scanopts *scanOptions) Result {
@ -436,6 +442,14 @@ retry:
builder.WriteString(" [websocket]")
}
pipeline := false
if scanopts.Pipeline {
pipeline = hp.SupportPipeline(protocol, scanopts.Method, domain, port)
if pipeline {
builder.WriteString(" [pipeline]")
}
}
// store responses in directory
if scanopts.StoreResponse {
domainFile := fmt.Sprintf("%s%s", domain, scanopts.RequestURI)
@ -464,6 +478,7 @@ retry:
WebSocket: isWebSocket,
TlsData: resp.TlsData,
CspData: resp.CspData,
Pipeline: pipeline,
}
}
@ -483,6 +498,7 @@ type Result struct {
ContentType string `json:"content-type,omitempty"`
TlsData *httpx.TlsData `json:"tls,omitempty"`
CspData *httpx.CspData `json:"csp,omitempty"`
Pipeline bool `json:"pipeline,omitempty"`
}
// JSON the result
@ -541,6 +557,7 @@ type Options struct {
Unsafe bool
RequestBody string
Debug bool
Pipeline bool
}
// ParseOptions parses the command line options for application
@ -585,6 +602,7 @@ func ParseOptions() *Options {
flag.BoolVar(&options.Unsafe, "unsafe", false, "Send raw requests skipping golang normalization")
flag.StringVar(&options.RequestBody, "body", "", "Request Body")
flag.BoolVar(&options.Debug, "debug", false, "Debug mode")
flag.BoolVar(&options.Pipeline, "pipeline", false, "HTTP1.1 Pipeline")
flag.Parse()
// Read the inputs and configure the logging

62
common/httpx/pipeline.go Normal file
View File

@ -0,0 +1,62 @@
package httpx
import (
"crypto/tls"
"fmt"
"net"
"strings"
"time"
)
// TODO: this code must be rewritten with rawhttp
// SupportPipeline checks if the target host supports HTTP1.1 pipelining by sending x probes
// and reading back responses expecting at least 2 with HTTP/1.1 or HTTP/1.0
func (h *HTTPX) SupportPipeline(protocol, method, host string, port int) bool {
addr := host
if port > 0 {
addr = fmt.Sprintf("%s:%d", host, port)
}
// dummy method while awaiting for full rawhttp implementation
dummyReq := fmt.Sprintf("%s / HTTP/1.1\nHost: %s\n\n", method, addr)
conn, err := pipelineDial(protocol, addr)
if err != nil {
return false
}
// send some probes
nprobes := 10
for i := 0; i < nprobes; i++ {
if _, err = conn.Write([]byte(dummyReq)); err != nil {
return false
}
}
gotReplies := 0
reply := make([]byte, 1024)
for i := 0; i < nprobes; i++ {
conn.SetReadDeadline(time.Now().Add(1 * time.Second))
if _, err := conn.Read(reply); err != nil {
break
}
// The check is very naive, but it works most of the times
for _, s := range strings.Split(string(reply), "\n\n") {
if strings.Contains(s, "HTTP/1.1") || strings.Contains(s, "HTTP/1.0") {
gotReplies++
}
}
}
// expect at least 2 replies
return gotReplies >= 2
}
func pipelineDial(protocol, addr string) (net.Conn, error) {
// http
if protocol == "http" {
return net.Dial("tcp", addr)
}
// https
return tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
}