Compare commits

...

20 Commits

Author SHA1 Message Date
allcontributors[bot]
378d75964c docs: add aldamd as a contributor for code (#1309)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-04-15 08:31:37 -04:00
Daniel Aldam
ffdf871abe fix: support LF-only line endings in --request-file parsing (#1306)
* fix: support LF-only line endings in --request-file parsing
* preserve raw body when parsing request file
* Added CRLFCRLF/LFLF request-file parsing tests
* better invalid UTF-8 in request file header error message
* strengthened request-file mixed CRLF LF headers test
* added request-file explicit binary body test
* cargo fmt
* updated request-file header-body separation logic to choose first occurrence & added testing
2026-04-15 08:30:39 -04:00
epi
bedf4d3f8e visual update for readme 2026-04-12 08:02:37 -04:00
epi
7787c83e1e updated readme with pro domain 2026-04-12 07:47:56 -04:00
allcontributors[bot]
242b134a3d docs: add ghsdpolley as a contributor for bug (#1300)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-02-08 09:37:34 -05:00
epi
b4ceaef08d removed is_file check from path extraction (#1299) 2026-02-08 09:36:53 -05:00
allcontributors[bot]
143d5710fc docs: add redacean as a contributor for bug (#1296)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-02-06 09:25:18 -05:00
epi
0efb0684b5 1293 fix parser unwrap (#1295)
* removed help unwraps

* clippy

* refixed clippy fix
2026-02-06 09:23:37 -05:00
allcontributors[bot]
c7ed9c9899 docs: add Antonio-R1 as a contributor for code, and bug (#1291)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-01-21 20:55:27 -05:00
Antonio
510bad0473 Improve the robots.txt regex (#1290)
Co-authored-by: sbiotto <54334833+sbiotto@users.noreply.github.com>
2026-01-21 20:54:36 -05:00
allcontributors[bot]
23661d17c9 docs: add OpenSourceKyle as a contributor for doc, and bug (#1288)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-01-17 06:52:48 -05:00
epi
097d54f384 Add security notice for domain impersonation
Added a security notice regarding domain impersonation and official download sources.
2026-01-17 06:47:48 -05:00
epi
970ce73ac4 Merge branch 'main' of github.com:epi052/feroxbuster 2025-12-24 05:46:10 -05:00
epi
5bb42c4004 updated integration tests to use cargo_bin! macro 2025-12-24 05:45:10 -05:00
allcontributors[bot]
0732ee11ef docs: add sebastiaanspeck as a contributor for bug, and doc (#1286)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-12-24 05:04:04 -05:00
epi
47b4efdd1b updated links to new docs 2025-12-24 05:01:48 -05:00
epi
e50e150fb9 Update links in README for example usage and documentation 2025-12-24 04:47:31 -05:00
epi
84aef80cea Update copyright year in LICENSE file 2025-12-15 19:35:28 -05:00
epi
9fe5bfd622 re-added dockerhub verification 2025-12-13 09:18:43 -05:00
epi
ddd04dac7f Revert workflow changes 2025-12-13 09:17:21 -05:00
31 changed files with 540 additions and 755 deletions

View File

@@ -990,6 +990,63 @@
"contributions": [
"doc"
]
},
{
"login": "sebastiaanspeck",
"name": "Sebastiaan Speck",
"avatar_url": "https://avatars.githubusercontent.com/u/12570668?v=4",
"profile": "https://github.com/sebastiaanspeck",
"contributions": [
"bug",
"doc"
]
},
{
"login": "OpenSourceKyle",
"name": "OpenSourceKyle",
"avatar_url": "https://avatars.githubusercontent.com/u/173112933?v=4",
"profile": "https://github.com/OpenSourceKyle",
"contributions": [
"doc",
"bug"
]
},
{
"login": "Antonio-R1",
"name": "Antonio",
"avatar_url": "https://avatars.githubusercontent.com/u/54741970?v=4",
"profile": "https://github.com/Antonio-R1",
"contributions": [
"code",
"bug"
]
},
{
"login": "redacean",
"name": "Redacean",
"avatar_url": "https://avatars.githubusercontent.com/u/125687454?v=4",
"profile": "https://github.com/redacean",
"contributions": [
"bug"
]
},
{
"login": "ghsdpolley",
"name": "ghsdpolley",
"avatar_url": "https://avatars.githubusercontent.com/u/19826831?v=4",
"profile": "https://github.com/ghsdpolley",
"contributions": [
"bug"
]
},
{
"login": "aldamd",
"name": "Daniel Aldam",
"avatar_url": "https://avatars.githubusercontent.com/u/178115486?v=4",
"profile": "https://github.com/aldamd",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@@ -16,10 +16,10 @@ Long form explanations of most of the items below can be found in the [CONTRIBUT
## Documentation
- [ ] New code is documented using [doc comments](https://doc.rust-lang.org/stable/rust-by-example/meta/doc.html)
- [ ] Documentation about your PR is included in the `docs`, as needed. The docs live in a [separate repository](https://epi052.github.io/feroxbuster-docs/docs/). Update the appropriate pages at the links below.
- [ ] update [example config file section](https://epi052.github.io/feroxbuster-docs/docs/configuration/ferox-config-toml/)
- [ ] update [help output section](https://epi052.github.io/feroxbuster-docs/docs/configuration/command-line/)
- [ ] add an [example](https://epi052.github.io/feroxbuster-docs/docs/examples/)
- [ ] Documentation about your PR is included in the `docs`, as needed. The docs live in a [separate repository](https://epi052.github.io/feroxbuster-docs/). Update the appropriate pages at the links below.
- [ ] update [example config file section](https://epi052.github.io/feroxbuster-docs/configuration/ferox-config-toml/)
- [ ] update [help output section](https://epi052.github.io/feroxbuster-docs/configuration/command-line/)
- [ ] add an [example](https://epi052.github.io/feroxbuster-docs/examples/auto-tune/)
## Additional Tests
- [ ] New code is unit tested

View File

@@ -1,310 +0,0 @@
name: Release
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
jobs:
create-release:
name: Create GitHub Release
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
version: ${{ steps.get_version.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get version from tag
id: get_version
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Generate changelog
id: changelog
run: |
# Get previous tag
PREV_TAG=$(git describe --abbrev=0 --tags HEAD^ 2>/dev/null || echo "")
if [ -z "$PREV_TAG" ]; then
# First release, get all commits
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
else
# Get commits since previous tag
CHANGELOG=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
fi
# Create changelog file
{
echo "## What's Changed"
echo ""
echo "$CHANGELOG"
echo ""
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${GITHUB_REF_NAME}"
} > CHANGELOG.md
cat CHANGELOG.md
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v2
with:
body_path: CHANGELOG.md
draft: false
prerelease: false
download-and-upload-artifacts:
name: Download & Upload Release Assets
needs: create-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get latest CD Pipeline run
id: get_run
run: |
# Get the latest successful CD Pipeline run for main branch
RUN_ID=$(gh run list --workflow="CD Pipeline" --branch=main --status=success --limit=1 --json databaseId --jq='.[0].databaseId')
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
run-id: ${{ steps.get_run.outputs.run_id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Display structure of downloaded files
run: ls -R artifacts/
- name: Prepare release assets
id: prepare
run: |
mkdir -p release-assets
cd artifacts
# Process Linux x86_64 binary - create tar.gz
if [ -d "x86_64-linux-feroxbuster" ]; then
tar czf ../release-assets/x86_64-linux-feroxbuster.tar.gz -C x86_64-linux-feroxbuster feroxbuster
fi
# Process Linux x86 binary - create tar.gz
if [ -d "x86-linux-feroxbuster" ]; then
tar czf ../release-assets/x86-linux-feroxbuster.tar.gz -C x86-linux-feroxbuster feroxbuster
fi
# Process ARM binaries - create tar.gz
if [ -d "armv7-linux-feroxbuster" ]; then
tar czf ../release-assets/armv7-linux-feroxbuster.tar.gz -C armv7-linux-feroxbuster feroxbuster
fi
if [ -d "aarch64-linux-feroxbuster" ]; then
tar czf ../release-assets/aarch64-linux-feroxbuster.tar.gz -C aarch64-linux-feroxbuster feroxbuster
fi
# Copy macOS tar.gz files (already compressed)
if [ -f "x86_64-macos-feroxbuster.tar.gz/x86_64-macos-feroxbuster.tar.gz" ]; then
cp x86_64-macos-feroxbuster.tar.gz/x86_64-macos-feroxbuster.tar.gz ../release-assets/
fi
if [ -f "aarch64-macos-feroxbuster.tar.gz/aarch64-macos-feroxbuster.tar.gz" ]; then
cp aarch64-macos-feroxbuster.tar.gz/aarch64-macos-feroxbuster.tar.gz ../release-assets/
fi
# Copy Windows executables - create zip files
if [ -d "x86_64-windows-feroxbuster.exe" ]; then
cd x86_64-windows-feroxbuster.exe
zip ../../release-assets/x86_64-windows-feroxbuster.zip feroxbuster.exe
cd ..
fi
if [ -d "x86-windows-feroxbuster.exe" ]; then
cd x86-windows-feroxbuster.exe
zip ../../release-assets/x86-windows-feroxbuster.zip feroxbuster.exe
cd ..
fi
# Copy .deb file
if [ -d "feroxbuster_amd64.deb" ]; then
cp feroxbuster_amd64.deb/*.deb ../release-assets/ || true
fi
cd ..
# Generate SHA256 checksums
cd release-assets
sha256sum * > SHA256SUMS
cat SHA256SUMS
# Extract specific hashes for homebrew
LINUX_HASH=$(grep "x86_64-linux-feroxbuster.tar.gz" SHA256SUMS | awk '{print $1}')
MACOS_X64_HASH=$(grep "x86_64-macos-feroxbuster.tar.gz" SHA256SUMS | awk '{print $1}')
MACOS_ARM_HASH=$(grep "aarch64-macos-feroxbuster.tar.gz" SHA256SUMS | awk '{print $1}')
echo "linux_hash=$LINUX_HASH" >> $GITHUB_OUTPUT
echo "macos_x64_hash=$MACOS_X64_HASH" >> $GITHUB_OUTPUT
echo "macos_arm_hash=$MACOS_ARM_HASH" >> $GITHUB_OUTPUT
- name: Upload Release Assets
uses: softprops/action-gh-release@v2
with:
files: release-assets/*
publish-crates-io:
name: Publish to crates.io
needs: create-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish
update-homebrew:
name: Update Homebrew Taps
needs: [create-release, download-and-upload-artifacts]
runs-on: ubuntu-latest
steps:
- name: Checkout TGotwig's homebrew-linux-feroxbuster
uses: actions/checkout@v4
with:
repository: TGotwig/homebrew-linux-feroxbuster
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
path: homebrew-linux
- name: Update Linux formula
run: |
cd homebrew-linux
VERSION="${{ needs.create-release.outputs.version }}"
HASH="${{ needs.download-and-upload-artifacts.outputs.linux_hash }}"
# Update version and hash in formula
sed -i "s|url \"https://github.com/epi052/feroxbuster/releases/download/v[^/]*/x86_64-linux-feroxbuster.tar.gz\"|url \"https://github.com/epi052/feroxbuster/releases/download/v${VERSION}/x86_64-linux-feroxbuster.tar.gz\"|g" feroxbuster.rb
sed -i "s/sha256 \"[^\"]*\"/sha256 \"${HASH}\"/g" feroxbuster.rb
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add feroxbuster.rb
git commit -m "Update feroxbuster to v${VERSION}" || echo "No changes to commit"
git push
- name: Checkout feroxbuster main repo to get config
uses: actions/checkout@v4
with:
path: feroxbuster-src
- name: Check if config changed
id: config_check
run: |
cd feroxbuster-src
CONFIG_HASH=$(sha256sum ferox-config.toml.example | awk '{print $1}')
echo "config_hash=$CONFIG_HASH" >> $GITHUB_OUTPUT
# Check if config changed since last tag
PREV_TAG=$(git describe --abbrev=0 --tags HEAD^ 2>/dev/null || echo "")
if [ -n "$PREV_TAG" ]; then
if git diff ${PREV_TAG}..HEAD --quiet -- ferox-config.toml.example; then
echo "config_changed=false" >> $GITHUB_OUTPUT
else
echo "config_changed=true" >> $GITHUB_OUTPUT
fi
else
echo "config_changed=true" >> $GITHUB_OUTPUT
fi
- name: Update config hash in homebrew if changed
if: steps.config_check.outputs.config_changed == 'true'
run: |
cd homebrew-linux
CONFIG_HASH="${{ steps.config_check.outputs.config_hash }}"
# Update config hash if it exists in formula
if grep -q "ferox-config.toml.example" feroxbuster.rb; then
sed -i "s/sha256 \"[^\"]*\" # ferox-config.toml.example/sha256 \"${CONFIG_HASH}\" # ferox-config.toml.example/g" feroxbuster.rb
git add feroxbuster.rb
git commit -m "Update ferox-config.toml.example hash" || echo "No changes to commit"
git push
fi
publish-winget:
name: Publish to Winget
needs: [create-release, download-and-upload-artifacts]
runs-on: ubuntu-latest
steps:
- uses: vedantmgoyal2009/winget-releaser@main
with:
identifier: epi052.feroxbuster
installers-regex: '-windows-feroxbuster\.exe\.zip$'
token: ${{ secrets.WINGET_TOKEN }}
release-tag: v${{ needs.create-release.outputs.version }}
publish-snapcraft:
name: Publish to Snapcraft
needs: [create-release, download-and-upload-artifacts]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Publish to Snapcraft
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
with:
snap: feroxbuster
release: stable
manual-steps-reminder:
name: Manual Steps Reminder
needs: [create-release, download-and-upload-artifacts]
runs-on: ubuntu-latest
steps:
- name: Create comment with manual steps
uses: actions/github-script@v7
with:
script: |
const version = '${{ needs.create-release.outputs.version }}';
const linuxHash = '${{ needs.download-and-upload-artifacts.outputs.linux_hash }}';
const body = `## 🚀 Release v${version} Published!
### ✅ Automated Steps Completed
- [x] GitHub Release created with changelog
- [x] All artifacts uploaded with SHA256 checksums
- [x] Published to crates.io
- [x] Homebrew tap updated
- [x] Winget package published
- [x] Snapcraft published to stable
### 📋 Manual Steps Required
1. **Kali Linux**
- Go to https://bugs.kali.org/login_page.php?return=%2Fmy_view_page.php
- Request a tool update
3. **Announcement** (optional)
- Tweet about the release if it's significant!
2. **Announcement** (optional)
- Linux x86_64: \`${linuxHash}\`
See full checksums in release assets: SHA256SUMS
`;
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});

21
.github/workflows/winget.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Publish to Winget
on:
release:
types: [released]
workflow_dispatch:
inputs:
tag_name:
description: 'Tag name of release'
required: true
type: string
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: vedantmgoyal2009/winget-releaser@main
with:
identifier: epi052.feroxbuster
installers-regex: '-windows-feroxbuster\.exe\.zip$'
token: ${{ secrets.WINGET_TOKEN }}
release-tag: ${{ inputs.tag_name || github.event.release.tag_name || github.ref_name }}

11
Cargo.lock generated
View File

@@ -116,13 +116,12 @@ dependencies = [
[[package]]
name = "assert_cmd"
version = "2.0.17"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66"
checksum = "bcbb6924530aa9e0432442af08bbcafdad182db80d2e560da42a6d442535bf85"
dependencies = [
"anstyle",
"bstr",
"doc-comment",
"libc",
"predicates",
"predicates-core",
@@ -790,12 +789,6 @@ dependencies = [
"syn 2.0.104",
]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "dtoa"
version = "1.0.10"

View File

@@ -69,7 +69,7 @@ self_update = { version = "0.40", features = [
[dev-dependencies]
tempfile = "3.20"
httpmock = "0.7"
assert_cmd = "2.0"
assert_cmd = "2.1"
predicates = "3.1"
[profile.release]

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020-2023 epi
Copyright (c) 2020-2026 epi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -50,12 +50,4 @@ condition = { env_not_set = ["CI"] }
clear = true
script = """
cargo nextest run --all-features --all-targets --no-fail-fast --run-ignored all --retries 4
"""
# coverage
[tasks.coverage]
clear = true
script = """
cargo llvm-cov nextest --all-features --no-fail-fast --retries 4 --html
echo "Coverage report generated at target/llvm-cov/html/index.html"
"""

View File

@@ -1,3 +1,18 @@
> [!WARNING]
> **Security Notice Domain Impersonation**
>
> The domain **feroxbuster.com** is **NOT affiliated** with this project, its maintainers, or any official feroxbuster releases.
>
> Official feroxbuster downloads are distributed **ONLY** through:
>
> - [https://github.com/epi052/feroxbuster](https://github.com/epi052/feroxbuster/releases) (open source)
> - [https://www.feroxbuster.pro](https://www.feroxbuster.pro) (commercial)
> - package repositories listed in this README
> - package repositories listed in the [installation docs](https://epi052.github.io/feroxbuster-docs/installation/android/)
>
> We do **not** distribute software from feroxbuster.com, and we cannot vouch for the authenticity or safety of files hosted there.
> If you downloaded feroxbuster from any other domain, we strongly recommend deleting it and reinstalling from an official source.
<h1 align="center">
<br>
<a href="https://github.com/epi052/feroxbuster"><img src="img/logo/default-cropped.png" alt="feroxbuster"></a>
@@ -43,29 +58,26 @@
![demo](img/demo.gif)
<p align="center">
🦀
<a href="https://github.com/epi052/feroxbuster/releases">Releases</a> ✨
<a href="https://epi052.github.io/feroxbuster-docs/docs/examples/">Example Usage</a> ✨
<a href="https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md">Contributing</a> ✨
<a href="https://epi052.github.io/feroxbuster-docs/docs/">Documentation</a>
🦀
<a href="https://github.com/epi052/feroxbuster/releases"><img src="https://img.shields.io/badge/Releases-CF4F4B?style=flat-square&logo=github&logoColor=white" alt="Releases"></a>&nbsp;
<a href="https://epi052.github.io/feroxbuster-docs/examples/auto-tune/"><img src="https://img.shields.io/badge/Examples-CF4F4B?style=flat-square" alt="Example Usage"></a>&nbsp;
<a href="https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md"><img src="https://img.shields.io/badge/Contributing-CF4F4B?style=flat-square" alt="Contributing"></a>&nbsp;
<a href="https://epi052.github.io/feroxbuster-docs/overview"><img src="https://img.shields.io/badge/Documentation-CF4F4B?style=flat-square&logo=bookstack&logoColor=white" alt="Documentation"></a>&nbsp;
<a href="https://www.feroxbuster.pro"><img src="https://img.shields.io/badge/Pro-CF4F4B?style=flat-square" alt="Pro"></a>
</p>
---
<h1><p align="center">✨🎉👉 <a href="https://epi052.github.io/feroxbuster-docs/docs/">NEW DOCUMENTATION SITE</a> 👈🎉✨</p></h1>
> [!TIP]
> **Documentation has moved!** &mdash; Instead of having a 1300 line `README.md` (sorry...), feroxbuster's documentation has moved to GitHub Pages. The move to hosting documentation on Pages should make it a LOT easier to find the information you're looking for, whatever that may be. Please check it out for anything you need beyond a quick-start.
>
> **[View the full documentation &#8594;](https://epi052.github.io/feroxbuster-docs/overview)**
## 🚀 Documentation has **moved** 🚀
Instead of having a 1300 line `README.md` (sorry...), feroxbuster's documentation has moved to GitHub Pages. The move to hosting documentation on Pages should make it a LOT easier to find the information you're looking for, whatever that may be. Please check it out for anything you need beyond a quick-start. The new documentation can be found [here](https://epi052.github.io/feroxbuster-docs/docs/).
## 😕 What the heck is a ferox anyway?
## What the heck is a ferox anyway?
Ferox is short for Ferric Oxide. Ferric Oxide, simply put, is rust. The name rustbuster was taken, so I decided on a
variation. 🤷
variation.
## 🤔 What's it do tho?
## What's it do tho?
`feroxbuster` is a tool designed to perform [Forced Browsing](https://owasp.org/www-community/attacks/Forced_browsing).
@@ -79,17 +91,17 @@ credentials, internal network addressing, etc...
This attack is also known as Predictable Resource Location, File Enumeration, Directory Enumeration, and Resource
Enumeration.
## Quick Start
## Quick Start
This section will cover the minimum amount of information to get up and running with feroxbuster. Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/), as it's much more comprehensive.
This section will cover the minimum amount of information to get up and running with feroxbuster. Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/overview/), as it's much more comprehensive.
### 💿 Installation
### Installation
There are quite a few other [installation methods](https://epi052.github.io/feroxbuster-docs/docs/installation/), but these snippets should cover the majority of users.
There are quite a few other [installation methods](https://epi052.github.io/feroxbuster-docs/installation/android/), but these snippets should cover the majority of users.
#### Kali
If you're using kali, this is the preferred install method. Installing from the repos adds a [**ferox-config.toml**](https://epi052.github.io/feroxbuster-docs/docs/configuration/ferox-config-toml/) in `/etc/feroxbuster/`, adds command completion for bash, fish, and zsh, includes a man page entry, and installs `feroxbuster` itself.
If you're using kali, this is the preferred install method. Installing from the repos adds a [**ferox-config.toml**](https://epi052.github.io/feroxbuster-docs/configuration/ferox-config-toml/) in `/etc/feroxbuster/`, adds command completion for bash, fish, and zsh, includes a man page entry, and installs `feroxbuster` itself.
```
sudo apt update && sudo apt install -y feroxbuster
@@ -135,7 +147,7 @@ choco install feroxbuster
#### All others
Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/overview).
### Updating feroxbuster (new in v2.9.1)
@@ -143,9 +155,9 @@ Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/d
./feroxbuster --update
```
## 🧰 Example Usage
## Example Usage
Here are a few brief examples to get you started. Please note, feroxbuster can do a **lot more** than what's listed below. As a result, there are **many more** examples, with **demonstration gifs** that highlight specific features, in the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
Here are a few brief examples to get you started. Please note, feroxbuster can do a **lot more** than what's listed below. As a result, there are **many more** examples, with **demonstration gifs** that highlight specific features, in the [documentation](https://epi052.github.io/feroxbuster-docs/overview).
### Multiple Values
@@ -205,13 +217,12 @@ cat targets | ./feroxbuster --stdin --silent -s 200 301 302 --redirects -x js |
./feroxbuster -u http://127.1 --data-urlencoded @file.payload
```
## 🚀 Documentation has **moved** 🚀
> [!TIP]
> For realsies, there used to be over 1300 lines in this README, but it's all been moved to the [new documentation site](https://epi052.github.io/feroxbuster-docs/overview). Go check it out!
>
> **[View the full documentation &#8594;](https://epi052.github.io/feroxbuster-docs/overview)**
For realsies, there used to be over 1300 lines in this README, but it's all been moved to the [new documentation site](https://epi052.github.io/feroxbuster-docs/docs/). Go check it out!
<h1><p align="center">✨🎉👉 <a href="https://epi052.github.io/feroxbuster-docs/docs/">DOCUMENTATION</a> 👈🎉✨</p></h1>
## Contributors ✨
## Contributors
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
@@ -357,6 +368,12 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pg9051"><img src="https://avatars.githubusercontent.com/u/202219877?v=4?s=100" width="100px;" alt="pg9051"/><br /><sub><b>pg9051</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/commits?author=pg9051" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sebastiaanspeck"><img src="https://avatars.githubusercontent.com/u/12570668?v=4?s=100" width="100px;" alt="Sebastiaan Speck"/><br /><sub><b>Sebastiaan Speck</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/issues?q=author%3Asebastiaanspeck" title="Bug reports">🐛</a> <a href="https://github.com/epi052/feroxbuster/commits?author=sebastiaanspeck" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/OpenSourceKyle"><img src="https://avatars.githubusercontent.com/u/173112933?v=4?s=100" width="100px;" alt="OpenSourceKyle"/><br /><sub><b>OpenSourceKyle</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/commits?author=OpenSourceKyle" title="Documentation">📖</a> <a href="https://github.com/epi052/feroxbuster/issues?q=author%3AOpenSourceKyle" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Antonio-R1"><img src="https://avatars.githubusercontent.com/u/54741970?v=4?s=100" width="100px;" alt="Antonio"/><br /><sub><b>Antonio</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/commits?author=Antonio-R1" title="Code">💻</a> <a href="https://github.com/epi052/feroxbuster/issues?q=author%3AAntonio-R1" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/redacean"><img src="https://avatars.githubusercontent.com/u/125687454?v=4?s=100" width="100px;" alt="Redacean"/><br /><sub><b>Redacean</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/issues?q=author%3Aredacean" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ghsdpolley"><img src="https://avatars.githubusercontent.com/u/19826831?v=4?s=100" width="100px;" alt="ghsdpolley"/><br /><sub><b>ghsdpolley</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/issues?q=author%3Aghsdpolley" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aldamd"><img src="https://avatars.githubusercontent.com/u/178115486?v=4?s=100" width="100px;" alt="Daniel Aldam"/><br /><sub><b>Daniel Aldam</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/commits?author=aldamd" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -13,7 +13,7 @@
<licenseUrl>https://github.com/epi052/feroxbuster/blob/main/LICENSE</licenseUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<projectSourceUrl>https://github.com/epi052/feroxbuster</projectSourceUrl>
<docsUrl>https://epi052.github.io/feroxbuster-docs/docs/</docsUrl>
<docsUrl>https://epi052.github.io/feroxbuster-docs/</docsUrl>
<!--<mailingListUrl></mailingListUrl>-->
<bugTrackerUrl>https://github.com/epi052/feroxbuster/issues</bugTrackerUrl>
<tags>content-discovery pentesting-tool url-bruteforcer</tags>
@@ -43,19 +43,19 @@ Enumeration.
## Quick Start
This section will cover the minimum amount of information to get up and running with feroxbuster. Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/), as it's much more comprehensive.
This section will cover the minimum amount of information to get up and running with feroxbuster. Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/overview), as it's much more comprehensive.
### Installation
There are quite a few other [installation methods](https://epi052.github.io/feroxbuster-docs/docs/installation/), but these snippets should cover the majority of users.
There are quite a few other [installation methods](https://epi052.github.io/feroxbuster-docs/installation/android/), but these snippets should cover the majority of users.
#### All others Docs
Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/overview).
## Example Usage
Here are a few brief examples to get you started. Please note, feroxbuster can do a **lot more** than what's listed below. As a result, there are **many more** examples, with **demonstration gifs** that highlight specific features, in the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
Here are a few brief examples to get you started. Please note, feroxbuster can do a **lot more** than what's listed below. As a result, there are **many more** examples, with **demonstration gifs** that highlight specific features, in the [documentation](https://epi052.github.io/feroxbuster-docs/overview).
### Multiple Values

View File

@@ -10,9 +10,8 @@ description: |
This attack is also known as Predictable Resource Location, File Enumeration, Directory Enumeration, and Resource Enumeration.
confinement: strict
grade: stable
base: core22
base: core18
plugs:
etc-feroxbuster:

View File

@@ -381,32 +381,54 @@ impl ContentType {
/// unless overridden by CLI options.
///
pub fn parse_request_file(config: &mut Configuration) -> Result<()> {
// read in the file located at config.request_file
// read in the file (raw bytes) located at config.request_file
// parse the file into a Request struct
let contents = std::fs::read_to_string(&config.request_file)?;
let contents = std::fs::read(&config.request_file)?;
if contents.is_empty() {
bail!("Empty --request-file file provided");
}
// this should split the body from the request line and headers
let lines = contents.split("\r\n\r\n").collect::<Vec<&str>>();
// find the first header/body separator
// locate both \r\n\r\n and \n\n and pick whichever appears earliest,
// so that a \r\n\r\n inside the body doesn't shadow a \n\n separator
// that terminates the headers
let crlf = contents.windows(4).position(|w| w == b"\r\n\r\n");
let lf = contents.windows(2).position(|w| w == b"\n\n");
if lines.len() < 2 {
bail!("Invalid request: Missing head/body CRLF separator");
}
let (sep_idx, sep_len) = match (crlf, lf) {
(Some(c), Some(l)) => {
if c <= l {
(c, 4)
} else {
(l, 2)
}
}
(Some(c), None) => (c, 4),
(None, Some(l)) => (l, 2),
(None, None) => bail!("Invalid request: Missing head/body separator"),
};
let head = lines[0];
let body = lines[1].as_bytes().to_vec();
// split the request head and body
let head_bytes = &contents[..sep_idx];
let body_bytes = &contents[sep_idx + sep_len..];
// we only want to use the request's body if the user hasn't
// decode only the head; HTTP framing is generally ascii/utf-8
// compatible
let head = std::str::from_utf8(head_bytes)
.map_err(|_| anyhow::anyhow!("Request headers contain invalid UTF-8"))?;
// normalize line endings in the decoded head
let normalized = head.replace("\r\n", "\n");
// we only want to use the request's body bytes if the user hasn't
// overridden it on the cli
if config.data.is_empty() {
config.data = body;
config.data = body_bytes.to_vec();
}
// begin parsing the request line and headers
let mut head_parts = head.split("\r\n");
// begin parsing the request line and normalized headers
let mut head_parts = normalized.split("\n");
let Some(request_line) = head_parts.next() else {
bail!("Invalid request: Missing request line");
@@ -441,7 +463,7 @@ pub fn parse_request_file(config: &mut Configuration) -> Result<()> {
}
for mut line in head_parts {
line = line.trim();
line = line.trim_matches('\r').trim();
if line.is_empty() {
break; // Empty line signals the end of headers
@@ -904,7 +926,7 @@ mod tests {
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"Invalid request: Missing head/body CRLF separator"
"Invalid request: Missing head/body separator"
);
tmp.cleanup();
@@ -1345,4 +1367,145 @@ mod tests {
let result = split_query("");
assert!(result.is_err());
}
#[test]
fn test_parse_raw_lf_only_request() -> io::Result<()> {
let mut tmp = TempSetup::new();
tmp.file
.write_all(b"GET / HTTP/1.1\nHost: example.com\n\nbody")?;
let result = parse_request_file(&mut tmp.config);
assert!(result.is_ok());
assert_eq!(tmp.config.data, b"body".to_vec());
tmp.cleanup();
Ok(())
}
#[test]
fn test_parse_raw_crlf_request() -> io::Result<()> {
let mut tmp = TempSetup::new();
tmp.file
.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\nbody")?;
let result = parse_request_file(&mut tmp.config);
assert!(result.is_ok());
assert_eq!(tmp.config.data, b"body".to_vec());
tmp.cleanup();
Ok(())
}
#[test]
fn test_parse_raw_crlf_body_preserved() -> io::Result<()> {
let mut tmp = TempSetup::new();
let body = b"line1\r\nline2\r\nbinary\x00data";
let mut request = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n".to_vec();
request.extend_from_slice(body);
tmp.file.write_all(&request)?;
parse_request_file(&mut tmp.config).unwrap();
assert_eq!(tmp.config.data, body.to_vec());
tmp.cleanup();
Ok(())
}
#[test]
fn test_parse_raw_lf_headers_crlf_body() -> io::Result<()> {
let mut tmp = TempSetup::new();
let body = b"line1\r\nline2\r\n";
let mut request = b"GET / HTTP/1.1\nHost: example.com\n\n".to_vec();
request.extend_from_slice(body);
tmp.file.write_all(&request)?;
parse_request_file(&mut tmp.config).unwrap();
assert_eq!(tmp.config.data, body.to_vec());
tmp.cleanup();
Ok(())
}
#[test]
fn test_parse_raw_mixed_newlines_headers() -> io::Result<()> {
let mut tmp = TempSetup::new();
tmp.file
.write_all(b"GET / HTTP/1.1\r\nHost: example.com\nUser-Agent: test\r\n\nbody")?;
let result = parse_request_file(&mut tmp.config);
assert!(result.is_ok());
assert_eq!(tmp.config.data, b"body".to_vec());
assert!(tmp.config.headers.contains_key("Host"));
assert_eq!(tmp.config.headers.get("Host").unwrap(), "example.com");
assert_eq!(tmp.config.user_agent, "test");
tmp.cleanup();
Ok(())
}
#[test]
fn test_parse_raw_binary_body_preserved() -> io::Result<()> {
let mut tmp = TempSetup::new();
let body = b"\x00\xde\xad\xbe\xef\x80binary";
let mut request = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n".to_vec();
request.extend_from_slice(body);
tmp.file.write_all(&request)?;
parse_request_file(&mut tmp.config).unwrap();
assert_eq!(tmp.config.data, body.to_vec());
tmp.cleanup();
Ok(())
}
#[test]
fn test_parse_raw_lf_headers_with_crlf_crlf_in_body() -> io::Result<()> {
// headers are LF-separated; body contains \r\n\r\n
let mut tmp = TempSetup::new();
tmp.file.write_all(
b"POST /upload HTTP/1.1\nHost: example.com\nContent-Type: application/octet-stream\n\nabc\r\n\r\ndef",
)?;
let result = parse_request_file(&mut tmp.config);
assert!(result.is_ok());
assert_eq!(tmp.config.data, b"abc\r\n\r\ndef".to_vec());
assert_eq!(tmp.config.target_url, "https://example.com/upload");
tmp.cleanup();
Ok(())
}
#[test]
fn test_parse_raw_crlf_headers_with_lf_lf_in_body() -> io::Result<()> {
let mut tmp = TempSetup::new();
tmp.file
.write_all(b"POST /upload HTTP/1.1\r\nHost: example.com\r\n\r\nabc\n\ndef")?;
parse_request_file(&mut tmp.config).unwrap();
assert_eq!(tmp.config.data, b"abc\n\ndef".to_vec());
tmp.cleanup();
Ok(())
}
}

View File

@@ -227,8 +227,10 @@ impl TermOutHandler {
self.handles = Some(handles);
}
Command::Exit => {
if self.file_task.is_some() && self.tx_file.send(Command::Exit).is_ok() {
self.file_task.as_mut().unwrap().await??; // wait for death
if self.tx_file.send(Command::Exit).is_ok() {
if let Some(task) = self.file_task.as_mut() {
task.await??; // wait for death
}
}
break;
}
@@ -280,26 +282,31 @@ impl TermOutHandler {
}
log::trace!("report complete: {}", resp.url());
if self.config.replay_client.is_some() && should_process_response {
// replay proxy specified/client created and this response's status code is one that
// should be replayed; not using logged_request due to replay proxy client
let data = if self.config.data.is_empty() {
None
} else {
Some(self.config.data.as_slice())
};
if should_process_response {
if let Some(client) = self.config.replay_client.as_ref() {
// replay proxy specified/client created and this response's status code is one that
// should be replayed; not using logged_request due to replay proxy client
let data = if self.config.data.is_empty() {
None
} else {
Some(self.config.data.as_slice())
};
make_request(
self.config.replay_client.as_ref().unwrap(),
resp.url(),
resp.method().as_str(),
data,
self.config.output_level,
&self.config,
tx_stats.clone(),
)
.await
.with_context(|| "Could not replay request through replay proxy")?;
make_request(
client,
resp.url(),
resp.method().as_str(),
data,
self.config.output_level,
&self.config,
tx_stats.clone(),
)
.await
.with_context(|| "Could not replay request through replay proxy")?;
} else {
// replay proxy not configured, skip replay without exiting response processing
log::trace!("replay proxy not configured, skipping replay");
}
}
if self.config.collect_backups

View File

@@ -51,7 +51,7 @@ pub(super) const LINKFINDER_REGEX: &str = r#"(?x)
///
/// ref: https://developers.google.com/search/reference/robots_txt
pub(super) const ROBOTS_TXT_REGEX: &str =
r#"(?m)^ *(Allow|Disallow): *(?P<url_path>[a-zA-Z0-9._/?#@!&'()+,;%=-]+?)$"#; // multi-line (?m)
r#"(?m)^[ \t]*(?i)(allow|disallow)[ \t]*:[ \t]*(?P<url_path>[^ \t\r\n#$]*)?[ \t]*\$?(?:#.*)?$"#; // multi-line (?m), case-insensitive (?i)
/// Regular expression to filter bad characters from extracted url paths
///
@@ -136,11 +136,7 @@ impl<'a> ExtractorBuilder<'a> {
links_regex: Regex::new(LINKFINDER_REGEX).unwrap(),
robots_regex: Regex::new(ROBOTS_TXT_REGEX).unwrap(),
url_regex: Regex::new(URL_CHARS_REGEX).unwrap(),
response: if self.response.is_some() {
Some(self.response.unwrap())
} else {
None
},
response: self.response,
url: self.url.to_owned(),
handles: self.handles.as_ref().unwrap().clone(),
target: self.target,

View File

@@ -233,9 +233,7 @@ impl<'a> Extractor<'a> {
}
// request and report assumed file
if (resp.is_file() || !resp.is_directory())
&& !c_handles.config.force_recursion
{
if !resp.is_directory() && !c_handles.config.force_recursion {
log::debug!("Extracted File: {resp}");
c_scanned_urls.add_file_scan(

View File

@@ -743,12 +743,18 @@ pub fn initialize() -> Command {
// which is fine, but if you add -h|--help, it still errors out on the bad flag/option,
// never showing the full help message. This code addresses that behavior
if arg == "--help" {
app.print_long_help().unwrap();
if let Err(err) = app.print_long_help() {
eprintln!("couldn't print help message: {}", err);
process::exit(1);
}
println!(); // just a newline to mirror original --help output
process::exit(0);
} else if arg == "-h" {
// same for -h, just shorter
app.print_help().unwrap();
if let Err(err) = app.print_help() {
eprintln!("couldn't print help message: {}", err);
process::exit(1);
}
println!();
process::exit(0);
}
@@ -813,7 +819,7 @@ EXAMPLES:
./feroxbuster -u http://127.1 --auto-tune
Examples and demonstrations of all features
https://epi052.github.io/feroxbuster-docs/docs/examples/
https://epi052.github.io/feroxbuster-docs/examples/auto-tune/
"#;
#[cfg(test)]

View File

@@ -192,26 +192,6 @@ impl FeroxResponse {
self.text.shrink_to_fit(); // allocated capacity shrinks to reflect the new size
}
/// Make a reasonable guess at whether the response is a file or not
///
/// Examines the last part of a path to determine if it has an obvious extension
/// i.e. http://localhost/some/path/stuff.js where stuff.js indicates a file
///
/// Additionally, inspects query parameters, as they're also often indicative of a file
pub fn is_file(&self) -> bool {
let has_extension = if let Some(mut path) = self.url.path_segments() {
if let Some(last) = path.next_back() {
last.contains('.') // last segment has some sort of extension, probably
} else {
false
}
} else {
false
};
self.url.query_pairs().count() > 0 || has_extension
}
/// Returns line count of the response text.
pub fn line_count(&self) -> usize {
self.line_count

View File

@@ -1,6 +1,8 @@
mod utils;
use assert_cmd::Command;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use predicates::prelude::*;
use std::process::Command;
use utils::{setup_tmp_directory, teardown_tmp_directory};
#[test]
@@ -13,15 +15,13 @@ fn banner_prints_proxy() -> Result<(), Box<dyn std::error::Error>> {
];
let (tmp_dir, file) = setup_tmp_directory(&urls, "wordlist")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--proxy")
.arg("http://127.0.0.1:8080")
.arg("--wordlist")
.arg("/definitely/doesnt/exist/0cd7fed0-47f4-4b18-a1b0-ac39708c1676")
.pipe_stdin(file)
.unwrap()
.stdin(std::fs::File::open(file)?)
.assert()
.success()
.stderr(
@@ -53,15 +53,13 @@ fn banner_prints_replay_proxy() -> Result<(), Box<dyn std::error::Error>> {
];
let (tmp_dir, file) = setup_tmp_directory(&urls, "wordlist")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--wordlist")
.arg("/definitely/doesnt/exist/0cd7fed0-47f4-4b18-a1b0-ac39708c1676")
.arg("--replay-proxy")
.arg("http://127.0.0.1:8081")
.pipe_stdin(file)
.unwrap()
.stdin(std::fs::File::open(file)?)
.assert()
.success()
.stderr(
@@ -87,8 +85,7 @@ fn banner_prints_replay_proxy() -> Result<(), Box<dyn std::error::Error>> {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + multiple headers
fn banner_prints_headers() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--headers")
@@ -119,8 +116,7 @@ fn banner_prints_headers() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + multiple dont scan url & regex entries
fn banner_prints_denied_urls() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--dont-scan")
@@ -155,8 +151,7 @@ fn banner_prints_denied_urls() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + multiple scope url entries
fn banner_prints_scope_urls() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--scope")
@@ -188,8 +183,7 @@ fn banner_prints_scope_urls() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + multiple headers
fn banner_prints_random_agent() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--random-agent")
@@ -215,8 +209,7 @@ fn banner_prints_random_agent() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + multiple size filters
fn banner_prints_filter_sizes() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-S")
@@ -261,8 +254,7 @@ fn banner_prints_filter_sizes() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + queries
fn banner_prints_queries() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-Q")
@@ -293,8 +285,7 @@ fn banner_prints_queries() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + status codes
fn banner_prints_status_codes() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-s")
@@ -321,8 +312,7 @@ fn banner_prints_status_codes() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + replay codes
fn banner_prints_replay_codes() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--replay-codes")
@@ -353,8 +343,7 @@ fn banner_prints_replay_codes() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + output file
fn banner_prints_output_file() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--output")
@@ -385,8 +374,7 @@ fn banner_prints_output_file() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + insecure
fn banner_prints_insecure() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-k")
@@ -413,8 +401,7 @@ fn banner_prints_insecure() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + follow redirects
fn banner_prints_redirects() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-r")
@@ -441,8 +428,7 @@ fn banner_prints_redirects() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + extensions
fn banner_prints_extensions() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-x")
@@ -472,8 +458,7 @@ fn banner_prints_extensions() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + dont_filter
fn banner_prints_dont_filter() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--dont-filter")
@@ -500,8 +485,7 @@ fn banner_prints_dont_filter() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + verbosity=1
fn banner_prints_verbosity_one() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-v")
@@ -528,8 +512,7 @@ fn banner_prints_verbosity_one() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + verbosity=2
fn banner_prints_verbosity_two() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-vv")
@@ -556,8 +539,7 @@ fn banner_prints_verbosity_two() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + verbosity=3
fn banner_prints_verbosity_three() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-vvv")
@@ -584,8 +566,7 @@ fn banner_prints_verbosity_three() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + verbosity=4
fn banner_prints_verbosity_four() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-vvvv")
@@ -612,8 +593,7 @@ fn banner_prints_verbosity_four() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + add slash
fn banner_prints_add_slash() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-f")
@@ -640,8 +620,7 @@ fn banner_prints_add_slash() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + INFINITE recursion
fn banner_prints_infinite_depth() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--depth")
@@ -669,8 +648,7 @@ fn banner_prints_infinite_depth() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + recursion depth
fn banner_prints_recursion_depth() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--depth")
@@ -698,8 +676,7 @@ fn banner_prints_recursion_depth() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + server certs
fn banner_prints_server_certs() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--server-certs")
@@ -729,8 +706,7 @@ fn banner_prints_server_certs() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + server certs
fn banner_prints_client_cert_and_key() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--client-cert")
@@ -762,8 +738,7 @@ fn banner_prints_client_cert_and_key() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + no recursion
fn banner_prints_no_recursion() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-n")
@@ -790,8 +765,7 @@ fn banner_prints_no_recursion() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see nothing
fn banner_doesnt_print() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-q")
@@ -808,8 +782,7 @@ fn banner_doesnt_print() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + extract-links
fn banner_prints_extract_links() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-e")
@@ -836,8 +809,7 @@ fn banner_prints_extract_links() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + scan-limit
fn banner_prints_scan_limit() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-L")
@@ -865,8 +837,7 @@ fn banner_prints_scan_limit() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + response-size-limit
fn banner_prints_response_size_limit() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--response-size-limit")
@@ -894,8 +865,7 @@ fn banner_prints_response_size_limit() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + filter-status
fn banner_prints_filter_status() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-C")
@@ -922,8 +892,7 @@ fn banner_prints_filter_status() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + json
fn banner_prints_json() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--json")
@@ -952,8 +921,7 @@ fn banner_prints_json() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + json
fn banner_prints_debug_log() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--debug-log")
@@ -981,8 +949,7 @@ fn banner_prints_debug_log() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + regex filters
fn banner_prints_filter_regex() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--filter-regex")
@@ -1010,8 +977,7 @@ fn banner_prints_filter_regex() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + time limit
fn banner_prints_time_limit() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--time-limit")
@@ -1039,8 +1005,7 @@ fn banner_prints_time_limit() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + similarity filter
fn banner_prints_similarity_filter() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--filter-similar-to")
@@ -1068,8 +1033,7 @@ fn banner_prints_similarity_filter() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + rate limit
fn banner_prints_rate_limit() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--rate-limit")
@@ -1097,8 +1061,7 @@ fn banner_prints_rate_limit() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + auto tune
fn banner_prints_auto_tune() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--auto-tune")
@@ -1125,8 +1088,7 @@ fn banner_prints_auto_tune() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + auto bail
fn banner_prints_auto_bail() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--auto-bail")
@@ -1153,8 +1115,7 @@ fn banner_prints_auto_bail() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see no banner output
fn banner_doesnt_print_when_silent() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--silent")
@@ -1179,8 +1140,7 @@ fn banner_doesnt_print_when_silent() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see no banner output
fn banner_doesnt_print_when_quiet() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--quiet")
@@ -1205,8 +1165,7 @@ fn banner_doesnt_print_when_quiet() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see nothing as --parallel forces --silent to be true
fn banner_prints_parallel() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--quiet")
.arg("--parallel")
@@ -1231,8 +1190,7 @@ fn banner_prints_parallel() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + methods
fn banner_prints_methods() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-m")
@@ -1262,8 +1220,7 @@ fn banner_prints_methods() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + data body
fn banner_prints_data() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-m")
@@ -1295,8 +1252,7 @@ fn banner_prints_data() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + ignored extensions
fn banner_prints_collect_extensions_and_dont_collect_default() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--collect-extensions")
@@ -1324,8 +1280,7 @@ fn banner_prints_collect_extensions_and_dont_collect_default() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect extensions
fn banner_prints_collect_extensions_and_dont_collect_with_input() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--collect-extensions")
@@ -1356,8 +1311,7 @@ fn banner_prints_collect_extensions_and_dont_collect_with_input() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect backups
fn banner_prints_collect_backups() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--collect-backups")
@@ -1383,8 +1337,7 @@ fn banner_prints_collect_backups() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect words
fn banner_prints_collect_words() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--collect-words")
@@ -1410,8 +1363,7 @@ fn banner_prints_collect_words() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect words
fn banner_prints_all_composite_settings_smart() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--smart")
@@ -1440,8 +1392,7 @@ fn banner_prints_all_composite_settings_smart() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect words
fn banner_prints_all_composite_settings_thorough() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--thorough")
@@ -1470,8 +1421,7 @@ fn banner_prints_all_composite_settings_thorough() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect words
fn banner_prints_all_composite_settings_burp() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--burp")
@@ -1498,8 +1448,7 @@ fn banner_prints_all_composite_settings_burp() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect words
fn banner_prints_all_composite_settings_data_json_stdin() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--data-json")
@@ -1525,8 +1474,7 @@ fn banner_prints_all_composite_settings_data_json_stdin() {
#[test]
fn banner_prints_all_composite_settings_data_json_file() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-m")
@@ -1555,8 +1503,7 @@ fn banner_prints_all_composite_settings_data_json_file() {
#[test]
fn banner_prints_all_composite_settings_data_urlencoded_stdin() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("-m")
@@ -1590,8 +1537,7 @@ fn banner_prints_all_composite_settings_data_urlencoded_stdin() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect words
fn banner_prints_all_composite_settings_data_urlencoded_file() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--data-urlencoded")
@@ -1622,8 +1568,7 @@ fn banner_prints_all_composite_settings_data_urlencoded_file() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + collect words
fn banner_prints_all_composite_settings_burp_replay() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--burp-replay")
@@ -1650,8 +1595,7 @@ fn banner_prints_all_composite_settings_burp_replay() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + force recursion
fn banner_prints_force_recursion() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--force-recursion")
@@ -1677,8 +1621,7 @@ fn banner_prints_force_recursion() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + scan-dir-listings
fn banner_prints_scan_dir_listings() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--scan-dir-listings")
@@ -1704,8 +1647,7 @@ fn banner_prints_scan_dir_listings() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + protocol
fn banner_prints_limit_dirs() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("localhost")
.arg("--limit-bars")
@@ -1732,8 +1674,7 @@ fn banner_prints_limit_dirs() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + force recursion
fn banner_prints_update_app() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--update")
.assert()
.success()
@@ -1744,8 +1685,7 @@ fn banner_prints_update_app() {
/// test allows non-existent wordlist to trigger the banner printing to stderr
/// expect to see all mandatory prints + unique
fn banner_prints_unique() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://localhost")
.arg("--unique")

View File

@@ -1,4 +1,5 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::MockServer;
use predicates::prelude::*;
@@ -12,8 +13,7 @@ fn read_in_config_file_for_settings() -> Result<(), Box<dyn std::error::Error>>
let (tmp_dir, file) = setup_tmp_directory(&["threads = 37".to_string()], "ferox-config.toml")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.current_dir(&tmp_dir)
.arg("--url")
.arg(srv.url("/"))

View File

@@ -1,9 +1,10 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use assert_cmd::Command;
use httpmock::Method::GET;
use httpmock::MockServer;
use predicates::prelude::*;
use std::process::Command;
use utils::{setup_tmp_directory, teardown_tmp_directory};
#[test]
@@ -17,8 +18,7 @@ fn deny_list_works_during_with_a_normal_scan() {
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -54,8 +54,7 @@ fn deny_list_works_during_extraction() {
then.status(200);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -109,8 +108,7 @@ fn deny_list_works_during_recursion() {
.body("this is a test and is more bytes than other ones");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -179,8 +177,7 @@ fn deny_list_works_during_recursion_with_inverted_parents() {
.body("this is a test and is more bytes than other ones");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/js"))
.arg("--wordlist")
@@ -222,8 +219,7 @@ fn deny_list_prevents_regex_that_denies_base_url() {
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -256,8 +252,7 @@ fn deny_list_prevents_url_that_denies_base_url() {
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")

View File

@@ -1,4 +1,5 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::MockServer;
@@ -25,8 +26,7 @@ fn extractor_finds_absolute_url() -> Result<(), Box<dyn std::error::Error>> {
then.status(200);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -61,8 +61,7 @@ fn extractor_finds_absolute_url_to_different_domain() -> Result<(), Box<dyn std:
.body("\"http://localhost/homepage/assets/img/icons/handshake.svg\"");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -102,8 +101,7 @@ fn extractor_finds_relative_url() -> Result<(), Box<dyn std::error::Error>> {
then.status(200);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -151,8 +149,7 @@ fn extractor_finds_same_relative_url_twice() {
then.status(200);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -194,8 +191,7 @@ fn extractor_finds_filtered_content() -> Result<(), Box<dyn std::error::Error>>
then.status(200).body("im a little teapot");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -266,8 +262,7 @@ fn extractor_finds_robots_txt_links_and_displays_files_or_scans_directories() {
then.status(403);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -341,8 +336,7 @@ fn extractor_finds_robots_txt_links_and_displays_files_non_recursive() {
then.status(404);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -448,8 +442,7 @@ fn extractor_finds_directory_listing_links_and_displays_files() {
then.status(200).body("im a little teapot too"); // 22
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -557,8 +550,7 @@ fn extractor_finds_directory_listing_links_and_displays_files_non_recursive() {
then.status(200).body("im a little teapot too"); // 22
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -613,8 +605,7 @@ fn extractor_recurses_into_403_directories() -> Result<(), Box<dyn std::error::E
then.status(403);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -685,8 +676,7 @@ fn robots_text_extraction_doesnt_run_with_dont_extract_links() {
then.status(404);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")

View File

@@ -1,4 +1,5 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::MockServer;
@@ -24,8 +25,7 @@ fn filters_status_code_should_filter_response() {
then.status(200).body("this is also a test of some import");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -71,8 +71,7 @@ fn filters_lines_should_filter_response() {
.body("this is also a test of some import\nwith 2 lines, no less");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -117,8 +116,7 @@ fn filters_words_should_filter_response() {
.body("this is also a test of some import\nwith 2 lines, no less");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -163,8 +161,7 @@ fn filters_size_should_filter_response() {
.body("this is also a test of some import\nwith 2 lines, no less");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -222,8 +219,7 @@ fn filters_similar_should_filter_response() {
then.status(200).body(mutated);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -266,8 +262,7 @@ fn collect_backups_should_be_filtered() {
.body("im a backup file, but filtered out because im not 200");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -316,8 +311,7 @@ fn filters_regex_should_filter_response_based_on_headers() {
.body("this is also a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")

View File

@@ -1,9 +1,10 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use assert_cmd::Command;
use httpmock::Method::GET;
use httpmock::{MockServer, Regex};
use predicates::prelude::*;
use std::process::Command;
use utils::{setup_tmp_directory, teardown_tmp_directory};
#[test]
@@ -12,8 +13,7 @@ use utils::{setup_tmp_directory, teardown_tmp_directory};
fn test_single_target_cannot_connect() -> Result<(), Box<dyn std::error::Error>> {
let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://fjdksafjkdsajfkdsajkfdsajkfsdjkdsfdsafdsafdsajkr3l2ajfdskafdsjk")
.arg("--wordlist")
@@ -37,12 +37,11 @@ fn test_two_targets_cannot_connect() -> Result<(), Box<dyn std::error::Error>> {
let urls = vec![not_real.clone(), not_real];
let (tmp_dir, file) = setup_tmp_directory(&urls, "wordlist")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--wordlist")
.arg(file.as_os_str())
.pipe_stdin(file)
.stdin(std::fs::File::open(file)?)
.unwrap()
.assert()
.success()
@@ -70,12 +69,11 @@ fn test_one_good_and_one_bad_target_scan_succeeds() -> Result<(), Box<dyn std::e
then.status(200).body("this is a test");
});
let mut cmd = Command::cargo_bin("feroxbuster").unwrap();
cmd.arg("--stdin")
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--wordlist")
.arg(file.as_os_str())
.pipe_stdin(file)
.stdin(std::fs::File::open(file)?)
.unwrap()
.assert()
.success()
@@ -96,8 +94,7 @@ fn test_one_good_and_one_bad_target_scan_succeeds() -> Result<(), Box<dyn std::e
fn test_single_target_cannot_connect_due_to_ssl_errors() -> Result<(), Box<dyn std::error::Error>> {
let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("https://expired.badssl.com")
.arg("--wordlist")
@@ -132,13 +129,11 @@ fn test_two_good_targets_scan_succeeds() -> Result<(), Box<dyn std::error::Error
then.status(403).body("this also is a test");
});
let mut cmd = Command::cargo_bin("feroxbuster").unwrap();
cmd.arg("--stdin")
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--wordlist")
.arg(file.as_os_str())
.pipe_stdin(file)
.unwrap()
.stdin(std::fs::File::open(file)?)
.assert()
.success()
.stdout(
@@ -168,8 +163,7 @@ fn test_static_wildcard_request_found() -> Result<(), Box<dyn std::error::Error>
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -205,8 +199,7 @@ fn heuristics_static_wildcard_request_with_dont_filter() -> Result<(), Box<dyn s
then.status(200).body("this is a test");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -289,8 +282,7 @@ fn heuristics_wildcard_test_with_two_static_wildcards_with_silent_enabled(
.body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -341,8 +333,7 @@ fn heuristics_wildcard_test_that_auto_filtering_403s_still_allows_for_recursion_
then.status(200);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")

View File

@@ -1,9 +1,11 @@
mod utils;
use assert_cmd::Command;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::{MockServer, Regex};
use predicates::prelude::*;
use std::fs::{read_dir, read_to_string};
use std::process::Command;
use utils::{setup_tmp_directory, teardown_tmp_directory};
#[test]
@@ -16,8 +18,7 @@ fn main_use_root_owned_file_as_wordlist() {
then.status(200).body("this is a test");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -41,8 +42,7 @@ fn main_use_empty_wordlist() -> Result<(), Box<dyn std::error::Error>> {
then.status(200).body("this is a test");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -65,14 +65,12 @@ fn main_use_empty_stdin_targets() -> Result<(), Box<dyn std::error::Error>> {
// get_targets is called before scan, so the empty wordlist shouldn't trigger
// the 'Did not find any words' error
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--wordlist")
.arg(file.as_os_str())
.arg("-vvv")
.pipe_stdin(file)
.unwrap()
.stdin(std::fs::File::open(file)?)
.assert()
.success()
.stderr(
@@ -106,8 +104,7 @@ fn main_parallel_spawns_children() -> Result<(), Box<dyn std::error::Error>> {
let (tgt_tmp_dir, targets) =
setup_tmp_directory(&[t1.url("/"), t2.url("/"), t3.url("/")], "targets")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.env("RUST_LOG", "trace")
.arg("--stdin")
.arg("--parallel")
@@ -117,8 +114,7 @@ fn main_parallel_spawns_children() -> Result<(), Box<dyn std::error::Error>> {
.arg(outfile.as_os_str())
.arg("--wordlist")
.arg(wordlist.as_os_str())
.pipe_stdin(targets)
.unwrap()
.stdin(std::fs::File::open(targets)?)
.assert()
.success()
.stderr(
@@ -170,8 +166,7 @@ fn main_parallel_creates_output_directory() -> Result<(), Box<dyn std::error::Er
let (tgt_tmp_dir, targets) =
setup_tmp_directory(&[t1.url("/"), t2.url("/"), t3.url("/")], "targets")?;
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("--quiet")
.arg("--parallel")
@@ -180,8 +175,7 @@ fn main_parallel_creates_output_directory() -> Result<(), Box<dyn std::error::Er
.arg(outfile.as_os_str())
.arg("--wordlist")
.arg(wordlist.as_os_str())
.pipe_stdin(targets)
.unwrap()
.stdin(std::fs::File::open(targets)?)
.assert()
.success()
.stderr(
@@ -276,8 +270,7 @@ fn main_download_wordlist_from_url() -> Result<(), Box<dyn std::error::Error>> {
then.status(200);
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.current_dir(&tmp_dir)
.arg("--url")
.arg(srv.url("/"))

View File

@@ -1,5 +1,7 @@
use assert_cmd::Command;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use predicates::prelude::*;
use std::process::Command;
#[test]
/// specify an incorrect param (-fc) with --help after it on the command line
@@ -14,8 +16,7 @@ use predicates::prelude::*;
/// the new behavior we expect to see is to print the long form help message, of which
/// Ludicrous speed... go! is near the bottom of that output, so we can test for that
fn parser_incorrect_param_with_tack_tack_help() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("-fc")
.arg("--help")
.assert()
@@ -36,8 +37,7 @@ fn parser_incorrect_param_with_tack_tack_help() {
/// the new behavior we expect to see is to print the short form help message, of which
/// "[CAUTION] 4 -v's is probably too much" is near the bottom of that output, so we can test for that
fn parser_incorrect_param_with_tack_h() {
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("-fc")
.arg("-h")
.assert()

View File

@@ -1,4 +1,5 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::MockServer;
@@ -48,8 +49,7 @@ fn auto_bail_cancels_scan_with_403s() {
.body("these guys need to be 403 in order to trigger 90% threshold");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -130,8 +130,7 @@ fn auto_bail_cancels_scan_with_429s() {
.body("these guys need to be 403 in order to trigger 90% threshold");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -213,8 +212,7 @@ fn auto_tune_slows_scan_with_429s() {
let start = Instant::now();
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -277,8 +275,7 @@ fn auto_tune_slows_scan_with_403s() {
let start = Instant::now();
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -342,8 +339,7 @@ fn auto_tune_slows_scan_with_general_errors() {
let start = Instant::now();
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")

View File

@@ -1,10 +1,12 @@
mod utils;
use assert_cmd::Command;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::prelude::*;
use httpmock::MockServer;
use regex::Regex;
use std::fs::{read_to_string, write};
use std::process::Command;
use utils::{setup_tmp_directory, teardown_tmp_directory};
/// Helper to create a test wordlist with controllable patterns
@@ -63,8 +65,7 @@ fn scenario_high_403_rate() {
then.status(403).body("Forbidden");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -124,8 +125,7 @@ fn scenario_high_429_rate() {
then.status(429).body("Too Many Requests");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -191,8 +191,7 @@ fn scenario_recovery_pattern() {
then.status(403).body("Forbidden");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -267,8 +266,7 @@ fn scenario_mixed_steady_state() {
then.status(429).body("Too Many Requests");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -340,8 +338,7 @@ fn scenario_capped_auto_tune() {
then.status(403).body("Forbidden");
});
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")

View File

@@ -1,4 +1,5 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::MockServer;
@@ -19,8 +20,7 @@ fn response_size_limit_small_response_not_truncated() {
then.status(200).body(small_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -55,8 +55,7 @@ fn response_size_limit_large_response_truncated() {
then.status(200).body(&large_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -109,8 +108,7 @@ fn response_size_limit_mixed_response_sizes() {
then.status(200).body(&large_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -173,8 +171,7 @@ fn response_size_limit_default_4mb() {
then.status(200).body(&body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -206,8 +203,7 @@ fn response_size_limit_very_small_limit() {
then.status(200).body(body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -242,8 +238,7 @@ fn response_size_limit_with_redirects() {
.body(&large_redirect_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -281,8 +276,7 @@ fn response_size_limit_with_error_responses() {
then.status(500).body(&large_error_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -318,8 +312,7 @@ fn response_size_limit_json_output_includes_truncated_field() {
then.status(200).body(&large_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -350,8 +343,7 @@ fn response_size_limit_json_output_includes_truncated_field() {
fn response_size_limit_shows_in_banner() {
let (tmp_dir, file) = setup_tmp_directory(&["test".to_string()], "wordlist").unwrap();
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg("http://127.0.0.1:1") // Non-existent server to trigger quick exit
.arg("--wordlist")
@@ -385,8 +377,7 @@ fn response_size_limit_exact_limit() {
then.status(200).body(&exact_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -425,8 +416,7 @@ fn response_size_limit_from_config_file() {
then.status(200).body(&large_body);
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.current_dir(tmp_dir.path())
.arg("--url")
.arg(srv.url("/"))

View File

@@ -1,10 +1,12 @@
mod utils;
use assert_cmd::Command;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::MockServer;
use predicates::prelude::*;
use std::fs::{read_to_string, write};
use std::path::Path;
use std::process::Command;
use std::time;
use utils::{setup_tmp_directory, teardown_tmp_directory};
@@ -67,8 +69,7 @@ fn resume_scan_works() {
let (tmp_dir2, state_file) = setup_tmp_directory(&[state_file_contents], "state-file").unwrap();
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("-vvv")
.arg("--resume-from")
.arg(state_file.as_os_str())
@@ -115,16 +116,14 @@ fn time_limit_enforced_when_specified() {
let lower_bound = time::Duration::new(5, 0);
let upper_bound = time::Duration::new(6, 0);
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--stdin")
.arg("-vv")
.arg("--wordlist")
.arg(file.as_os_str())
.arg("--time-limit")
.arg("5s")
.pipe_stdin(targets)
.unwrap()
.stdin(std::fs::File::open(targets).unwrap())
.assert()
.failure();

View File

@@ -1,4 +1,5 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::MockServer;
@@ -19,8 +20,7 @@ fn scanner_single_request_scan() -> Result<(), Box<dyn std::error::Error>> {
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -72,8 +72,7 @@ fn scanner_recursive_request_scan() -> Result<(), Box<dyn std::error::Error>> {
.body("this is a test and is more bytes than other ones");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -135,8 +134,7 @@ fn scanner_recursive_request_scan_using_only_success_responses(
.body("this is a test and is more bytes than other ones");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -178,8 +176,7 @@ fn scanner_single_request_scan_with_file_output() -> Result<(), Box<dyn std::err
let outfile = tmp_dir.path().join("output");
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -214,8 +211,7 @@ fn scanner_single_request_scan_with_file_output_and_tack_q(
let outfile = tmp_dir.path().join("output");
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -250,8 +246,7 @@ fn scanner_single_request_scan_with_invalid_file_output() -> Result<(), Box<dyn
let outfile = tmp_dir.path(); // outfile is a directory
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -281,8 +276,7 @@ fn scanner_single_request_quiet_scan() -> Result<(), Box<dyn std::error::Error>>
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -317,8 +311,7 @@ fn scanner_single_request_returns_301_without_location_header(
then.status(301).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -358,8 +351,7 @@ fn scanner_single_request_replayed_to_proxy() -> Result<(), Box<dyn std::error::
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -402,8 +394,7 @@ fn scanner_single_request_scan_with_filtered_result() -> Result<(), Box<dyn std:
then.status(200).body("this is a test");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -443,8 +434,7 @@ fn scanner_single_request_scan_with_debug_logging() {
let outfile = tmp_dir.path().join("debug.log");
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -481,8 +471,7 @@ fn scanner_single_request_scan_with_debug_logging_as_json() {
let outfile = tmp_dir.path().join("debug.log");
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -530,8 +519,7 @@ fn scanner_single_request_scan_with_regex_filtered_result() {
.body("this is a test\nThat rug really tied the room together");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -578,8 +566,7 @@ fn scanner_recursion_works_with_403_directories() {
.body("this is a test\nThat rug really tied the room together");
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -628,8 +615,7 @@ fn rate_limit_enforced_when_specified() {
let now = time::Instant::now();
let lower_bound = time::Duration::new(5, 0);
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -665,8 +651,7 @@ fn add_discovered_extension_updates_bars_and_stats() {
assert!(!file_path.exists());
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -735,8 +720,7 @@ fn collect_backups_makes_appropriate_requests() {
})
.collect();
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--collect-backups")
@@ -831,8 +815,7 @@ fn collect_words_makes_appropriate_requests() {
})
.collect();
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("-vv")
@@ -890,8 +873,7 @@ fn scanner_forced_recursion_ignores_normal_redirect_logic() -> Result<(), Box<dy
let outfile = tmp_dir.path().join("output");
Command::cargo_bin("feroxbuster")
.unwrap()
Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")

View File

@@ -1,4 +1,5 @@
mod utils;
use assert_cmd::cargo_bin;
use assert_cmd::prelude::*;
use httpmock::Method::GET;
use httpmock::MockServer;
@@ -26,8 +27,7 @@ fn word_and_status_makes_a_response_unique_and_isnt_seen() -> Result<(), Box<dyn
.body(srv.url("this is a word count supplier"));
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")
@@ -69,8 +69,7 @@ fn bytes_and_status_makes_a_redirect_response_unique_and_isnt_seen(
.body(srv.url("this is a word count supplier")); // redirect + same body
});
let cmd = Command::cargo_bin("feroxbuster")
.unwrap()
let cmd = Command::new(cargo_bin!("feroxbuster"))
.arg("--url")
.arg(srv.url("/"))
.arg("--wordlist")