update in response to merge comments. Covenant connector now looks for C3Bridge listener before creating one. User now only supplies listener port, url, username and password

dependabot/npm_and_yarn/Src/WebController/UI/websocket-extensions-0.1.4
tim.carrington 2020-01-16 16:40:45 +00:00
parent 6a7598c814
commit 86244b322d
2 changed files with 90 additions and 67 deletions

View File

@ -136,9 +136,54 @@ namespace MWR::C3::Interfaces::Connectors
/// Map of all connections. /// Map of all connections.
std::unordered_map<std::string, std::unique_ptr<Connection>> m_ConnectionMap; std::unordered_map<std::string, std::unique_ptr<Connection>> m_ConnectionMap;
bool GetListenerId();
}; };
} }
bool MWR::C3::Interfaces::Connectors::Covenant::GetListenerId()
{
std::string url = this->m_webHost + OBF("/api/listeners");
json response;
web::http::client::http_client_config config;
config.set_validate_certificates(false); //Covenant framework is unlikely to have a valid cert.
web::http::client::http_client webClient(utility::conversions::to_string_t(url), config);
web::http::http_request request;
request = web::http::http_request(web::http::methods::GET);
std::string authHeader = OBF("Bearer ") + this->m_token;
request.headers().add(OBF_W(L"Authorization"), utility::conversions::to_string_t(authHeader));
pplx::task<web::http::http_response> task = webClient.request(request);
web::http::http_response resp = task.get();
if (resp.status_code() == web::http::status_codes::OK)
{
//Get the json response
auto respData = resp.extract_string();
response = json::parse(respData.get());
for (auto& listeners : response)
{
if (listeners[OBF("name")] == OBF("C3Bridge"))
{
this->m_ListenerId = listeners[OBF("id")].get<int>();
this->m_ListeningPostAddress = listeners[OBF("connectAddresses")][0].get<std::string>();
this->m_ListeningPostPort = listeners[OBF("connectPort")];
return true;
}
}
return false; //we didn't find the listener
}
else
throw std::exception((OBF("[Covenant] Error getting Listeners, HTTP resp: ") + std::to_string(resp.status_code())).c_str());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments) MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
@ -146,7 +191,12 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
json postData; json postData;
json response; json response;
std::tie(m_ListeningPostAddress, m_ListeningPostPort, m_webHost, m_username, m_password) = arguments.Read<std::string, uint16_t, std::string, std::string, std::string>(); std::tie(m_ListeningPostPort, m_webHost, m_username, m_password) = arguments.Read<uint16_t, std::string, std::string, std::string>();
// if the last character is '/' remove it
if (this->m_webHost.back() == '/')
this->m_webHost.pop_back();
/***Authenticate to Web API ***/ /***Authenticate to Web API ***/
std::string url = this->m_webHost + OBF("/api/users/login"); std::string url = this->m_webHost + OBF("/api/users/login");
@ -182,69 +232,40 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
else else
throw std::exception(OBF("[Covenant] Could not get token, invalid logon")); throw std::exception(OBF("[Covenant] Could not get token, invalid logon"));
///Create the bridge listener //If the listener doesn't already exist create it.
url = this->m_webHost + OBF("/listener/createbridge"); if (!GetListenerId())
web::http::client::http_client webClientBridge(utility::conversions::to_string_t(url), config);
request = web::http::http_request(web::http::methods::POST);
request.headers().set_content_type(utility::conversions::to_string_t(OBF("application/x-www-form-urlencoded")));
std::string authHeader = OBF("Bearer ") + this->m_token;
request.headers().add(OBF_W(L"Authorization"), utility::conversions::to_string_t(authHeader));
std::string createBridgeString = "Id=0&GUID=b85ea642f2&ListenerTypeId=2&Status=Active&CovenantToken=&Description=A+Bridge+for+custom+listeners.&Name=C3Bridge&BindAddress=0.0.0.0&BindPort=" + \
std::to_string(this->m_ListeningPostPort) + "&ConnectPort=" + std::to_string(this->m_ListeningPostPort) + "&ConnectAddresses%5B0%5D=" + \
this->m_ListeningPostAddress + "&ProfileId=3";
request.set_body(utility::conversions::to_string_t(createBridgeString));
task = webClientBridge.request(request);
resp = task.get();
if (resp.status_code() == web::http::status_codes::OK)
{ {
//Find the listener we just created //extract ip address from url
url = this->m_webHost + OBF("/api/listeners"); size_t start = 0, end = 0;
web::http::client::http_client webClientListeners(utility::conversions::to_string_t(url), config); start = url.find("://") + 3;
end = url.find(":", start + 1);
request = web::http::http_request(web::http::methods::GET); this->m_ListeningPostAddress = url.substr(start, end - start);
///Create the bridge listener
url = this->m_webHost + OBF("/listener/createbridge");
web::http::client::http_client webClientBridge(utility::conversions::to_string_t(url), config);
request = web::http::http_request(web::http::methods::POST);
request.headers().set_content_type(utility::conversions::to_string_t(OBF("application/x-www-form-urlencoded")));
std::string authHeader = OBF("Bearer ") + this->m_token; std::string authHeader = OBF("Bearer ") + this->m_token;
request.headers().add(OBF_W(L"Authorization"), utility::conversions::to_string_t(authHeader)); request.headers().add(OBF_W(L"Authorization"), utility::conversions::to_string_t(authHeader));
task = webClientListeners.request(request); std::string createBridgeString = "Id=0&GUID=b85ea642f2&ListenerTypeId=2&Status=Active&CovenantToken=&Description=A+Bridge+for+custom+listeners.&Name=C3Bridge&BindAddress=0.0.0.0&BindPort=" + \
std::to_string(this->m_ListeningPostPort) + "&ConnectPort=" + std::to_string(this->m_ListeningPostPort) + "&ConnectAddresses%5B0%5D=" + \
this->m_ListeningPostAddress + "&ProfileId=3";
request.set_body(utility::conversions::to_string_t(createBridgeString));
task = webClientBridge.request(request);
resp = task.get(); resp = task.get();
bool found = false;
if (resp.status_code() == web::http::status_codes::OK) if (resp.status_code() == web::http::status_codes::OK)
{ GetListenerId(); //now get the id of the listener
//Get the json response else
auto respData = resp.extract_string(); throw std::exception((OBF("[Covenant] Error setting up BridgeListener, HTTP resp: ") + std::to_string(resp.status_code())).c_str());
response = json::parse(respData.get());
for (auto& listeners : response)
{
if (listeners[OBF("name")] == OBF("C3Bridge"))
{
this->m_ListenerId = listeners[OBF("id")].get<int>();
found = true;
}
}
}
//will be true if status_code != OK or C3Bridge wasn't found
if (!found)
{
throw std::exception(OBF("[Covenant] unable to identify ID of Bridge Listener"));
}
InitializeSockets();
} }
else
throw std::exception((OBF("[Covenant] Error setting up BridgeListener, HTTP resp: ") + std::to_string(resp.status_code())).c_str());
InitializeSockets();
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MWR::C3::Interfaces::Connectors::Covenant::~Covenant() MWR::C3::Interfaces::Connectors::Covenant::~Covenant()
@ -328,10 +349,17 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteV
task = webClient.request(request); task = webClient.request(request);
resp = task.get(); resp = task.get();
auto respData = resp.extract_string(); if (resp.status_code() == web::http::status_codes::OK)
json resp = json::parse(respData.get()); {
binary = resp[OBF("base64ILByteString")].get<std::string>(); //Contains the base64 encoded .NET assembly. auto respData = resp.extract_string();
json resp = json::parse(respData.get());
binary = resp[OBF("base64ILByteString")].get<std::string>(); //Contains the base64 encoded .NET assembly.
}
else
throw std::runtime_error(OBF("[Covenant] Non-200 HTTP code returned: ") + std::to_string(resp.status_code()));
} }
else
throw std::runtime_error(OBF("[Covenant] Non-200 HTTP code returned: ") + std::to_string(resp.status_code()));
auto payload = cppcodec::base64_rfc4648::decode(binary); auto payload = cppcodec::base64_rfc4648::decode(binary);
@ -348,8 +376,7 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteV
MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::CloseConnection(ByteView arguments) MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::CloseConnection(ByteView arguments)
{ {
auto id = arguments.Read<std::string>(); m_ConnectionMap.erase(arguments);
m_ConnectionMap.erase(id);
return {}; return {};
} }
@ -377,16 +404,11 @@ MWR::ByteView MWR::C3::Interfaces::Connectors::Covenant::GetCapability()
{ {
"arguments": "arguments":
[ [
{
"type": "ip",
"name": "Address",
"description": "C2Bridge ip address - this will be setup automatically"
},
{ {
"type": "uint16", "type": "uint16",
"name": "Port", "name": "C2BridgePort",
"min": 1, "min": 1,
"description": "C2Bridge port - this will be setup automatically" "description": "The port for the C2Bridge Listener if it doesn't already exist."
}, },
{ {
"type": "string", "type": "string",
@ -560,3 +582,4 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::PeripheralCreationCom
} }

View File

@ -193,7 +193,7 @@ MWR::C3::Interfaces::Peripherals::Grunt::Grunt(ByteView arguments)
} }
} }
std::runtime_error{ OBF("Grunt creation failed") }; throw std::runtime_error{ OBF("Grunt creation failed") };
} }
void MWR::C3::Interfaces::Peripherals::Grunt::OnCommandFromConnector(ByteView data) void MWR::C3::Interfaces::Peripherals::Grunt::OnCommandFromConnector(ByteView data)