Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Challenge X: nexus credentials as part of a project pushed (#810) #1046

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions maven/settings/settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<settings>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
Comment on lines +16 to +25

Check failure

Code scanning / CodeQL

Failure to use HTTPS or SFTP URL in Maven artifact upload/download High

Downloading or uploading artifacts over insecure protocol (eg. http or ftp) to/from repository http://central
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
Comment on lines +28 to +37

Check failure

Code scanning / CodeQL

Failure to use HTTPS or SFTP URL in Maven artifact upload/download High

Downloading or uploading artifacts over insecure protocol (eg. http or ftp) to/from repository http://central
</pluginRepositories>
</profile>
</profiles>
<pluginGroups>
<pluginGroup>org.owsap.plugins</pluginGroup>
</pluginGroups>
<servers>
<server>
<id>nexus</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
</settings>
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@
<artifactId>spotbugs-annotations</artifactId>
<version>4.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-configuration2</artifactId>
<version>2.7</version>
<!-- Replace with the latest version available -->
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.h2database</groupId>-->
<!-- <artifactId>h2</artifactId>-->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.owasp.wrongsecrets.challenges.docker;

import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.configuration2.XMLConfiguration;
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.core.io.Resource;
import org.springframework.stereotype.Component;

/**
* This is a challenge based on leaking secrets due to keeping the encryption key and secret
* together
*/
@Slf4j
@Component
@Order(42)
public class Challenge42 extends Challenge {

private final Resource resource;

public Challenge42(
ScoreCard scoreCard, @Value("classpath:maven/settings/settings.xml") Resource resource) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This resource does not exist (see below), can you instead have a look at the code of Challenge12.java? here you can see how a file is loaded either from test resources or from a filepath within a docker container or from the resources.

super(scoreCard);
this.resource = resource;
}

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

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

@Override
public boolean answerCorrect(String answer) {
return getSolution().equals(answer);
}

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

/** {@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);
}

private String getSolution() {
try {
String config = resource.getContentAsString(Charset.defaultCharset());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am getting

java.io.FileNotFoundException: class path resource [maven/settings/settings.xml] cannot be opened because it does not exist
	at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:211) ~[spring-core-6.0.12.jar:6.0.12]
	at org.springframework.core.io.Resource.getContentAsString(Resource.java:165) ~[spring-core-6.0.12.jar:6.0.12]

StringReader stringReader = new StringReader(config);

XMLConfiguration xmlConfiguration = new XMLConfiguration();
xmlConfiguration.read(stringReader);

// Retrieve the Nexus password
return xmlConfiguration.getString("nexus.password");
Comment on lines +76 to +82
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this gives quite a few different exceptions. Can we do it with the jdk based parser?

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        Document doc = dBuilder.parse(Paths.get(filepath "settings.xml").toFile());
        doc.getDocumentElement().normalize();
        return doc.getDocumentElement().getElementsByTagName("servers").item(0).getChildNodes().item(0).getNextSibling().getChildNodes().item(4).getNextSibling().getTextContent();

or something among these lines. And can you remove the entry from the pom.xml ?

} catch (Exception e) {
log.warn("there was an exception with decrypting content in challenge42", e);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.warn("there was an exception with decrypting content in challenge42", e);
log.warn("there was an exception with retrieving and parsing the xml content for challenge42", e);

return "error_decryption";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return "error_decryption";
return "error_parsing";

}
}
}
3 changes: 3 additions & 0 deletions src/main/resources/explanations/challenge42.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
=== Nexus credential read

Storing nexus deployment credentials in your github project hardcoded is generally considered a bad practice because it undermines the security provided by encryption.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Storing nexus deployment credentials in your github project hardcoded is generally considered a bad practice because it undermines the security provided by encryption.
A developer wanted to configure his Nexus credentials and copy-pasted the configuration from the internal Confluence documentation site, while accidentally committing it to git!
Can you find the password?

10 changes: 10 additions & 0 deletions src/main/resources/explanations/challenge42_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
This challenge can be solved by decrypting the base64 encoded secret in `secrchallenge.json`. You can do this either by:

1. Using an online aes decryption tool like https://www.devglan.com/online-tools/aes-encryption-decryption[https://www.devglan.com/online-tools/aes-encryption-decryption]
- Copy the value of `secret` from `secrchallenge.json` and paste it into the textbox of the decryptor.
- Ensure the input format is `Base64` and the cipher mode is `ECB`.
- Use the value of `key` from `secrchallenge.json` as decryption key and click on `Decrypt` to get the secret.
Comment on lines +3 to +6
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a left-over from challenge41, can you remove this please?


2. Using the terminal
- Launch the terminal while you are in the `maven` directory.
- Copy the value of `password` from `settings.xml`.
7 changes: 7 additions & 0 deletions src/main/resources/explanations/challenge42_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
*Why you should not have nexus deployment credentials in your github project hardcoded*

Storing nexus deployment credentials in your github project hardcoded is generally considered a bad practice because it undermines the security provided by encryption.

In such scenarios, an attacker has the key the moment the file is in his possession.

It is always recommended to store your credentials securely.
Comment on lines +3 to +7
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Storing nexus deployment credentials in your github project hardcoded is generally considered a bad practice because it undermines the security provided by encryption.
In such scenarios, an attacker has the key the moment the file is in his possession.
It is always recommended to store your credentials securely.
Storing the credentials of your artifact registry in your Github project is a bad practice, as others can use these credentials to login, pull, and sometimes push artifacts in the name of the identity user of which the credentials were committed to git.
We often see the situation getting worse by just having one user hardcoded in many configurations of their projects.
Alternatively, we often see the artifact registry credentials hardcoded in the internal documentation site of an organization.
In all cases, we often end up with a compromised user used to inject payloads into the artifact registry.
This is why it is better to have service accounts and/or personal accounts and/or a federated approach for users to the artifact registry. Next, make sure that you never hardcode the credentials: instead: have them configured as part of a secrets management setup.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.owasp.wrongsecrets.challenges.docker;

import static org.mockito.Mockito.when;

import java.io.IOException;
import java.nio.charset.Charset;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
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;
import org.springframework.core.io.Resource;

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

@Mock private Resource resource;

@BeforeEach
void setUp() throws IOException {
when(resource.getContentAsString(Charset.defaultCharset()))
.thenReturn(
"<root><nexus><username>test_user</username><password>test_password</password></nexus></root>");
}

@Test
void spoilerShouldGiveAnswer() {
var challenge = new Challenge42(scoreCard, resource);
Assertions.assertThat(challenge.spoiler().solution()).isNotEmpty();
Assertions.assertThat(challenge.answerCorrect(challenge.spoiler().solution())).isTrue();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Assertions.assertThat(challenge.answerCorrect(challenge.spoiler().solution())).isTrue();
Assertions.assertThat(challenge.answerCorrect(challenge.spoiler().solution())).isTrue();
Assertions.assertThat(challenge.answerCorrect("error_parsing").isFalse();

}

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