diff --git a/.travis.yml b/.travis.yml index ddd8e62dc..6a7c00b22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,7 +42,7 @@ addons: project: name: "WebGoat/WebGoat" description: "Coverity Scan from Travis CI Build Automation" - notification_email: doug.morato@owasp.org + notification_email: webgoat@owasp.org build_command_prepend: "mvn clean" build_command: "mvn -DskipTests=true package" branch_pattern: coverity_scan diff --git a/README.MD b/README.MD index ad25e4478..3a5d469b3 100644 --- a/README.MD +++ b/README.MD @@ -1,7 +1,7 @@ # WebGoat: A deliberately insecure Web Application [![Build Status](https://travis-ci.org/WebGoat/WebGoat.svg?branch=develop)](https://travis-ci.org/WebGoat/WebGoat) -[![Coverage Status](https://coveralls.io/repos/WebGoat/WebGoat/badge.svg?branch=master&service=github)](https://coveralls.io/github/WebGoat/WebGoat?branch=master) +[![Coverage Status](https://coveralls.io/repos/WebGoat/WebGoat/badge.svg?branch=develop&service=github)](https://coveralls.io/github/WebGoat/WebGoat?branch=master) [![Codacy Badge](https://api.codacy.com/project/badge/b69ee3a86e3b4afcaf993f210fccfb1d)](https://www.codacy.com/app/dm/WebGoat) [![Dependency Status](https://www.versioneye.com/user/projects/562da95ae346d7000e0369aa/badge.svg?style=flat)](https://www.versioneye.com/user/projects/562da95ae346d7000e0369aa) [![OWASP Labs](https://img.shields.io/badge/owasp-labs-orange.svg)](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Labs_Projects) @@ -22,7 +22,7 @@ penetration testing techniques. **WARNING 1:** *While running this program your machine will be extremely vulnerable to attack. You should disconnect from the Internet while using -this program.* WebGoat's default configuration binds to localhost to minimize +this program.* WebGoat's default configuration binds to localhost to minimize the exposure. **WARNING 2:** *This program is for educational purposes only. If you attempt @@ -33,7 +33,7 @@ first thing that all hackers claim.* # Run Instructions: -## 1. Run using Docker +## 1. Run using Docker From time to time we publish a new development preview of WebGoat 8 on Docker HUB, you can download this version [https://hub.docker.com/r/webgoat/webgoat-8.0/](https://hub.docker.com/r/webgoat/webgoat-8.0/). @@ -44,8 +44,21 @@ docker pull webgoat/webgoat-8.0 docker run -p 8080:8080 webgoat/webgoat-8.0 ``` -Wait for the Docker container to start and go to step 3. -Please note: this version may not be completely in sync with the develop branch. +Wait for the Docker container to start, and run `docker ps` to verify it's running. + +- If you are using `docker-machine`, verify the machine IP using `docker-machine env` +- If you are using `boot2docker` on OSX, verify the IP by running `docker network inspect bridge` +- Otherwise, the host will be bound to localhost + +Once you have the IP and port, you'll want to navigate to the `/WebGoat` path in the URL. For example: + +``` +http://192.168.99.100:8080/WebGoat +``` + +Here you'll be able to register a new user and get started. + +_Please note: this version may not be completely in sync with the develop branch._ ## 2. Run from the sources @@ -108,7 +121,7 @@ docker push webgoat/webgoat-8.0 ``` ### Docker on ARM (Raspberry Pi) -On a Raspberry Pi (it has yet been tested with a Raspberry Pi 3 and the hypriot Docker image) you need to build JFFI for +On a Raspberry Pi (it has yet been tested with a Raspberry Pi 3 and the hypriot Docker image) you need to build JFFI for ARM first. This is needed by the docker-maven-plugin ([see here](https://github.com/spotify/docker-maven-plugin/issues/233)): ```Shell @@ -121,7 +134,7 @@ sudo cp libjffi-1.2.so /usr/lib ``` When you have done this you can build the Docker container using the following commands: - + ```Shell cd WebGoat/ mvn install @@ -131,12 +144,3 @@ docker tag webgoat/webgoat-8.0 webgoat/webgoat-8.0:8.0 docker login docker push webgoat/webgoat-8.0 ``` - -With the following command you are able to run the Docker container on your local machine: - -```Shell -docker run -p 8080:8080 -t webgoat/webgoat-8.0 -docker ps -``` - -With the last command you are able to determine ip address to connect to. diff --git a/buildspec.yml b/buildspec.yml new file mode 100644 index 000000000..477440e02 --- /dev/null +++ b/buildspec.yml @@ -0,0 +1,12 @@ +version: 0.1 + +phases: + build: + commands: + - mvn package + +artifacts: + files: + - webgoat-server/target/webgoat-server-8.0-SNAPSHOT.jar + discard-paths: yes + diff --git a/platformQuickStarts/AWS/README.md b/platformQuickStarts/AWS/README.md new file mode 100644 index 000000000..762bdda12 --- /dev/null +++ b/platformQuickStarts/AWS/README.md @@ -0,0 +1,31 @@ +# AWS + +- This contains the various platform Quick Starts for Getting WebGoat Deployed into AWS. +- This IaaS quickstart uses AWS CloudFormation to perform most of the provisioning +- This IaaS quickstart is composed of three independent bundles + - Code pipeline and Build + - Deploying to EC2 + - Deploying to ECS + + +It is Assumed: +- You have an AWS Account +- You know what an S3 bucket is +- You have seen the IAM console and have permissions to create IAM Roles + + + + +## Code Pipeline and Build + +This Quickstart is for those that just want to perform builds with AWS. It Triggers off of Github to perform builds of `webgoat-server` + + + +## EC2 + +(WIP) This uses AWS CodePipeline, CodeBuild, and CodeDeploy to land WebGoat to Running EC2 instances + +## ECS + +(WIP) This uses AWS CodePipeline, CodeBuild, ECR, to land a container onto an ECS cluster \ No newline at end of file diff --git a/platformQuickStarts/AWS/codepipelinebuild/01_IAM_codebuild.json b/platformQuickStarts/AWS/codepipelinebuild/01_IAM_codebuild.json new file mode 100644 index 000000000..2fbf17f5a --- /dev/null +++ b/platformQuickStarts/AWS/codepipelinebuild/01_IAM_codebuild.json @@ -0,0 +1,101 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "IAM Roles for Code Build WebGoat IaaS Quickstart", + "Parameters": { + "qsS3BucketName": { + "Description": "Name of the S3 Bucket for artifacts", + "Type": "String", + "MinLength": "1" + }, + "qsRoleName": { + "Description": "Name of the IAM role that CodeBuild Will Use", + "Type": "String", + "Default": "SimpleCodeBuildRole", + "MinLength": "1" + } + }, + "Resources": { + "qsCodeBuildRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": [ + "codebuild.amazonaws.com" + ] + }, + "Action": [ + "sts:AssumeRole" + ] + } + ] + }, + "Path": "/webgoat/", + "RoleName": { + "Ref": "qsRoleName" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/AWSCodeCommitFullAccess", + "arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess", + "arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess" + ], + "Policies": [ + { + "PolicyName": "CloudWatchLogs", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + {"Fn::Join": [ "",["arn:aws:logs:*:", { "Ref": "AWS::AccountId" }, ":log-group:/aws/codebuild*" ] ]} + ], + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + } + ] + } + }, + { + "PolicyName": "S3buckets", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "qsS3BucketName" + }, + "*" + ] + ] + }, + "arn:aws:s3:::codepipeline-*" + ], + "Action": [ + "s3:Put*", + "s3:Get*", + "s3:List*" + ] + } + ] + } + } + ] + } + } + } +} diff --git a/platformQuickStarts/AWS/codepipelinebuild/01_IAM_codepipeline.json b/platformQuickStarts/AWS/codepipelinebuild/01_IAM_codepipeline.json new file mode 100644 index 000000000..58fd9f1f4 --- /dev/null +++ b/platformQuickStarts/AWS/codepipelinebuild/01_IAM_codepipeline.json @@ -0,0 +1,127 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "IAM Role for Code Pipeline WebGoat IaaS Quickstart", + "Parameters": { + "qsS3BucketName": { + "Description": "Name of the S3 Bucket for artifacts", + "Type": "String", + "MinLength": "1" + }, + "qsRoleName": { + "Description": "Name of the IAM role that CodePipeline Will Use", + "Type": "String", + "Default": "SimpleCodePipelineRole", + "MinLength": "1" + } + }, + "Resources": { + "qsCodePipelineRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + }, + "Path": "/webgoat/", + "RoleName": { + "Ref": "qsRoleName" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/AWSCodeCommitFullAccess", + "arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess", + "arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess" + ], + "Policies": [ + { + "PolicyName": "CloudWatchLogsPipeline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + {"Fn::Join": [ "",["arn:aws:logs:*:", { "Ref": "AWS::AccountId" }, ":log-group:/aws/*" ] ]} + ], + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + } + ] + } + }, + { + "PolicyName": "MiscComputeOpen", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": "*", + "Action": [ + "lambda:InvokeFunction", + "lambda:ListFunctions", + "elasticbeanstalk:*", + "ec2:*", + "elasticloadbalancing:*", + "autoscaling:*", + "cloudwatch:*", + "s3:*", + "sns:*", + "cloudformation:*", + "rds:*", + "sqs:*", + "ecs:*", + "iam:PassRole" + ] + } + ] + } + }, + { + "PolicyName": "S3buckets", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "qsS3BucketName" + }, + "*" + ] + ] + }, + "arn:aws:s3:::codepipeline-*", + "arn:aws:s3:::elasticbeanstalk*" + ], + "Action": [ + "s3:Put*", + "s3:Get*", + "s3:List*" + ] + } + ] + } + } + ] + } + } + } +} diff --git a/platformQuickStarts/AWS/codepipelinebuild/01_codepiplinebuild.yml b/platformQuickStarts/AWS/codepipelinebuild/01_codepiplinebuild.yml new file mode 100644 index 000000000..8aac7af2a --- /dev/null +++ b/platformQuickStarts/AWS/codepipelinebuild/01_codepiplinebuild.yml @@ -0,0 +1,123 @@ +AWSTemplateFormatVersion: "2010-09-09" + +Description: > + AWS Cloud Formation for creating an AWS CodePipeline that checks a git repo for changes and then performs a build using code build + + +Parameters: + qsPipelineName: + Description: The name of the AWS Code Pipeline + Type: String + Default: WG-pipeline + MinLength: 1 + qsPipelineRoleARN: + Description: The complete ARN to the IAM role that code pipeline should use + Type: String + MinLength: 1 + qsCodeRepo: + Description: The Repository + Type: String + MinLength: 1 + qsRepoBranch: + Description: The Branch in the Repository + Type: String + MinLength: 1 + qsGitHubUser: + Description: The GitHub User Id + Type: String + MinLength: 1 + qsGitHubAPIToken: + Description: The GitHub Personal Access token do not use password + NoEcho: true + Type: String + MinLength: 1 + qsS3PipelineArtifacts: + Description: Where Code Pipeline will state artifacts in S3 + Type: String + MinLength: 1 + qsS3CodeBuildArtifacts: + Description: Where Code Build will upload Artifacts can be same as codepipeline + Type: String + MinLength: 1 + qsCodeBuildName: + Description: Name of the AWS Code Build + Type: String + Default: WG-mvnBuilder + MinLength: 1 + qsKMSKeyARN: + Description: The KMS ARN that the IAM Role is allowed to use + Type: String + MinLength: 1 + qsCodeRoleArn: + Description: The IAM Role ARN for CodePipeline and CodeDeploy + Type: String + MinLength: 1 + + + +Resources: + + + + + stkcbrCodeBuild: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Description: Builds WebGoat Jar using build file in repo + EncryptionKey: !Ref 'qsKMSKeyARN' + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/java:openjdk-8 + Type: LINUX_CONTAINER + Name: !Ref 'qsCodeBuildName' + ServiceRole: !Ref 'qsCodeRoleArn' + TimeoutInMinutes: 10 + Source: + Type: CODEPIPELINE + + + + stkcplPipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + Name: !Ref 'qsPipelineName' + RoleArn: !Ref 'qsPipelineRoleARN' + ArtifactStore: + Location: !Ref 'qsS3PipelineArtifacts' + Type: S3 + Stages: + - Name: CodeRepo + Actions: + - Name: CodeSource + ActionTypeId: + Category: Source + Owner: ThirdParty + Provider: GitHub + Version: 1 + Configuration: + Branch: !Ref 'qsRepoBranch' + Repo: !Ref 'qsCodeRepo' + Owner: !Ref 'qsGitHubUser' + OAuthToken: !Ref 'qsGitHubAPIToken' + OutputArtifacts: + - Name: MySource + RunOrder: '1' + - Name: Build + Actions: + - Name: CodeBuild + ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: 1 + InputArtifacts: + - Name: MySource + Configuration: + ProjectName: !Ref stkcbrCodeBuild + OutputArtifacts: + - Name: MyBuild + RunOrder: '2' + + diff --git a/platformQuickStarts/AWS/codepipelinebuild/README.md b/platformQuickStarts/AWS/codepipelinebuild/README.md new file mode 100644 index 000000000..e8aea2d06 --- /dev/null +++ b/platformQuickStarts/AWS/codepipelinebuild/README.md @@ -0,0 +1,64 @@ +# Serverless MVN builds Featuring AWS + +This Quick Start forms the basis for the other AWS quickstarts. This only BUILDS the `webgoat-server` spring boot jar. If you want to also run it on AWS skip to the other AWS quickstarts + +Before you Begin +1. Do you have an AWS Account? +2. Can you create an S3 Bucket? +3. Can you create a KMS Key? +4. Do you know what Cloud Formation is? +5. Do you have enough permissions to do any real work in said AWS Account? + +If you said no to any of those...hop over to [docs](https://aws.amazon.com/documentation/) and learn (but don't do) how to create those. + + +You will also need: +1. A GitHub Account +2. Fork of WebGoat +3. Personal access Token with `Admin:repo_hook` and `repo` + + + +## Create Pre-requisites + +First pick an AWS region and stick with it for ALL the quickstarts. This one was mostly executed on US-east-1/2 but any region with KMS, CodePipeline, and CodeBuild will work. eu-Central-1, ap-southeast-1 and sa-east-1 have reported success also. + + +1. Create an S3 bucket and call it something meaningfull like `webgoat-stash-username` or something or use an existing bucket you have access to. +2. Create a KMS Key. Make sure you are a key administrator so you can add key users later. + +## Deploy IAM role Cloud Formation Stacks + +In this folder there are two json cloudformation templates: +-`01_IAM_codebuild.json` +-`01_IAM_codepipeline.json` + +You will use the CloudFormation templates to create two roles. One for CodePipeline and the Other for CodeBuild. You will use the name of the bucket you just created as a parameter. + +## Update KMS Key + +Access the KMS key you created earlier...add the two IAM roles you just created and Key Users + +## Finally the Pipeline + +You will use the yaml cloudformation template `01_codepiplinebuild.yml` to create the code building pipeline. + +Some of the parameters you will need to pass: +1. The S3 bucket (twice) +2. The Github Branch name (master? develop? yourbranchname?) +3. The Github user (if you forked it would be your username) +4. You personal access token for GitHub +5. The name or the repo (WebGoat! ...unless you renamed and did a whole bunch of fancy git magic) +6. The ARN of the KMS key +7. The ARN of the role for the codebuild for parameter qsCodeRoleArn +8. The ARN for codepipeline + +If this Stack successfully deploys a build will begin based on the latest commit automatically. You will have a funky named zip file (without the .zip ending) in a folder in the S3 bucket in a few minutes. + + + +Congratulations. You just Deployed a two step AWS Codepipeline that looks for codechanges and then performs a build. + +... ON to the next AWS Quickstart + + diff --git a/platformQuickStarts/GCP/GKE-Docker/README.md b/platformQuickStarts/GCP/GKE-Docker/README.md new file mode 100644 index 000000000..7b18993c1 --- /dev/null +++ b/platformQuickStarts/GCP/GKE-Docker/README.md @@ -0,0 +1,80 @@ +# GKE - DockerHub + +This Quickstart shows how to create a Kubernettes Cluster using Google Cloud Platform's [GKE](https://cloud.google.com/container-engine/) and WebGoat's Docker [Image](https://hub.docker.com/r/webgoat/webgoat-8.0/). + +To be Successfull with this Quickstart + +1. You have a Google Cloud Platform account and have enough access rights to create Compute Engine and Container Engine Resources +2. You know how to `git clone` +3. You have the gcloud SDK install and initialized somewhere ( do not use the google cloud shell) + + +Remeber to perform a 'gcloud auth login' before using the gcloud commands below. + + + +## Create Kubernettes Cluster + +You can create a cluster using the Google Cloud Console. The Default settings will suffice. For this QuickStart the cluster name used is `owaspbasiccluster`. The `PROJECTNAME` is whatever your project is. The `REGION` is a region/zone near you. + +If you want to use the gcloud sdk from a properly initialized gcloud commandline environment use the following command + + +``` +gcloud container --project "PROJECTNAME" clusters create "owaspbasiccluster" --zone "REGION" --machine-type "n1-standard-1" --image-type "COS" --disk-size "100" --scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append","https://www.googleapis.com/auth/source.read_only" --num-nodes "3" --network "default" --enable-cloud-logging --no-enable-cloud-monitoring + + +``` + +The command creates a similar cluster with more of the options set explicitly. + +## Set up Kubectl + +Using the commandline gcloud SDK environment you need to set-up 'kubectl' + +If you have not already installed 'Kubectl' you can do so with the following command using `gcloud` +- `gcloud components install kubectl` + +Then you just run: +- `gcloud container clusters get-credentials owaspbasiccluster --zone REGION --project PROJECTNAME` + + +## Deploy WebGoat Deployment + +Time to deploy the latest DockerImage for WebGoat! + + +Let's First Make a namespace for this: +- `kubectl create namespace webgoat` + +Now it is time to make the magic happen! + +- `kubectl create -f /where_you_git_cloned_webgoat/platformQuickStart/GCP/GKE-Docker/webgoat_noDNSnoTLS.yml` + +This should complete with no errors. + +Use the following command to see information/status about the deployment +- `kubectl describe deployment webgoat-dpl --namespace=webgoat` + +After a few minutes the service endpoint should be ready. You can check the status with +- `kubectl describe service webgoatsvc --namespace=webgoat` + +In the output you should see a message like "Created load..." after a "Creating load..." which means that the public facing loadbalancer (even thou there is just one container running!) is ready. + + +If you want to see the Kubernetes dashboard you can run `kubectl proxy` (in a new terminal window) and then navigate to http://localhost:8001/ui . + + + +## Test Deployment + +From the previous `describe service` command the `LoadBalancer Ingress:` line should have the external IP. The line below should give the port. + +So..... + +[IP]:[PORT]/WebGoat in your browser! + +DONE + + + diff --git a/platformQuickStarts/GCP/GKE-Docker/webgoat_deployment_noDNSnoTLS.yml b/platformQuickStarts/GCP/GKE-Docker/webgoat_deployment_noDNSnoTLS.yml new file mode 100644 index 000000000..228cf29ef --- /dev/null +++ b/platformQuickStarts/GCP/GKE-Docker/webgoat_deployment_noDNSnoTLS.yml @@ -0,0 +1,39 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: webgoatapp + name: webgoatsvc + namespace: webgoat +spec: + ports: + - + port: 8080 + protocol: TCP + selector: + app: webgoatapp + type: LoadBalancer +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: webgoat-dpl + namespace: webgoat +spec: + replicas: 1 + template: + metadata: + name: webgoatapp + labels: + app: webgoatapp + spec: + containers: + - + image: webgoat/webgoat-8.0 + name: webgoat + ports: + - + containerPort: 8080 + + \ No newline at end of file diff --git a/platformQuickStarts/GCP/README.md b/platformQuickStarts/GCP/README.md new file mode 100644 index 000000000..1c4eb30cb --- /dev/null +++ b/platformQuickStarts/GCP/README.md @@ -0,0 +1,17 @@ +# WebGoat on GCP! + +This folder contains sub folders for the various ways you could deploy WebGoat on Google Cloud Platform + +It is assumed: +1. You have a Google Cloud Platform Account +2. You can use Git +3. You can use a Linux/Mac/Google Cloud Shell + + +## GKE Docker + +Uses GKE to run the latest DockerHub version of WebGoat8 + +## AppEngine + +WIP \ No newline at end of file diff --git a/platformQuickStarts/README.md b/platformQuickStarts/README.md new file mode 100644 index 000000000..f647f3273 --- /dev/null +++ b/platformQuickStarts/README.md @@ -0,0 +1,22 @@ +# OWASP WebGoat Platform Quick Starts + +Want to Run WebGoat? Want to run WebGoat in the Cloud? Don't want to be cloud Expert? + +Do we have a solution for you! + + +Additionally, Each IaaS/PaaS will have their deployment steps broken down giving the *app-guy-new-to-cloud* an opportunity to learn how said platform works. + + + +## AWS + +Multi-Part Quickstart. Starts with simple pipeline that just builds code to a deploying onto EC2 instances and then containers using ECS/ECR + +## GCP + +Get WebGoat Running on GKE and AppEngine + + + + diff --git a/pom.xml b/pom.xml index af60fd088..79c12a753 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.5.3.RELEASE diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index f9e4f76ae..d2f86a151 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -242,6 +242,12 @@ ${junit.version} jar + + com.github.fakemongo + fongo + 2.1.0 + test + diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/CleanupLocalProgressFiles.java b/webgoat-container/src/main/java/org/owasp/webgoat/CleanupLocalProgressFiles.java index 9200a8a5a..d0667fd9f 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/CleanupLocalProgressFiles.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/CleanupLocalProgressFiles.java @@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.annotation.Configuration; +import org.springframework.util.FileSystemUtils; import javax.annotation.PostConstruct; import java.io.File; @@ -23,14 +24,10 @@ public class CleanupLocalProgressFiles { @PostConstruct public void clean() { File dir = new File(webgoatHome); - if (dir.exists()) { - File[] progressFiles = dir.listFiles(f -> f.getName().endsWith(".progress")); - if (progressFiles != null) { - log.info("Removing stored user preferences..."); - for (File f : progressFiles) { - f.delete(); - } - } + //do it safe, check whether the subdir mongodb is available as subdirectory + File[] mongoDir = dir.listFiles(f -> f.isDirectory() && f.getName().contains("mongodb")); + if (mongoDir != null && mongoDir.length == 1) { + FileSystemUtils.deleteRecursively(dir); } } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java index 1c949c85e..349904de9 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java @@ -124,6 +124,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter { registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/"); registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/"); registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/"); + registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/"); super.addResourceHandlers(registry); } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java index b10917d49..e78d46338 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java @@ -25,11 +25,10 @@ package org.owasp.webgoat.assignments; -import lombok.AllArgsConstructor; import lombok.Getter; +import org.apache.commons.lang3.StringEscapeUtils; import org.owasp.webgoat.i18n.PluginMessages; -@AllArgsConstructor public class AttackResult { public static class AttackResultBuilder { @@ -89,6 +88,11 @@ public class AttackResult { @Getter private String output; + public AttackResult(boolean lessonCompleted, String feedback, String output) { + this.lessonCompleted = lessonCompleted; + this.feedback = StringEscapeUtils.escapeJson(feedback); + this.output = StringEscapeUtils.escapeJson(output); + } public static AttackResultBuilder builder(PluginMessages messages) { return new AttackResultBuilder(messages); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java index 6af1770f3..28d0524fb 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java @@ -33,7 +33,6 @@ package org.owasp.webgoat.controller; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.WebSession; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; @@ -77,8 +76,8 @@ public class StartLesson { // I will set here the thymeleaf fragment location based on the resource requested. ModelAndView model = new ModelAndView(); SecurityContext context = SecurityContextHolder.getContext(); //TODO this should work with the security roles of Spring - GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next(); - String path = request.getServletPath(); // we now got /a/b/c/AccessControlMatrix.lesson + //GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next(); + String path = request.getRequestURL().toString(); // we now got /a/b/c/AccessControlMatrix.lesson String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson")); List lessons = course.getLessons(); Optional lesson = lessons.stream() diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java index eb200b354..1336fa326 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -1,6 +1,6 @@ package org.owasp.webgoat.lessons; -import lombok.Getter; +import com.google.common.collect.Lists; import lombok.Setter; import org.owasp.webgoat.session.Screen; @@ -44,10 +44,16 @@ public abstract class AbstractLesson extends Screen implements Comparable assignments; + public List getAssignments() { + if (assignments == null) { + return Lists.newArrayList(); + } + return assignments; + } + /** * Constructor for the Lesson object */ diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java index 6c3a5833b..7d47892ab 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java @@ -52,7 +52,7 @@ public enum Category { INSECURE_CONFIGURATION("Insecure Configuration", new Integer(1400)), INSECURE_STORAGE("Insecure Storage", new Integer(1500)), MALICIOUS_EXECUTION("Malicious Execution", new Integer(1600)), - PARAMETER_TAMPERING("Parameter Tampering", new Integer(1700)), + CLIENT_SIDE("Client side", new Integer(1700)), SESSION_MANAGEMENT("Session Management Flaws", new Integer(1800)), WEB_SERVICES("Web Services", new Integer(1900)), VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(1950)), diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java index 4031e0c82..725507cac 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java @@ -7,756 +7,708 @@ import java.sql.Statement; /** - ************************************************************************************************* - * - * + * ************************************************************************************************ + *

