See this proof of concept:
“`cpp
#include
#include
#include
INITIALIZE_EASYLOGGINGPP
template
static void invoke_http_json(void)
{
typename T::request ireq;
typename T::response ires;
std::string req_param;
if(!epee::serialization::store_t_to_json(ireq, req_param)) {
return;
}
printf(“%sn”, req_param.c_str());
}
int main(void)
{
while ( true ) {
const unsigned char which = rand() % 65;
printf(“which: %un”, which);
switch ( which ) {
case 0:
invoke_http_json();
break;
case 1:
invoke_http_json();
break;
case 2:
invoke_http_json();
break;
case 3:
invoke_http_json();
break;
case 4:
invoke_http_json();
break;
case 5:
invoke_http_json();
break;
case 6:
invoke_http_json();
break;
case 7:
invoke_http_json();
break;
case 8:
invoke_http_json();
break;
case 9:
invoke_http_json();
break;
case 10:
invoke_http_json();
break;
case 11:
invoke_http_json();
break;
case 12:
invoke_http_json();
break;
case 13:
invoke_http_json();
break;
case 14:
invoke_http_json();
break;
case 15:
invoke_http_json();
break;
case 16:
invoke_http_json();
break;
case 17:
invoke_http_json();
break;
case 18:
invoke_http_json();
break;
case 19:
invoke_http_json();
break;
case 20:
invoke_http_json();
break;
case 21:
invoke_http_json();
break;
case 22:
invoke_http_json();
break;
case 25:
invoke_http_json();
break;
case 27:
invoke_http_json();
break;
case 28:
invoke_http_json();
break;
case 29:
invoke_http_json();
break;
case 30:
invoke_http_json();
break;
case 31:
invoke_http_json();
break;
case 32:
invoke_http_json();
break;
case 33:
invoke_http_json();
break;
case 34:
invoke_http_json();
break;
case 35:
invoke_http_json();
break;
case 36:
invoke_http_json();
break;
case 37:
invoke_http_json();
break;
case 38:
invoke_http_json();
break;
case 39:
invoke_http_json();
break;
case 40:
invoke_http_json();
break;
case 41:
invoke_http_json();
break;
case 42:
invoke_http_json();
break;
case 43:
invoke_http_json();
break;
case 44:
invoke_http_json();
break;
case 45:
invoke_http_json();
break;
case 46:
invoke_http_json();
break;
case 47:
invoke_http_json();
break;
case 48:
invoke_http_json();
break;
case 49:
invoke_http_json();
break;
case 50:
invoke_http_json();
break;
case 51:
invoke_http_json();
break;
case 52:
invoke_http_json();
break;
case 53:
invoke_http_json();
break;
case 54:
invoke_http_json();
break;
case 55:
invoke_http_json();
break;
case 56:
invoke_http_json();
break;
case 57:
invoke_http_json();
break;
case 58:
invoke_http_json();
break;
case 59:
invoke_http_json();
break;
case 60:
invoke_http_json();
break;
case 61:
invoke_http_json();
break;
case 62:
invoke_http_json();
break;
case 63:
invoke_http_json();
break;
case 64:
invoke_http_json();
break;
}
}
return 0;
}
“`
Compile:
“`
g++ -std=c++11 -I $MONERO_PATH/src -I $MONERO_PATH/contrib/epee/include -I $MONERO_PATH/external/easylogging++ $MONERO_PATH/external/easylogging++/easylogging++.cc uninitialized-memory-send.cpp -lpthread -lboost_system -lcrypto -lssl
“`
Run:
“`
./a.out | head -n1000000 | sort -u >output
“`
If you examine “`output“`, you’ll see that JSON is generated with random data. This is uninitialized memory created at the instantiation of “`ireq“`.
To solve this, initialize “`ireq“`. For example, change
“`
typename T::request ireq;
“`
to
“`
boost::value_initialized _ireq;
typename T::request& ireq = _ireq;
“`
Compile and run again, and you’ll see that the random data is now gone.
Among other places, “`src/wallet/wallet2.cpp“` contains many calls to “`invoke_http_json“`, with some “`::request“` structs initialized with “`AUTO_VAL_INIT“`, but some not.
“`invoke_http_json“` serializes the “`::request“` struct exactly like in my proof-of-concept which is then sent to the RPC server:
“`
namespace epee
{
namespace net_utils
{
template
bool invoke_http_json(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = “GET”)
{
std::string req_param;
if(!serialization::store_t_to_json(out_struct, req_param))
return false;
https::fields_list additional_params;
additional_params.push_back(std::make_pair(“Content-Type”,”application/json; charset=utf-8″));
const https::http_response_info* pri = NULL;
if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri), std::move(additional_params)))
…
…
“`
Any outbound traffic (bootstrap node/public RPC server/other) where the “`::request“` struct is not explicitly initialized, is thus susceptible to leaking uninitialized memory. Uninitialized memory is never literally uninitialized — it contains remnants of previous use of the same memory region, and this can include cryptographic or other private material.
## Impact
Leaking sensitive data to untrusted network peers.Read More
References
Back to Main