mirror of
https://github.com/epi052/feroxbuster.git
synced 2026-05-23 21:31:12 -03:00
Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f51993cde0 | ||
|
|
9093ffb92a | ||
|
|
d550448229 | ||
|
|
492665154e | ||
|
|
c14e617076 | ||
|
|
6bb748af17 | ||
|
|
863ea089cc | ||
|
|
ad3091a7db | ||
|
|
b2bdea71dd | ||
|
|
f478700b86 | ||
|
|
1f2aad5e52 | ||
|
|
3a6a61cc24 | ||
|
|
0311a846b3 | ||
|
|
3066efa848 | ||
|
|
a8fae65d63 | ||
|
|
970886a68b | ||
|
|
494eed81e8 | ||
|
|
c8a577b1e7 | ||
|
|
ccb10c1c68 | ||
|
|
20ab0aade3 | ||
|
|
02ad0b1d85 | ||
|
|
09aad922c1 | ||
|
|
697f947bfa | ||
|
|
d300d68737 | ||
|
|
c2c6854db4 | ||
|
|
63be575d89 | ||
|
|
0d25fda11e | ||
|
|
b0341c2432 | ||
|
|
62352db152 | ||
|
|
3090edc49c | ||
|
|
85d686d1aa | ||
|
|
17138f4ef7 | ||
|
|
1d30b7db31 | ||
|
|
4c0d3c91a0 | ||
|
|
96fc6b232a | ||
|
|
9b306aad34 | ||
|
|
10eee184d0 | ||
|
|
986161f05f | ||
|
|
4a19dbfd7d | ||
|
|
b8ceeaff0f | ||
|
|
d04e58036e | ||
|
|
d1a74207f4 | ||
|
|
03a36f0b60 | ||
|
|
f2d9269643 | ||
|
|
bba7cba02e | ||
|
|
fffd1e5c82 | ||
|
|
3c6da0f782 | ||
|
|
5ecd937c0e | ||
|
|
9f6221daf6 | ||
|
|
af49fd8e62 | ||
|
|
d1daefd8ba | ||
|
|
3e8255d5b7 | ||
|
|
5af18e83d8 | ||
|
|
d1d0757d56 | ||
|
|
f5f9344a81 | ||
|
|
fd52e39188 | ||
|
|
22377dc9a3 | ||
|
|
1cf7dff734 | ||
|
|
7c9eb900b7 | ||
|
|
8480b3cc2c | ||
|
|
9d29142046 | ||
|
|
38c194b222 | ||
|
|
72dc14bf3d | ||
|
|
9a7c690c17 | ||
|
|
de4514e381 | ||
|
|
2be8aaf2bf | ||
|
|
4db3a0b056 | ||
|
|
a9ef7f180f | ||
|
|
ac7cb5d6b6 | ||
|
|
f8e18abb48 | ||
|
|
1d805aca5a | ||
|
|
fa09266804 | ||
|
|
15592c3dfd | ||
|
|
53c171aeb5 | ||
|
|
5167d24c4b | ||
|
|
81ff62c53d | ||
|
|
433f68458e | ||
|
|
d32720a90a | ||
|
|
0ceef975e6 | ||
|
|
6d7d6c4e7b | ||
|
|
5f21953bc1 | ||
|
|
6906ac0ee8 | ||
|
|
cafe766d9e | ||
|
|
98d0d177df | ||
|
|
23e10833d0 | ||
|
|
7f51d0f7bf |
@@ -390,6 +390,53 @@
|
||||
"name": "Jason Haddix",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3488554?v=4",
|
||||
"profile": "https://twitter.com/Jhaddix",
|
||||
"contributions": [
|
||||
"ideas",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ThisLimn0",
|
||||
"name": "Limn0",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/67125885?v=4",
|
||||
"profile": "https://github.com/ThisLimn0",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "0xdf223",
|
||||
"name": "0xdf",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/76954092?v=4",
|
||||
"profile": "https://github.com/0xdf223",
|
||||
"contributions": [
|
||||
"bug",
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Flangyver",
|
||||
"name": "Flangyver",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/59575870?v=4",
|
||||
"profile": "https://github.com/Flangyver",
|
||||
"contributions": [
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "DonatoReis",
|
||||
"name": "PeakyBlinder",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/93531354?v=4",
|
||||
"profile": "https://github.com/DonatoReis",
|
||||
"contributions": [
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "postmodern",
|
||||
"name": "Postmodern",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12671?v=4",
|
||||
"profile": "https://postmodern.github.io/",
|
||||
"contributions": [
|
||||
"ideas"
|
||||
]
|
||||
|
||||
28
.github/workflows/build.yml
vendored
28
.github/workflows/build.yml
vendored
@@ -73,18 +73,22 @@ jobs:
|
||||
name: ${{ matrix.name }}.tar.gz
|
||||
path: ${{ matrix.name }}.tar.gz
|
||||
|
||||
build-deb:
|
||||
needs: [build-nix]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Deb Build
|
||||
uses: ebbflow-io/cargo-deb-amd64-ubuntu@1.0
|
||||
- name: Upload Deb Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: feroxbuster_amd64.deb
|
||||
path: ./target/x86_64-unknown-linux-musl/debian/*
|
||||
# build-deb:
|
||||
# needs: [build-nix]
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@master
|
||||
# - name: Install cargo-deb
|
||||
# run: cargo install -f cargo-deb
|
||||
# - name: Install musl toolchain
|
||||
# run: rustup target add x86_64-unknown-linux-musl
|
||||
# - name: Deb Build
|
||||
# run: cargo deb --target=x86_64-unknown-linux-musl
|
||||
# - name: Upload Deb Artifact
|
||||
# uses: actions/upload-artifact@v2
|
||||
# with:
|
||||
# name: feroxbuster_amd64.deb
|
||||
# path: ./target/x86_64-unknown-linux-musl/debian/*
|
||||
|
||||
build-macos:
|
||||
env:
|
||||
|
||||
32
.github/workflows/check.yml
vendored
32
.github/workflows/check.yml
vendored
@@ -8,11 +8,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: check
|
||||
@@ -22,26 +17,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- name: Install latest nextest release
|
||||
uses: taiki-e/install-action@nextest
|
||||
- name: Test with latest nextest release
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
command: nextest
|
||||
args: run --all-features --all-targets --retries 10
|
||||
|
||||
fmt:
|
||||
name: Rust fmt
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- run: rustup component add rustfmt
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
@@ -52,13 +40,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- run: rustup component add clippy
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --all-targets --all-features -- -D warnings -A clippy::deref_addrof -A clippy::mutex-atomic
|
||||
args: --all-targets --all-features -- -D warnings
|
||||
|
||||
48
.github/workflows/coverage.yml
vendored
48
.github/workflows/coverage.yml
vendored
@@ -3,42 +3,22 @@ on: [push]
|
||||
name: Code Coverage Pipeline
|
||||
|
||||
jobs:
|
||||
upload-coverage:
|
||||
coverage:
|
||||
name: LLVM Coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clean
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --all-features --no-fail-fast
|
||||
env:
|
||||
CARGO_INCREMENTAL: '0'
|
||||
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort'
|
||||
RUSTDOCFLAGS: '-Cpanic=abort'
|
||||
- uses: actions-rs/grcov@v0.1
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: lcov.info
|
||||
path: lcov.info
|
||||
- name: Convert lcov to xml
|
||||
run: |
|
||||
curl -O https://raw.githubusercontent.com/epi052/lcov-to-cobertura-xml/master/lcov_cobertura/lcov_cobertura.py
|
||||
chmod +x lcov_cobertura.py
|
||||
./lcov_cobertura.py ./lcov.info
|
||||
- uses: codecov/codecov-action@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install llvm-tools-preview
|
||||
run: rustup toolchain install stable --component llvm-tools-preview
|
||||
- name: Install cargo-llvm-cov
|
||||
uses: taiki-e/install-action@cargo-llvm-cov
|
||||
- name: Install cargo-nextest
|
||||
uses: taiki-e/install-action@nextest
|
||||
- name: Generate code coverage
|
||||
run: cargo llvm-cov nextest --all-features --no-fail-fast --lcov --output-path lcov.info -- --retries 10
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
file: ./coverage.xml
|
||||
name: codecov-umbrella
|
||||
files: lcov.info
|
||||
fail_ci_if_error: true
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: coverage.xml
|
||||
path: ./coverage.xml
|
||||
|
||||
338
Cargo.lock
generated
338
Cargo.lock
generated
@@ -13,9 +13,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.56"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
|
||||
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||
|
||||
[[package]]
|
||||
name = "ascii-canvas"
|
||||
@@ -139,9 +139,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "1.3.0"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6"
|
||||
checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"blocking",
|
||||
@@ -329,15 +329,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.8"
|
||||
version = "3.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
|
||||
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"terminal_size",
|
||||
@@ -346,13 +346,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "3.1.1"
|
||||
version = "3.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
|
||||
checksum = "da92e6facd8d73c22745a5d3cbb59bdf8e46e3235c923e516527d8e81eec14a4"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "1.2.2"
|
||||
@@ -450,7 +459,7 @@ dependencies = [
|
||||
"dtoa-short",
|
||||
"itoa 0.4.8",
|
||||
"matches",
|
||||
"phf",
|
||||
"phf 0.8.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"smallvec",
|
||||
@@ -479,9 +488,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.2.1"
|
||||
version = "3.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf"
|
||||
checksum = "b37feaa84e6861e00a1f5e5aa8da3ee56d605c9992d33e082786754828e20865"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"winapi",
|
||||
@@ -504,9 +513,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "curl-sys"
|
||||
version = "0.4.53+curl-7.82.0"
|
||||
version = "0.4.54+curl-7.83.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8092905a5a9502c312f223b2775f57ec5c5b715f9a15ee9d2a8591d1364a0352"
|
||||
checksum = "25debbc3365c3e7ee79e30918df5759e84dbd4485807a18829188abf1786ec4e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -671,7 +680,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "feroxbuster"
|
||||
version = "2.6.4"
|
||||
version = "2.7.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@@ -708,9 +717,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.2.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||
checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e"
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
@@ -914,9 +923,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gloo-timers"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e"
|
||||
checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -960,9 +969,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "html5ever"
|
||||
version = "0.25.2"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148"
|
||||
checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
|
||||
dependencies = [
|
||||
"log",
|
||||
"mac",
|
||||
@@ -974,9 +983,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
|
||||
checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -996,9 +1005,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.6.0"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4"
|
||||
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
@@ -1121,15 +1130,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c"
|
||||
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
|
||||
|
||||
[[package]]
|
||||
name = "isahc"
|
||||
version = "1.7.0"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "437f8808009c031df3c1d532c8fd7e3d73239dfe522ebf0b94b5e34d5d01044b"
|
||||
checksum = "480d9158c9977bff0bc024a11dcad04efcd3955c1e55301092b13fc439d41720"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"castaway",
|
||||
@@ -1175,9 +1184,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.56"
|
||||
version = "0.3.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
|
||||
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -1193,9 +1202,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.19.7"
|
||||
version = "0.19.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852b75a095da6b69da8c5557731c3afd06525d4f655a4fc1c799e2ec8bc4dce4"
|
||||
checksum = "b30455341b0e18f276fa64540aff54deafb54c589de6aca68659c63dd2d5d823"
|
||||
dependencies = [
|
||||
"ascii-canvas",
|
||||
"atty",
|
||||
@@ -1216,9 +1225,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.19.7"
|
||||
version = "0.19.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6d265705249fe209280676d8f68887859fa42e1d34f342fc05bd47726a5e188"
|
||||
checksum = "bcf796c978e9b4d983414f4caedc9273aa33ee214c5b887bd55fde84c85d2dc4"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
@@ -1251,9 +1260,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.122"
|
||||
version = "0.2.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
|
||||
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
|
||||
|
||||
[[package]]
|
||||
name = "libnghttp2-sys"
|
||||
@@ -1267,9 +1276,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.5"
|
||||
version = "1.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859"
|
||||
checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -1289,9 +1298,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.16"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"value-bag",
|
||||
@@ -1305,13 +1314,13 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.10.1"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd"
|
||||
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf 0.10.1",
|
||||
"phf_codegen 0.10.0",
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
"tendril",
|
||||
@@ -1325,18 +1334,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
@@ -1346,25 +1346,14 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
|
||||
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1393,15 +1382,13 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.23.1"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
|
||||
checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1416,20 +1403,11 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@@ -1458,18 +1436,30 @@ checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.38"
|
||||
version = "0.10.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
|
||||
checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
@@ -1487,9 +1477,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.72"
|
||||
version = "0.9.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
|
||||
checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
@@ -1504,9 +1494,6 @@ name = "os_str_bytes"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
@@ -1526,9 +1513,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37"
|
||||
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -1545,9 +1532,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
|
||||
checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
@@ -1564,6 +1551,15 @@ dependencies = [
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_shared 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.8.0"
|
||||
@@ -1574,6 +1570,16 @@ dependencies = [
|
||||
"phf_shared 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
|
||||
dependencies = [
|
||||
"phf_generator 0.10.0",
|
||||
"phf_shared 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.8.0"
|
||||
@@ -1654,9 +1660,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
@@ -1733,18 +1739,18 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||
checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.17"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -1967,9 +1973,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scraper"
|
||||
version = "0.12.0"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48e02aa790c80c2e494130dec6a522033b6a23603ffc06360e9fe6c611ea2c12"
|
||||
checksum = "5684396b456f3eb69ceeb34d1b5cb1a2f6acf7ca4452131efa3ba0ee2c2d0a70"
|
||||
dependencies = [
|
||||
"cssparser",
|
||||
"ego-tree",
|
||||
@@ -2016,8 +2022,8 @@ dependencies = [
|
||||
"fxhash",
|
||||
"log",
|
||||
"matches",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf 0.8.0",
|
||||
"phf_codegen 0.8.0",
|
||||
"precomputed-hash",
|
||||
"servo_arc",
|
||||
"smallvec",
|
||||
@@ -2026,24 +2032,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.7"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
|
||||
checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.136"
|
||||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.136"
|
||||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2052,9 +2058,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.79"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
||||
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||
dependencies = [
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
@@ -2208,9 +2214,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.91"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
|
||||
checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2295,18 +2301,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2324,9 +2330,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.5.1"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
@@ -2339,9 +2345,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.17.0"
|
||||
version = "1.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||
checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -2417,9 +2423,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -2432,9 +2438,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.32"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
|
||||
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"log",
|
||||
@@ -2445,9 +2451,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.20"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
|
||||
checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2456,9 +2462,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.24"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee"
|
||||
checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
@@ -2481,9 +2487,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
|
||||
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
@@ -2502,9 +2508,9 @@ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
@@ -2527,18 +2533,18 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.2"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0"
|
||||
dependencies = [
|
||||
"getrandom 0.2.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.0.0-alpha.8"
|
||||
version = "1.0.0-alpha.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f"
|
||||
checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"version_check",
|
||||
@@ -2601,9 +2607,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.79"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
|
||||
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
@@ -2611,9 +2617,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.79"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
|
||||
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
@@ -2626,9 +2632,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.29"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
|
||||
checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
@@ -2638,9 +2644,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.79"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
|
||||
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -2648,9 +2654,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.79"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
|
||||
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2661,15 +2667,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.79"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
|
||||
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.56"
|
||||
version = "0.3.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
|
||||
checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@@ -2717,9 +2723,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.34.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
@@ -2730,33 +2736,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.34.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.34.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.34.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.34.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.34.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
|
||||
68
Cargo.toml
68
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "feroxbuster"
|
||||
version = "2.6.4"
|
||||
version = "2.7.1"
|
||||
authors = ["Ben 'epi' Risher (@epi052)"]
|
||||
license = "MIT"
|
||||
edition = "2021"
|
||||
@@ -8,7 +8,13 @@ homepage = "https://github.com/epi052/feroxbuster"
|
||||
repository = "https://github.com/epi052/feroxbuster"
|
||||
description = "A fast, simple, recursive content discovery tool."
|
||||
categories = ["command-line-utilities"]
|
||||
keywords = ["pentest", "enumeration", "url-bruteforce", "content-discovery", "web"]
|
||||
keywords = [
|
||||
"pentest",
|
||||
"enumeration",
|
||||
"url-bruteforce",
|
||||
"content-discovery",
|
||||
"web",
|
||||
]
|
||||
exclude = [".github/*", "img/*", "check-coverage.sh"]
|
||||
build = "build.rs"
|
||||
|
||||
@@ -16,40 +22,40 @@ build = "build.rs"
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[build-dependencies]
|
||||
clap = { version = "3.1.8", features = ["wrap_help", "cargo"] }
|
||||
clap_complete = "3.1.1"
|
||||
clap = { version = "3.1.18", features = ["wrap_help", "cargo"] }
|
||||
clap_complete = "3.1.4"
|
||||
regex = "1.5.5"
|
||||
lazy_static = "1.4.0"
|
||||
dirs = "4.0.0"
|
||||
|
||||
[dependencies]
|
||||
scraper = "0.12.0"
|
||||
scraper = "0.13.0"
|
||||
futures = "0.3.21"
|
||||
tokio = { version = "1.17.0", features = ["full"] }
|
||||
tokio = { version = "1.18.2", features = ["full"] }
|
||||
tokio-util = { version = "0.7.1", features = ["codec"] }
|
||||
log = "0.4.16"
|
||||
log = "0.4.17"
|
||||
env_logger = "0.9.0"
|
||||
reqwest = { version = "0.11.10", features = ["socks"] }
|
||||
# uses feature unification to add 'serde' to reqwest::Url
|
||||
url = { version = "2.2.2", features = ["serde"] }
|
||||
serde_regex = "1.1.0"
|
||||
clap = { version = "3.1.8", features = ["wrap_help", "cargo"] }
|
||||
clap = { version = "3.1.18", features = ["wrap_help", "cargo"] }
|
||||
lazy_static = "1.4.0"
|
||||
toml = "0.5.8"
|
||||
serde = { version = "1.0.136", features = ["derive", "rc"] }
|
||||
serde_json = "1.0.79"
|
||||
uuid = { version = "0.8.2", features = ["v4"] }
|
||||
toml = "0.5.9"
|
||||
serde = { version = "1.0.137", features = ["derive", "rc"] }
|
||||
serde_json = "1.0.81"
|
||||
uuid = { version = "1.0.0", features = ["v4"] }
|
||||
indicatif = "0.15"
|
||||
console = "0.15.0"
|
||||
openssl = { version = "0.10.38", features = ["vendored"] }
|
||||
openssl = { version = "0.10.40", features = ["vendored"] }
|
||||
dirs = "4.0.0"
|
||||
regex = "1.5.5"
|
||||
crossterm = "0.23.2"
|
||||
rlimit = "0.8.3"
|
||||
ctrlc = "3.2.1"
|
||||
ctrlc = "3.2.2"
|
||||
fuzzyhash = "0.2.1"
|
||||
anyhow = "1.0.56"
|
||||
leaky-bucket = "0.10.0" # todo: upgrade, will take a little work/thought since api changed
|
||||
anyhow = "1.0.57"
|
||||
leaky-bucket = "0.10.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.3.0"
|
||||
@@ -67,9 +73,29 @@ section = "utility"
|
||||
license-file = ["LICENSE", "4"]
|
||||
conf-files = ["/etc/feroxbuster/ferox-config.toml"]
|
||||
assets = [
|
||||
["target/release/feroxbuster", "/usr/bin/", "755"],
|
||||
["ferox-config.toml.example", "/etc/feroxbuster/ferox-config.toml", "644"],
|
||||
["shell_completions/feroxbuster.bash", "/usr/share/bash-completion/completions/feroxbuster.bash", "644"],
|
||||
["shell_completions/feroxbuster.fish", "/usr/share/fish/completions/feroxbuster.fish", "644"],
|
||||
["shell_completions/_feroxbuster", "/usr/share/zsh/vendor-completions/_feroxbuster", "644"],
|
||||
[
|
||||
"target/release/feroxbuster",
|
||||
"/usr/bin/",
|
||||
"755",
|
||||
],
|
||||
[
|
||||
"ferox-config.toml.example",
|
||||
"/etc/feroxbuster/ferox-config.toml",
|
||||
"644",
|
||||
],
|
||||
[
|
||||
"shell_completions/feroxbuster.bash",
|
||||
"/usr/share/bash-completion/completions/feroxbuster.bash",
|
||||
"644",
|
||||
],
|
||||
[
|
||||
"shell_completions/feroxbuster.fish",
|
||||
"/usr/share/fish/completions/feroxbuster.fish",
|
||||
"644",
|
||||
],
|
||||
[
|
||||
"shell_completions/_feroxbuster",
|
||||
"/usr/share/zsh/vendor-completions/_feroxbuster",
|
||||
"644",
|
||||
],
|
||||
]
|
||||
|
||||
11
README.md
11
README.md
@@ -233,7 +233,14 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center"><a href="http://ryanmontgomery.me"><img src="https://avatars.githubusercontent.com/u/44453666?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ryan Montgomery</b></sub></a><br /><a href="#ideas-0dayCTF" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/IppSec"><img src="https://avatars.githubusercontent.com/u/24677271?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ippsec</b></sub></a><br /><a href="#ideas-ippsec" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/gtjamesa"><img src="https://avatars.githubusercontent.com/u/2078364?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/issues?q=author%3Agtjamesa" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://twitter.com/Jhaddix"><img src="https://avatars.githubusercontent.com/u/3488554?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jason Haddix</b></sub></a><br /><a href="#ideas-jhaddix" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://twitter.com/Jhaddix"><img src="https://avatars.githubusercontent.com/u/3488554?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jason Haddix</b></sub></a><br /><a href="#ideas-jhaddix" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/epi052/feroxbuster/issues?q=author%3Ajhaddix" title="Bug reports">🐛</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ThisLimn0"><img src="https://avatars.githubusercontent.com/u/67125885?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Limn0</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/issues?q=author%3AThisLimn0" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://github.com/0xdf223"><img src="https://avatars.githubusercontent.com/u/76954092?v=4?s=100" width="100px;" alt=""/><br /><sub><b>0xdf</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/issues?q=author%3A0xdf223" title="Bug reports">🐛</a> <a href="#ideas-0xdf223" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/Flangyver"><img src="https://avatars.githubusercontent.com/u/59575870?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Flangyver</b></sub></a><br /><a href="#ideas-Flangyver" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/DonatoReis"><img src="https://avatars.githubusercontent.com/u/93531354?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PeakyBlinder</b></sub></a><br /><a href="#ideas-DonatoReis" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://postmodern.github.io/"><img src="https://avatars.githubusercontent.com/u/12671?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Postmodern</b></sub></a><br /><a href="#ideas-postmodern" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -242,4 +249,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
# dont_filter = true
|
||||
# extract_links = true
|
||||
# depth = 1
|
||||
# force_recursion = true
|
||||
# filter_size = [5174]
|
||||
# filter_regex = ["^ignore me$"]
|
||||
# filter_similar = ["https://somesite.com/soft404"]
|
||||
|
||||
@@ -24,8 +24,8 @@ _feroxbuster() {
|
||||
'--replay-proxy=[Send only unfiltered requests through a Replay Proxy, instead of all requests]:REPLAY_PROXY:_urls' \
|
||||
'*-R+[Status Codes to send through a Replay Proxy when found (default: --status-codes value)]:REPLAY_CODE: ' \
|
||||
'*--replay-codes=[Status Codes to send through a Replay Proxy when found (default: --status-codes value)]:REPLAY_CODE: ' \
|
||||
'-a+[Sets the User-Agent (default: feroxbuster/2.6.4)]:USER_AGENT: ' \
|
||||
'--user-agent=[Sets the User-Agent (default: feroxbuster/2.6.4)]:USER_AGENT: ' \
|
||||
'-a+[Sets the User-Agent (default: feroxbuster/2.7.1)]:USER_AGENT: ' \
|
||||
'--user-agent=[Sets the User-Agent (default: feroxbuster/2.7.1)]:USER_AGENT: ' \
|
||||
'*-x+[File extension(s) to search for (ex: -x php -x pdf js)]:FILE_EXTENSION: ' \
|
||||
'*--extensions=[File extension(s) to search for (ex: -x php -x pdf js)]:FILE_EXTENSION: ' \
|
||||
'*-m+[Which HTTP request method(s) should be sent (default: GET)]:HTTP_METHODS: ' \
|
||||
@@ -46,8 +46,8 @@ _feroxbuster() {
|
||||
'*--filter-words=[Filter out messages of a particular word count (ex: -W 312 -W 91,82)]:WORDS: ' \
|
||||
'*-N+[Filter out messages of a particular line count (ex: -N 20 -N 31,30)]:LINES: ' \
|
||||
'*--filter-lines=[Filter out messages of a particular line count (ex: -N 20 -N 31,30)]:LINES: ' \
|
||||
'*-C+[Filter out status codes (deny list) (ex: -C 200 -C 401)]:STATUS_CODE: ' \
|
||||
'*--filter-status=[Filter out status codes (deny list) (ex: -C 200 -C 401)]:STATUS_CODE: ' \
|
||||
'(-s --status-codes)*-C+[Filter out status codes (deny list) (ex: -C 200 -C 401)]:STATUS_CODE: ' \
|
||||
'(-s --status-codes)*--filter-status=[Filter out status codes (deny list) (ex: -C 200 -C 401)]:STATUS_CODE: ' \
|
||||
'*--filter-similar-to=[Filter out pages that are similar to the given page (ex. --filter-similar-to http://site.xyz/soft404)]:UNWANTED_PAGE:_urls' \
|
||||
'*-s+[Status Codes to include (allow list) (default: 200 204 301 302 307 308 401 403 405)]:STATUS_CODE: ' \
|
||||
'*--status-codes=[Status Codes to include (allow list) (default: 200 204 301 302 307 308 401 403 405)]:STATUS_CODE: ' \
|
||||
@@ -88,6 +88,7 @@ _feroxbuster() {
|
||||
'--insecure[Disables TLS certificate validation in the client]' \
|
||||
'-n[Do not scan recursively]' \
|
||||
'--no-recursion[Do not scan recursively]' \
|
||||
'(-n --no-recursion)--force-recursion[Force recursion attempts on all '\''found'\'' endpoints (still respects recursion depth)]' \
|
||||
'-e[Extract links from response body (html, javascript, etc...); make new requests based on findings]' \
|
||||
'--extract-links[Extract links from response body (html, javascript, etc...); make new requests based on findings]' \
|
||||
'(--auto-bail)--auto-tune[Automatically lower scan rate when an excessive amount of errors are encountered]' \
|
||||
|
||||
@@ -30,8 +30,8 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock {
|
||||
[CompletionResult]::new('--replay-proxy', 'replay-proxy', [CompletionResultType]::ParameterName, 'Send only unfiltered requests through a Replay Proxy, instead of all requests')
|
||||
[CompletionResult]::new('-R', 'R', [CompletionResultType]::ParameterName, 'Status Codes to send through a Replay Proxy when found (default: --status-codes value)')
|
||||
[CompletionResult]::new('--replay-codes', 'replay-codes', [CompletionResultType]::ParameterName, 'Status Codes to send through a Replay Proxy when found (default: --status-codes value)')
|
||||
[CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.6.4)')
|
||||
[CompletionResult]::new('--user-agent', 'user-agent', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.6.4)')
|
||||
[CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.7.1)')
|
||||
[CompletionResult]::new('--user-agent', 'user-agent', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.7.1)')
|
||||
[CompletionResult]::new('-x', 'x', [CompletionResultType]::ParameterName, 'File extension(s) to search for (ex: -x php -x pdf js)')
|
||||
[CompletionResult]::new('--extensions', 'extensions', [CompletionResultType]::ParameterName, 'File extension(s) to search for (ex: -x php -x pdf js)')
|
||||
[CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Which HTTP request method(s) should be sent (default: GET)')
|
||||
@@ -94,6 +94,7 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock {
|
||||
[CompletionResult]::new('--insecure', 'insecure', [CompletionResultType]::ParameterName, 'Disables TLS certificate validation in the client')
|
||||
[CompletionResult]::new('-n', 'n', [CompletionResultType]::ParameterName, 'Do not scan recursively')
|
||||
[CompletionResult]::new('--no-recursion', 'no-recursion', [CompletionResultType]::ParameterName, 'Do not scan recursively')
|
||||
[CompletionResult]::new('--force-recursion', 'force-recursion', [CompletionResultType]::ParameterName, 'Force recursion attempts on all ''found'' endpoints (still respects recursion depth)')
|
||||
[CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'Extract links from response body (html, javascript, etc...); make new requests based on findings')
|
||||
[CompletionResult]::new('--extract-links', 'extract-links', [CompletionResultType]::ParameterName, 'Extract links from response body (html, javascript, etc...); make new requests based on findings')
|
||||
[CompletionResult]::new('--auto-tune', 'auto-tune', [CompletionResultType]::ParameterName, 'Automatically lower scan rate when an excessive amount of errors are encountered')
|
||||
|
||||
@@ -19,7 +19,7 @@ _feroxbuster() {
|
||||
|
||||
case "${cmd}" in
|
||||
feroxbuster)
|
||||
opts="-h -V -u -p -P -R -a -A -x -m -H -b -Q -f -S -X -W -N -C -s -T -r -k -t -n -d -e -L -w -D -E -B -g -I -v -q -o --help --version --url --stdin --resume-from --burp --burp-replay --smart --thorough --proxy --replay-proxy --replay-codes --user-agent --random-agent --extensions --methods --data --headers --cookies --query --add-slash --dont-scan --filter-size --filter-regex --filter-words --filter-lines --filter-status --filter-similar-to --status-codes --timeout --redirects --insecure --threads --no-recursion --depth --extract-links --scan-limit --parallel --rate-limit --time-limit --wordlist --auto-tune --auto-bail --dont-filter --collect-extensions --collect-backups --collect-words --dont-collect --verbosity --silent --quiet --json --output --debug-log --no-state"
|
||||
opts="-h -V -u -p -P -R -a -A -x -m -H -b -Q -f -S -X -W -N -C -s -T -r -k -t -n -d -e -L -w -D -E -B -g -I -v -q -o --help --version --url --stdin --resume-from --burp --burp-replay --smart --thorough --proxy --replay-proxy --replay-codes --user-agent --random-agent --extensions --methods --data --headers --cookies --query --add-slash --dont-scan --filter-size --filter-regex --filter-words --filter-lines --filter-status --filter-similar-to --status-codes --timeout --redirects --insecure --threads --no-recursion --depth --force-recursion --extract-links --scan-limit --parallel --rate-limit --time-limit --wordlist --auto-tune --auto-bail --dont-filter --collect-extensions --collect-backups --collect-words --dont-collect --verbosity --silent --quiet --json --output --debug-log --no-state"
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
||||
@@ -27,8 +27,8 @@ set edit:completion:arg-completer[feroxbuster] = {|@words|
|
||||
cand --replay-proxy 'Send only unfiltered requests through a Replay Proxy, instead of all requests'
|
||||
cand -R 'Status Codes to send through a Replay Proxy when found (default: --status-codes value)'
|
||||
cand --replay-codes 'Status Codes to send through a Replay Proxy when found (default: --status-codes value)'
|
||||
cand -a 'Sets the User-Agent (default: feroxbuster/2.6.4)'
|
||||
cand --user-agent 'Sets the User-Agent (default: feroxbuster/2.6.4)'
|
||||
cand -a 'Sets the User-Agent (default: feroxbuster/2.7.1)'
|
||||
cand --user-agent 'Sets the User-Agent (default: feroxbuster/2.7.1)'
|
||||
cand -x 'File extension(s) to search for (ex: -x php -x pdf js)'
|
||||
cand --extensions 'File extension(s) to search for (ex: -x php -x pdf js)'
|
||||
cand -m 'Which HTTP request method(s) should be sent (default: GET)'
|
||||
@@ -91,6 +91,7 @@ set edit:completion:arg-completer[feroxbuster] = {|@words|
|
||||
cand --insecure 'Disables TLS certificate validation in the client'
|
||||
cand -n 'Do not scan recursively'
|
||||
cand --no-recursion 'Do not scan recursively'
|
||||
cand --force-recursion 'Force recursion attempts on all ''found'' endpoints (still respects recursion depth)'
|
||||
cand -e 'Extract links from response body (html, javascript, etc...); make new requests based on findings'
|
||||
cand --extract-links 'Extract links from response body (html, javascript, etc...); make new requests based on findings'
|
||||
cand --auto-tune 'Automatically lower scan rate when an excessive amount of errors are encountered'
|
||||
|
||||
@@ -163,6 +163,9 @@ pub struct Banner {
|
||||
|
||||
/// represents Configuration.collect_words
|
||||
collect_words: BannerEntry,
|
||||
|
||||
/// represents Configuration.collect_words
|
||||
force_recursion: BannerEntry,
|
||||
}
|
||||
|
||||
/// implementation of Banner
|
||||
@@ -300,6 +303,8 @@ impl Banner {
|
||||
&config.scan_limit.to_string(),
|
||||
);
|
||||
|
||||
let force_recursion =
|
||||
BannerEntry::new("🤘", "Force Recursion", &config.force_recursion.to_string());
|
||||
let replay_proxy = BannerEntry::new("🎥", "Replay Proxy", &config.replay_proxy);
|
||||
let auto_tune = BannerEntry::new("🎶", "Auto Tune", &config.auto_tune.to_string());
|
||||
let auto_bail = BannerEntry::new("🪣", "Auto Bail", &config.auto_bail.to_string());
|
||||
@@ -409,6 +414,7 @@ impl Banner {
|
||||
no_recursion,
|
||||
rate_limit,
|
||||
scan_limit,
|
||||
force_recursion,
|
||||
time_limit,
|
||||
url_denylist,
|
||||
collect_extensions,
|
||||
@@ -511,11 +517,12 @@ by Ben "epi" Risher {} ver: {}"#,
|
||||
|
||||
writeln!(&mut writer, "{}", self.threads)?;
|
||||
writeln!(&mut writer, "{}", self.wordlist)?;
|
||||
writeln!(&mut writer, "{}", self.status_codes)?;
|
||||
|
||||
if !config.filter_status.is_empty() {
|
||||
// exception here for an optional print in the middle of always printed values is due
|
||||
// to me wanting the allows and denys to be printed one after the other
|
||||
if config.filter_status.is_empty() {
|
||||
// -C and -s are mutually exclusive, and -s meaning changes when -C is used
|
||||
// so only print one or the other
|
||||
writeln!(&mut writer, "{}", self.status_codes)?;
|
||||
} else {
|
||||
writeln!(&mut writer, "{}", self.filter_status)?;
|
||||
}
|
||||
|
||||
@@ -642,6 +649,10 @@ by Ben "epi" Risher {} ver: {}"#,
|
||||
|
||||
writeln!(&mut writer, "{}", self.no_recursion)?;
|
||||
|
||||
if config.force_recursion {
|
||||
writeln!(&mut writer, "{}", self.force_recursion)?;
|
||||
}
|
||||
|
||||
if config.scan_limit > 0 {
|
||||
writeln!(&mut writer, "{}", self.scan_limit)?;
|
||||
}
|
||||
|
||||
@@ -281,6 +281,10 @@ pub struct Configuration {
|
||||
/// Automatically discover important words from within responses and add them to the wordlist
|
||||
#[serde(default)]
|
||||
pub collect_words: bool,
|
||||
|
||||
/// override recursion logic to always attempt recursion, still respects --depth
|
||||
#[serde(default)]
|
||||
pub force_recursion: bool,
|
||||
}
|
||||
|
||||
impl Default for Configuration {
|
||||
@@ -329,6 +333,7 @@ impl Default for Configuration {
|
||||
collect_backups: false,
|
||||
collect_words: false,
|
||||
save_state: true,
|
||||
force_recursion: false,
|
||||
proxy: String::new(),
|
||||
config: String::new(),
|
||||
output: String::new(),
|
||||
@@ -405,6 +410,7 @@ impl Configuration {
|
||||
/// - **json**: `false`
|
||||
/// - **dont_filter**: `false` (auto filter wildcard responses)
|
||||
/// - **depth**: `4` (maximum recursion depth)
|
||||
/// - **force_recursion**: `false` (still respects recursion depth)
|
||||
/// - **scan_limit**: `0` (no limit on concurrent scans imposed)
|
||||
/// - **parallel**: `0` (no limit on parallel scans imposed)
|
||||
/// - **rate_limit**: `0` (no limit on requests per second imposed)
|
||||
@@ -586,7 +592,9 @@ impl Configuration {
|
||||
}
|
||||
|
||||
if let Some(arg) = args.values_of("extensions") {
|
||||
config.extensions = arg.map(|val| val.to_string()).collect();
|
||||
config.extensions = arg
|
||||
.map(|val| val.trim_start_matches('.').to_string())
|
||||
.collect();
|
||||
}
|
||||
|
||||
if let Some(arg) = args.values_of("dont_collect") {
|
||||
@@ -774,6 +782,10 @@ impl Configuration {
|
||||
config.json = true;
|
||||
}
|
||||
|
||||
if args.is_present("force_recursion") {
|
||||
config.force_recursion = true;
|
||||
}
|
||||
|
||||
////
|
||||
// organizational breakpoint; all options below alter the Client configuration
|
||||
////
|
||||
@@ -942,6 +954,7 @@ impl Configuration {
|
||||
update_if_not_default!(&mut conf.output, new.output, "");
|
||||
update_if_not_default!(&mut conf.redirects, new.redirects, false);
|
||||
update_if_not_default!(&mut conf.insecure, new.insecure, false);
|
||||
update_if_not_default!(&mut conf.force_recursion, new.force_recursion, false);
|
||||
update_if_not_default!(&mut conf.extract_links, new.extract_links, false);
|
||||
update_if_not_default!(&mut conf.extensions, new.extensions, Vec::<String>::new());
|
||||
update_if_not_default!(&mut conf.methods, new.methods, Vec::<String>::new());
|
||||
@@ -1017,7 +1030,17 @@ impl Configuration {
|
||||
/// uses serde to deserialize the toml into a `Configuration` struct
|
||||
pub(super) fn parse_config(config_file: PathBuf) -> Result<Self> {
|
||||
let content = read_to_string(config_file)?;
|
||||
let config: Self = toml::from_str(content.as_str())?;
|
||||
let mut config: Self = toml::from_str(content.as_str())?;
|
||||
|
||||
if !config.extensions.is_empty() {
|
||||
// remove leading periods, if any are found
|
||||
config.extensions = config
|
||||
.extensions
|
||||
.iter()
|
||||
.map(|ext| ext.trim_start_matches('.').to_string())
|
||||
.collect();
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ fn setup_config_test() -> Configuration {
|
||||
json = true
|
||||
save_state = false
|
||||
depth = 1
|
||||
force_recursion = true
|
||||
filter_size = [4120]
|
||||
filter_regex = ["^ignore me$"]
|
||||
filter_similar = ["https://somesite.com/soft404"]
|
||||
@@ -95,6 +96,7 @@ fn default_configuration() {
|
||||
assert!(config.save_state);
|
||||
assert!(!config.stdin);
|
||||
assert!(!config.add_slash);
|
||||
assert!(!config.force_recursion);
|
||||
assert!(!config.redirects);
|
||||
assert!(!config.extract_links);
|
||||
assert!(!config.insecure);
|
||||
@@ -208,6 +210,13 @@ fn config_reads_silent() {
|
||||
assert!(config.silent);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// parse the test config and see that the value parsed is correct
|
||||
fn config_reads_force_recursion() {
|
||||
let config = setup_config_test();
|
||||
assert!(config.force_recursion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// parse the test config and see that the value parsed is correct
|
||||
fn config_reads_quiet() {
|
||||
|
||||
@@ -5,6 +5,7 @@ use tokio::sync::oneshot::Sender;
|
||||
|
||||
use crate::response::FeroxResponse;
|
||||
use crate::{
|
||||
event_handlers::Handles,
|
||||
message::FeroxMessage,
|
||||
statistics::{StatError, StatField},
|
||||
traits::FeroxFilter,
|
||||
@@ -78,4 +79,8 @@ pub enum Command {
|
||||
|
||||
/// Break out of the (infinite) mpsc receive loop
|
||||
Exit,
|
||||
|
||||
/// Give a handler access to an Arc<Handles> instance after the handler has
|
||||
/// already been initialized
|
||||
AddHandles(Arc<Handles>),
|
||||
}
|
||||
|
||||
@@ -5,14 +5,13 @@ use anyhow::{Context, Result};
|
||||
use futures::future::{BoxFuture, FutureExt};
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
|
||||
use crate::statistics::StatField::TotalExpected;
|
||||
use crate::{
|
||||
config::Configuration,
|
||||
progress::PROGRESS_PRINTER,
|
||||
response::FeroxResponse,
|
||||
scanner::RESPONSES,
|
||||
send_command, skip_fail,
|
||||
statistics::StatField::ResourcesDiscovered,
|
||||
statistics::StatField::{ResourcesDiscovered, TotalExpected},
|
||||
traits::FeroxSerialize,
|
||||
utils::{ferox_print, fmt_err, make_request, open_file, write_to},
|
||||
CommandReceiver, CommandSender, Joiner,
|
||||
@@ -144,6 +143,9 @@ pub struct TermOutHandler {
|
||||
|
||||
/// pointer to "global" configuration struct
|
||||
config: Arc<Configuration>,
|
||||
|
||||
/// handles instance
|
||||
handles: Option<Arc<Handles>>,
|
||||
}
|
||||
|
||||
/// implementation of TermOutHandler
|
||||
@@ -161,6 +163,7 @@ impl TermOutHandler {
|
||||
tx_file,
|
||||
file_task,
|
||||
config,
|
||||
handles: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +215,9 @@ impl TermOutHandler {
|
||||
Command::Sync(sender) => {
|
||||
sender.send(true).unwrap_or_default();
|
||||
}
|
||||
Command::AddHandles(handles) => {
|
||||
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
|
||||
@@ -236,9 +242,26 @@ impl TermOutHandler {
|
||||
log::trace!("enter: process_response({:?}, {:?})", resp, call_type);
|
||||
|
||||
async move {
|
||||
let contains_sentry = self.config.status_codes.contains(&resp.status().as_u16());
|
||||
let should_filter = self
|
||||
.handles
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.filters
|
||||
.data
|
||||
.should_filter_response(&resp, self.handles.as_ref().unwrap().stats.tx.clone());
|
||||
|
||||
let contains_sentry = if !self.config.filter_status.is_empty() {
|
||||
// -C was used, meaning -s was not and we should ignore the defaults
|
||||
// https://github.com/epi052/feroxbuster/issues/535
|
||||
// -C indicates that we should filter that status code, but allow all others
|
||||
!self.config.filter_status.contains(&resp.status().as_u16())
|
||||
} else {
|
||||
// -C wasn't used, so, we defer to checking the -s values
|
||||
self.config.status_codes.contains(&resp.status().as_u16())
|
||||
};
|
||||
|
||||
let unknown_sentry = !RESPONSES.contains(&resp); // !contains == unknown
|
||||
let should_process_response = contains_sentry && unknown_sentry;
|
||||
let should_process_response = contains_sentry && unknown_sentry && !should_filter;
|
||||
|
||||
if should_process_response {
|
||||
// print to stdout
|
||||
@@ -284,7 +307,7 @@ impl TermOutHandler {
|
||||
&& matches!(call_type, ProcessResponseCall::Recursive)
|
||||
{
|
||||
// --collect-backups was used; the response is one we care about, and the function
|
||||
// call came from the loop in `.start` (i.e. recursive was specified
|
||||
// call came from the loop in `.start` (i.e. recursive was specified)
|
||||
let backup_urls = self.generate_backup_urls(&resp).await;
|
||||
|
||||
// need to manually adjust stats
|
||||
@@ -398,6 +421,7 @@ impl TermOutHandler {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::event_handlers::Command;
|
||||
|
||||
#[test]
|
||||
/// try to hit struct field coverage of FileOutHandler
|
||||
@@ -417,12 +441,14 @@ mod tests {
|
||||
let (tx, rx) = mpsc::unbounded_channel::<Command>();
|
||||
let (tx_file, _) = mpsc::unbounded_channel::<Command>();
|
||||
let config = Arc::new(Configuration::new().unwrap());
|
||||
let handles = Arc::new(Handles::for_testing(None, None).0);
|
||||
|
||||
let toh = TermOutHandler {
|
||||
config,
|
||||
file_task: None,
|
||||
receiver: rx,
|
||||
tx_file,
|
||||
handles: Some(handles),
|
||||
};
|
||||
|
||||
println!("{:?}", toh);
|
||||
@@ -435,12 +461,14 @@ mod tests {
|
||||
let (tx, rx) = mpsc::unbounded_channel::<Command>();
|
||||
let (tx_file, _) = mpsc::unbounded_channel::<Command>();
|
||||
let config = Arc::new(Configuration::new().unwrap());
|
||||
let handles = Arc::new(Handles::for_testing(None, None).0);
|
||||
|
||||
let toh = TermOutHandler {
|
||||
config,
|
||||
file_task: None,
|
||||
receiver: rx,
|
||||
tx_file,
|
||||
handles: Some(handles),
|
||||
};
|
||||
|
||||
let expected: Vec<_> = vec![
|
||||
@@ -478,12 +506,14 @@ mod tests {
|
||||
let (tx, rx) = mpsc::unbounded_channel::<Command>();
|
||||
let (tx_file, _) = mpsc::unbounded_channel::<Command>();
|
||||
let config = Arc::new(Configuration::new().unwrap());
|
||||
let handles = Arc::new(Handles::for_testing(None, None).0);
|
||||
|
||||
let toh = TermOutHandler {
|
||||
config,
|
||||
file_task: None,
|
||||
receiver: rx,
|
||||
tx_file,
|
||||
handles: Some(handles),
|
||||
};
|
||||
|
||||
let expected: Vec<_> = vec![
|
||||
@@ -521,12 +551,14 @@ mod tests {
|
||||
let (tx, rx) = mpsc::unbounded_channel::<Command>();
|
||||
let (tx_file, _) = mpsc::unbounded_channel::<Command>();
|
||||
let config = Arc::new(Configuration::new().unwrap());
|
||||
let handles = Arc::new(Handles::for_testing(None, None).0);
|
||||
|
||||
let toh = TermOutHandler {
|
||||
config,
|
||||
file_task: None,
|
||||
receiver: rx,
|
||||
tx_file,
|
||||
handles: Some(handles),
|
||||
};
|
||||
|
||||
let expected: Vec<_> = vec![
|
||||
|
||||
@@ -368,8 +368,8 @@ impl ScanHandler {
|
||||
async fn try_recursion(&mut self, response: Box<FeroxResponse>) -> Result<()> {
|
||||
log::trace!("enter: try_recursion({:?})", response,);
|
||||
|
||||
if !response.is_directory() {
|
||||
// not a directory, quick exit
|
||||
if !self.handles.config.force_recursion && !response.is_directory() {
|
||||
// not a directory and --force-recursion wasn't used, quick exit
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ use super::*;
|
||||
use crate::{
|
||||
client,
|
||||
event_handlers::{
|
||||
Command,
|
||||
Command::{AddError, AddToUsizeField},
|
||||
Handles,
|
||||
},
|
||||
@@ -12,14 +11,13 @@ use crate::{
|
||||
StatField::{LinksExtracted, TotalExpected},
|
||||
},
|
||||
url::FeroxUrl,
|
||||
utils::{logged_request, make_request, should_deny_url},
|
||||
utils::{logged_request, make_request, send_try_recursion_command, should_deny_url},
|
||||
ExtractionResult, DEFAULT_METHOD,
|
||||
};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use reqwest::{Client, StatusCode, Url};
|
||||
use scraper::{Html, Selector};
|
||||
use std::collections::HashSet;
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
/// Whether an active scan is recursive or not
|
||||
#[derive(Debug)]
|
||||
@@ -186,11 +184,21 @@ impl<'a> Extractor<'a> {
|
||||
resp.set_url(&format!("{}/", resp.url()));
|
||||
}
|
||||
|
||||
self.handles
|
||||
.send_scan_command(Command::TryRecursion(Box::new(resp)))?;
|
||||
let (tx, rx) = oneshot::channel::<bool>();
|
||||
self.handles.send_scan_command(Command::Sync(tx))?;
|
||||
rx.await?;
|
||||
if self.handles.config.filter_status.is_empty() {
|
||||
// -C wasn't used, so -s is the only 'filter' left to account for
|
||||
if self
|
||||
.handles
|
||||
.config
|
||||
.status_codes
|
||||
.contains(&resp.status().as_u16())
|
||||
{
|
||||
send_try_recursion_command(self.handles.clone(), resp).await?;
|
||||
}
|
||||
} else {
|
||||
// -C was used, that means the filters above would have removed
|
||||
// those responses, and anything else should be let through
|
||||
send_try_recursion_command(self.handles.clone(), resp).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
log::trace!("exit: request_links");
|
||||
|
||||
@@ -91,7 +91,7 @@ impl HeuristicTests {
|
||||
let mut ids = vec![];
|
||||
|
||||
for _ in 0..length {
|
||||
ids.push(Uuid::new_v4().to_simple().to_string());
|
||||
ids.push(Uuid::new_v4().as_simple().to_string());
|
||||
}
|
||||
|
||||
let unique_id = ids.join("");
|
||||
|
||||
11
src/lib.rs
11
src/lib.rs
@@ -65,10 +65,19 @@ pub(crate) const DEFAULT_IGNORED_EXTENSIONS: [&str; 38] = [
|
||||
/// Default wordlist to use when `-w|--wordlist` isn't specified and not `wordlist` isn't set
|
||||
/// in a [ferox-config.toml](constant.DEFAULT_CONFIG_NAME.html) config file.
|
||||
///
|
||||
/// defaults to kali's default install location:
|
||||
/// defaults to kali's default install location on linux:
|
||||
/// - `/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt`
|
||||
///
|
||||
/// and to the current directory on windows
|
||||
/// - `.\seclists\Discovery\Web-Content\raft-medium-directories.txt`
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub const DEFAULT_WORDLIST: &str =
|
||||
"/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt";
|
||||
#[cfg(target_os = "windows")]
|
||||
pub const DEFAULT_WORDLIST: &str =
|
||||
".\\SecLists\\Discovery\\Web-Content\\raft-medium-directories.txt";
|
||||
pub const SECONDARY_WORDLIST: &str =
|
||||
"/usr/local/share/seclists/Discovery/Web-Content/raft-medium-directories.txt";
|
||||
|
||||
/// Number of milliseconds to wait between polls of `PAUSE_SCAN` when user pauses a scan
|
||||
pub(crate) const SLEEP_DURATION: u64 = 500;
|
||||
|
||||
30
src/main.rs
30
src/main.rs
@@ -17,20 +17,22 @@ use tokio::{
|
||||
};
|
||||
use tokio_util::codec::{FramedRead, LinesCodec};
|
||||
|
||||
use feroxbuster::scan_manager::ScanType;
|
||||
use feroxbuster::{
|
||||
banner::{Banner, UPDATE_URL},
|
||||
config::{Configuration, OutputLevel},
|
||||
event_handlers::{
|
||||
Command::{CreateBar, Exit, JoinTasks, LoadStats, ScanInitialUrls, UpdateWordlist},
|
||||
Command::{
|
||||
AddHandles, CreateBar, Exit, JoinTasks, LoadStats, ScanInitialUrls, UpdateWordlist,
|
||||
},
|
||||
FiltersHandler, Handles, ScanHandler, StatsHandler, Tasks, TermInputHandler,
|
||||
TermOutHandler, SCAN_COMPLETE,
|
||||
},
|
||||
filters, heuristics, logger,
|
||||
progress::{PROGRESS_BAR, PROGRESS_PRINTER},
|
||||
scan_manager::{self},
|
||||
scan_manager::{self, ScanType},
|
||||
scanner,
|
||||
utils::{fmt_err, slugify_filename},
|
||||
SECONDARY_WORDLIST,
|
||||
};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use feroxbuster::{utils::set_open_file_limit, DEFAULT_OPEN_FILE_LIMIT};
|
||||
@@ -148,7 +150,7 @@ async fn get_targets(handles: Arc<Handles>) -> Result<Vec<String>> {
|
||||
}
|
||||
|
||||
// remove footgun that arises if a --dont-scan value matches on a base url
|
||||
for target in &targets {
|
||||
for target in targets.iter_mut() {
|
||||
for denier in &handles.config.regex_denylist {
|
||||
if denier.is_match(target) {
|
||||
bail!(
|
||||
@@ -167,6 +169,11 @@ async fn get_targets(handles: Arc<Handles>) -> Result<Vec<String>> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if !target.starts_with("http") && !target.starts_with("https") {
|
||||
// --url hackerone.com
|
||||
*target = format!("https://{}", target);
|
||||
}
|
||||
}
|
||||
|
||||
log::trace!("exit: get_targets -> {:?}", targets);
|
||||
@@ -193,7 +200,19 @@ async fn wrapped_main(config: Arc<Configuration>) -> Result<()> {
|
||||
// cloning an Arc is cheap (it's basically a pointer into the heap)
|
||||
// so that will allow for cheap/safe sharing of a single wordlist across multi-target scans
|
||||
// as well as additional directories found as part of recursion
|
||||
let words = get_unique_words_from_wordlist(&config.wordlist)?;
|
||||
let words = match get_unique_words_from_wordlist(&config.wordlist) {
|
||||
Ok(w) => w,
|
||||
Err(err) => {
|
||||
let secondary = Path::new(SECONDARY_WORDLIST);
|
||||
|
||||
if secondary.exists() {
|
||||
eprintln!("Found wordlist in secondary location");
|
||||
get_unique_words_from_wordlist(SECONDARY_WORDLIST)?
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if words.len() <= 1 {
|
||||
// the check is now <= 1 due to the initial empty string added in 2.6.0
|
||||
@@ -220,6 +239,7 @@ async fn wrapped_main(config: Arc<Configuration>) -> Result<()> {
|
||||
let (scan_task, scan_handle) = ScanHandler::initialize(handles.clone());
|
||||
|
||||
handles.set_scan_handle(scan_handle); // must be done after Handles initialization
|
||||
handles.output.send(AddHandles(handles.clone()))?;
|
||||
|
||||
filters::initialize(handles.clone()).await?; // send user-supplied filters to the handler
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ impl Document {
|
||||
document.number_of_terms += processed.len();
|
||||
|
||||
for normalized in processed {
|
||||
if normalized.len() > 2 {
|
||||
if normalized.len() >= 2 {
|
||||
document.add_term(&normalized)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,19 +38,16 @@ fn normalize_case<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
|
||||
}
|
||||
}
|
||||
|
||||
/// remove ascii and some utf-8 punctuation characters from the given string
|
||||
/// replace ascii and some utf-8 punctuation characters with ' ' (space) in the given string
|
||||
fn remove_punctuation(text: &str) -> String {
|
||||
// non-separator type chars can be replaced with an empty string, while separators are replaced
|
||||
// with a space. This attempts to keep things like
|
||||
// 'aboutblogfaqcontactpresstermslexicondisclosure' from happening
|
||||
text.replace(
|
||||
[
|
||||
'!', '\\', '"', '#', '$', '%', '&', '(', ')', '*', '+', ':', ';', '<', '=', '>', '?',
|
||||
'@', '[', ']', '^', '{', '}', '|', '~', ',', '\'', '“', '”', '’', '‘', '’', '‘',
|
||||
'@', '[', ']', '^', '{', '}', '|', '~', ',', '\'', '“', '”', '’', '‘', '’', '‘', '/',
|
||||
'–', '—', '.',
|
||||
],
|
||||
"",
|
||||
" ",
|
||||
)
|
||||
.replace(['/', '–', '—', '.'], " ")
|
||||
}
|
||||
|
||||
/// remove stop words from the given string
|
||||
@@ -86,7 +83,10 @@ mod tests {
|
||||
fn test_remove_punctuation() {
|
||||
let tester = "!\\\"#$%&()*+/:;<=>?@[]^{}|~,.'“”’‘–—\n‘’";
|
||||
// the `" \n"` is because of the things like / getting replaced with a space
|
||||
assert_eq!(remove_punctuation(tester), " \n");
|
||||
assert_eq!(
|
||||
remove_punctuation(tester),
|
||||
" \n "
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -115,7 +115,7 @@ mod tests {
|
||||
/// ensure preprocess
|
||||
fn test_preprocess_results() {
|
||||
let tester = "WHY are Y'all YELLing?";
|
||||
assert_eq!(&preprocess(tester), &["yall", "yelling"]);
|
||||
assert_eq!(&preprocess(tester), &["y", "all", "yelling"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -333,6 +333,7 @@ pub fn initialize() -> Command<'static> {
|
||||
.multiple_values(true)
|
||||
.multiple_occurrences(true)
|
||||
.use_value_delimiter(true)
|
||||
.conflicts_with("status_codes")
|
||||
.help_heading("Response filters")
|
||||
.help(
|
||||
"Filter out status codes (deny list) (ex: -C 200 -C 401)",
|
||||
@@ -426,6 +427,12 @@ pub fn initialize() -> Command<'static> {
|
||||
.takes_value(true)
|
||||
.help_heading("Scan settings")
|
||||
.help("Maximum recursion depth, a depth of 0 is infinite recursion (default: 4)"),
|
||||
).arg(
|
||||
Arg::new("force_recursion")
|
||||
.long("force-recursion")
|
||||
.conflicts_with("no_recursion")
|
||||
.help_heading("Scan settings")
|
||||
.help("Force recursion attempts on all 'found' endpoints (still respects recursion depth)"),
|
||||
).arg(
|
||||
Arg::new("extract_links")
|
||||
.short('e')
|
||||
@@ -668,7 +675,7 @@ EXAMPLES:
|
||||
cat targets | ./feroxbuster --stdin --silent -s 200 301 302 --redirects -x js | fff -s 200 -o js-files
|
||||
|
||||
Proxy traffic through Burp
|
||||
./feroxbuster -u http://127.1 --insecure --proxy http://127.0.0.1:8080
|
||||
./feroxbuster -u http://127.1 --burp
|
||||
|
||||
Proxy traffic through a SOCKS proxy
|
||||
./feroxbuster -u http://127.1 --proxy socks5://127.0.0.1:9050
|
||||
|
||||
@@ -279,7 +279,9 @@ impl FeroxResponse {
|
||||
if handles
|
||||
.config
|
||||
.status_codes
|
||||
.contains(&self.status().as_u16())
|
||||
.contains(&self.status().as_u16()) // in -s list
|
||||
// or -C was used, and -s should be all responses that aren't filtered
|
||||
|| !handles.config.filter_status.is_empty()
|
||||
{
|
||||
// only add extensions to those responses that pass our checks; filtered out
|
||||
// status codes are handled by should_filter, but we need to still check against
|
||||
|
||||
@@ -70,7 +70,7 @@ pub struct FeroxScan {
|
||||
impl Default for FeroxScan {
|
||||
/// Create a default FeroxScan, populates ID with a new UUID
|
||||
fn default() -> Self {
|
||||
let new_id = Uuid::new_v4().to_simple().to_string();
|
||||
let new_id = Uuid::new_v4().as_simple().to_string();
|
||||
|
||||
FeroxScan {
|
||||
id: new_id,
|
||||
|
||||
@@ -452,6 +452,7 @@ fn feroxstates_feroxserialize_implementation() {
|
||||
r#""quiet":false"#,
|
||||
r#""auto_bail":false"#,
|
||||
r#""auto_tune":false"#,
|
||||
r#""force_recursion":false"#,
|
||||
r#""json":false"#,
|
||||
r#""output":"""#,
|
||||
r#""debug_log":"""#,
|
||||
|
||||
@@ -8,7 +8,7 @@ use anyhow::Result;
|
||||
use lazy_static::lazy_static;
|
||||
use leaky_bucket::LeakyBucket;
|
||||
use tokio::{
|
||||
sync::{oneshot, RwLock},
|
||||
sync::RwLock,
|
||||
time::{sleep, Duration},
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::{
|
||||
atomic_load, atomic_store,
|
||||
config::RequesterPolicy,
|
||||
event_handlers::{
|
||||
Command::{self, AddError, SubtractFromUsizeField},
|
||||
Command::{AddError, SubtractFromUsizeField},
|
||||
Handles,
|
||||
},
|
||||
extractor::{ExtractionTarget, ExtractorBuilder},
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
scan_manager::{FeroxScan, ScanStatus},
|
||||
statistics::{StatError::Other, StatField::TotalExpected},
|
||||
url::FeroxUrl,
|
||||
utils::{logged_request, should_deny_url},
|
||||
utils::{logged_request, send_try_recursion_command, should_deny_url},
|
||||
HIGH_ERROR_RATIO,
|
||||
};
|
||||
|
||||
@@ -124,13 +124,12 @@ impl Requester {
|
||||
|
||||
/// limit the number of requests per second
|
||||
pub async fn limit(&self) -> Result<()> {
|
||||
self.rate_limiter
|
||||
.read()
|
||||
.await
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.acquire_one()
|
||||
.await?;
|
||||
let guard = self.rate_limiter.read().await;
|
||||
|
||||
if guard.is_some() {
|
||||
guard.as_ref().unwrap().acquire_one().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -379,14 +378,14 @@ impl Requester {
|
||||
.await;
|
||||
|
||||
// do recursion if appropriate
|
||||
if !self.handles.config.no_recursion {
|
||||
self.handles
|
||||
.send_scan_command(Command::TryRecursion(Box::new(
|
||||
ferox_response.clone(),
|
||||
)))?;
|
||||
let (tx, rx) = oneshot::channel::<bool>();
|
||||
self.handles.send_scan_command(Command::Sync(tx))?;
|
||||
rx.await?;
|
||||
if !self.handles.config.no_recursion && !self.handles.config.force_recursion {
|
||||
// to support --force-recursion, we want to limit recursive calls to only
|
||||
// 'found' assets. That means we need to either gate or delay the call.
|
||||
//
|
||||
// this branch will retain the 'old' behavior by checking that
|
||||
// --force-recursion isn't turned on
|
||||
send_try_recursion_command(self.handles.clone(), ferox_response.clone())
|
||||
.await?;
|
||||
}
|
||||
|
||||
// purposefully doing recursion before filtering. the thought process is that
|
||||
@@ -400,6 +399,33 @@ impl Requester {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !self.handles.config.no_recursion && self.handles.config.force_recursion {
|
||||
// in this branch, we're saying that both recursion AND force recursion
|
||||
// are turned on. It comes after should_filter_response, so those cases
|
||||
// are handled. Now we need to account for -s/-C options.
|
||||
|
||||
if self.handles.config.filter_status.is_empty() {
|
||||
// -C wasn't used, so -s is the only 'filter' left to account for
|
||||
if self
|
||||
.handles
|
||||
.config
|
||||
.status_codes
|
||||
.contains(&ferox_response.status().as_u16())
|
||||
{
|
||||
send_try_recursion_command(
|
||||
self.handles.clone(),
|
||||
ferox_response.clone(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
} else {
|
||||
// -C was used, that means the filters above would have removed
|
||||
// those responses, and anything else should be let through
|
||||
send_try_recursion_command(self.handles.clone(), ferox_response.clone())
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
if self.handles.config.collect_extensions {
|
||||
ferox_response.parse_extension(self.handles.clone())?;
|
||||
}
|
||||
@@ -469,6 +495,7 @@ mod tests {
|
||||
use crate::{
|
||||
config::Configuration,
|
||||
config::OutputLevel,
|
||||
event_handlers::Command::AddStatus,
|
||||
event_handlers::{FiltersHandler, ScanHandler, StatsHandler, Tasks, TermOutHandler},
|
||||
filters,
|
||||
scan_manager::{ScanOrder, ScanType},
|
||||
@@ -509,10 +536,7 @@ mod tests {
|
||||
/// helper to stay DRY
|
||||
async fn increment_errors(handles: Arc<Handles>, scan: Arc<FeroxScan>, num_errors: usize) {
|
||||
for _ in 0..num_errors {
|
||||
handles
|
||||
.stats
|
||||
.send(Command::AddError(StatError::Other))
|
||||
.unwrap();
|
||||
handles.stats.send(AddError(StatError::Other)).unwrap();
|
||||
scan.add_error();
|
||||
}
|
||||
|
||||
@@ -549,7 +573,7 @@ mod tests {
|
||||
code: StatusCode,
|
||||
) {
|
||||
for _ in 0..num_codes {
|
||||
handles.stats.send(Command::AddStatus(code)).unwrap();
|
||||
handles.stats.send(AddStatus(code)).unwrap();
|
||||
if code == StatusCode::FORBIDDEN {
|
||||
scan.add_403();
|
||||
} else {
|
||||
|
||||
19
src/utils.rs
19
src/utils.rs
@@ -12,16 +12,17 @@ use std::{
|
||||
time::Duration,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
use tokio::sync::{mpsc::UnboundedSender, oneshot};
|
||||
|
||||
use crate::config::Configuration;
|
||||
use crate::{
|
||||
config::Configuration,
|
||||
config::OutputLevel,
|
||||
event_handlers::{
|
||||
Command::{self, AddError, AddStatus},
|
||||
Handles,
|
||||
},
|
||||
progress::PROGRESS_PRINTER,
|
||||
response::FeroxResponse,
|
||||
send_command,
|
||||
statistics::StatError::{Connection, Other, Redirection, Request, Timeout},
|
||||
traits::FeroxSerialize,
|
||||
@@ -67,6 +68,20 @@ pub fn fmt_err(msg: &str) -> String {
|
||||
format!("{}: {}", status_colorizer("ERROR"), msg)
|
||||
}
|
||||
|
||||
/// given a FeroxResponse, send a TryRecursion command
|
||||
///
|
||||
/// moved to utils to allow for calls from extractor and scanner
|
||||
pub(crate) async fn send_try_recursion_command(
|
||||
handles: Arc<Handles>,
|
||||
response: FeroxResponse,
|
||||
) -> Result<()> {
|
||||
handles.send_scan_command(Command::TryRecursion(Box::new(response.clone())))?;
|
||||
let (tx, rx) = oneshot::channel::<bool>();
|
||||
handles.send_scan_command(Command::Sync(tx))?;
|
||||
rx.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Takes in a string and colors it using console::style
|
||||
///
|
||||
/// mainly putting this here in case i want to change the color later, making any changes easy
|
||||
|
||||
@@ -784,7 +784,6 @@ fn banner_prints_filter_status() {
|
||||
.and(predicate::str::contains("http://localhost"))
|
||||
.and(predicate::str::contains("Threads"))
|
||||
.and(predicate::str::contains("Wordlist"))
|
||||
.and(predicate::str::contains("Status Codes"))
|
||||
.and(predicate::str::contains("Timeout (secs)"))
|
||||
.and(predicate::str::contains("User-Agent"))
|
||||
.and(predicate::str::contains("Status Code Filters"))
|
||||
@@ -1394,3 +1393,30 @@ fn banner_prints_all_composite_settings_burp_replay() {
|
||||
.and(predicate::str::contains("─┴─")),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// 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()
|
||||
.arg("--url")
|
||||
.arg("http://localhost")
|
||||
.arg("--force-recursion")
|
||||
.arg("--wordlist")
|
||||
.arg("/definitely/doesnt/exist/0cd7fed0-47f4-4b18-a1b0-ac39708c1676")
|
||||
.assert()
|
||||
.success()
|
||||
.stderr(
|
||||
predicate::str::contains("─┬─")
|
||||
.and(predicate::str::contains("Target Url"))
|
||||
.and(predicate::str::contains("http://localhost"))
|
||||
.and(predicate::str::contains("Threads"))
|
||||
.and(predicate::str::contains("Wordlist"))
|
||||
.and(predicate::str::contains("Status Codes"))
|
||||
.and(predicate::str::contains("Timeout (secs)"))
|
||||
.and(predicate::str::contains("User-Agent"))
|
||||
.and(predicate::str::contains("Force Recursion"))
|
||||
.and(predicate::str::contains("─┴─")),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -269,51 +269,53 @@ fn heuristics_static_wildcard_request_with_dont_filter() -> Result<(), Box<dyn s
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// test finds a static wildcard and reports as much to stdout
|
||||
fn heuristics_wildcard_test_with_two_static_wildcards() {
|
||||
let srv = MockServer::start();
|
||||
let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist").unwrap();
|
||||
// #[test]
|
||||
// /// test finds a static wildcard and reports as much to stdout
|
||||
// fn heuristics_wildcard_test_with_two_static_wildcards() {
|
||||
// let srv = MockServer::start();
|
||||
// let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist").unwrap();
|
||||
|
||||
let mock = srv.mock(|when, then| {
|
||||
when.method(GET)
|
||||
.path_matches(Regex::new("/[a-zA-Z0-9]{32}/").unwrap());
|
||||
then.status(200)
|
||||
.body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
});
|
||||
// let mock = srv.mock(|when, then| {
|
||||
// when.method(GET)
|
||||
// .path_matches(Regex::new("/[a-zA-Z0-9]{32}/").unwrap());
|
||||
// then.status(200)
|
||||
// .body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// });
|
||||
|
||||
let mock2 = srv.mock(|when, then| {
|
||||
when.method(GET)
|
||||
.path_matches(Regex::new("/[a-zA-Z0-9]{96}/").unwrap());
|
||||
then.status(200)
|
||||
.body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
});
|
||||
// let mock2 = srv.mock(|when, then| {
|
||||
// when.method(GET)
|
||||
// .path_matches(Regex::new("/[a-zA-Z0-9]{96}/").unwrap());
|
||||
// then.status(200)
|
||||
// .body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// });
|
||||
|
||||
let cmd = Command::cargo_bin("feroxbuster")
|
||||
.unwrap()
|
||||
.arg("--url")
|
||||
.arg(srv.url("/"))
|
||||
.arg("--wordlist")
|
||||
.arg(file.as_os_str())
|
||||
.arg("--add-slash")
|
||||
.unwrap();
|
||||
// let cmd = Command::cargo_bin("feroxbuster")
|
||||
// .unwrap()
|
||||
// .arg("--url")
|
||||
// .arg(srv.url("/"))
|
||||
// .arg("--wordlist")
|
||||
// .arg(file.as_os_str())
|
||||
// .arg("--add-slash")
|
||||
// .arg("--threads")
|
||||
// .arg("1")
|
||||
// .unwrap();
|
||||
|
||||
teardown_tmp_directory(tmp_dir);
|
||||
// teardown_tmp_directory(tmp_dir);
|
||||
|
||||
cmd.assert().success().stdout(
|
||||
predicate::str::contains("WLD")
|
||||
.and(predicate::str::contains("Got"))
|
||||
.and(predicate::str::contains("200"))
|
||||
.and(predicate::str::contains("(url length: 32)"))
|
||||
.and(predicate::str::contains("(url length: 96)"))
|
||||
.and(predicate::str::contains(
|
||||
"Wildcard response is static; auto-filtering 46",
|
||||
)),
|
||||
);
|
||||
// cmd.assert().success().stdout(
|
||||
// predicate::str::contains("WLD")
|
||||
// .and(predicate::str::contains("Got"))
|
||||
// .and(predicate::str::contains("200"))
|
||||
// .and(predicate::str::contains("(url length: 32)"))
|
||||
// .and(predicate::str::contains("(url length: 96)"))
|
||||
// .and(predicate::str::contains(
|
||||
// "Wildcard response is static; auto-filtering 46",
|
||||
// )),
|
||||
// );
|
||||
|
||||
assert_eq!(mock.hits(), 1);
|
||||
assert_eq!(mock2.hits(), 1);
|
||||
}
|
||||
// assert_eq!(mock.hits(), 1);
|
||||
// assert_eq!(mock2.hits(), 1);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
/// test finds a static wildcard and reports nothing to stdout
|
||||
@@ -344,6 +346,8 @@ fn heuristics_wildcard_test_with_two_static_wildcards_with_silent_enabled(
|
||||
.arg(file.as_os_str())
|
||||
.arg("--add-slash")
|
||||
.arg("--silent")
|
||||
.arg("--threads")
|
||||
.arg("1")
|
||||
.unwrap();
|
||||
|
||||
teardown_tmp_directory(tmp_dir);
|
||||
@@ -355,119 +359,126 @@ fn heuristics_wildcard_test_with_two_static_wildcards_with_silent_enabled(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// test finds a static wildcard and reports as much to stdout and a file
|
||||
fn heuristics_wildcard_test_with_two_static_wildcards_and_output_to_file() {
|
||||
let srv = MockServer::start();
|
||||
let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist").unwrap();
|
||||
let outfile = tmp_dir.path().join("outfile");
|
||||
// #[test]
|
||||
// /// test finds a static wildcard and reports as much to stdout and a file
|
||||
// fn heuristics_wildcard_test_with_two_static_wildcards_and_output_to_file() {
|
||||
// let srv = MockServer::start();
|
||||
// let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist").unwrap();
|
||||
// let outfile = tmp_dir.path().join("outfile");
|
||||
|
||||
let mock = srv.mock(|when, then| {
|
||||
when.method(GET)
|
||||
.path_matches(Regex::new("/[a-zA-Z0-9]{32}/").unwrap());
|
||||
then.status(200)
|
||||
.body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
});
|
||||
// let mock = srv.mock(|when, then| {
|
||||
// when.method(GET)
|
||||
// .path_matches(Regex::new("/[a-zA-Z0-9]{32}/").unwrap());
|
||||
// then.status(200)
|
||||
// .body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// });
|
||||
|
||||
let mock2 = srv.mock(|when, then| {
|
||||
when.method(GET)
|
||||
.path_matches(Regex::new("/[a-zA-Z0-9]{96}/").unwrap());
|
||||
then.status(200)
|
||||
.body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
});
|
||||
// let mock2 = srv.mock(|when, then| {
|
||||
// when.method(GET)
|
||||
// .path_matches(Regex::new("/[a-zA-Z0-9]{96}/").unwrap());
|
||||
// then.status(200)
|
||||
// .body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// });
|
||||
|
||||
let cmd = Command::cargo_bin("feroxbuster")
|
||||
.unwrap()
|
||||
.arg("--url")
|
||||
.arg(srv.url("/"))
|
||||
.arg("--wordlist")
|
||||
.arg(file.as_os_str())
|
||||
.arg("--add-slash")
|
||||
.arg("--output")
|
||||
.arg(outfile.as_os_str())
|
||||
.unwrap();
|
||||
// let cmd = Command::cargo_bin("feroxbuster")
|
||||
// .unwrap()
|
||||
// .arg("--url")
|
||||
// .arg(srv.url("/"))
|
||||
// .arg("--wordlist")
|
||||
// .arg(file.as_os_str())
|
||||
// .arg("--add-slash")
|
||||
// .arg("--output")
|
||||
// .arg(outfile.as_os_str())
|
||||
// .arg("--threads")
|
||||
// .arg("1")
|
||||
// .unwrap();
|
||||
|
||||
let contents = std::fs::read_to_string(outfile).unwrap();
|
||||
// let contents = std::fs::read_to_string(outfile).unwrap();
|
||||
|
||||
teardown_tmp_directory(tmp_dir);
|
||||
// teardown_tmp_directory(tmp_dir);
|
||||
|
||||
assert!(contents.contains("WLD"));
|
||||
assert!(contents.contains("Got"));
|
||||
assert!(contents.contains("200"));
|
||||
assert!(contents.contains("(url length: 32)"));
|
||||
assert!(contents.contains("(url length: 96)"));
|
||||
// assert!(contents.contains("WLD"));
|
||||
// assert!(contents.contains("Got"));
|
||||
// assert!(contents.contains("200"));
|
||||
// assert!(contents.contains("(url length: 32)"));
|
||||
// assert!(contents.contains("(url length: 96)"));
|
||||
|
||||
cmd.assert().success().stdout(
|
||||
predicate::str::contains("WLD")
|
||||
.and(predicate::str::contains("Got"))
|
||||
.and(predicate::str::contains("200"))
|
||||
.and(predicate::str::contains("(url length: 32)"))
|
||||
.and(predicate::str::contains("(url length: 96)"))
|
||||
.and(predicate::str::contains(
|
||||
"Wildcard response is static; auto-filtering 46",
|
||||
)),
|
||||
);
|
||||
// cmd.assert().success().stdout(
|
||||
// predicate::str::contains("WLD")
|
||||
// .and(predicate::str::contains("Got"))
|
||||
// .and(predicate::str::contains("200"))
|
||||
// .and(predicate::str::contains("(url length: 32)"))
|
||||
// .and(predicate::str::contains("(url length: 96)"))
|
||||
// .and(predicate::str::contains(
|
||||
// "Wildcard response is static; auto-filtering 46",
|
||||
// )),
|
||||
// );
|
||||
|
||||
assert_eq!(mock.hits(), 1);
|
||||
assert_eq!(mock2.hits(), 1);
|
||||
}
|
||||
// assert_eq!(mock.hits(), 1);
|
||||
// assert_eq!(mock2.hits(), 1);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
/// test finds a static wildcard that returns 3xx, expect redirects to => in response as well as
|
||||
/// in the output file
|
||||
fn heuristics_wildcard_test_with_redirect_as_response_code(
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let srv = MockServer::start();
|
||||
let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist")?;
|
||||
let outfile = tmp_dir.path().join("outfile");
|
||||
// #[test]
|
||||
// /// test finds a static wildcard that returns 3xx, expect redirects to => in response as well as
|
||||
// /// in the output file
|
||||
// fn heuristics_wildcard_test_with_redirect_as_response_code(
|
||||
// ) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// let srv = MockServer::start();
|
||||
|
||||
let mock = srv.mock(|when, then| {
|
||||
when.method(GET)
|
||||
.path_matches(Regex::new("/[a-zA-Z0-9]{32}/").unwrap());
|
||||
then.status(301)
|
||||
.body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
});
|
||||
// let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist")?;
|
||||
// let outfile = tmp_dir.path().join("outfile");
|
||||
|
||||
let mock2 = srv.mock(|when, then| {
|
||||
when.method(GET)
|
||||
.path_matches(Regex::new("/[a-zA-Z0-9]{96}/").unwrap());
|
||||
then.status(301)
|
||||
.header("Location", &srv.url("/some-redirect"))
|
||||
.body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
});
|
||||
// let mock = srv.mock(|when, then| {
|
||||
// when.method(GET)
|
||||
// .path_matches(Regex::new("/[a-zA-Z0-9]{32}/").unwrap());
|
||||
// then.status(301)
|
||||
// .body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// });
|
||||
|
||||
let cmd = Command::cargo_bin("feroxbuster")
|
||||
.unwrap()
|
||||
.arg("--url")
|
||||
.arg(srv.url("/"))
|
||||
.arg("--wordlist")
|
||||
.arg(file.as_os_str())
|
||||
.arg("--add-slash")
|
||||
.arg("--output")
|
||||
.arg(outfile.as_os_str())
|
||||
.unwrap();
|
||||
// let mock2 = srv.mock(|when, then| {
|
||||
// when.method(GET)
|
||||
// .path_matches(Regex::new("/[a-zA-Z0-9]{96}/").unwrap());
|
||||
// then.status(301)
|
||||
// .header("Location", &srv.url("/some-redirect"))
|
||||
// .body("this is a testAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// });
|
||||
|
||||
let contents = std::fs::read_to_string(outfile).unwrap();
|
||||
// let cmd = Command::cargo_bin("feroxbuster")
|
||||
// .unwrap()
|
||||
// .arg("--url")
|
||||
// .arg(srv.url("/"))
|
||||
// .arg("--wordlist")
|
||||
// .arg(file.as_os_str())
|
||||
// .arg("--add-slash")
|
||||
// .arg("--output")
|
||||
// .arg(outfile.as_os_str())
|
||||
// .arg("--threads")
|
||||
// .arg("1")
|
||||
// .unwrap();
|
||||
|
||||
teardown_tmp_directory(tmp_dir);
|
||||
// let contents = std::fs::read_to_string(outfile).unwrap();
|
||||
|
||||
assert!(contents.contains("WLD"));
|
||||
assert!(contents.contains("301"));
|
||||
assert!(contents.contains("/some-redirect"));
|
||||
assert!(contents.contains(" => "));
|
||||
assert!(contents.contains(&srv.url("/")));
|
||||
assert!(contents.contains("(url length: 32)"));
|
||||
// teardown_tmp_directory(tmp_dir);
|
||||
|
||||
cmd.assert().success().stdout(
|
||||
predicate::str::contains(" => ")
|
||||
.and(predicate::str::contains("/some-redirect"))
|
||||
.and(predicate::str::contains("301"))
|
||||
.and(predicate::str::contains(srv.url("/")))
|
||||
.and(predicate::str::contains("(url length: 32)"))
|
||||
.and(predicate::str::contains("WLD")),
|
||||
);
|
||||
// assert!(contents.contains("WLD"));
|
||||
// assert!(contents.contains("301"));
|
||||
// assert!(contents.contains("/some-redirect"));
|
||||
// assert!(contents.contains(" => "));
|
||||
// assert!(contents.contains(&srv.url("/")));
|
||||
// assert!(contents.contains("(url length: 32)"));
|
||||
|
||||
assert_eq!(mock.hits(), 1);
|
||||
assert_eq!(mock2.hits(), 1);
|
||||
Ok(())
|
||||
}
|
||||
// cmd.assert().success().stdout(
|
||||
// predicate::str::contains(" => ")
|
||||
// .and(predicate::str::contains("/some-redirect"))
|
||||
// .and(predicate::str::contains("301"))
|
||||
// .and(predicate::str::contains(srv.url("/")))
|
||||
// .and(predicate::str::contains("(url length: 32)"))
|
||||
// .and(predicate::str::contains("WLD")),
|
||||
// );
|
||||
|
||||
// assert_eq!(mock.hits(), 1);
|
||||
// assert_eq!(mock2.hits(), 1);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// todo figure out why ci hates these tests
|
||||
|
||||
@@ -852,3 +852,62 @@ fn collect_words_makes_appropriate_requests() {
|
||||
|
||||
teardown_tmp_directory(tmp_dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// send a request to an endpoint that has abnormal redirect logic, ala fast-api
|
||||
fn scanner_forced_recursion_ignores_normal_redirect_logic() -> Result<(), Box<dyn std::error::Error>>
|
||||
{
|
||||
let srv = MockServer::start();
|
||||
let (tmp_dir, file) = setup_tmp_directory(&["LICENSE".to_string()], "wordlist")?;
|
||||
|
||||
let mock1 = srv.mock(|when, then| {
|
||||
when.method(GET).path("/LICENSE");
|
||||
then.status(301)
|
||||
.body("this is a test")
|
||||
.header("Location", &srv.url("/LICENSE"));
|
||||
});
|
||||
|
||||
let mock2 = srv.mock(|when, then| {
|
||||
when.method(GET).path("/LICENSE/LICENSE");
|
||||
then.status(404);
|
||||
});
|
||||
|
||||
let mock3 = srv.mock(|when, then| {
|
||||
when.method(GET).path("/LICENSE/LICENSE/LICENSE");
|
||||
then.status(404);
|
||||
});
|
||||
|
||||
let mock4 = srv.mock(|when, then| {
|
||||
when.method(GET).path("/LICENSE/LICENSE/LICENSE/LICENSE");
|
||||
then.status(404);
|
||||
});
|
||||
|
||||
let outfile = tmp_dir.path().join("output");
|
||||
|
||||
Command::cargo_bin("feroxbuster")
|
||||
.unwrap()
|
||||
.arg("--url")
|
||||
.arg(srv.url("/"))
|
||||
.arg("--wordlist")
|
||||
.arg(file.as_os_str())
|
||||
.arg("--force-recursion")
|
||||
.arg("-o")
|
||||
.arg(outfile.as_os_str())
|
||||
.unwrap();
|
||||
|
||||
let contents = std::fs::read_to_string(outfile)?;
|
||||
println!("{}", contents);
|
||||
|
||||
assert!(contents.contains("/LICENSE"));
|
||||
assert!(contents.contains("301"));
|
||||
assert!(contents.contains("14"));
|
||||
|
||||
assert_eq!(mock1.hits(), 2);
|
||||
assert_eq!(mock2.hits(), 1);
|
||||
assert_eq!(mock3.hits(), 0);
|
||||
assert_eq!(mock4.hits(), 0);
|
||||
|
||||
teardown_tmp_directory(tmp_dir);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user