Populaire npm-library bevatte kwaadaardige code om cryptovaluta te stelen

Criminelen voorzagen Event-Stream, een populaire JavaScript-npm-library van malafide code. De code werd gebruikt voor Copay-apps van BitPay en kon daardoor wallets binnendringen en bitcoin en bitcoin cash stelen.

Vorige week werd ontdekt dat Event-Stream van kwaadaardige code voorzien was, maar toen was nog niet bekend wat de code deed. De npm-library voor Node.js-streamingdata wordt wekelijks zo'n twee miljoen keer gedownload van npmjs.com.

De code-injectie vond 5 oktober plaats bij Flatmap-Stream, die ontwikkelaar @right9ctrl in september aan Event-Stream 3.3.6 toevoegde en die versie vervolgens publiceerde. Drie dagen later publiceerde hij een nieuwe versie, zonder de injectie, maar toen waren er al een groot aantal installaties. De oorspronkelijke ontwikkelaar, Dominic Tarr, had het beheer over Event-Stream eerder aan @right9ctrl overgedragen omdat hij geen tijd en interesse had in de verdere ontwikkeling, schrijft ZDNet. Flatmap-Stream 1.1 kan inmiddels niet meer geïnstalleerd worden via npm.

Na analyse van de kwaadaardige code, bleek dat deze geen effect had, totdat deze gebruikt zou worden door enkele ontwikkelaars in de broncode van Copay, een wallet-app van BitPay. Na het compileren voor de consumenten-app werd de code actief, om zich op eindgebruikers te kunnen richten. Versies 5.0.2 tot 5.1.0 waren dan ook kwetsbaar en moeten niet meer gebruikt worden, waarschuwt BitPay.

Binnen de app kon de code wallet-profielen in kaart brengen en private sleutels doorsturen naar een server in Kuala Lumpur. De gegevens konden criminelen gebruiken om bitcoin en bitcoin cash te stelen uit de wallets. BitPay adviseert gebruikers om tegoeden zo snel mogelijk over te hevelen naar versie 5.2.0 van de wallet.

Door Olaf van Miltenburg

Nieuwscoördinator

27-11-2018 • 19:20

91

Submitter: HyperioN

Reacties (91)

Sorteer op:

Weergave:

Ik heb even mogen genieten van npm via React Native en wat een knettergekke dependency hell is dat. De meest simpele dingen hebben al gewoon 10000 files. Alles is continu versie < 1.0 en er is altijd iets kapot in combinatie met iets anders. Ook doordat er zo veel dependencies op dependencies op dependencies zijn heb je ook nauwelijks een idee wat er nou precies in je applicatie zit.

Sorry dat ik het zeg, maar je ziet wel een verschil in volwassenheid tussen pak hem beet Python en JavaScript als je gaat kijken hoe er ontwikkeld wordt qua dependencies.
Ik zie hier veel reacties die nogal de plank mis slaan.
Als we naar het huidige npm ecosysteem kijken zien we de volgende dingen:
  • Er zijn ontiegelijk veel packages.
  • Sommige packages zijn erg minimaal (in extreme gevallen zelfs one liners).
  • In een normaal project heb je (inclusief alle sub dependencies) al gauw meer dan 100 modules die worden geinstalleerd.
  • De meeste packages hebben een bovengemiddelde kwaliteit. Denk aan code style en unit tests / functionele tests.
  • Zelf een package maken en publiceren is heel laagdrempelig.
  • De meeste packages volgen semver, dit zorgt voor compatibiliteit
Dit biedt grote voordelen:
  • Vanwege de grote hoeveelheid packages en de grote granulariteit van de packages, vind je bijna altijd wat je nodig hebt.
  • Je hoeft zelf veel minder irrelevante code (code die niet specifiek is voor datgene wat je aan het maken bent) te schrijven en onderhouden.
  • Upgraden naar nieuwe versies van packages gaat meestal goed.
  • Package locking zorg ervoor dat je die situaties kunt voorkomen / oplossen waar het niet goed gaat.
Maar, elk voordeel heb z'n nadeel:
  • Vanwege de grote hoeveelheid aan dependencies, is het veiligheidsrisico groter.
  • Vanwege snelle update cyclus, is de impact van een hack groter.
  • Een 'onbenullige' dependency (bijv. leftpad) kan voor problemen zorgen.
Al met al vind ik het Node.js + npm een van de fijnste ontwikkelomgevingen, voor allerhande toepassingen. Wat betreft de veiligheid, tsjah, het probleem is groter dan in andere ecosystemen, maar hetzelfde probleem bestaat net zo goed in de andere ecosystemen.
Ik kijk altijd eerst even op github wat er precies inzit voordat ik besluit het te gaan gebruiken en dus te installeren. Heb op die manier al veel links laten liggen of alleen gekopieerd dat wat ik nodig had.
Wel even in je achterhoofd houden dat dat wat op github staat niet perse ook zo in npm staat. Haalt natuurlijk niet uit als je het kopieert van github.
Mooi voorbeeld: is-odd. Doet niet veel meer dan "return (n % 2) === 1"

Weekly downloads: 1.154.994

[Reactie gewijzigd door StephanVierkant op 27 juli 2024 13:18]

Om hier op aan te vullen, gelukkig is er ook een isEven(), en die is dependent op de isOdd-library. Inhoud:
var isOdd = require('is-odd');

