mirror of
https://github.com/projectdiscovery/httpx.git
synced 2024-12-01 12:13:00 +03:00
adding http pipeline check
This commit is contained in:
parent
a21f098b5b
commit
7091206e27
@ -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
62
common/httpx/pipeline.go
Normal 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})
|
||||
}
|
Loading…
Reference in New Issue
Block a user