Fixed ZoKrates vulnerability

frontend
Bazsalanszky 2022-12-06 21:18:32 +01:00
parent ec0fae56dc
commit 0f981ffea9
No known key found for this signature in database
GPG Key ID: B40814F4EFE23F96
2 changed files with 67 additions and 35 deletions

View File

@ -1,6 +1,6 @@
/** /**
*Submitted for verification at polygonscan.com on 2022-08-24 *Submitted for verification at polygonscan.com on 2022-08-24
*/ */
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Authors: six and Silur // Authors: six and Silur
@ -8,8 +8,7 @@ pragma solidity ^0.8.16;
import "./verifier.sol"; import "./verifier.sol";
contract CCTF9 is Verifier {
contract CCTF9 is Verifier{
address public admin; address public admin;
uint256 public volMaxPoints; uint256 public volMaxPoints;
bool public started; bool public started;
@ -25,12 +24,12 @@ contract CCTF9 is Verifier{
uint256 points; uint256 points;
} }
modifier onlyAdmin { modifier onlyAdmin() {
require(msg.sender == admin, "Not admin"); require(msg.sender == admin, "Not admin");
_; _;
} }
modifier onlyActive { modifier onlyActive() {
require(started == true, "CCTF not started."); require(started == true, "CCTF not started.");
_; _;
} }
@ -46,8 +45,8 @@ contract CCTF9 is Verifier{
string skill_name; string skill_name;
} }
mapping (address => Player) public players; mapping(address => Player) public players;
mapping (uint256 => Flag) public flags; mapping(uint256 => Flag) public flags;
event CCTFStarted(uint256 timestamp); event CCTFStarted(uint256 timestamp);
event FlagAdded(uint256 indexed flagId, Hash flagHash); event FlagAdded(uint256 indexed flagId, Hash flagHash);
@ -72,44 +71,66 @@ contract CCTF9 is Verifier{
} }
/// creates a new capturable flag according to the arguments /// 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); flags[_flagId] = Flag(_flagHash, _onlyFirstSolver, _points, _skill);
emit FlagAdded(_flagId, _flagHash); emit FlagAdded(_flagId, _flagHash);
} }
/// registers the caller as a player /// registers the caller as a player
function register() external { 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; players[msg.sender].status = PlayerStatus.Verified;
} }
/// sets the player's status either to Unverified, Verified or Banned /// 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; players[player].status = status;
} }
////////// Submit flags ////////// Submit flags
mapping (address => mapping (uint256 => bool)) Solves; // address -> challenge ID -> solved/not mapping(address => mapping(uint256 => bool)) Solves; // address -> challenge ID -> solved/not
uint256 public submission_success_count = 0; // For statistics uint256 public submission_success_count = 0; // For statistics
function SubmitFlag(Proof memory p, uint256 _submitFor) external onlyActive { function SubmitFlag(Proof memory p, uint256 _submitFor)
require(players[msg.sender].status == PlayerStatus.Verified, "You are not even playing"); external
onlyActive
{
require(
players[msg.sender].status == PlayerStatus.Verified,
"You are not even playing"
);
uint[13] memory inputs; uint256[13] memory inputs;
for(uint i =0 ; i < 8;++i){ for (uint256 i = 0; i < 8; ++i) {
inputs[i] = flags[_submitFor].flagHash.value[i]; inputs[i] = flags[_submitFor].flagHash.value[i];
} }
uint32[5] memory addr = addressToUint32(msg.sender); uint32[5] memory addr = addressToUint32(msg.sender);
for(uint i =0; i < 5;++i){ for (uint256 i = 0; i < 5; ++i) {
inputs[8+i] = addr[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; Solves[msg.sender][_submitFor] = true;
players[msg.sender].points += flags[_submitFor].points; 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) { if (flags[_submitFor].onlyFirstSolver) {
flags[_submitFor].points = 0; flags[_submitFor].points = 0;
@ -120,27 +141,39 @@ contract CCTF9 is Verifier{
} }
/// maps an address to unsigned int /// 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)); uint256 targetUint = uint256(uint160(_addr));
uint32[5] memory addr = [uint32(targetUint/4294967296**4), uint32[5] memory addr = [
uint32(targetUint/4294967296**3), uint32(targetUint / 4294967296**4),
uint32(targetUint/4294967296**2), uint32(targetUint / 4294967296**3),
uint32(targetUint/4294967296), uint32(targetUint / 4294967296**2),
uint32(targetUint)]; uint32(targetUint / 4294967296),
uint32(targetUint)
];
return addr; return addr;
} }
////////// Check status, scores, etc ////////// Check status, scores, etc
function getPlayerStatus(address _player) external view returns (PlayerStatus) { function getPlayerStatus(address _player)
external
view
returns (PlayerStatus)
{
return players[_player].status; return players[_player].status;
} }
function getPlayerPoints(address _player) external view returns (uint256) { 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; return submission_success_count;
} }

View File

@ -1,11 +1,10 @@
import "hashes/sha256/sha256Padded.zok" as sha256; import "hashes/sha256/sha256Padded.zok" as sha256;
from "utils/casts.zok" import cast; 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); u8[20] addr8 = cast(address);
u32[8] genHash = sha256(flag); u32[8] genHash = sha256(flag);
log("Hash: {} {} {} {} {} {} {} {}",genHash[0],genHash[1],genHash[2],genHash[3],genHash[4],genHash[5],genHash[6],genHash[7]); log("Hash: {} {} {} {} {} {} {} {}",genHash[0],genHash[1],genHash[2],genHash[3],genHash[4],genHash[5],genHash[6],genHash[7]);
assert(genHash == hash); assert(genHash == hash);
u8[32] hash8 = cast(hash); return;
return sha256([...addr8,...hash8]);
} }