關于python?-m?http.server的一些安全問題詳解
前言
在測試環(huán)境中使用 python -m http.server 8080 可以快速啟動一個web服務,測試一些簡單的網頁,
但是如果要在公網發(fā)布頁面還是存在一些安全問題的。
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)潛在的執(zhí)行風險
如果目錄中存在可執(zhí)行文件(如
.py、.sh),雖然默認不會執(zhí)行,但攻擊者可能通過其他方式誘導執(zhí)行。例如:上傳惡意文件到可訪問目錄,再結合其他漏洞執(zhí)行。
(4)性能與穩(wěn)定性
該服務器為單線程,不適合高并發(fā),易被 DDoS 攻擊拖垮。
2.http.server庫的安全漏洞情況
官方維護狀態(tài):
http.server是 Python 標準庫的一部分,安全漏洞會在新版本中修復。建議使用最新版本的 Python(如 3.12+)以獲取安全補丁。
已知漏洞(歷史):
CVE-2019-9740:目錄遍歷漏洞(已修復)。
CVE-2021-23336:請求解析缺陷(已修復)。
CVE-2023-40217:HTTP 請求zs漏洞(已修復)。
結論:
最新版本的 http.server 沒有已知高危漏洞,但它的設計目標是開發(fā)調試,不適合生產環(huán)境。
3. 安全使用建議
(1)限制訪問范圍
綁定到本地回環(huán)地址:
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)生產環(huán)境替換方案
Nginx:高性能、安全的靜態(tài)文件服務器。
Apache:支持復雜配置和訪問控制。
Flask/Django:帶路由和權限管理的應用服務器。
4. 總結
漏洞情況:最新版本的
http.server無已知高危漏洞,但它不是為生產環(huán)境設計的。安全風險:默認配置會暴露文件、無加密、無認證。
建議:
限制訪問范圍(
--bind 127.0.0.1)。在空目錄中運行。
添加身份驗證和 HTTPS。
生產環(huán)境使用專業(yè)服務器。
如果臨時使用,為了快速搭建一個應急用的服務器,這里有一個安全加固版的 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' ? ? ? # 監(jiān)聽地址,0.0.0.0 表示允許外網訪問
PORT = 8080 ? ? ? ? ? ?# 監(jiān)聽端口
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():
? ?# 創(chuàng)建服務器
? ?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)。
安全建議
密碼:生產環(huán)境中建議使用強密碼,并通過環(huán)境變量或配置文件讀取,而不是硬編碼。
證書:生產環(huán)境中建議使用可信 CA 簽發(fā)的證書,而不是自簽名證書。
防火墻:配合防火墻限制訪問 IP 范圍。
日志:定期查看
access.log以檢測異常訪問。
完。
總結
到此這篇關于python -m http.server的一些安全問題的文章就介紹到這了,更多相關python -m http.server安全問題內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Opencv中的cv2.calcHist()函數的作用及返回值說明
這篇文章主要介紹了Opencv中的cv2.calcHist()函數的作用及返回值說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11
Pygame游戲開發(fā)之太空射擊實戰(zhàn)添加圖形篇
相信大多數8090后都玩過太空射擊游戲,在過去游戲不多的年代太空射擊自然屬于經典好玩的一款了,今天我們來自己動手實現它,在編寫學習中回顧過往展望未來,在本課中,我們將討論如何在游戲中使用預先繪制的圖形2022-08-08
python自動化測試中裝飾器@ddt與@data源碼深入解析
最近工作中接觸了python自動化測試,所以下面這篇文章主要給大家介紹了關于python自動化測試中裝飾器@ddt與@data源碼解析的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-12-12
python給指定csv表格中的聯(lián)系人群發(fā)郵件(帶附件的郵件)
這篇文章主要介紹了python給指定csv表格中的聯(lián)系人群發(fā)郵件,本文通過代碼講解的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12