+ *

* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * please see http://www.owasp.org/ - * + *

* Copyright (c) 2002 - 20014 Bruce Mayhew - * + *

* This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License along with this program; if * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. - * + *

* Getting Source ============== - * + *

* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software * projects. * * @author Jeff Williams Aspect Security * @version $Id: $Id */ -public class CreateDB -{ - - /** - * Description of the Method - * - * @param connection - * Description of the Parameter - * - * @exception SQLException - * Description of the Exception - */ - private void createMessageTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - - // Drop admin user table - try - { - String dropTable = "DROP TABLE messages"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop message database"); - } - - // Create the new table - try - { - String createTableStatement = "CREATE TABLE messages (" + "num int not null," + "title varchar(50)," - + "message varchar(200)," + "user_name varchar(50) not null, " + "lesson_type varchar(50) not null" - + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating message database " + e.getLocalizedMessage()); - } - } +public class CreateDB { /** * Description of the Method * * @param connection Description of the Parameter - * - * @exception SQLException Description of the Exception + * @throws SQLException Description of the Exception */ - private void createMFEImagesTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - - // Drop mfe_images table - try - { - String dropTable = "DROP TABLE mfe_images"; - statement.executeUpdate(dropTable); - } - catch (SQLException e) - { - System.out.println("Info - Could not drop mfe_images table from database"); - } - - // Create the new mfe_images table - try - { - String createTableStatement = "CREATE TABLE mfe_images (" - + "user_name varchar(50) not null, " - + "image_relative_url varchar(50) not null" - + ")"; - statement.executeUpdate(createTableStatement); - } - catch (SQLException e) - { - System.out.println("Error creating mfe_images table in database " + e.getLocalizedMessage()); - } + private void createServersTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + + // Drop servers table + try { + String dropTable = "DROP TABLE servers"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop servers table"); + } + + // Create the new table + try { + String createTableStatement = "CREATE TABLE servers" + + " (" + "id varchar(10)," + + "hostname varchar(20)," + + "ip varchar(20)," + + "mac varchar(20)," + + "status varchar(20)," + + "description varchar(40)" + + ")"; + statement.executeUpdate(createTableStatement); + + String insertData1 = "INSERT INTO servers VALUES ('1', 'webgoat-dev', '192.168.4.0', 'AA:BB:11:22:CC:DD', 'online', 'Development server')"; + String insertData2 = "INSERT INTO servers VALUES ('2', 'webgoat-tst', '192.168.2.1', 'EE:FF:33:44:AB:CD', 'online', 'Test server')"; + String insertData3 = "INSERT INTO servers VALUES ('3', 'webgoat-acc', '192.168.3.3', 'EF:12:FE:34:AA:CC', 'offline', 'Acceptance server')"; + String insertData4 = "INSERT INTO servers VALUES ('4', 'webgoat-pre-prod', '192.168.6.4', 'EF:12:FE:34:AA:CC', 'offline', 'Pre-production server')"; + String insertData5 = "INSERT INTO servers VALUES ('4', 'webgoat-prd', '104.130.219.202', 'FA:91:EB:82:DC:73', 'out of order', 'Production server')"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); + } catch (SQLException e) { + System.out.println("Error creating product table " + e.getLocalizedMessage()); + } + } + + + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + */ + private void createMessageTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + + // Drop admin user table + try { + String dropTable = "DROP TABLE messages"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop message database"); + } + + // Create the new table + try { + String createTableStatement = "CREATE TABLE messages (" + "num int not null," + "title varchar(50)," + + "message varchar(200)," + "user_name varchar(50) not null, " + "lesson_type varchar(50) not null" + + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating message database " + e.getLocalizedMessage()); + } + } + + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + */ + private void createMFEImagesTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + + // Drop mfe_images table + try { + String dropTable = "DROP TABLE mfe_images"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop mfe_images table from database"); + } + + // Create the new mfe_images table + try { + String createTableStatement = "CREATE TABLE mfe_images (" + + "user_name varchar(50) not null, " + + "image_relative_url varchar(50) not null" + + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating mfe_images table in database " + e.getLocalizedMessage()); + } } - - /** - * Description of the Method - * - * @param connection - * Description of the Parameter - * - * @exception SQLException - * Description of the Exception - */ - private void createProductTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - // Drop admin user table - try - { - String dropTable = "DROP TABLE product_system_data"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop product table"); - } + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + */ + private void createProductTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - // Create the new table - try - { - String createTableStatement = "CREATE TABLE product_system_data (" - + "productid varchar(6) not null primary key," + "product_name varchar(20)," + "price varchar(10)" - + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating product table " + e.getLocalizedMessage()); - } + // Drop admin user table + try { + String dropTable = "DROP TABLE product_system_data"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop product table"); + } - // Populate - String insertData1 = "INSERT INTO product_system_data VALUES ('32226','Dog Bone','$1.99')"; - String insertData2 = "INSERT INTO product_system_data VALUES ('35632','DVD Player','$214.99')"; - String insertData3 = "INSERT INTO product_system_data VALUES ('24569','60 GB Hard Drive','$149.99')"; - String insertData4 = "INSERT INTO product_system_data VALUES ('56970','80 GB Hard Drive','$179.99')"; - String insertData5 = "INSERT INTO product_system_data VALUES ('14365','56 inch HDTV','$6999.99')"; - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - } + // Create the new table + try { + String createTableStatement = "CREATE TABLE product_system_data (" + + "productid varchar(6) not null primary key," + "product_name varchar(20)," + "price varchar(10)" + + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating product table " + e.getLocalizedMessage()); + } - /** - * Description of the Method - * - * @param connection - * Description of the Parameter - * - * @exception SQLException - * Description of the Exception - */ - private void createUserAdminTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - - // Drop admin user table - try - { - String dropTable = "DROP TABLE user_system_data"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop user admin table"); - } - - // Create the new table - try - { - String createTableStatement = "CREATE TABLE user_system_data (" + "userid varchar(5) not null primary key," - + "user_name varchar(12)," + "password varchar(10)," + "cookie varchar(30)" + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating user admin table " + e.getLocalizedMessage()); - } - - // Populate - String insertData1 = "INSERT INTO user_system_data VALUES ('101','jsnow','passwd1', '')"; - String insertData2 = "INSERT INTO user_system_data VALUES ('102','jdoe','passwd2', '')"; - String insertData3 = "INSERT INTO user_system_data VALUES ('103','jplane','passwd3', '')"; - String insertData4 = "INSERT INTO user_system_data VALUES ('104','jeff','jeff', '')"; - String insertData5 = "INSERT INTO user_system_data VALUES ('105','dave','dave', '')"; - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - } - - /** - * Description of the Method - * - * @param connection - * Description of the Parameter - * - * @exception SQLException - * Description of the Exception - */ - private void createUserDataTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - - // Delete table if there is one - try - { - String dropTable = "DROP TABLE user_data"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop user table"); - } - - // Create the new table - try - { - String createTableStatement = "CREATE TABLE user_data (" + "userid int not null," - + "first_name varchar(20)," + "last_name varchar(20)," + "cc_number varchar(30)," - + "cc_type varchar(10)," + "cookie varchar(20)," + "login_count int" + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating user table " + e.getLocalizedMessage()); - } - - // Populate it - String insertData1 = "INSERT INTO user_data VALUES (101,'Joe','Snow','987654321','VISA',' ',0)"; - String insertData2 = "INSERT INTO user_data VALUES (101,'Joe','Snow','2234200065411','MC',' ',0)"; - String insertData3 = "INSERT INTO user_data VALUES (102,'John','Smith','2435600002222','MC',' ',0)"; - String insertData4 = "INSERT INTO user_data VALUES (102,'John','Smith','4352209902222','AMEX',' ',0)"; - String insertData5 = "INSERT INTO user_data VALUES (103,'Jane','Plane','123456789','MC',' ',0)"; - String insertData6 = "INSERT INTO user_data VALUES (103,'Jane','Plane','333498703333','AMEX',' ',0)"; - String insertData7 = "INSERT INTO user_data VALUES (10312,'Jolly','Hershey','176896789','MC',' ',0)"; - String insertData8 = "INSERT INTO user_data VALUES (10312,'Jolly','Hershey','333300003333','AMEX',' ',0)"; - String insertData9 = "INSERT INTO user_data VALUES (10323,'Grumpy','youaretheweakestlink','673834489','MC',' ',0)"; - String insertData10 = "INSERT INTO user_data VALUES (10323,'Grumpy','youaretheweakestlink','33413003333','AMEX',' ',0)"; - String insertData11 = "INSERT INTO user_data VALUES (15603,'Peter','Sand','123609789','MC',' ',0)"; - String insertData12 = "INSERT INTO user_data VALUES (15603,'Peter','Sand','338893453333','AMEX',' ',0)"; - String insertData13 = "INSERT INTO user_data VALUES (15613,'Joesph','Something','33843453533','AMEX',' ',0)"; - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - statement.executeUpdate(insertData6); - statement.executeUpdate(insertData7); - statement.executeUpdate(insertData8); - statement.executeUpdate(insertData9); - statement.executeUpdate(insertData10); - statement.executeUpdate(insertData11); - statement.executeUpdate(insertData12); - statement.executeUpdate(insertData13); - - } - - private void createLoginTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - - // Delete table if there is one - try - { - String dropTable = "DROP TABLE user_login"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop user_login table"); - } - - // Create the new table - try - { - String createTableStatement = "CREATE TABLE user_login (" + "userid varchar(5)," - + "webgoat_user varchar(20)" + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating user_login table " + e.getLocalizedMessage()); - } - - } - - // creates the table pins which is used in the blind sql injection lesson - private void createBlindSQLLessonTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - - // Delete table if there is one - try - { - String dropTable = "DROP TABLE pins"; - statement.executeUpdate(dropTable); - } - catch (SQLException e) - { - System.out.println("Info - Could not drop pins table"); - } - - // Create the new table - try - { - String createTableStatement = "CREATE TABLE pins (" - + "cc_number varchar(30)," - + "pin int," - + "name varchar(20)" - + ")"; - statement.executeUpdate(createTableStatement); - } - catch (SQLException e) - { - System.out.println("Error creating pins table " + e.getLocalizedMessage()); - } - - // Populate it - String insertData1 = "INSERT INTO pins VALUES ('987654321098765', 1234, 'Joe')"; - String insertData2 = "INSERT INTO pins VALUES ('1234567890123456', 4567, 'Jack')"; - String insertData3 = "INSERT INTO pins VALUES ('4321432143214321', 4321, 'Jill')"; - String insertData4 = "INSERT INTO pins VALUES ('1111111111111111', 7777, 'Jim')"; - String insertData5 = "INSERT INTO pins VALUES ('1111222233334444', 2364, 'John')"; - - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - + // Populate + String insertData1 = "INSERT INTO product_system_data VALUES ('32226','Dog Bone','$1.99')"; + String insertData2 = "INSERT INTO product_system_data VALUES ('35632','DVD Player','$214.99')"; + String insertData3 = "INSERT INTO product_system_data VALUES ('24569','60 GB Hard Drive','$149.99')"; + String insertData4 = "INSERT INTO product_system_data VALUES ('56970','80 GB Hard Drive','$179.99')"; + String insertData5 = "INSERT INTO product_system_data VALUES ('14365','56 inch HDTV','$6999.99')"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); } - - // creates the table salaries which is used in the lessons - // which add or modify data using sql injection - private void createModifyWithSQLLessonTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - - // Delete table if there is one - try - { - String dropTable = "DROP TABLE salaries"; - statement.executeUpdate(dropTable); - } - catch (SQLException e) - { - System.out.println("Info - Could not drop salaries table"); - } - - // Create the new table - try - { - String createTableStatement = "CREATE TABLE salaries (" - + "userid varchar(50)," - + "salary int" - + ")"; - statement.executeUpdate(createTableStatement); - } - catch (SQLException e) - { - System.out.println("Error creating salaries table " + e.getLocalizedMessage()); - } - - // Populate it - String insertData1 = "INSERT INTO salaries VALUES ('jsmith', 20000)"; - String insertData2 = "INSERT INTO salaries VALUES ('lsmith', 45000)"; - String insertData3 = "INSERT INTO salaries VALUES ('wgoat', 100000)"; - String insertData4 = "INSERT INTO salaries VALUES ('rjones', 777777)"; - String insertData5 = "INSERT INTO salaries VALUES ('manderson', 65000)"; - - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - + + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + */ + private void createUserAdminTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + + // Drop admin user table + try { + String dropTable = "DROP TABLE user_system_data"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop user admin table"); + } + + // Create the new table + try { + String createTableStatement = "CREATE TABLE user_system_data (" + "userid varchar(5) not null primary key," + + "user_name varchar(12)," + "password varchar(10)," + "cookie varchar(30)" + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating user admin table " + e.getLocalizedMessage()); + } + + // Populate + String insertData1 = "INSERT INTO user_system_data VALUES ('101','jsnow','passwd1', '')"; + String insertData2 = "INSERT INTO user_system_data VALUES ('102','jdoe','passwd2', '')"; + String insertData3 = "INSERT INTO user_system_data VALUES ('103','jplane','passwd3', '')"; + String insertData4 = "INSERT INTO user_system_data VALUES ('104','jeff','jeff', '')"; + String insertData5 = "INSERT INTO user_system_data VALUES ('105','dave','dave', '')"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); } - - /** - * Description of the Method - * - * @param connection - * Description of the Parameter - * - * @exception SQLException - * Description of the Exception - */ - private void createWeatherDataTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); - // Delete table if there is one - try - { - String dropTable = "DROP TABLE weather_data"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop weather table"); - } + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + */ + private void createUserDataTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - // Create the new table - try - { - String createTableStatement = "CREATE TABLE weather_data (" + "station int not null," - + "name varchar(20) not null," + "state char(2) not null," + "min_temp int not null," - + "max_temp int not null" + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating weather table " + e.getLocalizedMessage()); - } + // Delete table if there is one + try { + String dropTable = "DROP TABLE user_data"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop user table"); + } - // Populate it - String insertData1 = "INSERT INTO weather_data VALUES (101,'Columbia','MD',-10,102)"; - String insertData2 = "INSERT INTO weather_data VALUES (102,'Seattle','WA',-15,90)"; - String insertData3 = "INSERT INTO weather_data VALUES (103,'New York','NY',-10,110)"; - String insertData4 = "INSERT INTO weather_data VALUES (104,'Houston','TX',20,120)"; - String insertData5 = "INSERT INTO weather_data VALUES (10001,'Camp David','MD',-10,100)"; - String insertData6 = "INSERT INTO weather_data VALUES (11001,'Ice Station Zebra','NA',-60,30)"; - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - statement.executeUpdate(insertData6); - } + // Create the new table + try { + String createTableStatement = "CREATE TABLE user_data (" + "userid int not null," + + "first_name varchar(20)," + "last_name varchar(20)," + "cc_number varchar(30)," + + "cc_type varchar(10)," + "cookie varchar(20)," + "login_count int" + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating user table " + e.getLocalizedMessage()); + } - /** - * Create users with tans - * - * @param connection - * @throws SQLException - */ - private void createTanUserDataTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); + // Populate it + String insertData1 = "INSERT INTO user_data VALUES (101,'Joe','Snow','987654321','VISA',' ',0)"; + String insertData2 = "INSERT INTO user_data VALUES (101,'Joe','Snow','2234200065411','MC',' ',0)"; + String insertData3 = "INSERT INTO user_data VALUES (102,'John','Smith','2435600002222','MC',' ',0)"; + String insertData4 = "INSERT INTO user_data VALUES (102,'John','Smith','4352209902222','AMEX',' ',0)"; + String insertData5 = "INSERT INTO user_data VALUES (103,'Jane','Plane','123456789','MC',' ',0)"; + String insertData6 = "INSERT INTO user_data VALUES (103,'Jane','Plane','333498703333','AMEX',' ',0)"; + String insertData7 = "INSERT INTO user_data VALUES (10312,'Jolly','Hershey','176896789','MC',' ',0)"; + String insertData8 = "INSERT INTO user_data VALUES (10312,'Jolly','Hershey','333300003333','AMEX',' ',0)"; + String insertData9 = "INSERT INTO user_data VALUES (10323,'Grumpy','youaretheweakestlink','673834489','MC',' ',0)"; + String insertData10 = "INSERT INTO user_data VALUES (10323,'Grumpy','youaretheweakestlink','33413003333','AMEX',' ',0)"; + String insertData11 = "INSERT INTO user_data VALUES (15603,'Peter','Sand','123609789','MC',' ',0)"; + String insertData12 = "INSERT INTO user_data VALUES (15603,'Peter','Sand','338893453333','AMEX',' ',0)"; + String insertData13 = "INSERT INTO user_data VALUES (15613,'Joesph','Something','33843453533','AMEX',' ',0)"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); + statement.executeUpdate(insertData6); + statement.executeUpdate(insertData7); + statement.executeUpdate(insertData8); + statement.executeUpdate(insertData9); + statement.executeUpdate(insertData10); + statement.executeUpdate(insertData11); + statement.executeUpdate(insertData12); + statement.executeUpdate(insertData13); - // Delete table if there is one - try - { - String dropTable = "DROP TABLE user_data_tan"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop user_data_tan table"); - } + } - // Create the new table - try - { - String createTableStatement = "CREATE TABLE user_data_tan (" + "userid int not null," - + "first_name varchar(20)," + "last_name varchar(20)," + "cc_number varchar(30)," - + "cc_type varchar(10)," + "cookie varchar(20)," + "login_count int," + "password varchar(20)" - + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating user_data_tan table " + e.getLocalizedMessage()); - } + private void createLoginTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - // Populate it - String insertData1 = "INSERT INTO user_data_tan VALUES (101,'Joe','Snow','987654321','VISA',' ',0, 'banana')"; - String insertData2 = "INSERT INTO user_data_tan VALUES (102,'Jane','Plane','74589864','MC',' ',0, 'tarzan')"; - String insertData3 = "INSERT INTO user_data_tan VALUES (103,'Jack','Sparrow','68659365','MC',' ',0, 'sniffy')"; + // Delete table if there is one + try { + String dropTable = "DROP TABLE user_login"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop user_login table"); + } - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - } + // Create the new table + try { + String createTableStatement = "CREATE TABLE user_login (" + "userid varchar(5)," + + "webgoat_user varchar(20)" + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating user_login table " + e.getLocalizedMessage()); + } - /** - * Create the Table for the tans - * - * @param connection - * @throws SQLException - */ - private void createTanTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); + } - // Delete table if there is one - try - { - String dropTable = "DROP TABLE tan"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop tan table"); - } + // creates the table pins which is used in the blind sql injection lesson + private void createBlindSQLLessonTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - // Create the new table - try - { - String createTableStatement = "CREATE TABLE tan (" + "userid int not null," + "tanNr int," + "tanValue int" - + ")"; - statement.executeUpdate(createTableStatement); - } catch (SQLException e) - { - System.out.println("Error creating tan table " + e.getLocalizedMessage()); - } + // Delete table if there is one + try { + String dropTable = "DROP TABLE pins"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop pins table"); + } - // Populate it - String insertData1 = "INSERT INTO tan VALUES (101,1,15161)"; - String insertData2 = "INSERT INTO tan VALUES (101,2,4894)"; - String insertData3 = "INSERT INTO tan VALUES (101,3,18794)"; - String insertData4 = "INSERT INTO tan VALUES (101,4,1564)"; - String insertData5 = "INSERT INTO tan VALUES (101,5,45751)"; + // Create the new table + try { + String createTableStatement = "CREATE TABLE pins (" + + "cc_number varchar(30)," + + "pin int," + + "name varchar(20)" + + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating pins table " + e.getLocalizedMessage()); + } - String insertData6 = "INSERT INTO tan VALUES (102,1,15648)"; - String insertData7 = "INSERT INTO tan VALUES (102,2,92156)"; - String insertData8 = "INSERT INTO tan VALUES (102,3,4879)"; - String insertData9 = "INSERT INTO tan VALUES (102,4,9458)"; - String insertData10 = "INSERT INTO tan VALUES (102,5,4879)"; + // Populate it + String insertData1 = "INSERT INTO pins VALUES ('987654321098765', 1234, 'Joe')"; + String insertData2 = "INSERT INTO pins VALUES ('1234567890123456', 4567, 'Jack')"; + String insertData3 = "INSERT INTO pins VALUES ('4321432143214321', 4321, 'Jill')"; + String insertData4 = "INSERT INTO pins VALUES ('1111111111111111', 7777, 'Jim')"; + String insertData5 = "INSERT INTO pins VALUES ('1111222233334444', 2364, 'John')"; - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - statement.executeUpdate(insertData6); - statement.executeUpdate(insertData7); - statement.executeUpdate(insertData8); - statement.executeUpdate(insertData9); - statement.executeUpdate(insertData10); + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); - } + } - // -------------------------------------------------------------------------- - // -------------------------------------------------------------------------- - // - // The tables below are for WebGoat Financials - // - // DO NOT MODIFY THESE TABLES - unless you change the org chart - // and access control matrix documents - // - // -------------------------------------------------------------------------- - // -------------------------------------------------------------------------- + // creates the table salaries which is used in the lessons + // which add or modify data using sql injection + private void createModifyWithSQLLessonTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - private void createEmployeeTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); + // Delete table if there is one + try { + String dropTable = "DROP TABLE salaries"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop salaries table"); + } - try - { - String dropTable = "DROP TABLE employee"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop employee table"); - } + // Create the new table + try { + String createTableStatement = "CREATE TABLE salaries (" + + "userid varchar(50)," + + "salary int" + + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating salaries table " + e.getLocalizedMessage()); + } - // Create Table - try - { - String createTable = "CREATE TABLE employee (" - // + "userid INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY," - + "userid INT NOT NULL PRIMARY KEY," + "first_name VARCHAR(20)," + "last_name VARCHAR(20)," - + "ssn VARCHAR(12)," + "password VARCHAR(10)," + "title VARCHAR(20)," + "phone VARCHAR(13)," - + "address1 VARCHAR(80)," + "address2 VARCHAR(80)," + "manager INT," + "start_date CHAR(8)," - + "salary INT," + "ccn VARCHAR(30)," + "ccn_limit INT," + "email VARCHAR(30)," // reason - // for the recent write-up - + "disciplined_date CHAR(8)," // date of write up, NA otherwise - + "disciplined_notes VARCHAR(60)," // reason for the recent write-up - + "personal_description VARCHAR(60)" // We can be rude here - // + ",CONSTRAINT fl UNIQUE NONCLUSTERED (first_name, last_name)" - + ")"; + // Populate it + String insertData1 = "INSERT INTO salaries VALUES ('jsmith', 20000)"; + String insertData2 = "INSERT INTO salaries VALUES ('lsmith', 45000)"; + String insertData3 = "INSERT INTO salaries VALUES ('wgoat', 100000)"; + String insertData4 = "INSERT INTO salaries VALUES ('rjones', 777777)"; + String insertData5 = "INSERT INTO salaries VALUES ('manderson', 65000)"; - statement.executeUpdate(createTable); - } catch (SQLException e) - { - System.out.println("Error: unable to create employee table " + e.getLocalizedMessage()); - } + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); - String insertData1 = "INSERT INTO employee VALUES (101, 'Larry', 'Stooge', '386-09-5451', 'larry'," - + "'Technician','443-689-0192','9175 Guilford Rd','New York, NY', 102, 01012000,55000,'2578546969853547'," - + "5000,'larry@stooges.com',010106,'Constantly harassing coworkers','Does not work well with others')"; + } - String insertData2 = "INSERT INTO employee VALUES (102, 'Moe', 'Stooge', '936-18-4524','moe'," - + "'CSO','443-938-5301', '3013 AMD Ave', 'New York, NY', 112, 03082003, 140000, 'NA', 0, 'moe@stooges.com', 0101013, " - + "'Hit Curly over head', 'Very dominating over Larry and Curly')"; + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + */ + private void createWeatherDataTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - String insertData3 = "INSERT INTO employee VALUES (103, 'Curly', 'Stooge', '961-08-0047','curly'," - + "'Technician','410-667-6654', '1112 Crusoe Lane', 'New York, NY', 102, 02122001, 50000, 'NA', 0, 'curly@stooges.com', 0101014, " - + "'Hit Moe back', 'Owes three-thousand to company for fradulent purchases')"; + // Delete table if there is one + try { + String dropTable = "DROP TABLE weather_data"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop weather table"); + } - String insertData4 = "INSERT INTO employee VALUES (104, 'Eric', 'Walker', '445-66-5565','eric'," - + "'Engineer','410-887-1193', '1160 Prescott Rd', 'New York, NY', 107, 12152005, 13000, 'NA', 0, 'eric@modelsrus.com',0101013, " - + "'Bothering Larry about webgoat problems', 'Late. Always needs help. Too intern-ish.')"; + // Create the new table + try { + String createTableStatement = "CREATE TABLE weather_data (" + "station int not null," + + "name varchar(20) not null," + "state char(2) not null," + "min_temp int not null," + + "max_temp int not null" + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating weather table " + e.getLocalizedMessage()); + } - String insertData5 = "INSERT INTO employee VALUES (105, 'Tom', 'Cat', '792-14-6364','tom'," - + "'Engineer','443-599-0762', '2211 HyperThread Rd.', 'New York, NY', 106, 01011999, 80000, '5481360857968521', 30000, 'tom@wb.com', 0, " - + "'NA', 'Co-Owner.')"; + // Populate it + String insertData1 = "INSERT INTO weather_data VALUES (101,'Columbia','MD',-10,102)"; + String insertData2 = "INSERT INTO weather_data VALUES (102,'Seattle','WA',-15,90)"; + String insertData3 = "INSERT INTO weather_data VALUES (103,'New York','NY',-10,110)"; + String insertData4 = "INSERT INTO weather_data VALUES (104,'Houston','TX',20,120)"; + String insertData5 = "INSERT INTO weather_data VALUES (10001,'Camp David','MD',-10,100)"; + String insertData6 = "INSERT INTO weather_data VALUES (11001,'Ice Station Zebra','NA',-60,30)"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); + statement.executeUpdate(insertData6); + } - String insertData6 = "INSERT INTO employee VALUES (106, 'Jerry', 'Mouse', '858-55-4452','jerry'," - + "'Human Resources','443-699-3366', '3011 Unix Drive', 'New York, NY', 102, 01011999, 70000, '6981754825013564', 20000, 'jerry@wb.com', 0, " - + "'NA', 'Co-Owner.')"; + /** + * Create users with tans + * + * @param connection + * @throws SQLException + */ + private void createTanUserDataTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - String insertData7 = "INSERT INTO employee VALUES (107, 'David', 'Giambi', '439-20-9405','david'," - + "'Human Resources','610-521-8413', '5132 DIMM Avenue', 'New York, NY', 102, 05011999, 100000, '6981754825018101', 10000, 'david@modelsrus.com', 061402, " - + "'Hacked into accounting server. Modified personal pay.', 'Strong work habbit. Questionable ethics.')"; + // Delete table if there is one + try { + String dropTable = "DROP TABLE user_data_tan"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop user_data_tan table"); + } - String insertData8 = "INSERT INTO employee VALUES (108, 'Bruce', 'McGuirre', '707-95-9482','bruce'," - + "'Engineer','610-282-1103', '8899 FreeBSD Drive ', 'New York, NY', 107, 03012000, 110000, '6981754825854136', 30000, 'bruce@modelsrus.com', 061502, " - + "'Tortuous Boot Camp workout at 5am. Employees felt sick.', 'Enjoys watching others struggle in exercises.')"; + // Create the new table + try { + String createTableStatement = "CREATE TABLE user_data_tan (" + "userid int not null," + + "first_name varchar(20)," + "last_name varchar(20)," + "cc_number varchar(30)," + + "cc_type varchar(10)," + "cookie varchar(20)," + "login_count int," + "password varchar(20)" + + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating user_data_tan table " + e.getLocalizedMessage()); + } - String insertData9 = "INSERT INTO employee VALUES (109, 'Sean', 'Livingston', '136-55-1046','sean'," - + "'Engineer','610-878-9549', '6422 dFlyBSD Road', 'New York, NY', 107, 06012003, 130000, '6981754825014510', 5000, 'sean@modelsrus.com', 072804, " - + "'Late to work 30 days in row due to excessive Halo 2', 'Has some fascination with Steelers. Go Ravens.')"; + // Populate it + String insertData1 = "INSERT INTO user_data_tan VALUES (101,'Joe','Snow','987654321','VISA',' ',0, 'banana')"; + String insertData2 = "INSERT INTO user_data_tan VALUES (102,'Jane','Plane','74589864','MC',' ',0, 'tarzan')"; + String insertData3 = "INSERT INTO user_data_tan VALUES (103,'Jack','Sparrow','68659365','MC',' ',0, 'sniffy')"; - String insertData10 = "INSERT INTO employee VALUES (110, 'Joanne', 'McDougal', '789-54-2413','joanne'," - + "'Human Resources','610-213-6341', '5567 Broadband Lane', 'New York, NY', 106, 01012001, 90000, '6981754825081054', 300, 'joanne@modelsrus.com', 112005, " - + "'Used company cc to purchase new car. Limit adjusted.', 'Finds it necessary to leave early every day.')"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + } - String insertData11 = "INSERT INTO employee VALUES (111, 'John', 'Wayne', '129-69-4572', 'john'," - + "'CTO','610-213-1134', '129 Third St', 'New York, NY', 112, 01012001, 200000, '4437334565679921', 300, 'john@guns.com', 112005, " - + "'', '')"; - String insertData12 = "INSERT INTO employee VALUES (112, 'Neville', 'Bartholomew', '111-111-1111', 'socks'," - + "'CEO','408-587-0024', '1 Corporate Headquarters', 'San Jose, CA', 112, 03012000, 450000, '4803389267684109', 300000, 'neville@modelsrus.com', 112005, " - + "'', '')"; + /** + * Create the Table for the tans + * + * @param connection + * @throws SQLException + */ + private void createTanTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - statement.executeUpdate(insertData6); - statement.executeUpdate(insertData7); - statement.executeUpdate(insertData8); - statement.executeUpdate(insertData9); - statement.executeUpdate(insertData10); - statement.executeUpdate(insertData11); - statement.executeUpdate(insertData12); + // Delete table if there is one + try { + String dropTable = "DROP TABLE tan"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop tan table"); + } - } + // Create the new table + try { + String createTableStatement = "CREATE TABLE tan (" + "userid int not null," + "tanNr int," + "tanValue int" + + ")"; + statement.executeUpdate(createTableStatement); + } catch (SQLException e) { + System.out.println("Error creating tan table " + e.getLocalizedMessage()); + } - private void createRolesTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); + // Populate it + String insertData1 = "INSERT INTO tan VALUES (101,1,15161)"; + String insertData2 = "INSERT INTO tan VALUES (101,2,4894)"; + String insertData3 = "INSERT INTO tan VALUES (101,3,18794)"; + String insertData4 = "INSERT INTO tan VALUES (101,4,1564)"; + String insertData5 = "INSERT INTO tan VALUES (101,5,45751)"; - try - { - String dropTable = "DROP TABLE roles"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop roles table"); - } + String insertData6 = "INSERT INTO tan VALUES (102,1,15648)"; + String insertData7 = "INSERT INTO tan VALUES (102,2,92156)"; + String insertData8 = "INSERT INTO tan VALUES (102,3,4879)"; + String insertData9 = "INSERT INTO tan VALUES (102,4,9458)"; + String insertData10 = "INSERT INTO tan VALUES (102,5,4879)"; - try - { - String createTable = "CREATE TABLE roles (" + "userid INT NOT NULL," + "role VARCHAR(10) NOT NULL," - + "PRIMARY KEY (userid, role)" + ")"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); + statement.executeUpdate(insertData6); + statement.executeUpdate(insertData7); + statement.executeUpdate(insertData8); + statement.executeUpdate(insertData9); + statement.executeUpdate(insertData10); - statement.executeUpdate(createTable); - } catch (SQLException e) - { - System.out.println("Error: Unable to create role table: " + e.getLocalizedMessage()); - } + } - String insertData1 = "INSERT INTO roles VALUES (101, 'employee')"; - String insertData2 = "INSERT INTO roles VALUES (102, 'manager')"; - String insertData3 = "INSERT INTO roles VALUES (103, 'employee')"; - String insertData4 = "INSERT INTO roles VALUES (104, 'employee')"; - String insertData5 = "INSERT INTO roles VALUES (105, 'employee')"; - String insertData6 = "INSERT INTO roles VALUES (106, 'hr')"; - String insertData7 = "INSERT INTO roles VALUES (107, 'manager')"; - String insertData8 = "INSERT INTO roles VALUES (108, 'employee')"; - String insertData9 = "INSERT INTO roles VALUES (109, 'employee')"; - String insertData10 = "INSERT INTO roles VALUES (110, 'hr')"; - String insertData11 = "INSERT INTO roles VALUES (111, 'admin')"; - String insertData12 = "INSERT INTO roles VALUES (112, 'admin')"; + // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- + // + // The tables below are for WebGoat Financials + // + // DO NOT MODIFY THESE TABLES - unless you change the org chart + // and access control matrix documents + // + // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData5); - statement.executeUpdate(insertData6); - statement.executeUpdate(insertData7); - statement.executeUpdate(insertData8); - statement.executeUpdate(insertData9); - statement.executeUpdate(insertData10); - statement.executeUpdate(insertData11); - statement.executeUpdate(insertData12); - } + private void createEmployeeTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - private void createAuthTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); + try { + String dropTable = "DROP TABLE employee"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop employee table"); + } - try - { - String dropTable = "DROP TABLE auth"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop auth table"); - } + // Create Table + try { + String createTable = "CREATE TABLE employee (" + // + "userid INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY," + + "userid INT NOT NULL PRIMARY KEY," + "first_name VARCHAR(20)," + "last_name VARCHAR(20)," + + "ssn VARCHAR(12)," + "password VARCHAR(10)," + "title VARCHAR(20)," + "phone VARCHAR(13)," + + "address1 VARCHAR(80)," + "address2 VARCHAR(80)," + "manager INT," + "start_date CHAR(8)," + + "salary INT," + "ccn VARCHAR(30)," + "ccn_limit INT," + "email VARCHAR(30)," // reason + // for the recent write-up + + "disciplined_date CHAR(8)," // date of write up, NA otherwise + + "disciplined_notes VARCHAR(60)," // reason for the recent write-up + + "personal_description VARCHAR(60)" // We can be rude here + // + ",CONSTRAINT fl UNIQUE NONCLUSTERED (first_name, last_name)" + + ")"; - try - { - String createTable = "CREATE TABLE auth (" + "role VARCHAR(10) NOT NULL," - + "functionid VARCHAR(20) NOT NULL," + "PRIMARY KEY (role, functionid)" + ")"; + statement.executeUpdate(createTable); + } catch (SQLException e) { + System.out.println("Error: unable to create employee table " + e.getLocalizedMessage()); + } - statement.executeUpdate(createTable); - } catch (SQLException e) - { - System.out.println("Error: unable to create auth table: " + e.getLocalizedMessage()); - } + String insertData1 = "INSERT INTO employee VALUES (101, 'Larry', 'Stooge', '386-09-5451', 'larry'," + + "'Technician','443-689-0192','9175 Guilford Rd','New York, NY', 102, 01012000,55000,'2578546969853547'," + + "5000,'larry@stooges.com',010106,'Constantly harassing coworkers','Does not work well with others')"; - String insertData1 = "INSERT INTO auth VALUES('employee', 'Logout')"; - String insertData2 = "INSERT INTO auth VALUES('employee', 'ListStaff')"; - String insertData3 = "INSERT INTO auth VALUES('employee', 'ViewProfile')"; - String insertData4 = "INSERT INTO auth VALUES('employee', 'EditProfile')"; - String insertData4_1 = "INSERT INTO auth VALUES('employee', 'SearchStaff')"; - String insertData4_2 = "INSERT INTO auth VALUES('employee', 'FindProfile')"; - String insertData5 = "INSERT INTO auth VALUES('manager', 'Logout')"; - String insertData6 = "INSERT INTO auth VALUES('manager', 'ListStaff')"; - String insertData7 = "INSERT INTO auth VALUES('manager', 'ViewProfile')"; - String insertData7_1 = "INSERT INTO auth VALUES('manager', 'SearchStaff')"; - String insertData7_2 = "INSERT INTO auth VALUES('manager', 'FindProfile')"; - // String insertData8 = "INSERT INTO auth VALUES('manager', 'EditProfile')"; - // String insertData9 = "INSERT INTO auth VALUES('manager', 'CreateProfile')"; - // String insertData10 = "INSERT INTO auth VALUES('manager', 'DeleteProfile')"; - // String insertData11 = "INSERT INTO auth VALUES('manager', 'UpdateProfile')"; - String insertData12 = "INSERT INTO auth VALUES('hr', 'Logout')"; - String insertData13 = "INSERT INTO auth VALUES('hr', 'ListStaff')"; - String insertData14 = "INSERT INTO auth VALUES('hr', 'ViewProfile')"; - String insertData15 = "INSERT INTO auth VALUES('hr', 'EditProfile')"; - String insertData16 = "INSERT INTO auth VALUES('hr', 'CreateProfile')"; - String insertData17 = "INSERT INTO auth VALUES('hr', 'DeleteProfile')"; - String insertData18 = "INSERT INTO auth VALUES('hr', 'UpdateProfile')"; - String insertData18_1 = "INSERT INTO auth VALUES('hr', 'SearchStaff')"; - String insertData18_2 = "INSERT INTO auth VALUES('hr', 'FindProfile')"; - String insertData19 = "INSERT INTO auth VALUES('admin', 'Logout')"; - String insertData20 = "INSERT INTO auth VALUES('admin', 'ListStaff')"; - String insertData21 = "INSERT INTO auth VALUES('admin', 'ViewProfile')"; - String insertData22 = "INSERT INTO auth VALUES('admin', 'EditProfile')"; - String insertData23 = "INSERT INTO auth VALUES('admin', 'CreateProfile')"; - String insertData24 = "INSERT INTO auth VALUES('admin', 'DeleteProfile')"; - String insertData25 = "INSERT INTO auth VALUES('admin', 'UpdateProfile')"; - String insertData25_1 = "INSERT INTO auth VALUES('admin', 'SearchStaff')"; - String insertData25_2 = "INSERT INTO auth VALUES('admin', 'FindProfile')"; + String insertData2 = "INSERT INTO employee VALUES (102, 'Moe', 'Stooge', '936-18-4524','moe'," + + "'CSO','443-938-5301', '3013 AMD Ave', 'New York, NY', 112, 03082003, 140000, 'NA', 0, 'moe@stooges.com', 0101013, " + + "'Hit Curly over head', 'Very dominating over Larry and Curly')"; + + String insertData3 = "INSERT INTO employee VALUES (103, 'Curly', 'Stooge', '961-08-0047','curly'," + + "'Technician','410-667-6654', '1112 Crusoe Lane', 'New York, NY', 102, 02122001, 50000, 'NA', 0, 'curly@stooges.com', 0101014, " + + "'Hit Moe back', 'Owes three-thousand to company for fradulent purchases')"; + + String insertData4 = "INSERT INTO employee VALUES (104, 'Eric', 'Walker', '445-66-5565','eric'," + + "'Engineer','410-887-1193', '1160 Prescott Rd', 'New York, NY', 107, 12152005, 13000, 'NA', 0, 'eric@modelsrus.com',0101013, " + + "'Bothering Larry about webgoat problems', 'Late. Always needs help. Too intern-ish.')"; + + String insertData5 = "INSERT INTO employee VALUES (105, 'Tom', 'Cat', '792-14-6364','tom'," + + "'Engineer','443-599-0762', '2211 HyperThread Rd.', 'New York, NY', 106, 01011999, 80000, '5481360857968521', 30000, 'tom@wb.com', 0, " + + "'NA', 'Co-Owner.')"; + + String insertData6 = "INSERT INTO employee VALUES (106, 'Jerry', 'Mouse', '858-55-4452','jerry'," + + "'Human Resources','443-699-3366', '3011 Unix Drive', 'New York, NY', 102, 01011999, 70000, '6981754825013564', 20000, 'jerry@wb.com', 0, " + + "'NA', 'Co-Owner.')"; + + String insertData7 = "INSERT INTO employee VALUES (107, 'David', 'Giambi', '439-20-9405','david'," + + "'Human Resources','610-521-8413', '5132 DIMM Avenue', 'New York, NY', 102, 05011999, 100000, '6981754825018101', 10000, 'david@modelsrus.com', 061402, " + + "'Hacked into accounting server. Modified personal pay.', 'Strong work habbit. Questionable ethics.')"; + + String insertData8 = "INSERT INTO employee VALUES (108, 'Bruce', 'McGuirre', '707-95-9482','bruce'," + + "'Engineer','610-282-1103', '8899 FreeBSD Drive ', 'New York, NY', 107, 03012000, 110000, '6981754825854136', 30000, 'bruce@modelsrus.com', 061502, " + + "'Tortuous Boot Camp workout at 5am. Employees felt sick.', 'Enjoys watching others struggle in exercises.')"; + + String insertData9 = "INSERT INTO employee VALUES (109, 'Sean', 'Livingston', '136-55-1046','sean'," + + "'Engineer','610-878-9549', '6422 dFlyBSD Road', 'New York, NY', 107, 06012003, 130000, '6981754825014510', 5000, 'sean@modelsrus.com', 072804, " + + "'Late to work 30 days in row due to excessive Halo 2', 'Has some fascination with Steelers. Go Ravens.')"; + + String insertData10 = "INSERT INTO employee VALUES (110, 'Joanne', 'McDougal', '789-54-2413','joanne'," + + "'Human Resources','610-213-6341', '5567 Broadband Lane', 'New York, NY', 106, 01012001, 90000, '6981754825081054', 300, 'joanne@modelsrus.com', 112005, " + + "'Used company cc to purchase new car. Limit adjusted.', 'Finds it necessary to leave early every day.')"; + + String insertData11 = "INSERT INTO employee VALUES (111, 'John', 'Wayne', '129-69-4572', 'john'," + + "'CTO','610-213-1134', '129 Third St', 'New York, NY', 112, 01012001, 200000, '4437334565679921', 300, 'john@guns.com', 112005, " + + "'', '')"; + String insertData12 = "INSERT INTO employee VALUES (112, 'Neville', 'Bartholomew', '111-111-1111', 'socks'," + + "'CEO','408-587-0024', '1 Corporate Headquarters', 'San Jose, CA', 112, 03012000, 450000, '4803389267684109', 300000, 'neville@modelsrus.com', 112005, " + + "'', '')"; + + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); + statement.executeUpdate(insertData6); + statement.executeUpdate(insertData7); + statement.executeUpdate(insertData8); + statement.executeUpdate(insertData9); + statement.executeUpdate(insertData10); + statement.executeUpdate(insertData11); + statement.executeUpdate(insertData12); + + } + + private void createRolesTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + + try { + String dropTable = "DROP TABLE roles"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop roles table"); + } + + try { + String createTable = "CREATE TABLE roles (" + "userid INT NOT NULL," + "role VARCHAR(10) NOT NULL," + + "PRIMARY KEY (userid, role)" + ")"; + + statement.executeUpdate(createTable); + } catch (SQLException e) { + System.out.println("Error: Unable to create role table: " + e.getLocalizedMessage()); + } + + String insertData1 = "INSERT INTO roles VALUES (101, 'employee')"; + String insertData2 = "INSERT INTO roles VALUES (102, 'manager')"; + String insertData3 = "INSERT INTO roles VALUES (103, 'employee')"; + String insertData4 = "INSERT INTO roles VALUES (104, 'employee')"; + String insertData5 = "INSERT INTO roles VALUES (105, 'employee')"; + String insertData6 = "INSERT INTO roles VALUES (106, 'hr')"; + String insertData7 = "INSERT INTO roles VALUES (107, 'manager')"; + String insertData8 = "INSERT INTO roles VALUES (108, 'employee')"; + String insertData9 = "INSERT INTO roles VALUES (109, 'employee')"; + String insertData10 = "INSERT INTO roles VALUES (110, 'hr')"; + String insertData11 = "INSERT INTO roles VALUES (111, 'admin')"; + String insertData12 = "INSERT INTO roles VALUES (112, 'admin')"; + + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData5); + statement.executeUpdate(insertData6); + statement.executeUpdate(insertData7); + statement.executeUpdate(insertData8); + statement.executeUpdate(insertData9); + statement.executeUpdate(insertData10); + statement.executeUpdate(insertData11); + statement.executeUpdate(insertData12); + } + + private void createAuthTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + + try { + String dropTable = "DROP TABLE auth"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop auth table"); + } + + try { + String createTable = "CREATE TABLE auth (" + "role VARCHAR(10) NOT NULL," + + "functionid VARCHAR(20) NOT NULL," + "PRIMARY KEY (role, functionid)" + ")"; + + statement.executeUpdate(createTable); + } catch (SQLException e) { + System.out.println("Error: unable to create auth table: " + e.getLocalizedMessage()); + } + + String insertData1 = "INSERT INTO auth VALUES('employee', 'Logout')"; + String insertData2 = "INSERT INTO auth VALUES('employee', 'ListStaff')"; + String insertData3 = "INSERT INTO auth VALUES('employee', 'ViewProfile')"; + String insertData4 = "INSERT INTO auth VALUES('employee', 'EditProfile')"; + String insertData4_1 = "INSERT INTO auth VALUES('employee', 'SearchStaff')"; + String insertData4_2 = "INSERT INTO auth VALUES('employee', 'FindProfile')"; + String insertData5 = "INSERT INTO auth VALUES('manager', 'Logout')"; + String insertData6 = "INSERT INTO auth VALUES('manager', 'ListStaff')"; + String insertData7 = "INSERT INTO auth VALUES('manager', 'ViewProfile')"; + String insertData7_1 = "INSERT INTO auth VALUES('manager', 'SearchStaff')"; + String insertData7_2 = "INSERT INTO auth VALUES('manager', 'FindProfile')"; + // String insertData8 = "INSERT INTO auth VALUES('manager', 'EditProfile')"; + // String insertData9 = "INSERT INTO auth VALUES('manager', 'CreateProfile')"; + // String insertData10 = "INSERT INTO auth VALUES('manager', 'DeleteProfile')"; + // String insertData11 = "INSERT INTO auth VALUES('manager', 'UpdateProfile')"; + String insertData12 = "INSERT INTO auth VALUES('hr', 'Logout')"; + String insertData13 = "INSERT INTO auth VALUES('hr', 'ListStaff')"; + String insertData14 = "INSERT INTO auth VALUES('hr', 'ViewProfile')"; + String insertData15 = "INSERT INTO auth VALUES('hr', 'EditProfile')"; + String insertData16 = "INSERT INTO auth VALUES('hr', 'CreateProfile')"; + String insertData17 = "INSERT INTO auth VALUES('hr', 'DeleteProfile')"; + String insertData18 = "INSERT INTO auth VALUES('hr', 'UpdateProfile')"; + String insertData18_1 = "INSERT INTO auth VALUES('hr', 'SearchStaff')"; + String insertData18_2 = "INSERT INTO auth VALUES('hr', 'FindProfile')"; + String insertData19 = "INSERT INTO auth VALUES('admin', 'Logout')"; + String insertData20 = "INSERT INTO auth VALUES('admin', 'ListStaff')"; + String insertData21 = "INSERT INTO auth VALUES('admin', 'ViewProfile')"; + String insertData22 = "INSERT INTO auth VALUES('admin', 'EditProfile')"; + String insertData23 = "INSERT INTO auth VALUES('admin', 'CreateProfile')"; + String insertData24 = "INSERT INTO auth VALUES('admin', 'DeleteProfile')"; + String insertData25 = "INSERT INTO auth VALUES('admin', 'UpdateProfile')"; + String insertData25_1 = "INSERT INTO auth VALUES('admin', 'SearchStaff')"; + String insertData25_2 = "INSERT INTO auth VALUES('admin', 'FindProfile')"; // // Add a permission for the webgoat role to see the source. // // The challenge(s) will change the default role to "challenge" @@ -764,274 +716,261 @@ public class CreateDB // + "')"; // String insertData27 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWHINTS // + "')"; - // Add a permission for the webgoat role to see the solution. - // The challenge(s) will change the default role to "challenge" + // Add a permission for the webgoat role to see the solution. + // The challenge(s) will change the default role to "challenge" // String insertData28 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWSOLUTION // + "')"; - statement.executeUpdate(insertData1); - statement.executeUpdate(insertData2); - statement.executeUpdate(insertData3); - statement.executeUpdate(insertData4); - statement.executeUpdate(insertData4_1); - statement.executeUpdate(insertData4_2); - statement.executeUpdate(insertData5); - statement.executeUpdate(insertData6); - statement.executeUpdate(insertData7); - statement.executeUpdate(insertData7_1); - statement.executeUpdate(insertData7_2); - // statement.executeUpdate(insertData8); - // statement.executeUpdate(insertData9); - // statement.executeUpdate(insertData10); - // statement.executeUpdate(insertData11); - statement.executeUpdate(insertData12); - statement.executeUpdate(insertData13); - statement.executeUpdate(insertData14); - statement.executeUpdate(insertData15); - statement.executeUpdate(insertData16); - statement.executeUpdate(insertData17); - statement.executeUpdate(insertData18); - statement.executeUpdate(insertData18_1); - statement.executeUpdate(insertData18_2); - statement.executeUpdate(insertData19); - statement.executeUpdate(insertData20); - statement.executeUpdate(insertData21); - statement.executeUpdate(insertData22); - statement.executeUpdate(insertData23); - statement.executeUpdate(insertData24); - statement.executeUpdate(insertData25); - statement.executeUpdate(insertData25_1); - statement.executeUpdate(insertData25_2); - //statement.executeUpdate(insertData26); - //statement.executeUpdate(insertData27); - //statement.executeUpdate(insertData28); - } + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + statement.executeUpdate(insertData4_1); + statement.executeUpdate(insertData4_2); + statement.executeUpdate(insertData5); + statement.executeUpdate(insertData6); + statement.executeUpdate(insertData7); + statement.executeUpdate(insertData7_1); + statement.executeUpdate(insertData7_2); + // statement.executeUpdate(insertData8); + // statement.executeUpdate(insertData9); + // statement.executeUpdate(insertData10); + // statement.executeUpdate(insertData11); + statement.executeUpdate(insertData12); + statement.executeUpdate(insertData13); + statement.executeUpdate(insertData14); + statement.executeUpdate(insertData15); + statement.executeUpdate(insertData16); + statement.executeUpdate(insertData17); + statement.executeUpdate(insertData18); + statement.executeUpdate(insertData18_1); + statement.executeUpdate(insertData18_2); + statement.executeUpdate(insertData19); + statement.executeUpdate(insertData20); + statement.executeUpdate(insertData21); + statement.executeUpdate(insertData22); + statement.executeUpdate(insertData23); + statement.executeUpdate(insertData24); + statement.executeUpdate(insertData25); + statement.executeUpdate(insertData25_1); + statement.executeUpdate(insertData25_2); + //statement.executeUpdate(insertData26); + //statement.executeUpdate(insertData27); + //statement.executeUpdate(insertData28); + } - private void createOwnershipTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); + private void createOwnershipTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - try - { - String dropTable = "DROP TABLE ownership"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop ownership table"); - } + try { + String dropTable = "DROP TABLE ownership"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop ownership table"); + } - try - { - String createTable = "CREATE TABLE ownership (" + "employer_id INT NOT NULL," + "employee_id INT NOT NULL," - + "PRIMARY KEY (employee_id, employer_id)" + ")"; + try { + String createTable = "CREATE TABLE ownership (" + "employer_id INT NOT NULL," + "employee_id INT NOT NULL," + + "PRIMARY KEY (employee_id, employer_id)" + ")"; - statement.executeUpdate(createTable); - } catch (SQLException e) - { - System.out.println("Error: unable to create ownership table: " + e.getLocalizedMessage()); - } + statement.executeUpdate(createTable); + } catch (SQLException e) { + System.out.println("Error: unable to create ownership table: " + e.getLocalizedMessage()); + } - String inputData = "INSERT INTO ownership VALUES (112, 101)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 102)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 103)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 104)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 105)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 106)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 107)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 108)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 109)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 110)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 111)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (112, 112)"; - statement.executeUpdate(inputData); + String inputData = "INSERT INTO ownership VALUES (112, 101)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 102)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 103)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 104)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 105)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 106)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 107)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 108)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 109)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 110)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 111)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (112, 112)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 101)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 102)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 103)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 104)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 105)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 106)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 107)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 108)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 109)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 110)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (102, 111)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 101)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 102)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 103)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 104)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 105)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 106)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 107)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 108)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 109)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 110)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (102, 111)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 101)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 102)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 103)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 104)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 105)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 106)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 107)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 108)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 109)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 110)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (111, 111)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 101)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 102)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 103)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 104)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 105)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 106)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 107)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 108)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 109)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 110)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (111, 111)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (106, 105)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (106, 106)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (106, 110)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (106, 105)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (106, 106)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (106, 110)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (101, 101)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (101, 101)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (103, 103)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (103, 103)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (107, 104)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (107, 108)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (107, 109)"; - statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (107, 107)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (107, 104)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (107, 108)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (107, 109)"; + statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (107, 107)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (105, 105)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (105, 105)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (110, 110)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (110, 110)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (104, 104)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (104, 104)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (108, 108)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (108, 108)"; + statement.executeUpdate(inputData); - inputData = "INSERT INTO ownership VALUES (109, 109)"; - statement.executeUpdate(inputData); + inputData = "INSERT INTO ownership VALUES (109, 109)"; + statement.executeUpdate(inputData); - } + } - // -------------------------------------------------------------------------- - // - // End of WebGoat Financials - // - // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- + // + // End of WebGoat Financials + // + // -------------------------------------------------------------------------- - /** - * Start creation of data for WebServices labs - */ + /** + * Start creation of data for WebServices labs + */ - private void createTransactionTable(Connection connection) throws SQLException - { - Statement statement = connection.createStatement(); + private void createTransactionTable(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); - try - { - String dropTable = "DROP TABLE transactions"; - statement.executeUpdate(dropTable); - } catch (SQLException e) - { - System.out.println("Info - Could not drop transactions table"); - } + try { + String dropTable = "DROP TABLE transactions"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop transactions table"); + } - try - { - String createTable = "CREATE TABLE Transactions (" + "userName VARCHAR(16) NOT NULL, " - + "sequence INTEGER NOT NULL, " + "from_account VARCHAR(16) NOT NULL, " - + "to_account VARCHAR(16) NOT NULL, " + "transactionDate TIMESTAMP NOT NULL, " - + "description VARCHAR(255) NOT NULL, " + "amount INTEGER NOT NULL" + ")"; + try { + String createTable = "CREATE TABLE Transactions (" + "userName VARCHAR(16) NOT NULL, " + + "sequence INTEGER NOT NULL, " + "from_account VARCHAR(16) NOT NULL, " + + "to_account VARCHAR(16) NOT NULL, " + "transactionDate TIMESTAMP NOT NULL, " + + "description VARCHAR(255) NOT NULL, " + "amount INTEGER NOT NULL" + ")"; - statement.executeUpdate(createTable); - } catch (SQLException e) - { - System.out.println("Error: unable to create transactions table: " + e.getLocalizedMessage()); - throw e; - } + statement.executeUpdate(createTable); + } catch (SQLException e) { + System.out.println("Error: unable to create transactions table: " + e.getLocalizedMessage()); + throw e; + } - String[] data = new String[] { - "'dave', 0, '238-4723-4024', '324-7635-9867', '2008-02-06 21:40:00', 'Mortgage', '150'", - "'dave', 1, '238-4723-4024', '324-7635-9867', '2008-02-12 21:41:00', 'Car', '150'", - "'dave', 2, '238-4723-4024', '324-7635-9867', '2008-02-20 21:42:00', 'School fees', '150'", - "'CEO', 3, '348-6324-9872', '345-3490-8345', '2008-02-15 21:40:00', 'Rolls Royce', '-150000'", - "'CEO', 4, '348-6324-9872', '342-5893-4503', '2008-02-25 21:41:00', 'Mansion', '-150000'", - "'CEO', 5, '348-6324-9872', '980-2344-5492', '2008-02-27 21:42:00', 'Vacation', '-150000'", - "'jeff', 6, '934-2002-3485', '783-2409-8234', '2008-02-01 21:40:00', 'Vet', '250'", - "'jeff', 7, '934-2002-3485', '634-5879-0345', '2008-02-19 21:41:00', 'Doctor', '800'", - "'jeff', 8, '934-2002-3485', '435-4325-3358', '2008-02-20 21:42:00', 'X-rays', '200'", }; - try - { - for (int i = 0; i < data.length; i++) - { - statement.executeUpdate("INSERT INTO Transactions VALUES (" + data[i] + ");"); - } - } catch (SQLException sqle) - { - System.out.println("Error: Unable to insert transactions: " + sqle.getLocalizedMessage()); - int errorCode = sqle.getErrorCode(); - System.out.println("Error Code: " + errorCode); - // ignore exceptions for Oracle and SQL Server - if (errorCode != 911 && errorCode != 273) { throw sqle; } - } - } + String[] data = new String[]{ + "'dave', 0, '238-4723-4024', '324-7635-9867', '2008-02-06 21:40:00', 'Mortgage', '150'", + "'dave', 1, '238-4723-4024', '324-7635-9867', '2008-02-12 21:41:00', 'Car', '150'", + "'dave', 2, '238-4723-4024', '324-7635-9867', '2008-02-20 21:42:00', 'School fees', '150'", + "'CEO', 3, '348-6324-9872', '345-3490-8345', '2008-02-15 21:40:00', 'Rolls Royce', '-150000'", + "'CEO', 4, '348-6324-9872', '342-5893-4503', '2008-02-25 21:41:00', 'Mansion', '-150000'", + "'CEO', 5, '348-6324-9872', '980-2344-5492', '2008-02-27 21:42:00', 'Vacation', '-150000'", + "'jeff', 6, '934-2002-3485', '783-2409-8234', '2008-02-01 21:40:00', 'Vet', '250'", + "'jeff', 7, '934-2002-3485', '634-5879-0345', '2008-02-19 21:41:00', 'Doctor', '800'", + "'jeff', 8, '934-2002-3485', '435-4325-3358', '2008-02-20 21:42:00', 'X-rays', '200'",}; + try { + for (int i = 0; i < data.length; i++) { + statement.executeUpdate("INSERT INTO Transactions VALUES (" + data[i] + ");"); + } + } catch (SQLException sqle) { + System.out.println("Error: Unable to insert transactions: " + sqle.getLocalizedMessage()); + int errorCode = sqle.getErrorCode(); + System.out.println("Error Code: " + errorCode); + // ignore exceptions for Oracle and SQL Server + if (errorCode != 911 && errorCode != 273) { + throw sqle; + } + } + } - /** - * Description of the Method - * - * @param connection - * Description of the Parameter - * @exception SQLException - * Description of the Exception - * @throws java.sql.SQLException if any. - */ - public void makeDB(Connection connection) throws SQLException - { - System.out.println("Successful connection to database"); - createUserDataTable(connection); - createLoginTable(connection); - createBlindSQLLessonTable(connection); - createUserAdminTable(connection); - createProductTable(connection); - createMessageTable(connection); - createEmployeeTable(connection); - createRolesTable(connection); - createAuthTable(connection); - createOwnershipTable(connection); - createWeatherDataTable(connection); - createTransactionTable(connection); - createTanUserDataTable(connection); - createTanTable(connection); - createMFEImagesTable(connection); - createModifyWithSQLLessonTable(connection); - System.out.println("Success: creating tables."); - } + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + * @throws java.sql.SQLException if any. + */ + public void makeDB(Connection connection) throws SQLException { + System.out.println("Successful connection to database"); + createServersTable(connection); + createUserDataTable(connection); + createLoginTable(connection); + createBlindSQLLessonTable(connection); + createUserAdminTable(connection); + createProductTable(connection); + createMessageTable(connection); + createEmployeeTable(connection); + createRolesTable(connection); + createAuthTable(connection); + createOwnershipTable(connection); + createWeatherDataTable(connection); + createTransactionTable(connection); + createTanUserDataTable(connection); + createTanTable(connection); + createMFEImagesTable(connection); + createModifyWithSQLLessonTable(connection); + System.out.println("Success: creating tables."); + } } diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties index 4119f9887..aa20c6c47 100644 --- a/webgoat-container/src/main/resources/application.properties +++ b/webgoat-container/src/main/resources/application.properties @@ -16,7 +16,7 @@ security.enable-csrf=false spring.resources.cache-period=0 spring.thymeleaf.cache=false -webgoat.clean=true +webgoat.clean=false webgoat.server.directory=${user.home}/.webgoat/ webgoat.user.directory=${user.home}/.webgoat/ webgoat.build.version=@project.version@ @@ -29,6 +29,7 @@ webgoat.database.driver=org.hsqldb.jdbcDriver webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.default.language=en + spring.data.mongodb.database=webgoat spring.mongodb.embedded.storage.databaseDir=${webgoat.user.directory}/mongodb/ diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js index beb0f6fa6..dd96905cb 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js @@ -80,7 +80,9 @@ define(['jquery', var self = this; // TODO custom Data prep for submission var prepareDataFunctionName = $(curForm).attr('prepareData'); + var callbackFunctionName = $(curForm).attr('callback'); var submitData = (typeof webgoat.customjs[prepareDataFunctionName] === 'function') ? webgoat.customjs[prepareDataFunctionName]() : $(curForm).serialize(); + var callbackFunction = (typeof webgoat.customjs[callbackFunctionName] === 'function') ? webgoat.customjs[callbackFunctionName] : function() {}; // var submitData = this.$form.serialize(); this.curForm = curForm; this.$curFeedback = $(curForm).closest('.attack-container').find('.attack-feedback'); @@ -93,14 +95,16 @@ define(['jquery', url:formUrl, method:formMethod, contentType:contentType, - data: submitData + data: submitData, + complete: function (data) { + callbackFunction(); + } }).then(self.onSuccessResponse.bind(self), self.onErrorResponse.bind(self)); return false; }, onSuccessResponse: function(data) { this.renderFeedback(data.feedback); - this.renderOutput(data.output || ""); //TODO: refactor back assignmentCompleted in Java if (data.lessonCompleted || data.assignmentCompleted) { diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java new file mode 100644 index 000000000..3e6dffe9e --- /dev/null +++ b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java @@ -0,0 +1,49 @@ +package org.owasp.webgoat.plugins; + +import org.junit.Before; +import org.owasp.webgoat.i18n.Language; +import org.owasp.webgoat.i18n.PluginMessages; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.session.WebgoatContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.context.WebApplicationContext; + +import java.util.Locale; + +import static org.mockito.Mockito.when; + +/** + * @author nbaars + * @since 5/20/17. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = "classpath:/application-test.properties") +public abstract class LessonTest { + + @LocalServerPort + protected int localPort; + protected MockMvc mockMvc; + @Autowired + protected WebApplicationContext wac; + @Autowired + protected PluginMessages messages; + @MockBean + protected WebSession webSession; + @Autowired + private WebgoatContext context; + @MockBean + private Language language; + + @Before + public void init() { + when(webSession.getUserName()).thenReturn("unit-test"); + when(language.getLocale()).thenReturn(Locale.getDefault()); + when(webSession.getWebgoatContext()).thenReturn(context); + } + +} diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/TestConfig.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/TestConfig.java new file mode 100644 index 000000000..5946104b4 --- /dev/null +++ b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/TestConfig.java @@ -0,0 +1,23 @@ +package org.owasp.webgoat.plugins; + +import com.github.fakemongo.Fongo; +import com.mongodb.MongoClient; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.config.AbstractMongoConfiguration; + +/** + * Using Fongo for embedded in memory MongoDB testing + */ +@Configuration +public class TestConfig extends AbstractMongoConfiguration { + + @Override + protected String getDatabaseName() { + return "test"; + } + + @Override + public MongoClient mongo() throws Exception { + return new Fongo(getDatabaseName()).getMongo(); + } +} \ No newline at end of file diff --git a/webgoat-container/src/test/resources/application-test.properties b/webgoat-container/src/test/resources/application-test.properties new file mode 100644 index 000000000..da678e27b --- /dev/null +++ b/webgoat-container/src/test/resources/application-test.properties @@ -0,0 +1 @@ +webgoat.user.directory=/tmp/ \ No newline at end of file diff --git a/webgoat-lessons/bypass-restrictions/pom.xml b/webgoat-lessons/bypass-restrictions/pom.xml new file mode 100755 index 000000000..8775fdbd5 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + bypass-restrictions + jar + + org.owasp.webgoat.lesson + webgoat-lessons-parent + 8.0-SNAPSHOT + + diff --git a/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictions.java b/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictions.java new file mode 100755 index 000000000..21e522a22 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictions.java @@ -0,0 +1,63 @@ +package org.owasp.webgoat.plugin; + +import com.beust.jcommander.internal.Lists; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.NewLesson; + +import java.util.List; + +/** + * ************************************************************************************************ + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + *

+ * Copyright (c) 2002 - 20014 Bruce Mayhew + *

+ * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + *

+ * Getting Source ============== + *

+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + *

+ * + * @author WebGoat + * @version $Id: $Id + * @since October 12, 2016 + */ +public class BypassRestrictions extends NewLesson { + @Override + public Category getDefaultCategory() { + return Category.CLIENT_SIDE; + } + + @Override + public List getHints() { + return Lists.newArrayList(); + } + + @Override + public Integer getDefaultRanking() { + return 2; + } + + @Override + public String getTitle() { + return "bypass-restrictions.title"; + } + + @Override + public String getId() { + return "BypassRestrictions"; + } +} diff --git a/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictionsFieldRestrictions.java b/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictionsFieldRestrictions.java new file mode 100755 index 000000000..b916019f8 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictionsFieldRestrictions.java @@ -0,0 +1,74 @@ +package org.owasp.webgoat.plugin; + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * ************************************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository + * for free software projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +@AssignmentPath("/BypassRestrictions/FieldRestrictions") +public class BypassRestrictionsFieldRestrictions extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String select, @RequestParam String radio, @RequestParam String checkbox, @RequestParam String shortInput) throws IOException { + if (select.toString().equals("option1") || select.toString().equals("option2")) { + return trackProgress(failed().build()); + } + if (radio.toString().equals("option1") || radio.toString().equals("option2")) { + return trackProgress(failed().build()); + } + if (checkbox.toString().equals("on") || checkbox.toString().equals("off")) { + return trackProgress(failed().build()); + } + if (shortInput.toString().length() <= 5) { + return trackProgress(failed().build()); + } + /*if (disabled == null) { + return trackProgress(failed().build()); + } + if (submit.toString().equals("submit")) { + return trackProgress(failed().build()); + }*/ + return trackProgress(success().build()); + } +} diff --git a/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidation.java b/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidation.java new file mode 100644 index 000000000..7eaefb129 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidation.java @@ -0,0 +1,87 @@ +package org.owasp.webgoat.plugin; + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * ************************************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository + * for free software projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +@AssignmentPath("/BypassRestrictions/frontendValidation") +public class BypassRestrictionsFrontendValidation extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String field1, @RequestParam String field2, @RequestParam String field3, @RequestParam String field4, @RequestParam String field5, @RequestParam String field6, @RequestParam String field7, @RequestParam Integer error) throws IOException { + String regex1="^[a-z]{3}$"; + String regex2="^[0-9]{3}$"; + String regex3="^[a-zA-Z0-9 ]*$"; + String regex4="^(one|two|three|four|five|six|seven|eight|nine)$"; + String regex5="^\\d{5}$"; + String regex6="^\\d{5}(-\\d{4})?$"; + String regex7="^[2-9]\\d{2}-?\\d{3}-?\\d{4}$"; + if (error>0) { + return trackProgress(failed().build()); + } + if (field1.matches(regex1)) { + return trackProgress(failed().build()); + } + if (field2.matches(regex2)) { + return trackProgress(failed().build()); + } + if (field3.matches(regex3)) { + return trackProgress(failed().build()); + } + if (field4.matches(regex4)) { + return trackProgress(failed().build()); + } + if (field5.matches(regex5)) { + return trackProgress(failed().build()); + } + if (field6.matches(regex6)) { + return trackProgress(failed().build()); + } + if (field7.matches(regex7)) { + return trackProgress(failed().build()); + } + return trackProgress(success().build()); + } +} diff --git a/webgoat-lessons/bypass-restrictions/src/main/resources/html/BypassRestrictions.html b/webgoat-lessons/bypass-restrictions/src/main/resources/html/BypassRestrictions.html new file mode 100755 index 000000000..c27984c4f --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/resources/html/BypassRestrictions.html @@ -0,0 +1,126 @@ + + + + +

