Researchers at Slowmist regularly analyze the security of the Bitcoin blockchain. During one such audit, they discovered a vulnerability in the Libbitcoin Explorer library version 3.x, which allowed attackers to steal over $900,000 from Bitcoin wallet owners.
According to experts, this vulnerability may threaten not only Bitcoin users but also those working with Ethereum, Ripple, Dogecoin, Solana, Litecoin, Bitcoin Cash, and Zcash if they use the Libbitcoin library to create wallets.
Milk Sad Vulnerability in Libbitcoin Explorer 3.x: How $900,000 Was Stolen
This vulnerability was named “Milk Sad.” Researchers suggested using the first two words from the first BIP39 mnemonic code generated with the bx utility with zero generation time to identify the issue.
Technical Description (CVE-2023-39910)
Libbitcoin Explorer versions 3.0.0 to 3.6.0 implemented a weak entropy generation mechanism for cryptocurrency wallets-this is the Milk Sad problem. The use of the Mersenne Twister (mt19937) pseudorandom number generator limits internal entropy to 32 bits, regardless of settings. This allows remote attackers to recover private keys of any wallets created via “bxseed” and steal funds. All users are advised to move their assets to new, secure wallets.
Entropy Issues in Cake Wallet
Cake Wallet uses the unsafe Dart language Random() function to generate seed phrases:
dartUint8List randomBytes(int length, {bool secure = false}) {
assert(length > 0);
final random = secure ? Random.secure() : Random();
final ret = Uint8List(length);
for (var i = 0; i < length; i++) {
ret[i] = random.nextInt(256);
}
return ret;
}
This is dangerous because the Random() function in Dart can be initialized with zero or system time, making results predictable.
cppRandom::Random() {
uint64_t seed = FLAG_random_seed;
if (seed == 0) {
Dart_EntropySource callback = Dart::entropy_source_callback();
if (callback != nullptr) {
if (!callback(reinterpret_cast<uint8_t*>(&seed), sizeof(seed))) {
seed = 0;
}
}
}
if (seed == 0) {
seed = OS::GetCurrentTimeMicros();
}
Initialize(seed);
}
Vulnerability in Trust Wallet Extension
Recently, Ledger’s Donjon team discovered a critical vulnerability in the Trust Wallet browser extension. It allowed attackers to access all funds in any wallet created with this extension simply by knowing its address. The private key could be instantly calculated, giving full control over the user’s assets.
The problem is that it’s difficult to verify the correct operation of a random number generator, and a poor generator can create an illusion of security. Creating new wallets still requires generating random data, and the quality of this data directly affects the security of all keys the wallet will use.
A mnemonic phrase (12–24 English words) encodes 16 to 32 bytes of entropy according to the BIP39 standard. The quality of this entropy is critical, as all the wallet’s keys for various blockchains (BIP32, BIP44) depend on it.
How the Vulnerability is Implemented in Trust Wallet and bx
In vulnerable versions of Trust Wallet and bx, wallet entropy was generated using the Mersenne Twister (MT19937) generator, which is a critical error. Although bx uses additional time data, this does not prevent attackers from brute-forcing all possible values due to the limited keyspace (32 bits). Trust Wallet uses only a 12-word BIP39 mnemonic to create wallets, implying 128 bits of entropy, but due to incorrect PRNG usage, only 32 bits are actually used.
cppvoid random_buffer(uint8_t* buf, size_t len) {
std::mt19937 rng(std::random_device{}());
std::generate_n(buf, len, [&rng]() -> uint8_t { return rng() & 0x000000ff; });
return;
}
A detailed technical description can be found in the blogs of Ledger Donjon and Milk Sad.
Practical Part: Extracting a Private Key Using the Vulnerability
Let’s look at real examples of obtaining a Bitcoin wallet’s private key via the vulnerability in Libbitcoin Explorer 3.x.
Example 1: Wallet #1
In September 2023, $40,886.76 (1.17536256 BTC) was stolen from this wallet.
- Open Google Colab and create a new notebook.
- Install the necessary libraries and tools (Ruby, bitcoin-ruby, ecdsa, base58, crypto, config-hash, Metasploit Framework).
- Clone the libbitcoin-system repository and open the vulnerable file pseudo_random.cpp.
- Download and extract the ExploitDarlenePRO exploit.
- Determine the virtual machine’s IP address.
- Use MSFVenom to generate a payload for wallet 12iBrqVPpQ2oNeDgJu1F8RtoH1TsD1brU2.
- Save the result in binary form and convert it to HEX to obtain the private key.
- Verify the correspondence of the private key and address using the bitcoin library.
Result: the private key C327FAC63DB7E0CCD1706C03EB5BE0DB2AB3E37A451B84054100D85F314E0F8B matches the address 12iBrqVPpQ2oNeDgJu1F8RtoH1TsD1brU2.
Example 2: Wallet #2
In September 2023, another wallet was robbed of $19,886.91 (0.58051256 BTC).
Similarly, using the vulnerable file and exploit, we obtain the private key 79121F26459E0BA130B5FEDFC223E506E9144339535A6327DA8076FFADDA61BC for the address 1GTBJsQvduQvJ6S6Cv6CsYA2Adj65aDRwe.
Conclusion
This article was created to improve financial security and protect elliptic curve cryptography secp256k1 from weak ECDSA signatures in Bitcoin cryptocurrency. The software authors are not responsible for the use of these materials.
Telegram: https://t.me/cryptodeeptech
Video: https://dzen.ru/video/watch/65478a2f6d9f3f7ec9641804
Source: https://cryptodeeptech.ru/milk-sad-vulnerability-in-libbitcoin-explorer