პროგრამული უზრუნველყოფის შემუშავებისას ჩვენ დამოკიდებულნი ვართ როგორც საკუთარ, ასევე მესამე მხარის კომპონენტებზე ან არტეფაქტებზე. მოქნილი დამოკიდებულების მართვა აუცილებელია თანამედროვე პროგრამული უზრუნველყოფისთვის. პაკეტების მენეჯერები, როგორიცაა NPM, Maven, pip or NuGet ხშირად გამოიყენება პროგრამული უზრუნველყოფის დამოკიდებულებების დასადგენად. ეს ინსტრუმენტები შექმნილია მოხერხებულობისა და გამოყენების სიმარტივის გათვალისწინებით და არა უსაფრთხოების გათვალისწინებით.
პრობლემა
პრობლემა ის არის, რომ დეველოპერებისთვის მოქნილობა და გამოყენების სიმარტივე ბოროტმოქმედებს იწვევს, რომლებიც პროგრამული უზრუნველყოფის დამოკიდებულებებს თავიანთი ბიზნესისთვის დაუძლეველ მომხიბვლელობად მიიჩნევენ. შედეგი: ბოროტმოქმედებმა აქ ნაჩვენები ყველა შესაძლო შეტევის გზა აირჩიეს. წყარო: „Backstabber's Knife Collection: A Review of Open Source Software Supply Chain Attacks“
ამ პოსტში ყურადღებას გავამახვილებთ ღია ვერსიის დეკლარაციების გამოყენებაზე, იმ გაგებით, რომ ჩამოტვირთული ვერსია არ არის დაფიქსირებული, არამედ უნდა ეკუთვნოდეს გარკვეულ დიაპაზონს. აწყობის დროს, პაკეტების მენეჯერი ირჩევს და ჩამოტვირთავს/ინსტალირებს მითითებულ ვერსიების დიაპაზონთან თავსებად არსებულ ყველაზე მაღალ ვერსიას.
მოდით, ილუსტრირება გავუკეთოთ ღია დეკლარაციებს დამოკიდებულებების დეკლარაციებში სხვადასხვა პაკეტის მენეჯერებისთვის:
- ეროვნული პრევენციის პროგრამა: პაკეტი.json
{
...
„დამოკიდებულებები“: {
...
„მიიღებს“: „>=1.3.8“,
„ლოდაში“: „~4.16.0“,
...
},
...
}
დაინსტალირდება Accepts პაკეტის ყველაზე დიდი არსებული ვერსია, რომელიც არ იქნება 1.3.8-ზე დაბალი, ასევე Lodash-ის ყველაზე დიდი „პაჩ“ განახლება 4.16.x დიაპაზონში.
- მავენი: pom.xml
...
...
commons-io
commons-io
გამოშვება
...
...
commons-io-სთვის (jar ფაილი) ხელმისაწვდომი ბოლო ვერსია დაემატება დამოკიდებულებად.
- მილსადენი: setup.py
...
დაყენება (
...
install_requires=['წიწაკის სიმინდი', 'launchpadlib'],
...
)
...
ასეთ ღია ვერსიის სქემებს აქვთ როგორც კარგი, ასევე ცუდი მხარეები. კარგი ის არის, რომ ახალი ვერსიები როგორც წესი, შეიცავს ფუნქციურ და ხარისხის გაუმჯობესებებს, შეცდომების გამოსწორებას და უსაფრთხოების პატჩებს, რომლებიც ავტომატურად განახლდება. გაითვალისწინეთ, რომ რეალური პროექტების უმეტესობისთვის, გამოსწორებები არ არის პორტირებული წინა მცირე ვერსიებზე, გარდა, შესაძლოა, კატასტროფული უსაფრთხოების ხარვეზებისა. ღია ვერსიები ასევე კარგია ბიბლიოთეკებში გამოსაყენებლად, რათა შემცირდეს იმ ვერსიების რაოდენობა, რომელთა ინსტალაციაც საჭიროა ყველა დამოკიდებულების მოგვარების შემდეგ.
თუმცა, ღია ვერსიების დიაპაზონებს უარყოფითი მხარეც აქვთ. თქვენ ზუსტად არ იცით, რომელი ვერსიები დაინსტალირდება აწყობის დროს და აწყობები განმეორებადი არ არის. ასევე არსებობს მუქი ღია ვერსიების მხარეს. თუ ბოროტმოქმედი მოახერხებს საჯარო საცავში მავნე კომპონენტის გამოქვეყნებას თქვენს ღია დიაპაზონთან თავსებადი მაღალი ვერსიით, თქვენი შემდეგი აწყობა მოიცავს მავნე კომპონენტს, შესაძლოა, ინსტალაციის სკრიპტებში მავნე პროგრამის შესრულებაც კი, რომლებიც შესაძლოა ავტომატურად შესრულდეს. შეტევის დატვირთვის დაფარვა ერთგვარი ხელოვნებაა.
ეს ცნობილია, როგორც ვერსიის დამაგრების ნაკლებობა პრობლემა.
ბოროტმოქმედი პირები ყოველთვის ცდილობენ პოპულარული ღია კოდის პაკეტების მავნე ვერსიების განთავსებას. მათ შეიძლება მიიღონ წვდომა პაკეტების საცავების გასაღებებზე საიდუმლო გაჟონვის გზით; ისინი ხშირად იყენებენ სოციალურ ინჟინერიას ან მალავენ ჩადგმულ მავნე დამოკიდებულებას ერთი შეხედვით სასარგებლო ადგილას. pull requestრამდენიმე ავტორიც კი ერთ დღეს თავად გადაწყვეტს, რომ სამყარო უსამართლოა და თავის კლიენტებს უკბინოს... საპროტესტო პროგრამული უზრუნველყოფა საკუთარ პაკეტებში!
ახლა წარმოიდგინეთ, რომ მუშაობთ ორგანიზაციაში, რომელიც იყენებს შიდა კომპონენტებს ღია კოდის კომპონენტებთან ერთად.
თუ არასწორმა მოთამაშემ იცის ასეთი შიდა კომპონენტების სახელი, მას შეუძლია მოახერხოს იმავე სახელის მქონე კომპონენტის საჯარო საცავში გამოქვეყნება. ბევრი პაკეტის მენეჯერი ჯერ საჯარო კომპონენტებს იღებს და თუ ვერსია სწორად არის შერჩეული და თქვენს მიერ გამოცხადებულ დამოკიდებულებაში არსებული ვერსია ღიაა, ბუმ! ეს პრობლემა დასახელებულია დამოკიდებულების დაბნეულობა.
მოდით, მაგალითი მოვიყვანოთ. დავუშვათ, რომ ჩვენს NPM პროექტში გვაქვს დამოკიდებულება კერძო კომპონენტზე:
- ეროვნული პრევენციის პროგრამა: პაკეტი.json
{
"სახელი": "ჩემი პროექტი",
...
„დამოკიდებულებები“: {...
„ჩემი-პირადი-დეპ“: „>=1.0.0“,...
}
...
}
თავდამსხმელმა შეიძლება შექმნას my-private-dep-ის მაღალი მნიშვნელობის ვერსია (მაგალითად, 99.0.0) და გამოაქვეყნოს ის საჯარო npm საცავში, საკუთარი ყალბი ანგარიშით (თავდამსხმელს არ სჭირდება ჩემს ორგანიზაციასთან არაფრის გაკეთება). NPM პაკეტების მენეჯერი დააინსტალირებს მავნე დამოკიდებულებას, ხშირად დამანგრეველი შედეგებით.
გადაწყვეტილება
პროგრამული უზრუნველყოფის შექმნის პროცესში ამ პრობლემების თავიდან ასაცილებლად, ჩვენ უნდა დავიცვათ კომპონენტების ვერსიების დეკლარირების მკაცრი ნორმები, რომლებიც დამოკიდებულია გამოყენებულ ტექნოლოგიაზე. მნიშვნელოვანია, რომ პაკეტის კონკრეტული ვერსია, საცავში გამოქვეყნების შემდეგ, იყოს უცვლელი (დამოკიდებული ფაილების გაწყვეტის თავიდან ასაცილებლად და არა მხოლოდ უსაფრთხოების მიზნით).
ზოგადი იდეაა ფიქსაცია (ამოძრავებთ) ვერსიები, ყოველთვის ამოწმებს, რომ კომპონენტების ფიქსირებული ვერსიები (მათ შორის ყველა გარდამავალი დამოკიდებულება) თავისუფალია მავნე პროგრამებისგან და ეს შესაძლებელია ამის წყალობით დაბლოკვის ფაილები რასაც ბევრი პაკეტის მენეჯერი გვთავაზობს. ვნახოთ, როგორ მუშაობს ვერსიის დამაგრება სხვადასხვა პაკეტის მენეჯერისთვის. არსებობს დელიკატური კომპრომისი ხშირი ვერსიის განახლებები ცნობილი დაუცველობების გამოსასწორებლად და ვერსიის დამაგრება არადეტერმინისტული აწყობისა და მიწოდების ჯაჭვზე პოტენციური შეტევების თავიდან ასაცილებლად.
- NPM:
npm ან yarn პაკეტების მენეჯერები იყენებენ სხვადასხვა lockfiles-ს (შესაბამისად, npm-shrinkwrap.json / package-lock.json ან yarn.lock), რომლებიც ჩამოთვლიან ყველა დამოკიდებულების, პირდაპირი და არაპირდაპირი, ფიქსირებულ ვერსიებს. lockfiles უნდა იყოს ვერსიის კონტროლის ქვეშ, წინააღმდეგ შემთხვევაში სხვა დეველოპერები/შექმნის კვანძები შეიძლება დასრულდეს სხვადასხვა ვერსიით. მოერიდეთ npm ინსტალაციას, თუ შემუშავების დროს არ გჭირდებათ დამოკიდებულებების განახლება (მაგ. უსაფრთხოების შესწორებების დასაყენებლად). ზოგადად გამოიყენეთ უფრო დეტერმინისტული npm ci (სუფთა ინსტალაცია), რათა პაკეტის მენეჯერი გამოიყენოს lockfile ან დაასრულოს შეცდომით, თუ lockfile არ არის, ან ის არ ემთხვევა package.json-ს. თუ ჩამოთვლილი ვერსიები შემოწმდა მავნე პროგრამებზე, lockfile უზრუნველყოფს, რომ შექმნის დროს არაფერი ცუდი არ მოხდება.შიდა კომპონენტებისთვის რეკომენდებულია შექმნათ NPM-ის ფარგლები ორგანიზაციის მიერ მართული (მაგალითად, @myorg) და ამ სფეროს გამოყენება დამოკიდებულებაში (მაგალითად, @myorg/my-private-dep), რომელსაც შეიძლება ჰქონდეს მხოლოდ პირადი ხილვადობა. ეს ბლოკავს დამოკიდებულების დაბნეულობა შეტევები, რადგან მხოლოდ ორგანიზაციის წევრებს, რომლებსაც აქვთ ჩაწერის ნებართვა, შეუძლიათ პაკეტების გამოქვეყნება ასეთი მასშტაბით.
- NPM:
- Maven:
Maven-ს / Gradle-ს არ აქვთ დაბლოკვის ფაილები (მაგრამ იხილეთ ეს StackOverflow სტატია).ვერსიების დიაპაზონები Maven/Gradle-ში ისე ხშირად არ გამოიყენება, როგორც სხვა ეკოსისტემებში. უბრალოდ მოერიდეთ ვერსიის დიაპაზონები და უახლესი ან გამოშვებული მეტავერსიები. ასევე უნდა შემოწმდეს არაპირდაპირი ვერსიები. ვერსიები Maven მოდული კარგი ინსტრუმენტია ვერსიის კონტროლისთვის.
გთხოვთ გაითვალისწინოთ, რომ Maven-ს ყოველთვის ჰქონდა ორგანიზაციის მასშტაბის კონცეფცია (დამოკიდებულების groupId ნაწილი) და დამოკიდებულებების დაბნეულობა, როგორც ჩანს, საერთოდ არ წარმოადგენს პრობლემას ამ ეკოსისტემისთვის.
- Maven:
- pip:
Python-ში არსებობს სხვადასხვა ინსტრუმენტი lockfiles-თან დასამუშავებლად:- პიპენვი, რომელიც წარმოქმნის Pipfile.lock lock ფაილს.
- პოეზია, რომელიც პოეზიას.დაბლოკვას წარმოქმნის.
- პიპების გაყინვა, ბრძანება, რომელიც ქმნის requirements.txt ფაილს, რომელიც მოქმედებს როგორც დაბლოკვის ფაილი. შეამოწმეთ, იყენებს თუ არა ყველა დამოკიდებულება ფიქსირებულ ვერსიებს == ოპერატორის გამოყენებით. შემდეგ pip install -r requirements.txt იყენებს ფიქსირებულ დამოკიდებულებებს.
- pip:
შეგახსენებთ, რომ ზემოთ მოცემული lockfiles უნდა იყოს ვერსიის კონტროლის ქვეშ და რომ არჩეული build ბრძანება უნდა იყენებდეს lockfile-ს.
pip-თან (PyPI) გამოყენებულ ჩვეულებრივ პაკეტების საცავს არ აქვს დასახელების სფეროები და ის დაუცველია დამოკიდებულების დაბნეულობის შეტევების მიმართ. დამოკიდებულების დაბნეულობის თავიდან აცილება Python-ის ეკოსისტემაში ეს ადვილი არ არის და ზოგიერთი ავტორი გვირჩევს შიდა საცავის გამოყენებას, რომელიც PyPI-დან აღებული საჯარო დამოკიდებულებების პროქსის ფუნქციას შეასრულებს, მაგრამ ჯერ შიდა საცავიდან კერძო დამოკიდებულებების აღებაა საჭირო (-index-url უნდა მიუთითებდეს შიდა საცავისკენ და არა PyPI-ზე, ხოლო –extra-index- url უნდა წაიშალოს).
რამდენიმე რეალური შეტევა
Getcookies-ის შეტევამსახიობმა dustin87-მა პოპულარულ npm mailparser პაკეტში არაპირდაპირი დამოკიდებულება დაამატა RCE backdoor-ის (gCOMMANDhDATAi) მქონე მავნე პაკეტზე:
JSON.stringify(req.headers).replace(/g([a-f0-9]{4})h((?:[a-f0-9]{2})+)i/gi, (o, p, v) => {})მიუხედავად იმისა, რომ mailparser-ს მოძველებული ვერსია ჰქონდა (მიმოხილვის ავტორები არ ჰყავდა!), ის მაინც იღებდა დაახლოებით 64,000 ყოველკვირეულ ჩამოტვირთვას. ეს იყო თითქმის წარუმატებელი შეტევის შემთხვევა, რადგან RCE რეალურად არ განხორციელებულა.cised.
NPM-მა გამოაქვეყნა ამ პოსტის getcookies შეტევის დეტალებით.
დამოკიდებულების დაბნეულობა:
ალექს ბირსანმა 2021 წელს აღმოაჩინა დამოკიდებულების დაბნეულობის პრობლემა და გამოაქვეყნა პოსტი სახელწოდებით „როგორ შევიჭრა Apple-ის, Microsoft-ის და ათობით სხვა კომპანიის სისტემაში".
გახსოვდეთ, რომ npm-ისთვის ორგანიზაციის სფერო, როგორიცაა @myorg, უნდა იყოს დაჯავშნილი და შიდა პაკეტები უნდა შეიცვალოს სფეროს გამოსაყენებლად.
pip-ის შემთხვევაში, საერთო საჯარო რეესტრის PyPI-ს არ აქვს სკოპები/სახელთა სივრცეები. თითოეულ კერძო პაკეტს შეიძლება ჰქონდეს საჯარო პაკეტის squat შიდა პაკეტის სახელით, მაგრამ ცარიელი და შესაძლოა გამოყენებისას შეცდომას წარმოქმნიდეს, რათა მისი იდენტიფიცირება მოხდეს შემთხვევით მოძიების შემთხვევაში.
Node-ipc:
რუსეთ-უკრაინის ომის დაწყებისას, პაკეტის მფლობელმა რუსულ და ბელორუსულ ჰოსტებზე ინსტალაციისას შემთხვევითი ფაილების წასაშლელად მავნე კოდი შეიყვანა. ფაილი ssl-geospec.js შემდეგ გეოგრაფიულ განსხვავებას ახორციელებდა:
საინტერესოა, რომ სხვა პაკეტები იყენებდნენ ღია ვერსიებს node-ipc დამოკიდებულებისთვის, როგორიცაა პოპულარული Vue.js ჩარჩო, და მისმა შემნახველებმა მიიღეს სასწრაფო მიმართვა node-ipc დამოკიდებულების უსაფრთხო ვერსიაზე დასამაგრებლად.
ეს პოსტი შეიცავს დამატებით დეტალებს ამ საბოტაჟზე, რომელიც სხვა საბოტაჟებთან შედარებით ერთი ნაბიჯით წინ მიდის პროტესტვერი საკითხები.
დასკვნითი შენიშვნები
ღია ვერსიები უნდა არასოდეს შეიძლება გამოყენებულ იქნას კონსოლიდირებულ პროგრამულ პროექტებში. ისინი აწყობას არარეპროდუცირებადს ხდიან და თავდამსხმელებმა შეიძლება გამოიყენონ ისინი და მოახერხონ მავნე პროგრამების შეყვანა დამოკიდებულების ხეებზე თავდასხმების გზით, როგორიცაა ზემოთ აღნიშნული დამოკიდებულების დაბნეულობა.
არასწორი კონფიგურაციები, როგორიცაა ღია ვერსიები, ვერსიის მიმაგრების არარსებობა ან არასკოპირებული შიდა კომპონენტები თავიდან უნდა იქნას აცილებული. პირველი, რაც უნდა გაკეთდეს, არის ასეთი პრობლემების აღმოჩენა, შესაძლოა, მათი აღმოჩენის შემთხვევაში, აწყობის დაბლოკვაც კი და მოქმედების პროტოკოლის სტანდარტიზაცია.
დამოკიდებულებებში ხარვეზებისა და არასწორი კონფიგურაციების ავტომატური აღმოჩენა, საეჭვო დამოკიდებულებების შესახებ ინფორმაციის მიწოდება, რომლებიც შეიძლება დაუცველი იყოს მიწოდების ჯაჭვის კონკრეტული შეტევების მიმართ, როგორიცაა დამოკიდებულების დაბნეულობა, ყველა ქმედითი გამოსწორების ინსტრუმენტებით, ერთ-ერთი მთავარი მიზანია Xygeni პლატფორმა.
| მეტი წასაკითხად |
| ომ მ., პლეით ჰ., სიკოში ა., მეიერი მ.: „ზურგის მტვრის დანების კოლექცია: ღია კოდის პროგრამული უზრუნველყოფის მიწოდების ჯაჭვის შეტევების მიმოხილვა“. DIMVA 2020. ლექციების ჩანაწერები კომპიუტერულ მეცნიერებაში, ტომი 12223. Springer – 2020 (დამოკიდებულების შეტევის ხის ფიგურის წყარო.) |
| @adam-npm: “მავნე მოდულის შესახებ შეტყობინება: getcookies„. npm ბლოგი (არქივირებული) – 2 მაისი, 2018. |
| ალექს ბირსანი: „როგორ შევიჭრა Apple-ის, Microsoft-ის და ათობით სხვა კომპანიის სისტემაში„მედიუმი“ – 2021 წლის 9 თებერვალი. |
| აქს შარმა: „დიდი საბოტაჟი: ცნობილი npm პაკეტი უკრაინის ომის პროტესტის ნიშნად ფაილებს შლის„BleepingComputer“ – 2022 წლის 17 მარტი |







