DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Znaczenie analizy komponentów oprogramowania stron trzecich (Software Composition Analysis - SCA) w procesie rozwoju rośnie wraz z publikacją corocznych raportów na temat podatności bibliotek open source, które są publikowane przez Synopsys, Sonatype, Snyk i White Source . Według raportu Stan luk w zabezpieczeniach oprogramowania Open Source 2020 liczba zidentyfikowanych podatności open source w 2019 roku wzrosła prawie 1.5-krotnie w porównaniu do roku poprzedniego, natomiast komponenty open source wykorzystywane są w 60% do 80% projektów. W niezależnej opinii procesy SCA stanowią odrębną praktykę OWASP SAMM i BSIMM jako wyznacznik dojrzałości, a w pierwszej połowie 2020 roku OWASP wydało nowy Standard weryfikacji komponentów oprogramowania OWASP (SCVS), dostarczający najlepszych praktyk w zakresie weryfikacji zewnętrznych elementy stron w łańcuchu dostaw BY.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Jeden z najbardziej ilustrujących przypadków stało się z Equifax w maju 2017 r. Nieznani napastnicy uzyskali informacje o 143 milionach Amerykanów, w tym imiona i nazwiska, adresy, numery ubezpieczenia społecznego i prawa jazdy. W 209 000 przypadków w dokumentach znajdowały się także informacje o kartach bankowych ofiar. Wyciek ten nastąpił w wyniku wykorzystania krytycznej luki w zabezpieczeniach Apache Struts 2 (CVE-2017-5638), a poprawka została opublikowana w marcu 2017 r. Firma miała dwa miesiące na zainstalowanie aktualizacji, ale nikt się tym nie przejął.

W artykule omówione zostanie zagadnienie wyboru narzędzia do przeprowadzenia SCA z punktu widzenia jakości wyników analiz. Przedstawione zostanie również porównanie funkcjonalne narzędzi. Proces integracji z CI/CD i możliwości integracji pozostawimy do kolejnych publikacji. Szeroką gamę narzędzi zaprezentowała firma OWASP w Twojej witrynie, ale w obecnej recenzji zajmiemy się tylko najpopularniejszym narzędziem open source Depency Check, nieco mniej znaną platformą open source Depency Track i rozwiązaniem Enterprise Sonatype Nexus IQ. Zrozumiemy również, jak działają te rozwiązania i porównamy wyniki uzyskane dla fałszywych alarmów.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Zasada działania

Kontrola zależności to narzędzie (CLI, maven, moduł jenkins, ant) ​​które analizuje pliki projektu, zbiera informacje o zależnościach (nazwa pakietu, groupid, tytuł specyfikacji, wersja...), buduje linię CPE (Common Platform Enumeration) , URL pakietu (PURL) i identyfikuje podatności dla CPE/PURL z baz danych (NVD, Sonatype OSS Index, NPM Audit API...), po czym buduje jednorazowy raport w formacie HTML, JSON, XML...

Przyjrzyjmy się, jak wygląda CPE:

cpe:2.3:part:vendor:product:version:update:edition:language:sw_edition:target_sw:target_hw:other

  • Część: Wskazanie, że komponent dotyczy aplikacji (a), systemu operacyjnego (o), sprzętu (h) (wymagane)
  • Producent Nazwa producenta produktu (wymagane)
  • Produkt: Nazwa produktu (wymagane)
  • Wersja: Wersja komponentu (element przestarzały)
  • aktualizacja: Aktualizacja pakietu
  • Wydanie: Starsza wersja (przestarzały element)
  • Język: Język zdefiniowany w RFC-5646
  • Wersja SW: Wersja oprogramowania
  • Docelowy SW: Środowisko oprogramowania, w którym działa produkt
  • Docelowy sprzęt: Środowisko sprzętowe, w którym działa produkt
  • Inny: Informacje o dostawcy lub produkcie

Przykładowy CPE wygląda następująco:

cpe:2.3:a:pivotal_software:spring_framework:3.0.0:*:*:*:*:*:*:*

Linia oznacza, że ​​wersja CPE 2.3 opisuje komponent aplikacji od producenta pivotal_software z tytułem spring_framework wersja 3.0.0. Jeśli otworzymy lukę CVE-2014-0225 w NVD widzimy wzmiankę o tym CPE. Pierwszym problemem, na który należy od razu zwrócić uwagę, jest to, że CVE w NVD według CPE zgłasza problem w frameworku, a nie w konkretnym komponencie. Oznacza to, że jeśli programiści są ściśle powiązani ze frameworkiem, a zidentyfikowana luka nie ma wpływu na moduły, z których korzystają programiści, specjalista ds. Bezpieczeństwa w ten czy inny sposób będzie musiał zdemontować to CVE i pomyśleć o aktualizacji.

Adres URL jest również używany przez narzędzia SCA. Format adresu URL pakietu jest następujący:

scheme:type/namespace/name@version?qualifiers#subpath

  • Schemat: Zawsze będzie „pkg” wskazujący, że jest to adres URL pakietu (wymagane)
  • Typ: „Typ” pakietu lub „protokół” pakietu, taki jak maven, npm, nuget, gem, pypi itp. (Wymagany element)
  • Przestrzeń nazw: Przedrostek nazwy, taki jak identyfikator grupy Maven, właściciel obrazu Docker, użytkownik GitHub lub organizacja. Opcjonalne i zależy od typu.
  • Nazwa: Nazwa pakietu (wymagane)
  • Wersja: Wersja pakietowa
  • Eliminacje: Dodatkowe dane kwalifikacyjne pakietu, takie jak system operacyjny, architektura, dystrybucja itp. Opcjonalne i specyficzne dla typu.
  • Podścieżka: Dodatkowa ścieżka w pakiecie względem katalogu głównego pakietu

Na przykład:

pkg:golang/google.golang.org/genproto#googleapis/api/annotations
pkg:maven/org.apache.commons/[email protected]
pkg:pypi/[email protected]

