TL; DR
კლასტერი ხუთი npm პაკეტი, გამოქვეყნდა ორი ანგარიშის სახელურზე, გაიგზავნა postinstall კაუჭი, რომელიც ჰოსტისგან კითხულობს ღრუბლოვან სერთიფიკატებს და აგზავნის მათ ყუთიდან. პაკეტებს აქვთ მოჩვენებითი და მეკობრული სახელები — coral-wraith, ecto-corsair-whisper-6f3b9, ecto-corsair-flag-x9m4, ecto-rust-read-f3a9c1, ecto-nightly-spirit — და ყველაფერს, რასაც აგროვებენ, სერიალიზებულად აქცევენ ყალბ ფაილად ecto_module: YAML მანიფესტი მის გადაცემამდე. ჩვენ ვაკვირდებით კლასტერს, როგორც ექტოპლაზმა.
დატვირთვა მხოლოდ მაშინ ირთვება, როდესაც ის აღმოაჩენს კონკრეტულ გარემოს: ჰოსტს, რომლის სახელიც არის 12-სიმბოლოიანი თექვსმეტობითი სტრიქონი და სამუშაო დირექტორია ქვემოთ /app/node_modules — კონტეინერიზებული შენობის ან CI მუშაკის ფორმა. როდესაც ეს კარიბჭე გაივლის, კაუჭი კითხვებს სვამს AWS ეგზემპლარის მეტამონაცემების სერვისი (IMDSv2) IAM როლის სერთიფიკატებისთვის, ჩამოთვლის AWS Secrets Manager სამ რეგიონში, გარემოს ცვლადების დამპინგი, ფაილების წაკითხვა /appდა ეძებს დროშის დაჭერის სტრიქონებს. შემდეგ ის შედეგს ორი გზით ამუშავებს: შუქურიდან webhook.site კოლექტორი და მანიფესტი PUT raw-IP საბოლოო წერტილისთვის, localhost-first სარეზერვო ვარიანტების სიით.
პაკეტების შემდგომ აღწერილობაში ნათქვამია „CTF დატვირთვა verdaccio-ს მიწოდების ჯაჭვის ტესტირებისთვის“. ჩვენ ამ თვითაღწერას დაკვირვებად ფაქტად ვაცხადებთ. თავად ქცევა — საჯარო IP-ზე პირდაპირი გადასვლა, IMDS-ის რეალური სერთიფიკატების წაკითხვა, Secrets Manager-ის რეალური გამოძახებები — არის ის, რაც არის, მიუხედავად ეტიკეტისა და სწორედ ეს არის მიზეზი, რის გამოც ეს ვერსიები კლასიფიცირდა, როგორც მავნე.
ერთი სახელი კლასტერში, coral-wraith, ერთი გამოცემით არ შემოიფარგლებოდა. ის სწრაფად, ზედიზედ, რამდენიმე საათში ათობით ვერსიით ხელახლა გამოიცა — 1.0.0 ასვლა 6.0.0 — და ამავე სახელწოდების ადრინდელ გამოცემაში გამოყენებული იყო გაბერილი 9999.0.x ვერსიის ნომრები, კლასიკური ფორმა a-ს დამოკიდებულება-დაბნეულობის მცდელობაამ გადატვირთვისას დატვირთვა თვალსაჩინოდ მომწიფდა: ერთჯერადი მასპინძლის ჩამოთვლის შუქურიდან სრულ AWS სერთიფიკატების პივორტად, რომელიც გარემოს შემოწმებებით არის შეფუთული, რაც მას დანიშნულებისამებრ გარეთ ჩუმად ინარჩუნებს.
| პაკეტები | 5 სახელი; coral-wraith მხოლოდ ათობით ვერსიით ხელახლა გამოქვეყნებული |
| ეკოსისტემა | npm |
| ვექტორის ინსტალაცია | postinstall სასიცოცხლო ციკლის სკრიპტი |
| ძირითადი სამიზნე | AWS IAM როლის სერთიფიკატები + Secrets Manager-ის საიდუმლო მნიშვნელობები, გარემოს ცვლადები, /app ფაილი |
| ექსფილი | webhook.site შუქურა + ნედლი-IP C2 PUT |
| ტრიგერის კარიბჭე | 12-თექვსმეტობითი ჰოსტის სახელი + /app/node_modules cwd, პლუს გარემოს შემოწმება, რომელიც თრგუნავს დატვირთვას ამ კონტექსტის გარეთ. |
| სიმძიმის | მაღალი — ღრუბლოვანი სერთიფიკატი და მართული საიდუმლოების გამჟღავნება კონტეინერიზებული აწყობის და გაშვების გარემო |
შეტევის ანატომია
კლასტერში ყველა პაკეტი ერთნაირად არის აგებული: თითქმის ცარიელი index.js (მოდული.ექსპორტი = {}), ერთსტრიქონიანი პაკეტი.json სკრიპტი — „პოსტინგლაინი“: „კვანძი postinstall.js“ — და ტვირთამწეობა პოსტინსტალაცია.jsპაკეტის ინსტალაცია საკმარისია კაუჭის გასაშვებად; იმპორტი ან გამოძახება საჭირო არ არის.
დამიზნების კარიბჭე. ნებისმიერი მოქმედების დაწყებამდე, ექტო-ოჯახის ტვირთი ამოწმებს გარემოს:
function isAppWorker(): host = os.hostname() if host does NOT match /^[0-9a-f]{12}$/ -> exit if cwd does NOT contain "/app/node_modules" -> exit if cwd contains "/tmp/npm-safe" -> exit otherwise -> proceed 12-ჰექსადიანი ჰოსტის სახელი არის სტანდარტული ფორმა, რომელსაც Docker ანიჭებს კონტეინერს და /app/node_modules არის ჩვეულებრივი კონტეინერში ინსტალაციის გზა. მესამე პუნქტი იხსნება, თუ გზა ჰგავს sandboxed ამოღების დირექტორიას. საბოლოო შედეგი ის არის, რომ დატვირთვა რჩება უმოქმედო დეველოპერის ლეპტოპზე ან ანალიზის sandbox-ზე და აქტიურდება მხოლოდ კონტეინერიზებულ build-ში ან runtime worker-ში — გარემოში, რომელიც, სავარაუდოდ, ინახავს live cloud credentials-ს. კლასტერში ყველაზე ადრეული პაკეტი, მარჯნის მოჩვენება, ასეთი კარიბჭე არ აქვს და თავის (უფრო მარტივ) კოლექციას უპირობოდ მართავს.
კოლექციაროდესაც კარიბჭე გაივლის, კაუჭი გამოდის execFileSync("/bin/sh", ["-c", ...]) და ასრულებს ერთ შედგენილ ბრძანებას, რომელიც თანმიმდევრობით:
1. PUT /latest/api/token to 169.254.169.254 (IMDSv2 token request) 2. GET .../iam/security-credentials/ (IAM role name) 3. GET .../iam/security-credentials/<role> (temporary credentials) 4. dump env | sort (environment variables) 5. list /app (excl. node_modules) + cat first 15 (application files) 6. aws secretsmanager list-secrets (us-east-1, eu-west-1, eu-central-1) 7. scrape readable files for HTB{...} (capture-the-flag strings) ნაბიჯები 1–3 წარმოადგენს IMDSv2 სახელმძღვანელოს მოძიების მაგალითს: მოითხოვეთ სესიის ტოკენი, შემდეგ მიამაგრეთ იგი, როგორც X-aws-ec2-მეტადამონაცემების-ტოკენი სათაური ინსტანციის IAM როლისა და ამ როლის დროებითი წვდომის გასაღებების მისაღებად. არჩევანი IMDSv2-ის იმპლემენტაციისა უფრო მარტივი, არაავტორიზებული IMDSv1-ის ნაცვლად. მთავარი აღსანიშნავია — ეს ნიშნავს, რომ დატვირთვა მუშაობს იმ ინსტანციებშიც კი, რომლებიც კონფიგურირებულია ტოკენებზე დაფუძნებული მეტამონაცემების წვდომის მოთხოვნისთვის, რაც AWS-ის მიერ რეკომენდებული გამკაცრების მეთოდია. მე-3 ნაბიჯით დაბრუნებული ავტორიზაციის მონაცემები ხანმოკლეა. AccessKeyId/საიდუმლო წვდომის გასაღები/ჟეტონი სამმაგი მასშტაბები ინსტანციის როლზეა ორიენტირებული; რაც არ უნდა გააკეთოს ამ როლმა, ამ გასაღებების მფლობელს შეუძლია გააკეთოს სერთიფიკატის მთელი სიცოცხლის განმავლობაში.
ნაბიჯები 4–6 აფართოებს ხედვას. env demp აფიქსირებს ყველაფერს, რაც მემკვიდრეობით მიიღო შექმნის ან გაშვების პროცესმა — პრაქტიკაში, სწორედ აქ ინახება რეესტრის ტოკენები, მონაცემთა ბაზის კავშირის სტრიქონები და API გასაღებები. / აპლიკაცია ფაილის გავლა კითხულობს თხუთმეტამდე აპლიკაციის ფაილს გარეთ კვანძის_მოდულები, რომელსაც შეუძლია ზედაპირის კონფიგურაცია, .ენვ ფაილები ან წყარო. ნაბიჯი 6 ზარები aws secretsmanager-ის სიის საიდუმლოებები სამ რეგიონში; 1-3 ნაბიჯებში მოყვანილი ავტორიზაციის მონაცემები სწორედ ისაა, რაც ამ ზარებს ავთენტიფიკაციას უკეთებს, ამიტომ IMDS-ის წაკითხვა და Secrets Manager-ის ჩამოთვლა ერთ ჯაჭვად არის გაერთიანებული: ეგზემპლარის როლი → მართული საიდუმლო ინვენტარი. მე-7 ნაბიჯი დროშის დაჭერის ჩარჩოს მინიშნებაა — როდესაც HTB{…} თუ დროშა იპოვნება, ის დამოუკიდებლად იგზავნება, წინააღმდეგ შემთხვევაში, შეგროვებული ნედლი ნაწილაკი ოთხ ნაწილად იჭრება და იგზავნება.
კლასტერის შემდგომი ვერსიები ესკალაციას კიდევ უფრო აგრძელებენ. ინვენტარზე გაჩერების ნაცვლად, ისინი აანალიზებენ IMDS პასუხს, ექსპორტს უწევენ დროებით გასაღებებს, როგორც AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN გარემოს ცვლადები, დაადასტურეთ იდენტურობა aws sts-ის აბონენტის იდენტობის მიღებადა შემდეგ მიმოიხილოს ყველა საიდუმლო, რომელიც დაბრუნებულია საიდუმლოებების სია მოუწოდებენ aws secretsmanager-ის get-secret-value თითოეულზე — საიდუმლო შინაარსის მოძიება და არა მხოლოდ მათი სახელები. იგივე ვერსიები ასევე კითხულობენ პროცესის მიერ ჩანაცვლებულ დროშის ბინარულ ფაილებს (/readflag და მეგობრები) და სცადეთ ტვირთის გადაზიდვა ნებისმიერი Rust პროექტის წინააღმდეგ, რომელიც აღმოჩენილია / აპლიკაცია, რაც აფართოებს მოსავალს ღრუბლოვანი მონაცემების მიღმა, ნებისმიერ საკითხში, რომელსაც შექმნის გარემო გამოავლენს.
ეს გვიანდელი ვერსიები ასევე უფრო აგრესიულად აკონტროლებენ საკუთარ თავს. 12-თექვსმეტობითი ჰოსტის სახელისა და /app/node_modules შემოწმების შემდეგ, დატვირთვა ამოწმებს აქტიური პაკეტის რეესტრის კონფიგურაციას და სამუშაო დირექტორიის გზას და ჩუმად მთავრდება, როდესაც ისინი მიუთითებენ ანალიზზე ან სარკისებურ კონტექსტზე და არა რეალურ სამიზნეზე. კომბინირებული ეფექტი არის დატვირთვა, რომელიც არაფერს აკეთებს, რაც შესამჩნევია უმეტეს შემოწმების გარემოში და სრულ კოლექციას მხოლოდ იქ ამუშავებს, სადაც თვლის, რომ ის ნამდვილ კონტეინერიზებულ ჰოსტზეა.
ექსფილტრაციაშეგროვებული მონაცემები მასპინძელს ორ არხზე ტოვებს. პირველი, შუქურა POST ფიქსირებულ webhook.site კოლექტორი, რომელიც შეიცავს ჰოსტის სახელს, რიცხვით UID-ს, სამუშაო დირექტორიას და შეგროვებული მონაცემების 120 კბ-მდე. მეორეც, მონაცემები იკვრება ყალბ YAML „მოდულის მანიფესტში“ და PUT to /api/მოდულები/ სამიზნე სერვერზე:
ecto_module: name: "<flag-or-chunk-0>" version: "1.0.0" power_level: "<chunk-1>" ship_deck: "<chunk-2>" cargo_hold: "<chunk-3>" მანიფესტის ველის სახელები (სიმძლავრის_დონე, გემის_გემბანი, ტვირთის_ჰოლდი) დეკორაციაა — მოპარული მონაცემები სტრიქონის მნიშვნელობებშია მოთავსებული, რის გამოც ქსელის მონიტორი ხედავს იმას, რაც აშკარად მონაცემების დემპინგის ნაცვლად, პაკეტის რეესტრის მანიფესტის ატვირთვას ჰგავს. შუქურის არხი მეტს შეიცავს: POST სხეული რომ webhook.site მოიცავს ჰოსტის სახელს, რიცხვით UID-ს, სამუშაო დირექტორიას და შეგროვებული blob-ის 120 კბ-მდე ფაილს, ამიტომ ერთი წარმატებული beacon-იც კი სრულ ვერსიას გვაწვდის. webhook.site არის უფასო მოთხოვნების შემოწმების სერვისი; მისი, როგორც შემგროვებლის, გამოყენება ნიშნავს, რომ ოპერატორს არასდროს მოუწევს ამ არხისთვის საკუთარი ინფრასტრუქტურის მიღება და ჩაწერილი მოთხოვნები სერვისის ურნაში რჩება.
მანიფესტი PUT დადის სარეზერვო სიაში, რომელიც იწყება რამდენიმეთი 127.0.0.1/localhost პორტები და შემდეგ გადის სამ საჯარო მისამართზე `154.57.164.0/24` დიაპაზონი, რომელიც ჩერდება პირველ საბოლოო წერტილზე, რომელიც პასუხობს 2xx სტატუსით. localhost-first თანმიმდევრობა შეესაბამება „verdaccio testing“-ის თვითაღწერილობას (ლოკალური რეესტრი loopback-ზე), მაგრამ public-IP სარეზერვო ვარიანტები ნიშნავს, რომ მონაცემები ტოვებს ჰოსტს ყოველთვის, როდესაც loopback არ უსმენს — ანუ ნებისმიერ მანქანაზე, რომელიც არ არის ავტორის საკუთარი სატესტო მოწყობილობა.
Timeline
კლასტერი აჩვენებს შესაძლებლობების ინკრემენტულ ზრდას და არა ერთ ვარდნას. ჩვენ მას ვახარისხებთ დაკვირვებული ქცევის მიხედვით და არა გამოქვეყნებული კედლის საათის მიხედვით:
| სტაჟირება | პაკეტები / ვერსიები | ქცევა |
|---|---|---|
| ადრეული სირბილი | coral-wraith 9999.0.x | გაბერილი ვერსიის ნომრები, რომლებიც შეესაბამება დამოკიდებულების დაბნეულობის მცდელობას; ინსტალაციის დროის ჩამოთვლა და exfil |
| Seed | coral-wraith 1.0.0 | პოსტინსტალაცია აგროვებს id/env/flag ფაილებს; ერთი PUT 154[.]57[.]164[.]71:30782, მარკერი ECT-472839 |
| სწრაფი იტერაცია | coral-wraith 1.0.1 → 6.0.0 | ათობით გამოშვება საათებში; ტვირთამწეობა იზრდება isAppWorker() კარიბჭე, IMDSv2 სერთიფიკატის ამოღება, სრული get-secret-value pivot, რეესტრის/გზის გარემოს შემოწმება და ორმაგი ჩაძირვის მარკერები |
| პარალელური სახელები | ecto-corsair-whisper-6f3b9 1.0.14–1.0.18 | იგივე დახურული ტვირთამწეობა; webhook.site შუქურის და მრავალჯერადი საბოლოო წერტილის სარეზერვო სია |
| ვარიანტები | ecto-rust-read-f3a9c1 1.0.1–1.0.2 | დამატებით ნიჟარის მარკერებს ამატებს ECT-987654, ECT-654321, ECT-839201 |
| ვარიანტები | ecto-corsair-flag-x9m4 1.0.0, ecto-nightly-spirit 1.1.0 | იგივე დახურული ტვირთამწეობა, იგივე C2 და შუქურა |
კლასტერის განმსაზღვრელი მახასიათებელი მისი გამოქვეყნების სიხშირეა: ერთი პაკეტისა და ერთი ვერსიის ნაცვლად, ერთი და იგივე სახელი სწრაფად ქვეყნდება განმეორებით, თითოეული გამოსცემს წინას მცირე ვარიაციას, რამდენიმე სხვადასხვა სახელწოდების მქონე და-ძმასთან ერთად, რომლებიც ერთსა და იმავე დატვირთვას ატარებენ. ჩურჩული ოჯახში კოდი იყოფა ორ მჭიდრო თითის ანაბეჭდად — ერთი ნაკრები რთავს ორ კრიტიკულ აღმოჩენას, მეორე კი სამს (დამატებითი ფაილის წაკითხვის წყარო) — მაგრამ ორივე ერთსა და იმავე დატვირთვაზე იშლება; განსხვავება კოდის დრიფტშია და არა ქცევით განშტოებაში. ჩურჩული რეესტრში დაფიქსირდა ანალიზირებული დიაპაზონის მიღმა (მინიმუმ 1.0.25-მდე წერის დროს) და მარჯნის მოჩვენება სახელი იმავე ფანჯრიდან საკუთარი ვერსიის კიბეზე ასვლას აგრძელებდა.
კომპრომისის ინდიკატორები
ქვემოთ მოცემული ყველა ინდიკატორი ამოღებულია დისკზე არსებული პაკეტის წყაროდან. ქსელის ინდიკატორები დეფანგირებულია.
ქსელი
| ინდიკატორი | როლი |
|---|---|
hxxp://154[.]57[.]164[.]71:30782 | C2 PUT სამიზნე (coral-wraith) |
hxxp://154[.]57[.]164[.]80:30543 | C2 PUT სარეზერვო (ecto-*) |
hxxp://154[.]57[.]164[.]82:31250 | C2 PUT სარეზერვო (ecto-*) |
hxxp://154[.]57[.]164[.]71:31289 | C2 PUT სარეზერვო (ecto-*) |
hxxps://webhook[.]site/602a4c72-7033-4e28-92ea-dc66e59206e5 | შუქურების კოლექციონერი |
169[.]254[.]169[.]254/latest/... | IMDSv2 ავტორიზაციის წაკითხვა (სამიზნე მხარე, AWS მეტამონაცემები) |
ქცევითი/ფაილის
| ინდიკატორი | როლი |
|---|---|
"postinstall": "node postinstall.js" | ვექტორის ინსტალაცია |
ecto_module: YAML-თან ერთად power_level / ship_deck / cargo_hold გასაღებები | Exfil მანიფესტის სქემა |
ნიჟარის მარკერები ECT-472839, ECT-987654, ECT-654321, ECT-839201 | C2 გზის სეგმენტი /api/modules/<marker> |
isAppWorker() კარიბჭე: მასპინძელი /^[0-9a-f]{12}$/, cwd შეიცავს /app/node_modules | გააქტიურების პირობა |
aws secretsmanager list-secrets მეტი us-east-1, eu-west-1, eu-central-1 | საიდუმლოებების ჩამოთვლა |
HTB{...} რეგულარული სკრაპი | დროშის აღების მოპოვება |
ფაილის ჰეშები (sha256, დაფიქსირებული ანალიზის დროს)
| ფაილი | შა 256 |
|---|---|
coral-wraith/postinstall.js | ce5ff035cfdfed1d0015446424b352c27b66bcb77e9fdb0a51e4245199146824 |
ecto-corsair-whisper-6f3b9 1.0.18/postinstall.js | b58432acba376aa6976f0490d9a1c04257ccdbc856d8390260c50322d63e31c3 |
ატრიბუცია და დაკვირვებული ქცევა
ხუთი პაკეტის სახელი გამოქვეყნდა ორი npm ანგარიშის სახელწოდებით, მაგრამ მათ საკმარისი ინფრასტრუქტურა აქვთ საერთო, რათა ისინი ერთ კლასტერად განიხილონ: იგივე ექტო_მოდული მანიფესტის სქემა, იგივე ECT-472839 პირველადი ნიჟარის მარკერი, იგივე webhook.site კოლექციონერის ID და C2 საბოლოო წერტილები იმავეში 154.57.164.0/24` ბლოკი. თესლის პაკეტი (`coral-wraith, უფრო მარტივი და არასრული) და კარიბჭიანი ექტო-ოჯახი, ამგვარად, ერთი ინსტრუმენტარიუმზე დაფუძნებულ იტერაციებად იკითხება და არა დამოუკიდებელ ძალისხმევად.
პაკეტები შემდგომ ვერსიებში აღწერენ საკუთარ თავს, როგორც „CTF დატვირთვა ვერდაჩოს მიწოდების ჯაჭვის ტესტირებისთვის.“ ჩვენ ამ ეტიკეტს დაკვირვებად ფაქტად წარმოვაჩენთ და არ ვიმეორებთ მას, როგორც დასკვნას მიზნის შესახებ. კოდის მოქმედება ცალსახაა და დამოუკიდებელია იმისგან, თუ როგორ არის მონიშნული: ის კითხულობს IAM როლის სერთიფიკატებს ეგზემპლარის მეტამონაცემების სერვისიდან, ჩამოთვლის მართულ საიდუმლოებებს სამ AWS რეგიონში და გადასცემს შედეგებს საჯარო IP-სა და მესამე მხარის webhook კოლექციონერს. მხოლოდ loopback-ზე მომუშავე სატესტო აღკაზმულობას არ დასჭირდება საჯარო IP-ის სარეზერვო სია, IMDS სერთიფიკატების წაკითხვა ან რეგიონებს შორის Secrets Manager-ის გამოძახებები. იმის გამო, რომ გასასვლელი და სერთიფიკატების დაფარვა რეალურია, კარიბჭიანი ვერსიები კლასიფიცირებულია, როგორც მავნე.
მხოლოდ კონტეინერზე დაფუძნებული კარიბჭე ოპერატიულად ყველაზე აღსანიშნავი მახასიათებელია. ის ერთდროულად არის თავის არიდების ღონისძიება — ლეპტოპებსა და ანალიზის სენდბოქსებში ჩუმად ყოფნა — და ასევე მიზნობრივი ღონისძიება, რომელიც ამოქმედდება მხოლოდ იქ, სადაც რეალური IAM როლი და ცოცხალი საიდუმლოებები, სავარაუდოდ, არსებობს. ანალიტიკოსები, რომლებიც ამ პაკეტებს ზოგად სენდბოქსში ამუშავებენ, ვერაფერს შეამჩნევენ; ეს ქცევა მხოლოდ Docker-ის სტილის ჰოსტის სახელისა და კონტეინერში ინსტალაციის გზის ქვეშ ვლინდება.
გავლენა, ტენდენციები და რეკომენდაციები დამცველებისთვის
აქ გამჟღავნება ღრუბლოვანი სერთიფიკატია და საიდუმლო გამჟღავნება შექმნისა და გაშვების კონტეინერებში. IMDS-დან აღებული IAM როლის სერთიფიკატი შეიცავს ამ როლისთვის განკუთვნილ ყველა ნებართვას; საიდუმლოებების მენეჯერი: სიის საიდუმლოებები (და ნებისმიერი შემდგომი GetSecretValue) აფართოებს ამას შენახული აპლიკაციის საიდუმლოებებამდე. გარემოს ცვლადის დემპები ხშირად შეიცავს რეესტრის ტოკენებს, მონაცემთა ბაზის URL-ებს და API გასაღებებს. CI ან კონტეინერის კონტექსტში — ზუსტად ის, რასაც კარიბჭე ირჩევს — ამ პაკეტიდან ერთ-ერთის ერთი ტრანზიტული ინსტალაცია საკმარისია ამ მასალის გასაჟონად.
Ectoplasm-ი იმ ნიმუშს ემორჩილება, რომელსაც ჩვენ დღემდე ვხედავთ: ინსტალაციის დროს დატვირთული ფაილები ლოკალური ფაილების ნაცვლად ღრუბლოვან მეტამონაცემებსა და მართულ საიდუმლოებებს იყენებს და მხოლოდ მაღალი ღირებულების მქონე გარემოში ირთვება. ქვემოთ მოცემულია ორი თავდაცვითი დაკვირვება.
- ფორმა შესამჩნევია;npm/PyPI ინსტალაციის კაუჭი, რომლის გამოძახების გრაფი აღწევს როგორც ღრუბლოვან საიდუმლოებების API-ს (aws საიდუმლოებების მენეჯერი, gcloud-ის საიდუმლოებები, az keyvault) ან IMDS მისამართი და ქსელის გასასვლელი წყარო ვიწრო, მაღალი სიგნალის ნიმუშია — ის თითქმის არასდროს გვხვდება ლეგიტიმურ სასიცოცხლო ციკლის სკრიპტში. სტატიკური ნაკადის ანალიზი მისი დროშის მონიშვნა შესაძლებელია კონკრეტული დომენის ან IP მისამართის გარეშე.
- გარემოს გამკვრივება მას აფერხებს. IMDSv2-ის 1-იანი ჰოპ ლიმიტით აღსრულება ხელს უშლის კონტეინერის სამუშაო დატვირთვების მიღწევას ეგზემპლარის მეტამონაცემებამდე; IAM როლების მინიმალური პრივილეგიებით განსაზღვრა ზღუდავს ნებისმიერი გაჟონვის შემთხვევაში აკრედიტაციის აფეთქების რადიუსს; ხოლო ინსტალაციების გაშვება... –იგნორირების სკრიპტები CI-ში ინსტალაციის კაუჭის ვექტორი მთლიანად შლის იმ პაკეტებისთვის, რომლებსაც ის არ სჭირდებათ.
დამცველებისთვის პრაქტიკული შემოწმებებია: გაფრთხილება გამავალი კავშირების შესახებ build/CI კონტეინერებიდან არადაშვებულ საჯარო IP მისამართებამდე npm ინსტალაცია; დააკვირდით პაკეტის სასიცოცხლო ციკლის სკრიპტებიდან წარმოშობილ IMDS წვდომას; და ნებისმიერი ინსტალაციის კაუჭი, რომელიც ღრუბლოვან CLI-ზე გადადის, საეჭვოდ მიიჩნიეთ, სანამ საპირისპირო არ დამტკიცდება.
კიდევ ორი შენიშვნა ამ კლასტერისთვის. პირველი, რადგან აქტივაცია შეზღუდულია კონტეინერიზებულ გარემოში, პაკეტი, რომელიც სამუშაო სადგურზე შემოწმებისას ინერტულად გამოიყურება, შეიძლება მაინც იყოს მოქმედი წარმოებაში — შემოწმებისას საჭიროა კონტეინერის ჰოსტის სახელისა და გზის პირობების რეპროდუცირება, ან წყაროს პირდაპირ წაკითხვა, იმის ნაცვლად, რომ დაეყრდნოს „მე დავაყენე და არაფერი მომხდარა“. მეორე, საჯარო მოთხოვნის შემოწმების სერვისის, როგორც შუქურის შემგროვებლის გამოყენება, ნიშნავს, რომ ამოღებული მონაცემების ნაწილი შეიძლება აღდგეს ინციდენტებზე რეაგირებისთვის: ორგანიზაციას, რომელიც ამ პაკეტებიდან ერთ-ერთს თავის დამოკიდებულების ხეში პოულობს, შეუძლია იმსჯელოს იმაზე, თუ რას შეიცავდა წარმატებული შუქურა დატვირთვის შეგროვების ლოგიკიდან და უნდა შეცვალოს ნებისმიერი IAM როლის ავტორიზაციის მონაცემები, რეესტრის ტოკენები და მართული საიდუმლოებები, რომლებიც ხელმისაწვდომი იყო დაზარალებული ბილდიდან ან გაშვების გარემოდან. სერთიფიკატების როტაციადა არა პაკეტის წაშლა, არის ოპერაციული გამოსწორება ინსტალაციის დასრულების შემდეგ.




