Seite wählen

NETWAYS Blog

Viel hilft viel? Nicht immer.

Wenn Systeme gesized werden, fällt üblicherweise bald die Frage: “Was brauchen wir denn besonders viel? CPU? Ram? I/O?” Elasticsearch ist ein schönes Beispiel, in dem man einfach antworten kann: “Alles!” Es braucht CPU, Ram, I/O, Platz, Netzwerkdurchsatz und alles möglichst viel. Tatsächlich braucht es eigentlich möglichst viele Maschinen, die dann jeweils von allem etwas mitbringen – daher auch die Empfehlung, immer auf Hardware zu setzen, weil sonst irgendwas zum Flaschenhals wird (z.B. das SAN).

Es gibt aber eine Ausnahme und schuld ist, wie so oft ( 😉 ): Java. Gibt man Java zu viel Ram, stellt es intern die Verwaltung seiner Pointer um und verliert dadurch so viel Performance, dass man noch ziemlich viel zusätzlichen Ram drauf schmeissen muss, um das wieder auszugleichen. Die genauen Zahlen variieren, liegen aber ungefähr so: Wenn man eine Schwelle überschreitet, die zwischen 30 und 32GB liegt, fällt die Performance so ab, dass man erst bei ca. 46GB wieder auf dem Stand von vor Überschreiten der Schwelle ist. Die ca. 16GB sind also verloren.

Da die Schwelle aber variabel ist, trägt man entweder zu niedrig an oder überschreitet sie unbemerkt. Elasticsearch bietet dabei aber eine einfache Möglichkeit, herauszufinden, ob die Schwelle schon überschritten wurde:

$ curl -s -XGET http://elastic02-hot.widhalm.or.at:9200/_nodes | jq '.nodes[].jvm.using_compressed_ordinary_object_pointers'
"true"
"true"
"true"
"true"
"true"

Dabei fragt man über die API eines Knoten den Zustand aller Knoten ab. Wenn so viele true als Antwort kommen, wie Knoten im Cluster sind, dann ist alles ok. Jedes false zeigt einen Knoten, der zu viel Ram zur Verfügung hat. Gesetzt in /etc/elasticsearch/jvm.options. Als Lösung: Einfach weniger Ram eintragen und die Knoten neu starten (immer nur dann, wenn der Cluster gerade im Status “green” ist)

Wer jq noch nicht installiert hat, sollte das nachholen, da damit wunderbar JSON geparsed werden kann. Ein paar Beispiele gibt’s hier.

Den Check würde ich übrigens regelmässig wiederholen. Ich habe noch keine genauen Daten, wie sich z.B. Updates darauf auswirken und ob sie nicht auch wirklich variabel sein kann.

(Photo by Liam Briese on Unsplash)

Thomas Widhalm
Thomas Widhalm
Lead Support Engineer

Thomas war Systemadministrator an einer österreichischen Universität und da besonders für Linux und Unix zuständig. Seit 2013 möchte er aber lieber die große weite Welt sehen und hat sich deshalb dem NETWAYS Consulting Team angeschlossen. Er möchte ausserdem möglichst weit verbreiten, wie und wie einfach man persönliche Kommunikation sicher verschlüsseln kann, damit nicht dauernd über fehlenden Datenschutz gejammert, sondern endlich was dagegen unternommen wird. Mittlerweile wird er zum logstash - Guy bei NETWAYS und hält...

OSDC 2018 Countdown – 65 days until Berlin

OSDC Countdown 2018 : Cloud Native Java by Josh Long

 
OSDC 2018 | Simplifying complex IT infrastructures with Open Source | June 12-13 Berlin
In 2017, Josh Long talked about how they look at how high-performance organizations like Ticketmaster, Alibaba, and Netflix and make short work of that complexity with Spring Boot, Spring Cloud and more.
Join us in Berlin and take part in the 10th internationally recognised Open Source Datacenter Conference 2018. There you will experience experts report on the latest development trends in Datacenter solutions and best practices with pro administrators and architects.
It is time to add on to your knowledge with Open Source Community members from all over the world.
For more information and to register visit osdc.de
See you in Berlin!
 

Keya Kher
Keya Kher
Creative Designer

Keya ist seit Oktober 2017 in unserem Marketing Team. Sie kennt sich mit Social Media Marketing aus und ist auf dem Weg, ein Grafikdesign-Profi zu werden. Wenn sie sich nicht kreativ auslebt, entdeckt sie andere Städte oder schmökert in einem Buch. Ihr Favorit ist “The Shiva Trilogy”.  

