Mały backdoor na Flasku lub jak zarządzać komputerem w lokalnej sieci

Cześć, Habr!

Niedawno obejrzałem pobraną wersję streamu na temat programowania „Jak stworzyć swoją aplikację webową w Flask”. Postanowiłem utrwalić swoją wiedzę w jakimś projekcie. Długo nie wiedziałem, co napisać i przyszedł mi do głowy pomysł: „A dlaczego by nie stworzyć mini-backdoora w Flask?”

W głowie od razu pojawiły się pierwsze pomysły na realizacje i możliwości backdoora. Postanowiłem jednak od razu sporządzić listę możliwości backdoora:

  1. Móc otwierać strony internetowe
  2. Mieć dostęp do wiersza poleceń
  3. Móc otwierać programy, zdjęcia, filmy

Zatem pierwszy punkt jest niezwykle łatwy do zrealizowania przy pomocy modułu webbrowser. Drugi punkt postanowiłem zrealizować przy użyciu modułu os. A trzeci też przez moduł os, ale skorzystam z „linków” (o tym później).

Pisanie serwera

A zatem, *werble* oto cały kod serwera:

from flask import Flask, request
import webbrowser
import os
import re

app = Flask(__name__)
@app.route('mycomp', methods=['POST'])
def hell():
    json_string = request.json
    if json_string['command'] == 'test':
        return 'Serwer działa i czeka na komendy...'
    if json_string['command'] == 'openweb':
        webbrowser.open(url='https://www.' + json_string['data'], new=0)
        return 'Otwieranie strony ' + json_string['data'] + '...'
    if json_string['command'] == 'shell':
        os.system(json_string['data'])
        return 'Wykonywanie komendy ' + json_string['data'] + '...'
    if json_string['command'] == 'link':
        links = open('links.txt', 'r')
        for i in range(int(json_string['data'])):
            link = links.readline()
        os.system(link.split('>')[0])
        return 'Uruchamianie ' + link.split('>')[1]
if __name__ == '__main__':
    app.run(host='0.0.0.0')

Już opublikowałem cały kod, pora wyjaśnić istotę.

Cały kod uruchamiany jest na lokalnym komputerze na porcie 5000. Aby wchodzić w interakcje z serwerem musimy wysyłać żądanie JSON POST.

Struktura żądania JSON:

{‘command’:  ‘comecommand’, ‘data’: ‘somedata’}

Cóż, logiczne, że ‘command’ to polecenie, które chcemy wykonać. A ‘data’ to argumenty polecenia.

Można pisać i wysyłać żądania JSON, aby wchodzić w interakcje z serwerem ręcznie (polecam requests). Można też napisać klienta konsolowego.

Pisanie klienta

Kod:

import requests

logo = ['nn',
        '******      ********',
        '*******     *********',
        '**    **    **     **',
        '**    **    **     **      Written on Python',
        '*******     **     **',
        '********    **     **',
        '**     **   **     **      Author: ROBOTD4',
        '**     **   **     **',
        '**     **   **     **',
        '********    *********',
        '*******     ********',
        'nn']

p = ''
iport = '192.168.1.2:5000'
host = 'http://' + iport + '/mycomp'

def test():
    dict = {'command': 'test', 'data': 0}
    r = requests.post(host, json=dict)
    if r.status_code == 200:
        print (r.content.decode('utf-8'))

def start():
    for i in logo:
        print(i)

start()
test()

while True:
    command = input('>')
    if command == '':
        continue
    a = command.split()
    if command == 'test':
        dict = {'command': 'test', 'data': 0}
        r = requests.post(host, json=dict)
        if r.status_code == 200:
            print (r.content.decode('utf-8'))
    if a[0] == 'shell':
        for i in range(1, len(a)):
            p = p + a[i] + ' '
        dict = {'command': 'shell', 'data': p}
        r = requests.post(host, json=dict)
        if r.status_code == 200:
            print (r.content.decode('utf-8'))
        p = ''
    if a[0] == 'link':
        if len(a) > 1:
            dict = {'command': 'link', 'data': int(a[1])}
            r = requests.post(host, json=dict)
            if r.status_code == 200:
                print (r.content.decode('utf-8'))
        else:
            print('Brak argumentów dla komendy!')
    if a[0] == 'openweb':
            if len(a) > 1:
                dict = {'command': 'openweb', 'data': a[1]}
                r = requests.post(host, json=dict)
                if r.status_code == 200:
                    print (r.content.decode('utf-8'))
            else:
                print('Brak argumentów dla komendy!')
    if a[0] == 'set':
        if a[1] == 'host':
            ip = a[2] + ':5000'
    if command == 'quit':
        break

Wyjaśnienia:

Najpierw importujemy moduł requests (do interakcji z serwerem). Następnie opisujemy funkcje start i test. A potem następuje pętla, w której dzieje się magia. Czytaliście kod? To znaczy, że rozumiecie sens magii zachodzącej w pętli. Wpisujcie polecenie – jest wykonywane. Shell – polecenia dla wiersza poleceń (logika szaleje).

Test – sprawdzenie, czy serwer (backdoor) działa
Link – użycie „skrótu”
Openweb – otwieranie strony internetowej
Quit – wyjście z klienta
Set – ustawienie IP twojego komputera w sieci lokalnej

A teraz szczegóły dotyczące linku.

Obok serwera znajduje się plik link.txt. Zawiera on linki (pełne ścieżki) do plików (wideo, zdjęcia, programy).

Struktura jest następująca:

pełny_szlak>opis
pełny_szlak>opis

Podsumowanie

Mamy serwer-backdoor do zarządzania komputerem w sieci lokalnej (w obrębie sieci Wi-Fi). Technicznie możemy uruchomić klienta z dowolnego urządzenia, na którym jest interpreter Pythona.

P.S. Komendę set dodałem po to, żeby można było zmienić IP komputera w sieci lokalnej w kliencie, jeśli zostanie mu przydzielony inny adres.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster