From 0f981ffea9d9be01203ee5cfda2c99d2d4e86f5b Mon Sep 17 00:00:00 2001 From: Bazsalanszky Date: Tue, 6 Dec 2022 21:18:32 +0100 Subject: [PATCH] Fixed ZoKrates vulnerability --- CCTF_Solutions_main/ctf.sol | 97 ++++++++++++++++++++++++------------ CCTF_Solutions_main/root.zok | 5 +- 2 files changed, 67 insertions(+), 35 deletions(-) diff --git a/CCTF_Solutions_main/ctf.sol b/CCTF_Solutions_main/ctf.sol index 2492187..35f5ea1 100644 --- a/CCTF_Solutions_main/ctf.sol +++ b/CCTF_Solutions_main/ctf.sol @@ -1,6 +1,6 @@ /** *Submitted for verification at polygonscan.com on 2022-08-24 -*/ + */ // SPDX-License-Identifier: Apache-2.0 // Authors: six and Silur @@ -8,8 +8,7 @@ pragma solidity ^0.8.16; import "./verifier.sol"; - -contract CCTF9 is Verifier{ +contract CCTF9 is Verifier { address public admin; uint256 public volMaxPoints; bool public started; @@ -25,12 +24,12 @@ contract CCTF9 is Verifier{ uint256 points; } - modifier onlyAdmin { + modifier onlyAdmin() { require(msg.sender == admin, "Not admin"); _; } - modifier onlyActive { + modifier onlyActive() { require(started == true, "CCTF not started."); _; } @@ -46,8 +45,8 @@ contract CCTF9 is Verifier{ string skill_name; } - mapping (address => Player) public players; - mapping (uint256 => Flag) public flags; + mapping(address => Player) public players; + mapping(uint256 => Flag) public flags; event CCTFStarted(uint256 timestamp); event FlagAdded(uint256 indexed flagId, Hash flagHash); @@ -72,44 +71,66 @@ contract CCTF9 is Verifier{ } /// creates a new capturable flag according to the arguments - function setFlag(uint256 _flagId,Hash memory _flagHash, bool _onlyFirstSolver, uint256 _points, string memory _skill) external onlyAdmin{ + function setFlag( + uint256 _flagId, + Hash memory _flagHash, + bool _onlyFirstSolver, + uint256 _points, + string memory _skill + ) external onlyAdmin { flags[_flagId] = Flag(_flagHash, _onlyFirstSolver, _points, _skill); emit FlagAdded(_flagId, _flagHash); } /// registers the caller as a player function register() external { - require(players[msg.sender].status == PlayerStatus.Unverified, 'Already registered or banned'); + require( + players[msg.sender].status == PlayerStatus.Unverified, + "Already registered or banned" + ); players[msg.sender].status = PlayerStatus.Verified; } + /// sets the player's status either to Unverified, Verified or Banned - function setPlayerStatus(address player, PlayerStatus status) external onlyAdmin { + function setPlayerStatus(address player, PlayerStatus status) + external + onlyAdmin + { players[player].status = status; } - ////////// Submit flags - mapping (address => mapping (uint256 => bool)) Solves; // address -> challenge ID -> solved/not - uint256 public submission_success_count = 0; // For statistics + mapping(address => mapping(uint256 => bool)) Solves; // address -> challenge ID -> solved/not + uint256 public submission_success_count = 0; // For statistics - function SubmitFlag(Proof memory p, uint256 _submitFor) external onlyActive { - require(players[msg.sender].status == PlayerStatus.Verified, "You are not even playing"); + function SubmitFlag(Proof memory p, uint256 _submitFor) + external + onlyActive + { + require( + players[msg.sender].status == PlayerStatus.Verified, + "You are not even playing" + ); - uint[13] memory inputs; - for(uint i =0 ; i < 8;++i){ + uint256[13] memory inputs; + for (uint256 i = 0; i < 8; ++i) { inputs[i] = flags[_submitFor].flagHash.value[i]; } uint32[5] memory addr = addressToUint32(msg.sender); - for(uint i =0; i < 5;++i){ - inputs[8+i] = addr[i]; + for (uint256 i = 0; i < 5; ++i) { + inputs[8 + i] = addr[i]; } - bool valid = verifyTx(p,inputs); - assert(valid); - require(!Solves[msg.sender][_submitFor]); // can't submit the same flag multiple times + + bool valid = verifyTx(p, inputs); + require(valid,"The proof is invalid"); + + require(!Solves[msg.sender][_submitFor],"You cannot submit your solution more than once"); // can't submit the same flag multiple times Solves[msg.sender][_submitFor] = true; players[msg.sender].points += flags[_submitFor].points; - players[msg.sender].points = players[msg.sender].points < volMaxPoints ? players[msg.sender].points : volMaxPoints; + players[msg.sender].points = players[msg.sender].points < volMaxPoints + ? players[msg.sender].points + : volMaxPoints; if (flags[_submitFor].onlyFirstSolver) { flags[_submitFor].points = 0; @@ -120,27 +141,39 @@ contract CCTF9 is Verifier{ } /// maps an address to unsigned int - function addressToUint32 (address _addr) public pure returns (uint32[5] memory) + function addressToUint32(address _addr) + public + pure + returns (uint32[5] memory) { uint256 targetUint = uint256(uint160(_addr)); - uint32[5] memory addr = [uint32(targetUint/4294967296**4), - uint32(targetUint/4294967296**3), - uint32(targetUint/4294967296**2), - uint32(targetUint/4294967296), - uint32(targetUint)]; + uint32[5] memory addr = [ + uint32(targetUint / 4294967296**4), + uint32(targetUint / 4294967296**3), + uint32(targetUint / 4294967296**2), + uint32(targetUint / 4294967296), + uint32(targetUint) + ]; return addr; } ////////// Check status, scores, etc - function getPlayerStatus(address _player) external view returns (PlayerStatus) { + function getPlayerStatus(address _player) + external + view + returns (PlayerStatus) + { return players[_player].status; } function getPlayerPoints(address _player) external view returns (uint256) { - return players[_player].points < volMaxPoints ? players[_player].points : volMaxPoints; + return + players[_player].points < volMaxPoints + ? players[_player].points + : volMaxPoints; } - function getSuccessfulSubmissionCount() external view returns (uint256){ + function getSuccessfulSubmissionCount() external view returns (uint256) { return submission_success_count; } diff --git a/CCTF_Solutions_main/root.zok b/CCTF_Solutions_main/root.zok index 3d66bde..0051bdd 100644 --- a/CCTF_Solutions_main/root.zok +++ b/CCTF_Solutions_main/root.zok @@ -1,11 +1,10 @@ import "hashes/sha256/sha256Padded.zok" as sha256; from "utils/casts.zok" import cast; -def main(public u32[8] hash,public u32[5] address,private u8[64] flag) -> u32[8]{ +def main(public u32[8] hash,public u32[5] address,private u8[64] flag){ u8[20] addr8 = cast(address); u32[8] genHash = sha256(flag); log("Hash: {} {} {} {} {} {} {} {}",genHash[0],genHash[1],genHash[2],genHash[3],genHash[4],genHash[5],genHash[6],genHash[7]); assert(genHash == hash); - u8[32] hash8 = cast(hash); - return sha256([...addr8,...hash8]); + return; } \ No newline at end of file