🚨 NFT & Gaming Security Alert for #EVM / #solidity projects 🚨
🧵 time on why weak PRNG can lead to technical users winning everything…
First, we're excited to announce our audit of @exiledracers' smart contract - in the lead up to their mint on May 31. ✅
Our work together helped identify this ecosystem-wide issue of a weak pseudo-random number generator (PRNG) + Signature frontrunning/replay
The weak PRNG issue is way too common in the #gaming ecosystem. If you are not using @chainlink VRF and want to generate a PRNG, never use msg.sender or a controlled address in the generation.
At the time of the audit of the EXR contracts, @MoonbeamNetwork did not have an implementation of Chainlink’s VRF or an equivalent solution for generating randomness.
In an attempt to further reduce miners’ ability to interfere, the EXR team introduced a seed that’s generated off-chain to be used in combination with the caller’s address.
Exiled Racers used an internal function named _claimRandomItems() to generate a pseudo-random number #️⃣:
The number #️⃣ was generated with:
✔️ The address of the caller
✔️ The current block number of the transaction minus one
✔️ A seed known by the user before the call
With this #️⃣, different item rarities were chosen: Common (50% chance), Mid (35% chance), Rare (15% chance).
When the address of the caller is involved, there can be a real security threat ☠️
@solidity_lang’s opcode CREATE2 predicts a contract’s address without creating it. So how can this be abused?
First, let's create a contract called POCCaller which will be the contract address that will call the _claimRandomItems() function getting us the rarest item:
This contract will be deployed at a precomputed “winning” address calculated by a contract called POC using CREATE2.
The “father” contract POC identifies a deployment address for the POCCaller contract that will win the game.
This is our exploit function, located in the POC contract:
With every iteration in the loop ➰, we precompute a contract address using the getAddress(<salt>) function:
Once we precompute the address, we check in our contract if it is going to give us the highest rarity. The contract logic from the Exiled Racers contract is copied into our POC contract. If the precomputed address is a winning one, we deploy the contract with the same salt:
And then we claim the rewards from our son contract:
As we could see in the claimNotRandomItems() function above we are looking for item categories >81. Here we are claiming with our exploit contract 2 items with a category > 81:
To prevent this, smart contracts should be blocked from calling PRNG functions by using this require statement:
🚨 Halborn Discovers Zero-Day in CosmWasm 🚨
Read below for a 🧵 on our zero-day vulnerability in @CosmWasm smart contracts across 20+ blockchains…
1/ Last month, Halborn security researcher @OwlAtNite discovered a #zeroday vulnerability from the lack of normalization of addresses in Bech32 specification (a format for SegWit addresses) in #CosmWasm.
2/ This critical vulnerability allows an attacker to bypass validity checks or break storage keys🔑 under certain conditions.