diff --git a/Cargo.lock b/Cargo.lock index 4c04eeac..e6baaca7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,11 +28,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstyle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" + [[package]] name = "anyhow" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "ascii-canvas" @@ -55,10 +61,11 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.0.8" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9834fcc22e0874394a010230586367d4a3e9f11b560f469262678547e1d2575e" +checksum = "ec0b2340f55d9661d76793b2bfc2eb0e62689bd79d067a95707ea762afd5e9dd" dependencies = [ + "anstyle", "bstr", "doc-comment", "predicates", @@ -198,13 +205,13 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" -version = "0.1.66" +version = "0.1.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" +checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.0", ] [[package]] @@ -299,9 +306,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" +checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" dependencies = [ "memchr", "once_cell", @@ -347,9 +354,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.1.8" +version = "4.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +checksum = "ce38afc168d8665cfc75c7b1dd9672e50716a137f433f070991619744a67342a" dependencies = [ "bitflags", "clap_lex", @@ -362,18 +369,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.1.4" +version = "4.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501ff0a401473ea1d4c3b125ff95506b62c5bc5768d818634195fbb7c4ad5ff4" +checksum = "37686beaba5ac9f3ab01ee3172f792fc6ffdd685bfb9e63cfef02c0571a4e8e1" dependencies = [ "clap", ] [[package]] name = "clap_lex" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" +checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" dependencies = [ "os_str_bytes", ] @@ -528,7 +535,7 @@ dependencies = [ "proc-macro2", "quote", "smallvec", - "syn", + "syn 1.0.109", ] [[package]] @@ -538,7 +545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -548,7 +555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -602,7 +609,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 1.0.109", ] [[package]] @@ -702,9 +709,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "ena" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e5d13ca2353ab7d0230988629def93914a8c4015f621f9b13ed2955614731d" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" dependencies = [ "log", ] @@ -775,7 +782,7 @@ dependencies = [ [[package]] name = "feroxbuster" -version = "2.9.1" +version = "2.9.2" dependencies = [ "anyhow", "assert_cmd", @@ -965,7 +972,7 @@ checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1142,7 +1149,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1305,10 +1312,11 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +checksum = "76e86b86ae312accbf05ade23ce76b625e0e47a255712b7414037385a1c05380" dependencies = [ + "hermit-abi 0.3.1", "libc", "windows-sys 0.45.0", ] @@ -1661,9 +1669,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.45" +version = "0.10.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +checksum = "fd2523381e46256e40930512c7fd25562b9eae4812cb52078f155e87217c9d1e" dependencies = [ "bitflags", "cfg-if", @@ -1682,7 +1690,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1702,9 +1710,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.80" +version = "0.9.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +checksum = "176be2629957c157240f68f61f2d0053ad3a4ecfdd9ebf1e6521d18d9635cf67" dependencies = [ "autocfg", "cc", @@ -1836,7 +1844,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1880,7 +1888,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1937,10 +1945,11 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" -version = "2.1.5" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +checksum = "1ba7d6ead3e3966038f68caa9fc1f860185d95a793180bbcfe0d0da47b3961ed" dependencies = [ + "anstyle", "difflib", "float-cmp", "itertools", @@ -1951,15 +1960,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" [[package]] name = "predicates-tree" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" dependencies = [ "predicates-core", "termtree", @@ -1973,9 +1982,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" dependencies = [ "unicode-ident", ] @@ -1991,9 +2000,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -2393,28 +2402,28 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.155" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71f2b4817415c6d4210bfe1c7bfcf4801b2d904cb4d0e1a8fdb651013c9e86b8" +checksum = "707de5fcf5df2b5788fca98dd7eab490bc2fd9b7ef1404defc462833b83f25ca" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.155" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d071a94a3fac4aff69d023a7f411e33f40f3483f8c5190b1953822b6b76d7630" +checksum = "78997f4555c22a7971214540c4a661291970619afd56de19f77e0de86296e1e5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.0", ] [[package]] @@ -2621,6 +2630,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cff13bb1732bccfe3b246f3fdb09edfd51c01d6f5299b7ccd9457c2e4e37774" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tar" version = "0.4.38" @@ -2688,28 +2708,28 @@ dependencies = [ [[package]] name = "termtree" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.0", ] [[package]] @@ -2780,7 +2800,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2821,9 +2841,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" dependencies = [ "serde", "serde_spanned", @@ -2842,9 +2862,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.5" +version = "0.19.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7082a95d48029677a28f181e5f6422d0c8339ad8396a39d3f33d62a90c1f6c30" +checksum = "dc18466501acd8ac6a3f615dd29a3438f8ca6bb3b19537138b3106e575621274" dependencies = [ "indexmap", "serde", @@ -2880,7 +2900,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2926,9 +2946,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-bidi" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c" +checksum = "7d502c968c6a838ead8e69b2ee18ec708802f99db92a0d156705ec9ef801993b" [[package]] name = "unicode-ident" @@ -3070,7 +3090,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -3104,7 +3124,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3182,9 +3202,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -3197,51 +3217,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "winnow" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" +checksum = "23d020b441f92996c80d94ae9166e8501e59c7bb56121189dc9eab3bd8216966" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 05c0c336..7cd3cc59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "feroxbuster" -version = "2.9.1" +version = "2.9.2" authors = ["Ben 'epi' Risher (@epi052)"] license = "MIT" edition = "2021" @@ -62,7 +62,7 @@ self_update = {version = "0.36.0", features = ["archive-tar", "compression-flate tempfile = "3.3.0" httpmock = "0.6.6" assert_cmd = "2.0.4" -predicates = "2.1.1" +predicates = "3.0.1" [profile.release] lto = true diff --git a/shell_completions/_feroxbuster b/shell_completions/_feroxbuster index 5231d203..04c7d580 100644 --- a/shell_completions/_feroxbuster +++ b/shell_completions/_feroxbuster @@ -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.9.1)]:USER_AGENT: ' \ -'--user-agent=[Sets the User-Agent (default: feroxbuster/2.9.1)]:USER_AGENT: ' \ +'-a+[Sets the User-Agent (default: feroxbuster/2.9.2)]:USER_AGENT: ' \ +'--user-agent=[Sets the User-Agent (default: feroxbuster/2.9.2)]: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: ' \ @@ -62,8 +62,8 @@ _feroxbuster() { '--parallel=[Run parallel feroxbuster instances (one child process per url passed via stdin)]:PARALLEL_SCANS: ' \ '(--auto-tune)--rate-limit=[Limit number of requests per second (per directory) (default: 0, i.e. no limit)]:RATE_LIMIT: ' \ '--time-limit=[Limit total run time of all scans (ex: --time-limit 10m)]:TIME_SPEC: ' \ -'-w+[Path to the wordlist]:FILE:_files' \ -'--wordlist=[Path to the wordlist]:FILE:_files' \ +'-w+[Path or URL of the wordlist]:FILE:_files' \ +'--wordlist=[Path or URL of the wordlist]:FILE:_files' \ '*-I+[File extension(s) to Ignore while collecting extensions (only used with --collect-extensions)]:FILE_EXTENSION: ' \ '*--dont-collect=[File extension(s) to Ignore while collecting extensions (only used with --collect-extensions)]:FILE_EXTENSION: ' \ '-o+[Output file to write results to (use w/ --json for JSON entries)]:FILE:_files' \ @@ -72,7 +72,7 @@ _feroxbuster() { '(-u --url)--stdin[Read url(s) from STDIN]' \ '(-p --proxy -k --insecure --burp-replay)--burp[Set --proxy to http://127.0.0.1:8080 and set --insecure to true]' \ '(-P --replay-proxy -k --insecure)--burp-replay[Set --replay-proxy to http://127.0.0.1:8080 and set --insecure to true]' \ -'(--rate-limit --auto-bail)--smart[Set --extract-links, --auto-tune, --collect-words, and --collect-backups to true]' \ +'(--rate-limit --auto-bail)--smart[Set --auto-tune, --collect-words, and --collect-backups to true]' \ '(--rate-limit --auto-bail)--thorough[Use the same settings as --smart and set --collect-extensions to true]' \ '-A[Use a random User-Agent]' \ '--random-agent[Use a random User-Agent]' \ @@ -85,8 +85,9 @@ _feroxbuster() { '-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]' \ +'-e[Extract links from response body (html, javascript, etc...); make new requests based on findings (default: true)]' \ +'--extract-links[Extract links from response body (html, javascript, etc...); make new requests based on findings (default: true)]' \ +'--dont-extract-links[Don'\''t extract links from response body (html, javascript, etc...)]' \ '(--auto-bail)--auto-tune[Automatically lower scan rate when an excessive amount of errors are encountered]' \ '--auto-bail[Automatically stop scanning when an excessive amount of errors are encountered]' \ '-D[Don'\''t auto-filter wildcard responses]' \ diff --git a/shell_completions/_feroxbuster.ps1 b/shell_completions/_feroxbuster.ps1 index b76f590c..aa141b2c 100644 --- a/shell_completions/_feroxbuster.ps1 +++ b/shell_completions/_feroxbuster.ps1 @@ -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.9.1)') - [CompletionResult]::new('--user-agent', 'user-agent', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.9.1)') + [CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.9.2)') + [CompletionResult]::new('--user-agent', 'user-agent', [CompletionResultType]::ParameterName, 'Sets the User-Agent (default: feroxbuster/2.9.2)') [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)') @@ -68,8 +68,8 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock { [CompletionResult]::new('--parallel', 'parallel', [CompletionResultType]::ParameterName, 'Run parallel feroxbuster instances (one child process per url passed via stdin)') [CompletionResult]::new('--rate-limit', 'rate-limit', [CompletionResultType]::ParameterName, 'Limit number of requests per second (per directory) (default: 0, i.e. no limit)') [CompletionResult]::new('--time-limit', 'time-limit', [CompletionResultType]::ParameterName, 'Limit total run time of all scans (ex: --time-limit 10m)') - [CompletionResult]::new('-w', 'w', [CompletionResultType]::ParameterName, 'Path to the wordlist') - [CompletionResult]::new('--wordlist', 'wordlist', [CompletionResultType]::ParameterName, 'Path to the wordlist') + [CompletionResult]::new('-w', 'w', [CompletionResultType]::ParameterName, 'Path or URL of the wordlist') + [CompletionResult]::new('--wordlist', 'wordlist', [CompletionResultType]::ParameterName, 'Path or URL of the wordlist') [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'File extension(s) to Ignore while collecting extensions (only used with --collect-extensions)') [CompletionResult]::new('--dont-collect', 'dont-collect', [CompletionResultType]::ParameterName, 'File extension(s) to Ignore while collecting extensions (only used with --collect-extensions)') [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Output file to write results to (use w/ --json for JSON entries)') @@ -78,7 +78,7 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock { [CompletionResult]::new('--stdin', 'stdin', [CompletionResultType]::ParameterName, 'Read url(s) from STDIN') [CompletionResult]::new('--burp', 'burp', [CompletionResultType]::ParameterName, 'Set --proxy to http://127.0.0.1:8080 and set --insecure to true') [CompletionResult]::new('--burp-replay', 'burp-replay', [CompletionResultType]::ParameterName, 'Set --replay-proxy to http://127.0.0.1:8080 and set --insecure to true') - [CompletionResult]::new('--smart', 'smart', [CompletionResultType]::ParameterName, 'Set --extract-links, --auto-tune, --collect-words, and --collect-backups to true') + [CompletionResult]::new('--smart', 'smart', [CompletionResultType]::ParameterName, 'Set --auto-tune, --collect-words, and --collect-backups to true') [CompletionResult]::new('--thorough', 'thorough', [CompletionResultType]::ParameterName, 'Use the same settings as --smart and set --collect-extensions to true') [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Use a random User-Agent') [CompletionResult]::new('--random-agent', 'random-agent', [CompletionResultType]::ParameterName, 'Use a random User-Agent') @@ -91,8 +91,9 @@ Register-ArgumentCompleter -Native -CommandName 'feroxbuster' -ScriptBlock { [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('-e', 'e', [CompletionResultType]::ParameterName, 'Extract links from response body (html, javascript, etc...); make new requests based on findings (default: true)') + [CompletionResult]::new('--extract-links', 'extract-links', [CompletionResultType]::ParameterName, 'Extract links from response body (html, javascript, etc...); make new requests based on findings (default: true)') + [CompletionResult]::new('--dont-extract-links', 'dont-extract-links', [CompletionResultType]::ParameterName, 'Don''t extract links from response body (html, javascript, etc...)') [CompletionResult]::new('--auto-tune', 'auto-tune', [CompletionResultType]::ParameterName, 'Automatically lower scan rate when an excessive amount of errors are encountered') [CompletionResult]::new('--auto-bail', 'auto-bail', [CompletionResultType]::ParameterName, 'Automatically stop scanning when an excessive amount of errors are encountered') [CompletionResult]::new('-D', 'D', [CompletionResultType]::ParameterName, 'Don''t auto-filter wildcard responses') diff --git a/shell_completions/feroxbuster.bash b/shell_completions/feroxbuster.bash index fea85cf5..143aebfc 100644 --- a/shell_completions/feroxbuster.bash +++ b/shell_completions/feroxbuster.bash @@ -19,7 +19,7 @@ _feroxbuster() { case "${cmd}" in feroxbuster) - opts="-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 -U -h -V --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 --update --help --version" + opts="-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 -U -h -V --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 --dont-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 --update --help --version" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/shell_completions/feroxbuster.elv b/shell_completions/feroxbuster.elv index 6dbdd180..c0594e2f 100644 --- a/shell_completions/feroxbuster.elv +++ b/shell_completions/feroxbuster.elv @@ -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.9.1)' - cand --user-agent 'Sets the User-Agent (default: feroxbuster/2.9.1)' + cand -a 'Sets the User-Agent (default: feroxbuster/2.9.2)' + cand --user-agent 'Sets the User-Agent (default: feroxbuster/2.9.2)' 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)' @@ -65,8 +65,8 @@ set edit:completion:arg-completer[feroxbuster] = {|@words| cand --parallel 'Run parallel feroxbuster instances (one child process per url passed via stdin)' cand --rate-limit 'Limit number of requests per second (per directory) (default: 0, i.e. no limit)' cand --time-limit 'Limit total run time of all scans (ex: --time-limit 10m)' - cand -w 'Path to the wordlist' - cand --wordlist 'Path to the wordlist' + cand -w 'Path or URL of the wordlist' + cand --wordlist 'Path or URL of the wordlist' cand -I 'File extension(s) to Ignore while collecting extensions (only used with --collect-extensions)' cand --dont-collect 'File extension(s) to Ignore while collecting extensions (only used with --collect-extensions)' cand -o 'Output file to write results to (use w/ --json for JSON entries)' @@ -75,7 +75,7 @@ set edit:completion:arg-completer[feroxbuster] = {|@words| cand --stdin 'Read url(s) from STDIN' cand --burp 'Set --proxy to http://127.0.0.1:8080 and set --insecure to true' cand --burp-replay 'Set --replay-proxy to http://127.0.0.1:8080 and set --insecure to true' - cand --smart 'Set --extract-links, --auto-tune, --collect-words, and --collect-backups to true' + cand --smart 'Set --auto-tune, --collect-words, and --collect-backups to true' cand --thorough 'Use the same settings as --smart and set --collect-extensions to true' cand -A 'Use a random User-Agent' cand --random-agent 'Use a random User-Agent' @@ -88,8 +88,9 @@ set edit:completion:arg-completer[feroxbuster] = {|@words| 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 -e 'Extract links from response body (html, javascript, etc...); make new requests based on findings (default: true)' + cand --extract-links 'Extract links from response body (html, javascript, etc...); make new requests based on findings (default: true)' + cand --dont-extract-links 'Don''t extract links from response body (html, javascript, etc...)' cand --auto-tune 'Automatically lower scan rate when an excessive amount of errors are encountered' cand --auto-bail 'Automatically stop scanning when an excessive amount of errors are encountered' cand -D 'Don''t auto-filter wildcard responses' diff --git a/src/config/container.rs b/src/config/container.rs index 5bebe2fe..d6186724 100644 --- a/src/config/container.rs +++ b/src/config/container.rs @@ -1,6 +1,7 @@ use super::utils::{ - depth, ignored_extensions, methods, report_and_exit, save_state, serialized_type, status_codes, - threads, timeout, user_agent, wordlist, OutputLevel, RequesterPolicy, + depth, extract_links, ignored_extensions, methods, report_and_exit, save_state, + serialized_type, status_codes, threads, timeout, user_agent, wordlist, OutputLevel, + RequesterPolicy, }; use crate::config::determine_output_level; use crate::config::utils::determine_requester_policy; @@ -214,7 +215,7 @@ pub struct Configuration { pub no_recursion: bool, /// Extract links from html/javscript - #[serde(default)] + #[serde(default = "extract_links")] pub extract_links: bool, /// Append / to each request @@ -328,6 +329,7 @@ impl Default for Configuration { let kind = serialized_type(); let output_level = OutputLevel::Default; let requester_policy = RequesterPolicy::Default; + let extract_links = extract_links(); Configuration { kind, @@ -336,6 +338,7 @@ impl Default for Configuration { user_agent, replay_codes, status_codes, + extract_links, replay_client, requester_policy, dont_filter: false, @@ -355,7 +358,6 @@ impl Default for Configuration { insecure: false, redirects: false, no_recursion: false, - extract_links: false, random_agent: false, collect_extensions: false, collect_backups: false, @@ -398,7 +400,7 @@ impl Configuration { /// /// - **timeout**: `5` seconds /// - **redirects**: `false` - /// - **extract-links**: `false` + /// - **extract_links**: `true` /// - **wordlist**: [`DEFAULT_WORDLIST`](constant.DEFAULT_WORDLIST.html) /// - **config**: `None` /// - **threads**: `50` @@ -807,11 +809,8 @@ impl Configuration { config.add_slash = true; } - if came_from_cli!(args, "extract_links") - || came_from_cli!(args, "smart") - || came_from_cli!(args, "thorough") - { - config.extract_links = true; + if came_from_cli!(args, "dont_extract_links") { + config.extract_links = false; } if came_from_cli!(args, "json") { @@ -997,7 +996,7 @@ impl Configuration { 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.extract_links, new.extract_links, extract_links()); update_if_not_default!(&mut conf.extensions, new.extensions, Vec::::new()); update_if_not_default!(&mut conf.methods, new.methods, methods()); update_if_not_default!(&mut conf.data, new.data, Vec::::new()); diff --git a/src/config/tests.rs b/src/config/tests.rs index 778ece4e..7af9ee8a 100644 --- a/src/config/tests.rs +++ b/src/config/tests.rs @@ -45,7 +45,7 @@ fn setup_config_test() -> Configuration { add_slash = true stdin = true dont_filter = true - extract_links = true + extract_links = false json = true save_state = false depth = 1 @@ -98,7 +98,7 @@ fn default_configuration() { assert!(!config.add_slash); assert!(!config.force_recursion); assert!(!config.redirects); - assert!(!config.extract_links); + assert!(config.extract_links); assert!(!config.insecure); assert!(!config.collect_extensions); assert!(!config.collect_backups); @@ -305,7 +305,7 @@ fn config_reads_add_slash() { /// parse the test config and see that the value parsed is correct fn config_reads_extract_links() { let config = setup_config_test(); - assert!(config.extract_links); + assert!(!config.extract_links); } #[test] diff --git a/src/config/utils.rs b/src/config/utils.rs index 594e98a5..e45c0ea6 100644 --- a/src/config/utils.rs +++ b/src/config/utils.rs @@ -84,6 +84,11 @@ pub(super) fn depth() -> usize { 4 } +/// default extract links +pub(super) fn extract_links() -> bool { + true +} + /// enum representing the three possible states for informational output (not logging verbosity) #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum OutputLevel { diff --git a/src/main.rs b/src/main.rs index 6a79211a..58350ddd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -237,19 +237,50 @@ async fn wrapped_main(config: Arc) -> Result<()> { exit(0); } - // 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 = 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); + let words = if config.wordlist.starts_with("http") { + // found a url scheme, attempt to download the wordlist + let response = config.client.get(&config.wordlist).send().await?; + + if !response.status().is_success() { + // status code isn't a 200, bail + bail!( + "[{}] Unable to download wordlist from url: {}", + response.status().as_str(), + config.wordlist + ); + } + + // attempt to get the filename from the url's path + let Some(path_segments) = response + .url() + .path_segments() else { + bail!("Unable to parse path from url: {}", response.url()); + }; + + let Some(filename) = path_segments.last() else { + bail!("Unable to parse filename from url's path: {}", response.url().path()); + }; + + let filename = filename.to_string(); + + // read the body and write it to disk, then use existing code to read the wordlist + let body = response.text().await?; + + std::fs::write(&filename, body)?; + + get_unique_words_from_wordlist(&filename)? + } else { + 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); + } } } }; diff --git a/src/parser.rs b/src/parser.rs index 2dc726d7..fbacdbe9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -92,8 +92,9 @@ pub fn initialize() -> Command { .num_args(0) .help_heading("Composite settings") .conflicts_with_all(["rate_limit", "auto_bail"]) - .help("Set --extract-links, --auto-tune, --collect-words, and --collect-backups to true"), - ).arg( + .help("Set --auto-tune, --collect-words, and --collect-backups to true"), + ) + .arg( Arg::new("thorough") .long("thorough") .num_args(0) @@ -433,7 +434,15 @@ pub fn initialize() -> Command { .long("extract-links") .num_args(0) .help_heading("Scan settings") - .help("Extract links from response body (html, javascript, etc...); make new requests based on findings") + .hide(true) + .help("Extract links from response body (html, javascript, etc...); make new requests based on findings (default: true)") + ) + .arg( + Arg::new("dont_extract_links") + .long("dont-extract-links") + .num_args(0) + .help_heading("Scan settings") + .help("Don't extract links from response body (html, javascript, etc...)") ) .arg( Arg::new("scan_limit") @@ -477,7 +486,7 @@ pub fn initialize() -> Command { .long("wordlist") .value_hint(ValueHint::FilePath) .value_name("FILE") - .help("Path to the wordlist") + .help("Path or URL of the wordlist") .help_heading("Scan settings") .num_args(1), ).arg( @@ -515,7 +524,8 @@ pub fn initialize() -> Command { .num_args(0) .help_heading("Dynamic collection settings") .help("Automatically request likely backup extensions for \"found\" urls") - ).arg( + ) + .arg( Arg::new("collect_words") .short('g') .long("collect-words") @@ -684,9 +694,6 @@ EXAMPLES: Pass auth token via query parameter ./feroxbuster -u http://127.1 --query token=0123456789ABCDEF - Find links in javascript/html and make additional requests based on results - ./feroxbuster -u http://127.1 --extract-links - Ludicrous speed... go! ./feroxbuster -u http://127.1 --threads 200 diff --git a/src/scan_manager/tests.rs b/src/scan_manager/tests.rs index 88626c4c..b0d039ca 100644 --- a/src/scan_manager/tests.rs +++ b/src/scan_manager/tests.rs @@ -469,7 +469,7 @@ fn feroxstates_feroxserialize_implementation() { r#""headers""#, r#""queries":[]"#, r#""no_recursion":false"#, - r#""extract_links":false"#, + r#""extract_links":true"#, r#""add_slash":false"#, r#""stdin":false"#, r#""depth":4"#, diff --git a/tests/test_main.rs b/tests/test_main.rs index 6db6a603..370d4f6c 100644 --- a/tests/test_main.rs +++ b/tests/test_main.rs @@ -218,3 +218,46 @@ fn main_parallel_creates_output_directory() -> Result<(), Box Result<(), Box> { + let srv = MockServer::start(); + + let (tmp_dir, _) = setup_tmp_directory(&["a".to_string()], "wordlist")?; + + let mock1 = srv.mock(|when, then| { + when.method(GET).path("/derp"); + then.status(200).body("stuff\nthings"); + }); + + // serve endpoints stuff and things + let mock2 = srv.mock(|when, then| { + when.method(GET).path("/stuff"); + then.status(200); + }); + + let mock3 = srv.mock(|when, then| { + when.method(GET).path("/things"); + then.status(200); + }); + + Command::cargo_bin("feroxbuster") + .unwrap() + .current_dir(&tmp_dir) + .arg("--url") + .arg(srv.url("/")) + .arg("--wordlist") + .arg(srv.url("/derp")) + .assert() + .success() + .stderr(predicate::str::contains(srv.url("/derp"))); + + teardown_tmp_directory(tmp_dir); + + assert_eq!(mock1.hits(), 1); // downloaded wordlist + assert_eq!(mock2.hits(), 1); // found stuff from wordlist + assert_eq!(mock3.hits(), 1); // found things from wordlist + + Ok(()) +}