From 38fea9cb405f8e634835f86b384dae28f15cf98c Mon Sep 17 00:00:00 2001 From: Chris Elbring Date: Wed, 28 Sep 2022 21:33:20 -0500 Subject: [PATCH 1/7] challenge26 --- .../challenges/docker/Challenge26.java | 82 +++++++++++++++++++ src/main/resources/application.properties | 1 + .../resources/explanations/challenge26.adoc | 5 ++ .../explanations/challenge26_hint.adoc | 13 +++ .../explanations/challenge26_reason.adoc | 5 ++ .../challenges/docker/Challenge26Test.java | 26 ++++++ 6 files changed, 132 insertions(+) create mode 100644 src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java create mode 100644 src/main/resources/explanations/challenge26.adoc create mode 100644 src/main/resources/explanations/challenge26_hint.adoc create mode 100644 src/main/resources/explanations/challenge26_reason.adoc create mode 100644 src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java new file mode 100644 index 000000000..690716ff1 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java @@ -0,0 +1,82 @@ +package org.owasp.wrongsecrets.challenges.docker; + + +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Base64; +import org.owasp.wrongsecrets.RuntimeEnvironment; +import org.owasp.wrongsecrets.ScoreCard; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.challenges.ChallengeTechnology; +import org.owasp.wrongsecrets.challenges.Spoiler; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.beans.factory.annotation.Value; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.spec.AlgorithmParameterSpec; +import java.util.List; + +@Slf4j +@Component +@Order(26) +public class Challenge26 extends Challenge { + private final String cipherText; + + public Challenge26(ScoreCard scoreCard, @Value("${challenge26ciphertext}") String cipherText) { + super(scoreCard); + this.cipherText = cipherText; + } + + @Override + public boolean canRunInCTFMode() { + return true; + } + + @Override + public Spoiler spoiler() { + return new Spoiler(quickDecrypt(cipherText)); + } + + @Override + public boolean answerCorrect(String answer) { + String correctString = quickDecrypt(cipherText); + return answer.equals(correctString); + } + + @Override + public List supportedRuntimeEnvironments() { + return List.of(RuntimeEnvironment.Environment.DOCKER); + } + + @Override + public int difficulty() { + return 2; + } + + @Override + public String getTech() { + return ChallengeTechnology.Tech.WEB3.id; + } + + @Override + public boolean isLimittedWhenOnlineHosted() { + return false; + } + + private String quickDecrypt(String cipherText) { + try { + final Cipher decryptor = Cipher.getInstance("AES/GCM/NoPadding"); + SecretKey decryptKey = new SecretKeySpec("thiszthekeytoday".getBytes(StandardCharsets.UTF_8), "AES"); + AlgorithmParameterSpec gcmIv = new GCMParameterSpec(128, Base64.decode(cipherText), 0, 12); + decryptor.init(Cipher.DECRYPT_MODE, decryptKey, gcmIv); + return new String(decryptor.doFinal(Base64.decode(cipherText), 12, Base64.decode(cipherText).length - 12)); + } catch (Exception e) { + log.warn("Exception with Challenge 26", e); + return ""; + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 59cab6f85..70d7961f4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -43,6 +43,7 @@ keepasspath=/var/tmp/helpers/alibabacreds.kdbx canarytokenURLs=http://canarytokens.com/terms/about/s7cfbdakys13246ewd8ivuvku/post.jsp,http://canarytokens.com/terms/about/y0all60b627gzp19ahqh7rl6j/post.jsp challenge15ciphertext=qcyRgfXSh0HUKsW/Xb5LnuWt9DgU8tQJfluR66UDDlmMgVWCGEwk1qxKCi4ZvzDwM38xP3nRFqO4SZEgqp8Ul8Ej/lNDbQCgBuszSILVSV6D9eojOMl6zTcNgzUmjW2K3dJKN9LqXOLYezEpEN2gUaYqPu2nVqmUptKTmXGwAnmQH1TIl2MUueRuXpRKe72IMzKenxZHKRsNFp+ebQebS3qzP+Q= challenge25ciphertext=dQMhBe8oLxIdGLcxPanDLS++srED/x05P+Ph9PFZKlL2K42vXi7Vtbh3/N90sGT087W7ARURZg== +challenge26ciphertext=gbU5thfgy8nwzF/qc1Pq59PrJzLB+bfAdTOrx969JZx1CKeG4Sq7v1uUpzyCH/Fo8W8ghdBJJrQORw== management.endpoint.health.probes.enabled=true management.health.livenessState.enabled=true management.health.readinessState.enabled=true diff --git a/src/main/resources/explanations/challenge26.adoc b/src/main/resources/explanations/challenge26.adoc new file mode 100644 index 000000000..6ddf48c2c --- /dev/null +++ b/src/main/resources/explanations/challenge26.adoc @@ -0,0 +1,5 @@ +=== Secrets in smart contracts part 2 + +Our smart contract developer realized he wrote a secret to the chain and went back and wrote over it. + +In this challenge, you need to read the variable named secret from the contract 0xCe793D588cd1Ee091290b4A1aE1D586B2a748eB4 on the goerli evm testnet as it was before it got changed. \ No newline at end of file diff --git a/src/main/resources/explanations/challenge26_hint.adoc b/src/main/resources/explanations/challenge26_hint.adoc new file mode 100644 index 000000000..edaa9537b --- /dev/null +++ b/src/main/resources/explanations/challenge26_hint.adoc @@ -0,0 +1,13 @@ +You can find the previous state one of two ways. + +Option 1: +1. Find the block number for any block after the contract was created and before it was updated. +2. Search for the storage state of the contract for that block. The below command is an example vs the infura API: + curl https://goerli.infura.io/v3/${your-infura-key} \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["${contract address}", "0x0", "${blocknumber}"], "id": 1}' + +Option 2: +1. Look under the contract creation transaction on etherscan +2. Go to state and look at storage \ No newline at end of file diff --git a/src/main/resources/explanations/challenge26_reason.adoc b/src/main/resources/explanations/challenge26_reason.adoc new file mode 100644 index 000000000..f108eed97 --- /dev/null +++ b/src/main/resources/explanations/challenge26_reason.adoc @@ -0,0 +1,5 @@ +*Why overwriting secrets on the blockchain does not get rid of them* + +The state of the chain can be verified for any point in time by executing the state updates up until a certain block. + +Updating the state of the chain does not remove previous changes to state. \ No newline at end of file diff --git a/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java new file mode 100644 index 000000000..cc4c52290 --- /dev/null +++ b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java @@ -0,0 +1,26 @@ +package org.owasp.wrongsecrets.challenges.docker; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.owasp.wrongsecrets.ScoreCard; + +@ExtendWith(MockitoExtension.class) +class Challenge25Test { + + @Mock + private ScoreCard scoreCard; + + @Test + void rightAnswerShouldSolveChallenge() { + var challenge = new Challenge26(scoreCard, "dQMhBe8oLxIdGLcxPanDLS++srED/x05P+Ph9PFZKlL2K42vXi7Vtbh3/N90sGT087W7ARURZg=="); + Assertions.assertThat(challenge.solved(challenge.spoiler().solution())).isTrue(); + Mockito.verify(scoreCard).completeChallenge(challenge); + } + + + +} From 90b4ff243ade0213e25e3f123a05877090f78673 Mon Sep 17 00:00:00 2001 From: Chris Elbring Date: Wed, 28 Sep 2022 21:36:56 -0500 Subject: [PATCH 2/7] challenge26-2 --- .../owasp/wrongsecrets/challenges/docker/Challenge26Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java index cc4c52290..fd33cfd25 100644 --- a/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java +++ b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java @@ -16,7 +16,7 @@ class Challenge25Test { @Test void rightAnswerShouldSolveChallenge() { - var challenge = new Challenge26(scoreCard, "dQMhBe8oLxIdGLcxPanDLS++srED/x05P+Ph9PFZKlL2K42vXi7Vtbh3/N90sGT087W7ARURZg=="); + var challenge = new Challenge26(scoreCard, "gbU5thfgy8nwzF/qc1Pq59PrJzLB+bfAdTOrx969JZx1CKeG4Sq7v1uUpzyCH/Fo8W8ghdBJJrQORw=="); Assertions.assertThat(challenge.solved(challenge.spoiler().solution())).isTrue(); Mockito.verify(scoreCard).completeChallenge(challenge); } From 8bc4b31b456fdb3d03fd6cc9987a06913ed75e2d Mon Sep 17 00:00:00 2001 From: Chris Elbring Date: Wed, 28 Sep 2022 22:08:07 -0500 Subject: [PATCH 3/7] challenge26-2 --- .../owasp/wrongsecrets/challenges/docker/Challenge26Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java index fd33cfd25..718746075 100644 --- a/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java +++ b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java @@ -9,7 +9,7 @@ import org.owasp.wrongsecrets.ScoreCard; @ExtendWith(MockitoExtension.class) -class Challenge25Test { +class Challenge26Test { @Mock private ScoreCard scoreCard; From 4a83851b8396338e07b2fdeeaa36696cf8538203 Mon Sep 17 00:00:00 2001 From: Chris Elbring Date: Wed, 28 Sep 2022 23:38:34 -0500 Subject: [PATCH 4/7] challenge27 --- src/main/resources/application.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 37a0e059a..d36e4194a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -46,6 +46,7 @@ canarytokenURLs=http://canarytokens.com/terms/about/s7cfbdakys13246ewd8ivuvku/po challenge15ciphertext=qcyRgfXSh0HUKsW/Xb5LnuWt9DgU8tQJfluR66UDDlmMgVWCGEwk1qxKCi4ZvzDwM38xP3nRFqO4SZEgqp8Ul8Ej/lNDbQCgBuszSILVSV6D9eojOMl6zTcNgzUmjW2K3dJKN9LqXOLYezEpEN2gUaYqPu2nVqmUptKTmXGwAnmQH1TIl2MUueRuXpRKe72IMzKenxZHKRsNFp+ebQebS3qzP+Q= challenge25ciphertext=dQMhBe8oLxIdGLcxPanDLS++srED/x05P+Ph9PFZKlL2K42vXi7Vtbh3/N90sGT087W7ARURZg== challenge26ciphertext=gbU5thfgy8nwzF/qc1Pq59PrJzLB+bfAdTOrx969JZx1CKeG4Sq7v1uUpzyCH/Fo8W8ghdBJJrQORw== +challenge27ciphertext=gYPQPfb0TUgWK630tHCWGwwME6IWtPWA51eU0Qpb9H7/lMlZPdLGZWmYE83YmEDmaEvFr2hX management.endpoint.health.probes.enabled=true management.health.livenessState.enabled=true management.health.readinessState.enabled=true From 501d539fc68b2c8a19ec7b7da59ce4669b9a1a7a Mon Sep 17 00:00:00 2001 From: Chris Elbring Date: Wed, 28 Sep 2022 23:38:41 -0500 Subject: [PATCH 5/7] challenge27 --- .../challenges/docker/Challenge27.java | 82 +++++++++++++++++++ .../resources/explanations/challenge27.adoc | 5 ++ .../explanations/challenge27_hint.adoc | 5 ++ .../explanations/challenge27_reason.adoc | 4 + .../challenges/docker/Challenge27Test.java | 26 ++++++ 5 files changed, 122 insertions(+) create mode 100644 src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java create mode 100644 src/main/resources/explanations/challenge27.adoc create mode 100644 src/main/resources/explanations/challenge27_hint.adoc create mode 100644 src/main/resources/explanations/challenge27_reason.adoc create mode 100644 src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge27Test.java diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java new file mode 100644 index 000000000..f63de9fe5 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java @@ -0,0 +1,82 @@ +package org.owasp.wrongsecrets.challenges.docker; + + +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Base64; +import org.owasp.wrongsecrets.RuntimeEnvironment; +import org.owasp.wrongsecrets.ScoreCard; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.challenges.ChallengeTechnology; +import org.owasp.wrongsecrets.challenges.Spoiler; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.beans.factory.annotation.Value; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.spec.AlgorithmParameterSpec; +import java.util.List; + +@Slf4j +@Component +@Order(26) +public class Challenge27 extends Challenge { + private final String cipherText; + + public Challenge27(ScoreCard scoreCard, @Value("${challenge27ciphertext}") String cipherText) { + super(scoreCard); + this.cipherText = cipherText; + } + + @Override + public boolean canRunInCTFMode() { + return true; + } + + @Override + public Spoiler spoiler() { + return new Spoiler(quickDecrypt(cipherText)); + } + + @Override + public boolean answerCorrect(String answer) { + String correctString = quickDecrypt(cipherText); + return answer.equals(correctString); + } + + @Override + public List supportedRuntimeEnvironments() { + return List.of(RuntimeEnvironment.Environment.DOCKER); + } + + @Override + public int difficulty() { + return 2; + } + + @Override + public String getTech() { + return ChallengeTechnology.Tech.WEB3.id; + } + + @Override + public boolean isLimittedWhenOnlineHosted() { + return false; + } + + private String quickDecrypt(String cipherText) { + try { + final Cipher decryptor = Cipher.getInstance("AES/GCM/NoPadding"); + SecretKey decryptKey = new SecretKeySpec("thiszthekeytoday".getBytes(StandardCharsets.UTF_8), "AES"); + AlgorithmParameterSpec gcmIv = new GCMParameterSpec(128, Base64.decode(cipherText), 0, 12); + decryptor.init(Cipher.DECRYPT_MODE, decryptKey, gcmIv); + return new String(decryptor.doFinal(Base64.decode(cipherText), 12, Base64.decode(cipherText).length - 12)); + } catch (Exception e) { + log.warn("Exception with Challenge 27", e); + return ""; + } + } +} diff --git a/src/main/resources/explanations/challenge27.adoc b/src/main/resources/explanations/challenge27.adoc new file mode 100644 index 000000000..d3593cd54 --- /dev/null +++ b/src/main/resources/explanations/challenge27.adoc @@ -0,0 +1,5 @@ +=== Secrets in smart contracts part 3 + +Our smart contract developer got somewhat smarter and only stored a hashed secret in his contract. He then checks a input data vs that hash to validate whether or not a transaction returns true or false. He is sure that since the secret is never stored in the internal state of the contract, that it can't be found. + +In this challenge, you need to find the correct secret that has the guess method from the contract 0x8318d477f4BCae5a80BEA22E3c040cf8BaaFFe8B on the goerli evm testnet return true. \ No newline at end of file diff --git a/src/main/resources/explanations/challenge27_hint.adoc b/src/main/resources/explanations/challenge27_hint.adoc new file mode 100644 index 000000000..8000d9849 --- /dev/null +++ b/src/main/resources/explanations/challenge27_hint.adoc @@ -0,0 +1,5 @@ +You can find the correct input to the guess method by: +1. Looking up the contract on the etherscan explorer. +2. Pulling the hash from the contract storage. +3. Going through the transactions and then opening the inputs tab and decoding them as UTF-8. +4. Comparing the the hashes of the inputs from the transactions with the stored hash value. diff --git a/src/main/resources/explanations/challenge27_reason.adoc b/src/main/resources/explanations/challenge27_reason.adoc new file mode 100644 index 000000000..82e2611f5 --- /dev/null +++ b/src/main/resources/explanations/challenge27_reason.adoc @@ -0,0 +1,4 @@ +*Why sending secrets as inputs to smart contracts is a bad idea even if they aren't stored* + +Inputs to all transactions to contracts, like the state of internal storage of contracts on the chain are stored forever and are easy to query. +Inputs to transactions are even visible before those transactions are accepted. This can lead to frontrunning by a 3rd party who has access to the pool of transactions and can send a transaction (with higher gas) that benefits from the known transaction running after it. \ No newline at end of file diff --git a/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge27Test.java b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge27Test.java new file mode 100644 index 000000000..56264b32a --- /dev/null +++ b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge27Test.java @@ -0,0 +1,26 @@ +package org.owasp.wrongsecrets.challenges.docker; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.owasp.wrongsecrets.ScoreCard; + +@ExtendWith(MockitoExtension.class) +class Challenge27Test { + + @Mock + private ScoreCard scoreCard; + + @Test + void rightAnswerShouldSolveChallenge() { + var challenge = new Challenge27(scoreCard, "gYPQPfb0TUgWK630tHCWGwwME6IWtPWA51eU0Qpb9H7/lMlZPdLGZWmYE83YmEDmaEvFr2hX"); + Assertions.assertThat(challenge.solved(challenge.spoiler().solution())).isTrue(); + Mockito.verify(scoreCard).completeChallenge(challenge); + } + + + +} From 0698a1a55da107b736a96bfe2d4fe4782a655fd4 Mon Sep 17 00:00:00 2001 From: Jeroen Willemsen Date: Thu, 29 Sep 2022 09:27:47 +0200 Subject: [PATCH 6/7] Fixed a few consistency items --- .../explanations/challenge25_hint.adoc | 27 ++++++++++--------- .../resources/explanations/challenge26.adoc | 2 +- .../explanations/challenge26_hint.adoc | 15 ++++++----- .../resources/explanations/challenge27.adoc | 2 +- .../explanations/challenge27_hint.adoc | 10 ++++--- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/main/resources/explanations/challenge25_hint.adoc b/src/main/resources/explanations/challenge25_hint.adoc index 7520094e9..20260ace6 100644 --- a/src/main/resources/explanations/challenge25_hint.adoc +++ b/src/main/resources/explanations/challenge25_hint.adoc @@ -1,21 +1,22 @@ You can solve this challenge by the following steps: -Option 1: -1. Look under the contract creation transaction on https://goerli.etherscan.io/tx/0x497b71a1fd4c57509bfecc2114ec649387fe669c23a3a7e97961f389444d9561[Etherscan] -2. Go to state and look at storage. +1. Look at the storage in Etherscan: +- Look under the contract creation transaction on https://goerli.etherscan.io/tx/0x497b71a1fd4c57509bfecc2114ec649387fe669c23a3a7e97961f389444d9561[Etherscan] +- Go to state and look at storage. -Option 2: -1. Look under the contract creation transaction on https://goerli.etherscan.io/tx/0x497b71a1fd4c57509bfecc2114ec649387fe669c23a3a7e97961f389444d9561[Etherscan] -2. Have a look at the input data. +2. Look at the input data in Etherscan: +- Look under the contract creation transaction on https://goerli.etherscan.io/tx/0x497b71a1fd4c57509bfecc2114ec649387fe669c23a3a7e97961f389444d9561[Etherscan] +- Have a look at the input data. -Option 3: -1. Create an Infura key at https://infura.io/[Infura]. -2. Write a simple script with web3js to call the view function on the public string "secret" +3. Use Infura with web3js at Infura: +- Create an Infura key at https://infura.io/[Infura]. +- Write a simple script with web3js to call the view function on the public string "secret" -Option 2: -1. Create an Infura key at https://infura.io/[Infura]. -2. Read the storage at position 0 for the contract like: -curl https://goerli.infura.io/v3/${} \ +4. Do a storage request at Infura: +- Create an Infura key at https://infura.io/[Infura]. +- Read the storage at position 0 for the contract like: + + curl https://goerli.infura.io/v3/${} \ -X POST \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x8b72f7cbAD50620c46219ad676Ad9d3a5A273587", "0x0", "latest"], "id": 1}' diff --git a/src/main/resources/explanations/challenge26.adoc b/src/main/resources/explanations/challenge26.adoc index 6ddf48c2c..1dd499070 100644 --- a/src/main/resources/explanations/challenge26.adoc +++ b/src/main/resources/explanations/challenge26.adoc @@ -2,4 +2,4 @@ Our smart contract developer realized he wrote a secret to the chain and went back and wrote over it. -In this challenge, you need to read the variable named secret from the contract 0xCe793D588cd1Ee091290b4A1aE1D586B2a748eB4 on the goerli evm testnet as it was before it got changed. \ No newline at end of file +In this challenge, you need to read the variable named secret from the contract `0xCe793D588cd1Ee091290b4A1aE1D586B2a748eB4` on the Goerli EVM Testnet as it was before it got changed. diff --git a/src/main/resources/explanations/challenge26_hint.adoc b/src/main/resources/explanations/challenge26_hint.adoc index edaa9537b..f373d6471 100644 --- a/src/main/resources/explanations/challenge26_hint.adoc +++ b/src/main/resources/explanations/challenge26_hint.adoc @@ -1,13 +1,14 @@ You can find the previous state one of two ways. -Option 1: -1. Find the block number for any block after the contract was created and before it was updated. -2. Search for the storage state of the contract for that block. The below command is an example vs the infura API: - curl https://goerli.infura.io/v3/${your-infura-key} \ +1. Find the previous block via a request to https://infura.io/[Infura]: +- Find the block number for any block after the contract was created and before it was updated. +- Search for the storage state of the contract for that block. The below command is an example vs the infura API: + + curl https://goerli.infura.io/v3/${your-infura-key} \ -X POST \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["${contract address}", "0x0", "${blocknumber}"], "id": 1}' -Option 2: -1. Look under the contract creation transaction on etherscan -2. Go to state and look at storage \ No newline at end of file +2. Look at the contract creation on https://etherscan.io/[Etherscan]: +- Look under the contract creation transaction on etherscan +- Go to state and look at storage diff --git a/src/main/resources/explanations/challenge27.adoc b/src/main/resources/explanations/challenge27.adoc index d3593cd54..0ddb52802 100644 --- a/src/main/resources/explanations/challenge27.adoc +++ b/src/main/resources/explanations/challenge27.adoc @@ -2,4 +2,4 @@ Our smart contract developer got somewhat smarter and only stored a hashed secret in his contract. He then checks a input data vs that hash to validate whether or not a transaction returns true or false. He is sure that since the secret is never stored in the internal state of the contract, that it can't be found. -In this challenge, you need to find the correct secret that has the guess method from the contract 0x8318d477f4BCae5a80BEA22E3c040cf8BaaFFe8B on the goerli evm testnet return true. \ No newline at end of file +In this challenge, you need to find the correct secret that has the guess method from the contract `0x8318d477f4BCae5a80BEA22E3c040cf8BaaFFe8B` on the Goerli EVM Testnet return true. diff --git a/src/main/resources/explanations/challenge27_hint.adoc b/src/main/resources/explanations/challenge27_hint.adoc index 8000d9849..4d3c47265 100644 --- a/src/main/resources/explanations/challenge27_hint.adoc +++ b/src/main/resources/explanations/challenge27_hint.adoc @@ -1,5 +1,7 @@ You can find the correct input to the guess method by: -1. Looking up the contract on the etherscan explorer. -2. Pulling the hash from the contract storage. -3. Going through the transactions and then opening the inputs tab and decoding them as UTF-8. -4. Comparing the the hashes of the inputs from the transactions with the stored hash value. + +1. Comparing hashes: +- Look up the contract on the https://etherscan.io/[Etherscan] explorer. +- Pull the hash from the contract storage. +- Go through the transactions and then opening the inputs tab and decoding them as UTF-8. +- Compare the hashes of the inputs from the transactions with the stored hash value. From c6194084b581377cecbd85a394aee8e067f1d4db Mon Sep 17 00:00:00 2001 From: Jeroen Willemsen Date: Thu, 29 Sep 2022 09:45:33 +0200 Subject: [PATCH 7/7] fixed file endings --- src/main/resources/explanations/challenge26_reason.adoc | 2 +- src/main/resources/explanations/challenge27_reason.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/explanations/challenge26_reason.adoc b/src/main/resources/explanations/challenge26_reason.adoc index f108eed97..ccffc3eea 100644 --- a/src/main/resources/explanations/challenge26_reason.adoc +++ b/src/main/resources/explanations/challenge26_reason.adoc @@ -2,4 +2,4 @@ The state of the chain can be verified for any point in time by executing the state updates up until a certain block. -Updating the state of the chain does not remove previous changes to state. \ No newline at end of file +Updating the state of the chain does not remove previous changes to state. diff --git a/src/main/resources/explanations/challenge27_reason.adoc b/src/main/resources/explanations/challenge27_reason.adoc index 82e2611f5..9a8d199e3 100644 --- a/src/main/resources/explanations/challenge27_reason.adoc +++ b/src/main/resources/explanations/challenge27_reason.adoc @@ -1,4 +1,4 @@ *Why sending secrets as inputs to smart contracts is a bad idea even if they aren't stored* Inputs to all transactions to contracts, like the state of internal storage of contracts on the chain are stored forever and are easy to query. -Inputs to transactions are even visible before those transactions are accepted. This can lead to frontrunning by a 3rd party who has access to the pool of transactions and can send a transaction (with higher gas) that benefits from the known transaction running after it. \ No newline at end of file +Inputs to transactions are even visible before those transactions are accepted. This can lead to front-running by a 3rd party who has access to the pool of transactions and can send a transaction (with higher gas) that benefits from the known transaction running after it.