module.exports = function isEven(i) {
return !isOdd(i);
};
Ik dacht dat je een grap maakte, maar nee... 8)7
* Copyright (c) 2015, 2017, Jon Schlinkert.
_O-
Mooi voorbeeld: is-odd. Doet niet veel meer dan "return (n % 2) === 1"
Dat zou al niet werken bij -1.
Die regel code niet maar de package wel die start namelijk met
const n = Math.abs(value);

[Reactie gewijzigd door JustSomeWords op 27 juli 2024 13:18]

Ik heb niet veel ervaring met python. Maar bij javascript is dit ontstaan door dat het zo gemakkelijk was om packages te maken.

Javascript/npm is pas later populair geworden en daardoor zijn vele packages nog niet volwassen. Maar door die populariteit gaat die wereld en innovatie heel snel en zijn er ook voor elke package wel een set aan alternatieven, zodat je veel gemakkelijker een package kan vinden die bij jou usecase past.

daarnaast komt het ook doordat javascript zelf relatief kleine kleine set a base lib functies ondersteund waardoor mensen zelf packages hiervoor gaan maken. Langzamerhand zal dat wel uitdeien tot een paar enkele utility libs die iedereen gebruikt en zullen de meeste van deze 'nutteloze' libs wegvallen denk ik.

Ik kom uit dotnet wereld maar prefereer tegenwoordig npm + typescript over dotnet. gewoon omdat er zoveel meer aanbod is aan libraries om dingen te maken. Dotnet begint met core langzaam wel een inhaal stap te maken maar toch is de community daar veel minder actief.

Al met al vind ik dat je op npm makkelijk een grote hoeveelheid kwalitatieve packages kunt vinden (goede docs, open source op github en unit tests). niet veel talen kunnen dat evenaren.

en om dependency hell te voorkomen heb je lock files. dat beginnen meer talen overigens te implementeren (php composer heeft het ook) waarbij het aantal packages substantieel wordt.
daarnaast komt het ook doordat javascript zelf relatief kleine kleine set a base lib functies ondersteund waardoor mensen zelf packages hiervoor gaan maken.
Daar heb je wel een punt, Python heeft een veel sterkere set aan basisklassen. Maar het zou makkelijk bepaald kunnen worden met een committee dat er dingen aan toegevoegd worden. Requests en zo zijn in de laatste versies ook veel makkelijker geworden. En voor de oudere JS versies gewoon een blok standaard code op een CDN zetten die het aanvult.
Jep...
Een tijdje terug (2016) was er de "left-pad" soap: How one developer just broke Node, Babel and thousands of projects in 11 lines of JavaScript
Lang verhaal kort: een developer van 't megasimpele package genaamt left-pad had besloten al zijn packages van npm af te halen vanwege een "zakelijk" conflict (npm had hem opgedragen om een andere package van hem van naam te veranderen vanwege vermeend copyright infringement; als antwoord daarop wilde hij niks meer met ze te maken hebben).

Gevolg: duizenden apps en libraries konden niet meer builden omdat die package niet meer beschikbaar was. (Héél veel apps/libs gebruiken Babel en die had left-pad als dependency).

En wat denk je dat left-pad deed? Jup.. het aan de linkerkant aanvullen van een string naar een bepaalde lengte. Het was letterlijk (het gebrek aan) een package van nog geen tien regels code, wat bijna heel de JS-ontwikkelende wereld stopzette. 8)7

[Reactie gewijzigd door HyperioN op 27 juli 2024 13:18]

Ik verbaas me inderdaad over het amateuristische niveau van versie en dependency beheer wat een aantal nieuwe programmeertalen gebruikt.

Een goed voorbeeld hoe het wel moet is bv Java icm Maven. Je builds zijn altijd repruceerbaar en je kan artifacts in je eigen repo cache bewaren om niet van dit soort gepruts afhankelijk te zijn.
Nog leuker, probeer dit alles eens op Windows, op een NTFS of soortgelijk filesysteem. Windows kan totaal niet omgaan met grote hoeveelheden piepkleine files. Traag als stront. Het andere effect is dat een project al snel een paar GB kan innemen vanwege de file allocatie tabel.
De gemiddelde Linux/macOS User had dat al gemerkt natuurlijk en daarom blijft ie ook weg van Windows ;)

Ik maak me wel zorgen door dit soort nieuwsberichten. Nu gaat het om jatten van cryptokeys maar uiteindelijk is npm in potentie één grote backdoor. Daar past een flink Paard van Troje in :/
Eens. Als we heel eerlijk zijn, kan de huidige npm situatie gewoon niet.

Ik werk in een omgeving met vrij strenge information security regels. Vanuit de wet wordt dat al steeds strenger, maar in deze omgeving gaan we nog een stap verder.

NPM ontspringt die dans omdat auditors er weinig of geen weet van hebben. Als we elkaar geen mietje noemen kunnen we vrij duidelijk zijn dat in zo'n omgeving, duizenden stukjes vreemde code runnen absoluut niet kan. Dat is een attack vector als de mount everest.
Dat komt omdat de nare cultuur is ontstaan om voor elke poep en een scheet een package te schrijven welke soms niet meer doet dan een simpel sommetje of string transform.
Of juist door luie programmeurs die voor elke poep en scheet gewoon gaan zoeken op Stack Overflow en de meest doodsimpele routines uit andere packages halen, waardoor het alleen maar dependencies zijn die met plakband aan elkaar hangen.
Jullie hebben beiden gelijk, maar eerst een stap terug: waarom ontstaat deze cultuur?