Ścieżka zależności — lokalna platforma internetowa, która akceptuje wygenerowane gotowe zestawienia materiałów (BOM). CyklonDX и SPDX, czyli gotowe specyfikacje dotyczące istniejących zależności. Jest to plik XML opisujący zależności - nazwa, skróty, adres URL pakietu, wydawca, licencja. Następnie Depency Track analizuje BOM, przegląda CVE dostępne dla zidentyfikowanych zależności z bazy danych podatności (NVD, Sonatype OSS Index...), po czym buduje wykresy, oblicza metryki, regularnie aktualizując dane o stanie podatności komponentów .

Przykład tego, jak może wyglądać BOM w formacie XML:

<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.2" serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1">
  <components>
    <component type="library">
      <publisher>Apache</publisher>
      <group>org.apache.tomcat</group>
      <name>tomcat-catalina</name>
      <version>9.0.14</version>
      <hashes>
        <hash alg="MD5">3942447fac867ae5cdb3229b658f4d48</hash>
        <hash alg="SHA-1">e6b1000b94e835ffd37f4c6dcbdad43f4b48a02a</hash>
        <hash alg="SHA-256">f498a8ff2dd007e29c2074f5e4b01a9a01775c3ff3aeaf6906ea503bc5791b7b</hash>
        <hash alg="SHA-512">e8f33e424f3f4ed6db76a482fde1a5298970e442c531729119e37991884bdffab4f9426b7ee11fccd074eeda0634d71697d6f88a460dce0ac8d627a29f7d1282</hash>
      </hashes>
      <licenses>
        <license>
          <id>Apache-2.0</id>
        </license>
      </licenses>
      <purl>pkg:maven/org.apache.tomcat/[email protected]</purl>
    </component>
      <!-- More components here -->
  </components>
</bom>

BOM można wykorzystać nie tylko jako parametry wejściowe dla ścieżki zależności, ale także do inwentaryzacji komponentów oprogramowania w łańcuchu dostaw, na przykład w celu dostarczenia oprogramowania klientowi. W 2014 r. w Stanach Zjednoczonych zaproponowano nawet wprowadzenie ustawy „Ustawa o zarządzaniu łańcuchem dostaw i przejrzystości w cyberprzestrzeni z 2014 r.”, w którym stwierdzono, że przy zakupie oprogramowania dowolny stan. Instytucja musi wystąpić o BOM, aby zapobiec zastosowaniu wrażliwych komponentów, ale ustawa nie weszła jeszcze w życie.

Wracając do SCA, Depency Track ma gotowe integracje z platformami powiadomień, takimi jak Slack, systemami zarządzania podatnościami, takimi jak Kenna Security. Warto też dodać, że Depency Track m.in. identyfikuje nieaktualne wersje pakietów oraz dostarcza informacji o licencjach (dzięki wsparciu SPDX).

Jeśli mówimy konkretnie o jakości SCA, to istnieje zasadnicza różnica.

Tor zależności nie akceptuje projektu jako danych wejściowych, ale raczej BOM. Oznacza to, że jeśli chcemy przetestować projekt, musimy najpierw wygenerować plik bom.xml, na przykład za pomocą CycloneDX. Zatem ścieżka zależności jest bezpośrednio zależna od CycloneDX. Jednocześnie pozwala na personalizację. Tak napisał zespół OZON Moduł CycloneDX do składania plików BOM dla projektów Golang w celu dalszego skanowania za pomocą ścieżki zależności.

IQ Nexusa to komercyjne rozwiązanie SCA firmy Sonatype, będące częścią ekosystemu Sonatype, w skład którego wchodzi również Nexus Repository Manager. Nexus IQ może przyjąć jako dane wejściowe zarówno archiwa wojenne (dla projektów Java) za pośrednictwem interfejsu sieciowego lub API, jak i BOM, jeśli Twoja organizacja nie przeszła jeszcze z CycloneDX na nowe rozwiązanie. W odróżnieniu od rozwiązań typu open source, IQ nie odnosi się tylko do CP/PURL do zidentyfikowanego komponentu i odpowiadającej mu podatności w bazie danych, ale uwzględnia także własne badania, np. nazwę podatnej funkcji lub klasy. Mechanizmy IQ zostaną omówione w dalszej części analizy wyników.

Podsumujmy niektóre funkcje funkcjonalne, a także rozważmy obsługiwane języki do analizy:

język
IQ Nexusa
Kontrola zależności
Ścieżka zależności

Java
+
+
+

C / C ++
+
+
-

C#
+
+
-

. Netto
+
+
+

Erlang
-
-
+

JavaScript (NodeJS)
+
+
+

PHP
+
+
+

Python
+
+
+

Rubin
+
+
+

Perl
-
-
-

Scala
+
+
+

Cel C
+
+
-

Szybki
+
+
-

R
+
-
-

Go
+
+
+

Funkcjonalność

Funkcjonalność
IQ Nexusa
Kontrola zależności
Ścieżka zależności

Możliwość zapewnienia, że ​​komponenty użyte w kodzie źródłowym są sprawdzane pod kątem licencjonowanej czystości
+
-
+

Możliwość skanowania i analizowania luk w zabezpieczeniach oraz czystości licencji dla obrazów Docker
+ Integracja z Clairem
-
-

Możliwość skonfigurowania zasad bezpieczeństwa w celu korzystania z bibliotek open source
+
-
-

Możliwość skanowania repozytoriów open source w poszukiwaniu wrażliwych komponentów
+ RubyGems, Maven, NPM, Nuget, Pypi, Conan, Bower, Conda, Go, p2, R, Yum, Helm, Docker, CocoaPods, Git LFS
-
+ Hex, RubyGems, Maven, NPM, Nuget, Pypi

Dostępność wyspecjalizowanej grupy badawczej
+
-
-

Działanie w zamkniętej pętli
+
+
+

Korzystanie z baz danych stron trzecich
+ Zamknięta baza danych Sonatype
+ Sonatype OSS, doradcy publiczni NPM
+ Sonatype OSS, NPM Public Advisors, RetireJS, VulnDB, obsługa własnej bazy danych podatności

