我有一个 Poco 服务器应用程序项目。此服务器应用程序用作 Web 服务器。现在我想加强它以抵御目录遍历攻击,并且我正在寻找最好的方法来确保服务器提供的文件来自内部wwwRoot
。结构是
project
|-src
| |-main.cpp
|-CMakeLists.txt
|-conanfile.txt
|-build
|-...
例如,当我使用build
as时wwwRoot
,conanfile.txt
在外面wwwRoot
但localhost:8080/../conanfile.txt
我可以打开它。我知道我可以搜索点段的路径,但我听说它不是很安全,因为有像编码路径这样的黑客攻击。由于 Poco 是我假设的服务器应用程序框架,因此已经有这样的功能来检查是否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
在build
项目中建