Simpel antwoord: omdat JavaScript een kale taal is. De taal zelf is kaal en gebrekkig en er is ook geen standard library.

Kijk bij .NET/C#, Java, of zelfs PHP wat je allemaal inbegrepen krijgt. Niemand installeerd daar duizend packages voor oersimpele dingen. Je krijgt dat kado en iedereen gebruikt hetzelfde. Groot verschil.
Eens :) Dat zal ook niet snel veranderen ben ik bang (in browsers dan) en dat helpt zo'n taal ten onder als je het mij vraagt.

Niet voor niets dat er talen zoals Typescript, Dart en Coffeescript zijn ontwikkeld die transpilen naar plain ES. Nu nog meer van dat soort simpele functies er in mikken en dan kan het weer leuk worden. Kunnen al die dependencies in de prullenbak.
Absoluut! Dan moet je Ruby eens gebruiken. Da's pas een verademing...
Hoezo lui? Heel veel programmeurs leiden aan “not invented” here syndrome, maar zullen we ff niet voor alles zelf code gaan schrijven.

Dus zoals met alles “it depends”. Die leftpad package moet je niet blind npm installen, dat schrijf je zo zelf En zo zijn er meer packages, desnoods kopieer je de code (mits de licentie het toelaat), en maintain je de code zelf. Maar het is niet alleen ff wat regels code, maar ook unit tests en eventuele documentatie erbij.
Bij JavaScript worden er veel micro packages gemaakt, dit geeft veel flexibiliteit, en hou elke package heel erg gericht op het oplossen van een kleine specifieke taak, zonder afleiding van simpele overhead zaken.
Dit zou de betreffende package overzichtelijk moeten maken.

Er zijn alleen wel hele bizarre kleine packages die weinig toevoegen, en door de vele dependencies van dependencies heb je nog minder goed overzicht over de gehele code.
Als je packages groter maakt, kan het zijn dat er weer in verschillende packages hetzelfde gedaan wordt.
Door de micro packages zou je de totale codebase kleiner kunnen houden, wat voor het web ideaal is. (niet dat NPM daar voor bedacht is, maar nu denk ik wel voor 90% daar voor gebruikt wordt)

Voordeel van NPM is wel dat je maar gemiddeld +/- 10% van de code zelf hoeft te schrijven, en je 90% van de code uit NPM haalt, wat je eigen code overzichtelijk houdt.

Wel is het belangrijk dat je audit gebruikt om alle packages te inspecteren, waardoor je snel weet als een dergelijke package voorzien is van kwaadaardige code.
Doen van een audit op de packages in he project is 1 regel op de cmdline, zie: https://docs.npmjs.com/au...-security-vulnerabilities

Mensen die klagen over npm en code hergebruik lijden doorgaans aan NIHS. Is niet erg, maar dat maakt je niet erg geloofwaardig als productieve (web)developer IMHO. Het is ook vrij hypocriet, immers je schrijft ook je eigen OS niet.

Ik vind dat het getuigd van zelf overschatting ("ik kan het beter"). Met onderhand tegen de 20 jaar development ervaring is mijn constatering dat tenminste 50% van de ontwikkelaars (en op een slechte dag reken ik mijzelf daar ook bij) er beter aan doet om zoveel mogelijk code van anderen te gebruiken ipv zelf te gaan prutsen...

[Reactie gewijzigd door bille op 27 juli 2024 13:18]

Kleine packages betekent veel managen. Ik doe veel Java en c#.. daar zie je ook veel libraries maar een libraries is daar een verzameling gerelateerde functies. Overlap? Wellicht, maar in een andere context. Ook is de standaard library al vrij breed, wat maakt dat je niet met mini helper functies komt te zitten. JS heeft geen bibliotheek van betekenis (een beetje zoals c/c++) en ook daar zie je wat JS nu doorloopt: veel utility functies met verschillende stijlen en kwaliteiten. Non maakt het echter wel heel makkelijk om rommel naar binnen te trekken.
Ja, het is totale waanzin. Ik snap het idee wel om alles zo veel mogelijk in kleine, zelfstandige, modules op te hakken, maar dit is doorgeschoten.
Het effect dat er nu dan weer gebruik wordt gemaakt van dependencies met vaste versies. In plaats van de dependen op (mylib >= 4.0) wordt het een dependency als (mylib = 4.0.1+0.2b7-tst) die nooit meer wordt bijgewerkt. Voor je het weet zit alles muurvast. Je wordt dan ook al snel gedwongen om voor iedere app een eigen omgeving op te zetten, want het delen van een omgeving lukt niet door al die conflicterende dependencies. Met tools als Docker wordt dan ook steeds meer gedaan. Handig als je iets wil dat snel werkt, maar een ramp als je het ooit wil upgraden.
Klopt, ik heb het idee dat dit een beetje in de 'javascript-cultuur' zit. Als je iets zoekt dat ingewikkelder is dan hello world wordt er al gauw een library voor gezocht..

Misschien komt dit dan weer voort uit dat met javascript vroegah niet zoveel mogelijk was als vandaag de dag, en er daardoor teveel amateurs in het vakgebied (zijn blijven) zitten? /speculatie
Het is wel eerlijk om erbij te zeggen dat Python het omgekeerde probleem heeft. Python zit al jaren klem tussen versie 2 en 3. Python 2 is nog steeds de standaard bij sommige Linux distro's. Dit komt omdat niemand zin heeft zijn packages om te zetten naar Python 3. Python 2 (1991 - 2011) is al lang EOL maar nog steeds uitgebreider, en heeft daarom bij veel mensen de voorkeur.

