-
-
Notifications
You must be signed in to change notification settings - Fork 372
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #432 from commjoen/challenge2627
Challenge 26 & 27
- Loading branch information
Showing
12 changed files
with
272 additions
and
13 deletions.
There are no files selected for viewing
82 changes: 82 additions & 0 deletions
82
src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge26.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<RuntimeEnvironment.Environment> 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 ""; | ||
} | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge27.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<RuntimeEnvironment.Environment> 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 ""; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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/${<your-infura-key>} \ | ||
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/${<your-infura-key>} \ | ||
-X POST \ | ||
-H "Content-Type: application/json" \ | ||
-d '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x8b72f7cbAD50620c46219ad676Ad9d3a5A273587", "0x0", "latest"], "id": 1}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
You can find the previous state one of two ways. | ||
|
||
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}' | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
You can find the correct input to the guess method by: | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 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. |
26 changes: 26 additions & 0 deletions
26
src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge26Test.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 Challenge26Test { | ||
|
||
@Mock | ||
private ScoreCard scoreCard; | ||
|
||
@Test | ||
void rightAnswerShouldSolveChallenge() { | ||
var challenge = new Challenge26(scoreCard, "gbU5thfgy8nwzF/qc1Pq59PrJzLB+bfAdTOrx969JZx1CKeG4Sq7v1uUpzyCH/Fo8W8ghdBJJrQORw=="); | ||
Assertions.assertThat(challenge.solved(challenge.spoiler().solution())).isTrue(); | ||
Mockito.verify(scoreCard).completeChallenge(challenge); | ||
} | ||
|
||
|
||
|
||
} |
26 changes: 26 additions & 0 deletions
26
src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge27Test.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
|
||
|
||
|
||
} |