Możliwość filtrowania komponentów open source podczas próby załadowania do pętli programistycznej zgodnie ze skonfigurowanymi zasadami
+
-
-

Zalecenia dotyczące naprawiania luk, dostępność linków do poprawek
+
+- (zależy od opisu w publicznych bazach danych)
+- (zależy od opisu w publicznych bazach danych)

Ranking wykrytych luk według ważności
+
+
+

Model dostępu oparty na rolach
+
-
+

Wsparcie dla CLI
+
+
+- (tylko dla CycloneDX)

Próbkowanie/sortowanie podatności według zdefiniowanych kryteriów
+
-
+

Panel według stanu aplikacji
+
-
+

Generowanie raportów w formacie PDF
+
-
-

Generowanie raportów w formacie JSONCSV
+
+
-

Obsługa języka rosyjskiego
-
-
-

Możliwości integracji

integracja
IQ Nexusa
Kontrola zależności
Ścieżka zależności

Integracja z LDAP/Active Directory
+
-
+

Integracja z systemem ciągłej integracji Bamboo
+
-
-

Integracja z systemem ciągłej integracji TeamCity
+
-
-

Integracja z systemem ciągłej integracji GitLab
+
+- (jako wtyczka do GitLaba)
+

Integracja z systemem ciągłej integracji Jenkins
+
+
+

Dostępność wtyczek dla IDE
+ IntelliJ, Eclipse, Visual Studio
-
-

Wsparcie dla niestandardowej integracji poprzez usługi sieciowe (API) narzędzia
+
-
+

Kontrola zależności

Pierwszy start

Uruchommy sprawdzanie zależności w aplikacji celowo podatnej na ataki DVJA.

Do tego użyjemy Sprawdzanie zależności Wtyczka Maven:

mvn org.owasp:dependency-check-maven:check

W rezultacie w katalogu docelowym pojawi się zależność-check-report.html.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Otwórzmy plik. Po podsumowaniu informacji o całkowitej liczbie podatności, możemy zobaczyć informację o podatnościach o wysokim poziomie Istotności i Pewności, ze wskazaniem pakietu, CPE i liczby CVE.

Następnie pojawiają się informacje bardziej szczegółowe, w szczególności podstawa, na której została podjęta decyzja (dowód), czyli określony BOM.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Następnie następuje opis CPE, PURL i CVE. Nawiasem mówiąc, zalecenia dotyczące korekty nie są uwzględnione ze względu na ich brak w bazie danych NVD.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Aby systematycznie przeglądać wyniki skanowania, możesz skonfigurować Nginx z minimalnymi ustawieniami lub wysłać powstałe defekty do systemu zarządzania defektami, który obsługuje złącza, do sprawdzania zależności. Na przykład Defekt Dojo.

Ścieżka zależności

Instalacja

Z kolei Depency Track to platforma internetowa z wyświetlaniem wykresów, więc nie pojawia się tutaj palący problem przechowywania defektów w rozwiązaniu firm trzecich.
Obsługiwane skrypty instalacyjne to: Docker, WAR, Executable WAR.

Pierwszy start

Przechodzimy do adresu URL działającej usługi. Logujemy się poprzez admin/admin, zmieniamy login i hasło, po czym trafiamy do Dashboardu. Następną rzeczą, którą zrobimy, będzie utworzenie projektu aplikacji testowej w języku Java w Strona główna/Projekty → Utwórz projekt . Weźmy na przykład DVJA.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Ponieważ ścieżka zależności może akceptować tylko BOM jako dane wejściowe, należy pobrać ten BOM. Skorzystajmy Wtyczka CycloneDX Maven:

mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom

Pobieramy plik bom.xml i ładujemy plik do utworzonego projektu DVJA → Zależności → Prześlij BOM.

Przejdźmy do Administracja → Analizatory. Rozumiemy, że mamy włączony tylko analizator wewnętrzny, który obejmuje NVD. Podłączmy także Sonatype OSS Index.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

W ten sposób otrzymujemy następujący obraz naszego projektu:

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Na liście znajduje się również jedna podatność dotycząca Sonatype OSS:

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Głównym rozczarowaniem było to, że Tor zależności nie akceptuje już raportów XML sprawdzania zależności. Najnowsze obsługiwane wersje integracji sprawdzania zależności to 1.0.0 - 4.0.2, podczas gdy ja testowałem 5.3.2.

tutaj jest wideo (i tutaj), kiedy było to jeszcze możliwe.

IQ Nexusa

Pierwszy start

Instalacja Nexusa IQ pochodzi z archiwum dokumentacja, ale w tym celu zbudowaliśmy obraz Dockera.

Po zalogowaniu się do konsoli należy utworzyć Organizację i Aplikację.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Jak widać, konfiguracja w przypadku IQ jest nieco bardziej skomplikowana, ponieważ musimy także stworzyć zasady, które będą miały zastosowanie na różnych „etapach” (dev, build, stage, release). Jest to konieczne, aby zablokować podatne komponenty, gdy przemieszczają się one w potoku bliżej produkcji lub aby zablokować je, gdy tylko dostaną się do Nexus Repo po pobraniu przez programistów.

Aby poczuć różnicę między oprogramowaniem open source a przedsiębiorstwem, wykonajmy to samo skanowanie za pomocą Nexusa IQ w ten sam sposób Wtyczka Maven, po wcześniejszym utworzeniu aplikacji testowej w interfejsie NexusIQ dvja-test-and-compare:

mvn com.sonatype.clm:clm-maven-plugin:evaluate -Dclm.applicationId=dvja-test-and-compare -Dclm.serverUrl=<NEXUSIQIP> -Dclm.username=<USERNAME> -Dclm.password=<PASSWORD>

Postępuj zgodnie z adresem URL wygenerowanego raportu w interfejsie internetowym IQ:

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Tutaj możesz zobaczyć wszystkie naruszenia zasad, wskazując różne poziomy istotności (od Informacje do Krytyczne dla bezpieczeństwa). Litera D obok składnika oznacza, że ​​składnik jest zależnością bezpośrednią, a litera T obok składnika oznacza, że ​​składnik jest zależnością przechodnią, czyli jest przechodnia.

