Aikido

Selbst die Gem-Liste kann den Code eines anderen ausführen

npm hat Installationsskripte zur optionalen Nutzung gemacht. Hier erfährst du, wie es bei RubyGems aussieht und wie du deine eigenen Installationen sichern kannst.

Verfasst von
Hunter Schwartz

Wenn Ihr Team läuft gem install oder Bundle installieren, auf Laptops oder in CI – dann ist dieser Beitrag genau das Richtige für Sie. So etwas hätte man nie erwartet. Ein Gem kann Code auf Ihrem Rechner ausführen, ohne dass ein Installationsskript erforderlich ist. Hier erfahren Sie, wie Sie nach vier Gems suchen können, die Daten abziehen und die wir auf RubyGems gefunden haben, wie Sie dieses Verhalten mit neuen Einstellungen deaktivieren und wie Sie sehen können, was „ Aikido “ in Ihrem Feed meldet.

TL;DR

  • Durch die Installation eines Ruby-Gems kann der Code dieses Gems ausgeführt werden, bevor Ihre App es lädt. Skripte zum Erstellen nativer Erweiterungen werden während der Installation ausgeführt. RubyGems-Plugins werden am Ende von gem install und ebenso bei jedem weiteren Edelstein Befehl, sogar Gem-Liste oder gem -v.
  • Npm hat dieses Problem bereits gelöst. Seit npm 12 sind Installationsskripte, einschließlich nativer Builds, nur noch auf Wunsch aktiv. RubyGems führt standardmäßig weiterhin Erweiterungs-Builds und Plugins aus.
  • Bei den stabilen RubyGems-Versionen und Bundler 4.0.x gibt es keine Möglichkeit, eines dieser beiden Verhaltensweisen zu deaktivieren. Die Vorabversionen von 4.1 enthalten zwar Einstellungen zum Deaktivieren, diese sind jedoch standardmäßig deaktiviert, sodass Sie sie selbst aktivieren müssen.
  • AikidoDie neuen Erkennungsregeln haben vier Gems auf RubyGems entdeckt, die zwischen 2013 und 2015 veröffentlicht wurden und den Benutzernamen des Installierenden, einen macOS-Screenshot oder ein Beacon an einen Remote-Server senden. Die gemeldeten Gems können zum Stand vom 4. November 2026 weiterhin installiert werden.
  • Um bekannte schädliche Gems zu blockieren, bevor sie den Rechner eines Entwicklers erreichen, verwenden Sie Aikido Device Protection. Es überprüft gem install und Bundle installieren unter Ruby 3 und höher auf Basis von „ Aikido “ von Intel und blockiert bekannte Malware, bevor diese das Dateisystem erreichen kann.
  • Wenn Sie Kunde von „ Aikido “ sind, kennzeichnet „ Aikido “ diese „Perlen“ in Ihrem Feed als Malware-Problem.
  • Wir haben dem RubyGems-Sicherheitsteam im Oktober die Erweiterung, die Ausführungspfade der Plugins und die vier von uns entdeckten Gems, die Daten abziehen, gemeldet. Das Team hat daraufhin Fragen zu den Opt-out-Flags gestellt und sich seitdem nicht weiter dazu geäußert.

Einstellungen zum Abmelden

(Die Opt-out-Flags und -Einstellungen gelten nur für 4.1.0.beta3):

  • Aktualisieren Sie RubyGems und Bundler auf Version 4.1.0.beta3.
  • Für gem install, weiter --no-build-extension --no-install-plugin.
  • Für Bundler führen Sie „bundle config set“ aus. --global no_build_extension true und bundle config set --global no_install_plugin true.
  • In CI ist Folgendes festgelegt: BUNDLE_NO_BUILD_EXTENSION=true und BUNDLE_NO_INSTALL_PLUGIN=truee.

Was tun, wenn Sie Ruby-Gems ausführen?

