zkSync Era - OffsideLabs's results

Future-proof zkEVM on the mission to scale freedom for all.

General Information

Platform: Code4rena

Start Date: 02/10/2023

Pot Size: $1,100,000 USDC

Total HM: 28

Participants: 64

Period: 21 days

Judge: GalloDaSballo

Total Solo HM: 13

Id: 292

League: ETH

zkSync

Findings Distribution

Researcher Performance

Rank: 6/64

Findings: 2

Award: $21,458.48

๐ŸŒŸ Selected for report: 1

๐Ÿš€ Solo Findings: 0

Findings Information

๐ŸŒŸ Selected for report: OffsideLabs

Also found by: HE1M, ustas

Labels

bug
2 (Med Risk)
disagree with severity
downgraded by judge
primary issue
selected for report
sponsor confirmed
sufficient quality report
M-05

Awards

14682.1206 USDC - $14,682.12

External Links

Lines of code

https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/contracts/libraries/TransactionHelper.sol#L183-L187 https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/contracts/DefaultAccount.sol#L78-L107

Vulnerability details

The L2 DefaultAccount.validateTransaction function and transaction encoding process in the bootloader do not enforce EIP-155. If the reserved[0] of the legacy tx is zero, the EIP-155 will be disabled. The chainId will not be included in the transaction signature.

        bytes memory encodedChainId;
        if (_transaction.reserved[0] != 0) {
            encodedChainId = bytes.concat(RLPEncoder.encodeUint256(block.chainid), hex"80_80");
        }

Impact

There are two potential exploitation scenarios:

  1. A malicious attacker can replay transactions from the mainnet or other networks not protected by EIP-155. While there are very few EVM networks currently supporting transactions without EIP-155, attackers still have an opportunity to profit by replaying early transactions from other networks. For example, if an early ETH user A sent a legacy tx to user B before EIP-155 enabled, and now user A deposited some ETH into the Zksync era network, then user B could replay the early transaction from user A to steal his funds on the Zksync network.

  2. Operators can replay early user transactions from eth/other EVM networks to collect gas fees or even profit directly.

Proof of Concept

EIP-155 will be disabled when the following two conditions are met:

  1. transaction type is legacy tx, which tx_type=0 ;

  2. tx.reserved[0] == 0

The value of the reserved field cannot be set arbitrarily, but if the user inputs a transaction with tx_type=0 and the v in the signature is 27 or 28, then reserved[0] will be set to 0.