Swoją drogą raport Raport o stanie bezpieczeństwa oprogramowania open source 2020 z Snyk podaje, że ponad 70% luk open source wykrytych w Node.js, Javie i Ruby ma zależności przechodnie.

Jeśli otworzymy jedno z naruszeń polityki Nexusa IQ, zobaczymy opis komponentu, a także wykres wersji, który pokazuje lokalizację aktualnej wersji na wykresie czasowym, a także moment, w którym luka przestaje działać być bezbronnym. Wysokość świec na wykresie pokazuje popularność stosowania tego składnika.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Jeśli przejdziesz do sekcji podatności i rozwiniesz CVE, możesz przeczytać opis tej luki, zalecenia dotyczące jej eliminacji, a także powód naruszenia tego komponentu, czyli obecność klasy DiskFileitem.class.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Podsumujmy tylko te związane z komponentami Java innych firm, usuwając komponenty js. W nawiasach podajemy liczbę luk, które zostały wykryte poza NVD.

Całkowity IQ Nexusa:

  • Przeskanowane zależności: 62
  • Zależności podatne na ataki: 16
  • Znaleziono luki: 42 (8 sonatype db)

Całkowita kontrola zależności:

  • Przeskanowane zależności: 47
  • Zależności podatne na ataki: 13
  • Znaleziono luki: 91 (14 oss typu sonatype)

Całkowita ścieżka zależności:

  • Przeskanowane zależności: 59
  • Zależności podatne na ataki: 10
  • Znaleziono luki: 51 (1 oss typu sonatype)

W kolejnych krokach przeanalizujemy uzyskane wyniki i ustalimy, która z tych luk jest prawdziwą wadą, a która fałszywie dodatnią.

Zrzeczenie się

Ta recenzja nie jest prawdą bezsporną. Autorowi nie przyświecało zadanie wyróżniania odrębnego instrumentu na tle innych. Celem przeglądu było pokazanie mechanizmów działania narzędzi SCA oraz sposobów sprawdzania ich wyników.

Porównanie wyników

Regulamin:

Fałszywym alarmem dotyczącym luk w komponentach innych firm jest:

  • Niedopasowanie CVE do zidentyfikowanego komponentu
  • Na przykład, jeśli w frameworku struts2 zostanie zidentyfikowana podatność, a narzędzie wskaże komponent frameworku struts-tiles, którego ta luka nie dotyczy, jest to fałszywy alarm
  • Niezgodność CVE ze zidentyfikowaną wersją komponentu
  • Na przykład luka jest powiązana z wersją Pythona > 3.5, a narzędzie oznacza wersję 2.7 jako podatną na ataki - jest to fałszywy alarm, ponieważ w rzeczywistości luka dotyczy tylko gałęzi produktów 3.x
  • Duplikat CVE
  • Na przykład, jeśli SCA określa CVE, który umożliwia RCE, wówczas SCA określa CVE dla tego samego komponentu, który ma zastosowanie do produktów Cisco, których dotyczy to RCE. W tym przypadku będzie to wynik fałszywie dodatni.
  • Na przykład w komponencie Spring-web znaleziono CVE, po czym SCA wskazuje na to samo CVE w innych komponentach Spring Framework, podczas gdy CVE nie ma nic wspólnego z innymi komponentami. W tym przypadku będzie to wynik fałszywie dodatni.

Obiektem badań był projekt Open Source DVJA. W badaniu wykorzystano wyłącznie komponenty Java (bez js).

Wyniki podsumowania

Przejdźmy od razu do wyników ręcznego przeglądu zidentyfikowanych podatności. Pełny raport dla każdego CVE można znaleźć w Załączniku.

Podsumowanie wyników dla wszystkich luk:

Parametr
IQ Nexusa
Kontrola zależności
Ścieżka zależności

Całkowita liczba zidentyfikowanych luk
42
91
51

Nieprawidłowo zidentyfikowane luki (fałszywie pozytywne)
2 (4.76%)
62 (68,13%)
29 (56.86%)

Nie znaleziono odpowiednich luk w zabezpieczeniach (fałszywie negatywny)
10
20
27

Podsumowanie wyników według składnika:

Parametr
IQ Nexusa
Kontrola zależności
Ścieżka zależności

Wszystkie zidentyfikowane komponenty
62
47
59

Łącznie wrażliwe komponenty
16
13
10

Nieprawidłowo zidentyfikowane wrażliwe komponenty (fałszywie dodatnie)
1
5
0

Nieprawidłowo zidentyfikowane wrażliwe komponenty (fałszywie dodatnie)
0
6
6

Zbudujmy wizualne wykresy, aby ocenić stosunek wyników fałszywie dodatnich i fałszywie ujemnych do całkowitej liczby luk. Komponenty są zaznaczane poziomo, a zidentyfikowane w nich podatności – pionowo.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Dla porównania podobne badanie przeprowadził zespół Sonatype testując projekt składający się z 1531 komponentów przy użyciu OWASP Depency Check. Jak widać, stosunek szumu do prawidłowych odpowiedzi jest porównywalny z naszymi wynikami.

DevSecOps: zasady działania i porównanie SCA. Część pierwsza
Źródło: www.sonatype.com/why-precision-matters-ebook

Przyjrzyjmy się niektórym CVE z wyników skanowania, aby zrozumieć przyczynę tych wyników.

Szczegółowo

№ 1

Przyjrzyjmy się najpierw kilku interesującym punktom dotyczącym Sonatype Nexus IQ.

Nexus IQ wskazuje na problem z deserializacją polegającą na możliwości wielokrotnego wykonywania RCE w Spring Framework. CVE-2016-1000027 w Spring-Web: 3.0.5 po raz pierwszy i CVE-2011-2894 w Spring-Context: 3.0.5 i Spring-Core: 3.0.5. Na pierwszy rzut oka wydaje się, że luki w zabezpieczeniach wielu CVE się powielają. Bo jeśli spojrzysz na CVE-2016-1000027 i CVE-2011-2894 w bazie NVD, wydaje się, że wszystko jest oczywiste

