mirror of
https://github.com/epi052/feroxbuster.git
synced 2026-05-28 09:31:13 -03:00
Compare commits
21 Commits
self-updat
...
v2.9.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04a43a0892 | ||
|
|
8a72e498e6 | ||
|
|
2987a84776 | ||
|
|
8add5599fb | ||
|
|
9f557329eb | ||
|
|
c04bf4a703 | ||
|
|
03e8625c6e | ||
|
|
5d6b85fe12 | ||
|
|
771041d225 | ||
|
|
b5debed322 | ||
|
|
30407cd338 | ||
|
|
ba4b26f2cd | ||
|
|
4fdf558936 | ||
|
|
2ffb0df516 | ||
|
|
10260f9db7 | ||
|
|
4067be2f82 | ||
|
|
7cb9c1c914 | ||
|
|
99cbd657a5 | ||
|
|
6431f01f12 | ||
|
|
fd0f31705d | ||
|
|
5252587e65 |
@@ -550,7 +550,8 @@
|
|||||||
"profile": "https://petruknisme.com",
|
"profile": "https://petruknisme.com",
|
||||||
"contributions": [
|
"contributions": [
|
||||||
"code",
|
"code",
|
||||||
"infra"
|
"infra",
|
||||||
|
"ideas"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -30,3 +30,6 @@ ferox-*.state
|
|||||||
|
|
||||||
# python stuff cuz reasons
|
# python stuff cuz reasons
|
||||||
Pipfile*
|
Pipfile*
|
||||||
|
|
||||||
|
# ignore choco_package generated nupkg
|
||||||
|
/choco_package/*.nupkg
|
||||||
|
|||||||
115
Cargo.lock
generated
115
Cargo.lock
generated
@@ -775,7 +775,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "feroxbuster"
|
name = "feroxbuster"
|
||||||
version = "2.10.0"
|
version = "2.9.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
@@ -896,9 +896,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
|
checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -911,9 +911,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
|
checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
@@ -921,15 +921,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
|
checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
|
checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@@ -938,9 +938,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
|
checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
@@ -959,9 +959,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
|
checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -970,21 +970,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
|
checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
|
checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
|
checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -1215,9 +1215,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.24"
|
version = "0.14.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
|
checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@@ -1448,9 +1448,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.140"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libnghttp2-sys"
|
name = "libnghttp2-sys"
|
||||||
@@ -1903,16 +1903,18 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "2.5.2"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6"
|
checksum = "7e1f879b2998099c2d69ab9605d145d5b661195627eccc680002c4918a7fb6fa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"concurrent-queue",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wepoll-ffi",
|
"pin-project-lite",
|
||||||
"windows-sys 0.42.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2386,6 +2388,7 @@ dependencies = [
|
|||||||
"tar",
|
"tar",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2396,18 +2399,18 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.152"
|
version = "1.0.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
checksum = "71f2b4817415c6d4210bfe1c7bfcf4801b2d904cb4d0e1a8fdb651013c9e86b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.152"
|
version = "1.0.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
checksum = "d071a94a3fac4aff69d023a7f411e33f40f3483f8c5190b1953822b6b76d7630"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2577,9 +2580,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "string_cache"
|
name = "string_cache"
|
||||||
version = "0.8.6"
|
version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d69e88b23f23030bf4d0e9ca7b07434f70e1c1f4d3ca7e93ce958b373654d9f"
|
checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -2709,6 +2712,22 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-keccak"
|
name = "tiny-keccak"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
@@ -2823,9 +2842,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.19.4"
|
version = "0.19.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
|
checksum = "7082a95d48029677a28f181e5f6422d0c8339ad8396a39d3f33d62a90c1f6c30"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2907,9 +2926,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.10"
|
version = "0.3.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
|
checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
@@ -3106,15 +3125,6 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wepoll-ffi"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -3253,3 +3263,16 @@ checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"crc32fast",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"flate2",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "feroxbuster"
|
name = "feroxbuster"
|
||||||
version = "2.10.0"
|
version = "2.9.1"
|
||||||
authors = ["Ben 'epi' Risher (@epi052)"]
|
authors = ["Ben 'epi' Risher (@epi052)"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -56,7 +56,7 @@ ctrlc = "3.2.2"
|
|||||||
anyhow = "1.0.69"
|
anyhow = "1.0.69"
|
||||||
leaky-bucket = "0.12.1"
|
leaky-bucket = "0.12.1"
|
||||||
gaoya = "0.1.2"
|
gaoya = "0.1.2"
|
||||||
self_update = {version = "0.36.0", features = ["archive-tar", "compression-flate2"]}
|
self_update = {version = "0.36.0", features = ["archive-tar", "compression-flate2", "archive-zip", "compression-zip-deflate"]}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.3.0"
|
tempfile = "3.3.0"
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 epi
|
Copyright (c) 2020-2023 epi
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -101,7 +101,6 @@ sudo apt update && sudo apt install -y feroxbuster
|
|||||||
curl -sL https://raw.githubusercontent.com/epi052/feroxbuster/master/install-nix.sh | bash
|
curl -sL https://raw.githubusercontent.com/epi052/feroxbuster/master/install-nix.sh | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Windows x86_64
|
#### Windows x86_64
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -114,6 +113,12 @@ Expand-Archive .\feroxbuster.zip
|
|||||||
|
|
||||||
Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
|
Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
|
||||||
|
|
||||||
|
### Updating feroxbuster (new in v2.9.1)
|
||||||
|
|
||||||
|
```
|
||||||
|
./feroxbuster --update
|
||||||
|
```
|
||||||
|
|
||||||
## 🧰 Example Usage
|
## 🧰 Example Usage
|
||||||
|
|
||||||
Here are a few brief examples to get you started. Please note, feroxbuster can do a **lot more** than what's listed below. As a result, there are **many more** examples, with **demonstration gifs** that highlight specific features, in the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
|
Here are a few brief examples to get you started. Please note, feroxbuster can do a **lot more** than what's listed below. As a result, there are **many more** examples, with **demonstration gifs** that highlight specific features, in the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
|
||||||
@@ -167,11 +172,7 @@ cat targets | ./feroxbuster --stdin --silent -s 200 301 302 --redirects -x js |
|
|||||||
./feroxbuster -u http://127.1 --query token=0123456789ABCDEF
|
./feroxbuster -u http://127.1 --query token=0123456789ABCDEF
|
||||||
```
|
```
|
||||||
|
|
||||||
### Updating feroxbuster (new in v2.10.0)
|
|
||||||
|
|
||||||
```
|
|
||||||
./feroxbuster --update
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 Documentation has **moved** 🚀
|
## 🚀 Documentation has **moved** 🚀
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<tr>
|
<tr>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xaeroborg"><img src="https://avatars.githubusercontent.com/u/33274680?v=4?s=100" width="100px;" alt="xaeroborg"/><br /><sub><b>xaeroborg</b></sub></a><br /><a href="#ideas-xaeroborg" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xaeroborg"><img src="https://avatars.githubusercontent.com/u/33274680?v=4?s=100" width="100px;" alt="xaeroborg"/><br /><sub><b>xaeroborg</b></sub></a><br /><a href="#ideas-xaeroborg" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Luoooio"><img src="https://avatars.githubusercontent.com/u/26653157?v=4?s=100" width="100px;" alt="Luoooio"/><br /><sub><b>Luoooio</b></sub></a><br /><a href="#ideas-Luoooio" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Luoooio"><img src="https://avatars.githubusercontent.com/u/26653157?v=4?s=100" width="100px;" alt="Luoooio"/><br /><sub><b>Luoooio</b></sub></a><br /><a href="#ideas-Luoooio" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://petruknisme.com"><img src="https://avatars.githubusercontent.com/u/6284204?v=4?s=100" width="100px;" alt="Aan"/><br /><sub><b>Aan</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/commits?author=aancw" title="Code">💻</a> <a href="#infra-aancw" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://petruknisme.com"><img src="https://avatars.githubusercontent.com/u/6284204?v=4?s=100" width="100px;" alt="Aan"/><br /><sub><b>Aan</b></sub></a><br /><a href="https://github.com/epi052/feroxbuster/commits?author=aancw" title="Code">💻</a> <a href="#infra-aancw" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#ideas-aancw" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
79
choco_package/feroxbuster.nuspec
Normal file
79
choco_package/feroxbuster.nuspec
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>feroxbuster</id>
|
||||||
|
<version>2.8.0</version>
|
||||||
|
<packageSourceUrl>https://github.com/epi052/feroxbuster/releases/</packageSourceUrl>
|
||||||
|
<owners>epi052</owners>
|
||||||
|
<title>feroxbuster (Install)</title>
|
||||||
|
<authors>epi052</authors>
|
||||||
|
<projectUrl>https://github.com/epi052/feroxbuster</projectUrl>
|
||||||
|
<iconUrl>https://rawcdn.githack.com/epi052/feroxbuster/2d381e7e057ce60c580b324dd36c9abaf30c2ec7/img/logo/logo.png</iconUrl>
|
||||||
|
<copyright>2020-2023</copyright>
|
||||||
|
<licenseUrl>https://github.com/epi052/feroxbuster/blob/main/LICENSE</licenseUrl>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
|
<projectSourceUrl>https://github.com/epi052/feroxbuster</projectSourceUrl>
|
||||||
|
<docsUrl>https://epi052.github.io/feroxbuster-docs/docs/</docsUrl>
|
||||||
|
<!--<mailingListUrl></mailingListUrl>-->
|
||||||
|
<bugTrackerUrl>https://github.com/epi052/feroxbuster/issues</bugTrackerUrl>
|
||||||
|
<tags>content-discovery pentesting-tool url-bruteforcer</tags>
|
||||||
|
<summary>A simple, fast, recursive content discovery tool written in Rust</summary>
|
||||||
|
<description>
|
||||||
|
A simple, fast, recursive content discovery tool written in Rust
|
||||||
|
[](https://github.com/epi052/feroxbuster)
|
||||||
|
|
||||||
|
## What the heck is a ferox anyway?
|
||||||
|
|
||||||
|
Ferox is short for Ferric Oxide. Ferric Oxide, simply put, is rust. The name rustbuster was taken, so I decided on a
|
||||||
|
variation.
|
||||||
|
|
||||||
|
## What's it do tho?
|
||||||
|
|
||||||
|
`feroxbuster` is a tool designed to perform [Forced Browsing](https://owasp.org/www-community/attacks/Forced_browsing).
|
||||||
|
|
||||||
|
Forced browsing is an attack where the aim is to enumerate and access resources that are not referenced by the web
|
||||||
|
application, but are still accessible by an attacker.
|
||||||
|
|
||||||
|
`feroxbuster` uses brute force combined with a wordlist to search for unlinked content in target directories. These
|
||||||
|
resources may store sensitive information about web applications and operational systems, such as source code,
|
||||||
|
credentials, internal network addressing, etc...
|
||||||
|
|
||||||
|
This attack is also known as Predictable Resource Location, File Enumeration, Directory Enumeration, and Resource
|
||||||
|
Enumeration.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
This section will cover the minimum amount of information to get up and running with feroxbuster. Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/), as it's much more comprehensive.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
There are quite a few other [installation methods](https://epi052.github.io/feroxbuster-docs/docs/installation/), but these snippets should cover the majority of users.
|
||||||
|
|
||||||
|
#### All others Docs
|
||||||
|
|
||||||
|
Please refer the the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
Here are a few brief examples to get you started. Please note, feroxbuster can do a **lot more** than what's listed below. As a result, there are **many more** examples, with **demonstration gifs** that highlight specific features, in the [documentation](https://epi052.github.io/feroxbuster-docs/docs/).
|
||||||
|
|
||||||
|
### Multiple Values
|
||||||
|
|
||||||
|
Options that take multiple values are very flexible. Consider the following ways of specifying extensions:
|
||||||
|
|
||||||
|
```
|
||||||
|
./feroxbuster -u http://127.1 -x pdf -x js,html -x php txt json,docx
|
||||||
|
```
|
||||||
|
|
||||||
|
The command above adds .pdf, .js, .html, .php, .txt, .json, and .docx to each url
|
||||||
|
|
||||||
|
All of the methods above (multiple flags, space separated, comma separated, etc...) are valid and interchangeable. The
|
||||||
|
same goes for urls, headers, status codes, queries, and size filters.
|
||||||
|
</description>
|
||||||
|
<!-- <releaseNotes>__REPLACE_OR_REMOVE__MarkDown_Okay</releaseNotes> -->
|
||||||
|
</metadata>
|
||||||
|
<files>
|
||||||
|
<!-- this section controls what actually gets packaged into the Chocolatey package -->
|
||||||
|
<file src="tools\**" target="tools" />
|
||||||
|
</files>
|
||||||
|
</package>
|
||||||
26
choco_package/legal/LICENSE.txt
Normal file
26
choco_package/legal/LICENSE.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
From: https://github.com/epi052/feroxbuster/blob/main/LICENSE
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020-2023 epi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
5
choco_package/legal/VERIFICATION.txt
Normal file
5
choco_package/legal/VERIFICATION.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
VERIFICATION
|
||||||
|
|
||||||
|
checksum -t sha512 -f .\x86-windows-feroxbuster.exe.zip
|
||||||
|
checksum -t sha512 -f .\x86_64-windows-feroxbuster.exe.zip
|
||||||
27
choco_package/tools/chocolateyinstall.ps1
Normal file
27
choco_package/tools/chocolateyinstall.ps1
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||||
|
$version = '2.8.0'
|
||||||
|
$url = "https://github.com/epi052/feroxbuster/releases/download/v$version/x86-windows-feroxbuster.exe.zip"
|
||||||
|
$url64 = "https://github.com/epi052/feroxbuster/releases/download/v$version/x86_64-windows-feroxbuster.exe.zip"
|
||||||
|
|
||||||
|
$packageArgs = @{
|
||||||
|
packageName = $env:ChocolateyPackageName
|
||||||
|
unzipLocation = $toolsDir
|
||||||
|
fileType = 'exe' #only one of these: exe, msi, msu
|
||||||
|
url = $url
|
||||||
|
url64bit = $url64
|
||||||
|
#file = $fileLocation
|
||||||
|
|
||||||
|
softwareName = 'feroxbuster*'
|
||||||
|
|
||||||
|
# Checksums are now required as of 0.10.0.
|
||||||
|
# To determine checksums, you can get that from the original site if provided.
|
||||||
|
# You can also use checksum.exe (choco install checksum) and use it
|
||||||
|
# e.g. checksum -t sha256 -f path\to\file
|
||||||
|
checksum = 'e5cac59c737260233903a17706a68bac11fe0d7a15169e1c5a9637cc221e7230fd6ddbfc1a7243833dde6472ad053c033449ca8338164654f7354363da54ba88'
|
||||||
|
checksumType = 'sha512'
|
||||||
|
checksum64 = 'cce58d6eacef7e12c31076f5a00fee9742a4e3fdfc69d807d98736200e50469f77359978e137ecafd87b14460845c65c6808d1f8b23ae561f7e7c637e355dee3'
|
||||||
|
checksumType64= 'sha512'
|
||||||
|
}
|
||||||
|
Install-ChocolateyZipPackage @packageArgs # https://docs.chocolatey.org/en-us/create/functions/install-chocolateyzippackage
|
||||||
47
choco_package/tools/chocolateyuninstall.ps1
Normal file
47
choco_package/tools/chocolateyuninstall.ps1
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
$ErrorActionPreference = 'Stop' # stop on all errors
|
||||||
|
$packageArgs = @{
|
||||||
|
packageName = $env:ChocolateyPackageName
|
||||||
|
softwareName = 'feroxbuster*' #part or all of the Display Name as you see it in Programs and Features. It should be enough to be unique
|
||||||
|
fileType = 'exe' #only one of these: MSI or EXE (ignore MSU for now)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get-UninstallRegistryKey is new to 0.9.10, if supporting 0.9.9.x and below,
|
||||||
|
# take a dependency on "chocolatey-core.extension" in your nuspec file.
|
||||||
|
# This is only a fuzzy search if $softwareName includes '*'. Otherwise it is
|
||||||
|
# exact. In the case of versions in key names, we recommend removing the version
|
||||||
|
# and using '*'.
|
||||||
|
[array]$key = Get-UninstallRegistryKey -SoftwareName $packageArgs['softwareName']
|
||||||
|
|
||||||
|
if ($key.Count -eq 1) {
|
||||||
|
$key | % {
|
||||||
|
$packageArgs['file'] = "$($_.UninstallString)" #NOTE: You may need to split this if it contains spaces, see below
|
||||||
|
|
||||||
|
if ($packageArgs['fileType'] -eq 'MSI') {
|
||||||
|
# The Product Code GUID is all that should be passed for MSI, and very
|
||||||
|
# FIRST, because it comes directly after /x, which is already set in the
|
||||||
|
# Uninstall-ChocolateyPackage msiargs (facepalm).
|
||||||
|
$packageArgs['silentArgs'] = "$($_.PSChildName) $($packageArgs['silentArgs'])"
|
||||||
|
|
||||||
|
# Don't pass anything for file, it is ignored for msi (facepalm number 2)
|
||||||
|
# Alternatively if you need to pass a path to an msi, determine that and
|
||||||
|
# use it instead of the above in silentArgs, still very first
|
||||||
|
$packageArgs['file'] = ''
|
||||||
|
} else {
|
||||||
|
# NOTES:
|
||||||
|
# - You probably will need to sanitize $packageArgs['file'] as it comes from the registry and could be in a variety of fun but unusable formats
|
||||||
|
# - Split args from exe in $packageArgs['file'] and pass those args through $packageArgs['silentArgs'] or ignore them
|
||||||
|
# - Ensure you don't pass double quotes in $file (aka $packageArgs['file']) - otherwise you will get "Illegal characters in path when you attempt to run this"
|
||||||
|
# - Review the code for auto-uninstaller for all of the fun things it does in sanitizing - https://github.com/chocolatey/choco/blob/bfe351b7d10c798014efe4bfbb100b171db25099/src/chocolatey/infrastructure.app/services/AutomaticUninstallerService.cs#L142-L192
|
||||||
|
}
|
||||||
|
|
||||||
|
Uninstall-ChocolateyPackage @packageArgs
|
||||||
|
}
|
||||||
|
} elseif ($key.Count -eq 0) {
|
||||||
|
Write-Warning "$packageName has already been uninstalled by other means."
|
||||||
|
} elseif ($key.Count -gt 1) {
|
||||||
|
Write-Warning "$($key.Count) matches found!"
|
||||||
|
Write-Warning "To prevent accidental data loss, no programs will be uninstalled."
|
||||||
|
Write-Warning "Please alert package maintainer the following keys were matched:"
|
||||||
|
$key | % {Write-Warning "- $($_.DisplayName)"}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,6 @@
|
|||||||
# queries = [["name","value"], ["rick", "astley"]]
|
# queries = [["name","value"], ["rick", "astley"]]
|
||||||
# save_state = false
|
# save_state = false
|
||||||
# time_limit = "10m"
|
# time_limit = "10m"
|
||||||
# update_app = false
|
|
||||||
|
|
||||||
# headers can be specified on multiple lines or as an inline table
|
# headers can be specified on multiple lines or as an inline table
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ _feroxbuster() {
|
|||||||
'--replay-proxy=[Send only unfiltered requests through a Replay Proxy, instead of all requests]:REPLAY_PROXY:_urls' \
|
'--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: ' \
|
'*-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: ' \
|
'*--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.10.0)]:USER_AGENT: ' \
|
'-a+[Sets the User-Agent (default: feroxbuster/2.9.1)]:USER_AGENT: ' \
|
||||||
'--user-agent=[Sets the User-Agent (default: feroxbuster/2.10.0)]:USER_AGENT: ' \
|
'--user-agent=[Sets the User-Agent (default: feroxbuster/2.9.1)]:USER_AGENT: ' \
|
||||||
'*-x+[File extension(s) to search for (ex: -x php -x pdf js)]:FILE_EXTENSION: ' \
|
'*-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: ' \
|
'*--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: ' \
|
'*-m+[Which HTTP request method(s) should be sent (default: GET)]:HTTP_METHODS: ' \
|
||||||
@@ -104,8 +104,8 @@ _feroxbuster() {
|
|||||||
'--quiet[Hide progress bars and banner (good for tmux windows w/ notifications)]' \
|
'--quiet[Hide progress bars and banner (good for tmux windows w/ notifications)]' \
|
||||||
'--json[Emit JSON logs to --output and --debug-log instead of normal text]' \
|
'--json[Emit JSON logs to --output and --debug-log instead of normal text]' \
|
||||||
'--no-state[Disable state output file (*.state)]' \
|
'--no-state[Disable state output file (*.state)]' \
|
||||||
'(-u --url -w --wordlist)-U[Update the app to the latest version]' \
|
'-U[Update feroxbuster to the latest version]' \
|
||||||
'(-u --url -w --wordlist)--update[Update the app to the latest version]' \
|
'--update[Update feroxbuster to the latest version]' \
|
||||||
'-h[Print help (see more with '\''--help'\'')]' \
|
'-h[Print help (see more with '\''--help'\'')]' \
|
||||||
'--help[Print help (see more with '\''--help'\'')]' \
|
'--help[Print help (see more with '\''--help'\'')]' \
|
||||||
'-V[Print version]' \
|
'-V[Print version]' \
|
||||||
|
|||||||
@@ -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('--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('-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('--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.10.0)')
|
[CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.9.1)')
|
||||||
[CompletionResult]::new('--user-agent', 'user-agent', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.10.0)')
|
[CompletionResult]::new('--user-agent', 'user-agent', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.9.1)')
|
||||||
[CompletionResult]::new('-x', 'x', [CompletionResultType]::ParameterName, 'File extension(s) to search for (ex: -x php -x pdf js)')
|
[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('--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)')
|
[CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Which HTTP request method(s) should be sent (default: GET)')
|
||||||
@@ -110,8 +110,8 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock {
|
|||||||
[CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Hide progress bars and banner (good for tmux windows w/ notifications)')
|
[CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Hide progress bars and banner (good for tmux windows w/ notifications)')
|
||||||
[CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'Emit JSON logs to --output and --debug-log instead of normal text')
|
[CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'Emit JSON logs to --output and --debug-log instead of normal text')
|
||||||
[CompletionResult]::new('--no-state', 'no-state', [CompletionResultType]::ParameterName, 'Disable state output file (*.state)')
|
[CompletionResult]::new('--no-state', 'no-state', [CompletionResultType]::ParameterName, 'Disable state output file (*.state)')
|
||||||
[CompletionResult]::new('-U', 'U', [CompletionResultType]::ParameterName, 'Update the app to the latest version')
|
[CompletionResult]::new('-U', 'U', [CompletionResultType]::ParameterName, 'Update feroxbuster to the latest version')
|
||||||
[CompletionResult]::new('--update', 'update', [CompletionResultType]::ParameterName, 'Update the app to the latest version')
|
[CompletionResult]::new('--update', 'update', [CompletionResultType]::ParameterName, 'Update feroxbuster to the latest version')
|
||||||
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
|
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
|
||||||
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
|
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
|
||||||
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
|
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version')
|
||||||
|
|||||||
@@ -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 --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 -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 --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.10.0)'
|
cand -a 'Sets the User-Agent (default: feroxbuster/2.9.1)'
|
||||||
cand --user-agent 'Sets the User-Agent (default: feroxbuster/2.10.0)'
|
cand --user-agent 'Sets the User-Agent (default: feroxbuster/2.9.1)'
|
||||||
cand -x 'File extension(s) to search for (ex: -x php -x pdf js)'
|
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 --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)'
|
cand -m 'Which HTTP request method(s) should be sent (default: GET)'
|
||||||
@@ -107,8 +107,8 @@ set edit:completion:arg-completer[feroxbuster] = {|@words|
|
|||||||
cand --quiet 'Hide progress bars and banner (good for tmux windows w/ notifications)'
|
cand --quiet 'Hide progress bars and banner (good for tmux windows w/ notifications)'
|
||||||
cand --json 'Emit JSON logs to --output and --debug-log instead of normal text'
|
cand --json 'Emit JSON logs to --output and --debug-log instead of normal text'
|
||||||
cand --no-state 'Disable state output file (*.state)'
|
cand --no-state 'Disable state output file (*.state)'
|
||||||
cand -U 'Update the app to the latest version'
|
cand -U 'Update feroxbuster to the latest version'
|
||||||
cand --update 'Update the app to the latest version'
|
cand --update 'Update feroxbuster to the latest version'
|
||||||
cand -h 'Print help (see more with ''--help'')'
|
cand -h 'Print help (see more with ''--help'')'
|
||||||
cand --help 'Print help (see more with ''--help'')'
|
cand --help 'Print help (see more with ''--help'')'
|
||||||
cand -V 'Print version'
|
cand -V 'Print version'
|
||||||
|
|||||||
@@ -166,9 +166,6 @@ pub struct Banner {
|
|||||||
|
|
||||||
/// represents Configuration.collect_words
|
/// represents Configuration.collect_words
|
||||||
force_recursion: BannerEntry,
|
force_recursion: BannerEntry,
|
||||||
|
|
||||||
/// represents Configuration.update_app
|
|
||||||
update_app: BannerEntry,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// implementation of Banner
|
/// implementation of Banner
|
||||||
@@ -336,7 +333,6 @@ impl Banner {
|
|||||||
let json = BannerEntry::new("🧔", "JSON Output", &config.json.to_string());
|
let json = BannerEntry::new("🧔", "JSON Output", &config.json.to_string());
|
||||||
let output = BannerEntry::new("💾", "Output File", &config.output);
|
let output = BannerEntry::new("💾", "Output File", &config.output);
|
||||||
let debug_log = BannerEntry::new("🪲", "Debugging Log", &config.debug_log);
|
let debug_log = BannerEntry::new("🪲", "Debugging Log", &config.debug_log);
|
||||||
let update_app = BannerEntry::new("🔥", "Update app", &config.update_app.to_string());
|
|
||||||
let extensions = BannerEntry::new(
|
let extensions = BannerEntry::new(
|
||||||
"💲",
|
"💲",
|
||||||
"Extensions",
|
"Extensions",
|
||||||
@@ -441,7 +437,6 @@ impl Banner {
|
|||||||
config: cfg,
|
config: cfg,
|
||||||
version: VERSION.to_string(),
|
version: VERSION.to_string(),
|
||||||
update_status: UpdateStatus::Unknown,
|
update_status: UpdateStatus::Unknown,
|
||||||
update_app,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,10 +666,6 @@ by Ben "epi" Risher {} ver: {}"#,
|
|||||||
writeln!(&mut writer, "{}", self.force_recursion)?;
|
writeln!(&mut writer, "{}", self.force_recursion)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.update_app {
|
|
||||||
writeln!(&mut writer, "{}", self.update_app)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.scan_limit > 0 {
|
if config.scan_limit > 0 {
|
||||||
writeln!(&mut writer, "{}", self.scan_limit)?;
|
writeln!(&mut writer, "{}", self.scan_limit)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ pub struct Configuration {
|
|||||||
pub force_recursion: bool,
|
pub force_recursion: bool,
|
||||||
|
|
||||||
/// Auto update app feature
|
/// Auto update app feature
|
||||||
#[serde(default)]
|
#[serde(skip)]
|
||||||
pub update_app: bool,
|
pub update_app: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ fn setup_config_test() -> Configuration {
|
|||||||
filter_word_count = [994, 992]
|
filter_word_count = [994, 992]
|
||||||
filter_line_count = [34]
|
filter_line_count = [34]
|
||||||
filter_status = [201]
|
filter_status = [201]
|
||||||
update_app = false
|
|
||||||
"#;
|
"#;
|
||||||
let tmp_dir = TempDir::new().unwrap();
|
let tmp_dir = TempDir::new().unwrap();
|
||||||
let file = tmp_dir.path().join(DEFAULT_CONFIG_NAME);
|
let file = tmp_dir.path().join(DEFAULT_CONFIG_NAME);
|
||||||
@@ -104,7 +103,6 @@ fn default_configuration() {
|
|||||||
assert!(!config.collect_extensions);
|
assert!(!config.collect_extensions);
|
||||||
assert!(!config.collect_backups);
|
assert!(!config.collect_backups);
|
||||||
assert!(!config.collect_words);
|
assert!(!config.collect_words);
|
||||||
assert!(!config.update_app);
|
|
||||||
assert!(config.regex_denylist.is_empty());
|
assert!(config.regex_denylist.is_empty());
|
||||||
assert_eq!(config.queries, Vec::new());
|
assert_eq!(config.queries, Vec::new());
|
||||||
assert_eq!(config.filter_size, Vec::<u64>::new());
|
assert_eq!(config.filter_size, Vec::<u64>::new());
|
||||||
@@ -472,13 +470,6 @@ fn config_default_not_random_agent() {
|
|||||||
assert!(!config.random_agent);
|
assert!(!config.random_agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
/// parse the test config and see that the value parsed is correct
|
|
||||||
fn config_update_app() {
|
|
||||||
let config = setup_config_test();
|
|
||||||
assert!(!config.update_app);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
/// test that an error message is printed and panic is called when report_and_exit is called
|
/// test that an error message is printed and panic is called when report_and_exit is called
|
||||||
|
|||||||
@@ -160,13 +160,17 @@ impl Handles {
|
|||||||
/// number of extensions plus the number of request method types plus any dynamically collected
|
/// number of extensions plus the number of request method types plus any dynamically collected
|
||||||
/// extensions
|
/// extensions
|
||||||
pub fn expected_num_requests_multiplier(&self) -> usize {
|
pub fn expected_num_requests_multiplier(&self) -> usize {
|
||||||
let multiplier = self.config.extensions.len()
|
let mut multiplier = self.config.extensions.len().max(1);
|
||||||
+ self.config.methods.len()
|
|
||||||
+ self.num_collected_extensions();
|
|
||||||
|
|
||||||
// methods should always have at least 1 member, likely making this .max call unneeded
|
if multiplier > 1 {
|
||||||
// but leaving it for 'just in case' reasons
|
// when we have more than one extension, we need to account for the fact that we'll
|
||||||
multiplier.max(1)
|
// be making a request for each extension and the base word (e.g. /foo.html and /foo)
|
||||||
|
multiplier += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiplier *= self.config.methods.len().max(1) * self.num_collected_extensions().max(1);
|
||||||
|
|
||||||
|
multiplier
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper to easily get the (locked) underlying FeroxScans object
|
/// Helper to easily get the (locked) underlying FeroxScans object
|
||||||
|
|||||||
@@ -294,12 +294,7 @@ impl ScanHandler {
|
|||||||
if let Ok(guard) = self.wordlist.lock().as_ref() {
|
if let Ok(guard) = self.wordlist.lock().as_ref() {
|
||||||
if let Some(list) = guard.as_ref() {
|
if let Some(list) = guard.as_ref() {
|
||||||
return if offset > 0 {
|
return if offset > 0 {
|
||||||
// the offset could be off a bit, so we'll adjust it backwards by 10%
|
Ok(Arc::new(list[offset..].to_vec()))
|
||||||
// of the overall wordlist size to ensure we don't miss any words
|
|
||||||
// (hopefully)
|
|
||||||
let adjusted_offset = offset - ((offset as f64 * 0.10) as usize);
|
|
||||||
|
|
||||||
Ok(Arc::new(list[adjusted_offset..].to_vec()))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(list.clone())
|
Ok(list.clone())
|
||||||
};
|
};
|
||||||
@@ -337,7 +332,18 @@ impl ScanHandler {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let list = self.get_wordlist(scan.requests() as usize)?;
|
let divisor = self.handles.expected_num_requests_multiplier();
|
||||||
|
|
||||||
|
let list = if divisor > 1 && scan.requests() > 0 {
|
||||||
|
// if there were extensions provided and/or more than a single method used, and some
|
||||||
|
// number of requests have already been sent, we need to adjust the offset into the
|
||||||
|
// wordlist to ensure we don't index out of bounds
|
||||||
|
|
||||||
|
let adjusted = scan.requests_made_so_far() as f64 / divisor as f64 - 1.0;
|
||||||
|
self.get_wordlist(adjusted as usize)?
|
||||||
|
} else {
|
||||||
|
self.get_wordlist(scan.requests_made_so_far() as usize)?
|
||||||
|
};
|
||||||
|
|
||||||
log::info!("scan handler received {} - beginning scan", target);
|
log::info!("scan handler received {} - beginning scan", target);
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,12 @@ impl StatsHandler {
|
|||||||
);
|
);
|
||||||
|
|
||||||
self.bar.set_message(&msg);
|
self.bar.set_message(&msg);
|
||||||
self.bar.inc(1);
|
|
||||||
|
if self.bar.position() < self.stats.total_expected() as u64 {
|
||||||
|
// don't run off the end when we're a few requests over the expected total
|
||||||
|
// due to the heuristics tests
|
||||||
|
self.bar.inc(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize new `Stats` object and the sc side of an mpsc channel that is responsible for
|
/// Initialize new `Stats` object and the sc side of an mpsc channel that is responsible for
|
||||||
|
|||||||
46
src/main.rs
46
src/main.rs
@@ -225,25 +225,15 @@ async fn wrapped_main(config: Arc<Configuration>) -> Result<()> {
|
|||||||
|
|
||||||
// check if update_app is true
|
// check if update_app is true
|
||||||
if config.update_app {
|
if config.update_app {
|
||||||
let target_os = format!("{}-{}", ARCH, OS);
|
match update_app().await {
|
||||||
tokio::task::spawn_blocking(move || {
|
Err(e) => eprintln!("\n[ERROR] {}", e),
|
||||||
let status = self_update::backends::github::Update::configure()
|
Ok(self_update::Status::UpToDate(version)) => {
|
||||||
.repo_owner("epi052")
|
eprintln!("\nFeroxbuster {} is up to date", version)
|
||||||
.repo_name("feroxbuster")
|
}
|
||||||
.bin_name("feroxbuster")
|
Ok(self_update::Status::Updated(version)) => {
|
||||||
.target(target_os.as_str())
|
eprintln!("\nFeroxbuster updated to {} version", version)
|
||||||
.show_download_progress(true)
|
}
|
||||||
.current_version(cargo_crate_version!())
|
}
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
.update()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("Updated version: `{}`!", status.version());
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,6 +544,24 @@ async fn clean_up(handles: Arc<Handles>, tasks: Tasks) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn update_app() -> Result<self_update::Status, Box<dyn ::std::error::Error>> {
|
||||||
|
let target_os = format!("{}-{}", ARCH, OS);
|
||||||
|
let status = tokio::task::spawn_blocking(move || {
|
||||||
|
self_update::backends::github::Update::configure()
|
||||||
|
.repo_owner("epi052")
|
||||||
|
.repo_name("feroxbuster")
|
||||||
|
.bin_name("feroxbuster")
|
||||||
|
.target(target_os.as_str())
|
||||||
|
.show_download_progress(true)
|
||||||
|
.current_version(cargo_crate_version!())
|
||||||
|
.build()?
|
||||||
|
.update()
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
Ok(status)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let config = Arc::new(Configuration::new().with_context(|| "Could not create Configuration")?);
|
let config = Arc::new(Configuration::new().with_context(|| "Could not create Configuration")?);
|
||||||
|
|
||||||
|
|||||||
@@ -475,7 +475,6 @@ pub fn initialize() -> Command {
|
|||||||
Arg::new("wordlist")
|
Arg::new("wordlist")
|
||||||
.short('w')
|
.short('w')
|
||||||
.long("wordlist")
|
.long("wordlist")
|
||||||
.required_unless_present_any(["update_app"])
|
|
||||||
.value_hint(ValueHint::FilePath)
|
.value_hint(ValueHint::FilePath)
|
||||||
.value_name("FILE")
|
.value_name("FILE")
|
||||||
.help("Path to the wordlist")
|
.help("Path to the wordlist")
|
||||||
@@ -614,10 +613,10 @@ pub fn initialize() -> Command {
|
|||||||
Arg::new("update_app")
|
Arg::new("update_app")
|
||||||
.short('U')
|
.short('U')
|
||||||
.long("update")
|
.long("update")
|
||||||
.conflicts_with_all(["url", "wordlist"])
|
.exclusive(true)
|
||||||
.num_args(0)
|
.num_args(0)
|
||||||
.help_heading("Update settings")
|
.help_heading("Update settings")
|
||||||
.help("Update the app to the latest version"),
|
.help("Update feroxbuster to the latest version"),
|
||||||
)
|
)
|
||||||
.after_long_help(EPILOGUE);
|
.after_long_help(EPILOGUE);
|
||||||
|
|
||||||
|
|||||||
@@ -210,10 +210,14 @@ impl Menu {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
if value.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let value = self.str_to_usize(value);
|
let value = self.str_to_usize(value);
|
||||||
|
|
||||||
if value != 0 && !nums.contains(&value) {
|
if !nums.contains(&value) {
|
||||||
// the zeroth scan is always skipped, skip already known values
|
// skip already known values
|
||||||
nums.push(value);
|
nums.push(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ pub struct FeroxScan {
|
|||||||
pub scan_type: ScanType,
|
pub scan_type: ScanType,
|
||||||
|
|
||||||
/// The order in which the scan was received
|
/// The order in which the scan was received
|
||||||
|
#[allow(dead_code)] // not entirely sure this isn't used somewhere
|
||||||
pub(crate) scan_order: ScanOrder,
|
pub(crate) scan_order: ScanOrder,
|
||||||
|
|
||||||
/// Number of requests to populate the progress bar with
|
/// Number of requests to populate the progress bar with
|
||||||
@@ -153,7 +154,13 @@ impl FeroxScan {
|
|||||||
pub(super) fn stop_progress_bar(&self) {
|
pub(super) fn stop_progress_bar(&self) {
|
||||||
if let Ok(guard) = self.progress_bar.lock() {
|
if let Ok(guard) = self.progress_bar.lock() {
|
||||||
if guard.is_some() {
|
if guard.is_some() {
|
||||||
(*guard).as_ref().unwrap().finish_at_current_pos()
|
let pb = (*guard).as_ref().unwrap();
|
||||||
|
|
||||||
|
if pb.position() > self.num_requests {
|
||||||
|
pb.finish()
|
||||||
|
} else {
|
||||||
|
pb.finish_at_current_pos()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,11 +325,6 @@ impl FeroxScans {
|
|||||||
let mut printed = 0;
|
let mut printed = 0;
|
||||||
|
|
||||||
for (i, scan) in scans.iter().enumerate() {
|
for (i, scan) in scans.iter().enumerate() {
|
||||||
if matches!(scan.scan_order, ScanOrder::Initial) || scan.task.try_lock().is_err() {
|
|
||||||
// original target passed in via either -u or --stdin
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if matches!(scan.scan_type, ScanType::Directory) {
|
if matches!(scan.scan_type, ScanType::Directory) {
|
||||||
if printed == 0 {
|
if printed == 0 {
|
||||||
self.menu
|
self.menu
|
||||||
@@ -378,14 +373,13 @@ impl FeroxScans {
|
|||||||
|
|
||||||
if input == 'y' || input == '\n' {
|
if input == 'y' || input == '\n' {
|
||||||
self.menu.println(&format!("Stopping {}...", selected.url));
|
self.menu.println(&format!("Stopping {}...", selected.url));
|
||||||
|
|
||||||
selected
|
selected
|
||||||
.abort()
|
.abort()
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| log::warn!("Could not cancel task: {}", e));
|
.unwrap_or_else(|e| log::warn!("Could not cancel task: {}", e));
|
||||||
|
|
||||||
let pb = selected.progress_bar();
|
let pb = selected.progress_bar();
|
||||||
num_cancelled += pb.length() as usize - pb.position() as usize
|
num_cancelled += pb.length() as usize - pb.position() as usize;
|
||||||
} else {
|
} else {
|
||||||
self.menu.println("Ok, doing nothing...");
|
self.menu.println("Ok, doing nothing...");
|
||||||
}
|
}
|
||||||
@@ -459,6 +453,32 @@ impl FeroxScans {
|
|||||||
|
|
||||||
self.menu.show_progress_bars();
|
self.menu.show_progress_bars();
|
||||||
|
|
||||||
|
let has_active_scans = if let Ok(guard) = self.scans.read() {
|
||||||
|
guard.iter().any(|s| s.is_active())
|
||||||
|
} else {
|
||||||
|
// if we can't tell for sure, we'll let it ride
|
||||||
|
//
|
||||||
|
// i'm not sure which is the better option here:
|
||||||
|
// either return true and let it potentially hang, or
|
||||||
|
// return false and exit, so just going with not
|
||||||
|
// abruptly exiting for maybe no reason
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
if !has_active_scans {
|
||||||
|
// the last active scan was cancelled, so we can exit
|
||||||
|
self.menu.println(&format!(
|
||||||
|
" 😱 no more active scans... {}",
|
||||||
|
style("exiting").red()
|
||||||
|
));
|
||||||
|
|
||||||
|
let (tx, rx) = tokio::sync::oneshot::channel::<bool>();
|
||||||
|
handles
|
||||||
|
.send_scan_command(Command::JoinTasks(tx))
|
||||||
|
.unwrap_or_default();
|
||||||
|
rx.await.unwrap_or_default();
|
||||||
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -668,11 +668,7 @@ fn menu_get_command_input_from_user_returns_cancel() {
|
|||||||
assert!(matches!(result, MenuCmd::Cancel(_, _)));
|
assert!(matches!(result, MenuCmd::Cancel(_, _)));
|
||||||
|
|
||||||
if let MenuCmd::Cancel(canx_list, ret_force) = result {
|
if let MenuCmd::Cancel(canx_list, ret_force) = result {
|
||||||
if idx == 0 {
|
assert_eq!(canx_list, vec![idx]);
|
||||||
assert!(canx_list.is_empty());
|
|
||||||
} else {
|
|
||||||
assert_eq!(canx_list, vec![idx]);
|
|
||||||
}
|
|
||||||
assert_eq!(force, ret_force);
|
assert_eq!(force, ret_force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1430,9 +1430,5 @@ fn banner_prints_update_app() {
|
|||||||
.arg("--update")
|
.arg("--update")
|
||||||
.assert()
|
.assert()
|
||||||
.success()
|
.success()
|
||||||
.stderr(
|
.stdout(predicate::str::contains("Checking target-arch..."));
|
||||||
predicate::str::contains("─┬─")
|
|
||||||
.and(predicate::str::contains("Update app"))
|
|
||||||
.and(predicate::str::contains("─┴─")),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user