Site icon API Security Blog

Monero: Monero can leak unitialized memory

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

Exit mobile version