komponent
Słaby punkt

wiosna-web:3.0.5
CVE-2016-1000027

kontekst wiosenny:3.0.5
CVE-2011-2894

rdzeń sprężynowy:3.0.5
CVE-2011-2894

Opis CVE-2011-2894 z NVD:
DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Opis CVE-2016-1000027 z NVD:
DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Sam CVE-2011-2894 jest dość znany. W raporcie Białe źródło 2011 ten CVE został uznany za jeden z najczęstszych. Opisów CVE-2016-100027 w zasadzie jest niewiele w NVD i wydaje się, że mają one zastosowanie tylko do Spring Framework 4.1.4. Przyjrzyjmy się odniesienie i tu wszystko staje się mniej więcej jasne. Z Artykuły nadające się do utrzymania Rozumiemy, że oprócz luki w RemoteInvocationSerializingExporter w CVE-2011-2894 lukę obserwuje się w HttpInvokerServiceExporter. Oto, co mówi nam Nexus IQ:

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Jednak w NVD nie ma czegoś takiego, dlatego też sprawdzanie zależności i śledzenie zależności otrzymują fałszywie negatywne wyniki.

Z opisu CVE-2011-2894 można wywnioskować, że luka rzeczywiście występuje zarówno w kontekście Spring-context:3.0.5, jak i Spring-core:3.0.5. Potwierdzenie tego można znaleźć w artykule osoby, która znalazła tę lukę.

№ 2

komponent
Słaby punkt
Doświadcz mocnych i skutecznych rezultatów

rozpórki2-rdzeń:2.3.30
CVE-2016-4003
FAŁSZYWY

Jeśli przestudiujemy lukę CVE-2016-4003, zrozumiemy, że została ona naprawiona w wersji 2.3.28, jednak Nexus IQ nam to zgłasza. W opisie luki znajduje się uwaga:

DevSecOps: zasady działania i porównanie SCA. Część pierwsza

Oznacza to, że luka istnieje tylko w połączeniu z przestarzałą wersją środowiska JRE, o której postanowiono nas ostrzec. Niemniej jednak uważamy to za fałszywie pozytywne, choć nie najgorsze.

№ 3

komponent
Słaby punkt
Doświadcz mocnych i skutecznych rezultatów

xwork-core:2.3.30
CVE-2017-9804
TRUE

xwork-core:2.3.30
CVE-2017-7672
FAŁSZYWY

Jeśli spojrzymy na opisy CVE-2017-9804 i CVE-2017-7672, zrozumiemy, że problem polega na tym, że URLValidator class, z CVE-2017-9804 wywodzącym się z CVE-2017-7672. Obecność drugiej luki nie niesie ze sobą żadnego użytecznego obciążenia poza tym, że jej istotność wzrosła do Wysokiej, zatem możemy uznać ją za niepotrzebny szum.

Ogólnie rzecz biorąc, nie znaleziono żadnych innych fałszywych alarmów dla Nexusa IQ.

№ 4

Jest kilka rzeczy, które wyróżniają IQ na tle innych rozwiązań.

komponent
Słaby punkt
Doświadcz mocnych i skutecznych rezultatów

wiosna-web:3.0.5
CVE-2020-5398
TRUE

CVE w NVD stwierdza, że ​​ma zastosowanie tylko do wersji 5.2.x przed 5.2.3, 5.1.x przed 5.1.13 i wersji 5.0.x przed 5.0.16, jeśli jednak spojrzymy na opis CVE w Nexusie IQ , wówczas zobaczymy:
Doradcza uwaga dotycząca odstępstwa: Zespół badawczy firmy Sonatype zajmujący się badaniami nad bezpieczeństwem odkrył, że ta luka została wprowadzona w wersji 3.0.2.RELEASE, a nie 5.0.x, jak podano w poradniku.

Następnie znajduje się dokument PoC dotyczący tej luki, w którym stwierdza się, że występuje ona w wersji 3.0.5.

Fałszywy wynik negatywny jest wysyłany do sprawdzania zależności i śledzenia zależności.

№ 5

Przyjrzyjmy się fałszywym alarmom w przypadku sprawdzania zależności i śledzenia zależności.

Kontrola zależności wyróżnia się tym, że odzwierciedla te CVE, które mają zastosowanie do całego frameworku w NVD, do tych komponentów, do których te CVE nie mają zastosowania. Dotyczy to CVE-2012-0394, CVE-2013-2115, CVE-2014-0114, CVE-2015-0899, CVE-2015-2992, CVE-2016-1181, CVE-2016-1182, których sprawdzanie zależności „spieprzyło ” do struts-taglib:1.3.8 i struts-tiles-1.3.8. Te komponenty nie mają nic wspólnego z tym, co opisano w CVE – przetwarzaniem żądań, sprawdzaniem poprawności strony i tak dalej. Wynika to z faktu, że tym, co łączy te CVE i komponenty, jest jedynie framework, dlatego też Kontrola zależności uznała to za lukę.

Ta sama sytuacja ma miejsce w przypadku spring-tx:3.0.5 i podobna sytuacja w przypadku struts-core:1.3.8. W przypadku struts-core funkcje sprawdzania zależności i śledzenia zależności znalazły wiele luk w zabezpieczeniach, które w rzeczywistości dotyczą struts2-core, który w zasadzie jest oddzielnym frameworkiem. W tym przypadku Nexus IQ prawidłowo zrozumiał obraz i w wydanych przez siebie certyfikatach CVE wskazano, że żywotność struts-core dobiegła końca i konieczne było przejście na struts2-core.

№ 6

