#pragma once #include #include #include class PathTraversal { public: enum class UrlSafetyStatus { Safe, // 1. 完全安全:无任何穿透特征 LiteralTraversal, // 2. 明文穿透:URL 包含裸 ".."(老旧客户端未展开,内核可选择为其“规范化”后放行) EvasiveTraversal // 3. 转义伪装:明文无异常,解码后才出现 ".."(100% 恶意攻击,内核应直接阻断并拉黑) }; private: /** * @brief 内部辅助:检测已统一斜杠的字符串中是否包含标准的 ".." 路径层级 */ static bool InlineHasTraversalPattern(std::string_view path); public: /** * @brief 实用可靠的 URL 解码函数 (符合 RFC 3986 规范) * @note 针对路径解析优化:未将 '+' 转换为系统空格('+'仅在 query 参数中代表空格,在 path 中代表字面量) */ static std::string UrlDecode(std::string_view src); /** * @brief 纯字符串层面的路径穿透行为检测 (内核特征级拦截) * @param raw_url_path 客户端传入的原始未解码 URL 路径 (注意:必须是不包含 Query 参数的纯 Path 部分) * @return true 存在路径穿透特征(危险);false 未检测到穿透特征(安全) */ static bool HasPathTraversalPattern(std::string_view raw_url_path); /** * @brief 基于物理与逻辑边界的路径穿透(目录穿越)安全校验 * @param base_path 允许访问的沙盒根目录(绝对或相对路径均可) * @param user_path 客户端传入的、解码后的目标子路径 * @return true 安全(在沙盒内);false 不安全(企图穿越或路径非法) */ static bool IsSafePath(const std::filesystem::path& base_path, const std::filesystem::path& user_path); /** * @brief 函数 1:内核级明文与密文对比检测 * @param raw_url_path 核心网关拿到的原始未解码、且已剥离 Query 参数的纯 Path 部分 */ static UrlSafetyStatus AnalyzeUrlTraversal(std::string_view raw_url_path); /** * @brief 函数 2:纯文本 URL 路径规范化 (实现 RFC 3986 逻辑) * @details 剥离路径中所有的 "." 和 "..",将其坍缩为安全的绝对路由路径(例如:把 `/a/b/../c` 规范化为 `/a/c`) * @param decoded_url_path 已经过安全校验并确认非恶意攻击的【已解码】路径 */ static std::string NormalizeUrlPath(std::string_view decoded_url_path); static std::string ToString(UrlSafetyStatus s); };