学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

2万

积分

41

好友

1168

主题
发表于 2022-11-7 16:20:15 | 查看: 1916| 回复: 0
外部输入的参数不能直接作为文件路径,防止被恶意攻击,比如构造一个跨目录限制的文件路径…/…/…/etc/passwd 或…/…/boot.ini,或构造一个指向系统关键文件的链接文件 symlink (“/etc/shadow”,“tmp/log”)。PS "./“表示当前目录,可以不写,”…/" 表示当前目录的上一级目录,即当前目录的父目录。windows 可以用 PathCanonicalizeA 或者 PathCanonicalizeW 检查文件目录是否标准,但是微软 msdn 官网不建议使用 PathCanonicalize 这个函数,如下图所示:

微软 msdn 官网说误用 PathCanonicalizeA 会导致 buffer 溢出,建议使用更安全的 PathCchCanonicalize 或 PathCchCanonicalizeEx 代替。

对 PathCchCanonicalize 函数的使用示例如下:



#include <Windows.h>
#include <pathcch.h>
#include <string>
#include <iostream>
#pragma comment(lib,"Pathcch.lib")

using namespace std;

//将string转换成wstring  
wstring String2WString(string str)
{
    wstring result;
    //获取缓冲区大小,并申请空间,缓冲区大小按字符计算  
    int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
    TCHAR* buffer = new TCHAR[len + 1];
    //多字节编码转换成宽字节编码  
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
    buffer[len] = '\0';             //添加字符串结尾  
    //删除缓冲区并返回值  
    result.append(buffer);
    delete[] buffer;
    return result;
}

//将wstring转换成string  
string WString2String(wstring wstr)
{
    string result;
    //获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的  
    int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
    char* buffer = new char[len + 1];
    //宽字节编码转换成多字节编码  
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
    buffer[len] = '\0';
    //删除缓冲区并返回值  
    result.append(buffer);
    delete[] buffer;
    return result;
}

bool GetCanonicalizePath(const std::wstring& path, std::wstring& cannoPath)
{
    wchar_t tempArrPath[MAX_PATH] = { 0 };
    if (path.empty() || path.length() > MAX_PATH ||
        PathCchCanonicalize(tempArrPath, MAX_PATH, path.c_str()) != S_OK) {
        return false;
    }
    std::wstring resultPath = tempArrPath;
    cannoPath = resultPath;
    return true;
}

bool GetCanonicalizePathA(const std::string& path, std::string& cannoPath)
{
    std::wstring wstrPath = String2WString(path);
    wchar_t tempArrPath[MAX_PATH] = { 0 };
    if (wstrPath.empty() || wstrPath.length() > MAX_PATH ||
        PathCchCanonicalize(tempArrPath, MAX_PATH, wstrPath.c_str()) != S_OK) {
        return false;
    }
    std::wstring resultPath = tempArrPath;
    std::string strTempResultPath = WString2String(resultPath);
    cannoPath = strTempResultPath;
    return true;
}

int main(int argc, char* argv[])
{
    std::string fileFullPath = "D:\\name_1\\.\\name_2\\.\\name_3\\..\\name_4\\..";
    std::string canonicalizePath;
    bool bCanonicalizeOk = GetCanonicalizePathA(fileFullPath, canonicalizePath);
    if (bCanonicalizeOk) {
        std::cout << "canonicalizePath=" << canonicalizePath.c_str() << endl;  //  D:\name_1\name_2
    } else {
        std::cout << "GetCanonicalizePathA failed, lastErrorCode: " << GetLastError() << endl;
    };

    std::wstring fileFullWstrPath = L"D:\\name_1\\.\\name_2\\.\\name_3\\..\\name_4\\..";
    std::wstring canonicalizeWstrPath;
    bCanonicalizeOk = GetCanonicalizePath(fileFullWstrPath, canonicalizeWstrPath);
    if (bCanonicalizeOk) {
        std::cout << "canonicalizeWstrPath=" << WString2String(canonicalizeWstrPath).c_str() << endl;  //  D:\name_1\name_2
    } else {
        std::cout << "GetCanonicalizePathA failed, lastErrorCode: " << GetLastError() << endl;
    };

    return 0;
}


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

GMT+8, 2024-11-23 16:13 , Processed in 0.130377 second(s), 37 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表