Es trifft mich wie ein Blitz …

Java-Logo
… heute früh meldete Heise Security einen seit ca. neun Monaten bekannten Exploit, der sich als besonders kritisch einstuft.
Zu diesem Zeitpunkt war ich gerade in einem Meeting mit Bernd und bin fast aus allen Wolken gefallen, als Sebastian mit dieser Nachricht in der Tür stand.
Ich bot an dieser Meldung genauer auf den Grund zu gehen, da ich selber begeisterter Java Entwickler bin und mich wie vermutlich auch viele von euch direkt oder eben auch indirekt mit Java und dem erweiterten Stack tagtäglich beschäftige.
Im Netz kursiert seit dem 6. November der folgende Artikel, dessen Autor Herr Stephen Breen, sehr genau, fast schon spielerisch beschreibt, wie dieser Exploit denn genau funktioniert.
Er schreibt dort im wesentlichen über die in Java schon seit Version 1.1 verfügbare ‘Serializable’ Schnittstelle, die es dem Programmierer ermöglicht fertig instanziierte Java Objekte über das Netzwerk zu senden oder auch von Festspeichern zu lesen. Diese Klasse ist allerdings nur der kleinere Teil des Übels, genauer gesagt ist es die Methode “InvokerTransformer” der “Apache CommonCollections API” die hier über die “Java Reflections API” es einem möglichen Angreifer hier Kinderleicht macht seinen Schadcode auf dem Zielsystem zur Ausführung zu bringen.
Nun könnte man fast meinen das einen das ja nicht wirklich betrifft, da muss ich euch leider enttäuschen und das sogar berechtigterweise.
Folgende Szenarien um das Problem im wesentlichen zu konkretisieren:

  • Servlet Container sowie Application Server verwenden diese API, wie im Artikel zu lesen ist, auch um Cookies und HTTP Header zu lesen. Das ist im ersten Moment noch nicht so kritisch, nur werden heutzutage auch viele Cross-Site-Request-Forgery und andere Angriffe dazu verwendet die Systeme der Wahl erfolgreich zu attackieren.
    Ein Angreifer könnte versuchen über entsprechende HTTP Header mit Cookie Payload ein bösartiges Objekt seiner Wahl einzubetten, das wiederum wenn auf dem Ziel System einmal angekommen, im ersten Moment Zugriff auf die der dort laufenden Anwendung zu Verfügung stehenden Klassen nutzen kann. Hier ist es dann bereits ein leichtes dem Application Server bzw. ServletContainer einen separaten URL Context ( zum Beispiel unter http://application.yourdomain.com/nasty-little-exploit ) mit anderen Funktionen unterzujubeln. Et Voila der Schaden wäre bereits immens.
    Auch ein simpler Download als Injected Java Objekt könnte hier den Rest des Ziel Systems mit entsprechenden Schadcode über eine Art Bootstrap Job infizieren.
    Um dem vorher gehenden Beispiel noch einmal etwas Würze zu verleihen, einen bereits bestehenden URL Context einer großen Bank könnte so manipuliert werden, um Kundendaten abzugreifen. Auch hier wäre der Schaden nicht zu ermessen.
  • Die Software von Drittanbietern ist davon mit unter auch betroffen. Vor allem wenn sie die oben genannte Schnittstelle verwendet oder sogar muss. Hier sollte man schnell Handeln aber auf keinen Fall das Problem ignorieren. Allein anzunehmen das hier ja bereits verschlüsselte Kommunikation stattfindet, schütz vor diesem Exploit nicht.
  • Ich schlage ihnen daher vor, den Rat des Autors zu beherzigen und diese Schnittstelle aus der Apache CommonCollections API zu verbannen, allein die Nutzung der Application einzustellen um anschließend ein komplettes Refacturing der Anwendungen vorzunehmen verursacht vermutlich sehr hohe Kosten und ist hier mit der Gefahr verbunden sich einem weiteren Exploit zu schaffen, jedoch recht schnell geschehen. Schnelle Änderungen schaffen immer wieder neue Bugs und vermutlich auch neue noch unbekannte ZeroDay Vectoren.

Dem einen oder anderen von euch stellen sich hier vermutlich schon die Nackenhaare auf, daher wollen wir nun lieber über die Deeskalation bzw. möglichen Lösungen kümmern, was gilt es nun zu tun!?

  • Evaluieren ob die Apache CommonCollections API auf dem eigenen Systemen existiert.
  • Prüfen ob die eingesetzte Java Software von dieser Gebrauch macht.
    • Wenn dem so ist, sollte die Anwendung aus der DMZ entfernt werden, das blockieren der von außerhalb erreichbaren Ports genügt im ersten Moment bereits.
    • Wenn dem nicht so ist, dann Schwein gehabt.
  • Sofern die betroffenen Anwendungen ermittelt werden konnten, sollten folgende Punkte abgearbeitet werden.
    • Test der Anwendung in isolierter Umgebung ( Docker kann hierbei recht hilfreich sein ) mit der Apache CommonCollections API. Wobei vor Beginn die org/apache/commons/collections/functors/InvokerTransformer.class bereits aus der API entfernt sein sollte.
      Wenn es hier nichts zu beanstanden gibt und die Application auch ohne diese Schnittstelle zu laufen scheint, kann diese wieder in den Betrieb überführt werden.
    • Sollte die Anwendung nicht korrekt funktionieren, wird empfohlen diese unter Vorbehalt nur den eig. Mitarbeitern zur Verfügung zu stellen, sollte es sich bei der Anwendung allerdings, um eine des Kunden handeln, sieht es da schon etwas schwieriger aus, wobei sich vmtl. kein Kunde den damit einhergehenden Gefahren gerne ausgesetzt sieht.
      Hier sollte dem Kunden angeraten werden, die Application bis zu einem erfolgreichen Security Audit vom Netz zu nehmen.

Weitere Lösungsansätze sind derzeit noch nicht bekannt, wir versuchen euch aber entsprechend auf dem Laufenden zu halten.
Nützliche Links:

Link Inhalt
http://www.heise.de/security/meldung/Zero-Day-Alarm-fuer-viele-Server-mit-Java-2913605.html Heise Security Artikel
http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/ der Exploit im Detail
https://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/functors/InvokerTransformer.html Javadoc zum betroffenen Interface
https://github.com/frohoff/ysoserial das daraus entwickelte Framework für Penetration Tests
https://www.cvedetails.com/vulnerability-list/vendor_id-93/product_id-19117/Oracle-JRE.html Java CVE – Übersicht

Wer die Wahl hat, hat die Qual?

Wer jetzt ein politisches Statement zur Wahl erwartet, wird wohl enttäuscht werden, da sich dieser Blogpost um ein nettes kleines Werkzeug namens update-alternatives (oder je nach Distribution auch nur alternatives) dreht. Aber vorweg: Im Gegensatz zur Wahl kann ich hier meine Entscheidung jederzeit und nicht erst nach 4 Jahren überdenken.
Aktueller Auslöser für den Post ist mal wieder eine Kundendiskussion wegen verschiedener Java-Versionen, aber hierauf ist update-alternatives nicht beschränkt. Das Werkzeug dient der Konfiguration eines netten Features unter Linux. Statt dem eigentlich Programmaufruf findet hier eine Verlinkung statt, die es ermöglicht schnell zwischen den Alternativen umzuschalten um einen Standard festzulegen. Wer statt dem Standard seine persönliche Wunschalternative benutzen möchte hat hierbei trotzdem noch die Wahl diese direkt aufzurufen.
Da sich die Funktion am besten an einem Beispiel erklärt, möchte ich als erstes Beispiel den Editor unter Debian verwenden.
Debian verwendet update-alternatives um den Standardeditor festzulegen, aufzurufen ist dieser mit dem Kommando editor. Überprüft man nun was sich dahinter verbirgt sieht man folgendes:
# ls -l $(which editor)
lrwxrwxrwx 1 root root 24 14. Mär 10:42 /usr/bin/editor -> /etc/alternatives/editor

Ok, der Programmaufruf editor zeigt also auf eine Datei unter /etc/alternatives. /etc ist laut Filesystem Hierarchy Standard für “Host-specific system configuration”, handelt es sich also bei dieser datei um eine Konfigurationsdatei?
# ls -l /etc/alternatives/editor
lrwxrwxrwx 1 root root 9 14. Mär 10:42 /etc/alternatives/editor -> /bin/nano

Wie man sieht ist es keine Konfigurationsdatei sondern ein weiterer Link auf das eigentliche Programm.
Da mir persönlich diese Vorgabe nicht gefällt und ich die Kontrolle über das System habe, möchte ich mir vim als Standard setzen, wofür folgender Aufruf reicht (vorausgesetzt vim ist installiert):
# update-alternatives --config editor
Es gibt 3 Auswahlmöglichkeiten für die Alternative editor (welche /usr/bin/editor bereitstellen).
Auswahl Pfad Priorität Status
------------------------------------------------------------
* 0 /bin/nano 40 Auto-Modus
1 /bin/nano 40 manueller Modus
2 /usr/bin/vim.basic 30 manueller Modus
3 /usr/bin/vim.tiny 10 manueller Modus
Drücken Sie die Eingabetaste, um die aktuelle Wahl[*] beizubehalten,
oder geben Sie die Auswahlnummer ein: 2
update-alternatives: /usr/bin/vim.basic wird verwendet, um /usr/bin/editor (editor) im manueller Modus bereitzustellen.

Dies hat folgende Änderung zur Folge:
# ls -l /etc/alternatives/editor
lrwxrwxrwx 1 root root 18 9. Sep 13:51 /etc/alternatives/editor -> /usr/bin/vim.basic

Anhand dieses einfachen Beispiels kann man bereits sehen wie einfach es ist dieses System zu nutzen, dies ist aber nur möglich wenn dies die Packager entsprechend gut unterstützen. Hier kommen wir dann wieder zu meinem Beispiel java, diesmal auf einem Fedora-System.
Hier wird in unserem openjdk-1.7.0-Paket folgendes Skript verwendet um bei der Installation openjdk als eine Alternative für Java einzurichten:
ext=.gz
alternatives \
--install /usr/bin/java java /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java 170025 \
--slave /usr/lib/jvm/jre jre /usr/lib/jvm/jre-1.7.0-openjdk.x86_64 \
--slave /usr/lib/jvm-exports/jre jre_exports /usr/lib/jvm-exports/jre-1.7.0-openjdk.x86_64 \
--slave /usr/bin/keytool keytool /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/keytool \
--slave /usr/bin/orbd orbd /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/orbd \
--slave /usr/bin/pack200 pack200 /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/pack200 \
--slave /usr/bin/rmid rmid /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/rmid \
--slave /usr/bin/rmiregistry rmiregistry /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/rmiregistry \
--slave /usr/bin/servertool servertool /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/servertool \
--slave /usr/bin/tnameserv tnameserv /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/tnameserv \
--slave /usr/bin/unpack200 unpack200 /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/unpack200 \
--slave /usr/share/man/man1/java.1$ext java.1$ext /usr/share/man/man1/java-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/keytool.1$ext keytool.1$ext /usr/share/man/man1/keytool-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/orbd.1$ext orbd.1$ext /usr/share/man/man1/orbd-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/pack200.1$ext pack200.1$ext /usr/share/man/man1/pack200-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/rmid.1$ext rmid.1$ext /usr/share/man/man1/rmid-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/rmiregistry.1$ext rmiregistry.1$ext /usr/share/man/man1/rmiregistry-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/servertool.1$ext servertool.1$ext /usr/share/man/man1/servertool-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/tnameserv.1$ext tnameserv.1$ext /usr/share/man/man1/tnameserv-java-1.7.0-openjdk.1$ext \
--slave /usr/share/man/man1/unpack200.1$ext unpack200.1$ext /usr/share/man/man1/unpack200-java-1.7.0-openjdk.1$ext

Wie man sieht ist es also nicht nur möglich ein einzelnes Programm zu verlinken sondern auch alle dazugehörigen Unterprogramme und Hilfen, so dass nicht eine einzelne Komponente vergessen wird. Die Syntax hierbei ist:
alternatives --install <Link> <Name> <Pfad> <Priorität>
[--slave <Link> <Name> <Pfad>]*

Der Link ist hierbei der Programmaufruf, der Name legt fest wie die Datei unter /etc/alternatives heißt, der Pfad ist der Pfad zum eigentlich Programm und die Priorität wird nur für das Hauptprogramm festgelegt und ist für die automatische Auswahl der best-möglichen Alternative zuständig, wobei die höchste Zahl gewinnt.
Damit wäre ich auch wieder bei meinem Ausgangspunkt für die geführte Diskussion beim Kunden, denn leider nutzt das Java-Paket von Oracle update-alternatives nicht. Schlimmer sogar ist dass es seine eigene Logik hierfür mitbringt, die update-alternatives für java zerstört. Wer es trotzdem nutzen möchte, kann auf den Tar-Ball zurückgreifen und diesen selbst mit dem oben stehenden Kommando und angepassten Pfaden einrichten. Dadurch wäre es dann möglich als Admin festzulegen welches Java standardmäßig zu verwenden ist um die Version mit den aktuellsten Sicherheitsfixes vorzugeben. Läuft etwas mit dieser Version nicht muss dort nur statt java aus dem Suchpfad java mit vollem Pfad aufgerufen werden.
Natürlich kann ich es auch nutzen um meine eigene Software parallel zu installieren, zu testen und irgendwann nach erfolgreichem Test auf die neue Version umzuschalten. Ein Beispiel gefällig?
LConf mit Versionsnummer im Präfix:
update-alternatives \
--install /usr/bin/LConfExport LConfExport /usr/local/LConf-1.2.1/bin/LConfExport.pl 10201 \
--slave /usr/bin/LConfImport LConfImport /usr/local/LConf-1.2.1/bin/LConfImport.pl \
--slave /usr/bin/LConfSlaveExport LConfSlaveExport /usr/local/LConf-1.2.1/bin/LConfSlaveExport.pl \
--slave /usr/bin/LConfSlaveExportRules LConfSlaveExportRules /usr/local/LConf-1.2.1/bin/LConfSlaveExportRules.pl \
--slave /usr/bin/LConfSlaveSync LConfSlaveSync /usr/local/LConf-1.2.1/bin/LConfSlaveSync.pl \
--slave /usr/bin/LConfDeploy LConfDeploy /usr/local/LConf-1.2.1/bin/LConfDeploy.sh
update-alternatives \
--install /usr/bin/LConfExport LConfExport /usr/local/LConf-1.3.0/bin/LConfExport.pl 10300 \
--slave /usr/bin/LConfImport LConfImport /usr/local/LConf-1.3.0/bin/LConfImport.pl \
--slave /usr/bin/LConfSlaveExport LConfSlaveExport /usr/local/LConf-1.3.0/bin/LConfSlaveExport.pl \
--slave /usr/bin/LConfSlaveExportRules LConfSlaveExportRules /usr/local/LConf-1.3.0/bin/LConfSlaveExportRules.pl \
--slave /usr/bin/LConfSlaveSync LConfSlaveSync /usr/local/LConf-1.3.0/bin/LConfSlaveSync.pl \
--slave /usr/bin/LConfDeploy LConfDeploy /usr/local/LConf-1.3.0/bin/LConfDeploy.sh

Damit hätte man automatisch durch die höhere Priorität Version 1.3.0 im Einsatz, könnte es manuell auf 1.2.1 umschalten (update-alternatives --config) und solange mit den neuen Optionen experimentieren bis man bereit ist dieses produktiv zu nutzen (update-alternatives --auto). Und man kann auch anschließend noch jederzeit prüfen ob sich die beiden Versionen unterschiedlich verhalten.
Ich hoffe man sieht den Nutzen dieses Werkzeugs, dass es keine Hexenwerk ist dieses zu verwenden und welche Situationen im Adminleben es einem einfacher macht!

Dirk Götz
Dirk Götz
Principal Consultant

Dirk ist Red Hat Spezialist und arbeitet bei NETWAYS im Bereich Consulting für Icinga, Puppet, Ansible, Foreman und andere Systems-Management-Lösungen. Früher war er bei einem Träger der gesetzlichen Rentenversicherung als Senior Administrator beschäftigt und auch für die Ausbildung der Azubis verantwortlich wie nun bei NETWAYS.

Veranstaltungen

Dez 01

Icinga 2 Fundamentals Training | Online

Dezember 1 @ 09:00 - Dezember 4 @ 17:00
Dez 03

DevOps Meetup

Dezember 3 @ 17:30 - 20:30
Dez 08

Terraform mit OpenStack Training | Online

Dezember 8 @ 09:00 - Dezember 9 @ 17:00
Dez 08

Icinga 2 Advanced Training | Online

Dezember 8 @ 09:00 - Dezember 10 @ 17:00
Dez 15

GitLab Training | Online

Dezember 15 @ 09:00 - Dezember 16 @ 17:00