W niektórych sytuacjach interpretowanie oczywistego błędu sprawdzania zależności i śledzenia zależności jest niesprawiedliwe. W szczególności CVE-2013-4152, CVE-2013-6429, CVE-2013-6430, CVE-2013-7315, CVE-2014-0054, CVE-2014-0225, CVE-2014-0225, których sprawdzanie zależności i śledzenie zależności przypisywany spring-core:3.0.5 w rzeczywistości należy do spring-web:3.0.5. W tym samym czasie niektóre z tych CVE zostały również odnalezione przez Nexus IQ, jednakże IQ poprawnie zidentyfikowało je z innym komponentem. Ponieważ tych luk nie wykryto w Spring-Core, nie można argumentować, że w zasadzie nie ma ich w frameworku, a narzędzia open source słusznie wskazały te luki (tylko trochę je przeoczyły).

odkrycia

Jak widać, określenie wiarygodności zidentyfikowanych podatności metodą ręcznego przeglądu nie daje jednoznacznych wyników, dlatego pojawiają się kontrowersje. Wyniki są takie, że rozwiązanie Nexus IQ ma najniższy odsetek fałszywych alarmów i najwyższą dokładność.

Przede wszystkim wynika to z faktu, że zespół Sonatype rozbudował w swoich bazach opis każdej podatności CVE firmy NVD, wskazując podatności dla konkretnej wersji komponentów aż do klasy lub funkcji, przeprowadzając dodatkowe badania (np. , sprawdzanie luk w starszych wersjach oprogramowania).

Istotny wpływ na wyniki mają także te luki, które nie zostały uwzględnione w NVD, a mimo to są obecne w bazie Sonatype ze znakiem SONATYPE. Według raportu Stan luk w zabezpieczeniach oprogramowania Open Source 2020 45% wykrytych luk w zabezpieczeniach open source nie jest zgłaszanych do NVD. Według bazy danych WhiteSource tylko 29% wszystkich luk w zabezpieczeniach open source zgłoszonych poza NVD zostaje tam opublikowanych, dlatego ważne jest, aby szukać luk także w innych źródłach.

W rezultacie sprawdzanie zależności generuje dużo hałasu i brakuje niektórych wrażliwych komponentów. Zależność Track generuje mniej szumów i wykrywa dużą liczbę komponentów, co nie razi oczu w interfejsie internetowym.

Praktyka pokazuje jednak, że open source powinno stać się pierwszym krokiem w stronę dojrzałego DevSecOps. Pierwszą rzeczą, o której powinieneś pomyśleć włączając SCA do rozwoju, są procesy, czyli wspólne przemyślenie z zarządem i powiązanymi działami, jak powinny wyglądać idealne procesy w Twojej organizacji. Może się okazać, że dla Twojej organizacji na początku Depency Check lub Depency Track pokryje wszystkie potrzeby biznesowe, a rozwiązania Enterprise będą logiczną kontynuacją ze względu na rosnącą złożoność tworzonych aplikacji.

Dodatek A: Wyniki komponentów
Symbole:

  • Wysoki — luki w komponencie na poziomie wysokim i krytycznym
  • Średni — Luki w komponencie o średnim poziomie krytyczności
  • PRAWDA — prawdziwie pozytywny problem
  • FAŁSZ — problem fałszywie pozytywny

komponent
IQ Nexusa
Kontrola zależności
Ścieżka zależności
Doświadcz mocnych i skutecznych rezultatów

dom4j: 1.6.1
Wysoki
Wysoki
Wysoki
TRUE

log4j-core: 2.3
Wysoki
Wysoki
Wysoki
TRUE

log4j: 1.2.14
Wysoki
Wysoki
-
TRUE

zbiory wspólne:3.1
Wysoki
Wysoki
Wysoki
TRUE

Commons-fileupload:1.3.2
Wysoki
Wysoki
Wysoki
TRUE

commons-beanutils:1.7.0
Wysoki
Wysoki
Wysoki
TRUE

kodek Commons:1:10
Średni
-
-
TRUE

złącze mysql-java:5.1.42
Wysoki
Wysoki
Wysoki
TRUE

wyrażenie-sprężynowe:3.0.5
Wysoki
nie znaleziono komponentu

TRUE

wiosna-web:3.0.5
Wysoki
nie znaleziono komponentu
Wysoki
TRUE

kontekst wiosenny:3.0.5
Średni
nie znaleziono komponentu
-
TRUE

rdzeń sprężynowy:3.0.5
Średni
Wysoki
Wysoki
TRUE

struts2-config-browser-plugin:2.3.30
Średni
-
-
TRUE

wiosna-tx:3.0.5
-
Wysoki
-
FAŁSZYWY

rdzeń rozpórkowy: 1.3.8
Wysoki
Wysoki
Wysoki
TRUE

xwork-core: 2.3.30
Wysoki
-
-
TRUE

rozpórki2-rdzeń: 2.3.30
Wysoki
Wysoki
Wysoki
TRUE

taglib struts:1.3.8
-
Wysoki
-
FAŁSZYWY

rozpórki-płytki-1.3.8
-
Wysoki
-
FAŁSZYWY

Dodatek B: Wyniki luk w zabezpieczeniach
Symbole:

  • Wysoki — luki w komponencie na poziomie wysokim i krytycznym
  • Średni — Luki w komponencie o średnim poziomie krytyczności
  • PRAWDA — prawdziwie pozytywny problem
  • FAŁSZ — problem fałszywie pozytywny

komponent
IQ Nexusa
Kontrola zależności
Ścieżka zależności
Dotkliwość
Doświadcz mocnych i skutecznych rezultatów
Komentarz

dom4j: 1.6.1
CVE-2018-1000632
CVE-2018-1000632
CVE-2018-1000632
Wysoki
TRUE

CVE-2020-10683
CVE-2020-10683
CVE-2020-10683
Wysoki
TRUE

log4j-core: 2.3
CVE-2017-5645
CVE-2017-5645
CVE-2017-5645
Wysoki
TRUE

CVE-2020-9488
CVE-2020-9488
CVE-2020-9488
niski
TRUE

log4j: 1.2.14
CVE-2019-17571
CVE-2019-17571
-
Wysoki
TRUE

-
CVE-2020-9488
-
niski
TRUE

