防止Poco Server应用程序中的目录遍历攻击

时间:2019-02-16 10:59:32

标签: c++ poco-libraries directory-traversal

我有一个Poco服务器应用程序项目。该服务器应用程序用作Web服务器。现在,我想对它进行加固,使其免受目录遍历攻击,并且我正在寻找确保服务器提供的文件来自import { Component, ViewChild, HostListener } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import {MatSidenav} from '@angular/material/sidenav'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent { screenWidth: number; private screenWidth$ = new BehaviorSubject<number>(window.innerWidth); @ViewChild('sidenav') sidenav: MatSidenav; @HostListener('window:resize', ['$event']) onResize(event) { this.screenWidth$.next(event.target.innerWidth); } constructor() { } ngOnInit() { this.screenWidth$.subscribe(width => { this.screenWidth = width; }); } } 内部的最佳方法。结构是

wwwRoot

例如当我将project |-src | |-main.cpp |-CMakeLists.txt |-conanfile.txt |-build |-... 用作build时,wwwRootconanfile.txt之外,但是使用wwwRoot可以打开它。我知道我可以在路径中搜索点段,但是我听说它并不是很安全,因为存在诸如编码路径之类的黑客攻击。由于我认为Poco是服务器应用程序的框架,因此已经有了这样的功能来检查localhost:8080/../conanfile.txt是否在filePath内部,但是我找不到它。

wwwRoot包含:

src/main.cpp

#include <Poco/Net/HTTPServer.h> #include <Poco/Net/ServerSocket.h> #include <Poco/Util/ServerApplication.h> #include <Poco/Net/HTTPRequestHandler.h> #include <Poco/Net/HTTPRequestHandlerFactory.h> #include <Poco/Net/HTTPServerRequest.h> #include <Poco/Net/HTTPServerResponse.h> #include <Poco/Path.h> #include <string> class FileHandler: public Poco::Net::HTTPRequestHandler { public: explicit FileHandler(const Poco::Path &wwwRoot); protected: void handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response) override; private: Poco::Path wwwRoot; }; FileHandler::FileHandler(const Poco::Path &aWwwRoot) : wwwRoot(aWwwRoot) {} void FileHandler::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response) { Poco::Util::Application &app = Poco::Util::Application::instance(); app.logger().information("FileHandler Request from " + request.clientAddress().toString() + ": " + request.getURI()); Poco::Path path(wwwRoot.absolute(), request.getURI()); std::string filePath(path.toString()); app.logger().information(filePath); response.sendFile(filePath, "text/html"); } class HTTPRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory { public: explicit HTTPRequestHandlerFactory(const Poco::Path &wwwRoot); protected: Poco::Net::HTTPRequestHandler* createRequestHandler( const Poco::Net::HTTPServerRequest& request) override; private: Poco::Path wwwRoot; }; HTTPRequestHandlerFactory::HTTPRequestHandlerFactory(const Poco::Path &aWwwRoot) : wwwRoot(aWwwRoot) {} Poco::Net::HTTPRequestHandler* HTTPRequestHandlerFactory::createRequestHandler( const Poco::Net::HTTPServerRequest &) { return new FileHandler(wwwRoot); } class ServerApplication : public Poco::Util::ServerApplication { protected: void initialize(Application& self) override; int main(const std::vector<std::string> &args) override; }; void ServerApplication::initialize(Application& self) { loadConfiguration(); Poco::Util::ServerApplication::initialize(self); } int ServerApplication::main(const std::vector<std::string> &) { Poco::Net::ServerSocket svs(8080); Poco::Net::HTTPServer srv(new HTTPRequestHandlerFactory(Poco::Path(".").absolute()), svs, new Poco::Net::HTTPServerParams); srv.start(); waitForTerminationRequest(); srv.stop(); return Application::EXIT_OK; } int main(int argc, char **argv) { ServerApplication app; return app.run(argc, argv); } 包含:

CMakeLists.txt

cmake_minimum_required (VERSION 3.5.1) project (Sandbox) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) endif() set(CMAKE_CXX_FLAGS "-Wall -Wextra") set(CMAKE_CXX_FLAGS_DEBUG "-g") set(CMAKE_CXX_FLAGS_RELEASE "-O3") set(CMAKE_CXX_STANDARD 14) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup(TARGETS) add_executable(${PROJECT_NAME} src/main.cpp) target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::Poco) 包含:

conanfile.txt

[requires] Poco/1.9.0@pocoproject/stable [generators] cmake 中构建了项目

1 个答案:

答案 0 :(得分:1)

您将必须解码请求路径并逐步构建本地路径,并检查“ ..”路径段。这是执行此操作的代码段,还处理了在提供文件时应注意的其他事项。您需要编写mapContentType()方法,或执行等效操作。

Poco::URI uri(request.getURI());
std::string decodedPath = uri.getPath();

Poco::Path requestPath(decodedPath, Poco::Path::PATH_UNIX);
Poco::Path localPath(wwwRoot.absolute());
localPath.makeDirectory();

bool valid = true;
for (int i = 0; valid && i < requestPath.depth(); i++)
{
    if (requestPath[i] != "..")
        localPath.pushDirectory(requestPath[i]);
    else
        valid = false;
}
if (valid)
{
    localPath.setFileName(requestPath.getFileName());
    Poco::File requestedFile(localPath.toString());
    if (requestedFile.exists())
    {
        std::string contentType = mapContentType(localPath.getExtension());

        if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD)
        {
            response.set("Last-Modified", Poco::DateTimeFormatter::format(dateTime, Poco::DateTimeFormat::HTTP_FORMAT));
            response.setContentLength64(requestedFile.getSize());
            response.setContentType(contentType);
            response.send();
        }
        else if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET)
        {
            response.sendFile(localPath.toString(), contentType);
        }
        else
        {
            response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_METHOD_NOT_ALLOWED);
            response.send();
        }
    }
    else
    {
        response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
        response.send();
    }
}
else
{
    response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
    response.send();
}