Wenn Sie Ruby-Gems ausführen, befolgen Sie diese Schritte, um sicherzustellen, dass Ihr System geschützt ist. Andernfalls können Sie diesen Abschnitt überspringen, um mehr über die Funktionsweise dieser Funktionen zu erfahren.

1. Suchen Sie nach den vier schädlichen Gems. Durchsuchen Sie in jedem Projekt alle Lockfiles im aktuellen Verzeichnis:

grep -rE '^ +(xmastree|ancient-city-ruby|hacky|et_phone_home) \(' --include=Gemfile.lock .

Um die installierten Gems zu überprüfen, ohne einen Gem-Befehl auszuführen (wodurch Plugins geladen würden), führen Sie Folgendes aus:

ruby -e 'Gem.path.each { |p| puts Dir.glob("#{p}/gems/*") }' | grep -E '/(xmastree|ancient-city-ruby|hacky|et_phone_home)-[0-9]'

Wenn Sie rbenv oder einen anderen Ruby-Versionsmanager verwenden, wiederholen Sie diesen Vorgang für jede Ruby-Version. Die betroffenen Versionen sind in der IOC-Tabelle am Ende dieses Beitrags aufgeführt.

2. Was tun, wenn Sie eines dieser Gems installiert haben? Die Payload wird während der Installation über eine Rakefile-Datei (native Erweiterung) ausgeführt, sodass bereits die Installation des Gems ausreichte, um sie auszuführen.

  • Beende alle Prozesse, die das Gem gestartet hat.
  • Deinstalliere das Gem. Ersetze GEM_NAME mit dem Namen des betroffenen Edelsteins: gem uninstall GEM_NAME --all --executables
  • Entfernen Sie das Gem aus den Abhängigkeiten Ihres Projekts. Löschen Sie es aus Ihrer Gemfile-Datei und führen Sie anschließend folgenden Befehl aus: Bundle installieren um das Gemfile.lock.
  • Bewerten Sie das potenzielle Risiko. Überprüfen Sie die Aktionen des „Gems“ im Abschnitt „IOC“, um festzustellen, welche Daten möglicherweise abgezogen wurden, und ergreifen Sie entsprechende Maßnahmen.

3. Überprüfen Sie, welche RubyGems-Plugins Sie installiert haben, und deinstallieren Sie nicht benötigte Plugins. Führen Sie den folgenden Befehl aus und listen Sie jedes Verzeichnis auf, das angezeigt wird. RubyGems lädt Plugins aus jedem Gem-Pfad, nicht nur aus dem Standardpfad.

ruby -e 'Gem.path.each { |p| puts Gem.plugindir(p) }'

