Ensure the security of your smart contracts

How to Compare VMs

Author: Alexey Naberezhniy
Security researcher at MixBytes
What potential vulnerabilities exist in blockchains that have an Ethereum-like VM?
Complete Blockchain Shutdown Caused by Sending a Malicious Transaction
Blockchain is an open system that allows users to send any transactions that will be processed by a virtual machine. One of the potential vulnerabilities that can exist in blockchains is the lack of verification that the payload sent by the user will not completely stop the network since block producers are not be able to process this operation.
An example of the error in the Aptos VM
The following commands lead to a potential issue in the Aptos virtual machine:

Bytecode::VecPack(si, num)
Bytecode::VecUnpack(si, num)
The presence of these opcodes which interact with the stack results in a user's being able to add num (u64) elements to the stack (it's impossible in the Ethereum VM, since PUSH opcodes are limited).
In this place in code, it becomes possible to cause an overflow, since num_pushes are not validated in any way:
Calling an overflow in this place does not lead to the theft of funds, but causes a critical error in the node, and therefore in the entire blockchain. Since Aptos is a new network, this may cause the entire network to go down at the moment. To do this, it is enough for a hacker to send one malicious transaction. Ethereum is not susceptible to this type of vulnerability, as there are a number of alternative chain node implementations.

Source: https://medium.com/numen-cyber-labs/analysis-of-the-first-critical-0-day-vulnerability-of-aptos-move-vm-8c1fd6c2b98e
Incorrect implementation of precompiles
In order to optimize the execution of smart contracts, node chain developers add additional functionality that can be utilized directly from the virtual machine to speed up some complex functions (such as sha3, ecrecover, etc.). The easiest example to understand is JNI for communicating java bytecode with native code directly.
Examples of precompiles implementations:

An example of an error in the Precompile (Avalanche)
An error in the precompile that caused some smart contracts to work incorrectly is presented below:

// https://snowtrace.io/address/0x0100000000000000000000000000000000000000

func (evm *EVM) NativeAssetCall(caller common.Address, input []byte, suppliedGas uint64, gasCost uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
	if suppliedGas < gasCost {
		return nil, 0, vmerrs.ErrOutOfGas
	remainingGas = suppliedGas - gasCost

    // Send [assetAmount] of [assetID] to [to] address
	evm.Context.TransferMultiCoin(evm.StateDB, caller, to, assetID, assetAmount)
	ret, remainingGas, err = evm.Call(AccountRef(caller), to, callData, remainingGas, new(big.Int))

require(callee != address(bentoBox) && callee != address(this), "Cauldron: can't call");

(bool success, bytes memory returnData) = callee.call{value: value}(callData);
Before callee.call is called, there is a check for callee != address(bentoBox), which restricts the call to bentoBox. But if we call contract 0x0100000000000000000000000000000000000000 passing the call to bentoBox, then the require check can be bypassed.
After this vulnerability disclosure, this precompile was excluded from the node.

Source: https://medium.com/avalancheavax/apricot-phase-6-native-asset-call-deprecation-a7b7a77b850a
Network Attacks
Each blockchain node interacts with the outside world in one way or another. There are many interfaces, such as: RPC, admin interface, etc. An attacker is also able to attack the network via these interfaces.

How to check for vulnerabilities of these types?
There are several options for finding vulnerabilities in Ethereum-like VMs:

Other posts