Dat kan je volwassen noemen. Of gedateerd.

[Reactie gewijzigd door Sando op 27 juli 2024 13:18]

Nouuuu ik hoor helemaal niemand meer over Python 2, maar dat kan in een andere niche misschien wel anders zijn zoals Scientific. Maar Django ondersteunt het niet eens meer.
Goed om te horen! Misschien is mijn mening ook gedateerd. Was vroeger Python developer.
ubuntu 16.04 default python 2.7
centos 6 default python 2.6
centos 7 default python 2.7
Zet macOS ook nog maar in het rijtje met 2.7. Maar die shipt ook nog Bash 3.2. En een verouderde versie van Ruby. De meeste distributies zijn vooral van "don't break stuff" en niet van "wat gebruikt een programmeur anno 2018".
Zo ongeveer alles binnen security land draait nog op Python2.
Nouja, Django versie 1.11 (LTS) technisch gezien nog wel een dik jaar ;)
Heb thuis nog wel wat oude meuk draaien op 1.11 of lager maar al het nieuwe wat ik start gaat netjes in Django2 + Python3
Maar een goede build tool heeft wel tree shaking. Doet niets af aan de depemdency hell though.
Ik heb ook nooit begrepen hoe grote organisaties met buildtools (geinstalleerd via npm) kunnen toelaten. Voor eigen ontwikkelde code is 4-ogen (of meer) principe. Maar even de front-end builden en je haalt i.d.d. 1.000 tot 10.000 pakketjes binnen. Die allemaal nakijken is onmogelijk.

Dus stel je wil in NL een grote bank targetten, dan is het een kwestie van uitzoeken hoe ze hun front-end builden (bijvoorbeeld) en dan ergens mee gaan schrijven aan 1 van die 1.000 packages. Als je genoeg vertrouwen hebt bouw je een of andere sideloader o.i.d. die code injecteert in de App/Website.
Een groot nadeel van NPM is dat er by default een versienummer met dakje ( ^ ) gebruikt wordt, wat aangeeft dat nieuwere versies blindelings geïnstalleerd mogen worden. Zelfs als je expliciete versienummers gebruikt, dan worden de dependencies van je dependencies alsnog op een hogere versie geïnstalleerd, wanneer zij dus dat dakje gebruiken. Ik heb wel vernomen dat ze hiermee bezig zijn, maar dit is echt een grote fout in het beginsel geweest.

Op mijn werk gebruiken we MyGet, waar we de NPM packages doorheen trekken. Die checkt sowieso op licentie, maar ook op CVEs (Common Vulnerabilities and Exposures). Dat is een db van ruim 100.000 entries, welke door MITRE Corp. wordt onderhouden en wordt gefinancieerd door Homeland Security. Nieuwe entries in de db worden eerst voorgesteld en daarna goed onder de loep genomen voordat ze er ook daadwerkelijk in komen. Ik weet niet of dit type vulnerability in de db voorkomt, maar je kun in ieder geval stellen dat je packages een basic check hebben doorstaan (of juist niet).

Ik heb deze specifieke injectie niet bekeken, maar wil daarnaast nog wel CSP (Content Security Policy) benadrukken. CSP zorgt ervoor dat je het expliciet maakt met welke domeinen je communiceert (voor xhr requests, maar ook inladen van externe zaken als images, scripts en fonts).

Beide zaken zou ik sterk aanraden om toe te passen.

[Reactie gewijzigd door TomONeill op 27 juli 2024 13:18]

CSP i.d.d. voor Front-End, maar voor bijv. Node wat op de server draait moet je weer andere truuks toepassen (2-way Firewall + monitoring). Maar hetzelfde geldt ook voor React Native, en/of voor Java build-tools en zelfs IDE's + plugins. Al is het met NPM wel het meest problematisch.
Java apps zijn minder gevoelig voor het ^ probleem, het gebruik van snapshots of flexibele versies is niet onmogelijk maar zeker ongebruikelijk.
Banken etc hebben code audits.
Ja, maar die auditten echt geen duizenden NPM packages!
Ik werk aan de App van een van de grootste banken van NL. En ja, alle packages worden vrij regelmatig geaudit.
Ook van je hele buildstraat?
Grote kans dat die buildstraat niet bij externe package managers kan komen en alle packages via een interne package manager lopen.

Op die manier ben je volledig in controle over welke packages gebruikt kunnen worden voor builds en releases.
Meestal wel ligt aan het bedrijf maar vaak via code checkers. Plus ook een package white list.

Niet perfect maar gecontroleerd.
Nee, banken zorgen gewoon dat kwetsbare packages niet in de buurt van een mogelijke aanvalsvector kunnen komen.

Je kan dan bijvoorbeeld wel een phishing-poging doen via een om de tuin geleide front-end, maar dan is de gebruiker, niet het systeem van de bank, het doelwit.
Zie hier een van de keerzijden van het gebruik van externe libraries.
Wat is het alternatief? Alle code zelf schrijven? Veel succes met het schrijven van bijvoorbeeld je eigen SSL/TLS implementatie. Foutloos, natuurlijk. ;)

Het probleem is dat de code niet ondertekend wordt en dat ondertekening niet afgedwongen wordt, waardoor het zonder verificatie wordt geïnstalleerd. Er zijn veel open-source projecten waarbij de naam van de programmeur of het project verbonden is aan diens code, en waarbij packages die niet/verkeerd ondertekend zijn niet geïnstalleerd worden.