4. Deaktivieren Sie die Erstellung von Erweiterungen und die Installation von Plugins, wo immer dies möglich ist. Dazu sind RubyGems und Bundler 4.1.0.beta3 erforderlich. Installieren Sie diese mit gem update --system 4.1.0.beta3, wodurch auch Bundler aktualisiert wird. (gem update --system --pre (wird nicht installiert.)

  • Für gem install, weiter --no-build-extension --no-install-plugin.
  • Für Bundler führe Folgendes aus: bundle config set --global no_build_extension true und bundle config set --global no_install_plugin true.
  • In CI ist Folgendes festgelegt: BUNDLE_NO_BUILD_EXTENSION=true und BUNDLE_NO_INSTALL_PLUGIN=true. Deaktivieren Sie die Erstellung von Erweiterungen nur in einem CI-Job, in dem die App nicht geladen wird, wie beispielsweise bei der Installation von Abhängigkeiten oder bei einem Prüfschritt, es sei denn, jedes Gem in Ihrem Bundle verfügt über einen vorkompilierten Build. Andernfalls können Ihre App und Ihre Tests keine Gems laden, bei denen die Erweiterungen übersprungen wurden.

Diese Einstellungen verhindern lediglich, dass der Code während der Installation ausgeführt wird. Der Code eines bösartigen Gems wird weiterhin ausgeführt, wenn Ihre App oder Ihre Tests ihn laden. Sie schützen also nur Schritte, die ausschließlich bei der Installation stattfinden, nicht jedoch alles, wofür das Bundle benötigt wird.

5. Es ist zu erwarten, dass Gems mit ausgelassenen Erweiterungen nicht mehr geladen werden. RubyGems lädt kein Gem, dessen deklarierte Erweiterungen nicht erstellt wurden, selbst wenn dessen nativer Code optional ist, und gibt folgende Meldung aus: Ignoring <gem> because its extensions are not built. Bundler behandelt das Gem als fehlend, daher bundle exec schlägt fehl mit Could not find <gem> in locally installed gems, und jedes Bundle installieren installiert es erneut.

Vorkompilierte Plattform-Builds deklarieren keine Erweiterungen, sodass sie dennoch geladen werden. Sobald Sie ein Gem überprüft haben, fügen Sie dessen Erweiterung wieder hinzu:

  • gem install: ausführen gem pristine <gem> --extensions. Dabei wird auch das Plugin des Gems installiert, sofern vorhanden, und dieses Plugin wird anschließend ausgeführt. Um nur das Plugin zu installieren, führen Sie folgenden Befehl aus: gem pristine <gem> --only-plugins.
  • Bundler: nicht festgelegt no_build_extension und ausführen Bundle installieren wieder. Weiter no_install_plugin Setzen Sie diese Option, wenn Sie möchten, dass Plugins deaktiviert bleiben. Dadurch werden alle Gems im Bundle neu erstellt, deren Erweiterungen übersprungen wurden. In der Warnmeldung von Bundler selbst wird empfohlen, folgenden Befehl auszuführen: bundle pristine <gem>, aber in 4.1.0.beta3 schlägt das mit demselben Fehler fehl Konnte nicht gefunden werden Fehler, da Bundler das Gem nicht als installiert erkennt. Bundle „Pristine“ Das funktioniert zwar bei einem Gem, bei dem lediglich das Plugin übersprungen wurde, allerdings wird dabei auch die Erweiterung neu erstellt.

6. Überprüfen Sie neue oder kürzlich aktualisierte Gems, bevor Sie sie installieren. Führen Sie in einer sauberen Umgebung folgenden Befehl aus: gem fetch und dann gem entpacken. Lesen extconf.rb, mkrf_conf.rb, alle unter Erweiterungen in der GemSpec und alle lib/rubygems_plugin.rb.

Wir haben diese Befehle unter Ruby 4.0.9 mit RubyGems und Bundler 4.0.23 (der aktuellen stabilen Version) sowie 4.1.0.beta3 getestet. Die Opt-out-Flags, Einstellungen und Wiederherstellungsschritte gelten nur für 4.1.0.beta3.

Zwei Möglichkeiten, wie ein Gem Code auf Ihrem Rechner ausführt

Ruby bietet zwei Möglichkeiten, den Code eines Gems ohne ein Installationsskript auszuführen: Native Extensions und RubyGems-Plugins. Beide ermöglichen es einem Angreifer, eine Schadfunktion auszuführen, bevor ein Entwickler die Anwendung startet. Ein bösartiges Skript zum Erstellen einer Erweiterung könnte während der Installation Anmeldedaten stehlen. Ein bösartiges RubyGems-Plugin könnte dasselbe am Ende desselben gem install, und zwar jedes Mal, wenn der Entwickler einen Gem-Befehl ausführt.

Methode 1: Native Erweiterungen

Ein Edelstein besagt Erweiterungen in seiner Gemspec (dem Manifest des Gems). Wenn eines davon ein extconf.rb Im Build-Skript führt RubyGems diese Ruby-Datei während der Installation aus und führt anschließend das dadurch generierte Makefile aus. Was auch immer in dieser Datei in Ruby geschrieben ist, wird bei der Installation ausgeführt – genauso wie node-gyp native Builds für npm-Pakete ausführt.

RubyGems läuft ebenfalls mkrf_conf.rb als Ruby-Skript während der Installation, wenn ein Gem eines unter Erweiterungen, und führt dann Rechen im selben Verzeichnis. Neben diesen Ruby-Skripten unterstützt RubyGems Builds mit „configure“, „Rakefile“, CMake und Cargo, wobei jeweils das jeweilige Build-Tool den Code ausführt.

Was ein Angreifer zu einem Edelstein beiträgt:

  • Eine Datei, extconf.rb oder mkrf_conf.rb (zum Beispiel, ext/foo/extconf.rb), das beliebiges Ruby enthalten kann
  • Eine Zeile in der Gemspec: spec.extensions = ["ext/foo/extconf.rb"]

Warum man sich da leicht täuschen lässt: Viele seriöse Programme wie bcrypt und bootsnap verwenden extconf.rb. Sie sieht aus wie jede andere Build-Datei, und es gibt keinen separaten Abschnitt „Skripte“, der die Aufmerksamkeit eines Prüfers auf sich ziehen würde.

Methode 2: RubyGems-Plugins

Wenn ein Gem eine Datei mit dem Namen rubygems_plugin.rb, RubyGems installiert es als Plugin. Bei der Installation schreibt RubyGems einen kleinen Loader für diese Datei in sein Plugin-Verzeichnis, und jeder spätere `gem`-Befehl lädt den Inhalt dieses Verzeichnisses.

Was ein Angreifer zu einem Gem hinzufügt: Eine Datei mit genau diesem Namen rubygems_plugin.rb am Anfang eines deklarierten „require“-Pfads, normalerweise lib/rubygems_plugin.rb.

Wenn es läuft:

  • RubyGems lädt ein neu installiertes Plugin sofort am Ende von gem install (sofern keine andere Version installiert ist).
  • Anschließend werden bei jedem „gem“-Befehl alle installierten Plugins geladen, einschließlich schreibgeschützter Befehle wie Gem-Liste, Gem-Suche, und gem -vsowie Befehle, die sich auf andere Edelsteine beziehen.
  • Das Plugin wird bei jedem Befehl wiederholt ausgeführt, solange das Gem installiert bleibt.

Warum man das leicht übersehen kann: Es handelt sich um eine Datei in lib/ mit einem speziellen Namen. Es ist keine separate Plugin-Deklaration erforderlich, sodass ein Prüfer, der nach expliziten Ausführungs-Hooks sucht, dies möglicherweise übersehen könnte. RubyGems meldet Ausnahmen beim Laden von Plugins als Warnungen, sodass der Befehl auch dann weiterläuft, wenn ein Plugin fehlschlägt.

Gems, die Bundler in Anbieter/Paket oder eine individuelle BUNDLE_PATH funktionieren ein wenig anders. Ein einfaches Gem-Liste lädt deren Plugins nicht, sondern bundle exec gem list tut.

npm hat das schon hinter sich

Npm hat auf die harte Tour gelernt, dass die Sicherheit bei der Installation mehr als nur die Skripte des Lebenszyklus umfassen muss. In der „Miasma“-Kampagne, verlegten die Angreifer ihren Auslösepunkt von package.json in binding.gyp, die native Build-Datei von npm, die node-gyp wird bei der Installation automatisch ausgeführt. Überprüft, ob nur die überwachten package.json Die Installation von Hooks wurde übersehen. NPM 12 reagierte darauf, indem es die Skripte zur Installation von Abhängigkeiten – einschließlich der „node-gyp“-Builds – optional machte. 

Ruby hat das gleiche Problem, und es gibt noch keine stabile Version, die es behebt. Eine „extconf.rb“-Datei sieht wie eine gewöhnliche Build-Konfiguration aus, und eine „rubygems_plugin.rb“-Datei benötigt überhaupt keine Deklaration, sodass keine der beiden wie ein Installationsskript aussieht, das überprüft werden müsste. Auch Ruby-Entwickler sind bereits ins Visier von Angreifern geraten. Im Rahmen der „SleeperGem“-Kampagne veröffentlichten Angreifer bösartige Gem-Versionen über offenbar kompromittierte, inaktive Konten von Betreuern.

Ein aktuelles Beispiel zeigt, dass dieser Ausführungspfad zur Verbreitung von Malware genutzt wird. Sowohl Oliver Smith vom Forschungsteam von Aikido als auch Socket berichteten über die Version 1.0.1 von „strutil-core“. Deren „extconf.rb“-Datei lud die „Bun“-Laufzeitumgebung herunter und startete während der Installation eine gebündelte Payload zum Diebstahl von Anmeldedaten. Die Malware weist funktional identische Komponenten wie zuvor dokumentierte Nachkommen von Shai-Hulud auf, wobei der gemeinsame Code jedoch keinen Rückschluss darauf zulässt, wer dahinter steckt. RubyGems hat beide veröffentlichten Versionen am 1. November entfernt. Dieser Fall stand in keinem Zusammenhang mit unserer Offenlegung im Oktober, veranschaulicht jedoch denselben oben beschriebenen Ausführungspfad über native Erweiterungen.

Jedes 13. beliebte Juwel führt bei der Installation Code aus

Am 26. Oktober 2026 haben wir die rund 1.000 Gems mit den meisten Downloads von bestgems.org herangezogen und deren veröffentlichte Gemspecs durchgesehen, um zu verstehen, wie verbreitet native Erweiterungen und Plugin-Dateien heutzutage sind. Beachten Sie dabei, dass die Tatsache, ob Gems diese Mechanismen zur Installationszeit derzeit nutzen oder nicht, kein Maß für das Risiko darstellt, da Angreifer sie jederzeit ausnutzen können. Es zeigt jedoch, wie normal diese Build-Schritte für einen Prüfer erscheinen.

  • Native Erweiterungen: 74 von 997 (etwa 1 von 13) deklarieren Build-Schritte für Erweiterungen, darunter bcrypt, bigdecimal, bootsnap, bson, debug sowie viele gängige Datenbank- und Parsing-Gems.
  • Plugin-Dateien: 2 von 997 (rdoc und yard) sind enthalten rubygems_plugin.rb. Beide werden bei der Installation in der aktiven Umgebung bei späteren Gem-Befehlen geladen.

Vier Proof-of-Concept-Programme, die Daten an den Urheber senden, lassen sich nach wie vor installieren

Beim Testen unserer Erkennungsregeln sind wir auf vier Juwelen gestoßen, die zwischen 2013 und 2015 veröffentlicht wurden und bei der Installation Code ausführen: xmastree, ancient-city-ruby, hacky und et_phone_home. Sie senden den Benutzernamen des Installierenden, einen unbemerkten macOS-Screenshot oder ein einfaches Signal an einen Remote-Server.

Sie sehen zwar wie Proof-of-Concept- oder Forschungstests aus, werden aber dennoch nach der Installation ausgeführt und senden Daten vom Rechner ab. Die betroffenen Versionen und Ziele sind in der IOC-Tabelle am Ende dieses Beitrags aufgeführt.

Zeitplan für die Veröffentlichung unserer Ergebnisse

  • 27. Oktober 2026: Wir haben dem RubyGems-Sicherheitsteam die Ausführungswege für Erweiterungen und Plugins gemeldet. Das Team hat daraufhin Fragen zu den Opt-out-Flags gestellt und sich seitdem nicht weiter dazu geäußert.
  • 30. Oktober 2026: Wir haben die vier Gems dem RubyGems-Sicherheitsteam gemeldet.
  • 4. November 2026: Die aufgeführten Gems sind weiterhin auf RubyGems verfügbar.

Stabile RubyGems lassen sich nicht einfach abschalten

Man könnte meinen, man könne die Flags einfach so übergeben --no-build-extension und --no-install-plugin zu gem. Allerdings gibt es diese beiden Flags nur in den Vorabversionen von 4.1, und selbst in 4.1.0.beta3 bleiben beide Verhaltensweisen aktiv, sofern man sie nicht deaktiviert. In der stabilen Version 4.0.x, gem install lehnt sie als ungültige Option ab.

InstallationspfadSteuerelemente für die Erstellung von Erweiterungen und die Installation von Plugins
gem install, stabile Version 4.0.xKeine. Die Flags existieren nicht.
Bundle installieren, stabile Version 4.0.xKeine. Die Einstellungen gibt es nicht.
gem install, 4.1.0.beta3--no-build-extension und --no-install-plugin Flags. Beide Verhaltensweisen bleiben aktiv, solange Sie sie nicht übergeben.
Bundle installieren, 4.1.0.beta3no_build_extension und no_install_plugin Einstellungen in Paketkonfiguration. Beide Einstellungen bleiben aktiv, sofern Sie sie nicht ändern.

Wie Aikido dies erkennt

Wenn Sie Aikido nutzen, überprüfen Sie Ihren zentralen Feed und filtern Sie nach Malware-Problemen. Wenn ein bösartiges Gem in einem der Lockfiles Ihrer Repos auftaucht, wird es von Aikido als Malware-Problem markiert. Aikido führt jede Nacht einen erneuten Scan durch, wir empfehlen jedoch, sofort einen manuellen Scan auszulösen, wenn Sie glauben, dass Sie betroffen sein könnten.

Um bekannte schädliche Gems zu stoppen, bevor sie den Rechner eines Entwicklers erreichen, nutzen Sie den „Aikido -Geräteschutz“. Dieser überprüft „gem install“ und „bundle install“ unter Ruby 3 und höher anhand von Aikido Intel und blockiert bekannte Malware, bevor sie das Dateisystem erreicht. Sie können ihn über Ihr Mobile-Device-Management-Tool (MDM) bereitstellen.

IOCs für die vier Edelsteine, über die wir berichtet haben.

EdelsteinVersionGemarkiert von AikidoFunktionsweise
Weihnachtsbaum0.0.2JaRakefile in Erweiterungen. Beiträge whoami Ausgabe an http://cryptic-ocean-8847.herokuapp.com/usernames bei der Installation.
Weihnachtsbaum0.0.1JaGleiche Nutzlast und URL, aber Erweiterungen ist leer, daher wird es bei der Installation nicht ausgeführt. Es wird nur ausgeführt, wenn jemand Rechen im Gem-Verzeichnis.
antike-stadt-ruby2013.1JaRakefile in Erweiterungen. Beiträge whoami Ausgabe an http://stark-samurai-8122.herokuapp.com/logs, und löscht sich anschließend selbst.
hackig0.0.2 (einzige Version)JaRakefile in Erweiterungen. Macht einen Screenshot im Hintergrund und lädt ihn hoch auf http://appfolio.herokuapp.com/upload Bei der Installation wird der Screenshot gelöscht, anschließend löscht sich das Programm selbst. Funktioniert nur unter macOS.
et_phone_home0.1.0 (einzige Version)JaRakefile in Erweiterungen. Sendet eine GET-Anfrage an http://176.31.142.25/ruby_no_way_you_got_here_randomly bei der Installation.
Teilen:

https://www.aikido.dev/blog/gem-list-runs-someone-elses-code

Nach Malware scannen

Kostenlos starten
4.7/5
Falschpositive Ergebnisse leid?

Probieren Sie Aikido, wie 100.000 andere.
Jetzt starten
Erhalten Sie eine personalisierte Führung

Von über 100.000 Teams vertraut

Jetzt buchen
Scannen Sie Ihre App nach IDORs und realen Angriffspfaden

Von über 100.000 Teams vertraut

Scan starten
Erfahren Sie, wie KI-Penetrationstests Ihre App testen

Von über 100.000 Teams vertraut

Testen starten

Werden Sie noch heute sicher,
schnell und kostenlos.

Sichern Sie Code, Cloud und Laufzeit in einem zentralen System.
Verbinden Sie ein Repository, um herauszufinden, was die Reasoning Agents in Ihrer Codebasis finden.

Keine Kreditkarte erforderlich | Scan-Ergebnisse in 32 Sekunden.
Von über 150.000 Unternehmen vertraut