🎉 [Gate 30 Million Milestone] Share Your Gate Moment & Win Exclusive Gifts!
Gate has surpassed 30M users worldwide — not just a number, but a journey we've built together.
Remember the thrill of opening your first account, or the Gate merch that’s been part of your daily life?
📸 Join the #MyGateMoment# campaign!
Share your story on Gate Square, and embrace the next 30 million together!
✅ How to Participate:
1️⃣ Post a photo or video with Gate elements
2️⃣ Add #MyGateMoment# and share your story, wishes, or thoughts
3️⃣ Share your post on Twitter (X) — top 10 views will get extra rewards!
👉
Move language reference security vulnerabilities: integer overflow risks and prevention recommendations
In-depth Analysis of Move Language Reference Security Vulnerabilities
Recently, during our in-depth research on Aptos Moveevm, we discovered a new integer overflow vulnerability. The process of triggering this vulnerability is quite interesting, and below we will conduct an in-depth analysis of it and introduce relevant background knowledge of the Move language. Through this explanation, we believe readers will gain a deeper understanding of the Move language.
The Move language performs code unit validation before executing bytecode, a process that consists of 4 steps. The vulnerability discussed in this article occurs during the reference_safety step.
The reference_safety module defines transfer functions used to verify the reference safety of the process subject. It mainly checks for issues such as dangling references, the safety of mutable reference access, and the safety of global storage reference access.
The verification process starts from the secure verification entry function, which calls analyze_function. In analyze_function, each basic block is verified. A basic block is a sequence of code that has no branch instructions except at the entry and exit.
The Move language identifies basic blocks by traversing the bytecode and looking for all branch instructions and loop instruction sequences. A typical example of a Move IR code basic block may contain 3 basic blocks, determined by the BrTrue, Branch, and Ret instructions.
The Move language supports two types of references: immutable references (&) and mutable references (&mut). Immutable references are used for reading data, while mutable references are used for modifying data. This design helps maintain code safety and identify reading modules.
The main process of reference safety verification includes: scanning the bytecode instructions of basic blocks in the function and determining whether all reference operations are legal. This process uses the AbstractState structure, which contains the borrow graph and locals, to ensure the reference safety within the function.
During the verification process, the basic block code will be executed to generate the post state, then the pre state and post state will be merged to update the block state, and the post conditions of the block will be propagated to subsequent blocks. This process is similar to the Sea of Nodes concept in the V8 turbofan.
The vulnerability occurs in the join_ function. When the sum of the parameter length and the local variable length exceeds 256, an integer overflow occurs because local is of u8 type. Although Move has a process to check the number of locals, the check bounds module only verifies locals and does not include the parameter length.
This integer overflow vulnerability could lead to a DoS attack. By creating a loop code block and exploiting the overflow to change the block's state, the new locals map can differ from the previous one. When the execute_block function is executed again, if the index that the instruction needs to access does not exist in the new AbstractState locals map, it will result in a DoS.
We found that the MoveLoc/CopyLoc/FreeRef opcodes in the reference safety module can achieve this goal. Taking the copy_loc function as an example, if the LocalIndex does not exist, it will lead to a panic, causing the entire node to crash.
To verify this vulnerability, we wrote a PoC. The code block in this PoC contains an unconditional branch instruction that jumps back to the first instruction every time the last instruction is executed, so this code block will repeatedly call the execute_block and join functions.
By setting appropriate parameters, we can make the length of the new locals map become 8. When the execute_block function is executed for the second time, a panic will occur due to insufficient locals length.
This vulnerability reminds us that even languages like Move, which emphasize security, can have flaws. We recommend that Move language designers add more checking code at runtime to prevent unexpected situations. Currently, security checks in the Move language mainly occur during the verify phase, but this may not be sufficient. Once verification is bypassed, if there is not enough security reinforcement in the runtime phase, it could lead to more severe issues.
As a leader in Move language security research, we will continue to delve into the security issues of Move and share more findings in the future.