+ + +
+
+ +
+ +
+
+
+
+ +
Select field with two possible values
+ +
Radio button with two possible values
+ Option 1
+ Option 2
+
Checkbox: value either on or off
+ Checkbox +
Input restricted to max 5 characters
+ +
Disabled input field
+ + +
+
+
+
+
+ +
+
+
+
+ +
+
+ Field 1: exactly three lowercase characters(^[a-z]{3}$) +
+
+ +
+

+
Field 2: exactly three digits(^[0-9]{3}$)
+
+ +
+

+
Field 3: letters, numbers, and space only(^[a-zA-Z0-9 ]*$)
+
+ +
+

+
Field 4: enumeration of numbers (^(one|two|three|four|five|six|seven|eight|nine)$)
+
+ +
+

+
Field 5: simple zip code (^\d{5}$)
+
+ +
+

+
Field 6: zip with optional dash four (^\d{5}(-\d{4})?$)
+
+ +
+

+
Field 7: US phone number with or without dashes (^[2-9]\d{2}-?\d{3}-?\d{4}$)
+
+ +
+ +

+
+ + +
+
+
+
+
+
+ diff --git a/webgoat-lessons/bypass-restrictions/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/bypass-restrictions/src/main/resources/i18n/WebGoatLabels.properties new file mode 100755 index 000000000..bff117c72 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/resources/i18n/WebGoatLabels.properties @@ -0,0 +1,4 @@ +bypass-restrictions.title=Bypass front-end restrictions + +bypass-restrictions.intercept.success=Well done, you intercepted the request as expected +bypass-restrictions.intercept.failure=Please try again. Make sure to make all the changes. And case sensitivity may matter ... or not, you never know! diff --git a/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FieldRestrictions.adoc b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FieldRestrictions.adoc new file mode 100755 index 000000000..4d103d6b3 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FieldRestrictions.adoc @@ -0,0 +1,6 @@ +== Field Restrictions +In most browsers, client has complete or almost complete control over HTML part +of the webpage. They can alter values or restrictions to fit their preference. + +=== Task +Send a request that bypasses restrictions of all four of these fields diff --git a/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FrontendValidation.adoc b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FrontendValidation.adoc new file mode 100644 index 000000000..67b4dd857 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FrontendValidation.adoc @@ -0,0 +1,9 @@ +== Validation + +Often, there is some mechanism in place to prevent users from sending altered +field values to server, such as validation before sending. Most of popular browsers +such as Chrome don't allow editing scripts during runtime. We will have to circumvent +the validation some other way. + +=== Task +Send a request that does not fit the regular expression above the field in all fields. diff --git a/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_Intro.adoc b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_Intro.adoc new file mode 100755 index 000000000..e75483bc8 --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_Intro.adoc @@ -0,0 +1,11 @@ +== Concept + +Users have a great degree of control over the front-end of the web application. +They can alter HTML code, sometimes also scripts. This is why +apps that require certain format of input should also validate on server-side. + +== Goals + +* The user should have a basic knowledge of HTML +* The user should be able to tamper a request before sending (with proxy or other tool) +* The user will be able to tamper with field restrictions and bypass client-side validation diff --git a/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java b/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java new file mode 100644 index 000000000..8fb0657fa --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java @@ -0,0 +1,76 @@ +package org.owasp.webgoat.plugin; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 6/16/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class BypassRestrictionsFrontendValidationTest extends LessonTest { + + @Before + public void setup() throws Exception { + when(webSession.getCurrentLesson()).thenReturn(new BypassRestrictions()); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void noChangesShouldNotPassTheLesson() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation") + .param("field1", "abc") + .param("field2", "123") + .param("field3", "abc ABC 123") + .param("field4", "seven") + .param("field5", "01101") + .param("field6", "90201 1111") + .param("field7", "301-604-4882") + .param("error", "2")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false))); + } + + @Test + public void bypassAllFieldShouldPass() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation") + .param("field1", "abcd") + .param("field2", "1234") + .param("field3", "abc $ABC 123") + .param("field4", "ten") + .param("field5", "01101AA") + .param("field6", "90201 1111AA") + .param("field7", "301-604-4882$$") + .param("error", "0")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true))); + } + + @Test + public void notBypassingAllFieldShouldNotPass() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation") + .param("field1", "abc") + .param("field2", "1234") + .param("field3", "abc $ABC 123") + .param("field4", "ten") + .param("field5", "01101AA") + .param("field6", "90201 1111AA") + .param("field7", "301-604-4882AA") + .param("error", "0")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false))); + } + + +} \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_introduction.adoc b/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_introduction.adoc index 03774d6f7..d6037af18 100644 --- a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_introduction.adoc +++ b/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_introduction.adoc @@ -1,5 +1,11 @@ === Welcome to the WebGoat challenge (CTF) +==== Introduction + +The challenges contain more a CTF like lessons where we do not provide any explanations what you need to do, no hints +will be provided. You can use these challenges in a CTF style where you can run WebGoat on one server and all +participants can join and hack the challenges. A scoreboard is available at http://localhost:8080/WebGoat/scoreboard + :hardbreaks: In this CTF you will need to solve a couple of challenges, each challenge will give you a flag which you will need to post in order to gain points. diff --git a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/ClientSideFiltering.java b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/ClientSideFiltering.java index feff55a0f..98a7c4172 100644 --- a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/ClientSideFiltering.java +++ b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/ClientSideFiltering.java @@ -39,7 +39,7 @@ public class ClientSideFiltering extends NewLesson { @Override public Category getDefaultCategory() { - return Category.AJAX_SECURITY; + return Category.CLIENT_SIDE; } @Override diff --git a/webgoat-lessons/html-tampering/pom.xml b/webgoat-lessons/html-tampering/pom.xml new file mode 100755 index 000000000..44d24a8ce --- /dev/null +++ b/webgoat-lessons/html-tampering/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + html-tampering + jar + + org.owasp.webgoat.lesson + webgoat-lessons-parent + 8.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + 4.1.3.RELEASE + test + + + junit + junit + ${junit.version} + jar + test + + + + + diff --git a/webgoat-lessons/html-tampering/src/main/java/org/owasp/webgoat/plugin/HtmlTampering.java b/webgoat-lessons/html-tampering/src/main/java/org/owasp/webgoat/plugin/HtmlTampering.java new file mode 100755 index 000000000..a03dddd1b --- /dev/null +++ b/webgoat-lessons/html-tampering/src/main/java/org/owasp/webgoat/plugin/HtmlTampering.java @@ -0,0 +1,63 @@ +package org.owasp.webgoat.plugin; + +import com.beust.jcommander.internal.Lists; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.NewLesson; + +import java.util.List; + +/** + * ************************************************************************************************ + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + *

