Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions cmd/pipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package cmd

import (
"bufio"
"encoding/base64"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -35,6 +38,13 @@ func runPipeCmd(cmd *cobra.Command, args []string) {
options.Method = "Pipe Mode"
printing.Summary(options, "Stdin (pipeline)")
options.Method = tMethod

rawdata, _ := cmd.Flags().GetBool("rawdata")
if rawdata {
runRawDataPipeMode(cmd)
return
}

var targets []string
mutex := &sync.Mutex{}
options.Mutex = mutex
Expand All @@ -60,6 +70,71 @@ func runPipeCmd(cmd *cobra.Command, args []string) {
}
}

// runRawDataPipeMode processes a file containing raw HTTP request data
func runRawDataPipeMode(cmd *cobra.Command) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The function runRawDataPipeMode directly exits the program using os.Exit(1) when encountering errors. This abrupt termination can hinder testability and reusability. It's better to return an error to allow the caller function to handle the error gracefully.

Suggested change
func runRawDataPipeMode(cmd *cobra.Command) {
func runRawDataPipeMode(cmd *cobra.Command) error {

printing.DalLog("SYSTEM", "Using pipe mode with raw data format", options)
bytes, err := ioutil.ReadAll(os.Stdin)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The io/ioutil package is deprecated. Use io.ReadAll instead.

Suggested change
bytes, err := ioutil.ReadAll(os.Stdin)
bytes, err := io.ReadAll(os.Stdin)

if err != nil {
printing.DalLog("ERROR", "Failed to read from stdin: "+err.Error(), options)
return
}
rawReq := string(bytes)

// Check if the input is base64 encoded
b64decoded, err := base64.StdEncoding.DecodeString(rawReq)
if err == nil {
rawReq = string(b64decoded)
}

ff := strings.Split(strings.ReplaceAll(rawReq, "\r\n", "\n"), "\n")

var path, body, host, target string
bodyswitch := false
for index, line := range ff {
if index == 0 {
parse := strings.Split(line, " ")
if len(parse) > 1 {
options.Method = parse[0]
path = parse[1]
} else {
printing.DalLog("ERROR", "HTTP Raw Request Format Error", options)
os.Exit(1)
}
} else {
if strings.Contains(line, "Host: ") || strings.Contains(line, "host: ") {
host = line[6:]
} else {
parse := strings.Split(line, ":")
if len(parse) > 1 {
options.Header = append(options.Header, line)
}
}
if bodyswitch {
body = body + line
}
if len(line) == 0 {
bodyswitch = true
}
}
}
Comment on lines +91 to +119
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The HTTP request parsing loop has potential issues:

  • The request body is reconstructed by concatenating lines without considering newlines, which can corrupt multi-line bodies.
  • Using body = body + line for string concatenation in a loop is inefficient for large bodies.
  • Parsing the request line with strings.Split(line, " ") is not robust against multiple spaces.
  • The Host header check is case-sensitive and brittle to extra whitespace.

Consider refactoring the parsing logic to improve correctness and robustness.

var path, host, target string
var body strings.Builder

// Normalize line endings and split headers from body
rawReq = strings.ReplaceAll(rawReq, "\r\n", "\n")
parts := strings.SplitN(rawReq, "\n\n", 2)
headerLines := strings.Split(parts[0], "\n")
if len(parts) > 1 {
	body.WriteString(parts[1])
}

if len(headerLines) == 0 || headerLines[0] == "" {
	printing.DalLog("ERROR", "HTTP Raw Request Format Error: Empty request", options)
	os.Exit(1)
}

// Parse first line (request line)
firstLine := headerLines[0]
parse := strings.Fields(firstLine)
if len(parse) > 1 {
	options.Method = parse[0]
	path = parse[1]
} else {
	printing.DalLog("ERROR", "HTTP Raw Request Format Error", options)
	os.Exit(1)
}

// Parse headers
for _, line := range headerLines[1:] {
	if strings.HasPrefix(strings.ToLower(line), "host:") {
		host = strings.TrimSpace(line[len("host:"):])
	} else if strings.Contains(line, ":") {
		options.Header = append(options.Header, line)
	}
}

options.Data = body
http, _ := cmd.Flags().GetBool("http")
if strings.Index(path, "http") == 0 {
target = path
} else {
if host == "" {
printing.DalLog("ERROR", "HTTP Raw Request Format Error - Host not found", options)
os.Exit(1)
}
if http {
target = "http://" + host + path
} else {
target = "https://" + host + path
}
}
_, _ = scanning.Scan(target, options, "single")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The error returned by scanning.Scan is ignored. Handle the error to prevent silent failures.

_, err = scanning.Scan(target, options, "single")
if err != nil {
	printing.DalLog("ERROR", "Scanning failed for target "+target+": "+err.Error(), options)
}

}

// runMulticastMode processes multiple targets in parallel using worker pools
// It distributes scanning tasks across multiple goroutines for efficient processing
func runMulticastMode(targets []string, cmd *cobra.Command, sf bool, limit int) {
Expand Down Expand Up @@ -209,6 +284,8 @@ func runSingleMode(targets []string, sf bool, limit int) {
// init registers the pipe command and its flags
func init() {
rootCmd.AddCommand(pipeCmd)
pipeCmd.Flags().Bool("rawdata", false, "[FORMAT] Use raw data from Burp/ZAP. Example: --rawdata")
pipeCmd.Flags().Bool("http", false, "Force HTTP on raw data mode. Example: --http")
pipeCmd.Flags().Bool("multicast", false, "Enable parallel scanning in N*Host mode (only shows PoC code). Example: --multicast")
pipeCmd.Flags().Bool("mass", false, "Enable parallel scanning in N*Host mode (only shows PoC code). Example: --mass")
pipeCmd.Flags().Bool("silence-force", false, "Only print PoC code, suppress progress output. Example: --silence-force")
Expand Down
30 changes: 25 additions & 5 deletions docs/page/running/scan-from-rawreq.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ layout: page

This guide provides detailed instructions on how to scan a target using a raw HTTP request with Dalfox. Follow the steps below to perform a scan using a raw request.

## Sample Raw Request
## Using `file` mode

### Sample Raw Request

Create a file named `sample_rawdata.txt` with the following content:

```http
POST https://www.hahwul.com/?q=xspear HTTP/1.1
POST https://www.hahwul.com/?q=dalfox HTTP/1.1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The query parameter value in the sample raw request has been changed from xspear to dalfox. Ensure this change aligns with the intended purpose of the documentation.

Suggested change
POST https://www.hahwul.com/?q=dalfox HTTP/1.1
POST https://www.hahwul.com/?q=xspear HTTP/1.1

User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3
Expand All @@ -28,14 +30,32 @@ Host: www.hahwul.com
asdf=asdf
```

## Command
### Command

To scan using the raw request from a file, use the following command:

```bash
dalfox file ./samples/sample_rawdata.txt --rawdata
```

## Using `pipe` mode

To scan using the raw request, use the following command:
You can also provide the raw request via stdin using the `pipe` command.

### Command

```bash
cat ./samples/sample_rawdata.txt | dalfox pipe --rawdata
```

Or for base64 encoded requests:

```bash
dalfox file --rawdata ./samples/sample_rawdata.txt
cat ./samples/sample_rawdata.txt | base64 | dalfox pipe --rawdata
```

Dalfox will automatically detect if the piped input is base64 encoded and decode it before parsing.

## Output

Here is an example of the output you can expect from running the above command:
Expand Down
Loading