#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 路徑遍歷防護測試腳本 測試 app.py 中的 safe_join 函數 """ import sys import os # 確保可以導入專案模組 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from app import safe_join from pathlib import Path def test_safe_join(): """測試 safe_join 函數""" print("="*60) print("MOMO 監控系統 - 路徑遍歷防護測試") print("="*60) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BACKUP_DIR = os.path.join(BASE_DIR, 'backups') test_cases = [ # (基礎路徑, 子路徑, 是否應該通過, 描述) (BACKUP_DIR, 'backup.zip', True, '正常檔案名'), (BACKUP_DIR, 'subfolder/backup.zip', True, '子目錄中的檔案'), (BACKUP_DIR, 'backup_20260112.zip', True, '帶日期的檔案名'), (BACKUP_DIR, '../../../etc/passwd', False, '路徑遍歷攻擊 (../)'), (BACKUP_DIR, '..\\..\\..\\windows\\system32\\config\\sam', False, 'Windows 路徑遍歷'), (BACKUP_DIR, '/etc/passwd', False, '絕對路徑攻擊'), (BACKUP_DIR, 'backup/../../../etc/passwd', False, '混合路徑遍歷'), (BACKUP_DIR, '....//....//etc/passwd', False, '變種路徑遍歷'), (BACKUP_DIR, 'backup/./../../../config.py', False, '多層目錄遍歷'), (BASE_DIR, '.env', True, '根目錄檔案'), (BASE_DIR, '../momo_pro_system/.env', False, '繞過根目錄'), ] passed = 0 failed = 0 print("\n測試 safe_join() 函數:") print("-"*60) for base, path, should_pass, description in test_cases: try: result = safe_join(base, path) if should_pass: print(f"✅ 通過: {description}") print(f" 基礎: {base}") print(f" 路徑: {path}") print(f" 結果: {result}") passed += 1 else: print(f"❌ 失敗: {description}") print(f" 基礎: {base}") print(f" 路徑: {path}") print(f" 錯誤: 應該被阻擋但通過了") print(f" 結果: {result}") failed += 1 except ValueError as e: if not should_pass: print(f"✅ 通過: {description}") print(f" 基礎: {base}") print(f" 路徑: {path}") print(f" 結果: 成功阻擋 - {str(e)[:60]}") passed += 1 else: print(f"❌ 失敗: {description}") print(f" 基礎: {base}") print(f" 路徑: {path}") print(f" 錯誤: 不應該被阻擋 - {e}") failed += 1 except Exception as e: print(f"❌ 失敗: {description}") print(f" 基礎: {base}") print(f" 路徑: {path}") print(f" 錯誤: 未預期的異常 - {e}") failed += 1 print() # 顯示總結 print("="*60) print("測試結果摘要") print("="*60) print(f"✅ 通過: {passed}") print(f"❌ 失敗: {failed}") print(f"總計: {passed + failed}") assert failed == 0 print("\n🎉 所有路徑遍歷防護測試通過!") if __name__ == "__main__": sys.exit(test_safe_join())