forked from Contrast-Security-OSS/demo-petclinic
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
David Archer
committed
Sep 4, 2020
1 parent
c535d47
commit 177bea1
Showing
18 changed files
with
443 additions
and
1 deletion.
There are no files selected for viewing
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,10 @@ | ||
contrast.jar | ||
terraform.tfstate | ||
terraform.tfstate.backup | ||
.terraform | ||
contrast_security.yaml | ||
.terraform.tfstate.lock.info | ||
node_modules | ||
.idea | ||
package-lock.json | ||
terraform.tfvars |
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,3 @@ | ||
#!/bin/bash | ||
|
||
docker build . -t spring-petclinic:1.5.1 --no-cache |
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,6 @@ | ||
#!/bin/bash | ||
|
||
echo "Please log in using your Docker Hub credentials to update the container image" | ||
docker login | ||
docker tag spring-petclinic:1.5.1 contrastsecuritydemo/spring-petclinic:1.5.1 | ||
docker push contrastsecuritydemo/spring-petclinic:1.5.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,17 @@ | ||
FROM openjdk:8-jre-alpine | ||
RUN mkdir /spring-petclinic | ||
WORKDIR /spring-petclinic | ||
|
||
#Add application | ||
ADD ./spring-petclinic-1.5.1.jar /spring-petclinic/spring-petclinic-1.5.1.jar | ||
|
||
#Add Contrast | ||
RUN mkdir /opt/contrast | ||
RUN apk --no-cache add curl | ||
RUN curl --fail --silent --location "https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.contrastsecurity&a=contrast-agent&v=LATEST" -o /opt/contrast/contrast.jar | ||
|
||
#Enable Contrast | ||
ENV JAVA_TOOL_OPTIONS='-javaagent:/opt/contrast/contrast.jar -Dcontrast.agent.java.standalone_app_name=spring-petclinic' | ||
|
||
EXPOSE 8080 | ||
ENTRYPOINT ["java", "-jar", "spring-petclinic-1.5.1.jar"] |
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,87 @@ | ||
env.terraform_version = '0.12.3' | ||
|
||
pipeline { | ||
agent any | ||
|
||
stages { | ||
stage('dependencies') { | ||
steps { | ||
sh """ | ||
FILE=/usr/bin/terraform | ||
if [ -f "\$FILE" ]; then | ||
echo "\$FILE exists, skipping download" | ||
else | ||
echo "\$FILE does not exist" | ||
cd /tmp | ||
curl -o terraform.zip https://releases.hashicorp.com/terraform/'$terraform_version'/terraform_'$terraform_version'_linux_amd64.zip | ||
unzip -o terraform.zip | ||
sudo mv terraform /usr/bin | ||
rm -rf terraform.zip | ||
fi | ||
""" | ||
script { | ||
withCredentials([file(credentialsId: env.contrast_yaml, variable: 'path')]) { | ||
def contents = readFile(env.path) | ||
writeFile file: 'contrast_security.yaml', text: "$contents" | ||
} | ||
} | ||
sh """ | ||
terraform init | ||
npm i puppeteer | ||
""" | ||
} | ||
} | ||
stage('provision') { | ||
steps { | ||
script { | ||
env.GIT_SHORT_COMMIT = checkout(scm).GIT_COMMIT.take(7) | ||
env.GIT_BRANCH = checkout(scm).GIT_BRANCH | ||
|
||
withCredentials([azureServicePrincipal('ContrastAzureSponsored')]) { | ||
try { | ||
sh """ | ||
export ARM_CLIENT_ID=$AZURE_CLIENT_ID | ||
export ARM_CLIENT_SECRET=$AZURE_CLIENT_SECRET | ||
export ARM_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID | ||
export ARM_TENANT_ID=$AZURE_TENANT_ID | ||
terraform apply -auto-approve -var 'location=$location' -var 'initials=$initials' -var 'environment=qa' -var 'servername=jenkins' -var 'session_metadata="branchName=${env.GIT_BRANCH},buildNumber=${BUILD_NUMBER},commitHash=${env.GIT_SHORT_COMMIT},version=1.5.1"' | ||
""" | ||
} catch (Exception e) { | ||
echo "Terraform refresh failed, deleting state" | ||
sh "rm -rf terraform.tfstate" | ||
currentBuild.result = "FAILURE" | ||
error("Aborting the build.") | ||
} | ||
} | ||
} | ||
} | ||
} | ||
stage('sleeping') { | ||
steps { | ||
sleep 120 | ||
} | ||
} | ||
stage('exercise') { | ||
steps { | ||
timeout(20) { | ||
sh """ | ||
FQDN=\$(terraform output fqdn) | ||
BASEURL=\$FQDN node exercise.js | ||
""" | ||
} | ||
} | ||
} | ||
stage('destroy') { | ||
steps { | ||
withCredentials([azureServicePrincipal('ContrastAzureSponsored')]) { | ||
sh """export ARM_CLIENT_ID=$AZURE_CLIENT_ID | ||
export ARM_CLIENT_SECRET=$AZURE_CLIENT_SECRET | ||
export ARM_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID | ||
export ARM_TENANT_ID=$AZURE_TENANT_ID | ||
terraform destroy -auto-approve""" | ||
} | ||
} | ||
} | ||
} | ||
} |
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 +1,56 @@ | ||
# demo-petclinic | ||
# Spring PetClinic: A deliberately insecure Java web application | ||
|
||
This sample application is based on https://github.com/Contrast-Security-OSS/spring-petclinic | ||
|
||
**Warning**: The computer running this application will be vulnerable to attacks, please take appropriate precautions. | ||
|
||
# Running standalone | ||
|
||
You can run PetClinic locally on any machine with Java 1.8 RE installed. | ||
|
||
1. Place a `contrast_security.yaml` file into the application's root folder. | ||
1. Place a `contrast.jar` into the application's root folder. | ||
1. Run the application using: | ||
```sh | ||
java -javaagent:contrast.jar -Dcontrast.config.path=contrast_security.yaml -Dcontrast.agent.java.standalone_app_name=spring-petclinic -jar spring-petclinic-1.5.1.jar [--server.port=8080] [--server.address=localhost] | ||
``` | ||
1. Browse the application at http://localhost:8080/ | ||
|
||
# Running in Docker | ||
|
||
You can run PetClinic within a Docker container. | ||
|
||
1. Place a `contrast_security.yaml` file into the application's root folder. | ||
1. Build the PetClinic container image using `./1-Build-Docker-Image.sh`. The Contrast agent is added automatically during the Docker build process. | ||
1. Run the container using `docker run -v $PWD/contrast_security.yaml:/etc/contrast/java/contrast_security.yaml -p 8080:8080 spring-petclinic:1.5.1` | ||
1. Browse the application at http://localhost:8080/ | ||
|
||
# Running in Azure (Azure Container Instance): | ||
|
||
## Pre-Requisites | ||
|
||
1. Place a `contrast_security.yaml` file into the application's root folder. | ||
1. Install Terraform from here: https://www.terraform.io/downloads.html. | ||
1. Install PyYAML using `pip install PyYAML`. | ||
1. Install the Azure cli tools using `brew update && brew install azure-cli`. | ||
1. Log into Azure to make sure you cache your credentials using `az login`. | ||
1. Edit the [variables.tf](variables.tf) file (or add a terraform.tfvars) to add your initials, preferred Azure location, app name, server name and environment. | ||
1. Run `terraform init` to download the required plugins. | ||
1. Run `terraform plan` and check the output for errors. | ||
1. Run `terraform apply` to build the infrastructure that you need in Azure, this will output the web address for the application. | ||
1. Run `terraform destroy` when you would like to stop the app service and release the resources. | ||
|
||
# Running automated tests | ||
|
||
There is a test script which you can use to reveal vulnerabilities which requires node and puppeteer. | ||
|
||
1. Install Node, NPM and Chrome. | ||
1. From the app folder run `npm i puppeteer`. | ||
1. Run `BASEURL=https://<your service name>.azurewebsites.net node exercise.js` or `BASEURL=https://<your service name>.azurewebsites.net DEBUG=true node exercise.js` to watch the automated script. | ||
|
||
## Updating the Docker Image | ||
|
||
You can re-build the docker image (used by Terraform) by running two scripts in order: | ||
|
||
* 1-Build-Docker-Image.sh | ||
* 2-Deploy-Docker-Image-To-Docker-Hub.sh |
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,78 @@ | ||
const puppeteer = require('puppeteer'); | ||
|
||
(async () => { | ||
if (!process.env.BASEURL) { | ||
console.log('Please specify a base url. E.g. `BASEURL=http://example.org node exercise.js`'); | ||
} else { | ||
var browser; | ||
|
||
if (process.env.DEBUG) { | ||
browser = await puppeteer.launch({ | ||
headless: false, | ||
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' | ||
}); | ||
} else { | ||
browser = await puppeteer.launch(); | ||
} | ||
|
||
const sqliPayload = "D' OR '1%'='1" | ||
|
||
//home page | ||
|
||
console.log('visiting home page') | ||
const page = await browser.newPage() | ||
await page.goto(process.env.BASEURL) | ||
await page.waitFor(2000) | ||
|
||
//exercising sqli vulnerability | ||
console.log('exercising sqli vulnerability') | ||
const page2 = await browser.newPage() | ||
await page2.goto(process.env.BASEURL + '/owners/find') | ||
await page2.waitFor(2000) | ||
await page2.focus('#lastName.form-control') | ||
await page2.keyboard.type('Davis'); | ||
await page2.waitFor(2000) | ||
await page2.click('button.btn.btn-default') | ||
await page2.waitFor(2000) | ||
|
||
//attacking sqli vulnerability | ||
|
||
console.log('attacking sqli vulnerability') | ||
const page3 = await browser.newPage() | ||
await page3.goto(process.env.BASEURL + '/owners/find') | ||
await page3.waitFor(2000) | ||
await page3.focus('#lastName.form-control') | ||
await page3.keyboard.type(sqliPayload); | ||
await page3.waitFor(2000) | ||
await page3.click('button.btn.btn-default') | ||
await page3.waitFor(2000) | ||
|
||
//vets | ||
console.log('visiting vets') | ||
const page4 = await browser.newPage() | ||
await page4.goto(process.env.BASEURL + '/vets.html') | ||
await page4.waitFor(2000) | ||
|
||
//owners | ||
console.log('visiting owners') | ||
const page5 = await browser.newPage() | ||
await page5.goto(process.env.BASEURL + '/owners') | ||
await page5.waitFor(2000) | ||
|
||
// edit owner | ||
|
||
console.log('editing an owner') | ||
const page6 = await browser.newPage() | ||
await page6.goto(process.env.BASEURL + '/owners/1/edit') | ||
await page6.waitFor(2000) | ||
await page6.evaluate( () => document.getElementById("firstName").value = "David") | ||
await page6.waitFor(2000) | ||
await page6.click('button.btn.btn-default') | ||
await page6.waitFor(2000) | ||
|
||
|
||
|
||
browser.close() | ||
console.log('End') | ||
} | ||
})() |
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,40 @@ | ||
#Terraform `provider` section is required since the `azurerm` provider update to 2.0+ | ||
provider "azurerm" { | ||
features {} | ||
} | ||
|
||
#Extract the connection from the normal yaml file to pass to the app container | ||
data "external" "yaml" { | ||
program = [var.python_binary, "${path.module}/parseyaml.py"] | ||
} | ||
|
||
#Set up a personal resource group for the SE local to them | ||
resource "azurerm_resource_group" "personal" { | ||
name = "Sales-Engineer-${var.initials}" | ||
location = var.location | ||
} | ||
|
||
#Set up a container group | ||
resource "azurerm_container_group" "app" { | ||
name = "${var.appname}-${var.initials}" | ||
location = azurerm_resource_group.personal.location | ||
resource_group_name = azurerm_resource_group.personal.name | ||
ip_address_type = "public" | ||
dns_name_label = "${replace(var.appname, "/[^-0-9a-zA-Z]/", "-")}-${var.initials}" | ||
os_type = "linux" | ||
|
||
container { | ||
name = "web" | ||
image = "contrastsecuritydemo/spring-petclinic:1.5.1" | ||
cpu = "1" | ||
memory = "1.5" | ||
ports { | ||
port = 8080 | ||
protocol = "TCP" | ||
} | ||
environment_variables = { | ||
JAVA_TOOL_OPTIONS = "-javaagent:/opt/contrast/contrast.jar -Dcontrast.agent.java.standalone_app_name=spring-petclinic -Dcontrast.api.url=${data.external.yaml.result.url} -Dcontrast.api.api_key=${data.external.yaml.result.api_key} -Dcontrast.api.service_key=${data.external.yaml.result.service_key} -Dcontrast.api.user_name=${data.external.yaml.result.user_name} -Dcontrast.standalone.appname=${var.appname} -Dcontrast.server.name=${var.servername} -Dcontrast.server.environment=${var.environment} -Dcontrast.application.session_metadata=${var.session_metadata} -Dcontrast.application.tags=${var.apptags} -Dcontrast.server.tags=${var.servertags}" | ||
} | ||
} | ||
} | ||
|
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,13 @@ | ||
output "ip_address" { | ||
value = azurerm_container_group.app.ip_address | ||
} | ||
|
||
#the dns fqdn of the container group if dns_name_label is set | ||
output "fqdn" { | ||
value = "http://${azurerm_container_group.app.fqdn}:8080" | ||
} | ||
|
||
output "contrast" { | ||
value = "This app should appear in the environment ${data.external.yaml.result.url}" | ||
} | ||
|
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 @@ | ||
import yaml, json | ||
with open('./contrast_security.yaml') as f: | ||
config = yaml.load(f) | ||
print(json.dumps(config['api'])) |
Binary file not shown.
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,29 @@ | ||
#Terraform `provider` section is required since the `azurerm` provider update to 2.0+ | ||
provider "azurerm" { | ||
features {} | ||
} | ||
|
||
# Configure the Docker provider | ||
provider "docker" { | ||
host = "unix:///var/run/docker.sock" | ||
} | ||
|
||
data "external" "yaml" { | ||
program = [var.python_binary, "${path.module}/parseyaml.py"] | ||
} | ||
|
||
# Create a container | ||
resource "docker_container" "spring-petclinic" { | ||
image = "contrastsecuritydemo/spring-petclinic:1.5.1" | ||
name = "spring-petclinic" | ||
|
||
ports { | ||
internal = 8080 | ||
external = 8081 | ||
} | ||
|
||
env = [ | ||
"JAVA_TOOL_OPTIONS=-Dcontrast.api.url=${data.external.yaml.result.url} -Dcontrast.api.api_key=${data.external.yaml.result.api_key} -Dcontrast.api.service_key=${data.external.yaml.result.service_key} -Dcontrast.api.user_name=${data.external.yaml.result.user_name} -Dcontrast.standalone.appname=${var.appname} -Dcontrast.server.name=${var.servername} -Dcontrast.server.environment=${var.environment} -Dcontrast.application.session_metadata=${var.session_metadata} -Dcontrast.application.tags=${var.apptags} -Dcontrast.server.tags=${var.servertags}" | ||
] | ||
} | ||
|
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 @@ | ||
#the dns fqdn of the container group if dns_name_label is set | ||
output "fqdn" { | ||
value = "http://localhost:8081/" | ||
} | ||
|
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 @@ | ||
import yaml, json | ||
with open('./contrast_security.yaml') as f: | ||
config = yaml.load(f) | ||
print(json.dumps(config['api'])) |
Oops, something went wrong.