3. Programowanie sieciowe

3.1. Socket

3.1.1. Protokoły

  • IPv4 - socket.AF_INET
  • IPv6 - socket.AF_INET6
  • UDP - socket.SOCK_DGRAM
  • TCP - socket.SOCK_STREAM

3.1.2. Otwieranie połączeń

Code Listing 3.14. Komunikacja za pomocą socketów
import socketserver

class UDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        log.info('Received ping from %s:%s' % self.client_address)


if __name__ == '__main__':
    addr = ('localhost', 1234)

    logging.info('Listening for pings on %s...', addr)
    listener = socketserver.UDPServer(addr, UDPHandler)

    listener.serve_forever()

3.1.3. Nasłuchiwanie

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
    sock.sendto(bytes('%s:%s\n', 'utf-8'), addr)

3.1.4. Przekazywanie informacji

3.2. Biblioteki sieciowe

3.2.1. smtp

3.3. Automatyzacja pracy

3.4. Zadania kontrolne

3.4.1. Mini Botnet

  1. Do pliku botnet-commands.xml skopiuj zawartość Code Listing 3.15..

  2. Stwórz mini botnet o architekturz podanej Fig. 3.1.. Mini botnet składa się z trzech części:

    • Heartbeat Server - server przyjmujący informacje o ofiarach (czy wciąż żyją),
    • Victim - ofiara,
    • Attacket - atakujący.
../_images/botnet.png

Fig. 3.1. Architektura botnet

Podpowiedź:
  • Do weryfikacji czy port jest otwarty możesz użyć telnet albo netcat

3.4.1.1. Heartbeat

  1. Skrypt serwera heartbeat nazwij botnet-heartbeat-server.py

  2. Server ma przyjmować komunikaty UDP na porcie 1337

  3. Datę UTC przyjścia pakietu, IP i port backdoora zapisuje do bazy danych sqlite3 jako pola:

    • datetime DATETIME,
    • ip TEXT,
    • port INTEGER
Podpowiedź:
  • socketserver.UDPServer
  • sqlite3

3.4.1.2. Victim

  1. Skrypt ofiary nazwij botnet-victim.py
  2. Po zainfekowaniu otwiera randomowy port TCP (backdoor) z przedziału 1025-65535 na którym nasłuchuje komunikatów. Dlaczego taki zakres portów?
  3. Co 5 sekund wysyła informację ze swoim numerem portu backdoor oraz swoim adresem IP do serwera Heartbeat
  4. Po otrzymaniu komunikatu XML na port backdoora wykonuje operację w nim zawarte
  5. Ofiara ma przesyłać dane atakującemu w formacie JSON w formacie zawierającym datę, ip, port, stdout, stderror
  6. Stwórz dekorator is_valid_xml, który sprawdzi czy XML się waliduje (czy ma poprawną strukturę) i tylko wtedy wykona polecenia
  7. Stwórz dekorator log_incoming_requests, który zapisze do pliku botnet.log logi w formacie Request from IP:PORT to execute COMMAND ARGUMENTS dla każdego polecenia wykonywanego na systemie ofiary
Podpowiedź:
  • random
  • logging
  • socket
  • socketserver.TCPServer
  • subprocess.run()
  • json.dumps(), json.loads()
  • xml.etree.ElementTree

3.4.1.3. Attacker

  1. Skopiuj zawartość Code Listing 3.15. do pliku botnet-commands.xml

  2. Skrypt atakującego nazwij botnet-attacker.py

  3. Skrypt można wywoływać z parametrami linii poleceń:

    • --xml FILENAME, domyślnie botnet-commands.xml, opcjonalny (jeżeli podano inne parametry),
    • --exec COMMAND - opcjonalny,
    • --cat FILENAME - opcjonalny,
    • --ls PATH - opcjonalny,
    • --eval CODE - opcjonalny.
  4. Skrypt ma do wszystkich botów (ofiar), które pingnęły serwer heartbeat w ciągu godziny wysyłać (IP ofiary, port backdoor) polecenia do wykonania.

  5. Polecenia są:

    • w pliku XML podanym jako parametr (jeżeli podano flagę --xml),
    • podane jako parametr do --exec,
    • wyświetlanie zawartości pliku podanego jako parametr --cat,
    • listowanie zawartości katalogu podanego jako parametr --ls,
    • wykonywanie kodu Python i zwracanie wyników, jeżeli podano --eval.
  6. Polecenia do wykonania bez względu na flagę muszą być przesłane za pomocą komunikatów XML.

  7. Datę, komunikat XML, oraz listę hostów do których poszło zapytanie zapisuj w bazie sqlite3 w charakterze logów

  8. Wyniki, które przyjdą od ofiar zapisuj w bazie danych sqlite3 wraz z datą otrzymania, adresem IP ofiary, portem (backdoor), stdout i stderr

Założenia:
  1. Do obsługi parametrów z linii poleceń wykorzystaj argparse
  2. Przetwarzanie requestów jest nieblokujące, tzn. otwieraj wątek dla każdego zapytania
  3. Wykorzystaj os.path.join (łączenie ścieżki) oraz os.walk (wyświetlanie zawartości).
Code Listing 3.15. Komunikat XML z listą poleceń do wykonania na komputerze ofiary
    <execute>
        <command timeout="2">/bin/ls -la /home</command>
        <command>/bin/ls -l /home/ /tmp/</command>
        <command timeout="1">/bin/sleep 2</command>
        <command timeout="2">/bin/echo 'juz wstalem'</command>
    </execute>
Podpowiedź:
  • argparse
  • socket
  • json.dumps(), json.loads()
Zadanie z gwiazdką:
 

Za pomocą Django stwórz panel administracyjny dla botnetu:

  • Wyszukiwanie aktywnych hostów
  • command