A small backdoor on Flask or how to manage a computer on a local network

Hey Habr!

I recently watched a downloaded version of the programming stream How to Build Your Own Flask Web Application. And I decided to consolidate my knowledge in some project. I didn’t know what to write for a long time and the idea came to me: “Why not make a mini-backdoor on Flask?”.

The first variants of implementations and possibilities of the backdoor immediately appeared in my head. But I decided to immediately compile a list of backdoor features:

  1. Know how to open websites
  2. Have command line access
  3. Be able to open programs, photos, videos

So, the first point is extremely easy to implement using the webbrowser module. I decided to implement the second point using the os module. And the third one is also through the os module, but I will use "links" (more on that later).

Server writing

So, *drumroll* all the server code:

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 'The server is running and waiting for commands...'
    if json_string['command'] == 'openweb':
        webbrowser.open(url='https://www.'+json_string['data'], new=0)
        return 'Site opening ' + json_string['data'] + '...'
    if json_string['command'] == 'shell':
        os.system(json_string['data'])
        return 'Command execution ' + 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 'Launch ' + link.split('>')[1]
if __name__ == '__main__':
    app.run(host='0.0.0.0')

I already threw out all the code, it's time to explain the essence.

All code is run on the local machine on port 5000. To interact with the server, we must send a JSON POST request.

Request JSON structure:

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

Well, it makes sense that 'command' is the command we want to execute. And 'data' are command arguments.

You can write and send JSON requests to interact with the server manually (requests will help you). And it is possible to write the console client.

Writing a client

Code:

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('Комманда не содержит аргументов!')
    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('Комманда не содержит аргументов!')
    if a[0] == 'set':
        if a[1] == 'host':
            ip = a[2] + ':5000'
    if command == 'quit':
        break

Explanations:

The first step is to import the requests module (to interact with the server). Further descriptions of the start and test functions. And then the cycle in which the magic happens. Have you read the code? So you understand the meaning of the magic that happens in the cycle. Enter the command - it is executed. Shell - commands for the command line (the logic goes off scale).

Test - check if the server is running (backdoor)
Link - use of "shortcut"
Openweb - site opening
Quit - exit from the client
Set - setting the ip of your computer on the local network

And now in more detail about link.

Next to the server is the link.txt file. It contains links (full path) to files (video, photos, programs).

The structure is like this:

полный_путь>описание
полный_путь>описание

Сonclusion

We have a backdoor server for managing a computer on a local network (within a wi-fi network). Technically, we can run the client from any device that has a python interpreter.

PS I added the set command so that if another ip is assigned to a computer on the local network, you can change it directly in the client.

Source: habr.com

Add a comment