Wat voorbeelden:
Arch Linux
Debian Linux
Mozilla Firefox

En zo zijn er nog veel meer.

[Reactie gewijzigd door The Zep Man op 27 juli 2024 13:18]

Het probleem is dat de code niet ondertekend wordt en dat ondertekening niet afgedwongen wordt.
Dat is zeker een deel van het probleem, maar volgens mij gaat het hier om een programmeur met kwade bedoelingen die zichzelf het project in heeft weten te kletsen. Daar helpt geen technisch middel tegen, indien nodig had hij z'n eigen handtekening gezet.

Het helpt vast wel als mensen beseffen dat hun naam onlosmakelijk verbonden wordt met de slechte code.

[Reactie gewijzigd door CAPSLOCK2000 op 27 juli 2024 13:18]

Dat is zeker een deel van het probleem, maar volgens mij gaat het hier om een programmeur met kwade bedoelingen die zichzelf het project in heeft weten te kletsen. Daar helpt geen technisch middel tegen, indien nodig had hij z'n eigen handtekening gezet.
Het gaat om een project waarbij eigendom over de package naam overgedragen is naar een andere persoon. Indien NPM bijv. af zou dwingen dat de major versie van een package op zo'n moment omhoog moet rollen, kun je bij zulke gevallen al een hoop kwaad voorkomen. Anderen zullen actief een breaking version change moeten nemen; komen er (hopelijk) achter dat er een nieuw persoon a/h bewind staat en gaan hun opties her-evalueren.

Wat je nu ziet is dat iemand een patch-versie kan introduceren die sneaky mee geinstalleerd wordt door een developer die even niet oplet wanneer hij of zij een verse installatie doet van de dependencies voor een project.

[Reactie gewijzigd door R4gnax op 27 juli 2024 13:18]

Dat is zeker een deel van het probleem, maar volgens mij gaat het hier om een programmeur met kwade bedoelingen die zichzelf het project in heeft weten te kletsen.
Bron? Misschien wordt het account van die programmeur wel misbruikt.
Daar helpt geen technisch middel tegen, indien nodig had hij z'n eigen handtekening gezet.
Standaard wordt ondertekende code niet afgedwongen. Er zijn daarom heel veel ontwikkelaars die hun code niet ondertekenen. Het verplichten van ondertekenen zou al een stap in de juiste richting zijn, maar dan nog moet de identiteit van de ontwikkelaars bevestigd worden.

[Reactie gewijzigd door The Zep Man op 27 juli 2024 13:18]

[quote]
Bron? Misschien wordt het account van die programmeur wel misbruikt.
[quote]
Het artikel waar we op reageren?
Ok, er is niet bewezen wie er achter de toetsen zat, maar gezien de geschiedenis lijkt het er op dat het de echte "right9ctrl" is, wie dat ook moge zijn. Anders had hij daarna geen versie geupload zonder de fout of had hij wel alarm geslagen.
Het verplichten van ondertekenen zou al een stap in de juiste richting zijn, maar dan nog moet de identiteit van de ontwikkelaars bevestigd worden.
Het zou zeker helpen, zelfs zonder identiteit. Reputatie is ook veel waard.
Ok, er is niet bewezen wie er achter de toetsen zat, maar gezien de geschiedenis lijkt het er op dat het de echte "right9ctrl" is, wie dat ook moge zijn. Anders had hij daarna geen versie geupload zonder de fout of had hij wel alarm geslagen.
Want een programmeur is nooit op vakantie?

Het is overigens al uitgelegd in een andere reactie:
jeroentjo in 'nieuws: Populaire npm-library bevatte kwaadaardige code om cryp...
Daarbij tot zekere hoogte zou het ook wel schelen als er wat minder packages werden gebruikt in projecten.

Met +1000 verschillende packages verlies je sws het overzicht wat je nou allemaal gebruikt. Kan je de packages wel ondertekenen maar stel dat de ontwikkelaar zelf kwaadwillend is?
Met +1000 verschillende packages verlies je sws het overzicht wat je nou allemaal gebruikt. Kan je de packages wel ondertekenen maar stel dat de ontwikkelaar zelf kwaadwillend is?
Het gaat om vertrouwen. Als jij bijvoorbeeld alleen de ontwikkelaars vertrouwt die hun eigen naam gebruiken om code te ondertekenen en hun identiteit is geverifieerd door het project dat je gebruikt (dat je ook vertrouwt), dan is er zoiets als aansprakelijkheid voor opzettelijk schade toedienen.

Het is een groot verschil als iemand een bug per ongeluk in een programma laat ten opzichte van het opzettelijk verwerken van malware in de eigen broncode. ;)

[Reactie gewijzigd door The Zep Man op 27 juli 2024 13:18]

Dat zal niet helpen als dat account bijvoorbeeld is gehacked.

Het zou veel beter zijn als men wat kritischer was met dependencies. Ze zijn niet gratis, er zitten ook nadelen aan. Niet alleen op security vlak maar bijvoorbeeld ook op onderhoudbaarheid. Dit zal echter altijd een case by case afweging zijn maar zomaar van alles je project binnentrekken omdat dat zo makkelijk is is gewoon niet zo'n goed idee. Op zijn minst moet je nog weten wat je allemaal gebruikt in je project en met +1000 packages ben je dat stadium al ver voorbij. Het erge is nog dat iemand die op zijn beurt jouw library weer gebruikt ook opgezadeld zit met al die dependencies.
Volgens mij komt dat nummer 1000 van het aantal dependencies dat wordt toegevoegd als je de 'create-react-app' runt, iets wat veel voorkomt. Sowieso komt er vaak een enorme zwik binnen als je nodejs libraries toevoegt.