+ * Copyright (c) 2002 - 20014 Bruce Mayhew + *

+ * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + *

+ * Getting Source ============== + *

+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + *

+ * + * @author WebGoat + * @version $Id: $Id + * @since October 12, 2016 + */ +public class HtmlTampering extends NewLesson { + @Override + public Category getDefaultCategory() { + return Category.CLIENT_SIDE; + } + + @Override + public List getHints() { + return Lists.newArrayList(); + } + + @Override + public Integer getDefaultRanking() { + return 3; + } + + @Override + public String getTitle() { + return "html-tampering.title"; + } + + @Override + public String getId() { + return "HtmlTampering"; + } +} diff --git a/webgoat-lessons/html-tampering/src/main/java/org/owasp/webgoat/plugin/HtmlTamperingTask.java b/webgoat-lessons/html-tampering/src/main/java/org/owasp/webgoat/plugin/HtmlTamperingTask.java new file mode 100755 index 000000000..2f62612c0 --- /dev/null +++ b/webgoat-lessons/html-tampering/src/main/java/org/owasp/webgoat/plugin/HtmlTamperingTask.java @@ -0,0 +1,60 @@ +package org.owasp.webgoat.plugin; + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentHints; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.io.IOException; + +/** + * ************************************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository + * for free software projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +@AssignmentPath("/HtmlTampering/task") +@AssignmentHints({ "hint1", "hint2", "hint3"}) +public class HtmlTamperingTask extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String QTY, @RequestParam String Total) throws IOException { + if (Float.parseFloat(QTY) * 2999.99 > Float.parseFloat(Total) + 1) { + return trackProgress(success().feedback("html-tampering.tamper.success").build()); + } + return trackProgress(failed().feedback("html-tampering.tamper.failure").build()); + } +} diff --git a/webgoat-lessons/html-tampering/src/main/resources/html/HtmlTampering.html b/webgoat-lessons/html-tampering/src/main/resources/html/HtmlTampering.html new file mode 100755 index 000000000..b21ba255a --- /dev/null +++ b/webgoat-lessons/html-tampering/src/main/resources/html/HtmlTampering.html @@ -0,0 +1,149 @@ + + + + +

+
+
+ +
+ +
+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProductQuantityPriceTotal 
+
+ + +
+

55'' M5510 White Full HD Smart TV +

+
by Samsung
+ Status: In Stock +
+
+
+ + 2999.99$2999.99 + +
     
Subtotal
$2999.99
+
     
Shipping costs
$0.00
+
     

Total

$2999.99

+
      + + +
+ +
+
+
+
+
+
+

+
+
+
+
+
+
+
+ diff --git a/webgoat-lessons/html-tampering/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/html-tampering/src/main/resources/i18n/WebGoatLabels.properties new file mode 100755 index 000000000..24ae7a2ed --- /dev/null +++ b/webgoat-lessons/html-tampering/src/main/resources/i18n/WebGoatLabels.properties @@ -0,0 +1,9 @@ +html-tampering.title=HTML tampering + + +html-tampering.tamper.success=Well done, you just bought a TV at a discount +html-tampering.tamper.failure=This is too expensive... You need to buy at a cheaper cost! + +hint1=Try to change the number of items and see what is happening +hint2=Is the price part of the HTML request? +hint3=Intercept the request and manipulate the price before submitting it. diff --git a/webgoat-lessons/html-tampering/src/main/resources/images/samsung.jpg b/webgoat-lessons/html-tampering/src/main/resources/images/samsung.jpg new file mode 100644 index 000000000..dd15a64cf Binary files /dev/null and b/webgoat-lessons/html-tampering/src/main/resources/images/samsung.jpg differ diff --git a/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Intro.adoc b/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Intro.adoc new file mode 100755 index 000000000..998433314 --- /dev/null +++ b/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Intro.adoc @@ -0,0 +1,8 @@ + +== Concept +Browsers generally offer many options of editing the displayed content. Developers +therefore must be aware that the values sent by the user may have been tampered with. + +== Goals +* The user should have a basic understanding of HTML +* The user will be able to exploit editing front end of website diff --git a/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Mitigation.adoc b/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Mitigation.adoc new file mode 100755 index 000000000..22eb72fa2 --- /dev/null +++ b/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Mitigation.adoc @@ -0,0 +1,14 @@ +=== Mitigation + +In this simple example you noticed that the price is calculated server side and send to the server. The server +accepted the input as a given and did not calculate the price again. One of the mitigations in this case is to look up +the price of the television in your database and calculate the total price again. + + +In a real application you should never rely on client side validation it is important to verify all the input +send by the client. Always remember: **NEVER TRUST INPUT SEND BY A CLIENT.** + +'''' +==== References + +https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet diff --git a/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Task.adoc b/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Task.adoc new file mode 100755 index 000000000..ae07f6891 --- /dev/null +++ b/webgoat-lessons/html-tampering/src/main/resources/lessonPlans/en/HtmlTampering_Task.adoc @@ -0,0 +1,2 @@ +=== Try it yourself +In an online store you ordered a new TV, try to buy one or more TVs for a lower price. diff --git a/webgoat-lessons/idor/pom.xml b/webgoat-lessons/idor/pom.xml index 21437a0c9..2ddeee2d1 100644 --- a/webgoat-lessons/idor/pom.xml +++ b/webgoat-lessons/idor/pom.xml @@ -9,28 +9,4 @@ 8.0-SNAPSHOT - - - - org.asciidoctor - asciidoctor-maven-plugin - 1.5.3 - - - - output-html - generate-resources - - process-asciidoc - - - html - src/main/resources/lessonPlans/en/ - - - - - - - \ No newline at end of file diff --git a/webgoat-lessons/insecure-login/pom.xml b/webgoat-lessons/insecure-login/pom.xml new file mode 100755 index 000000000..aac10ceef --- /dev/null +++ b/webgoat-lessons/insecure-login/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + insecure-login + jar + + org.owasp.webgoat.lesson + webgoat-lessons-parent + 8.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + 4.1.3.RELEASE + test + + + junit + junit + ${junit.version} + jar + test + + + + + diff --git a/webgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/plugin/InsecureLogin.java b/webgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/plugin/InsecureLogin.java new file mode 100755 index 000000000..6d8108e63 --- /dev/null +++ b/webgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/plugin/InsecureLogin.java @@ -0,0 +1,63 @@ +package org.owasp.webgoat.plugin; + +import com.beust.jcommander.internal.Lists; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.NewLesson; + +import java.util.List; + +/** + * ************************************************************************************************ + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + *

+ * Copyright (c) 2002 - 20014 Bruce Mayhew + *

+ * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + *

+ * Getting Source ============== + *

+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + *

+ * + * @author WebGoat + * @version $Id: $Id + * @since October 12, 2016 + */ +public class InsecureLogin extends NewLesson { + @Override + public Category getDefaultCategory() { + return Category.INSECURE_COMMUNICATION; + } + + @Override + public List getHints() { + return Lists.newArrayList(); + } + + @Override + public Integer getDefaultRanking() { + return 1; + } + + @Override + public String getTitle() { + return "insecure-login.title"; + } + + @Override + public String getId() { + return "InsecureLogin"; + } +} diff --git a/webgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/plugin/InsecureLoginTask.java b/webgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/plugin/InsecureLoginTask.java new file mode 100755 index 000000000..e5895f39c --- /dev/null +++ b/webgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/plugin/InsecureLoginTask.java @@ -0,0 +1,59 @@ +package org.owasp.webgoat.plugin; + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * ************************************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository + * for free software projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +@AssignmentPath("/InsecureLogin/task") +public class InsecureLoginTask extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String username, @RequestParam String password) throws IOException { + if (username.toString().equals("CaptainJack") && password.toString().equals("BlackPearl")) { + return trackProgress(success().build()); + } + return trackProgress(failed().build()); + } +} diff --git a/webgoat-lessons/insecure-login/src/main/resources/html/InsecureLogin.html b/webgoat-lessons/insecure-login/src/main/resources/html/InsecureLogin.html new file mode 100755 index 000000000..04798c65f --- /dev/null +++ b/webgoat-lessons/insecure-login/src/main/resources/html/InsecureLogin.html @@ -0,0 +1,45 @@ + + + + +

+ + +
+
+ +
+ +
+
+
+ +
+ + + +
+

+
+ + + + + +
+
+
+
+
+ diff --git a/webgoat-lessons/insecure-login/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/insecure-login/src/main/resources/i18n/WebGoatLabels.properties new file mode 100755 index 000000000..dc4f1874f --- /dev/null +++ b/webgoat-lessons/insecure-login/src/main/resources/i18n/WebGoatLabels.properties @@ -0,0 +1,4 @@ +insecure-login.title=Insecure Login + +insecure-login.intercept.success=Welcome, CaptainJack! +insecure-login.intercept.failure=Wrong username or password diff --git a/webgoat-lessons/insecure-login/src/main/resources/js/credentials.js b/webgoat-lessons/insecure-login/src/main/resources/js/credentials.js new file mode 100755 index 000000000..b7387c623 --- /dev/null +++ b/webgoat-lessons/insecure-login/src/main/resources/js/credentials.js @@ -0,0 +1,6 @@ +function submit_secret_credentials() { + var xhttp = new XMLHttpRequest(); + xhttp['open']('POST', '#attack/307/100', true); + //sending the request is obfuscated, to descourage js reading + var _0xb7f9=["\x43\x61\x70\x74\x61\x69\x6E\x4A\x61\x63\x6B","\x42\x6C\x61\x63\x6B\x50\x65\x61\x72\x6C","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x73\x65\x6E\x64"];xhttp[_0xb7f9[3]](JSON[_0xb7f9[2]]({username:_0xb7f9[0],password:_0xb7f9[1]})) +} \ No newline at end of file diff --git a/webgoat-lessons/insecure-login/src/main/resources/lessonPlans/en/InsecureLogin_Intro.adoc b/webgoat-lessons/insecure-login/src/main/resources/lessonPlans/en/InsecureLogin_Intro.adoc new file mode 100755 index 000000000..f4fac8471 --- /dev/null +++ b/webgoat-lessons/insecure-login/src/main/resources/lessonPlans/en/InsecureLogin_Intro.adoc @@ -0,0 +1,7 @@ + +== Concept +Encryption is a very inportant tool for secure communication. In this lesson, we will find out, why it should always be employed when sending sensitive data. + +== Goals +* The user should have a basic understanding of packet sniffer usage +* The user will be able to intercept and read an unencrypted requests \ No newline at end of file diff --git a/webgoat-lessons/insecure-login/src/main/resources/lessonPlans/en/InsecureLogin_Task.adoc b/webgoat-lessons/insecure-login/src/main/resources/lessonPlans/en/InsecureLogin_Task.adoc new file mode 100755 index 000000000..e6e7fea56 --- /dev/null +++ b/webgoat-lessons/insecure-login/src/main/resources/lessonPlans/en/InsecureLogin_Task.adoc @@ -0,0 +1,4 @@ +=== Let's try +Click the "log in" button to send a request containing login credentials of another user. +Then, write these credentials into the appropriate fields and submit to confirm. +Try using a packet sniffer to intercept the request. diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml index 51babeab6..5137709b1 100644 --- a/webgoat-lessons/pom.xml +++ b/webgoat-lessons/pom.xml @@ -14,16 +14,21 @@ + bypass-restrictions challenge client-side-filtering cross-site-scripting + html-tampering http-basics http-proxies + insecure-login jwt sql-injection xxe idor vulnerable-components + + @@ -33,11 +38,19 @@ ${project.version} provided jar + + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + + - - - + + + org.owasp.webgoat @@ -45,6 +58,14 @@ ${project.version} tests test + + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + + junit @@ -70,6 +91,12 @@ 4.1.3.RELEASE test + + com.github.fakemongo + fongo + 2.1.0 + test + org.owasp.encoder encoder @@ -119,6 +146,6 @@ - - + + diff --git a/webgoat-lessons/sol.txt b/webgoat-lessons/sol.txt index 9fa1aa3a4..0d549b92b 100644 --- a/webgoat-lessons/sol.txt +++ b/webgoat-lessons/sol.txt @@ -14,7 +14,7 @@ Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from ## XXE ## -Simple ]> &root;test +Simple - ]>&root; Modern Rest Framework - change content type to: Content-Type: application/xml && ]> &root;test diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java deleted file mode 100644 index c7dbb59b8..000000000 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java +++ /dev/null @@ -1,220 +0,0 @@ - -package org.owasp.webgoat.plugin; - -import org.owasp.webgoat.assignments.AssignmentEndpoint; -import org.owasp.webgoat.assignments.AssignmentPath; -import org.owasp.webgoat.assignments.AttackResult; -import org.owasp.webgoat.session.DatabaseUtilities; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.sql.*; - - - -/*************************************************************************************************** - * - * - * This file is part of WebGoat, an Open Web Application Security Project utility. For details, - * please see http://www.owasp.org/ - * - * Copyright (c) 2002 - 20014 Bruce Mayhew - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Getting Source ============== - * - * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software - * projects. - * - * For details, please see http://webgoat.github.io - * - * @author Bruce Mayhew WebGoat - * @created October 28, 2003 - */ -@AssignmentPath("/SqlInjection/attack5a") -public class SqlInjectionLesson5a extends AssignmentEndpoint { - - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String account, HttpServletRequest request) throws IOException { - return injectableQuery(account); - } - - protected AttackResult injectableQuery(String accountName) - { - try - { - Connection connection = DatabaseUtilities.getConnection(getWebSession()); - String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'"; - - try - { - Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - ResultSet results = statement.executeQuery(query); - - if ((results != null) && (results.first() == true)) - { - ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); - - output.append(writeTable(results, resultsMetaData)); - results.last(); - - // If they get back more than one user they succeeded - if (results.getRow() >= 6) - { - return trackProgress(success().feedback("sql-injection.5a.success").feedbackArgs(output.toString()).build()); - } else { - return trackProgress(failed().output(output.toString()).build()); - } - } - else - { - return trackProgress(failed().feedback("sql-injection.5a.no.results").build()); - - } - } catch (SQLException sqle) - { - - return trackProgress(failed().output(sqle.getMessage()).build()); - } - } catch (Exception e) - { - e.printStackTrace(); - return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); - } - } - - public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException, - SQLException - { - int numColumns = resultsMetaData.getColumnCount(); - results.beforeFirst(); - StringBuffer t = new StringBuffer(); - t.append("

"); - - if (results.next()) - { - for (int i = 1; i < (numColumns + 1); i++) - { - t.append(resultsMetaData.getColumnName(i)); - t.append(", "); - } - - t.append("
"); - results.beforeFirst(); - - while (results.next()) - { - - for (int i = 1; i < (numColumns + 1); i++) - { - t.append(results.getString(i)); - t.append(", "); - } - - t.append("
"); - } - - } - else - { - t.append ("Query Successful; however no data was returned from this query."); - } - - t.append("

"); - return (t.toString()); - } -// -// protected Element parameterizedQuery(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// -// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage")); -// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart")) -// { -// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1"); -// return (injectableQuery(s)); -// } -// -// ec.addElement(new BR()); -// -// try -// { -// Connection connection = DatabaseUtilities.getConnection(s); -// -// ec.addElement(makeAccountLine(s)); -// -// String query = "SELECT * FROM user_data WHERE last_name = ?"; -// ec.addElement(new PRE(query)); -// -// try -// { -// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, -// ResultSet.CONCUR_READ_ONLY); -// statement.setString(1, accountName); -// ResultSet results = statement.executeQuery(); -// -// if ((results != null) && (results.first() == true)) -// { -// ResultSetMetaData resultsMetaData = results.getMetaData(); -// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData)); -// results.last(); -// -// // If they get back more than one user they succeeded -// if (results.getRow() >= 6) -// { -// makeSuccess(s); -// } -// } -// else -// { -// ec.addElement(getLabelManager().get("NoResultsMatched")); -// } -// } catch (SQLException sqle) -// { -// ec.addElement(new P().addElement(sqle.getMessage())); -// } -// } catch (Exception e) -// { -// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName()); -// e.printStackTrace(); -// } -// -// return (ec); -// } -// -// protected Element makeAccountLine(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName"))); -// -// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name"); -// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString()); -// ec.addElement(input); -// -// Element b = ECSFactory.makeButton(getLabelManager().get("Go!")); -// ec.addElement(b); -// -// return ec; -// -// } - - - -} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java deleted file mode 100644 index c21a9e3e6..000000000 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java +++ /dev/null @@ -1,224 +0,0 @@ -package org.owasp.webgoat.plugin; - - - -import org.owasp.webgoat.assignments.AssignmentEndpoint; -import org.owasp.webgoat.assignments.AssignmentPath; -import org.owasp.webgoat.assignments.AttackResult; -import org.owasp.webgoat.session.DatabaseUtilities; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.sql.*; - - - -/*************************************************************************************************** - * - * - * This file is part of WebGoat, an Open Web Application Security Project utility. For details, - * please see http://www.owasp.org/ - * - * Copyright (c) 2002 - 20014 Bruce Mayhew - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Getting Source ============== - * - * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software - * projects. - * - * For details, please see http://webgoat.github.io - * - * @author Bruce Mayhew WebGoat - * @created October 28, 2003 - */ -@AssignmentPath("/SqlInjection/attack5b") -public class SqlInjectionLesson5b extends AssignmentEndpoint { - - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String userid, HttpServletRequest request) throws IOException { - return injectableQuery(userid); - - } - - protected AttackResult injectableQuery(String accountName) - { - try - { - Connection connection = DatabaseUtilities.getConnection(getWebSession()); - String query = "SELECT * FROM user_data WHERE userid = " + accountName; - - try - { - Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - ResultSet results = statement.executeQuery(query); - - if ((results != null) && (results.first() == true)) - { - ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); - - output.append(writeTable(results, resultsMetaData)); - results.last(); - - // If they get back more than one user they succeeded - if (results.getRow() >= 6) - { - return trackProgress(success().feedback("sql-injection.5b.success").feedbackArgs(output.toString()).build()); - } else { - return trackProgress(failed().output(output.toString()).build()); - } - - } - else - { - return trackProgress(failed().feedback("sql-injection.5b.no.results").build()); - -// output.append(getLabelManager().get("NoResultsMatched")); - } - } catch (SQLException sqle) - { - - return trackProgress(failed().output(sqle.getMessage()).build()); - } - } catch (Exception e) - { - e.printStackTrace(); - return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); - } - } - - public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException, - SQLException - { - int numColumns = resultsMetaData.getColumnCount(); - results.beforeFirst(); - StringBuffer t = new StringBuffer(); - t.append("

"); - - if (results.next()) - { - for (int i = 1; i < (numColumns + 1); i++) - { - t.append(resultsMetaData.getColumnName(i)); - t.append(", "); - } - - t.append("
"); - results.beforeFirst(); - - while (results.next()) - { - - for (int i = 1; i < (numColumns + 1); i++) - { - t.append(results.getString(i)); - t.append(", "); - } - - t.append("
"); - } - - } - else - { - t.append ("Query Successful; however no data was returned from this query."); - } - - t.append("

"); - return (t.toString()); - } -// -// protected Element parameterizedQuery(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// -// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage")); -// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart")) -// { -// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1"); -// return (injectableQuery(s)); -// } -// -// ec.addElement(new BR()); -// -// try -// { -// Connection connection = DatabaseUtilities.getConnection(s); -// -// ec.addElement(makeAccountLine(s)); -// -// String query = "SELECT * FROM user_data WHERE last_name = ?"; -// ec.addElement(new PRE(query)); -// -// try -// { -// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, -// ResultSet.CONCUR_READ_ONLY); -// statement.setString(1, accountName); -// ResultSet results = statement.executeQuery(); -// -// if ((results != null) && (results.first() == true)) -// { -// ResultSetMetaData resultsMetaData = results.getMetaData(); -// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData)); -// results.last(); -// -// // If they get back more than one user they succeeded -// if (results.getRow() >= 6) -// { -// makeSuccess(s); -// } -// } -// else -// { -// ec.addElement(getLabelManager().get("NoResultsMatched")); -// } -// } catch (SQLException sqle) -// { -// ec.addElement(new P().addElement(sqle.getMessage())); -// } -// } catch (Exception e) -// { -// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName()); -// e.printStackTrace(); -// } -// -// return (ec); -// } -// -// protected Element makeAccountLine(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName"))); -// -// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name"); -// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString()); -// ec.addElement(input); -// -// Element b = ECSFactory.makeButton(getLabelManager().get("Go!")); -// ec.addElement(b); -// -// return ec; -// -// } - - - -} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java deleted file mode 100644 index 9e0950c12..000000000 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java +++ /dev/null @@ -1,223 +0,0 @@ - -package org.owasp.webgoat.plugin; - -import org.owasp.webgoat.assignments.AssignmentEndpoint; -import org.owasp.webgoat.assignments.AssignmentPath; -import org.owasp.webgoat.assignments.AttackResult; -import org.owasp.webgoat.session.DatabaseUtilities; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.sql.*; - - - -/*************************************************************************************************** - * - * - * This file is part of WebGoat, an Open Web Application Security Project utility. For details, - * please see http://www.owasp.org/ - * - * Copyright (c) 2002 - 20014 Bruce Mayhew - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Getting Source ============== - * - * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software - * projects. - * - * For details, please see http://webgoat.github.io - * - * @author Bruce Mayhew WebGoat - * @created October 28, 2003 - */ -@AssignmentPath("/SqlInjection/attack6a") -public class SqlInjectionLesson6a extends AssignmentEndpoint { - - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String userid_6a, HttpServletRequest request) throws IOException { - return injectableQuery(userid_6a); - // The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- - - } - - protected AttackResult injectableQuery(String accountName) - { - try - { - Connection connection = DatabaseUtilities.getConnection(getWebSession()); - String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'"; - - try - { - Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - ResultSet results = statement.executeQuery(query); - - if ((results != null) && (results.first() == true)) - { - ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); - - output.append(writeTable(results, resultsMetaData)); - results.last(); - - // If they get back more than one user they succeeded - if (results.getRow() >= 5) - { - return trackProgress(success().feedback("sql-injection.6a.success").feedbackArgs(output.toString()).build()); - } else { - return trackProgress(failed().output(output.toString()).build()); - } - - } - else - { - return trackProgress(failed().feedback("sql-injection.6a.no.results").build()); - - } - } catch (SQLException sqle) - { - - return trackProgress(failed().output(sqle.getMessage()).build()); - } - } catch (Exception e) - { - e.printStackTrace(); - return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); - } - } - - public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException, - SQLException - { - int numColumns = resultsMetaData.getColumnCount(); - results.beforeFirst(); - StringBuffer t = new StringBuffer(); - t.append("

"); - - if (results.next()) - { - for (int i = 1; i < (numColumns + 1); i++) - { - t.append(resultsMetaData.getColumnName(i)); - t.append(", "); - } - - t.append("
"); - results.beforeFirst(); - - while (results.next()) - { - - for (int i = 1; i < (numColumns + 1); i++) - { - t.append(results.getString(i)); - t.append(", "); - } - - t.append("
"); - } - - } - else - { - t.append ("Query Successful; however no data was returned from this query."); - } - - t.append("

"); - return (t.toString()); - } -// -// protected Element parameterizedQuery(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// -// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage")); -// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart")) -// { -// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1"); -// return (injectableQuery(s)); -// } -// -// ec.addElement(new BR()); -// -// try -// { -// Connection connection = DatabaseUtilities.getConnection(s); -// -// ec.addElement(makeAccountLine(s)); -// -// String query = "SELECT * FROM user_data WHERE last_name = ?"; -// ec.addElement(new PRE(query)); -// -// try -// { -// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, -// ResultSet.CONCUR_READ_ONLY); -// statement.setString(1, accountName); -// ResultSet results = statement.executeQuery(); -// -// if ((results != null) && (results.first() == true)) -// { -// ResultSetMetaData resultsMetaData = results.getMetaData(); -// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData)); -// results.last(); -// -// // If they get back more than one user they succeeded -// if (results.getRow() >= 6) -// { -// makeSuccess(s); -// } -// } -// else -// { -// ec.addElement(getLabelManager().get("NoResultsMatched")); -// } -// } catch (SQLException sqle) -// { -// ec.addElement(new P().addElement(sqle.getMessage())); -// } -// } catch (Exception e) -// { -// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName()); -// e.printStackTrace(); -// } -// -// return (ec); -// } -// -// protected Element makeAccountLine(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName"))); -// -// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name"); -// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString()); -// ec.addElement(input); -// -// Element b = ECSFactory.makeButton(getLabelManager().get("Go!")); -// ec.addElement(b); -// -// return ec; -// -// } - - - -} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionAdvanced.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionAdvanced.java new file mode 100644 index 000000000..3df685705 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionAdvanced.java @@ -0,0 +1,63 @@ +package org.owasp.webgoat.plugin.advanced; + +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.NewLesson; + +import java.util.ArrayList; +import java.util.List; + +/** + * ************************************************************************************************ + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + *

+ * Copyright (c) 2002 - 20014 Bruce Mayhew + *

+ * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + *

+ * Getting Source ============== + *

+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + *

