Spielchen mit RSA-Schlüsseln

Als Einstiegshürde für ein CTF (Capture the Flag) dient gerne mal ein RSA Schlüsselpaar, von dem nur der öffentliche Teil bekannt ist. Also kein unrealistischer Ansatz, lediglich die Schlüssellängen sollten entsprechend klein sein.

Vorbereiten der Challenge

Diese Schritte werden vom Spielleitder durchgeführt. Wichtig ist eine geeignete, nicht zu lange Schlüssellänge zu wählen. Hier wählen wir 256 Bit als Schlüssellänge. Das sollte die Teilnehmer vor keine Probleme stellen.

Generieren des Schlüsselpaars

Der wesentliche Schritt bei der Erzeugung eines RSA-Schlüsselpaars ist die Wahl von 2 Primzahlen p und q, deren Produkt n (der RSA-Modulus) die gewünschte Schlüssellänge besitzt.

Dank OpenSSL ist es einfach ein RSA-Schlüsselpaar zu erzeugen:

openssl genrsa -des3 -out private.pem 256
openssl rsa -in private.pem -outform PEM -pubout -out public.pem

Daraus ergibt sich als Public Key beispielsweise:

-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhALRUOO0rvPEA282wqL4VF5GibnA1kcux
LHdIOcT807+DAgMBAAE=
-----END PUBLIC KEY-----

Den privaten Schlüssel private.pem können wir nun löschen, da wir diesen zum Einen nicht mehr benötigen und zum Anderen ja rekonstruieren wollen.

Verschlüsseln der Probedatei

Eine Probedatei lesbar.txt wird mit dem öffentlichen Schlüssel mit OpenSSL verschlüsselt:

openssl rsautl -encrypt -inkey public.pem -pubin -in lesbar.txt -out geheim.txt

Das Ergebnis der Verschlüsselung ist eine Datei, die nur unlesbare binäre Daten enthält. Sie kann hier heruntergeladen werden: geheim.txt. Diese Datei und der öffentliche Schlüssel gehen an die Teilnehmer.

Lösen der Challenge

Diese Schritte werden durch die Teilnehmer durchgeführt.

Knacken der Schlüssel

Zunächst müssen wir aus dem öffentlichen Schlüssel die beiden Parameter  n (Modulus) und e (Exponent) extrahieren:

from Crypto.PublicKey import RSA

public_key = RSA.importKey(open('public.pem', 'r').read())
print 'n =', public_key.n
print 'e =', public_key.e

Dazu verwenden wir die Bibliothek pycrypto (Debian: python-crypto). Ausgegeben werden die beiden oben genannten Werte, in unserem Beispiel also:

n = 815651207903382691105573612057017618852
    64115611526254943458542612275141001091
e = 65537

Nun muss der Modulus faktorisiert werden (n ist das Produkt der beiden Primzahlen p und q). Dazu kann das msieve von Jason Papadopoulos verwendet werden.

Für unsere Zahl n liefert msieve auf einem Core2Duo T7400 nach knapp 10 Minuten die beiden Primfaktoren:

p = 264446414907090989475638551039611206507
q = 308437234133027923039636551098640509513

Alternativ können wir auch factordb.com verwenden, wenn die Zahl dort bereits faktorisiert vorliegt.

Nun müssen wir aus p und q den privaten Exponenten d berechnen:

d = 1/e mod (p-1)*(q-1)

oder mit Python und dem Modul gmpy2:

import gmpy2

p = 264446414907090989475638551039611206507
q = 308437234133027923039636551098640509513
e = 65537
d = gmpy2.invert(e,(p-1)*(q-1))

Aus den Werten n,e und d wird nun der private Schlüssel erstellt und ausgegeben:

from Crypto.PublicKey import RSA
key = RSA.construct((n,e,d))
print key.exportKey()

In unserem Beispiel ergibt das:

-----BEGIN RSA PRIVATE KEY-----
MIGrAgEAAiEAtFQ47Su88QDbzbCovhUXkaJucDWRy7Esd0g5xPzTv4MCAwEAAQIh
ALFDhX4nG6FxbaChww6vnyzjasWei1L/rUg3aG/c6MaxAhEA6ArZu41/pzoKRlXH
MfYqSQIRAMbyhuPv26I/S0+zokene2sCEDxkfpDK3huHBp+RubtuJ0kCECAEWecG
6+7Rhto9y4kCkB8CEQCSSbMXMjOybMpz3gCOQYeS
-----END RSA PRIVATE KEY-----

Wir speichern den privaten Schlüssel wieder in der Datei private.pem ab.

Entschlüsseln der Probedatei

Wurde alles richtig durchgeführt, so kann man mit folgender OpenSSL Anweisung die Probedatei entschlüsseln:

openssl rsautl -decrypt -inkey private.pem -in geheim.txt -out lesbar.txt

Der genaue Inhalt von lesbar.txt wird hier jedoch nicht verraten.

Abschluss