Zijdelings; leuk artikel wat de problemen blootlegt - https://hackernoon.com/im...e-here-s-how-9a8cb347c5b5

[Reactie gewijzigd door Basszje op 27 juli 2024 13:18]

Vertrouwen is niet de oplossing als je honderden packages gebruikt. Zoals de onderbuurman al zegt: als er eentje gehacked wordt of eventjes een slechte bui heeft, valt bij miljoenen ontwikkelaars de boel om.

Grootschalig NPM gebruik is vanuit security gezien een drama, de attack vector is oneindig groot.
er zijn toch al een hoop hashes van releases? Kan je mij uitleggen wat pkgsign daar extra bovenop doet?

Die hashes zorgen er voor dat wat wordt binnengehaald ook precies hetzelfde moet zijn als wat er binnen kwam toen library ooit aan de dependency lijst is toegevoegd. Dus het zou moeten beschermen tegen libraries die opeens verdwijnen en terug komen (met een andere hash) omdat het opeens door iemand anders gemanaged wordt.

Maar ik heb het idee dat de source-repo van de ontwikkelaar van deze library geïnfecteerd is, en correct me if wrong maar wat doet pkgsign daar tegen?

(zoals altijd, niet als flame bedoeld maar ik wil uitleg van iets wat ik niet helemaal snap :P)
er zijn toch al een hoop hashes van releases? Kan je mij uitleggen wat pkgsign daar extra bovenop doet?
Een hash is geen digitale handtekening.
Maar ik heb het idee dat de source-repo van de ontwikkelaar van deze library geïnfecteerd is, en correct me if wrong maar wat doet pkgsign daar tegen?
Bij een juiste implementatie wordt de private key onafhankelijk opgeslagen en verwerkt t.o.v. van de plaats waar de software wordt aangeboden. Zonder private key kunnen er geen geldige digitale handtekeningen voor gemodificeerde pakketten gegenereerd worden.

[Reactie gewijzigd door The Zep Man op 27 juli 2024 13:18]

Maar dat had dit geval dus niet kunnen voorkomen.
De nieuwe geïnfecteerde versie had een geldige handtekening (en hash) gehad.
Dit kan alleen voorkomen worden met een scan van NPM op kwaadaardige code wanneer deze wordt ingediend en voordat ze wordt gepubliceerd.
Zoals de app- en playstore al doen...
Nee, zie hier de keerzijde van mensen die libraries klakkeloos updaten zonder ze van te voren eerst te inspecteren. Het is altijd goed om na te gaan of een update goed is en er geen bugs of dergelijke oneffenheden in geslopen zijn.
In theorie heb je volkomen gelijk; maar in de praktijk is dat echt niet te doen.
In npm heb je last van wat dependency hell genoemd wordt. Misschien wil jij een handige package gebruiken, libA. Voor jouzelf heb je dus één dependency, libA. Alleen libA heeft zelf ook weer dependencies, libB t/m libG. En die hebben allemaal zelf ook weer dependencies, en die dependencies hebben ook weer dependencies en die ...!
Enfin, je begrijpt wat ik bedoel. Vaak als je binnen het npm-ecosysteem één library wil gebruiken, krijg je tientallen packages binnen. Het is echt ondoenlijk om al die code zelf te gaan inspecteren.
Als je een middelgrote applicatie hebt, dan heb je het al over tienduizenden regels code. Ook bij updates zou je die dan door moeten lopen.
In de praktijk is het dus echt niet mogelijk om dat zelf te checken.

Wat moet je dan, niet meer updaten? Nee, dat lijkt me ook geen optie.
Je wil natuurlijk je packages up-to-date houden om te profiteren van nieuwe features, security fixes, bug-fixes, performance verbeteringen.
Geen externe packages meer gebruiken? Kan, maar dan ben je wel honderden keren het wiel opnieuw aan het uitvinden. Bovendien is je ontwikkeltijd dan exponentieel langer en waarschijnlijk de kwaliteit ook lager (want je kan als dev-team nooit zoveel domeinkennis hebben als "het hele internet").. en dat vind je klant natuurlijk weer niet leuk (als je voor een klant werkt).

De perfecte oplossing kan ik je helaas ook niet geven.
Er zou misschien bijvoorbeeld vanuit NPM en/of Github beter gemonitord moeten worden als een maintainer zijn/haar package(s) overdraagt aan een ander. Wellicht dat er dan één of meerdere anderen moeten aangesteld worden om dat eventjes in de gaten te houden.. Maar ja, daar moet je dan wel de juiste mensen voor vinden. De meeste open source contributors doen het in hun vrije tijd, en die zijn schaars.

[Reactie gewijzigd door HyperioN op 27 juli 2024 13:18]

