mirror of https://github.com/oxen-io/lokinet
fix dns rebinding vuln in jsonrpc
This commit is contained in:
parent
0302864e11
commit
99c814e6b0
|
@ -37,6 +37,10 @@ namespace abyss
|
|||
bool
|
||||
ShouldClose(llarp_time_t now) const;
|
||||
|
||||
/// return true if the host header is correct
|
||||
virtual bool
|
||||
ValidateHost(const std::string& host) const = 0;
|
||||
|
||||
private:
|
||||
ConnImpl* m_Impl;
|
||||
};
|
||||
|
|
|
@ -192,6 +192,7 @@ namespace abyss
|
|||
authgen << ", " << opt.first << "=" << opt.second;
|
||||
}
|
||||
m_SendHeaders.clear();
|
||||
m_SendHeaders.emplace("Host", "localhost");
|
||||
m_SendHeaders.emplace("Authorization", authgen.str());
|
||||
SendRequest();
|
||||
return true;
|
||||
|
@ -320,6 +321,7 @@ namespace abyss
|
|||
std::string body;
|
||||
std::stringstream ss;
|
||||
body = m_RequestBody.dump();
|
||||
m_SendHeaders.emplace("Host", "localhost");
|
||||
m_SendHeaders.emplace("Content-Type", "application/json");
|
||||
m_SendHeaders.emplace("Content-Length", std::to_string(body.size()));
|
||||
m_SendHeaders.emplace("Accept", "application/json");
|
||||
|
|
|
@ -96,7 +96,8 @@ namespace abyss
|
|||
{
|
||||
// TODO: header whitelist
|
||||
return name == string_view("content-type")
|
||||
|| name == string_view("content-length");
|
||||
|| name == string_view("content-length")
|
||||
|| name == string_view("host");
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -162,6 +163,17 @@ namespace abyss
|
|||
{
|
||||
m_BodyParser.reset(json::MakeParser(contentLength));
|
||||
}
|
||||
itr = Header.Headers.find("host");
|
||||
if(itr == Header.Headers.end())
|
||||
{
|
||||
return WriteResponseSimple(400, "Bad Request", "text/plain",
|
||||
"no host header provided");
|
||||
}
|
||||
if(not handler->ValidateHost(itr->second))
|
||||
{
|
||||
return WriteResponseSimple(400, "Bad Request", "text/plain",
|
||||
"invalid host header");
|
||||
}
|
||||
}
|
||||
if(!m_BodyParser->FeedData(buf, sz))
|
||||
{
|
||||
|
|
|
@ -285,12 +285,16 @@ namespace llarp
|
|||
|
||||
struct Handler : public ::abyss::httpd::IRPCHandler
|
||||
{
|
||||
std::string expectedHostname;
|
||||
AbstractRouter* router;
|
||||
std::unordered_map< std::string, std::function< Response() > > m_dispatch;
|
||||
Handler(::abyss::httpd::ConnImpl* conn, AbstractRouter* r)
|
||||
Handler(::abyss::httpd::ConnImpl* conn, AbstractRouter* r,
|
||||
std::string hostname)
|
||||
: ::abyss::httpd::IRPCHandler(conn)
|
||||
, expectedHostname(std::move(hostname))
|
||||
, router(r)
|
||||
, m_dispatch{
|
||||
{"llarp.admin.die", [=]() { return KillRouter(); }},
|
||||
{"llarp.admin.wakeup", [=]() { return StartRouter(); }},
|
||||
{"llarp.admin.link.neighbor",
|
||||
[=]() { return ListNeighbors(); }},
|
||||
|
@ -304,6 +308,12 @@ namespace llarp
|
|||
|
||||
~Handler() override = default;
|
||||
|
||||
bool
|
||||
ValidateHost(const std::string& host) const override
|
||||
{
|
||||
return host == "localhost" || host == expectedHostname;
|
||||
}
|
||||
|
||||
Response
|
||||
StartRouter() const
|
||||
{
|
||||
|
@ -317,6 +327,15 @@ namespace llarp
|
|||
return router->ExtractStatus();
|
||||
}
|
||||
|
||||
Response
|
||||
KillRouter() const
|
||||
{
|
||||
if(not router->IsRunning())
|
||||
return {{"error", "already stopping"}};
|
||||
router->Stop();
|
||||
return {{"status", "OK"}};
|
||||
}
|
||||
|
||||
Response
|
||||
ListExitLevels() const
|
||||
{
|
||||
|
@ -416,11 +435,15 @@ namespace llarp
|
|||
: ::abyss::httpd::BaseReqHandler(reqtimeout), router(r)
|
||||
{
|
||||
}
|
||||
|
||||
std::string expectedHostname;
|
||||
|
||||
AbstractRouter* router;
|
||||
|
||||
::abyss::httpd::IRPCHandler*
|
||||
CreateHandler(::abyss::httpd::ConnImpl* conn) override
|
||||
{
|
||||
return new Handler(conn, router);
|
||||
return new Handler(conn, router, expectedHostname);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -447,15 +470,20 @@ namespace llarp
|
|||
sockaddr_in saddr;
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = 0;
|
||||
saddr.sin_port = 1190;
|
||||
|
||||
auto idx = addr.find_first_of(':');
|
||||
if(idx != std::string::npos)
|
||||
{
|
||||
_handler.expectedHostname = addr.substr(0, idx);
|
||||
Addr netaddr{addr.substr(0, idx), addr.substr(1 + idx)};
|
||||
saddr.sin_addr.s_addr = netaddr.ton();
|
||||
saddr.sin_port = htons(netaddr.port());
|
||||
}
|
||||
else
|
||||
{
|
||||
_handler.expectedHostname = addr;
|
||||
}
|
||||
return _handler.ServeAsync(router->netloop(), router->logic(),
|
||||
(const sockaddr*)&saddr);
|
||||
}
|
||||
|
|
|
@ -107,6 +107,12 @@ struct ServerHandler : public abyss::httpd::IRPCHandler
|
|||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ValidateHost(const std::string & /*hostname */) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Response
|
||||
HandleJSONRPC(Method_t method, const Params& /*params*/)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue