关于python -m http.server的一些安全问题详解

 更新时间:2026年01月22日 09:15:33   作者:飞鸟真人  
这篇文章主要介绍了关于python -m http.server的一些安全问题的相关资料,文章还列举了该模块已知的安全漏洞,并建议在生产环境中使用专业的服务器替代,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在测试环境中使用 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 无已知高危漏洞,但它不是为生产环境设计的。

  • 安全风险:默认配置会暴露文件、无加密、无认证。

  • 建议

    1. 限制访问范围(--bind 127.0.0.1)。

    2. 在空目录中运行。

    3. 添加身份验证和 HTTPS。

    4. 生产环境使用专业服务器。

如果临时使用,为了快速搭建一个应急用的服务器,这里有一个安全加固版的 Python HTTP 服务器脚本,它会包含以下安全特性:

安全特性

  1. 目录白名单:只允许访问指定目录,防止越权访问。

  2. 身份验证:支持 HTTP Basic Auth。

  3. HTTPS 加密:通过 SSL/TLS 加密传输。

  4. 访问日志:记录访问请求(方便审计)。

  5. 禁用目录列表:防止直接列出目录内容。

安全加固版 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安全问题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Opencv中的cv2.calcHist()函数的作用及返回值说明

    Opencv中的cv2.calcHist()函数的作用及返回值说明

    这篇文章主要介绍了Opencv中的cv2.calcHist()函数的作用及返回值说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • python实现K折交叉验证

    python实现K折交叉验证

    这篇文章主要为大家详细介绍了python实现K折交叉验证,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • Python的协程操作几种实现方式总结

    Python的协程操作几种实现方式总结

    在Python中协程(Coroutine)是一种强大的并发编程工具,允许你以非阻塞方式处理I/O密集型任务、异步操作等场景,这篇文章主要介绍了Python的协程操作几种实现方式,需要的朋友可以参考下
    2025-09-09
  • 在Python中将元组转换为列表的方法详解

    在Python中将元组转换为列表的方法详解

    这两种Python 数据类型看起来很相似,但在上下文中却有不同的用法,元组和列表之间的主要区别在于它们的可变性,仅当您需要修改元素时才会将元组转换为列表,本文现在我们将深入研究将元组转换为列表的不同方法,需要的朋友可以参考下
    2023-09-09
  • Pygame游戏开发之太空射击实战添加图形篇

    Pygame游戏开发之太空射击实战添加图形篇

    相信大多数8090后都玩过太空射击游戏,在过去游戏不多的年代太空射击自然属于经典好玩的一款了,今天我们来自己动手实现它,在编写学习中回顾过往展望未来,在本课中,我们将讨论如何在游戏中使用预先绘制的图形
    2022-08-08
  • python自动化测试中装饰器@ddt与@data源码深入解析

    python自动化测试中装饰器@ddt与@data源码深入解析

    最近工作中接触了python自动化测试,所以下面这篇文章主要给大家介绍了关于python自动化测试中装饰器@ddt与@data源码解析的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • 总结Python图形用户界面和游戏开发知识点

    总结Python图形用户界面和游戏开发知识点

    在本篇文章里小编给大家整理了关于Python图形用户界面和游戏开发知识点以及实例代码,需要的朋友们学习下。
    2019-05-05
  • python给指定csv表格中的联系人群发邮件(带附件的邮件)

    python给指定csv表格中的联系人群发邮件(带附件的邮件)

    这篇文章主要介绍了python给指定csv表格中的联系人群发邮件,本文通过代码讲解的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • python判断数字是否是超级素数幂

    python判断数字是否是超级素数幂

    这篇文章主要为大家详细介绍了python判断数字是否是超级素数幂,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09
  • Python检测PE所启用保护方式详解

    Python检测PE所启用保护方式详解

    Python通过pywin32模块调用WindowsAPI接口,可以实现对特定进程加载模块的枚举输出并检测该PE程序模块所启用的保护方式,感兴趣的可以了解一下
    2022-10-10

最新评论