Man erkennt hier am Zeitaufwand zur Faktorisierung eines 256 Bit Schlüssels bereits, dass die Sicherheit von RSA auf genau dieser Schwierigkeit basiert. In der Praxis verwendet man daher Schlüssellängen von mindestens 2000 Bit (siehe dazu die Technische Richtilinie des BSI: Kryptographische Verfahren: Empfehlungen und Schlüssellängen (Seite 39, Kapitel 3.5 – RSA).

Dynamische IP – Reagieren auf Änderungen

Als DSL Nutzer kommt man hierzulande meist nicht in den Genuss einer statischen IPv4 Adresse sondern bekommt regelmäßig eine andere IPv4 von seinem Provider zugewiesen. Als Nebeneffekt wird dadurch das Anbieten von Serverdiensten an Heimanschlüssen oder auch der Betrieb eines IPv6 Tunnels erschwert.

Die FRITZ!Box bietet Unterstützung für einige DDNS-Provider, manchmal möchte man aber auch einfach ein Skript ausführen. Den möglichen Anwendungen sind kaum Grenzen gesetzt.

Über Dienste wie https://icanhazip.com/ kann man sich seine öffentliche IP-Adresse, die zum Abrufen der Seite verwendet wurde, einfach anzeigen lassen und auch in Skripten verwenden. Möchte man die Aktualisierungen wirklich nur dann ausführen, wenn sich die IP geändert hat, so kann das Skript react_to_ip_change.sh helfen. Zu finden ist es im GIT.

Im wesentlichen Skript vergleicht das Skript eine gespeicherte IP mit der aktuell von https://icanhazip.com/ zurück gelieferten. Unterscheiden die beiden sich, so werden alle Skripte in /usr/local/etc/ipchange.d/ ausgeführt.

Kombiniert man das mit Cron, so aktualisiert man die eigene IP zeitnah in allen relevanten Systemen:

# m h dom mon dow command
* * * * * /usr/local/bin/react_to_ip_change.sh

Noch mal der Link zum GIT: https://code.nerd2nerd.org/n0ob/react_to_ip_changes

Mounten von Partitionen aus Image-Dateien

Ist das Backup einer SD-Karte nur als Image-Datei vorhanden und keine Zeit erst wieder auf SD-Karte zu schreiben? Dateimanager kann Image-Dateien nicht direkt einbinden? Hier die Lösung:

  1. Auslesen der Partitionen und ihrer Startsektoren:
    fdisk -l ${QUELLDATEI}

    (Hier in der Spalte Start nach dem Anfang der Partition suchen, unter Units steht die Größe der Sektoren)

  2. Einbinden der gewählten Partition:
    mount ${QUELLDATEI} /mnt -o offset=$((${ANFANGSSEKTOR}*${SEKTORGRÖßE}
  3. Und fertig!

 

Programme mit tmux beim Systemstart automatisch starten

Da ich für das neuste Projekt (ClimateRecording) für den Linux-Client auf der Arietta Hardware erstmal noch kein Init-Script wollte, musste eine alternative Lösung gefunden werden.

Nachdem der Client bisher manuell in tmux gestartet wurde, bot sich als Lösung die Skriptbarkeit von tmux an:

tmux new-session -d -s client_tmux
tmux select-pane -t client_tmux
tmux send-keys "cd /$PATH/ClimateRecording/linuxClient" C-m
tmux send-keys "/$PATH/ClimateRecording/linuxClient/client.py" C-m

Trägt man diese Zeilen in der Datei /etc/rc.local ein, so wird bei jedem Systemstart eine Session für tmux gestartet und darin der Linux-Client ausgeführt.

Mit

tmux a -t client_tmux

kann man dann nach Login auf der Arietta die tmux-Session aktivieren.

 

jq – Kommandozeilenbasiertes Tool für JSON

Viele Web-Dienste basieren auf REST und liefern die Resultate häufig als JSON. Das auf der Kommandozeile auszuwerten gestaltet sich wegen der verschachtelten Struktur als etwas schwerer.

EIne Lösung stellt jq dar, jq erlaubt das gezielte Abfragen der einzelnen Einträge in einem JSON String.

Beispiel:

docker inspect openvpn_server | jq '.[0].NetworkSettings.Ports | keys '

inspiziert zunächst einen Docker-Container, fragt die Ports aus den Networksettings ab und extrahiert die Keys des Objects. Das Ergebnis ist:

[
  "1194/tcp",
  "1194/udp"
]

Ein Tutorial bietet das Projekt hier: http://stedolan.github.io/jq/tutorial/. Das ausführliche Handbuch hier: http://stedolan.github.io/jq/manual/.

Update

curl -s http://api.bitcoincharts.com/v1/markets.json | jq '.[] | select(.symbol == "btcdeEUR" )'

fragt eine JSON-Datei (mit Bitcoin Informationen) und extrahiert aus dem Array das Objekt, welches den Wert btcdeEUR als symbol besitzt.

UUID für Device direkt abfragen

UUIDs werden unter Linux verwendet um Partition eindeutig zu identifizieren. Klassischerweise dient das Kommando blkid zum Abfragen der entsprechenden Information:

/dev/sda1: UUID="612adf0a-1780-ad4c-3fb6-082ee5593158" TYPE="linux_raid_member" 
/dev/sda2: UUID="950bb587-ea1d-4dbf-bd6f-7c9d1c234175" TYPE="swap"              
/dev/sda3: UUID="313669c6-3d82-132e-3fb6-082ee5593158" TYPE="linux_raid_member" 
/dev/sdb1: UUID="612adf0a-1780-ad4c-3fb6-082ee5593158" TYPE="linux_raid_member" 
/dev/sdb2: UUID="bd6fa3c7-37cc-455e-acea-0aaa1fb44290" TYPE="swap"              
/dev/sdb3: UUID="313669c6-3d82-132e-3fb6-082ee5593158" TYPE="linux_raid_member"

Will man nun zu einem Device nun nur die UUID abfragen, so hilft folgendes Kommando:

blkid -o value -s UUID /dev/sdb1

Dabei wird lediglich die UUID ausgegeben:

612adf0a-1780-ad4c-3fb6-082ee5593158

Somit kann man in Skripten problemlos mit UUIDs arbeiten.

nmon: Einschränken auf ausgewählte Festplatten bzw. Partitionen

nmon is bei der Anzeige von Festplattendaten nicht wählerisch und zeigt (zumindest unter Linux, AIX war grade nicht zur Hand ;) ) jeweils Daten zur Gesamtplatte (z.B.  /dev/sda) als auch zu einzelnen Partitionen (z.B. /dev/sda1 und /dev/sda3) an. Soweit ist das kein Problem, nur summiert nmon die einzelnen Werte auf, was zu unsinnig hohen Werten führt, wenn in der Summe sowohl die Festplatte als auch einzelne Partitionen summiert werden.

Nun gilt es also nmon auf ausgewählte Festplatten oder einzelne Partitionen zu beschränken. Das Handbuch (nmon -h) ergibt:

-g <filename> User Defined Disk Groups [hit g to show them]
 - file = on each line: group_name <disks list> space separated
 - like: database sdb sdc sdd sde
 - upto 64 disk groups, 512 disks per line
 - disks can appear more than once and in many groups

Also sieht eine entsprechende Datei für meinen Fall (3 Festplatten, jeweils eine relevante Partition) so aus:

Data1 sda3
Data2 sdb1
Data3 sdc1

Wie in der Hilfe beschrieben, wird nmon nun mit der Datei als Parameter gestartet:

nmon -g disks.dat

Anschließend zeigt nmon nach Druck auf ‚g‚ die entsprechenden Statistiken an.

Verwendung eines speziellen SSH-Keys für rsync

Will man bei rsync einen speziellen SSH-Key verwenden um sich zu einem Server zu verbinden, so kann man das mit der rsync-Option -e verwenden:

rsync -e "ssh -i PRIVATE-KEYFILE" SOURCE TARGET

Und schon wird dieser ausgewählte Schlüssel für diese SSH-Verbindung verwendet und nicht der eventuell vorhandene Standardschlüssel.

SPEC Dateien für Red Hat Pakete bekommen

Will man eigene RPM-Dateien erstellen oder vorhandene updaten, so braucht man ein SPEC-File. Diese kann man natürlich selbst erstellen oder bei anderen abschauen. Speziell bei Updates ist das sinnvoll. SPEC-Files sind in den sogenannten SRPM-Dateien der Pakete enthalten. Frei nach einem englischen Artikel kann man diese SRPm-Dateien herunter laden.

Die notwendigen Schritte sind:

yum install yum-utils

Installieren der yum-utils um das Kommando yumdownloader zu erhalten.

Anschließend muss ein Repository für die SRPM-Dateien eingerichtet werden. Dazu editiert man die Datei /etc/yum.repos.d/srpm.repo und fügt folgende Zeilen ein:

[rhel-src]
name=Red Hat Enterprise Linux $releasever - $basearch - Source
baseurl=ftp://ftp.redhat.com/pub/redhat/linux/enterprise/$releasever/en/os/SRPMS/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

Anschließend kann mit yumdownloader die entsprechende SRPM-Datei heruntergeladen werden:

yumdownloader --source $NAME_DES_PAKETS

Mit dem midnight commander kann das heruntergeladene SRPM dann geöffnet werden, die SPEC-Datei befindet sich dann in der Datei CONTENTS.cpio.

XTerm Titel setzen

Wieder einmal ein kleiner Trick, der mir das Leben einfacher machen wird. Setzen der Titel meiner Xterms um meine Taskleiste übersichtlicher zu machen.

changeTitle() {
    echo -e "\033]2;$1\007"
}

Einfach in der .bashrc ablegen und schon kann man einfach mit

changeTitle foobarbaz

den Titel des Terminals anpassen.