56 lines
2.5 KiB
C++
56 lines
2.5 KiB
C++
#pragma once
|
||
#include <string>
|
||
#include <filesystem>
|
||
#include <string_view>
|
||
|
||
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);
|
||
};
|
||
|