Codebase list feroxbuster / upstream/2.3.3
New upstream version 2.3.3 Sophie Brun 2 years ago
26 changed file(s) with 529 addition(s) and 326 deletion(s). Raw diff Collapse all Expand all
2121
2222 [[package]]
2323 name = "anyhow"
24 version = "1.0.41"
25 source = "registry+https://github.com/rust-lang/crates.io-index"
26 checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
24 version = "1.0.43"
25 source = "registry+https://github.com/rust-lang/crates.io-index"
26 checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf"
2727
2828 [[package]]
2929 name = "ascii-canvas"
4646
4747 [[package]]
4848 name = "assert_cmd"
49 version = "1.0.5"
50 source = "registry+https://github.com/rust-lang/crates.io-index"
51 checksum = "a88b6bd5df287567ffdf4ddf4d33060048e1068308e5f62d81c6f9824a045a48"
49 version = "2.0.0"
50 source = "registry+https://github.com/rust-lang/crates.io-index"
51 checksum = "54f002ce7d0c5e809ebb02be78fd503aeed4a511fd0fcaff6e6914cbdabbfa33"
5252 dependencies = [
5353 "bstr",
5454 "doc-comment",
101101
102102 [[package]]
103103 name = "async-io"
104 version = "1.4.1"
105 source = "registry+https://github.com/rust-lang/crates.io-index"
106 checksum = "4bbfd5cf2794b1e908ea8457e6c45f8f8f1f6ec5f74617bf4662623f47503c3b"
104 version = "1.6.0"
105 source = "registry+https://github.com/rust-lang/crates.io-index"
106 checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b"
107107 dependencies = [
108108 "concurrent-queue",
109 "fastrand",
110109 "futures-lite",
111110 "libc",
112111 "log",
148147
149148 [[package]]
150149 name = "async-process"
151 version = "1.1.0"
152 source = "registry+https://github.com/rust-lang/crates.io-index"
153 checksum = "a8f38756dd9ac84671c428afbf7c9f7495feff9ec5b0710f17100098e5b354ac"
150 version = "1.2.0"
151 source = "registry+https://github.com/rust-lang/crates.io-index"
152 checksum = "b21b63ab5a0db0369deb913540af2892750e42d949faacc7a61495ac418a1692"
154153 dependencies = [
155154 "async-io",
156155 "blocking",
199198
200199 [[package]]
201200 name = "async-trait"
202 version = "0.1.50"
203 source = "registry+https://github.com/rust-lang/crates.io-index"
204 checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722"
201 version = "0.1.51"
202 source = "registry+https://github.com/rust-lang/crates.io-index"
203 checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
205204 dependencies = [
206205 "proc-macro2",
207206 "quote",
314313
315314 [[package]]
316315 name = "cc"
317 version = "1.0.68"
318 source = "registry+https://github.com/rust-lang/crates.io-index"
319 checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
316 version = "1.0.69"
317 source = "registry+https://github.com/rust-lang/crates.io-index"
318 checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
320319
321320 [[package]]
322321 name = "cfg-if"
432431
433432 [[package]]
434433 name = "ctrlc"
435 version = "3.1.9"
436 source = "registry+https://github.com/rust-lang/crates.io-index"
437 checksum = "232295399409a8b7ae41276757b5a1cc21032848d42bff2352261f958b3ca29a"
434 version = "3.2.0"
435 source = "registry+https://github.com/rust-lang/crates.io-index"
436 checksum = "377c9b002a72a0b2c1a18c62e2f3864bdfea4a015e3683a96e24aa45dd6c02d1"
438437 dependencies = [
439438 "nix",
440439 "winapi",
457456
458457 [[package]]
459458 name = "curl-sys"
460 version = "0.4.44+curl-7.77.0"
461 source = "registry+https://github.com/rust-lang/crates.io-index"
462 checksum = "4b6d85e9322b193f117c966e79c2d6929ec08c02f339f950044aba12e20bbaf1"
459 version = "0.4.45+curl-7.78.0"
460 source = "registry+https://github.com/rust-lang/crates.io-index"
461 checksum = "de9e5a72b1c744eb5dd20b2be4d7eb84625070bb5c4ab9b347b70464ab1e62eb"
463462 dependencies = [
464463 "cc",
465464 "libc",
484483 checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
485484
486485 [[package]]
486 name = "difflib"
487 version = "0.4.0"
488 source = "registry+https://github.com/rust-lang/crates.io-index"
489 checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
490
491 [[package]]
487492 name = "dirs"
488493 version = "3.0.2"
489494 source = "registry+https://github.com/rust-lang/crates.io-index"
562567
563568 [[package]]
564569 name = "env_logger"
565 version = "0.8.4"
566 source = "registry+https://github.com/rust-lang/crates.io-index"
567 checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
570 version = "0.9.0"
571 source = "registry+https://github.com/rust-lang/crates.io-index"
572 checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
568573 dependencies = [
569574 "atty",
570575 "humantime",
581586
582587 [[package]]
583588 name = "fastrand"
584 version = "1.4.1"
585 source = "registry+https://github.com/rust-lang/crates.io-index"
586 checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb"
589 version = "1.5.0"
590 source = "registry+https://github.com/rust-lang/crates.io-index"
591 checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e"
587592 dependencies = [
588593 "instant",
589594 ]
590595
591596 [[package]]
592597 name = "feroxbuster"
593 version = "2.3.1"
598 version = "2.3.3"
594599 dependencies = [
595600 "anyhow",
596601 "assert_cmd",
629634
630635 [[package]]
631636 name = "float-cmp"
632 version = "0.8.0"
633 source = "registry+https://github.com/rust-lang/crates.io-index"
634 checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4"
637 version = "0.9.0"
638 source = "registry+https://github.com/rust-lang/crates.io-index"
639 checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
635640 dependencies = [
636641 "num-traits",
637642 ]
669674
670675 [[package]]
671676 name = "futures"
672 version = "0.3.15"
673 source = "registry+https://github.com/rust-lang/crates.io-index"
674 checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27"
677 version = "0.3.16"
678 source = "registry+https://github.com/rust-lang/crates.io-index"
679 checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b"
675680 dependencies = [
676681 "futures-channel",
677682 "futures-core",
684689
685690 [[package]]
686691 name = "futures-channel"
687 version = "0.3.15"
688 source = "registry+https://github.com/rust-lang/crates.io-index"
689 checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2"
692 version = "0.3.16"
693 source = "registry+https://github.com/rust-lang/crates.io-index"
694 checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9"
690695 dependencies = [
691696 "futures-core",
692697 "futures-sink",
694699
695700 [[package]]
696701 name = "futures-core"
697 version = "0.3.15"
698 source = "registry+https://github.com/rust-lang/crates.io-index"
699 checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1"
702 version = "0.3.16"
703 source = "registry+https://github.com/rust-lang/crates.io-index"
704 checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99"
700705
701706 [[package]]
702707 name = "futures-executor"
703 version = "0.3.15"
704 source = "registry+https://github.com/rust-lang/crates.io-index"
705 checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79"
708 version = "0.3.16"
709 source = "registry+https://github.com/rust-lang/crates.io-index"
710 checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c"
706711 dependencies = [
707712 "futures-core",
708713 "futures-task",
711716
712717 [[package]]
713718 name = "futures-io"
714 version = "0.3.15"
715 source = "registry+https://github.com/rust-lang/crates.io-index"
716 checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1"
719 version = "0.3.16"
720 source = "registry+https://github.com/rust-lang/crates.io-index"
721 checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582"
717722
718723 [[package]]
719724 name = "futures-lite"
732737
733738 [[package]]
734739 name = "futures-macro"
735 version = "0.3.15"
736 source = "registry+https://github.com/rust-lang/crates.io-index"
737 checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121"
740 version = "0.3.16"
741 source = "registry+https://github.com/rust-lang/crates.io-index"
742 checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57"
738743 dependencies = [
739744 "autocfg",
740745 "proc-macro-hack",
745750
746751 [[package]]
747752 name = "futures-sink"
748 version = "0.3.15"
749 source = "registry+https://github.com/rust-lang/crates.io-index"
750 checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282"
753 version = "0.3.16"
754 source = "registry+https://github.com/rust-lang/crates.io-index"
755 checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53"
751756
752757 [[package]]
753758 name = "futures-task"
754 version = "0.3.15"
755 source = "registry+https://github.com/rust-lang/crates.io-index"
756 checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae"
759 version = "0.3.16"
760 source = "registry+https://github.com/rust-lang/crates.io-index"
761 checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2"
757762
758763 [[package]]
759764 name = "futures-util"
760 version = "0.3.15"
761 source = "registry+https://github.com/rust-lang/crates.io-index"
762 checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967"
765 version = "0.3.16"
766 source = "registry+https://github.com/rust-lang/crates.io-index"
767 checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78"
763768 dependencies = [
764769 "autocfg",
765770 "futures-channel",
808813
809814 [[package]]
810815 name = "h2"
811 version = "0.3.3"
812 source = "registry+https://github.com/rust-lang/crates.io-index"
813 checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726"
816 version = "0.3.4"
817 source = "registry+https://github.com/rust-lang/crates.io-index"
818 checksum = "d7f3675cfef6a30c8031cf9e6493ebdc3bb3272a3fea3923c4210d1830e6a472"
814819 dependencies = [
815820 "bytes",
816821 "fnv",
827832
828833 [[package]]
829834 name = "hashbrown"
830 version = "0.9.1"
831 source = "registry+https://github.com/rust-lang/crates.io-index"
832 checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
835 version = "0.11.2"
836 source = "registry+https://github.com/rust-lang/crates.io-index"
837 checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
833838
834839 [[package]]
835840 name = "hermit-abi"
836 version = "0.1.18"
837 source = "registry+https://github.com/rust-lang/crates.io-index"
838 checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
841 version = "0.1.19"
842 source = "registry+https://github.com/rust-lang/crates.io-index"
843 checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
839844 dependencies = [
840845 "libc",
841846 ]
853858
854859 [[package]]
855860 name = "http-body"
856 version = "0.4.2"
857 source = "registry+https://github.com/rust-lang/crates.io-index"
858 checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9"
861 version = "0.4.3"
862 source = "registry+https://github.com/rust-lang/crates.io-index"
863 checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5"
859864 dependencies = [
860865 "bytes",
861866 "http",
864869
865870 [[package]]
866871 name = "httparse"
867 version = "1.4.1"
868 source = "registry+https://github.com/rust-lang/crates.io-index"
869 checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68"
872 version = "1.5.1"
873 source = "registry+https://github.com/rust-lang/crates.io-index"
874 checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
870875
871876 [[package]]
872877 name = "httpdate"
876881
877882 [[package]]
878883 name = "httpmock"
879 version = "0.5.8"
880 source = "registry+https://github.com/rust-lang/crates.io-index"
881 checksum = "b217899bcbe8ad3bdee7a46727bd3754b908831462755567852fb20eac585d46"
884 version = "0.6.2"
885 source = "registry+https://github.com/rust-lang/crates.io-index"
886 checksum = "218c2c3dabf4497c87d042b43984a5fd03bcd8a6adb0056ade7df20f88df225a"
882887 dependencies = [
883888 "assert-json-diff",
884889 "async-object-pool",
887892 "basic-cookies",
888893 "crossbeam-utils",
889894 "difference",
895 "form_urlencoded",
890896 "futures-util",
891897 "hyper",
892898 "isahc",
909915
910916 [[package]]
911917 name = "hyper"
912 version = "0.14.9"
913 source = "registry+https://github.com/rust-lang/crates.io-index"
914 checksum = "07d6baa1b441335f3ce5098ac421fb6547c46dda735ca1bc6d0153c838f9dd83"
918 version = "0.14.11"
919 source = "registry+https://github.com/rust-lang/crates.io-index"
920 checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11"
915921 dependencies = [
916922 "bytes",
917923 "futures-channel",
957963
958964 [[package]]
959965 name = "indexmap"
960 version = "1.6.2"
961 source = "registry+https://github.com/rust-lang/crates.io-index"
962 checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
966 version = "1.7.0"
967 source = "registry+https://github.com/rust-lang/crates.io-index"
968 checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
963969 dependencies = [
964970 "autocfg",
965971 "hashbrown",
979985
980986 [[package]]
981987 name = "instant"
982 version = "0.1.9"
983 source = "registry+https://github.com/rust-lang/crates.io-index"
984 checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
988 version = "0.1.10"
989 source = "registry+https://github.com/rust-lang/crates.io-index"
990 checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
985991 dependencies = [
986992 "cfg-if",
987993 ]
988994
989995 [[package]]
990996 name = "ipnet"
991 version = "2.3.0"
992 source = "registry+https://github.com/rust-lang/crates.io-index"
993 checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
997 version = "2.3.1"
998 source = "registry+https://github.com/rust-lang/crates.io-index"
999 checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
9941000
9951001 [[package]]
9961002 name = "isahc"
997 version = "1.4.0"
998 source = "registry+https://github.com/rust-lang/crates.io-index"
999 checksum = "81c01404730bb4574bbacb59ca0855f969f8eabd688ca22866f2cc333f1a4f69"
1003 version = "1.4.1"
1004 source = "registry+https://github.com/rust-lang/crates.io-index"
1005 checksum = "0b183576592898e9e007d41b7cf2bc8bb3f8b5d2733b9291e42618d50040e7ba"
10001006 dependencies = [
10011007 "async-channel",
10021008 "crossbeam-utils",
10351041
10361042 [[package]]
10371043 name = "js-sys"
1038 version = "0.3.51"
1039 source = "registry+https://github.com/rust-lang/crates.io-index"
1040 checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062"
1044 version = "0.3.53"
1045 source = "registry+https://github.com/rust-lang/crates.io-index"
1046 checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d"
10411047 dependencies = [
10421048 "wasm-bindgen",
10431049 ]
11111117
11121118 [[package]]
11131119 name = "libc"
1114 version = "0.2.97"
1115 source = "registry+https://github.com/rust-lang/crates.io-index"
1116 checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
1120 version = "0.2.99"
1121 source = "registry+https://github.com/rust-lang/crates.io-index"
1122 checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
11171123
11181124 [[package]]
11191125 name = "libnghttp2-sys"
11581164
11591165 [[package]]
11601166 name = "matches"
1161 version = "0.1.8"
1162 source = "registry+https://github.com/rust-lang/crates.io-index"
1163 checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
1167 version = "0.1.9"
1168 source = "registry+https://github.com/rust-lang/crates.io-index"
1169 checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
11641170
11651171 [[package]]
11661172 name = "memchr"
1167 version = "2.4.0"
1168 source = "registry+https://github.com/rust-lang/crates.io-index"
1169 checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
1173 version = "2.4.1"
1174 source = "registry+https://github.com/rust-lang/crates.io-index"
1175 checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
1176
1177 [[package]]
1178 name = "memoffset"
1179 version = "0.6.4"
1180 source = "registry+https://github.com/rust-lang/crates.io-index"
1181 checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
1182 dependencies = [
1183 "autocfg",
1184 ]
11701185
11711186 [[package]]
11721187 name = "mime"
11981213
11991214 [[package]]
12001215 name = "native-tls"
1201 version = "0.2.7"
1202 source = "registry+https://github.com/rust-lang/crates.io-index"
1203 checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
1216 version = "0.2.8"
1217 source = "registry+https://github.com/rust-lang/crates.io-index"
1218 checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
12041219 dependencies = [
12051220 "lazy_static",
12061221 "libc",
12221237
12231238 [[package]]
12241239 name = "nix"
1225 version = "0.20.0"
1226 source = "registry+https://github.com/rust-lang/crates.io-index"
1227 checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
1240 version = "0.22.1"
1241 source = "registry+https://github.com/rust-lang/crates.io-index"
1242 checksum = "e7555d6c7164cc913be1ce7f95cbecdabda61eb2ccd89008524af306fb7f5031"
12281243 dependencies = [
12291244 "bitflags",
12301245 "cc",
12311246 "cfg-if",
12321247 "libc",
1248 "memoffset",
12331249 ]
12341250
12351251 [[package]]
12801296
12811297 [[package]]
12821298 name = "openssl"
1283 version = "0.10.34"
1284 source = "registry+https://github.com/rust-lang/crates.io-index"
1285 checksum = "6d7830286ad6a3973c0f1d9b73738f69c76b739301d0229c4b96501695cbe4c8"
1299 version = "0.10.36"
1300 source = "registry+https://github.com/rust-lang/crates.io-index"
1301 checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a"
12861302 dependencies = [
12871303 "bitflags",
12881304 "cfg-if",
13091325
13101326 [[package]]
13111327 name = "openssl-sys"
1312 version = "0.9.63"
1313 source = "registry+https://github.com/rust-lang/crates.io-index"
1314 checksum = "b6b0d6fb7d80f877617dfcb014e605e2b5ab2fb0afdf27935219bb6bd984cb98"
1328 version = "0.9.66"
1329 source = "registry+https://github.com/rust-lang/crates.io-index"
1330 checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82"
13151331 dependencies = [
13161332 "autocfg",
13171333 "cc",
13851401
13861402 [[package]]
13871403 name = "pin-project"
1388 version = "1.0.7"
1389 source = "registry+https://github.com/rust-lang/crates.io-index"
1390 checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4"
1404 version = "1.0.8"
1405 source = "registry+https://github.com/rust-lang/crates.io-index"
1406 checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
13911407 dependencies = [
13921408 "pin-project-internal",
13931409 ]
13941410
13951411 [[package]]
13961412 name = "pin-project-internal"
1397 version = "1.0.7"
1398 source = "registry+https://github.com/rust-lang/crates.io-index"
1399 checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"
1413 version = "1.0.8"
1414 source = "registry+https://github.com/rust-lang/crates.io-index"
1415 checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
14001416 dependencies = [
14011417 "proc-macro2",
14021418 "quote",
14051421
14061422 [[package]]
14071423 name = "pin-project-lite"
1408 version = "0.2.6"
1409 source = "registry+https://github.com/rust-lang/crates.io-index"
1410 checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
1424 version = "0.2.7"
1425 source = "registry+https://github.com/rust-lang/crates.io-index"
1426 checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
14111427
14121428 [[package]]
14131429 name = "pin-utils"
14481464
14491465 [[package]]
14501466 name = "predicates"
1451 version = "1.0.8"
1452 source = "registry+https://github.com/rust-lang/crates.io-index"
1453 checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df"
1454 dependencies = [
1455 "difference",
1467 version = "2.0.2"
1468 source = "registry+https://github.com/rust-lang/crates.io-index"
1469 checksum = "c143348f141cc87aab5b950021bac6145d0e5ae754b0591de23244cee42c9308"
1470 dependencies = [
1471 "difflib",
14561472 "float-cmp",
1473 "itertools",
14571474 "normalize-line-endings",
14581475 "predicates-core",
14591476 "regex",
14671484
14681485 [[package]]
14691486 name = "predicates-tree"
1470 version = "1.0.2"
1471 source = "registry+https://github.com/rust-lang/crates.io-index"
1472 checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2"
1487 version = "1.0.3"
1488 source = "registry+https://github.com/rust-lang/crates.io-index"
1489 checksum = "d7dd0fd014130206c9352efbdc92be592751b2b9274dff685348341082c6ea3d"
14731490 dependencies = [
14741491 "predicates-core",
14751492 "treeline",
14891506
14901507 [[package]]
14911508 name = "proc-macro2"
1492 version = "1.0.27"
1493 source = "registry+https://github.com/rust-lang/crates.io-index"
1494 checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
1509 version = "1.0.28"
1510 source = "registry+https://github.com/rust-lang/crates.io-index"
1511 checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
14951512 dependencies = [
14961513 "unicode-xid",
14971514 ]
15161533
15171534 [[package]]
15181535 name = "rand"
1519 version = "0.8.3"
1520 source = "registry+https://github.com/rust-lang/crates.io-index"
1521 checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
1536 version = "0.8.4"
1537 source = "registry+https://github.com/rust-lang/crates.io-index"
1538 checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
15221539 dependencies = [
15231540 "libc",
15241541 "rand_chacha",
15381555
15391556 [[package]]
15401557 name = "rand_core"
1541 version = "0.6.2"
1542 source = "registry+https://github.com/rust-lang/crates.io-index"
1543 checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
1558 version = "0.6.3"
1559 source = "registry+https://github.com/rust-lang/crates.io-index"
1560 checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
15441561 dependencies = [
15451562 "getrandom",
15461563 ]
15471564
15481565 [[package]]
15491566 name = "rand_hc"
1550 version = "0.3.0"
1551 source = "registry+https://github.com/rust-lang/crates.io-index"
1552 checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
1567 version = "0.3.1"
1568 source = "registry+https://github.com/rust-lang/crates.io-index"
1569 checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
15531570 dependencies = [
15541571 "rand_core",
15551572 ]
15561573
15571574 [[package]]
15581575 name = "redox_syscall"
1559 version = "0.2.8"
1560 source = "registry+https://github.com/rust-lang/crates.io-index"
1561 checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
1576 version = "0.2.10"
1577 source = "registry+https://github.com/rust-lang/crates.io-index"
1578 checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
15621579 dependencies = [
15631580 "bitflags",
15641581 ]
16071624
16081625 [[package]]
16091626 name = "reqwest"
1610 version = "0.11.3"
1611 source = "registry+https://github.com/rust-lang/crates.io-index"
1612 checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124"
1627 version = "0.11.4"
1628 source = "registry+https://github.com/rust-lang/crates.io-index"
1629 checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22"
16131630 dependencies = [
16141631 "base64",
16151632 "bytes",
16421659
16431660 [[package]]
16441661 name = "rlimit"
1645 version = "0.5.4"
1646 source = "registry+https://github.com/rust-lang/crates.io-index"
1647 checksum = "81a9ed03edbed449d6897c2092c71ab5f7b5fb80f6f0b1a3ed6d40a6f9fc0720"
1662 version = "0.6.2"
1663 source = "registry+https://github.com/rust-lang/crates.io-index"
1664 checksum = "cc0bf25554376fd362f54332b8410a625c71f15445bca32ffdfdf4ec9ac91726"
16481665 dependencies = [
16491666 "libc",
16501667 ]
17021719
17031720 [[package]]
17041721 name = "serde"
1705 version = "1.0.126"
1706 source = "registry+https://github.com/rust-lang/crates.io-index"
1707 checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
1722 version = "1.0.127"
1723 source = "registry+https://github.com/rust-lang/crates.io-index"
1724 checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
17081725 dependencies = [
17091726 "serde_derive",
17101727 ]
17111728
17121729 [[package]]
17131730 name = "serde_derive"
1714 version = "1.0.126"
1715 source = "registry+https://github.com/rust-lang/crates.io-index"
1716 checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
1731 version = "1.0.127"
1732 source = "registry+https://github.com/rust-lang/crates.io-index"
1733 checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
17171734 dependencies = [
17181735 "proc-macro2",
17191736 "quote",
17221739
17231740 [[package]]
17241741 name = "serde_json"
1725 version = "1.0.64"
1726 source = "registry+https://github.com/rust-lang/crates.io-index"
1727 checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
1742 version = "1.0.66"
1743 source = "registry+https://github.com/rust-lang/crates.io-index"
1744 checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
17281745 dependencies = [
17291746 "itoa",
17301747 "ryu",
17851802
17861803 [[package]]
17871804 name = "siphasher"
1788 version = "0.3.5"
1789 source = "registry+https://github.com/rust-lang/crates.io-index"
1790 checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27"
1805 version = "0.3.6"
1806 source = "registry+https://github.com/rust-lang/crates.io-index"
1807 checksum = "729a25c17d72b06c68cb47955d44fda88ad2d3e7d77e025663fdd69b93dd71a1"
17911808
17921809 [[package]]
17931810 name = "slab"
1794 version = "0.4.3"
1795 source = "registry+https://github.com/rust-lang/crates.io-index"
1796 checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
1811 version = "0.4.4"
1812 source = "registry+https://github.com/rust-lang/crates.io-index"
1813 checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
17971814
17981815 [[package]]
17991816 name = "sluice"
1800 version = "0.5.4"
1801 source = "registry+https://github.com/rust-lang/crates.io-index"
1802 checksum = "8fa0333a60ff2e3474a6775cc611840c2a55610c831dd366503474c02f1a28f5"
1803 dependencies = [
1804 "futures-channel",
1817 version = "0.5.5"
1818 source = "registry+https://github.com/rust-lang/crates.io-index"
1819 checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5"
1820 dependencies = [
1821 "async-channel",
18051822 "futures-core",
18061823 "futures-io",
18071824 ]
18141831
18151832 [[package]]
18161833 name = "socket2"
1817 version = "0.4.0"
1818 source = "registry+https://github.com/rust-lang/crates.io-index"
1819 checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
1834 version = "0.4.1"
1835 source = "registry+https://github.com/rust-lang/crates.io-index"
1836 checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad"
18201837 dependencies = [
18211838 "libc",
18221839 "winapi",
18421859
18431860 [[package]]
18441861 name = "syn"
1845 version = "1.0.73"
1846 source = "registry+https://github.com/rust-lang/crates.io-index"
1847 checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
1862 version = "1.0.75"
1863 source = "registry+https://github.com/rust-lang/crates.io-index"
1864 checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
18481865 dependencies = [
18491866 "proc-macro2",
18501867 "quote",
19061923
19071924 [[package]]
19081925 name = "thiserror"
1909 version = "1.0.25"
1910 source = "registry+https://github.com/rust-lang/crates.io-index"
1911 checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
1926 version = "1.0.26"
1927 source = "registry+https://github.com/rust-lang/crates.io-index"
1928 checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
19121929 dependencies = [
19131930 "thiserror-impl",
19141931 ]
19151932
19161933 [[package]]
19171934 name = "thiserror-impl"
1918 version = "1.0.25"
1919 source = "registry+https://github.com/rust-lang/crates.io-index"
1920 checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
1935 version = "1.0.26"
1936 source = "registry+https://github.com/rust-lang/crates.io-index"
1937 checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
19211938 dependencies = [
19221939 "proc-macro2",
19231940 "quote",
19351952
19361953 [[package]]
19371954 name = "tinyvec"
1938 version = "1.2.0"
1939 source = "registry+https://github.com/rust-lang/crates.io-index"
1940 checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
1955 version = "1.3.1"
1956 source = "registry+https://github.com/rust-lang/crates.io-index"
1957 checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338"
19411958 dependencies = [
19421959 "tinyvec_macros",
19431960 ]
19501967
19511968 [[package]]
19521969 name = "tokio"
1953 version = "1.6.2"
1954 source = "registry+https://github.com/rust-lang/crates.io-index"
1955 checksum = "aea337f72e96efe29acc234d803a5981cd9a2b6ed21655cd7fc21cfe021e8ec7"
1970 version = "1.10.0"
1971 source = "registry+https://github.com/rust-lang/crates.io-index"
1972 checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b"
19561973 dependencies = [
19571974 "autocfg",
19581975 "bytes",
19701987
19711988 [[package]]
19721989 name = "tokio-macros"
1973 version = "1.2.0"
1974 source = "registry+https://github.com/rust-lang/crates.io-index"
1975 checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37"
1990 version = "1.3.0"
1991 source = "registry+https://github.com/rust-lang/crates.io-index"
1992 checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110"
19761993 dependencies = [
19771994 "proc-macro2",
19781995 "quote",
20032020
20042021 [[package]]
20052022 name = "tokio-stream"
2006 version = "0.1.6"
2007 source = "registry+https://github.com/rust-lang/crates.io-index"
2008 checksum = "f8864d706fdb3cc0843a49647ac892720dac98a6eeb818b77190592cf4994066"
2023 version = "0.1.7"
2024 source = "registry+https://github.com/rust-lang/crates.io-index"
2025 checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
20092026 dependencies = [
20102027 "futures-core",
20112028 "pin-project-lite",
20672084
20682085 [[package]]
20692086 name = "tracing-core"
2070 version = "0.1.18"
2071 source = "registry+https://github.com/rust-lang/crates.io-index"
2072 checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052"
2087 version = "0.1.19"
2088 source = "registry+https://github.com/rust-lang/crates.io-index"
2089 checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8"
20732090 dependencies = [
20742091 "lazy_static",
20752092 ]
20982115
20992116 [[package]]
21002117 name = "unicode-bidi"
2101 version = "0.3.5"
2102 source = "registry+https://github.com/rust-lang/crates.io-index"
2103 checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0"
2104 dependencies = [
2105 "matches",
2106 ]
2118 version = "0.3.6"
2119 source = "registry+https://github.com/rust-lang/crates.io-index"
2120 checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085"
21072121
21082122 [[package]]
21092123 name = "unicode-normalization"
21592173
21602174 [[package]]
21612175 name = "vcpkg"
2162 version = "0.2.13"
2163 source = "registry+https://github.com/rust-lang/crates.io-index"
2164 checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa"
2176 version = "0.2.15"
2177 source = "registry+https://github.com/rust-lang/crates.io-index"
2178 checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
21652179
21662180 [[package]]
21672181 name = "vec_map"
22082222
22092223 [[package]]
22102224 name = "wasm-bindgen"
2211 version = "0.2.74"
2212 source = "registry+https://github.com/rust-lang/crates.io-index"
2213 checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
2225 version = "0.2.76"
2226 source = "registry+https://github.com/rust-lang/crates.io-index"
2227 checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0"
22142228 dependencies = [
22152229 "cfg-if",
22162230 "serde",
22202234
22212235 [[package]]
22222236 name = "wasm-bindgen-backend"
2223 version = "0.2.74"
2224 source = "registry+https://github.com/rust-lang/crates.io-index"
2225 checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900"
2237 version = "0.2.76"
2238 source = "registry+https://github.com/rust-lang/crates.io-index"
2239 checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041"
22262240 dependencies = [
22272241 "bumpalo",
22282242 "lazy_static",
22352249
22362250 [[package]]
22372251 name = "wasm-bindgen-futures"
2238 version = "0.4.24"
2239 source = "registry+https://github.com/rust-lang/crates.io-index"
2240 checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1"
2252 version = "0.4.26"
2253 source = "registry+https://github.com/rust-lang/crates.io-index"
2254 checksum = "95fded345a6559c2cfee778d562300c581f7d4ff3edb9b0d230d69800d213972"
22412255 dependencies = [
22422256 "cfg-if",
22432257 "js-sys",
22472261
22482262 [[package]]
22492263 name = "wasm-bindgen-macro"
2250 version = "0.2.74"
2251 source = "registry+https://github.com/rust-lang/crates.io-index"
2252 checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4"
2264 version = "0.2.76"
2265 source = "registry+https://github.com/rust-lang/crates.io-index"
2266 checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef"
22532267 dependencies = [
22542268 "quote",
22552269 "wasm-bindgen-macro-support",
22572271
22582272 [[package]]
22592273 name = "wasm-bindgen-macro-support"
2260 version = "0.2.74"
2261 source = "registry+https://github.com/rust-lang/crates.io-index"
2262 checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97"
2274 version = "0.2.76"
2275 source = "registry+https://github.com/rust-lang/crates.io-index"
2276 checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad"
22632277 dependencies = [
22642278 "proc-macro2",
22652279 "quote",
22702284
22712285 [[package]]
22722286 name = "wasm-bindgen-shared"
2273 version = "0.2.74"
2274 source = "registry+https://github.com/rust-lang/crates.io-index"
2275 checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
2287 version = "0.2.76"
2288 source = "registry+https://github.com/rust-lang/crates.io-index"
2289 checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29"
22762290
22772291 [[package]]
22782292 name = "web-sys"
2279 version = "0.3.51"
2280 source = "registry+https://github.com/rust-lang/crates.io-index"
2281 checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582"
2293 version = "0.3.53"
2294 source = "registry+https://github.com/rust-lang/crates.io-index"
2295 checksum = "224b2f6b67919060055ef1a67807367c2066ed520c3862cc013d26cf893a783c"
22822296 dependencies = [
22832297 "js-sys",
22842298 "wasm-bindgen",
00 [package]
11 name = "feroxbuster"
2 version = "2.3.1"
2 version = "2.3.3"
33 authors = ["Ben 'epi' Risher <[email protected]>"]
44 license = "MIT"
55 edition = "2018"
2121 dirs = "3.0"
2222
2323 [dependencies]
24 futures = { version = "0.3.14"}
25 tokio = { version = "1.6", features = ["full"] }
24 futures = { version = "0.3"}
25 tokio = { version = "1.10", features = ["full"] }
2626 tokio-util = {version = "0.6.6", features = ["codec"]}
2727 log = "0.4"
28 env_logger = "0.8"
28 env_logger = "0.9"
2929 reqwest = { version = "0.11", features = ["socks"] }
3030 clap = "2.33"
3131 lazy_static = "1.4"
3232 toml = "0.5"
3333 serde = { version = "1.0", features = ["derive", "rc"] }
34 serde_json = "1.0.64"
34 serde_json = "1.0"
3535 uuid = { version = "0.8", features = ["v4"] }
3636 indicatif = "0.15"
3737 console = "0.14"
3939 dirs = "3.0"
4040 regex = "1"
4141 crossterm = "0.20"
42 rlimit = "0.5.4"
43 ctrlc = "3.1.9"
42 rlimit = "0.6"
43 ctrlc = "3.2"
4444 fuzzyhash = "0.2.1"
4545 anyhow = "1.0"
4646 leaky-bucket = "0.10.0"
4747
4848 [dev-dependencies]
4949 tempfile = "3.1"
50 httpmock = "0.5.8"
51 assert_cmd = "1.0"
52 predicates = "1.0.8"
50 httpmock = "0.6.2"
51 assert_cmd = "2.0"
52 predicates = "2.0"
5353
5454 [profile.release]
5555 lto = true
303303 - verbosity: `0` (no logging enabled)
304304 - scan_limit: `0` (no limit imposed on concurrent scans)
305305 - rate_limit: `0` (no limit imposed on requests per second)
306 - status_codes: `200 204 301 302 307 308 401 403 405`
306 - status_codes: `200 204 301 302 307 308 401 403 405 500`
307307 - user_agent: `feroxbuster/VERSION`
308308 - recursion depth: `4`
309309 - auto-filter wildcards - `true`
555555 Limit total number of concurrent scans (default: 0, i.e. no limit)
556556
557557 -s, --status-codes <STATUS_CODE>...
558 Status Codes to include (allow list) (default: 200 204 301 302 307 308 401 403 405)
558 Status Codes to include (allow list) (default: 200 204 301 302 307 308 401 403 405 500)
559559
560560 -t, --threads <THREADS>
561561 Number of concurrent threads (default: 50)
10001000 cat large-target-list | ./feroxbuster --stdin --parallel 10 --extract-links --auto-bail
10011001 ```
10021002
1003 Resuling Process List (illustrative):
1003 Resulting Process List (illustrative):
10041004 ```
10051005 feroxbuster --stdin --parallel 10
10061006 \_ feroxbuster --silent --extract-links --auto-bail -u https://target-one
10081008 \_ feroxbuster --silent --extract-links --auto-bail -u https://target-three
10091009 \_ ...
10101010 \_ feroxbuster --silent --extract-links --auto-bail -u https://target-ten
1011 ```
1012
1013 As of `v2.3.2`, logging while using `--parallel` uses the value of `-o`|`--output` as a seed to create a directory named `OUTPUT_VALUE-TIMESTAMP.logs/`. Within the directory, an individual log file is created for each target passed over stdin.
1014
1015 Example Command:
1016 ```
1017 cat large-target-list | ./feroxbuster --stdin --parallel 10 --output super-cool-mega-scan
1018 ```
1019
1020 Resulting directory structure (illustrative):
1021 ```
1022 super-cool-mega-scan-1627865696.logs/
1023 ├── ferox-https_target_one_com-1627865696.log
1024 ├── ...
1025 └── ferox-https_target_two_net-1627865696.log
10111026 ```
10121027
10131028 ### Prevent Specific Domain/Directory Scans aka a Deny List (new in `v2.3.0`)
164164 }
165165
166166 for denied_url in &config.url_denylist {
167 url_denylist.push(BannerEntry::new("🚫", "Don't Scan", &denied_url));
167 url_denylist.push(BannerEntry::new("🚫", "Don't Scan", denied_url));
168168 }
169169
170170 let mut codes = vec![];
33 scan_manager::{FeroxState, PAUSE_SCAN},
44 scanner::RESPONSES,
55 statistics::StatError,
6 utils::slugify_filename,
67 utils::{open_file, write_to},
78 SLEEP_DURATION,
89 };
1617 },
1718 thread::sleep,
1819 time::Duration,
19 time::{SystemTime, UNIX_EPOCH},
2020 };
2121
2222 /// Atomic boolean flag, used to determine whether or not the terminal input handler should exit
7676 pub fn sigint_handler(handles: Arc<Handles>) -> Result<()> {
7777 log::trace!("enter: sigint_handler({:?})", handles);
7878
79 let ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
80
81 let slug = if !handles.config.target_url.is_empty() {
79 let filename = if !handles.config.target_url.is_empty() {
8280 // target url populated
83 handles
84 .config
85 .target_url
86 .replace("://", "_")
87 .replace("/", "_")
88 .replace(".", "_")
81 slugify_filename(&handles.config.target_url, "ferox", "state")
8982 } else {
9083 // stdin used
91 "stdin".to_string()
84 slugify_filename("stdin", "ferox", "state")
9285 };
9386
94 let filename = format!("ferox-{}-{}.state", slug, ts);
9587 let warning = format!(
9688 "🚨 Caught {} 🚨 saving scan state to {} ...",
9789 style("ctrl+c").yellow(),
212212 // should be replayed; not using logged_request due to replay proxy client
213213 make_request(
214214 self.config.replay_client.as_ref().unwrap(),
215 &resp.url(),
215 resp.url(),
216216 self.config.output_level,
217217 tx_stats.clone(),
218218 )
148148
149149 let body = self.response.unwrap().text();
150150
151 for capture in self.links_regex.captures_iter(&body) {
151 for capture in self.links_regex.captures_iter(body) {
152152 // remove single & double quotes from both ends of the capture
153153 // capture[0] is the entire match, additional capture groups start at [1]
154154 let link = capture[0].trim_matches(|c| c == '\'' || c == '"');
274274 };
275275
276276 let new_url = old_url
277 .join(&link)
277 .join(link)
278278 .with_context(|| format!("Could not join {} with {}", old_url, link))?;
279279
280280 links.insert(new_url.to_string());
296296 pub(super) async fn request_link(&self, url: &str) -> Result<FeroxResponse> {
297297 log::trace!("enter: request_link({})", url);
298298
299 let ferox_url = FeroxUrl::from_string(&url, self.handles.clone());
299 let ferox_url = FeroxUrl::from_string(url, self.handles.clone());
300300
301301 // create a url based on the given command line options
302 let new_url = ferox_url.format(&"", None)?;
302 let new_url = ferox_url.format("", None)?;
303303
304304 let scanned_urls = self.handles.ferox_scans()?;
305305
350350 if let Some(new_path) = capture.name("url_path") {
351351 let mut new_url = Url::parse(&self.url)?;
352352 new_url.set_path(new_path.as_str());
353 if self.add_all_sub_paths(&new_url.path(), &mut links).is_err() {
353 if self.add_all_sub_paths(new_url.path(), &mut links).is_err() {
354354 log::warn!("could not add sub-paths from {} to {:?}", new_url, links);
355355 }
356356 }
5353 /// in the expected array
5454 fn extractor_get_sub_paths_from_path_with_multiple_paths() {
5555 let path = "homepage/assets/img/icons/handshake.svg";
56 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(&path);
57 let b_paths = BODY_EXT.get_sub_paths_from_path(&path);
56 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(path);
57 let b_paths = BODY_EXT.get_sub_paths_from_path(path);
5858 let expected = vec![
5959 "homepage/",
6060 "homepage/assets/",
7777 /// returned
7878 fn extractor_get_sub_paths_from_path_with_enclosing_slashes() {
7979 let path = "/homepage/assets/";
80 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(&path);
81 let b_paths = BODY_EXT.get_sub_paths_from_path(&path);
80 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(path);
81 let b_paths = BODY_EXT.get_sub_paths_from_path(path);
8282 let expected = vec!["homepage/", "homepage/assets"];
8383
8484 assert_eq!(r_paths.len(), expected.len());
9494 /// included
9595 fn extractor_get_sub_paths_from_path_with_only_a_word() {
9696 let path = "homepage";
97 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(&path);
98 let b_paths = BODY_EXT.get_sub_paths_from_path(&path);
97 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(path);
98 let b_paths = BODY_EXT.get_sub_paths_from_path(path);
9999 let expected = vec!["homepage"];
100100
101101 assert_eq!(r_paths.len(), expected.len());
110110 /// extract sub paths from the given url fragment; expect 1 sub path, forward slash removed
111111 fn extractor_get_sub_paths_from_path_with_an_absolute_word() {
112112 let path = "/homepage";
113 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(&path);
114 let b_paths = BODY_EXT.get_sub_paths_from_path(&path);
113 let r_paths = ROBOTS_EXT.get_sub_paths_from_path(path);
114 let b_paths = BODY_EXT.get_sub_paths_from_path(path);
115115 let expected = vec!["homepage"];
116116
117117 assert_eq!(r_paths.len(), expected.len());
4040 if let Ok(filters) = self.filters.lock() {
4141 for filter in filters.iter() {
4242 // wildcard.should_filter goes here
43 if filter.should_filter_response(&response) {
43 if filter.should_filter_response(response) {
4444 if filter.as_any().downcast_ref::<WildcardFilter>().is_some() {
4545 tx_stats
4646 .send(AddToUsizeField(WildcardsFiltered, 1))
5555 // add any regex filters to filters handler's FeroxFilters (-X|--filter-regex)
5656 for regex_filter in &handles.config.filter_regex {
5757 let raw = regex_filter;
58 let compiled = skip_fail!(Regex::new(&raw));
58 let compiled = skip_fail!(Regex::new(raw));
5959
6060 let filter = RegexFilter {
6161 raw_string: raw.to_owned(),
6868 // add any similarity filters to filters handler's FeroxFilters (--filter-similar-to)
6969 for similarity_filter in &handles.config.filter_similar {
7070 // url as-is based on input, ignores user-specified url manipulation options (add-slash etc)
71 let url = skip_fail!(Url::parse(&similarity_filter));
71 let url = skip_fail!(Url::parse(similarity_filter));
7272
7373 // attempt to request the given url
7474 let resp = skip_fail!(logged_request(&url, handles.clone()).await);
127127 }
128128
129129 #[test]
130 /// test should_filter on WilcardFilter where static logic matches but response length is 0
131 fn wildcard_should_filter_when_static_wildcard_len_is_zero() {
132 let mut resp = FeroxResponse::default();
133 resp.set_wildcard(true);
134 resp.set_url("http://localhost");
135
136 // default WildcardFilter is used in the code that executes when response.content_length() == 0
137 let filter = WildcardFilter::new(false);
138
139 assert!(filter.should_filter_response(&resp));
140 }
141
142 #[test]
130143 /// test should_filter on WilcardFilter where dynamic logic matches
131144 fn wildcard_should_filter_when_dynamic_wildcard_found() {
132145 let mut resp = FeroxResponse::default();
6767 return true;
6868 }
6969
70 if self.size == u64::MAX && response.content_length() == 0 {
71 // static wildcard size found during testing
72 // but response length was zero; pointed out by @Tib3rius
73 log::debug!("static wildcard: filtered out {}", response.url());
74 log::trace!("exit: should_filter_response -> true");
75 return true;
76 }
77
7078 if self.dynamic != u64::MAX {
7179 // dynamic wildcard offset found during testing
7280
7583 // except that I don't want an empty string taking up the last index in the
7684 // event that the url ends with a forward slash. It's ugly enough to be split
7785 // into its own function for readability.
78 let url_len = FeroxUrl::path_length_of_url(&response.url());
86 let url_len = FeroxUrl::path_length_of_url(response.url());
7987
8088 if url_len + self.dynamic == response.content_length() {
8189 log::debug!("dynamic wildcard: filtered out {}", response.url());
206206 let mut good_urls = vec![];
207207
208208 for target_url in target_urls {
209 let url = FeroxUrl::from_string(&target_url, self.handles.clone());
209 let url = FeroxUrl::from_string(target_url, self.handles.clone());
210210 let request = skip_fail!(url.format("", None));
211211
212212 let result = logged_request(&request, self.handles.clone()).await;
4242 pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION");
4343
4444 /// Maximum number of file descriptors that can be opened during a scan
45 pub const DEFAULT_OPEN_FILE_LIMIT: usize = 8192;
45 pub const DEFAULT_OPEN_FILE_LIMIT: u64 = 8192;
4646
4747 /// Default value used to determine near-duplicate web pages (equivalent to 95%)
4848 pub const SIMILARITY_THRESHOLD: u32 = 95;
7272 /// * 401 Unauthorized
7373 /// * 403 Forbidden
7474 /// * 405 Method Not Allowed
75 pub const DEFAULT_STATUS_CODES: [StatusCode; 9] = [
75 /// * 500 Internal Server Error
76 pub const DEFAULT_STATUS_CODES: [StatusCode; 10] = [
7677 StatusCode::OK,
7778 StatusCode::NO_CONTENT,
7879 StatusCode::MOVED_PERMANENTLY,
8283 StatusCode::UNAUTHORIZED,
8384 StatusCode::FORBIDDEN,
8485 StatusCode::METHOD_NOT_ALLOWED,
86 StatusCode::INTERNAL_SERVER_ERROR,
8587 ];
8688
8789 /// Default filename for config file settings
00 use std::{
11 env::args,
2 fs::File,
2 fs::{create_dir, remove_file, File},
33 io::{stderr, BufRead, BufReader},
44 ops::Index,
5 path::Path,
56 process::Command,
67 sync::{atomic::Ordering, Arc},
78 };
2627 progress::{PROGRESS_BAR, PROGRESS_PRINTER},
2728 scan_manager::{self},
2829 scanner,
29 utils::fmt_err,
30 utils::{fmt_err, slugify_filename},
3031 };
3132 #[cfg(not(target_os = "windows"))]
3233 use feroxbuster::{utils::set_open_file_limit, DEFAULT_OPEN_FILE_LIMIT};
266267 // from removing --parallel)
267268 original.remove(parallel_index);
268269
270 // to log unique files to a shared folder, we need to first check for the presence
271 // of -o|--output.
272 let out_dir = if !config.output.is_empty() {
273 // -o|--output was used, so we'll attempt to create a directory to store the files
274 let output_path = Path::new(&handles.config.output);
275
276 // this only returns None if the path terminates in `..`. Since I don't want to
277 // hand-hold to that degree, we'll unwrap and fail if the output path ends in `..`
278 let base_name = output_path.file_name().unwrap();
279
280 let new_folder = slugify_filename(&base_name.to_string_lossy(), "", "logs");
281
282 let final_path = output_path.with_file_name(&new_folder);
283
284 // create the directory or fail silently, assuming the reason for failure is that
285 // the path exists already
286 create_dir(&final_path).unwrap_or(());
287
288 final_path.to_string_lossy().to_string()
289 } else {
290 String::new()
291 };
292
269293 // unvalidated targets fresh from stdin, just spawn children and let them do all checks
270294 for target in targets {
271295 // add the current target to the provided command
272296 let mut cloned = original.clone();
297
298 if !out_dir.is_empty() {
299 // output directory value is not empty, need to join output directory with
300 // unique scan filename
301
302 // unwrap is ok, we already know -o was used
303 let out_idx = original
304 .iter()
305 .position(|s| *s == "--output" || *s == "-o")
306 .unwrap();
307
308 let filename = slugify_filename(&target, "ferox", "log");
309
310 let full_path = Path::new(&out_dir)
311 .join(filename)
312 .to_string_lossy()
313 .to_string();
314
315 // a +1 to the index is fine here, as clap has already validated that
316 // -o|--output has a value associated with it
317 cloned[out_idx + 1] = full_path;
318 }
319
273320 cloned.push("-u".to_string());
274321 cloned.push(target);
275322
293340 });
294341 }
295342
343 // the output handler creates an empty file to which it will try to write, because
344 // this happens before we enter the --parallel branch, we need to remove that file
345 // if it's empty
346 let output = handles.config.output.to_owned();
347
296348 clean_up(handles, tasks).await?;
349
350 let file = Path::new(&output);
351 if file.exists() {
352 // expectation is that this is always true for the first ferox process
353 if file.metadata()?.len() == 0 {
354 // empty file, attempt to remove it
355 remove_file(file)?;
356 }
357 }
297358
298359 log::trace!("exit: parallel branch && wrapped main");
299360 return Ok(());
5050
5151 progress_bar.set_style(style);
5252
53 progress_bar.set_prefix(&prefix);
53 progress_bar.set_prefix(prefix);
5454
5555 progress_bar
5656 }
120120
121121 /// Set `FeroxResponse`'s `url` attribute, has no affect if an error occurs
122122 pub fn set_url(&mut self, url: &str) {
123 match Url::parse(&url) {
123 match Url::parse(url) {
124124 Ok(url) => {
125125 self.url = url;
126126 }
338338 lines,
339339 words,
340340 chars,
341 status_colorizer(&status),
341 status_colorizer(status),
342342 self.url(),
343343 FeroxUrl::path_length_of_url(&self.url)
344344 );
430430 OutputLevel::Silent => BarType::Hidden,
431431 };
432432
433 let progress_bar = add_bar(&url, bar_length, bar_type);
433 let progress_bar = add_bar(url, bar_length, bar_type);
434434
435435 progress_bar.reset_elapsed();
436436
440440 };
441441
442442 let ferox_scan = FeroxScan::new(
443 &url,
443 url,
444444 scan_type,
445445 scan_order,
446446 bar_length,
461461 ///
462462 /// Also return a reference to the new `FeroxScan`
463463 pub fn add_directory_scan(&self, url: &str, scan_order: ScanOrder) -> (bool, Arc<FeroxScan>) {
464 self.add_scan(&url, ScanType::Directory, scan_order)
464 self.add_scan(url, ScanType::Directory, scan_order)
465465 }
466466
467467 /// Given a url, create a new `FeroxScan` and add it to `FeroxScans` as a File Scan
470470 ///
471471 /// Also return a reference to the new `FeroxScan`
472472 pub fn add_file_scan(&self, url: &str, scan_order: ScanOrder) -> (bool, Arc<FeroxScan>) {
473 self.add_scan(&url, ScanType::File, scan_order)
473 self.add_scan(url, ScanType::File, scan_order)
474474 }
475475
476476 /// small helper to determine whether any scans are active or not
378378
379379 let json_state = ferox_state.as_json().unwrap();
380380 let expected = format!(
381 r#"{{"scans":[{{"id":"{}","url":"https://spiritanimal.com","scan_type":"Directory","status":"NotStarted","num_requests":0}}],"config":{{"type":"configuration","wordlist":"/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt","config":"","proxy":"","replay_proxy":"","target_url":"","status_codes":[200,204,301,302,307,308,401,403,405],"replay_codes":[200,204,301,302,307,308,401,403,405],"filter_status":[],"threads":50,"timeout":7,"verbosity":0,"silent":false,"quiet":false,"auto_bail":false,"auto_tune":false,"json":false,"output":"","debug_log":"","user_agent":"feroxbuster/{}","redirects":false,"insecure":false,"extensions":[],"headers":{{}},"queries":[],"no_recursion":false,"extract_links":false,"add_slash":false,"stdin":false,"depth":4,"scan_limit":0,"parallel":0,"rate_limit":0,"filter_size":[],"filter_line_count":[],"filter_word_count":[],"filter_regex":[],"dont_filter":false,"resumed":false,"resume_from":"","save_state":false,"time_limit":"","filter_similar":[],"url_denylist":[]}},"responses":[{{"type":"response","url":"https://nerdcore.com/css","path":"/css","wildcard":true,"status":301,"content_length":173,"line_count":10,"word_count":16,"headers":{{"server":"nginx/1.16.1"}}}}]"#,
381 r#"{{"scans":[{{"id":"{}","url":"https://spiritanimal.com","scan_type":"Directory","status":"NotStarted","num_requests":0}}],"config":{{"type":"configuration","wordlist":"/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt","config":"","proxy":"","replay_proxy":"","target_url":"","status_codes":[200,204,301,302,307,308,401,403,405,500],"replay_codes":[200,204,301,302,307,308,401,403,405,500],"filter_status":[],"threads":50,"timeout":7,"verbosity":0,"silent":false,"quiet":false,"auto_bail":false,"auto_tune":false,"json":false,"output":"","debug_log":"","user_agent":"feroxbuster/{}","redirects":false,"insecure":false,"extensions":[],"headers":{{}},"queries":[],"no_recursion":false,"extract_links":false,"add_slash":false,"stdin":false,"depth":4,"scan_limit":0,"parallel":0,"rate_limit":0,"filter_size":[],"filter_line_count":[],"filter_word_count":[],"filter_regex":[],"dont_filter":false,"resumed":false,"resume_from":"","save_state":false,"time_limit":"","filter_similar":[],"url_denylist":[]}},"responses":[{{"type":"response","url":"https://nerdcore.com/css","path":"/css","wildcard":true,"status":301,"content_length":173,"line_count":10,"word_count":16,"headers":{{"server":"nginx/1.16.1"}}}}]"#,
382382 saved_id, VERSION
383383 );
384384 println!("{}\n{}", expected, json_state);
619619 atomic_increment!(self.expected_per_scan, value);
620620 }
621621 StatField::TotalScans => {
622 let multiplier = self.num_extensions.max(1);
623
624622 atomic_increment!(self.total_scans, value);
625623 atomic_increment!(
626624 self.total_expected,
627 value * self.expected_per_scan.load(Ordering::Relaxed) * multiplier
625 value * self.expected_per_scan.load(Ordering::Relaxed)
628626 );
629627 }
630628 StatField::TotalExpected => {
5454 stats.add_status_code(StatusCode::OK);
5555 stats.add_status_code(StatusCode::OK);
5656 let outfile = NamedTempFile::new().unwrap();
57 if stats
58 .save(174.33, &outfile.path().to_str().unwrap())
59 .is_ok()
60 {}
57 if stats.save(174.33, outfile.path().to_str().unwrap()).is_ok() {}
6158
6259 assert!(stats.as_json().unwrap().contains("statistics"));
6360 assert!(stats.as_json().unwrap().contains("11")); // requests made
6565 pub fn format(&self, word: &str, extension: Option<&str>) -> Result<Url> {
6666 log::trace!("enter: format({}, {:?})", word, extension);
6767
68 if Url::parse(&word).is_ok() {
68 if Url::parse(word).is_ok() {
6969 // when a full url is passed in as a word to be joined to a base url using
7070 // reqwest::Url::join, the result is that the word (url) completely overwrites the base
7171 // url, potentially resulting in requests to places that aren't actually the target
22 use indicatif::ProgressBar;
33 use reqwest::{Client, Response, StatusCode, Url};
44 #[cfg(not(target_os = "windows"))]
5 use rlimit::{getrlimit, setrlimit, Resource, Rlim};
5 use rlimit::{getrlimit, setrlimit, Resource};
66 use std::{
77 fs,
88 io::{self, BufWriter, Write},
99 sync::Arc,
10 time::Duration,
11 time::{SystemTime, UNIX_EPOCH},
1012 };
1113 use tokio::sync::mpsc::UnboundedSender;
1214
216218 /// as the adjustment made here is only valid for the scan itself (and any child processes, of which
217219 /// there are none).
218220 #[cfg(not(target_os = "windows"))]
219 pub fn set_open_file_limit(limit: usize) -> bool {
221 pub fn set_open_file_limit(limit: u64) -> bool {
220222 log::trace!("enter: set_open_file_limit");
221223
222224 if let Ok((soft, hard)) = getrlimit(Resource::NOFILE) {
223 if hard.as_usize() > limit {
225 if hard > limit {
224226 // our default open file limit is less than the current hard limit, this means we can
225227 // set the soft limit to our default
226 let new_soft_limit = Rlim::from_usize(limit);
227
228 if setrlimit(Resource::NOFILE, new_soft_limit, hard).is_ok() {
228
229 if setrlimit(Resource::NOFILE, limit, hard).is_ok() {
229230 log::debug!("set open file descriptor limit to {}", limit);
230231
231232 log::trace!("exit: set_open_file_limit -> {}", true);
297298 );
298299 // normalization for comparison is to remove the trailing / if one exists, this is done for
299300 // the given url and any url to which it's compared
300 let normed_url = Url::parse(&url.to_string().trim_end_matches('/'))?;
301 let normed_url = Url::parse(url.to_string().trim_end_matches('/'))?;
301302
302303 for deny_url in &handles.config.url_denylist {
303304 // parse the denying url for easier comparison
384385 Ok(false)
385386 }
386387
388 /// given a url and filename-suffix, return a unique filename comprised of the slugified url,
389 /// current unix timestamp and suffix
390 ///
391 /// ex: ferox-http_telsa_com-1606947491.state
392 pub fn slugify_filename(url: &str, prefix: &str, suffix: &str) -> String {
393 log::trace!("enter: slugify({:?}, {:?}, {:?})", url, prefix, suffix);
394
395 let ts = SystemTime::now()
396 .duration_since(UNIX_EPOCH)
397 .unwrap_or_else(|_| Duration::from_secs(0))
398 .as_secs();
399
400 let altered_prefix = if !prefix.is_empty() {
401 format!("{}-", prefix)
402 } else {
403 String::new()
404 };
405
406 let slug = url.replace("://", "_").replace("/", "_").replace(".", "_");
407
408 let filename = format!("{}{}-{}.{}", altered_prefix, slug, ts, suffix);
409
410 log::trace!("exit: slugify -> {}", filename);
411 filename
412 }
413
387414 #[cfg(test)]
388415 mod tests {
389416 use super::*;
394421 /// set_open_file_limit with a low requested limit succeeds
395422 fn utils_set_open_file_limit_with_low_requested_limit() {
396423 let (_, hard) = getrlimit(Resource::NOFILE).unwrap();
397 let lower_limit = hard.as_usize() - 1;
424 let lower_limit = hard - 1;
398425 assert!(set_open_file_limit(lower_limit));
399426 }
400427
402429 /// set_open_file_limit with a high requested limit succeeds
403430 fn utils_set_open_file_limit_with_high_requested_limit() {
404431 let (_, hard) = getrlimit(Resource::NOFILE).unwrap();
405 let higher_limit = hard.as_usize() + 1;
432 let higher_limit = hard + 1;
406433 // calculate a new soft to ensure soft != hard and hit that logic branch
407 let new_soft = Rlim::from_usize(hard.as_usize() - 1);
434 let new_soft = hard - 1;
408435 setrlimit(Resource::NOFILE, new_soft, hard).unwrap();
409436 assert!(set_open_file_limit(higher_limit));
410437 }
415442 let (_, hard) = getrlimit(Resource::NOFILE).unwrap();
416443 // calculate a new soft to ensure soft == hard and hit the failure logic branch
417444 setrlimit(Resource::NOFILE, hard, hard).unwrap();
418 assert!(!set_open_file_limit(hard.as_usize())); // returns false
445 assert!(!set_open_file_limit(hard)); // returns false
419446 }
420447
421448 #[test]
475502 let tested_url = Url::parse("https://testdomain.com/denied/").unwrap();
476503
477504 let scans = Arc::new(FeroxScans::default());
478 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
505 scans.add_directory_scan(scan_url, ScanOrder::Initial);
479506
480507 let mut config = Configuration::new().unwrap();
481508 config.url_denylist = vec![String::from(deny_url)];
494521 let tested_url = Url::parse("https://testdomain.com/denied/").unwrap();
495522
496523 let scans = Arc::new(FeroxScans::default());
497 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
524 scans.add_directory_scan(scan_url, ScanOrder::Initial);
498525
499526 let mut config = Configuration::new().unwrap();
500527 config.url_denylist = vec![String::from(deny_url)];
513540 let tested_url = Url::parse("https://testdomain.com/denied/").unwrap();
514541
515542 let scans = Arc::new(FeroxScans::default());
516 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
543 scans.add_directory_scan(scan_url, ScanOrder::Initial);
517544
518545 let mut config = Configuration::new().unwrap();
519546 config.url_denylist = vec![String::from(deny_url)];
534561 let tested_url = Url::parse("https://testdomain.com/denied/").unwrap();
535562
536563 let scans = Arc::new(FeroxScans::default());
537 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
564 scans.add_directory_scan(scan_url, ScanOrder::Initial);
538565
539566 let mut config = Configuration::new().unwrap();
540567 config.url_denylist = vec![String::from(deny_url)];
555582 let tested_url = Url::parse("https://testdomain.com/denied/").unwrap();
556583
557584 let scans = Arc::new(FeroxScans::default());
558 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
585 scans.add_directory_scan(scan_url, ScanOrder::Initial);
559586
560587 let mut config = Configuration::new().unwrap();
561588 config.url_denylist = vec![String::from(deny_url)];
574601 let tested_url = Url::parse("https://testdomain.com/api/denied/").unwrap();
575602
576603 let scans = Arc::new(FeroxScans::default());
577 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
604 scans.add_directory_scan(scan_url, ScanOrder::Initial);
578605
579606 let mut config = Configuration::new().unwrap();
580607 config.url_denylist = vec![String::from(deny_url)];
593620 let tested_url = Url::parse("https://testdomain.com/not-denied/").unwrap();
594621
595622 let scans = Arc::new(FeroxScans::default());
596 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
623 scans.add_directory_scan(scan_url, ScanOrder::Initial);
597624
598625 let mut config = Configuration::new().unwrap();
599626 config.url_denylist = vec![String::from(deny_url)];
612639 let tested_url = Url::parse("https://testdomain.com/stuff/").unwrap();
613640
614641 let scans = Arc::new(FeroxScans::default());
615 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
642 scans.add_directory_scan(scan_url, ScanOrder::Initial);
616643
617644 let mut config = Configuration::new().unwrap();
618645 config.url_denylist = vec![String::from(deny_url)];
631658 let tested_url = Url::parse("https://testdomain.com/api/not-denied/").unwrap();
632659
633660 let scans = Arc::new(FeroxScans::default());
634 scans.add_directory_scan(&scan_url, ScanOrder::Initial);
661 scans.add_directory_scan(scan_url, ScanOrder::Initial);
635662
636663 let mut config = Configuration::new().unwrap();
637664 config.url_denylist = vec![String::from(deny_url)];
22 use httpmock::Method::GET;
33 use httpmock::{MockServer, Regex};
44 use predicates::prelude::*;
5 use std::fs::read_to_string;
5 use std::fs::{read_dir, read_to_string};
66 use utils::{setup_tmp_directory, teardown_tmp_directory};
77
88 #[test]
152152
153153 Ok(())
154154 }
155
156 #[test]
157 /// send three targets over stdin with --output enabled, expect parallel to create a new directory
158 /// and the log files therein
159 fn main_parallel_creates_output_directory() -> Result<(), Box<dyn std::error::Error>> {
160 let t1 = MockServer::start();
161 let t2 = MockServer::start();
162 let t3 = MockServer::start();
163
164 let words = [
165 String::from("LICENSE"),
166 String::from("stuff"),
167 String::from("things"),
168 String::from("mostuff"),
169 String::from("mothings"),
170 ];
171 let (word_tmp_dir, wordlist) = setup_tmp_directory(&words, "wordlist")?;
172 let (output_dir, outfile) = setup_tmp_directory(&[], "output-file")?;
173 let (tgt_tmp_dir, targets) =
174 setup_tmp_directory(&[t1.url("/"), t2.url("/"), t3.url("/")], "targets")?;
175
176 Command::cargo_bin("feroxbuster")
177 .unwrap()
178 .arg("--stdin")
179 .arg("--parallel")
180 .arg("2")
181 .arg("--output")
182 .arg(outfile.as_os_str())
183 .arg("--wordlist")
184 .arg(wordlist.as_os_str())
185 .pipe_stdin(targets)
186 .unwrap()
187 .assert()
188 .success()
189 .stderr(
190 predicate::str::contains("Could not connect to any target provided")
191 .and(predicate::str::contains("Target Url"))
192 .not(), // no target url found
193 );
194
195 // output_dir should return something similar to output-file-1627845244.logs with the
196 // line below. if it ever fails, can use the regex below to filter out the right directory
197 let sub_dir = read_dir(&output_dir)?.next().unwrap()?.file_name();
198
199 let mut num_logs = 0;
200 let file_regex = Regex::new("ferox-[a-zA-Z_:0-9]+-[0-9]+.log").unwrap();
201 let dir_regex = Regex::new("output-file-[0-9]+.logs").unwrap();
202
203 let sub_dir = output_dir.as_ref().join(&sub_dir);
204
205 // created directory like output-file-1627845741.logs/
206 assert!(dir_regex.is_match(&sub_dir.to_string_lossy().to_string()));
207
208 for entry in sub_dir.read_dir()? {
209 let entry = entry?;
210 // created each file like ferox-https_localhost-1627845741.log
211 println!("name: {:?}", entry.file_name().to_string_lossy());
212 assert!(file_regex.is_match(&entry.file_name().to_string_lossy()));
213 num_logs += 1;
214 }
215
216 // should be 3 log files total
217 assert_eq!(num_logs, 3);
218
219 teardown_tmp_directory(word_tmp_dir);
220 teardown_tmp_directory(tgt_tmp_dir);
221 teardown_tmp_directory(output_dir);
222
223 Ok(())
224 }
7676
7777 // read debug log to get the number of errors enforced
7878 for line in debug_log.lines() {
79 let log: serde_json::Value = serde_json::from_str(&line).unwrap_or_default();
79 let log: serde_json::Value = serde_json::from_str(line).unwrap_or_default();
8080 if let Some(message) = log.get("message") {
8181 let str_msg = message.as_str().unwrap_or_default().to_string();
8282
155155
156156 // read debug log to get the number of errors enforced
157157 for line in debug_log.lines() {
158 let log: serde_json::Value = serde_json::from_str(&line).unwrap_or_default();
158 let log: serde_json::Value = serde_json::from_str(line).unwrap_or_default();
159159 if let Some(message) = log.get("message") {
160160 let str_msg = message.as_str().unwrap_or_default().to_string();
161161
237237
238238 // read debug log to get the number of errors enforced
239239 for line in debug_log.lines() {
240 let log: serde_json::Value = serde_json::from_str(&line).unwrap_or_default();
240 let log: serde_json::Value = serde_json::from_str(line).unwrap_or_default();
241241 if let Some(message) = log.get("message") {
242242 let str_msg = message.as_str().unwrap_or_default().to_string();
243243
9292 #[test]
9393 /// kick off scan with a time limit;
9494 fn time_limit_enforced_when_specified() {
95 let srv = MockServer::start();
95 let t1 = MockServer::start();
96 let t2 = MockServer::start();
97
9698 let (tmp_dir, file) =
9799 setup_tmp_directory(&["css".to_string(), "stuff".to_string()], "wordlist").unwrap();
100 let (tgt_tmp_dir, targets) =
101 setup_tmp_directory(&[t1.url("/"), t2.url("/")], "targets").unwrap();
98102
99103 // ensure the command will run long enough by adding crap to the wordlist
100104 let more_words = read_to_string(Path::new("tests/extra-words")).unwrap();
108112
109113 Command::cargo_bin("feroxbuster")
110114 .unwrap()
111 .arg("--url")
112 .arg(srv.url("/"))
115 .arg("--stdin")
113116 .arg("--wordlist")
114117 .arg(file.as_os_str())
115118 .arg("--time-limit")
116119 .arg("5s")
120 .pipe_stdin(targets)
121 .unwrap()
117122 .assert()
118123 .failure();
119124
126131 assert!(now.elapsed() > lower_bound && now.elapsed() < upper_bound);
127132
128133 teardown_tmp_directory(tmp_dir);
134 teardown_tmp_directory(tgt_tmp_dir);
129135 }