Skip to content

Commit

Permalink
Merge branch 'OWASP:master' into nexus-credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
divyanshuagarwal-23 authored Oct 17, 2023
2 parents 8a22f38 + f9957ad commit 61310cd
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 60 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,7 @@ py_env
tmp/
.env
contributors_file*

##documentation
scripts/sort_contibutors/.env
scripts/sort_contibutors/contributors_file.*
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Want to play the other challenges? Read the instructions on how to set them up b
- [Basic docker exercises](#basic-docker-exercises)
- [Running these on Heroku](#running-these-on-heroku)
- [Running these on Render.io](#running-these-on-renderio)
- [Running these on Railway](#running-these-on-railway)
- [Basic K8s exercise](#basic-k8s-exercise)
- [Minikube based](#minikube-based)
- [k8s based](#k8s-based)
Expand Down Expand Up @@ -134,6 +135,10 @@ Want to deploy yourself with Render? Click the button below:

[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/OWASP/wrongsecrets)

### Running these on Railway
*status: maintained by [alphasec.io](https://github.com/alphasecio)*

If you want to host WrongSecrets on Railway, you can do so by deploying [this one-click template](https://railway.app/new/template/7pnwRj). Railway does not offer an always-free plan anymore, but the free trial is good enough to test-drive this before you decide to upgrade. If you need a step-by-step companion guide, see [this blog post](https://alphasec.io/test-your-secret-management-skills-with-owasp-wrongsecrets/).

## Basic K8s exercise

Expand Down
1 change: 0 additions & 1 deletion scripts/sort_contibutors/contributors_file.html

This file was deleted.

57 changes: 0 additions & 57 deletions scripts/sort_contibutors/contributors_file.md

This file was deleted.

4 changes: 2 additions & 2 deletions scripts/sort_contibutors/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ def print_file(s: str, flag: bool) -> None:

def print_md(user_list: dict, label="") -> str:

string = '{}\n'.format(label)
string = '{}:\n\n'.format(label)
for value in user_list:
string += '- [{} @{}](https://www.github.com/{})\n'.format(value['name'],
value['username'], value['username'])
return string + '\n'
return string + '\n\n'


def print_html(leaders: dict, top_contributors: dict, contributors: dict, testers: dict, special_thanks: dict) -> str:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.owasp.wrongsecrets.challenges.docker;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
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.Difficulty;
import org.owasp.wrongsecrets.challenges.Spoiler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

/** This is a challenge based on finding secret using password shucking */
@Slf4j
@Component
@Order(41)
public class Challenge41 extends Challenge {

private final String password;

public Challenge41(ScoreCard scoreCard, @Value("${challenge41password}") String password) {
super(scoreCard);
this.password = password;
}

@Override
public boolean canRunInCTFMode() {
return true;
}

@Override
public Spoiler spoiler() {
return new Spoiler(base64Decode(password));
}

/** {@inheritDoc} */
@Override
public int difficulty() {
return Difficulty.HARD;
}

/** {@inheritDoc} Cryptography based. */
@Override
public String getTech() {
return ChallengeTechnology.Tech.CRYPTOGRAPHY.id;
}

@Override
public boolean isLimitedWhenOnlineHosted() {
return false;
}

@Override
public List<RuntimeEnvironment.Environment> supportedRuntimeEnvironments() {
return List.of(RuntimeEnvironment.Environment.DOCKER);
}

@Override
public boolean answerCorrect(String answer) {
try {
BCryptPasswordEncoder bcrypt = new BCryptPasswordEncoder();
String hash = bcrypt.encode(hashWithMd5(base64Decode(password)));
String md5Hash = hashWithMd5(answer);
return bcrypt.matches(md5Hash, hash);
} catch (Exception e) {
log.warn("there was an exception with hashing content in challenge41", e);
return false;
}
}

@SuppressFBWarnings(
value = "WEAK_MESSAGE_DIGEST_MD5",
justification = "This is to allow md5 hashing")
private String hashWithMd5(String plainText) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");

byte[] result = md.digest(plainText.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : result) {
hexString.append(String.format("%02x", b));
}
return hexString.toString();
}

private String base64Decode(String base64) {
byte[] decodedBytes = Base64.getDecoder().decode(base64);
return new String(decodedBytes, StandardCharsets.UTF_8);
}
}
1 change: 1 addition & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ challenge15ciphertext=qcyRgfXSh0HUKsW/Xb5LnuWt9DgU8tQJfluR66UDDlmMgVWCGEwk1qxKCi
challenge25ciphertext=dQMhBe8oLxIdGLcxPanDLS++srED/x05P+Ph9PFZKlL2K42vXi7Vtbh3/N90sGT087W7ARURZg==
challenge26ciphertext=gbU5thfgy8nwzF/qc1Pq59PrJzLB+bfAdTOrx969JZx1CKeG4Sq7v1uUpzyCH/Fo8W8ghdBJJrQORw==
challenge27ciphertext=gYPQPfb0TUgWK630tHCWGwwME6IWtPWA51eU0Qpb9H7/lMlZPdLGZWmYE83YmEDmaEvFr2hX
challenge41password=UEBzc3dvcmQxMjM=
management.endpoint.health.probes.enabled=true
management.health.livenessState.enabled=true
management.health.readinessState.enabled=true
Expand Down
20 changes: 20 additions & 0 deletions src/main/resources/executables/db-dumps/db-dump-2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
user_1, $2b$10$AL/XPsWYU0cekug9KxIEBuSWbgaNCjaDWq/w/MBT0l3FEyz1RtaE2
user_2, $2b$10$AL/XPsWYU0cekug9KxIEBu/hlEgW48XTPh7IxKMoUD7MvR5yw5GzS
user_3, $2b$10$AL/XPsWYU0cekug9KxIEBucrOlG1vqF9tT12HHMQO3LsoZfXV4Kwm
user_4, $2b$10$AL/XPsWYU0cekug9KxIEBuzCs0Pf9LkaJr4q3RoQmN4pMfQ4W3f7W
user_5, $2b$10$AL/XPsWYU0cekug9KxIEBub4kocue4NeBWRw13nJY73lfcpj0W9sK
user_6, $2b$10$AL/XPsWYU0cekug9KxIEBueWjLD7koXriGpJubmPHZdgvXr7TXqt2
user_7, $2b$10$AL/XPsWYU0cekug9KxIEBub7GTp65ElqcvyNYn7tiTgfIJDbSIor2
user_8, $2b$10$AL/XPsWYU0cekug9KxIEBuXJmQXySRKIzazcUmQmTdsD6nqGLwjp6
user_9, $2b$10$AL/XPsWYU0cekug9KxIEBuQLvMTuJ3ZEcOQwGFhAAJxZEDurO5nkK
user_10, $2b$10$AL/XPsWYU0cekug9KxIEBuG0lxHNKB1b8/irnbvU.LewlaOCpNsYK
user_11, $2b$10$AL/XPsWYU0cekug9KxIEBuDQnjd2Pq8MrbcnbJWC0eJndpg25AKDS
user_12, $2b$10$AL/XPsWYU0cekug9KxIEBuvZcoNJHxTiiQKxbUhWjOcm9ACoaIFNW
user_13, $2b$10$AL/XPsWYU0cekug9KxIEBuG4wtyDXcqJsGC6EOUELUXV0GHULXZ32
user_14, $2b$10$AL/XPsWYU0cekug9KxIEBu75XkDPcwCMNEp1n1HqVJhtwXIdr/qsS
user_15, $2b$10$AL/XPsWYU0cekug9KxIEBuE5MsvF02vTcs/F/YfgUS/8bsntiNj1S
user_16, $2b$10$AL/XPsWYU0cekug9KxIEBuss9lfL0d0Fo5bwXngStAWpxp.IwSt9q
user_17, $2b$10$AL/XPsWYU0cekug9KxIEBuyQ.QgBukZtpC83AALn/5DhxmqJPDQmW
user_18, $2b$10$AL/XPsWYU0cekug9KxIEBuqD0hv0PWUPIbwKPI7n6s.qRGiOXgHxO
user_19, $2b$10$AL/XPsWYU0cekug9KxIEBubeLb2lU4oRL.eW38bbJsjdL.ddrUJoi
user_20, $2b$10$AL/XPsWYU0cekug9KxIEBueJHMcO2DtodfwSHkzDbL4vrkrerLzk.
20 changes: 20 additions & 0 deletions src/main/resources/executables/db-dumps/db-dump.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
user_1, 9ed98e5c3e9685aa3de82c99009a2ed3
user_2, 6988ec3aba1eaddf2435141bf10487ca
user_3, 056f2914fd9a607d48f5491a53b4deb5
user_4, 04dac8afe0ca501587bad66f6b5ce5ad
user_5, 82080600934821faf0bc59cba79964bc
user_6, 74e37ee1078418fb58433aaf0fdd5a9a
user_7, 5903d9e9a8884c8c04ad16559446735a
user_8, 229979fce5174c17d4645bf8752dae1e
user_9, 67b2bad64c2f7ae974140d1742539665
user_10, ffc150a160d37e92012c196b6af4160d
user_11, 52b14869c15726dda86b87cb93666a74
user_12, 210dc1fd8cb4e4e43cb4961b28fac275
user_13, e60408e9a55027070e3caf0550d2b4df
user_14, 6d6354ece40846bf7fca65dfabd5d9d4
user_15, 231badb19b93e44f47da1bd64a8147f2
user_16, 292903fa88d000b48ebdacd12eaf124e
user_17, af089cedf4fb105aca50a170c2b545de
user_18, aa1cbddbb1667f7227bcfdb25772f85c
user_19, ef4cdd3117793b9fd593d7488409626d
user_20, c5aa3124b1adad080927ce4d144c6b33
13 changes: 13 additions & 0 deletions src/main/resources/explanations/challenge41.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=== Password Shucking

A website was using https://en.wikipedia.org/wiki/MD5[MD5] for hashing passwords, and its developers recently found out that someone released a dump of their user data.

In an attempt to improve security, they decided to migrate to a stronger hashing algorithm like https://en.wikipedia.org/wiki/Bcrypt[bcrypt].

The developers decided that the fastest way to migrate would be to hash the pre-existing hashes using bcrypt. Using two hashing algorithms would be more secure than using one, right? It appears so.

Unfortunately, a data leak occurred again and this time the dump contained the bcrypt hashed passwords. At least, this time they are safe right?

For this challenge, you are provided with two database dumps containing usernames and passwords. The dump file https://github.com/OWASP/wrongsecrets/tree/master/src/main/resources/executables/db-dumps/db-dump.txt[db-dump.txt] was generated before the migration and the other dump file https://github.com/OWASP/wrongsecrets/tree/master/src/main/resources/executables/db-dumps/db-dump-2.txt[db-dump-2.txt] was generated after the migration. Both dump files are available inside the https://github.com/OWASP/wrongsecrets/tree/master/src/main/resources/executables/db-dumps[db-dumps folder].

Now, assuming that all the users except one have changed their passwords, can you find the unchanged password?
9 changes: 9 additions & 0 deletions src/main/resources/explanations/challenge41_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This challenge can be solved using the following steps:

1. Create two txt files `old_hashes.txt` and `new_hashes.txt` containing only the hashes copied from the dump files.
2. Using `old_hashes.txt` as password list we can use hashcat to check md5 hashes that match with the bcrypt hashes.
- Install https://hashcat.net/hashcat/[Hashcat]
- Type in `hashcat -m 3200 -a 0 new_hashes.txt old_hashes.txt --show`. You will find a single bcrypt hash mapped to a md5 hash.
3. Using `rockyou.txt` as password list we can crack the obtained md5 hash.
- Download the https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt[rockyou.txt password list]
- Type in `hashcat -m 0 -a 0 82080600934821faf0bc59cba79964bc rockyou.txt --show` to find the cracked password.
9 changes: 9 additions & 0 deletions src/main/resources/explanations/challenge41_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*Why pre-hashing passwords is not a good idea?*

Though pre-hashing passwords is an easy way to upgrade legacy hashes, it becomes prone to https://www.scottbrady91.com/authentication/beware-of-password-shucking[Password shucking].

It is a technique in which the attackers strip off the newer secure layers of an updated hash reducing it into its weak older counterpart. In this case, we were able to reduce bcrypt hashes to insecure md5 hashes and then crack it.

The safest way to avoid this is to reset the passwords of all users and hash the new passwords with the newer algorithm. But, this method is not user-friendly.

The best way to upgrade is by layering the hashes initially and replacing with direct hashes of the users' passwords next time they logs in.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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.junit.jupiter.MockitoExtension;
import org.owasp.wrongsecrets.ScoreCard;

@ExtendWith(MockitoExtension.class)
class Challenge41Test {
@Mock private ScoreCard scoreCard;

@Test
void spoilerShouldGiveAnswer() {
var challenge = new Challenge41(scoreCard, "dGVzdA==");
Assertions.assertThat(challenge.spoiler().solution()).isEqualTo("test");
}

@Test
void rightAnswerShouldSolveChallenge() {
var challenge = new Challenge18(scoreCard, "dGVzdA==");
Assertions.assertThat(challenge.solved("test")).isTrue();
}

@Test
void incorrectAnswerShouldNotSolveChallenge() {
var challenge = new Challenge41(scoreCard, "dGVzdA==");
Assertions.assertThat(challenge.answerCorrect("wrong answer")).isFalse();
}
}

0 comments on commit 61310cd

Please sign in to comment.