+ * + * @author WebGoat + * @version $Id: $Id + * @since October 12, 2016 + */ +public class SqlInjectionAdvanced extends NewLesson { + @Override + public Category getDefaultCategory() { + return Category.INJECTION; + } + + @Override + public List getHints() { + return new ArrayList<>(); + } + + @Override + public Integer getDefaultRanking() { + return 1; + } + + @Override + public String getTitle() { + return "SQL Injection (advanced)"; + } + + @Override + public String getId() { + return "SqlInjectionAdvanced"; + } +} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java new file mode 100644 index 000000000..a81fa8299 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java @@ -0,0 +1,136 @@ +package org.owasp.webgoat.plugin.advanced; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.sql.*; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +/** + * @author nbaars + * @since 4/8/17. + */ +@AssignmentPath("SqlInjection/challenge") +@Slf4j +public class SqlInjectionChallenge extends AssignmentEndpoint { + + private static final String PASSWORD_TOM = "thisisasecretfortomonly"; + //Make it more random at runtime (good luck guessing) + private static final String USERS_TABLE_NAME = "challenge_users_6" + RandomStringUtils.randomAlphabetic(16); + + @Autowired + private WebSession webSession; + + public SqlInjectionChallenge() { + log.info("Challenge 6 tablename is: {}", USERS_TABLE_NAME); + } + + @PutMapping //assignment path is bounded to class so we use different http method :-) + @ResponseBody + public AttackResult registerNewUser(@RequestParam String username_reg, @RequestParam String email_reg, @RequestParam String password_reg) throws Exception { + AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg); + + if (attackResult == null) { + Connection connection = DatabaseUtilities.getConnection(webSession); + checkDatabase(connection); + + String checkUserQuery = "select userid from " + USERS_TABLE_NAME + " where userid = '" + username_reg + "'"; + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(checkUserQuery); + + if (resultSet.next()) { + attackResult = failed().feedback("user.exists").feedbackArgs(username_reg).build(); + } else { + PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO " + USERS_TABLE_NAME + " VALUES (?, ?, ?)"); + preparedStatement.setString(1, username_reg); + preparedStatement.setString(2, email_reg); + preparedStatement.setString(3, password_reg); + preparedStatement.execute(); + attackResult = success().feedback("user.created").feedbackArgs(username_reg).build(); + } + } + return attackResult; + } + + private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) { + if (StringUtils.isEmpty(username_reg) || StringUtils.isEmpty(email_reg) || StringUtils.isEmpty(password_reg)) { + return failed().feedback("input.invalid").build(); + } + if (username_reg.length() > 250 || email_reg.length() > 30 || password_reg.length() > 30) { + return failed().feedback("input.invalid").build(); + } + return null; + } + + @RequestMapping(method = POST) + @ResponseBody + public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception { + Connection connection = DatabaseUtilities.getConnection(webSession); + checkDatabase(connection); + + PreparedStatement statement = connection.prepareStatement("select password from " + USERS_TABLE_NAME + " where userid = ? and password = ?"); + statement.setString(1, username_login); + statement.setString(2, password_login); + ResultSet resultSet = statement.executeQuery(); + + if (resultSet.next() && "tom".equals(username_login)) { + return success().build(); + } else { + return failed().feedback("NoResultsMatched").build(); + } + } + + private void checkDatabase(Connection connection) throws SQLException { + try { + Statement statement = connection.createStatement(); + statement.execute("select 1 from " + USERS_TABLE_NAME); + } catch (SQLException e) { + createChallengeTable(connection); + } + } + + private void createChallengeTable(Connection connection) { + Statement statement = null; + try { + statement = connection.createStatement(); + String dropTable = "DROP TABLE " + USERS_TABLE_NAME; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + log.info("Delete failed, this does not point to an error table might not have been present..."); + } + log.debug("Challenge 6 - Creating tables for users {}", USERS_TABLE_NAME); + try { + String createTableStatement = "CREATE TABLE " + USERS_TABLE_NAME + + " (" + "userid varchar(250)," + + "email varchar(30)," + + "password varchar(30)" + + ")"; + statement.executeUpdate(createTableStatement); + + String insertData1 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('larry', 'larry@webgoat.org', 'larryknows')"; + String insertData2 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('tom', 'tom@webgoat.org', '" + PASSWORD_TOM + "')"; + String insertData3 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**')"; + String insertData4 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('eve', 'eve@webgoat.org', '**********')"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + statement.executeUpdate(insertData3); + statement.executeUpdate(insertData4); + } catch (SQLException e) { + log.error("Unable create table", e); + } + } + +} + diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjection.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjection.java similarity index 97% rename from webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjection.java rename to webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjection.java index 2ac3acc10..d5df3c88a 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjection.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjection.java @@ -1,4 +1,4 @@ -package org.owasp.webgoat.plugin; +package org.owasp.webgoat.plugin.introduction; import java.util.ArrayList; import java.util.List; diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java new file mode 100644 index 000000000..87a776d2f --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java @@ -0,0 +1,128 @@ + +package org.owasp.webgoat.plugin.introduction; + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentHints; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.io.IOException; +import java.sql.*; + + +/*************************************************************************************************** + * + * + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +@AssignmentPath("/SqlInjection/attack5a") +@AssignmentHints(value = {"SqlStringInjectionHint1", "SqlStringInjectionHint2", "SqlStringInjectionHint3", "SqlStringInjectionHint4"}) +public class SqlInjectionLesson5a extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String account) { + return injectableQuery(account); + } + + protected AttackResult injectableQuery(String accountName) { + try { + Connection connection = DatabaseUtilities.getConnection(getWebSession()); + String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'"; + + try { + Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement.executeQuery(query); + + if ((results != null) && (results.first())) { + ResultSetMetaData resultsMetaData = results.getMetaData(); + StringBuffer output = new StringBuffer(); + + output.append(writeTable(results, resultsMetaData)); + results.last(); + + // If they get back more than one user they succeeded + if (results.getRow() >= 6) { + return trackProgress(success().feedback("sql-injection.5a.success").feedbackArgs(output.toString()).build()); + } else { + return trackProgress(failed().output(output.toString()).build()); + } + } else { + return trackProgress(failed().feedback("sql-injection.5a.no.results").build()); + + } + } catch (SQLException sqle) { + + return trackProgress(failed().output(sqle.getMessage()).build()); + } + } catch (Exception e) { + return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); + } + } + + public static String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException, + SQLException { + int numColumns = resultsMetaData.getColumnCount(); + results.beforeFirst(); + StringBuffer t = new StringBuffer(); + t.append("

"); + + if (results.next()) { + for (int i = 1; i < (numColumns + 1); i++) { + t.append(resultsMetaData.getColumnName(i)); + t.append(", "); + } + + t.append("
"); + results.beforeFirst(); + + while (results.next()) { + + for (int i = 1; i < (numColumns + 1); i++) { + t.append(results.getString(i)); + t.append(", "); + } + + t.append("
"); + } + + } else { + t.append("Query Successful; however no data was returned from this query."); + } + + t.append("

"); + return (t.toString()); + } +} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5b.java new file mode 100644 index 000000000..deeaa7666 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5b.java @@ -0,0 +1,99 @@ +package org.owasp.webgoat.plugin.introduction; + + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentHints; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.sql.*; + + +/*************************************************************************************************** + * + * + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +@AssignmentPath("/SqlInjection/attack5b") +@AssignmentHints(value = {"SqlStringInjectionHint1", "SqlStringInjectionHint2", "SqlStringInjectionHint3", "SqlStringInjectionHint4"}) +public class SqlInjectionLesson5b extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String userid, HttpServletRequest request) throws IOException { + return injectableQuery(userid); + + } + + protected AttackResult injectableQuery(String accountName) { + try { + Connection connection = DatabaseUtilities.getConnection(getWebSession()); + String query = "SELECT * FROM user_data WHERE userid = " + accountName; + + try { + Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement.executeQuery(query); + + if ((results != null) && (results.first() == true)) { + ResultSetMetaData resultsMetaData = results.getMetaData(); + StringBuffer output = new StringBuffer(); + + output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData)); + results.last(); + + // If they get back more than one user they succeeded + if (results.getRow() >= 6) { + return trackProgress(success().feedback("sql-injection.5b.success").feedbackArgs(output.toString()).build()); + } else { + return trackProgress(failed().output(output.toString()).build()); + } + + } else { + return trackProgress(failed().feedback("sql-injection.5b.no.results").build()); + +// output.append(getLabelManager().get("NoResultsMatched")); + } + } catch (SQLException sqle) { + + return trackProgress(failed().output(sqle.getMessage()).build()); + } + } catch (Exception e) { + e.printStackTrace(); + return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); + } + } +} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6a.java new file mode 100644 index 000000000..136723f8d --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6a.java @@ -0,0 +1,97 @@ + +package org.owasp.webgoat.plugin.introduction; + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentHints; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.io.IOException; +import java.sql.*; + + +/*************************************************************************************************** + * + * + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +@AssignmentPath("/SqlInjection/attack6a") +@AssignmentHints(value = {"SqlStringInjectionHint5", "SqlStringInjectionHint6", "SqlStringInjectionHint7"}) +public class SqlInjectionLesson6a extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String userid_6a) throws IOException { + return injectableQuery(userid_6a); + // The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- + + } + + protected AttackResult injectableQuery(String accountName) { + try { + Connection connection = DatabaseUtilities.getConnection(getWebSession()); + String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'"; + + try { + Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement.executeQuery(query); + + if ((results != null) && (results.first())) { + ResultSetMetaData resultsMetaData = results.getMetaData(); + StringBuffer output = new StringBuffer(); + + output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData)); + results.last(); + + // If they get back more than one user they succeeded + if (results.getRow() >= 5) { + return trackProgress(success().feedback("sql-injection.6a.success").feedbackArgs(output.toString()).build()); + } else { + return trackProgress(failed().output(output.toString()).build()); + } + + } else { + return trackProgress(failed().feedback("sql-injection.6a.no.results").build()); + + } + } catch (SQLException sqle) { + return trackProgress(failed().output(sqle.getMessage()).build()); + } + } catch (Exception e) { + e.printStackTrace(); + return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); + } + } +} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6b.java similarity index 73% rename from webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6b.java rename to webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6b.java index 2bf828c90..77bd7b66e 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6b.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6b.java @@ -1,5 +1,5 @@ -package org.owasp.webgoat.plugin; +package org.owasp.webgoat.plugin.introduction; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; @@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; -import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; @@ -18,77 +17,71 @@ import java.sql.SQLException; import java.sql.Statement; - /*************************************************************************************************** - * - * + * + * * This file is part of WebGoat, an Open Web Application Security Project utility. For details, * please see http://www.owasp.org/ - * + * * Copyright (c) 2002 - 20014 Bruce Mayhew - * + * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with this program; if * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. - * + * * Getting Source ============== - * + * * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software * projects. - * + * * For details, please see http://webgoat.github.io - * + * * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ @AssignmentPath("/SqlInjection/attack6b") public class SqlInjectionLesson6b extends AssignmentEndpoint { - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String userid_6b, HttpServletRequest request) throws IOException { - if (userid_6b.toString().equals(getPassword())) { - return trackProgress(success().build()); - } else { - return trackProgress(failed().build()); - } - } + @RequestMapping(method = RequestMethod.POST) + @ResponseBody + public AttackResult completed(@RequestParam String userid_6b) throws IOException { + if (userid_6b.toString().equals(getPassword())) { + return trackProgress(success().build()); + } else { + return trackProgress(failed().build()); + } + } - protected String getPassword() - { - - String password="dave"; - try - { + protected String getPassword() { + + String password = "dave"; + try { Connection connection = DatabaseUtilities.getConnection(getWebSession()); String query = "SELECT password FROM user_system_data WHERE user_name = 'dave'"; - - try - { + + try { Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); + ResultSet.CONCUR_READ_ONLY); ResultSet results = statement.executeQuery(query); - if ((results != null) && (results.first() == true)) - { + if ((results != null) && (results.first() == true)) { password = results.getString("password"); } - } catch (SQLException sqle) - { - sqle.printStackTrace(); - // do nothing + } catch (SQLException sqle) { + sqle.printStackTrace(); + // do nothing } - } catch (Exception e) - { - e.printStackTrace(); - // do nothing + } catch (Exception e) { + e.printStackTrace(); + // do nothing } return (password); } diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/Servers.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/Servers.java new file mode 100644 index 000000000..cb7ee35c0 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/Servers.java @@ -0,0 +1,56 @@ +package org.owasp.webgoat.plugin.mitigation; + +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.SneakyThrows; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.List; + +/** + * @author nbaars + * @since 6/13/17. + */ +@RestController +@RequestMapping("SqlInjection/servers") +public class Servers { + + @AllArgsConstructor + @Getter + private class Server { + + private String id; + private String hostname; + private String ip; + private String mac; + private String status; + private String description; + } + + @Autowired + private WebSession webSession; + + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + @SneakyThrows + @ResponseBody + public List sort(@RequestParam String column) { + Connection connection = DatabaseUtilities.getConnection(webSession); + PreparedStatement preparedStatement = connection.prepareStatement("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by " + column); + ResultSet rs = preparedStatement.executeQuery(); + List servers = Lists.newArrayList(); + while (rs.next()) { + Server server = new Server(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6)); + servers.add(server); + } + return servers; + } + +} diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java new file mode 100644 index 000000000..b8237b8df --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java @@ -0,0 +1,46 @@ +package org.owasp.webgoat.plugin.mitigation; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentHints; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.sql.*; + +/** + * @author nbaars + * @since 6/13/17. + */ +@AssignmentPath("SqlInjection/attack12a") +@AssignmentHints(value = {"SqlStringInjectionHint8", "SqlStringInjectionHint9", "SqlStringInjectionHint10", "SqlStringInjectionHint11"}) +@Slf4j +public class SqlInjectionLesson12a extends AssignmentEndpoint { + + @Autowired + private WebSession webSession; + + @RequestMapping(method = RequestMethod.POST) + @ResponseBody + @SneakyThrows + public AttackResult completed(@RequestParam String ip) { + Connection connection = DatabaseUtilities.getConnection(webSession); + PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ?"); + preparedStatement.setString(1, ip); + ResultSet resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + return trackProgress(success().build()); + } + return trackProgress(failed().build()); + } +} + + diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionMitigations.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionMitigations.java new file mode 100644 index 000000000..463c4dfdc --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionMitigations.java @@ -0,0 +1,63 @@ +package org.owasp.webgoat.plugin.mitigation; + +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.NewLesson; + +import java.util.ArrayList; +import java.util.List; + +/** + * ************************************************************************************************ + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + *

+ * Copyright (c) 2002 - 20014 Bruce Mayhew + *

+ * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + *

+ * Getting Source ============== + *

+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + *

+ * + * @author WebGoat + * @version $Id: $Id + * @since October 12, 2016 + */ +public class SqlInjectionMitigations extends NewLesson { + @Override + public Category getDefaultCategory() { + return Category.INJECTION; + } + + @Override + public List getHints() { + return new ArrayList<>(); + } + + @Override + public Integer getDefaultRanking() { + return 1; + } + + @Override + public String getTitle() { + return "SQL Injection (mitigations)"; + } + + @Override + public String getId() { + return "SqlInjectionMitigations"; + } +} diff --git a/webgoat-lessons/sql-injection/src/main/resources/css/challenge.css b/webgoat-lessons/sql-injection/src/main/resources/css/challenge.css new file mode 100644 index 000000000..6a8635ae6 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/css/challenge.css @@ -0,0 +1,96 @@ +.panel-login { + border-color: #ccc; + -webkit-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2); + -moz-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2); + box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2); +} +.panel-login>.panel-heading { + color: #00415d; + background-color: #fff; + border-color: #fff; + text-align:center; +} +.panel-login>.panel-heading a{ + text-decoration: none; + color: #666; + font-weight: bold; + font-size: 15px; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear; +} +.panel-login>.panel-heading a.active{ + color: #029f5b; + font-size: 18px; +} +.panel-login>.panel-heading hr{ + margin-top: 10px; + margin-bottom: 0px; + clear: both; + border: 0; + height: 1px; + background-image: -webkit-linear-gradient(left,rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.15),rgba(0, 0, 0, 0)); + background-image: -moz-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0)); + background-image: -ms-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0)); + background-image: -o-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0)); +} +.panel-login input[type="text"],.panel-login input[type="email"],.panel-login input[type="password"] { + height: 45px; + border: 1px solid #ddd; + font-size: 16px; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear; +} +.panel-login input:hover, +.panel-login input:focus { + outline:none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + border-color: #ccc; +} +.btn-login { + background-color: #59B2E0; + outline: none; + color: #fff; + font-size: 14px; + height: auto; + font-weight: normal; + padding: 14px 0; + text-transform: uppercase; + border-color: #59B2E6; +} +.btn-login:hover, +.btn-login:focus { + color: #fff; + background-color: #53A3CD; + border-color: #53A3CD; +} +.forgot-password { + text-decoration: underline; + color: #888; +} +.forgot-password:hover, +.forgot-password:focus { + text-decoration: underline; + color: #666; +} + +.btn-register { + background-color: #1CB94E; + outline: none; + color: #fff; + font-size: 14px; + height: auto; + font-weight: normal; + padding: 14px 0; + text-transform: uppercase; + border-color: #1CB94A; +} +.btn-register:hover, +.btn-register:focus { + color: #fff; + background-color: #1CA347; + border-color: #1CA347; +} diff --git a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html index 85d55aadb..bdbe8095e 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html +++ b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html @@ -3,54 +3,33 @@

- -
- -
+
- -
+
- -
+
- -
+
- -
+
- -
- - - - -
-
-
+
- -
- - - -
- -
-
-
- - -
-
-
- - -
-
-
- - - - -
- - - - - - - -
Name:
-
- - -
-
- -
-
-
- - - - -
- - - - - - - -
Password:
-
- - -
-
- -
- -
-
- - -
-
-
- - -
-
-
- - -
-
-
- - -
-
-
- - -
-
-
- - -
-
-
- - -
-
diff --git a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionAdvanced.html b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionAdvanced.html new file mode 100644 index 000000000..a4b749dc6 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionAdvanced.html @@ -0,0 +1,166 @@ + + + + + +
+
+
+ + +
+
+
+ +
+
+
+
+
+ + + + + + + +
Name:
+
+
+
+
+
+
+
+ + + + + + + +
Password:
+
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ + + diff --git a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionMitigations.html b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionMitigations.html new file mode 100644 index 000000000..f34037088 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionMitigations.html @@ -0,0 +1,112 @@ + + + + + +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+
+

List of servers +
+ +
+

+
+
+ +
+ + + + + + + + + + + + + + +
Hostname + IP MAC Status + Description +
+
+
+
+
+
+
+
+
+
+
IP address webgoat-prd server:
+ +
+
+ +
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties index 407f5367a..8f4c69431 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties @@ -1,12 +1,18 @@ #StringSqlInjection.java StringSqlInjectionSecondStage=Now that you have successfully performed an SQL injection, try the same type of attack on a parameterized query. Restart the lesson if you wish to return to the injectable query. EnterLastName=Enter your last name: -NoResultsMatched=No results matched. Try Again. +NoResultsMatched=No results matched. Try Again. SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command. SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:

"SELECT * FROM user_data WHERE last_name = "accountName" SqlStringInjectionHint3=Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. Try appending a SQL statement that always resolves to true SqlStringInjectionHint4=Try entering [ smith' OR '1' = '1 ]. - +SqlStringInjectionHint5=First try to find out the number of columns by adding a group by 1,2,3 etc to the query. +SqlStringInjectionHint6=Try adding a union to the query, the number of columns should match. +SqlStringInjectionHint7=Try entering [ Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- ]. +SqlStringInjectionHint8=Try sorting and look at the request +SqlStringInjectionHint9=Intercept the request and try to specify a different order by +SqlStringInjectionHint10=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens +SqlStringInjectionHint11=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens sql-injection.5a.success=You have succeed: {0} sql-injection.5a.no.results=No results matched. Try Again. diff --git a/webgoat-lessons/sql-injection/src/main/resources/js/assignment12.js b/webgoat-lessons/sql-injection/src/main/resources/js/assignment12.js new file mode 100644 index 000000000..b001e4572 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/js/assignment12.js @@ -0,0 +1,61 @@ +$(function () { + $('.col-check').hide(); + $('#btn-admin').on('click', function () { + if ($("#toolbar-admin").is(":visible")) { + $("#toolbar-admin").hide(); + $(".col-check").hide(); + } + else { + $("#toolbar-admin").show(); + $(".col-check").show(); + } + }); + + $('#btn-online').on('click', function () { + $('table tr').filter(':has(:checkbox:checked)').find('td').parent().removeClass().addClass('success'); + $('table tr').filter(':has(:checkbox:checked)').find('td.status').text('online'); + }); + $('#btn-offline').on('click', function () { + $('table tr').filter(':has(:checkbox:checked)').find('td').parent().removeClass().addClass('warning'); + $('table tr').filter(':has(:checkbox:checked)').find('td.status').text('offline'); + }); + $('#btn-out-of-order').on('click', function () { + $('table tr').filter(':has(:checkbox:checked)').find('td').parent().removeClass().addClass('danger'); + $('table tr').filter(':has(:checkbox:checked)').find('td.status').text('out of order'); + }); + +}); + +$(document).ready(function () { + getServers('id'); +}); + +var html = '' + + '' + + 'HOSTNAME' + + 'IP' + + 'MAC' + + 'ONLINE' + + 'DESCRIPTION' + + ''; + +function getServers(column) { + $.get("SqlInjection/servers?column=" + column, function (result, status) { + $("#servers").empty(); + for (var i = 0; i < result.length; i++) { + var server = html.replace('ID', result[i].id); + var status = "success"; + if (result[i].status === 'offline') { + status = "danger"; + } + server = server.replace('ONLINE', status); + server = server.replace('STATUS', status); + server = server.replace('HOSTNAME', result[i].hostname); + server = server.replace('IP', result[i].ip); + server = server.replace('MAC', result[i].mac); + server = server.replace('DESCRIPTION', result[i].description); + $("#servers").append(server); + } + + }); +} \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/src/main/resources/js/challenge.js b/webgoat-lessons/sql-injection/src/main/resources/js/challenge.js new file mode 100644 index 000000000..9107e1176 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/js/challenge.js @@ -0,0 +1,18 @@ +$(function() { + + $('#login-form-link').click(function(e) { + $("#login-form").delay(100).fadeIn(100); + $("#register-form").fadeOut(100); + $('#register-form-link').removeClass('active'); + $(this).addClass('active'); + e.preventDefault(); + }); + $('#register-form-link').click(function(e) { + $("#register-form").delay(100).fadeIn(100); + $("#login-form").fadeOut(100); + $('#login-form-link').removeClass('active'); + $(this).addClass('active'); + e.preventDefault(); + }); + +}); \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjectionAdvanced_plan.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjectionAdvanced_plan.adoc new file mode 100644 index 000000000..c9a75b8a6 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjectionAdvanced_plan.adoc @@ -0,0 +1,8 @@ +== Concept + +This lesson describes the more advanced topics for an SQL injection. + +== Goals + +** Combining SQL Injection Techniques +** Blind SQL injection diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_challenge.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_challenge.adoc new file mode 100644 index 000000000..0fdb4f2d3 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_challenge.adoc @@ -0,0 +1,4 @@ +We now explained the basic steps involved in an SQL injection. In this assignment you will need to combine all +the things we explained in the SQL lessons. + +Have fun! \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content10.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content10.adoc index c0ad3d455..2e4a775d1 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content10.adoc +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content10.adoc @@ -1,35 +1,28 @@ == Parameterized Queries – Java Example +[source,java] ------------------------------------------------------- -// Parser returns only valid string data -String accountID = getParser().getStringParameter(ACCT_ID, ""); -String data = null; -try -{ - // Read only database connection - Statement connection = DatabaseUtilities.getConnection(READ_ONLY); - - // Build a fully qualified query - String query = "SELECT first_name, last_name, acct_id, balance - FROM user_data WHERE acct_id = ?"; - PreparedStatement statement = connection.prepareStatement(query); - statement.setString(1, accountID); - ResultSet results = statement.executeQuery(); - if ((results != null) && (results.first() == true)) - { - // Only one record should be returned for this query - Results.last(); - if (results.getRow() <= 2) - { - data = processAccount(results); - } - else { // Handle the error – Database integrity issue } - } - else { // Handle the error – no records found } +public static String loadAccount() { + // Parser returns only valid string data + String accountID = getParser().getStringParameter(ACCT_ID, ""); + String data = null; + String query = "SELECT first_name, last_name, acct_id, balance FROM user_data WHERE acct_id = ?"; + try (Connection connection = null; + PreparedStatement statement = connection.prepareStatement(query)) { + statement.setString(1, accountID); + ResultSet results = statement.executeQuery(); + if (results != null && results.first()) { + results.last(); // Only one record should be returned for this query + if (results.getRow() <= 2) { + data = processAccount(results); + } else { + // Handle the error – Database integrity issue + } + } else { + // Handle the error – no records found } + } + } catch (SQLException sqle) { + // Log and handle the SQL Exception } + } + return data; } -catch (SQLException sqle) { // Log and handle the SQL Exception } -catch (Exception e) { // Log and handle the Exception } -finally { // Always close connection in finally block - DatabaseUtilities.closeConnection(); -} -return data; ------------------------------------------------------- diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content12a.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content12a.adoc new file mode 100644 index 000000000..88d1a4f4c --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content12a.adoc @@ -0,0 +1,48 @@ +== Order by clause + +Question: Does a preparared statement always prevent against an SQL injection? +Answer: No it does not + +Let's take a look at the following statement: + +---- +select * from users order by lastname; +---- + +If we look at the specification of the SQL grammar the definition is as follows: + +---- +SELECT ... +FROM tableList +[WHERE Expression] +[ORDER BY orderExpression [, ...]] + +orderExpression: +{ columnNr | columnAlias | selectExpression } + [ASC | DESC] + +selectExpression: +{ Expression | COUNT(*) | { + COUNT | MIN | MAX | SUM | AVG | SOME | EVERY | + VAR_POP | VAR_SAMP | STDDEV_POP | STDDEV_SAMP +} ([ALL | DISTINCT][2]] Expression) } [[AS] label] + +Based on HSQLDB +---- + +This means an `orderExpression` van be a `selectExpression` which can be a function as well, so for example with +a `case` statement we might be able to ask the database some questions, like: + +---- +select * from users order by + (select case when (true) then lastname else firstname) +---- + +So we can substitute any kind of boolean operation in the `when(....)` part. The statement will just work because +it is a valid query whether you use a prepared statement or not an order by clause can by definition contain a +expression. + +=== Mitigation + +If you need to provide a sorting column in your web application you should implement a whitelist to validate the value +of the `order by` statement it should always be limited to something like 'firstname' or 'lastname'. diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6c.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6c.adoc new file mode 100644 index 000000000..53fc5e140 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6c.adoc @@ -0,0 +1,59 @@ +== Blind SQL Injection + +Blind SQL injection is a type of SQL injection attack that asks the database true or false +questions and determines the answer based on the applications response. This attack is often used when the web +application is configured to show generic error messages, but has not mitigated the code that is vulnerable to SQL +injection. + +=== Difference + +Let's first start with the difference between a normal SQL injection and a blind SQL injection. In a normal +SQL injection the error messages from the database are displayed and gives enough information to find out how +the query is working. Or in the case of an union based SQL injection the application does not reflect the information +directly on the webpage. So in the case where nothing is displayed you will need to start asking the database questions +based on a true or false statement. That's why a blind SQL injection is much more difficult to exploit. + +There are several different types of blind SQL injections: content based and time based SQL injections. + + +=== Example + +In this case we are trying to ask the database a boolean question based on for example a unique id, for example +suppose we have the following url: `https://my-shop.com?article=4` +On the server side this query will be translated as follows: + +---- +SELECT * from articles where article_id = 4 +---- + +When we want to exploit this we change the url into: `https://my-shop.com?article=4 AND 1=1` +This will be translated to: + +---- +SELECT * from articles where article_id = 4 AND 1 = 1 +---- + +If the browser will return the same page as it used to when using `https://my-shop.com?article=4` you know the +website is vulnerable for a blind SQL injection. +If the browser responds with a page not found or something else you know a blind SQL injection might not work. +You can now change the SQL query and test for example: `https://my-shop.com?article=4 AND 1=2` which will not return +anything because the query returns false. + +So but how do we actually take advantage of this? Above we only asked the database for trivial question but you can +for example also use the following url: `https://my-shop.com?article=4 AND substring(database_version(),1,1) = 2` + +Most of the time you start by finding which type of database is used, based on the type of database you can find +the system tables of the database you can enumerate all the tables present in the database. With this information +you can start getting information from all the tables and you are able to dump the database. +Be aware that this approach might not work if the privileges of the database are setup correctly (meaning the +system tables cannot be queried with the user used to connect from the web application to the database). + + +Another way is called a time based SQL injection, in this case you will ask the database to wait before returning +the result. You might need to use this if you are totally blind so there is no difference between the response you +can use for example: + +---- +article = 4; sleep(10) -- +---- + diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_order_by.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_order_by.adoc new file mode 100644 index 000000000..6adb9156b --- /dev/null +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_order_by.adoc @@ -0,0 +1,4 @@ +In this assignment try to perform an SQL injection through the ORDER BY field. +Try to find the ip address of the `webgoat-prd` server. + +Note: The submit field of this assignment is *NOT* vulnerable for an SQL injection. \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_plan.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_plan.adoc index 2865b3d81..6fd7064aa 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_plan.adoc +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_plan.adoc @@ -9,5 +9,4 @@ This lesson describes what is Structured Query Language (SQL) and how it can be * The user will demonstrate knowledge on: ** String SQL Injection ** Numeric SQL Injection -** Combining SQL Injection Techniques diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5aTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5aTest.java new file mode 100644 index 000000000..4c544c17c --- /dev/null +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5aTest.java @@ -0,0 +1,81 @@ +package org.owasp.webgoat.plugin.introduction; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.owasp.webgoat.session.WebgoatContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 5/21/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class SqlInjectionLesson5aTest extends LessonTest { + + @Autowired + private WebgoatContext context; + + @Before + public void setup() throws Exception { + SqlInjection sql = new SqlInjection(); + when(webSession.getCurrentLesson()).thenReturn(sql); + when(webSession.getWebgoatContext()).thenReturn(context); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void knownAccountShouldDisplayData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "Smith")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", is(messages.getMessage("assignment.not.solved")))) + .andExpect(jsonPath("$.output", containsString("

USERID, FIRST_NAME"))); + } + + @Test + public void unknownAccount() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "Smithh")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", is(messages.getMessage("NoResultsMatched")))) + .andExpect(jsonPath("$.output").doesNotExist()); + } + + @Test + public void sqlInjection() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "smith' OR '1' = '1")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(true))) + .andExpect(jsonPath("$.feedback", containsString("You have succeed"))) + .andExpect(jsonPath("$.output").doesNotExist()); + } + + @Test + public void sqlInjectionWrongShouldDisplayError() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "smith' OR '1' = '1'")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved")))) + .andExpect(jsonPath("$.output", is("malformed string: '1''"))); + } +} \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6aTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6aTest.java new file mode 100644 index 000000000..be735f9c0 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6aTest.java @@ -0,0 +1,81 @@ +package org.owasp.webgoat.plugin.introduction; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 6/15/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class SqlInjectionLesson6aTest extends LessonTest { + + @Before + public void setup() throws Exception { + when(webSession.getCurrentLesson()).thenReturn(new SqlInjection()); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void wrongSolution() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6a") + .param("userid_6a", "John")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.lessonCompleted", is(false))); + } + + @Test + public void wrongNumberOfColumns() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6a") + .param("userid_6a", "Smith' union select userid,user_name, password,cookie from user_system_data --")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.lessonCompleted", is(false))) + .andExpect(jsonPath("$.output", is("column number mismatch detected in rows of UNION, INTERSECT, EXCEPT, or VALUES operation"))); + } + + @Test + public void wrongDataTypeOfColumns() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6a") + .param("userid_6a", "Smith' union select 1,password, 1,'2','3', '4',1 from user_system_data --")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.lessonCompleted", is(false))) + .andExpect(jsonPath("$.output", containsString("incompatible data types in combination"))); + } + + @Test + public void correctSolution() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6a") + .param("userid_6a", "Smith' union select 1,password, '1','2','3', '4',1 from user_system_data --")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.lessonCompleted", is(true))) + .andExpect(jsonPath("$.feedback", containsString("dave"))); + } + + @Test + public void noResultsReturned() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6a") + .param("userid_6a", "Smith' and 1 = 2 --")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.6a.no.results")))); + } + + +} \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6bTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6bTest.java new file mode 100644 index 000000000..394d5baa9 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6bTest.java @@ -0,0 +1,46 @@ +package org.owasp.webgoat.plugin.introduction; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/**a + * @author nbaars + * @since 6/16/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class SqlInjectionLesson6bTest extends LessonTest { + + @Before + public void setup() throws Exception { + when(webSession.getCurrentLesson()).thenReturn(new SqlInjection()); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void submitCorrectPassword() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6b") + .param("userid_6b", "dave")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true))); + } + + @Test + public void submitWrongPassword() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6b") + .param("userid_6b", "John")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false))); + } + +} \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12aTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12aTest.java new file mode 100644 index 000000000..70e42cfcb --- /dev/null +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12aTest.java @@ -0,0 +1,96 @@ +package org.owasp.webgoat.plugin.mitigation; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugin.introduction.SqlInjection; +import org.owasp.webgoat.plugins.LessonTest; +import org.owasp.webgoat.session.WebgoatContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 5/21/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class SqlInjectionLesson12aTest extends LessonTest { + + @Autowired + private WebgoatContext context; + + @Before + public void setup() throws Exception { + SqlInjection sql = new SqlInjection(); + + when(webSession.getCurrentLesson()).thenReturn(sql); + when(webSession.getWebgoatContext()).thenReturn(context); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void knownAccountShouldDisplayData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + .param("column", "id")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()); + } + + @Test + public void trueShouldSortByHostname() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + .param("column", "(case when (true) then hostname else id end)")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc"))); + } + + @Test + public void falseShouldSortById() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + .param("column", "(case when (true) then hostname else id end)")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc"))); + } + + @Test + public void passwordIncorrectShouldOrderByHostname() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + .param("column", "CASE WHEN (SELECT ip FROM servers WHERE hostname='webgoat-prd') LIKE '192.%' THEN hostname ELSE id END")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-dev"))); + } + + @Test + public void passwordCorrectShouldOrderByHostname() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + .param("column", "CASE WHEN (SELECT ip FROM servers WHERE hostname='webgoat-prd') LIKE '104.%' THEN hostname ELSE id END")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc"))); + } + + @Test + public void postingCorrectAnswerShouldPassTheLesson() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack12a") + .param("ip", "104.130.219.202")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true))); + } + + @Test + public void postingWrongAnswerShouldNotPassTheLesson() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack12a") + .param("ip", "192.168.219.202")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false))); + } +} \ No newline at end of file diff --git a/webgoat-lessons/webgoat-lesson-template/.DS_Store b/webgoat-lessons/webgoat-lesson-template/.DS_Store new file mode 100644 index 000000000..0d597e3db Binary files /dev/null and b/webgoat-lessons/webgoat-lesson-template/.DS_Store differ diff --git a/webgoat-lessons/webgoat-lesson-template/getting-started.txt b/webgoat-lessons/webgoat-lesson-template/getting-started.txt new file mode 100644 index 000000000..c0677c6b7 --- /dev/null +++ b/webgoat-lessons/webgoat-lesson-template/getting-started.txt @@ -0,0 +1,55 @@ +##### To include lesson template in build ##### +1. edit theh webgoat-server/pom.xml file and uncomment the section under ... + + +2. Also uncomment in webgoat-lessons/pom.xml where it says ... + + +##### To add a lesson to WebGoat ##### + +There are a number of moving parts and this sample lesson will help you navigate those parts. Most of your work will be done in two directories. To start though, you can copy this directory with the name of your-lesson in the webgoat-lessons directory. + +0. The POM file + a. change the ... + webgoat-lesson-template + ... line to give your lesson its own artifactId.That should be all you need to do there + +1. The Base Class ... + In webgoat-lessons/{your-lesson}/src/main/java, refactor the LessonTemplate.java class, changing ... + a. the category in which you want your lesson to be in. You can create a new category if you want, or put in an issue to have one added + b. The 'defaultRanking' will move your lesson up or down in the categories list + c. implement a new key name pair "lesson-template.title" (the key) and update the same key/value pair (your.key=your value) in src/main/resources/i18n/WebGoatLabels.properties + d. Implement a new value for the getId method, which leads us to ... + +2. The HTML content framing ... + a. Rename the provided file in src/main/resources/html using your value from the getId method in your lesson's base class (e.g. public String getId() { return "your-lesson"; } >> "your-lesson.html") + b. Modify that file following the commented instructions in there + c. In conjunction with this file you + +3. Assignment Endpoints + a. In the above html file, you will see an example of an 'attack form'. You can create endpoints to handle these attacks and provide the user feedback and simulated output. See the example file here as well as other existing lessons for ways to extend these. You will extend the AssignmentEndpoint as the example will show + b. You can also create supporting (non-assignment) endpoints, that are not evaluated/graded. + c. See other lesson examples for creating unit/integration tests for your project as well + + +4. Getting your lesson to show up + a. modify the webgoat-lessons/pom.xml to include your project in the section + + + webgoat-lesson-template + + + + b. modify the webgoat-server/pom.xml to add your project as a dependency in the section ... + + + +

