前言
在测试环境中使用 python -m http.server 8080 可以快速启动一个web服务,测试一些简单的网页,
但是如果要在公网发布页面还是存在一些安全问题的。
1.python -m http.server的作用与安全风险
python -m http.server 8080 是 python 内置的一个简单 http 服务器,用于快速共享文件或调试。它的主要安全风险如下:
(1)默认暴露当前目录所有文件
启动后,任何人(包括外网)都能访问你当前工作目录及子目录的所有文件,存在信息泄露风险。
例如:
cd /etc && python3 -m http.server 8080
会导致 /etc 目录下的敏感配置文件被公开访问。
(2)无身份验证与加密
传输为明文 http,没有 https 加密,数据可能被中间人窃取或篡改。
没有密码保护,任何人都可访问服务器。
(3)潜在的执行风险
如果目录中存在可执行文件(如
.py、.sh),虽然默认不会执行,但攻击者可能通过其他方式诱导执行。例如:上传恶意文件到可访问目录,再结合其他漏洞执行。
(4)性能与稳定性
该服务器为单线程,不适合高并发,易被 ddos 攻击拖垮。
2.http.server库的安全漏洞情况
官方维护状态:
http.server是 python 标准库的一部分,安全漏洞会在新版本中修复。建议使用最新版本的 python(如 3.12+)以获取安全补丁。
已知漏洞(历史):
cve-2019-9740:目录遍历漏洞(已修复)。
cve-2021-23336:请求解析缺陷(已修复)。
cve-2023-40217:http 请求zs漏洞(已修复)。
结论:
最新版本的 http.server 没有已知高危漏洞,但它的设计目标是开发调试,不适合生产环境。
3. 安全使用建议
(1)限制访问范围
绑定到本地回环地址:
python3 -m http.server 8080 --bind 127.0.0.1
或使用防火墙限制端口:
sudo ufw allow from 192.168.1.0/24 to any port 8080
(2)使用临时目录
在空目录中启动服务器,避免暴露敏感文件:
mkdir /tmp/web && cd /tmp/web && python3 -m http.server 8080
(3)启用身份验证
自定义 simplehttprequesthandler 添加 basic auth:
from http.server import simplehttprequesthandler
import base64
class authhandler(simplehttprequesthandler):
def do_authhead(self):
self.send_response(401)
self.send_header('www-authenticate', 'basic realm=\"test\"')
self.send_header('content-type', 'text/html')
self.end_headers()
def do_get(self):
if self.headers.get('authorization') is none:
self.do_authhead()
self.wfile.write(b'no auth header received')
else:
auth = self.headers.get('authorization').split()[1]
username, password = base64.b64decode(auth).decode().split(':')
if username == 'admin' and password == 'password':
simplehttprequesthandler.do_get(self)
else:
self.do_authhead()
self.wfile.write(b'invalid credentials')
if __name__ == '__main__':
from http.server import httpserver
server = httpserver(('0.0.0.0', 8080), authhandler)
server.serve_forever()(4)使用 https
通过 ssl 模块包装:
openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out cert.pem python3 -m http.server 8080 --bind 0.0.0.0 --ssl-cert cert.pem --ssl-key key.pem
(5)生产环境替换方案
nginx:高性能、安全的静态文件服务器。
apache:支持复杂配置和访问控制。
flask/django:带路由和权限管理的应用服务器。
4. 总结
漏洞情况:最新版本的
http.server无已知高危漏洞,但它不是为生产环境设计的。安全风险:默认配置会暴露文件、无加密、无认证。
建议:
限制访问范围(
--bind 127.0.0.1)。在空目录中运行。
添加身份验证和 https。
生产环境使用专业服务器。
如果临时使用,为了快速搭建一个应急用的服务器,这里有一个安全加固版的 python http 服务器脚本,它会包含以下安全特性:
安全特性
目录白名单:只允许访问指定目录,防止越权访问。
身份验证:支持 http basic auth。
https 加密:通过 ssl/tls 加密传输。
访问日志:记录访问请求(方便审计)。
禁用目录列表:防止直接列出目录内容。
安全加固版 python http 服务器脚本
import os
import ssl
import base64
import logging
from http.server import httpserver, simplehttprequesthandler
# ===== 配置 =====
host = '0.0.0.0' # 监听地址,0.0.0.0 表示允许外网访问
port = 8080 # 监听端口
whitelist_dir = '/tmp/web' # 允许访问的目录
username = 'admin' # 用户名
password = 'securepass' # 密码
cert_file = 'cert.pem' # ssl证书
key_file = 'key.pem' # ssl私钥
# 初始化日志
logging.basicconfig(
level=logging.info,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.filehandler('access.log'),
logging.streamhandler()
]
)
class securehttprequesthandler(simplehttprequesthandler):
def __init__(self, *args, **kwargs):
# 切换到白名单目录
os.chdir(whitelist_dir)
super().__init__(*args, **kwargs)
def do_authhead(self):
self.send_response(401)
self.send_header('www-authenticate', 'basic realm=\"secure file server\"')
self.send_header('content-type', 'text/html')
self.end_headers()
def do_get(self):
# 1. 检查认证
auth_header = self.headers.get('authorization')
if not auth_header or not auth_header.startswith('basic '):
self.do_authhead()
self.wfile.write(b'401 unauthorized: authentication required.')
logging.warning(f"unauthorized access attempt from {self.client_address[0]}")
return
# 2. 验证用户名和密码
try:
auth_decoded = base64.b64decode(auth_header.split(' ')[1]).decode('utf-8')
username, password = auth_decoded.split(':')
except exception:
self.do_authhead()
self.wfile.write(b'401 unauthorized: invalid credentials.')
logging.warning(f"invalid credentials from {self.client_address[0]}")
return
if username != username or password != password:
self.do_authhead()
self.wfile.write(b'401 unauthorized: invalid username or password.')
logging.warning(f"failed login from {self.client_address[0]}")
return
# 3. 检查路径是否在白名单目录内
path = self.translate_path(self.path)
if not path.startswith(os.path.abspath(whitelist_dir)):
self.send_response(403)
self.send_header('content-type', 'text/html')
self.end_headers()
self.wfile.write(b'403 forbidden: access denied.')
logging.warning(f"directory traversal attempt from {self.client_address[0]}: {self.path}")
return
# 4. 禁用目录列表
if os.path.isdir(path):
self.send_response(404)
self.send_header('content-type', 'text/html')
self.end_headers()
self.wfile.write(b'404 not found: directory listing disabled.')
logging.info(f"directory listing attempt from {self.client_address[0]}: {self.path}")
return
# 5. 正常响应
logging.info(f"access from {self.client_address[0]}: {self.path}")
super().do_get()
def log_message(self, format, *args):
# 自定义日志格式
logging.info(f"{self.client_address[0]} - {format % args}")
def run_server():
# 创建服务器
server_address = (host, port)
httpd = httpserver(server_address, securehttprequesthandler)
# 启用https
context = ssl.create_default_context(ssl.purpose.client_auth)
context.load_cert_chain(certfile=cert_file, keyfile=key_file)
httpd.socket = context.wrap_socket(httpd.socket, server_side=true)
print(f"secure http server running on https://{host}:{port}")
print(f"whitelisted directory: {whitelist_dir}")
try:
httpd.serve_forever()
except keyboardinterrupt:
print("\nserver stopped.")
httpd.server_close()
if __name__ == '__main__':
# 检查目录是否存在
if not os.path.isdir(whitelist_dir):
os.makedirs(whitelist_dir)
print(f"created whitelist directory: {whitelist_dir}")
# 检查证书和密钥
if not (os.path.isfile(cert_file) and os.path.isfile(key_file)):
print("generating self-signed ssl certificate...")
os.system(f"openssl req -newkey rsa:2048 -nodes -keyout {key_file} -x509 -days 365 -out {cert_file} -subj '/cn=localhost'")
run_server()使用步骤
1. 保存脚本
将上面的代码保存为 secure_server.py。
2. 安装依赖
脚本使用 python 标准库,无需额外安装依赖。
3. 生成 ssl 证书
首次运行会自动生成自签名证书:
python3 secure_server.py
4. 启动服务器
python3 secure_server.py
5. 访问测试
浏览器访问:
https://your-ip:8080
会提示输入用户名(admin)和密码(securepass)。
安全建议
密码:生产环境中建议使用强密码,并通过环境变量或配置文件读取,而不是硬编码。
证书:生产环境中建议使用可信 ca 签发的证书,而不是自签名证书。
防火墙:配合防火墙限制访问 ip 范围。
日志:定期查看
access.log以检测异常访问。
完。
总结
到此这篇关于python -m http.server的一些安全问题的文章就介绍到这了,更多相关python -m http.server安全问题内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论