SONATYPE-2010-0053
-
-
Wysoki
TRUE

zbiory wspólne:3.1
-
CVE-2015-6420
CVE-2015-6420
Wysoki
FAŁSZYWY
Duplikaty RCE(OSSINDEX)

-
CVE-2017-15708
CVE-2017-15708
Wysoki
FAŁSZYWY
Duplikaty RCE(OSSINDEX)

SONATYPE-2015-0002
RCE (OSSINDEX)
RCE(OSSINDEX)
Wysoki
TRUE

Commons-fileupload:1.3.2
CVE-2016-1000031
CVE-2016-1000031
CVE-2016-1000031
Wysoki
TRUE

SONATYPE-2014-0173
-
-
Średni
TRUE

commons-beanutils:1.7.0
CVE-2014-0114
CVE-2014-0114
CVE-2014-0114
Wysoki
TRUE

-
CVE-2019-10086
CVE-2019-10086
Wysoki
FAŁSZYWY
Luka dotyczy wyłącznie wersji 1.9.2+

kodek Commons:1:10
SONATYPE-2012-0050
-
-
Średni
TRUE

złącze mysql-java:5.1.42
CVE-2018-3258
CVE-2018-3258
CVE-2018-3258
Wysoki
TRUE

CVE-2019-2692
CVE-2019-2692
-
Średni
TRUE

-
CVE-2020-2875
-
Średni
FAŁSZYWY
Ta sama luka co CVE-2019-2692, ale z dopiskiem „ataki mogą znacząco wpłynąć na dodatkowe produkty”

-
CVE-2017-15945
-
Wysoki
FAŁSZYWY
Nie dotyczy mysql-connector-Java

-
CVE-2020-2933
-
niski
FAŁSZYWY
Duplikat CVE-2020-2934

CVE-2020-2934
CVE-2020-2934
-
Średni
TRUE

wyrażenie-sprężynowe:3.0.5
CVE-2018-1270
nie znaleziono komponentu
-
Wysoki
TRUE

CVE-2018-1257
-
-
Średni
TRUE

wiosna-web:3.0.5
CVE-2016-1000027
nie znaleziono komponentu
-
Wysoki
TRUE

CVE-2014-0225
-
CVE-2014-0225
Wysoki
TRUE

CVE-2011-2730
-
-
Wysoki
TRUE

-
-
CVE-2013-4152
Średni
TRUE

CVE-2018-1272
-
-
Wysoki
TRUE

CVE-2020-5398
-
-
Wysoki
TRUE
Ilustrujący przykład na korzyść IQ: „Zespół badawczy ds. bezpieczeństwa Sonatype odkrył, że ta luka została wprowadzona w wersji 3.0.2.RELEASE, a nie 5.0.x, jak podano w poradniku”.

CVE-2013-6429
-
-
Średni
TRUE

CVE-2014-0054
-
CVE-2014-0054
Średni
TRUE

CVE-2013-6430
-
-
Średni
TRUE

kontekst wiosenny:3.0.5
CVE-2011-2894
nie znaleziono komponentu
-
Średni
TRUE

rdzeń sprężynowy:3.0.5
-
CVE-2011-2730
CVE-2011-2730
Wysoki
TRUE

CVE-2011-2894
CVE-2011-2894
CVE-2011-2894
Średni
TRUE

-
-
CVE-2013-4152
Średni
FAŁSZYWY
Duplikat tej samej luki w Spring-Web

-
CVE-2013-4152
-
Średni
FAŁSZYWY
Luka dotyczy komponentu Spring-web

-
CVE-2013-6429
CVE-2013-6429
Średni
FAŁSZYWY
Luka dotyczy komponentu Spring-web

-
CVE-2013-6430
-
Średni
FAŁSZYWY
Luka dotyczy komponentu Spring-web

-
CVE-2013-7315
CVE-2013-7315
Średni
FAŁSZYWY
PODZIEL z CVE-2013-4152. + Luka dotyczy komponentu Spring-web

-
CVE-2014-0054
CVE-2014-0054
Średni
FAŁSZYWY
Luka dotyczy komponentu Spring-web

-
CVE-2014-0225
-
Wysoki
FAŁSZYWY
Luka dotyczy komponentu Spring-web

-
-
CVE-2014-0225
Wysoki
FAŁSZYWY
Duplikat tej samej luki w Spring-Web

-
CVE-2014-1904
CVE-2014-1904
Średni
FAŁSZYWY
Luka dotyczy komponentu spring-web-mvc

-
CVE-2014-3625
CVE-2014-3625
Średni
FAŁSZYWY
Luka dotyczy komponentu spring-web-mvc

-
CVE-2016-9878
CVE-2016-9878
Wysoki
FAŁSZYWY
Luka dotyczy komponentu spring-web-mvc

-
CVE-2018-1270
CVE-2018-1270
Wysoki
FAŁSZYWY
Dla ekspresji wiosennej/wiadomości wiosennych

-
CVE-2018-1271
CVE-2018-1271
Średni
FAŁSZYWY
Luka dotyczy komponentu spring-web-mvc

-
CVE-2018-1272
CVE-2018-1272
Wysoki
TRUE

CVE-2014-3578
CVE-2014-3578 (OSSINDEX)
CVE-2014-3578
Średni
TRUE

SONATYPE-2015-0327
-
-
niski
TRUE

struts2-config-browser-plugin:2.3.30
SONATYPE-2016-0104
-
-
Średni
TRUE

wiosna-tx:3.0.5
-
CVE-2011-2730
-
Wysoki
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2011-2894
-
Wysoki
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2013-4152
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2013-6429
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2013-6430
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2013-7315
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2014-0054
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2014-0225
-
Wysoki
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2014-1904
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2014-3625
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2016-9878
-
Wysoki
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2018-1270
-
Wysoki
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2018-1271
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

-
CVE-2018-1272
-
Średni
FAŁSZYWY
Luka nie jest specyficzna dla spring-tx

rdzeń rozpórkowy: 1.3.8
-
CVE-2011-5057 (OSSINDEX)