Code: https://github.com/matter-labs/zksync-era/blob/6cb8c2c350385ed96c0824869a885a7285735a91/core/lib/vm/src/types/internals/transaction_data.rs#L52-L60

                let should_check_chain_id = if matches!(
                    common_data.transaction_type,
                    TransactionType::LegacyTransaction
                ) && common_data.extract_chain_id().is_some()
                {
                    U256([1, 0, 0, 0])
                } else {
                    U256::zero()
                };
    pub fn extract_chain_id(&self) -> Option<u64> {
        let bytes = self.input_data()?;
        let chain_id = match bytes.first() {
            Some(x) if *x >= 0x80 => {
                let rlp = Rlp::new(bytes);
                let v = rlp.val_at(6).ok()?;
                PackedEthSignature::unpack_v(v).ok()?.1?
            }

Tools Used

Manual review

Enforce EIP-155 signature verification in the contract DefaultAccount.validateTransaction

Assessed type

Other

#0 - c4-pre-sort

2023-11-01T05:34:54Z

bytes032 marked the issue as primary issue

#1 - c4-pre-sort

2023-11-01T05:34:58Z

bytes032 marked the issue as sufficient quality report

#2 - miladpiri

2023-11-06T11:54:37Z

This is a design decision. So, QA.

#3 - c4-sponsor

2023-11-06T11:54:58Z

miladpiri (sponsor) confirmed

#4 - c4-sponsor

2023-11-06T11:55:03Z

miladpiri marked the issue as disagree with severity

#5 - GalloDaSballo

2023-11-23T19:22:38Z

Downgrading to QA because this is an option, not the default

#6 - c4-judge

2023-11-23T19:22:46Z

GalloDaSballo changed the severity to QA (Quality Assurance)

#7 - 5z1punch

2023-12-01T02:26:59Z

I have privately submitted a real attack example to sponsor and judge to demonstrate that this is a critical issue. However, due to its impact on the era mainnet, I am currently not publicly disclosing them on this page. Respectfully ping @GalloDaSballo @miladpiri

#8 - c4-judge

2023-12-05T12:51:24Z

This previously downgraded issue has been upgraded by GalloDaSballo

#9 - vladbochok

2023-12-11T12:04:24Z

This is design decision for supporting pre EIP155 transactions, that many other EVM compatible chains supports. The exact reason for supporting pre EIP155 transaction is having benefits of keyless transactions (as deterministic deployments). Due to this reason, I don't see this as a security issue at all.

#10 - c4-judge

2023-12-13T15:52:14Z

GalloDaSballo marked the issue as selected for report

#11 - c4-judge

2024-01-11T15:36:47Z

GalloDaSballo changed the severity to 2 (Med Risk)

#12 - GalloDaSballo

2024-01-11T15:40:26Z

I have spent tens of hours around this issue

Investigating it's impact And investigating why this issue is considered "acceptable"

I believe that a clear divide between Developers and Security Researchers can be seen in how Severity is interpreted for this issue.

Any "EVM Developer" will look at this finding as trivial, and obvious, "it's the user fault" for having a wallet that is pre EIP-155 And the usage of this signature scheme are keyless deployments

Any SR will look at this as a means to DOS users, and potentially steal their funds

I have spoken with a lot of different actors in the security space and have heard every possible severity for this type of findings

From known to high severity

After talking with 4 different judges, am going to set the finding as Medium Severity as zkSync is not uniquely subjected to this finding, but I believe the finding to be a danger to end users which should be publicly disclosed to them

Findings Information

๐ŸŒŸ Selected for report: HE1M

Also found by: Audittens, OffsideLabs, zkrunner

Labels

bug
2 (Med Risk)
disagree with severity
downgraded by judge
satisfactory
sponsor confirmed
sufficient quality report
duplicate-71

Awards

6776.3633 USDC - $6,776.36

External Links

Lines of code

https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/contracts/Compressor.sol#L54-L82

Vulnerability details

The _rawCompressedData parameter for Compressor.publishCompressedBytecode is currently provided directly by the operator and it represents the compressed bytecode, which should be published as โ€œexpensiveโ€ pubdata. But the publishCompressedBytecode function only check if the compressed data matchs with the original bytecode and bytecode hash. The only check for the length of _rawCompressedData is

require(dictionary.length <= 2 ** 16 * 8, "Dictionary is too big");

However, the check doesn't guarantee the compression ratio of the compressed bytecode. So a malicious operator submit a very long but valid dictionary to overcharge users gas, and even force users transactions to fail.

Impact

  1. Malicious operators can overcharge users gas for the L2 transactions with FactoryDeps .

  2. And since the publishCompressedBytecode function is called at the very beginning of bootloader.l2TxExecution , if a malicious operator exploits this vulnerability to consume all the gas passed into ZKSYNC_NEAR_CALL_markFactoryDepsL2, the normal transaction execution may be forced to fail due to out of gas.

Proof of Concept

The compressed bytecode is inputted directly from operator memory in the ZKSYNC_NEAR_CALL_markFactoryDepsL2 :

let dataInfoPtr := mload(COMPRESSED_BYTECODES_BEGIN_BYTE())

The operator can first compress the bytecode into the correct format and then pad the end of the dictionary with 0xff bytes that won't be used or checked, until the dictionary length reaches its maximum value of 2**19.

Tools Used

Manual review

Check the compression ratio, the length of the compressed bytecode should not be greater than the original length.

Assessed type

Invalid Validation

#0 - bytes032

2023-11-01T16:08:44Z

length of compressed bytecode should <= original length

#1 - c4-pre-sort

2023-11-02T13:56:48Z

141345 marked the issue as sufficient quality report

#2 - miladpiri

2023-11-06T11:37:05Z

This finding is valid but it is not explaing the attack clearly. This is duplicate of https://github.com/code-423n4/2023-10-zksync-findings/issues/71 that is explaining better and detailed.

#3 - c4-sponsor

2023-11-06T11:37:14Z

miladpiri marked the issue as disagree with severity

#4 - c4-sponsor

2023-11-06T11:37:26Z

miladpiri (sponsor) confirmed

#5 - c4-judge

2023-11-25T10:17:12Z

GalloDaSballo marked the issue as duplicate of #71

#6 - c4-judge

2023-11-28T15:51:29Z

GalloDaSballo changed the severity to 2 (Med Risk)

#7 - c4-judge

2023-11-28T15:51:39Z

GalloDaSballo marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax ยฉ 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter