Merge pull request #1112 from majestrate/dns-rebind

mitigate dns rebinding in webui
This commit is contained in:
orignal 2018-02-15 09:57:16 -05:00 committed by GitHub
commit b7596b7f70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 6 deletions

View File

@ -733,8 +733,9 @@ namespace http {
}
}
HTTPConnection::HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket):
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0)
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0),
expected_host(hostname)
{
/* cache options */
i2p::config::GetOption("http.auth", needAuth);
@ -833,7 +834,28 @@ namespace http {
SendReply(res, content);
return;
}
bool strictheaders;
i2p::config::GetOption("http.strictheaders", strictheaders);
if (strictheaders)
{
std::string http_hostname;
i2p::config::GetOption("http.hostname", http_hostname);
std::string host = req.GetHeader("Host");
auto idx = host.find(':');
/* strip out port so it's just host */
if (idx != std::string::npos && idx > 0)
{
host = host.substr(0, idx);
}
if (!(host == expected_host || host == http_hostname))
{
/* deny request as it's from a non whitelisted hostname */
res.code = 403;
content = "host missmatch";
SendReply(res, content);
return;
}
}
// Html5 head start
ShowPageHead (s);
if (req.uri.find("page=") != std::string::npos) {
@ -976,7 +998,8 @@ namespace http {
HTTPServer::HTTPServer (const std::string& address, int port):
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port))
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port)),
m_Hostname(address)
{
}
@ -1061,7 +1084,7 @@ namespace http {
void HTTPServer::CreateConnection(std::shared_ptr<boost::asio::ip::tcp::socket> newSocket)
{
auto conn = std::make_shared<HTTPConnection> (newSocket);
auto conn = std::make_shared<HTTPConnection> (m_Hostname, newSocket);
conn->Receive ();
}
} // http

View File

@ -21,7 +21,7 @@ namespace http
{
public:
HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket);
HTTPConnection (std::string serverhost, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
void Receive ();
private:
@ -46,6 +46,7 @@ namespace http
bool needAuth;
std::string user;
std::string pass;
std::string expected_host;
static std::map<uint32_t, uint32_t> m_Tokens; // token->timestamp in seconds
};
@ -75,6 +76,7 @@ namespace http
boost::asio::io_service m_Service;
boost::asio::io_service::work m_Work;
boost::asio::ip::tcp::acceptor m_Acceptor;
std::string m_Hostname;
};
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml

View File

@ -83,6 +83,8 @@ namespace config {
("http.auth", value<bool>()->default_value(false), "Enable Basic HTTP auth for webconsole")
("http.user", value<std::string>()->default_value("i2pd"), "Username for basic auth")
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
("http.hostname", value<std::string>()->default_value("localhost"),"Expected hostname for WebUI")
;
options_description httpproxy("HTTP Proxy options");