Średni
FASLE
Podatność na Struts 2

-
CVE-2012-0391 (OSSINDEX)
CVE-2012-0391
Wysoki
FAŁSZYWY
Podatność na Struts 2

-
CVE-2014-0094 (OSSINDEX)
CVE-2014-0094
Średni
FAŁSZYWY
Podatność na Struts 2

-
CVE-2014-0113 (OSSINDEX)
CVE-2014-0113
Wysoki
FAŁSZYWY
Podatność na Struts 2

CVE-2016-1182
3VE-2016-1182
-
Wysoki
TRUE

-
-
CVE-2011-5057
Średni
FAŁSZYWY
Podatność na Struts 2

-
CVE-2012-0392 (OSSINDEX)
CVE-2012-0392
Wysoki
FAŁSZYWY
Podatność na Struts 2

-
CVE-2012-0393 (OSSINDEX)
CVE-2012-0393
Średni
FAŁSZYWY
Podatność na Struts 2

CVE-2015-0899
CVE-2015-0899
-
Wysoki
TRUE

-
CVE-2012-0394
CVE-2012-0394
Średni
FAŁSZYWY
Podatność na Struts 2

-
CVE-2012-0838 (OSSINDEX)
CVE-2012-0838
Wysoki
FAŁSZYWY
Podatność na Struts 2

-
CVE-2013-1965 (OSSINDEX)
CVE-2013-1965
Wysoki
FAŁSZYWY
Podatność na Struts 2

-
CVE-2013-1966 (OSSINDEX)
CVE-2013-1966
Wysoki
FASLE
Podatność na Struts 2

-
CVE-2013-2115
CVE-2013-2115
Wysoki
FASLE
Podatność na Struts 2

-
CVE-2013-2134 (OSSINDEX)
CVE-2013-2134
Wysoki
FASLE
Podatność na Struts 2

-
CVE-2013-2135 (OSSINDEX)
CVE-2013-2135
Wysoki
FASLE
Podatność na Struts 2

CVE-2014-0114
CVE-2014-0114
-
Wysoki
TRUE

-
CVE-2015-2992
CVE-2015-2992
Średni
FAŁSZYWY
Podatność na Struts 2

-
CVE-2016-0785 (OSSINDEX)
CVE-2016-0785
Wysoki
FAŁSZYWY
Podatność na Struts 2

CVE-2016-1181
CVE-2016-1181
-
Wysoki
TRUE

-
CVE-2016-4003 (OSSINDEX)
CVE-2016-4003
Wysoki
FAŁSZYWY
Podatność na Struts 2

xwork-core:2.3.30
CVE-2017-9804
-
-
Wysoki
TRUE

SONATYPE-2017-0173
-
-
Wysoki
TRUE

CVE-2017-7672
-
-
Wysoki
FAŁSZYWY
Duplikat CVE-2017-9804

SONATYPE-2016-0127
-
-
Wysoki
TRUE

rozpórki2-rdzeń:2.3.30
-
CVE-2016-6795
CVE-2016-6795
Wysoki
TRUE

-
CVE-2017-9787
CVE-2017-9787
Wysoki
TRUE

-
CVE-2017-9791
CVE-2017-9791
Wysoki
TRUE

-
CVE-2017-9793
-
Wysoki
FAŁSZYWY
Duplikat CVE-2018-1327

-
CVE-2017-9804
-
Wysoki
TRUE

-
CVE-2017-9805
CVE-2017-9805
Wysoki
TRUE

CVE-2016-4003
-
-
Średni
FAŁSZYWY
Dotyczy Apache Struts 2.x do 2.3.28, czyli wersji 2.3.30. Jednak z opisu wynika, że ​​CVE jest ważne dla dowolnej wersji Struts 2, jeśli używane jest środowisko JRE 1.7 lub starsze. Najwyraźniej postanowili nas tutaj ponownie ubezpieczyć, ale wygląda to bardziej na FAŁSZ

-
CVE-2018-1327
CVE-2018-1327
Wysoki
TRUE

CVE-2017-5638
CVE-2017-5638
CVE-2017-5638
Wysoki
TRUE
Ta sama luka, którą hakerzy Equifax wykorzystali w 2017 roku

CVE-2017-12611
CVE-2017-12611
-
Wysoki
TRUE

CVE-2018-11776
CVE-2018-11776
CVE-2018-11776
Wysoki
TRUE

taglib struts:1.3.8
-
CVE-2012-0394
-
Średni
FAŁSZYWY
Dla rozpórek 2-rdzeniowych

-
CVE-2013-2115
-
Wysoki
FAŁSZYWY
Dla rozpórek 2-rdzeniowych

-
CVE-2014-0114
-
Wysoki
FAŁSZYWY
Dla Commons-beanutils

-
CVE-2015-0899
-
Wysoki
FAŁSZYWY
Nie dotyczy taglib

-
CVE-2015-2992
-
Średni
FAŁSZYWY
Odnosi się do struts2-core

-
CVE-2016-1181
-
Wysoki
FAŁSZYWY
Nie dotyczy taglib

-
CVE-2016-1182
-
Wysoki
FAŁSZYWY
Nie dotyczy taglib

rozpórki-płytki-1.3.8
-
CVE-2012-0394
-
Średni
FAŁSZYWY
Dla rozpórek 2-rdzeniowych

-
CVE-2013-2115
-
Wysoki
FAŁSZYWY
Dla rozpórek 2-rdzeniowych

-
CVE-2014-0114
-
Wysoki
FAŁSZYWY
Pod Commons-beanutils

-
CVE-2015-0899
-
Wysoki
FAŁSZYWY
Nie dotyczy płytek

-
CVE-2015-2992
-
Średni
FAŁSZYWY
Dla rozpórek 2-rdzeniowych

-
CVE-2016-1181
-
Wysoki
FAŁSZYWY
Nie dotyczy taglib

-
CVE-2016-1182
-
Wysoki
FAŁSZYWY
Nie dotyczy taglib

Źródło: www.habr.com

Dodaj komentarz