Tuurlijk is dat wel te doen. Kijk alleen naar de npm package die nodig hebt en check of daar issues mee zijn. Je bent echt niet de eerste die zo'n package gaat installeren en als er serieuze problemen mee zijn, heeft een ander die vast al wel gevonden en de bevindingen ergens op het web geslingerd.
Wacht een weekje af voordat je de update uitvoert. Of als je een nieuw project start waarbij je de dependencies nodig, check of de huidige versie deugd of pak een oudere versie.
Wederom: je redenering klopt in theorie maar gaat niet op in de praktijk. Wat als iedereen een week gaat wachten? Iemand moet de eerste zijn..
En is een week lang genoeg?
Dit verhaal is daar letterlijk een voorbeeld van, want de kwaadaardige code werd op 5 oktober geplaatst, en op 20 november pas ontdekt - terwijl deze package dus ook in honderden libraries geinclude wordt.

No offence, maar ik denk echt dat je het wat te rooskleurig inziet :) Open source is fantastisch en ontzettend veel dingen gaan heel erg goed; maar dit soort zaken zijn echt moeilijk te voorkomen en ik ben bang dat we het in de toekomst ook vaker gaan zien.

[Reactie gewijzigd door HyperioN op 27 juli 2024 13:18]

De code injectie van de 5 okt versie is pas vorige week ontdekt...
Dependency hell is wanneer, soms doordat het er zoveel zijn, er meerdere versies van dezelfde dependency in het uiteindelijke product eindigen. In Java kan dit leiden tot problemen tijdens runtime, omdat er maar 1 klasse kan 'winnen' en op het classpath terecht kan komen. Bij Javascript komen er geen runtime problemen voor en kunnen er prima meerdere versies van 1 library live komen te staan zonder Runtime issues.

Uiteraard heeft het hebben van veel dependencies wel nadelen, hoewel dat niet de traditionele Dependency Hell is. Eigenlijk is het vooral de lage kwaliteit van de NPM packages en het gebrek aan peer-review op die dependencies wat het grote probleem is.

De oplossing is daarom vrij simpel: gebruik alleen packages in je package.json waar je echt van weet wat de inhoud is, hoeveel erop wordt gecontribute, en wat het security profile is. Gebruik tools zoals Sonatype vulnerability scanner, of Snyk.io. Met andere woorden: doe in de JS wereld wat al 10+ jaar gebruikelijk is in de echte software wereld.
In Java is dit ook al opgelost. Er kan maar 1 module zijn die een package exporteert, anders start je applicatie geeneens.

Nu nog zorgen dat alle frameworks en applicaties geupdate worden naar dit model, dat is inderdaad nog een vrij grote uitdaging (en 1 die ik voorlopig nog niet zie gebeuren).

M.a.w. het framework ondersteunt het, alleen de community moet er nog mee leren werken.
Theorie en praktijk. Ga je daadwerkelijk alle packages die gebruikt worden elke keer keer op keer nalopen? Daar is de tijd veel te kostbaar voor. Helaas.
Nee, de praktijk is dat je de versies van alle packages waar je van afhankelijk bent bevriest en het dan pas uitrolt naar productie.

Dan kan een ontwikkelaar wel een update doen van één van die packages, maar die wordt niet automatisch in de productie-omgeving gegooid.
Alsof jij elke externe library die jij gebruikt gaat zitten nakijken, je gaat er eigenlijk van uit dat de maintainers dat wel voor je doen.
Doe je dat ook met een os upgrade? Nieuwe drivers? Nieuwe applicaties naast de jouwe? Het houd een keer op.
Zie hier een van de keerzijden van het gebruik van externe libraries.
Externe libraries van niet geheel gecontroleerde bronnen. Niemand neemt aan dat libraries van Microsoft dit soort dingen bevatten.

Als je Open Source gebruikt krijg je waar je voor betaald hebt. Steeds meer criminelen weten precies waar ze moeten zijn en het hele idee dat Open Source betekend dat mensen elkaar code bekijken is al sinds 1980 een achterhaald idee. Als iemand een module maakt die goed werkt en gratis is vind je die na een paar maanden overal. En omdat alles steeds complexer word is het steeds moeilijker om de mogelijke problemen te zien.

Mijn eigen dev teams gebruikte ook meer en meer van dit soort delen code. Op mijn vragen bij wie we moesten zijn om problemen op te lossen en wie er gecontroleerd had of de code (gratis of payware) geen malware bevatte kreeg ik alleen antwoorden dat 'iedereen het gebruikte' en dat het twee weken zou kosten om het zelf te doen. Ik heb toen drie devs twee maanden gegeven om alles na te kijken en alle code waarvan ze niet begrepen wat er gebeurde als verdacht aan te merken. Als die code niet ondertekend was wilde ik het eruit hebben. Moeilijke vergaderingen. maar als een dev een deel code wilde houden moest ie de verantwoordelijkheid ook nemen.

Om eerlijk te zijn ben ik me een ongeluk geschrokken. Software development is meer dan shoppen voor de modules die je nodig hebt en ze aan elkaar plakken. Het is ook je verantwoordelijkheid nemen dat die modules okay zijn. En zeker met jonge developers ontbrak dat in mijn bedrijf volkomen.
Niemand neemt aan dat libraries van Microsoft dit soort dingen bevatten.
Dat is dan een verkeerde aanname:
Dependencies van Microsoft Azure Data Studio: https://github.com/Micros...udio/network/dependencies
Wat staat er bovenaan? dominictarr/event-stream, de package waar dit artikel over gaat.
(Edit: inmiddels niet meer)

Ook als je de andere (open source-)producten van Microsoft bekijkt (bijv. VS Code, Typescript) zie je tientallen dependencies van willekeurige ontwikkelaars.
Zouden de Microsoft-devs al die dependencies regel voor regel checken? Ik betwijfel het, om eerlijk te zijn...

