Merge pull request #124 from edoardottt/store-resp

Store resp
This commit is contained in:
vrenzolaverace
2023-06-09 11:37:45 +02:00
committed by GitHub
13 changed files with 420 additions and 142 deletions
-1
View File
@@ -5,7 +5,6 @@ linters:
enable:
- asciicheck
- bodyclose
- depguard
- dogsled
- dupl
- errcheck
+68 -63
View File
@@ -56,7 +56,7 @@
<a href="#license-">License</a>
</p>
Preview :bar_chart:
Preview 📊
----------
<!--[![asciicast](https://asciinema.org/a/415989.svg)](https://asciinema.org/a/415989)-->
@@ -69,11 +69,13 @@ Installation 📡
----------
### Using Snap
```bash
sudo snap install cariddi
```
### Using Go
```bash
go install -v github.com/edoardottt/cariddi/cmd/cariddi@latest
```
@@ -97,7 +99,7 @@ You need [Go](https://golang.org/).
- `git clone https://github.com/edoardottt/cariddi.git`
- `cd cariddi`
- `go get ./...`
- `.\make.bat windows` (to install)
- `.\make.bat windows` (to install)
- `.\make.bat unwindows` (to uninstall)
Get Started 🎉
@@ -108,99 +110,101 @@ Get Started 🎉
```
Usage of cariddi:
-c int
Concurrency level. (default 20)
Concurrency level. (default 20)
-cache
Use the .cariddi_cache folder as cache.
Use the .cariddi_cache folder as cache.
-d int
Delay between a page crawled and another.
Delay between a page crawled and another.
-debug
Print debug information while crawling.
-e Hunt for juicy endpoints.
Print debug information while crawling.
-e Hunt for juicy endpoints.
-ef string
Use an external file (txt, one per line) to use custom parameters for endpoints hunting.
Use an external file (txt, one per line) to use custom parameters for endpoints hunting.
-err
Hunt for errors in websites.
Hunt for errors in websites.
-examples
Print the examples.
Print the examples.
-ext int
Hunt for juicy file extensions. Integer from 1(juicy) to 7(not juicy).
-h Print the help.
Hunt for juicy file extensions. Integer from 1(juicy) to 7(not juicy).
-h Print the help.
-headers string
Use custom headers for each request E.g. -headers "Cookie: auth=yes;;Client: type=2".
Use custom headers for each request E.g. -headers "Cookie: auth=yes;;Client: type=2".
-headersfile string
Read from an external file custom headers (same format of headers flag).
Read from an external file custom headers (same format of headers flag).
-json
Print the output as JSON in stdout.
Print the output as JSON in stdout.
-i string
Ignore the URL containing at least one of the elements of this array.
Ignore the URL containing at least one of the elements of this array.
-info
Hunt for useful informations in websites.
Hunt for useful informations in websites.
-intensive
Crawl searching for resources matching 2nd level domain.
Crawl searching for resources matching 2nd level domain.
-it string
Ignore the URL containing at least one of the lines of this file.
Ignore the URL containing at least one of the lines of this file.
-oh string
Write the output into an HTML file.
Write the output into an HTML file.
-ot string
Write the output into a TXT file.
Write the output into a TXT file.
-plain
Print only the results.
Print only the results.
-proxy string
Set a Proxy to be used (http and socks5 supported).
Set a Proxy to be used (http and socks5 supported).
-rua
Use a random browser user agent on every request.
-s Hunt for secrets.
Use a random browser user agent on every request.
-s Hunt for secrets.
-sf string
Use an external file (txt, one per line) to use custom regexes for secrets hunting.
Use an external file (txt, one per line) to use custom regexes for secrets hunting.
-sr
Store HTTP responses.
-t int
Set timeout for the requests. (default 10)
Set timeout for the requests. (default 10)
-ua string
Use a custom User Agent.
Use a custom User Agent.
-version
Print the version.
Print the version.
```
Examples 💡
----------
- `cariddi -version` (Print the version)
- `cariddi -h` (Print the help)
- `cariddi -examples` (Print the examples)
- `cat urls | cariddi -s` (Hunt for secrets)
- `cat urls | cariddi -d 2` (2 seconds between a page crawled and another)
- `cat urls | cariddi -c 200` (Set the concurrency level to 200)
- `cat urls | cariddi -e` (Hunt for juicy endpoints)
- `cat urls | cariddi -plain` (Print only results)
- `cat urls | cariddi -ot target_name` (Results in txt file)
- `cat urls | cariddi -oh target_name` (Results in html file)
- `cat urls | cariddi -ext 2` (Hunt for juicy (level 2 out of 7) files)
- `cat urls | cariddi -e -ef endpoints_file` (Hunt for custom endpoints)
- `cat urls | cariddi -s -sf secrets_file` (Hunt for custom secrets)
- `cat urls | cariddi -i forum,blog,community,open` (Ignore urls containing these words)
- `cat urls | cariddi -it ignore_file` (Ignore urls containing at least one line in the input file)
- `cat urls | cariddi -cache` (Use the .cariddi_cache folder as cache)
- `cat urls | cariddi -t 5` (Set the timeout for the requests)
- `cat urls | cariddi -intensive` (Crawl searching also subdomains, same as `*.target.com`)
- `cat urls | cariddi -rua` (Use a random browser user agent on every request)
- `cat urls | cariddi -proxy http://127.0.0.1:8080` (Set a Proxy, http and socks5 supported)
- `cat urls | cariddi -headers "Cookie: auth=admin;type=2;; X-Custom: customHeader"`
- `cat urls | cariddi -headersfile headers.txt` (Read from an external file custom headers)
- `cat urls | cariddi -err` (Hunt for errors in websites)
- `cat urls | cariddi -info` (Hunt for useful informations in websites)
- `cat urls | cariddi -debug` (Print debug information while crawling)
- `cat urls | cariddi -ua "Custom User Agent"` (Use a custom User Agent)
- `cat urls | cariddi -json` (Print the output as JSON in stdout)
- `cat urls | cariddi -json | jq .` (Pipe the JSON output into jq)
- `cariddi -version` (Print the version)
- `cariddi -h` (Print the help)
- `cariddi -examples` (Print the examples)
- `cat urls | cariddi -s` (Hunt for secrets)
- `cat urls | cariddi -d 2` (2 seconds between a page crawled and another)
- `cat urls | cariddi -c 200` (Set the concurrency level to 200)
- `cat urls | cariddi -e` (Hunt for juicy endpoints)
- `cat urls | cariddi -plain` (Print only results)
- `cat urls | cariddi -ot target_name` (Results in txt file)
- `cat urls | cariddi -oh target_name` (Results in html file)
- `cat urls | cariddi -ext 2` (Hunt for juicy (level 2 out of 7) files)
- `cat urls | cariddi -e -ef endpoints_file` (Hunt for custom endpoints)
- `cat urls | cariddi -s -sf secrets_file` (Hunt for custom secrets)
- `cat urls | cariddi -i forum,blog,community,open` (Ignore urls containing these words)
- `cat urls | cariddi -it ignore_file` (Ignore urls containing at least one line in the input file)
- `cat urls | cariddi -cache` (Use the .cariddi_cache folder as cache)
- `cat urls | cariddi -t 5` (Set the timeout for the requests)
- `cat urls | cariddi -intensive` (Crawl searching also subdomains, same as `*.target.com`)
- `cat urls | cariddi -rua` (Use a random browser user agent on every request)
- `cat urls | cariddi -proxy http://127.0.0.1:8080` (Set a Proxy, http and socks5 supported)
- `cat urls | cariddi -headers "Cookie: auth=admin;type=2;; X-Custom: customHeader"`
- `cat urls | cariddi -headersfile headers.txt` (Read from an external file custom headers)
- `cat urls | cariddi -err` (Hunt for errors in websites)
- `cat urls | cariddi -info` (Hunt for useful informations in websites)
- `cat urls | cariddi -debug` (Print debug information while crawling)
- `cat urls | cariddi -ua "Custom User Agent"` (Use a custom User Agent)
- `cat urls | cariddi -json` (Print the output as JSON in stdout)
- `cat urls | cariddi -sr` (Store HTTP responses)
- For Windows:
- use `powershell.exe -Command "cat urls | .\cariddi.exe"` inside the Command prompt
- or just `cat urls | cariddi.exe` using PowerShell
- For Windows:
- use `powershell.exe -Command "cat urls | .\cariddi.exe"` inside the Command prompt
- or just `cat urls | cariddi.exe` using PowerShell
- To integrate cariddi with Burpsuite [make sure to follow these steps](https://github.com/edoardottt/cariddi/wiki/BurpSuite-Integration).
- To integrate cariddi with Burpsuite [make sure to follow these steps](https://github.com/edoardottt/cariddi/wiki/BurpSuite-Integration).
Changelog 📌
-------
Detailed changes for each release are documented in the [release notes](https://github.com/edoardottt/cariddi/releases).
Contributing 🛠
@@ -209,16 +213,17 @@ Contributing 🛠
Just open an [issue](https://github.com/edoardottt/cariddi/issues)/[pull request](https://github.com/edoardottt/cariddi/pulls).
Before opening a pull request, download [golangci-lint](https://golangci-lint.run/usage/install/) and run
```bash
golangci-lint run
```
If there aren't errors, go ahead :)
**Help me building this!**
Special thanks to: [go-colly](http://go-colly.org/), [zricethezav](https://github.com/zricethezav/gitleaks/blob/master/config/default.go), [projectdiscovery](https://github.com/projectdiscovery/nuclei-templates/tree/master/file/keys), [tomnomnom](https://github.com/tomnomnom/gf/tree/master/examples), [RegexPassive](https://github.com/hahwul/RegexPassive) and [all the contributors](https://github.com/edoardottt/cariddi/wiki/Contributors).
License 📝
-------
+5
View File
@@ -86,6 +86,7 @@ func main() {
InfoFlag: flags.Info,
Debug: flags.Debug,
UserAgent: flags.UserAgent,
StoreResp: flags.StoreResp,
}
// Read the targets from standard input.
@@ -126,6 +127,10 @@ func main() {
output.HeaderHTML("Results", ResultHTML)
}
if config.StoreResp {
fileUtils.CreateIndexOutputFile("index.responses.txt")
}
// Read headers if needed
if flags.HeadersFile != "" || flags.Headers != "" {
var headersInput string
+41 -5
View File
@@ -33,6 +33,7 @@ import (
"log"
"net/http"
"os"
"path/filepath"
"strings"
)
@@ -52,20 +53,32 @@ func CreateOutputFolder() {
}
}
// CreateOutputFile takes a target (of the attack), a subcommand
// CreateHostOutputFolder creates the host output folder
// for the HTTP responses.
// If it fails exits with an error message.
func CreateHostOutputFolder(host string) {
// Create a folder/directory at a full qualified path
err := os.MkdirAll(filepath.Join("output-cariddi", host), Permission0755)
if err != nil {
fmt.Println("Can't create host output folder.")
os.Exit(1)
}
}
// CreateOutputFile takes as input a target (of the attack), a subcommand
// (PORT-DNS-DIR-SUBDOMAIN-REPORT) and a format (json-html-txt).
// It creates the output folder if needed, then checks if the output file
// already exists, if yes asks the user if scilla has to overwrite it;
// if no scilla creates it.
// already exists, if yes asks the user if cariddi has to overwrite it;
// if no cariddi creates it.
// Whenever an instruction fails, it exits with an error message.
func CreateOutputFile(target string, subcommand string, format string) string {
target = ReplaceBadCharacterOutput(target)
var filename string
if subcommand != "" {
filename = "output-cariddi" + "/" + target + "." + subcommand + "." + format
filename = filepath.Join("output-cariddi", target+"."+subcommand+"."+format)
} else {
filename = "output-cariddi" + "/" + target + "." + format
filename = filepath.Join("output-cariddi", target+"."+format)
}
_, err := os.Stat(filename)
@@ -101,6 +114,29 @@ func CreateOutputFile(target string, subcommand string, format string) string {
return filename
}
// CreateIndexOutputFile takes as input the name of the index file.
// It creates the output folder if needed, then checks if the index output file
// already exists, if no cariddi creates it.
// Whenever an instruction fails, it exits with an error message.
func CreateIndexOutputFile(filename string) {
_, err := os.Stat(filename)
if os.IsNotExist(err) {
if _, err := os.Stat("output-cariddi/"); os.IsNotExist(err) {
CreateOutputFolder()
}
// If the file doesn't exist, create it.
filename = filepath.Join("output-cariddi", filename)
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, Permission0644)
if err != nil {
fmt.Println("Can't create output file.")
os.Exit(1)
}
f.Close()
}
}
// ReplaceBadCharacterOutput replaces forward-slashes
// with dashes (to avoid problems with output folder).
func ReplaceBadCharacterOutput(input string) string {
+13 -60
View File
@@ -48,59 +48,6 @@ import (
"github.com/gocolly/colly/extensions"
)
type Results struct {
URLs []string
Secrets []scanner.SecretMatched
Endpoints []scanner.EndpointMatched
Extensions []scanner.FileTypeMatched
Errors []scanner.ErrorMatched
Infos []scanner.InfoMatched
}
type Scan struct {
// Flags
Cache bool
Debug bool
EndpointsFlag bool
ErrorsFlag bool
InfoFlag bool
Intensive bool
Plain bool
Rua bool
SecretsFlag bool
Ignore string
IgnoreTxt string
JSON bool
HTML string
Proxy string
Target string
Txt string
UserAgent string
FileType int
Headers map[string]string
// Settings
Concurrency int
Delay int
Timeout int
// Storage
SecretsSlice []string
EndpointsSlice []string
}
type Event struct {
ProtocolTemp string
TargetTemp string
Target string
Intensive bool
Ignore bool
Debug bool
JSON bool
IgnoreSlice []string
URLs *[]string
}
// New it's the actual crawler engine.
// It controls all the behaviours of a scan
// (event handlers, secrets, errors, extensions and endpoints scanning).
@@ -182,6 +129,17 @@ func New(scan *Scan) *Results {
}
c.OnResponse(func(r *colly.Response) {
if !scan.JSON {
fmt.Println(r.Request.URL)
}
if scan.StoreResp {
err := output.StoreHTTPResponse(r)
if err != nil {
log.Println(err)
}
}
minBodyLentgh := 10
lengthOk := len(string(r.Body)) > minBodyLentgh
secrets := []scanner.SecretMatched{}
@@ -231,10 +189,12 @@ func New(scan *Scan) *Results {
infos = append(infos, infosSlice...)
}
}
if scan.JSON {
jsonOutput, err := output.GetJSONString(
r, secrets, parameters, filetype, errors, infos,
)
if err == nil {
fmt.Println(string(jsonOutput))
} else {
@@ -374,13 +334,6 @@ func CreateColly(delayTime int, concurrency int, cache bool, timeout int,
// registerHTMLEvents registers the associated functions for each
// HTML event triggering an action.
func registerHTMLEvents(c *colly.Collector, event *Event) {
// On every request that Colly is making, print the URL it's currently visiting
c.OnRequest(func(e *colly.Request) {
if !event.JSON {
fmt.Println(e.URL.String())
}
})
// On every a element which has href attribute call callback
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
link := e.Attr("href")
+83
View File
@@ -0,0 +1,83 @@
/*
==========
Cariddi
==========
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
@Repository: https://github.com/edoardottt/cariddi
@Author: edoardottt, https://www.edoardoottavianelli.it
@License: https://github.com/edoardottt/cariddi/blob/main/LICENSE
*/
package crawler
import "github.com/edoardottt/cariddi/pkg/scanner"
type Results struct {
URLs []string
Secrets []scanner.SecretMatched
Endpoints []scanner.EndpointMatched
Extensions []scanner.FileTypeMatched
Errors []scanner.ErrorMatched
Infos []scanner.InfoMatched
}
type Scan struct {
// Flags
Cache bool
Debug bool
EndpointsFlag bool
ErrorsFlag bool
InfoFlag bool
Intensive bool
Plain bool
Rua bool
SecretsFlag bool
Ignore string
IgnoreTxt string
JSON bool
HTML string
Proxy string
Target string
Txt string
UserAgent string
FileType int
Headers map[string]string
StoreResp bool
// Settings
Concurrency int
Delay int
Timeout int
// Storage
SecretsSlice []string
EndpointsSlice []string
}
type Event struct {
ProtocolTemp string
TargetTemp string
Target string
Intensive bool
Ignore bool
Debug bool
JSON bool
IgnoreSlice []string
URLs *[]string
}
+4
View File
@@ -65,6 +65,7 @@ type Input struct {
Info bool
Debug bool
UserAgent string
StoreResp bool
}
// ScanFlag defines all the options taken
@@ -111,6 +112,8 @@ func ScanFlag() Input {
userAgentPtr := flag.String("ua", "", "Use a custom User Agent.")
storeRespPtr := flag.Bool("sr", false, "Store HTTP responses.")
flag.Parse()
result := Input{
@@ -141,6 +144,7 @@ func ScanFlag() Input {
*infoPtr,
*debugPtr,
*userAgentPtr,
*storeRespPtr,
}
return result
+1 -1
View File
@@ -35,7 +35,7 @@ import (
// nolint: checknoglobals
const (
version = "v1.3.1"
version = "v1.3.2"
banner = ` _ _ _ _
(_) | | | (_)
___ __ _ _ __ _ __| | __| |_
+8 -8
View File
@@ -72,19 +72,19 @@ func PrintExamples() {
cat urls | cariddi -proxy http://127.0.0.1:8080 (Set a Proxy to be used (http and socks5 supported))
cat urls | cariddi -headers "Cookie: auth=admin;type=2;; X-Custom: customHeader"
cat urls | cariddi -headers "Cookie: auth=admin;type=2;; X-Custom: customHeader (Use custom headers)"
cat urls | cariddi -headersfile headers.txt
cat urls | cariddi -headersfile headers.txt (Read from an external file custom headers)
cat urls | cariddi -err
cat urls | cariddi -err (Hunt for errors)
cat urls | cariddi -info
cat urls | cariddi -info (Hunt for useful information)
cat urls | cariddi -debug
cat urls | cariddi -debug (Print debug information)
cat urls | cariddi -ua "Custom User Agent"
cat urls | cariddi -ua "Custom User Agent" (Use a custom User Agent)
cat urls | cariddi -json
cat urls | cariddi -json (Print the output as JSON)
cat urls | cariddi -json | jq .`)
cat urls | cariddi -sr (Store HTTP responses)`)
}
+3 -1
View File
@@ -59,7 +59,7 @@ func PrintHelp() {
-i string
Ignore the URL containing at least one of the elements of this array.
-info
Hunt for useful informations in websites.
Hunt for useful information in websites.
-intensive
Crawl searching for resources matching 2nd level domain.
-it string
@@ -77,6 +77,8 @@ func PrintHelp() {
-s Hunt for secrets.
-sf string
Use an external file (txt, one per line) to use custom regexes for secrets hunting.
-sr
Store HTTP responses.
-t int
Set timeout for the requests. (default 10)
-ua
+6 -2
View File
@@ -36,6 +36,10 @@ import (
"github.com/edoardottt/cariddi/pkg/scanner"
)
const (
CariddiOutputFolder = "output-cariddi"
)
// PrintSimpleOutput prints line by line.
func PrintSimpleOutput(out []string) {
for _, elem := range out {
@@ -48,7 +52,7 @@ func PrintSimpleOutput(out []string) {
func TxtOutput(flags input.Input, finalResults []string, finalSecret []scanner.SecretMatched,
finalEndpoints []scanner.EndpointMatched, finalExtensions []scanner.FileTypeMatched,
finalErrors []scanner.ErrorMatched, finalInfos []scanner.InfoMatched) {
exists, err := fileUtils.ElementExists("output-cariddi")
exists, err := fileUtils.ElementExists(CariddiOutputFolder)
if err != nil {
fmt.Println("Error while creating the output directory.")
os.Exit(1)
@@ -120,7 +124,7 @@ func TxtOutput(flags input.Input, finalResults []string, finalSecret []scanner.S
func HTMLOutput(flags input.Input, resultFilename string, finalResults []string, finalSecret []scanner.SecretMatched,
finalEndpoints []scanner.EndpointMatched, finalExtensions []scanner.FileTypeMatched,
finalErrors []scanner.ErrorMatched, finalInfos []scanner.InfoMatched) {
exists, err := fileUtils.ElementExists("output-cariddi")
exists, err := fileUtils.ElementExists(CariddiOutputFolder)
if err != nil {
fmt.Println("Error while creating the output directory.")
+187
View File
@@ -0,0 +1,187 @@
/*
==========
Cariddi
==========
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
@Repository: https://github.com/edoardottt/cariddi
@Author: edoardottt, https://www.edoardoottavianelli.it
@License: https://github.com/edoardottt/cariddi/blob/main/LICENSE
*/
package output
import (
"bytes"
"crypto/sha1"
"encoding/hex"
"errors"
"fmt"
"io"
"log"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/gocolly/colly"
fileUtils "github.com/edoardottt/cariddi/internal/file"
)
const (
index = "index.responses.txt"
)
var (
ErrHTTPResp = errors.New("cannot store HTTP response")
)
func getResponseHash(url string) string {
hash := sha1.Sum([]byte(url))
return hex.EncodeToString(hash[:])
}
// FormatResponse formats an HTTP response ready to be written in a file.
func FormatResponse(resp *colly.Response) ([]byte, error) {
builder := &bytes.Buffer{}
builder.WriteString(resp.Request.URL.String())
builder.WriteString("\n\n\n")
builder.WriteString(resp.Request.Method)
builder.WriteString(" ")
path := resp.Request.URL.Path
if resp.Request.URL.Fragment != "" {
path = path + "#" + resp.Request.URL.Fragment
}
builder.WriteString(path)
builder.WriteString(" ")
builder.WriteString("HTTP/1.1")
builder.WriteString("\n")
builder.WriteString("Host: " + resp.Request.URL.Host)
builder.WriteRune('\n')
for k, v := range *resp.Request.Headers {
builder.WriteString(k + ": " + strings.Join(v, "; ") + "\n")
}
if resp.Request.Body != nil {
bodyResp, _ := io.ReadAll(resp.Request.Body)
if string(bodyResp) != "" {
builder.WriteString("\n")
builder.WriteString(string(bodyResp))
}
}
builder.WriteString("\n\n")
builder.WriteString("HTTP/1.1")
builder.WriteString(" ")
builder.WriteString(fmt.Sprint(resp.StatusCode))
builder.WriteString("\n")
for k, v := range *resp.Headers {
builder.WriteString(k + ": " + strings.Join(v, "; ") + "\n")
}
builder.WriteString("\n")
body, _ := io.ReadAll(bytes.NewReader(resp.Body))
builder.WriteString(string(body))
return builder.Bytes(), nil
}
func getResponseFileName(folder, url string) string {
file := getResponseHash(url) + ".txt"
return filepath.Join(folder, file)
}
// UpdateIndex updates the index file with the
// correct information linking to HTTP responses files.
// If it fails returns an error.
func UpdateIndex(resp *colly.Response) error {
index, err := os.OpenFile(filepath.Join(CariddiOutputFolder, index),
os.O_APPEND|os.O_WRONLY,
fileUtils.Permission0644)
if err != nil {
return err
}
defer index.Close()
builder := &bytes.Buffer{}
builder.WriteString(getResponseFileName(filepath.Join(CariddiOutputFolder, resp.Request.URL.Host),
resp.Request.URL.String()))
builder.WriteRune(' ')
builder.WriteString(resp.Request.URL.String())
builder.WriteRune(' ')
builder.WriteString("(" + fmt.Sprint(resp.StatusCode) + ")")
builder.WriteRune('\n')
if _, writeErr := index.Write(builder.Bytes()); writeErr != nil {
return fmt.Errorf("%w %s", err, "could not update index")
}
return nil
}
// WriteHTTPResponse creates an HTTP response output file and
// writes the HTTP response inside it.
// If it fails returns an error.
func WriteHTTPResponse(inputURL *url.URL, response []byte) error {
file := getResponseFileName(filepath.Join(CariddiOutputFolder, inputURL.Host), inputURL.String())
outFile, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, fileUtils.Permission0644)
if err != nil {
return err
}
if _, writeErr := outFile.Write(response); writeErr != nil {
return ErrHTTPResp
}
return nil
}
// StoreHTTPResponse stores an HTTP response in a file.
// If it fails returns an error.
func StoreHTTPResponse(r *colly.Response) error {
fileUtils.CreateHostOutputFolder(r.Request.URL.Host)
err := UpdateIndex(r)
if err != nil {
log.Println(err)
}
response, err := FormatResponse(r)
if err != nil {
log.Println(err)
}
err = WriteHTTPResponse(r.Request.URL, response)
if err != nil {
log.Println(err)
}
return nil
}
+1 -1
View File
@@ -2,7 +2,7 @@ name: cariddi
summary: Fast web crawler and scanner
description: |
Take a list of domains, crawl urls and scan for endpoints, secrets, api keys, file extensions, tokens and more
version: 1.3.1
version: 1.3.2
grade: stable
base: core20