+ + +
+ + +
+ +
+ + +
+
+ + + + + + -
-
- - - -
-
- Registration form - - - - - - - - - - - - - - - - - - -
Username
E-mail
Password
-
-
- -
-
+
+
+
+
+
+ user profile image +
+
+
+ John Doe + uploaded a photo. +
+
24 days ago
+
+
+ +
+ image post +
+ +
+ +
+ +
+ +
+
+
- -
- -
- -
- - - -
-
- Registration form - - - - - - - - - - - - - - - - - - -
Username
E-mail
Password
-
-
- -
-
+
+
+
+
+
+ user profile image +
+
+
+ John Doe + uploaded a photo. +
+
24 days ago
+
+
+ +
+ image post +
+ +
+ +
+ +
+ +
+
+
- -
diff --git a/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties index 864ae5afb..877a3774c 100644 --- a/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties @@ -31,7 +31,7 @@ xxe.blind.output=Contents of the file is: {0} xxe.hints.simple.xxe.1=Try submitting the form and see what happens xxe.hints.simple.xxe.2=XXE stands for XML External Entity attack xxe.hints.simple.xxe.3=Try to include your own DTD -xxe.hints.simple.xxe.4=Try to include a doctype (' + + '' + + ' ' + commentInput + '' + + ''; + return xml; +} + +webgoat.customjs.simpleXXECallback = function() { + $("#commentInputBlind").val(''); + getComments('#commentsListSimple'); +} + $(document).ready(function () { - $("#postComment").unbind(); - $("#postComment").on("click", function () { - var commentInput = $("#commentInput").val(); - $.ajax({ - type: 'POST', - url: 'xxe/simple', - data: JSON.stringify({text: commentInput}), - contentType: "application/json", - dataType: 'json' - }).then( - function () { - getComments(); - $("#commentInput").val(''); - } - ) - }) - getComments(); -}) + getComments('#commentsListSimple'); +}); + +webgoat.customjs.blindXXE = function() { + var commentInput = $("#commentInputBlind").val(); + var xml = '' + + '' + + ' ' + commentInput + '' + + ''; + return xml; +} + +webgoat.customjs.blindXXECallback = function() { + $("#commentInputBlind").val(''); + getComments('#commentsListBlind'); +} + +$(document).ready(function () { + getComments('#commentsListBlind'); +}); + +webgoat.customjs.contentTypeXXE = function() { + var commentInput = $("#commentInputContentType").val(); + return JSON.stringify({text: commentInput}); +} + +webgoat.customjs.contentTypeXXECallback = function() { + $("#commentInputContentType").val(''); + getComments('#commentsListContentType'); +} + +$(document).ready(function () { + getComments('#commentsListContentType'); +}); var html = '
  • ' + '
    ' + @@ -31,15 +61,15 @@ var html = '
  • ' + '
  • ' + ''; -function getComments() { - $.get("xxe/simple", function (result, status) { - $("#comments_list").empty(); +function getComments(field) { + $.get("xxe/comments", function (result, status) { + $(field).empty(); for (var i = 0; i < result.length; i++) { var comment = html.replace('USER', result[i].user); comment = comment.replace('DATETIME', result[i].dateTime); comment = comment.replace('COMMENT', result[i].text); - $("#comments_list").append(comment); + $(field).append(comment); } }); -} \ No newline at end of file +} diff --git a/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc b/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc index cd615ee26..0d7e110e4 100644 --- a/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc +++ b/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc @@ -8,11 +8,11 @@ Our WebGoat server by default has an /xxe/ping endpoint which we can use. *This [source] ---- -curl -i http://localhost:8080/WebGoat/XXE/ping +curl -i http://localhost:8080/WebGoat/XXE/ping?text=HelloWorld will result in: -GET curl/7.45.0 +GET curl/7.45.0 HelloWorld ---- at the server side. @@ -33,12 +33,12 @@ Now submit the form and change the xml to: ---- + %remote; ]> - - test&ping; - + + test&ping; + ---- Now if we check our server log we will see: @@ -48,7 +48,8 @@ Now if we check our server log we will see: GET Java/1.8.0_101 HelloWorld ---- -So with the XXE we are able to ping our own server which means XXE injection is possible. +So with the XXE we are able to ping our own server which means XXE injection is possible. So with the XXE injection +we are basically able to reach the same effect as we did in the beginning with the curl command. [NOTE] In this case we use http://localhost:8080/WebGoat/plugin_lessons/XXE/test.dtd to fetch the dtd but in reality this will diff --git a/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_mitigation.adoc b/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_mitigation.adoc index 2ba1be885..2e30c8a40 100644 --- a/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_mitigation.adoc +++ b/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_mitigation.adoc @@ -19,3 +19,11 @@ xif.setProperty(XMLInputFactory.SUPPORT_DTD, true); ---- For more information about configuration, see https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet + + +==== Validate + +Implement proper validation for the Content-type and Accept header do not simply rely on the framework to handle + the incoming request. Also if the client specifies a proper accept header return with a `406/Not Acceptable. + +` \ No newline at end of file diff --git a/webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java b/webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java new file mode 100644 index 000000000..9f31bf8eb --- /dev/null +++ b/webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java @@ -0,0 +1,90 @@ +package org.owasp.webgoat.plugin; + +import com.google.common.io.Files; +import org.hamcrest.CoreMatchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 5/4/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class BlindSendFileAssignmentTest extends LessonTest { + + @Autowired + private Comments comments; + @Value("${webgoat.user.directory}") + private String webGoatHomeDirectory; + + @Before + public void setup() throws Exception { + XXE xxe = new XXE(); + when(webSession.getCurrentLesson()).thenReturn(xxe); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + File logFile = new File(webGoatHomeDirectory, "/XXE/log" + webSession.getUserName() + ".txt"); + if (logFile.exists()) logFile.delete(); + when(webSession.getUserName()).thenReturn("unit-test"); + } + + @Test + public void validCommentMustBeAdded() throws Exception { + int nrOfComments = comments.getComments().size(); + mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind") + .content("test")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved")))); + assertThat(comments.getComments().size()).isEqualTo(nrOfComments + 1); + } + + @Test + public void wrongXmlShouldGiveErrorBack() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind") + .content("test")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved")))) + .andExpect(jsonPath("$.output", CoreMatchers.is("javax.xml.bind.UnmarshalException\\n - with linked exception:\\n[javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,22]\\nMessage: The element type \\\"text\\\" must be terminated by the matching end-tag \\\"<\\/text>\\\".]"))); + } + + @Test + public void solve() throws Exception { + File file = new File(webGoatHomeDirectory, "XXE/attack.dtd"); + String dtd = "\n" + + "\n" + + "\">\n" + + "%all;"; + Files.write(dtd.getBytes(), file); + String xml = "\n" + + "\n" + + "%remote;\n" + + "]>\n" + + "\n" + + " test&send;\n" + + ""; + mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind") + .content(xml)) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.solved")))) + .andExpect(jsonPath("$.output", CoreMatchers.containsString("WebGoat 8 rocks..."))); + } + +} \ No newline at end of file diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml index 8dff0cda9..10408a19f 100644 --- a/webgoat-server/pom.xml +++ b/webgoat-server/pom.xml @@ -72,8 +72,6 @@ - - com.spotify @@ -86,11 +84,16 @@ webgoat-container ${project.version} - - - - - + + org.owasp.webgoat.lesson + challenge + ${project.version} + + + org.owasp.webgoat.lesson + bypass-restrictions + ${project.version} + org.owasp.webgoat.lesson client-side-filtering @@ -101,6 +104,11 @@ cross-site-scripting ${project.version} + + org.owasp.webgoat.lesson + html-tampering + ${project.version} + org.owasp.webgoat.lesson http-basics @@ -116,6 +124,11 @@ idor ${project.version} + + org.owasp.webgoat.lesson + insecure-login + ${project.version} + org.owasp.webgoat.lesson jwt @@ -136,6 +149,13 @@ xxe ${project.version} + + + + + + + org.springframework.boot spring-boot-devtools