[Reactie gewijzigd door HyperioN op 27 juli 2024 13:18]

Ik snap je punt, maar ga je dan bijvoorbeeld je eigen oauth implementatie van 0 af aan maken? En hoeveel bugs en security issues zitten daar dan in?
M.n. het nadeel van open source-projecten van één enkele auteur.

Deze library werd initieel onderhouden door één enkele auteur (dominictarr), die dit project niet langer wilde onderhouden en vrij argeloos overdroeg naar een andere ontwikkelaar. Die heeft er toen kwaadaardige code in geïnjecteerd.

Bij grote partijen zal je dit niet snel krijgen.
Het probleem is dat de "grote partijen" ook gewoon packages gebruiken van individuele maintainers..
Dus zelf als jij denkt veilig te zitten door bijv. Angular te gebruiken (voorheen van Google, nu een groot contributor-team), dan krijg je alsnog al die kleine packages binnen: https://github.com/angular/angular/network/dependencies

[Reactie gewijzigd door HyperioN op 27 juli 2024 13:18]

Juist ja, want het wiel zelf uitvinden is is lekker ;) Laten we het eens over de nadelen daar van hebben.
Wel benieuwd hoe de code injectie plaats heeft kunnen vinden. Geen gpg signing van alle commits of keys gestolen, Github account gehacked?

Mis die diepgang wel in het artikel :/
De auteur heeft letterlijk gewoon iemand anders 'maintainer' gemaakt, zie ook https://github.com/domini...16#issuecomment-440927400 :+ Drama ensues! Wakkert wel een goede discussie aan m.b.t. open source maintainers imo, gelukkig sponseren grote bedrijven tegenwoordig ook bepaalde projecten (Vue.js bijvb.). Vind het nog altijd ongelovelijk hoe mensen hun leven wijden aan het maintainen van zulke packages (en hoe weinig credit ze daarvoor terugkrijgen).
ironisch dat deze module dan ook in vuejs-cli zit ;)
ironisch dat deze module dan ook in vuejs-cli zit ;)
event-stream is een foundational dependency van een hele grote poel projecten. Het is ook compleet krankjorem dat er bij de NPM organisatie geen alarmbellen zijn gaan rinkelen toen de ontwikkelaar van dit project het eigendom over droeg.
Oh wauw, daar gaat de reputatie van je package en als developer :Y)
Maanden geleden was dit al voorspeld door David Gilbertson: I’m harvesting credit card numbers and passwords from your site. Here’s how..

De aanvaller heeft hier slim gebruik van gemaakt dat je niet alleen de unminified source code zelf aanleverd, maar ook de minified versie. In de unminfied code was de kwaadardige code niet aanwezig, in de minified versie daarentegen was deze er achteraan geplakt.

Het was dan ook eigenlijk geen kwestie van of, maar meer wanneer dit zou plaatsvinden. Ik vind dat het nog verbazingwekkend lang heeft geduurd voor iemand dit in een daadwerkelijke aanval heeft omgezet.

[Reactie gewijzigd door hello123456 op 27 juli 2024 13:18]

Leuk, uitgebreid van de laatste keer dat ik die voorbij zag komen :)

(overigens, niet vergeten dat onderaan dat verhaal wel staat dat het "harvesten" een fictioneel verhaal is, maar dat hij het wel even echt uitgeprobeerd heeft met non-malicious stukje code ;-) )
A serious note
I know that sometimes my relentless sarcasm can be difficult to unravel by people on the English-learning path (and also people in need of lightening up). So just to be clear, I have not created an npm package that steals information. This post is entirely fictional, but altogether plausible, and I hope at least a little educational.
[...]
And here’s an interesting thought experiment: I wrote an npm package last week, a little easing function. Totally unrelated to this post and I give you my word as a gentleman that there is nothing malicious in there. How nervous would you be adding that to your site?
(die easing function library heeft toch een 10-20'tal downloads per week)
Dit probleem heeft niets met npm te maken, dit kan gebeuren met elk package management systeem. Ik kan zonder moeite een Java library op Maven Central of een .NET library op NuGet gooien die vol met malware zit. Voor Java moet deze library signed zijn - prima, dan sign ik hem toch gewoon? En ook hier geldt dat de code op GitHub niet dezelfde hoeft te zijn als de gepushte libraries.

Het punt is dat third party libraries een mate van vertrouwen nodig hebben om succesvol te zijn. Als je elke willekeurige dependency zomaar include dan is het een kwestie van tijd voordat je dit soort problemen tegen komt.
Ik kom genoeg projecten tegen op github die ik graag uitprobeer, maar als je het met npm installeert blijf ik er zo ver mogelijk vandaan.
npm heeft direct NIETS hiermee te maken.

Enkel indirect omdat mensen klakkeloos libraries in hun packages.json gooien zonder door de code van de library te bladeren. En het feit dat de library in kwestie is overgedragen aan iemand die daarna kwaad in de zin ermee had.

Het had een willekeurig ander open source project kunnen zijn wat voor het grootst gedeelte door één hoofdontwikkelaar wordt onderhouden.
Dat snap ik ook wel.

Echter is een ecosysteem, waarbij projecten als isOdd en isEven als dependency gebruikt worden, niet echt serieus te nemen. Het voelt gewoon niet betrouwbaar en veilig, dus mijd ik het liever.

Op dit item kan niet meer gereageerd worden.