diff options
Diffstat (limited to 'doc/tutorials/fuzz_testing/index.md')
-rw-r--r-- | doc/tutorials/fuzz_testing/index.md | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/doc/tutorials/fuzz_testing/index.md b/doc/tutorials/fuzz_testing/index.md new file mode 100644 index 00000000000..1d4985f9003 --- /dev/null +++ b/doc/tutorials/fuzz_testing/index.md @@ -0,0 +1,243 @@ +--- +stage: Secure +group: Dynamic Analysis +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Tutorial: Perform fuzz testing in GitLab **(ULTIMATE)** + +[Coverage-guided fuzz testing](../../user/application_security/coverage_fuzzing/index.md#coverage-guided-fuzz-testing-process) sends unexpected, malformed, or random data to your application, and then monitors +your application for unstable behaviors and crashes. + +This helps you discover bugs and potential security issues that other QA processes may miss. + +You should use fuzz testing in addition to other security scanners and your own test processes. +If you're using GitLab CI/CD, you can run fuzz tests as part your CI/CD workflow. + +To set up, configure, and perform coverage-guided fuzz testing +using JavaScript in this tutorial, you: + +1. [Fork the project template](#fork-the-project-template) to create a project + to run the fuzz tests in. +1. [Create the fuzz targets](#create-the-fuzz-targets). +1. [Enable coverage-guided fuzz testing](#enable-coverage-guided-fuzz-testing) + in your forked project. +1. [Run the fuzz test](#run-the-fuzz-test) to identify security vulnerabilities. +1. [Fix any vulnerabilities](#fix-the-vulnerabilities) identified by the fuzz test. + +## Fork the project template + +First, to create a project to try out fuzz testing in, you must fork the `fuzz-testing` +project template: + +1. Open the [`fuzz-testing` project template](https://gitlab.com/gitlab-org/tutorial-project-templates/fuzz-testing). +1. [Fork the project template](../../user/project/repository/forking_workflow.md). +1. When forking the project template: + - Name the forked project `fuzz-testing-demo`. + - Select an appropriate [namespace](../../user/namespace/index.md). + - Set [project visibility](../../user/public_access.md) to **Private**. + +You have successfully forked the `fuzz-testing` project template. Before you can +start fuzz testing, remove the relationship between the project template and the fork: + +1. On the left sidebar, select **Settings > General**. +1. Expand **Advanced**. +1. In the **Remove fork relationship** section, select **Remove fork relationship**. + Enter the name of the project when prompted. + +Your project is ready and you can now create the fuzz test. Next you will create +the fuzz targets. + +## Create the fuzz targets + +Now you have a project for fuzz testing, you create the fuzz targets. A fuzz target +is a function or program that, given an input, makes a call to the application +being tested. + +In this tutorial, the fuzz targets call a function of the `my-tools.js` file using +a random buffer as a parameter. + +To create the two fuzz target files: + +1. On the top bar, select **Main menu > Projects** and select the `fuzz-testing-demo` project. +1. Create a file in the root directory of the project. +1. Name the file `fuzz-sayhello.js` and add the following code: + + ```javascript + let tools = require('./my-tools') + + function fuzz(buf) { + const text = buf.toString() + tools.sayHello(text) + } + + module.exports = { + fuzz + } + ``` + + You can also copy this code from the `fuzz-testing-demo/fuzzers/fuzz-sayhello.js` + project file. + +1. Name the **Target Branch** `add-fuzz-test` and write a descriptive commit message. + - Do not select the **Start a new merge request with these changes** checkbox yet. +1. Select **Commit changes**. +1. Return to the root directory of the project. +1. Make sure you are in the `add-fuzz-test` branch. +1. Create the second file named `fuzz-readme.js` and add the following code: + + ```javascript + let tools = require('./my-tools') + function fuzz(buf) { + const text = buf.toString() + tools.readmeContent(text) + } + module.exports = { + fuzz + } + ``` + + You can also copy this code from the `fuzz-testing-demo/fuzzers/fuzz-readme.js` + project file. + +1. Write a descriptive commit message. +1. Make sure the **Target Branch** is `add-fuzz-test`. +1. Select **Commit changes**. + +You now have two fuzz targets that can make calls to the application being tested. +Next you will enable the fuzz testing. + +## Enable coverage-guided fuzz testing + +To enable coverage-guided fuzz testing, create a CI/CD pipeline running +the `gitlab-cov-fuzz` CLI to execute the fuzz test on the two fuzz targets. + +To create the pipeline file: + +1. Make sure you are in the `add-fuzz-test` branch. +1. In the root directory of the `fuzz-testing-demo` project, create a new file. +1. Name the file `.gitlab-ci.yml` and add the following code: + + ```yaml + image: node:18 + + stages: + - fuzz + + include: + - template: Coverage-Fuzzing.gitlab-ci.yml + + readme_fuzz_target: + extends: .fuzz_base + tags: [saas-linux-large-amd64] # Optional + variables: + COVFUZZ_ADDITIONAL_ARGS: '--fuzzTime=60' + script: + - npm config set @gitlab-org:registry https://gitlab.com/api/v4/packages/npm/ && npm i -g @gitlab-org/jsfuzz + - ./gitlab-cov-fuzz run --engine jsfuzz -- fuzz-readme.js + + hello_fuzzing_target: + extends: .fuzz_base + tags: [saas-linux-large-amd64] # Optional + variables: + COVFUZZ_ADDITIONAL_ARGS: '--fuzzTime=60' + script: + - npm config set @gitlab-org:registry https://gitlab.com/api/v4/packages/npm/ && npm i -g @gitlab-org/jsfuzz + - ./gitlab-cov-fuzz run --engine jsfuzz -- fuzz-sayhello.js + ``` + + This step adds the following to your pipeline: + - A `fuzz` stage using a template. + - Two jobs, `readme_fuzz_target` and `hello_fuzzing_target`. Each job runs using + the `jsfuzz` engine, which reports unhandled exceptions as crashes. + + You can also copy this code from the `fuzz-testing-demo/fuzzers/fuzzers.yml` + project file. + +1. Write a descriptive commit message. +1. Make sure the **Target Branch** is `add-fuzz-test`. +1. Select **Commit changes**. + +You have successfully enabled coverage-guided fuzz testing. Next you will run the +fuzz test using the pipeline you've just created. + +## Run the fuzz test + +To run the fuzz test: + +1. On the left sidebar, select **Merge requests**. +1. Select **New merge request**. +1. In the **Source branch** section, select the `add-fuzz-test` branch. +1. In the **Target branch** section, make sure that your namespace and the `main` branch are selected. +1. Select **Compare branches and continue**. +1. [Create the merge request](../../user/project/merge_requests/creating_merge_requests.md). + +Creating the merge request triggers a new pipeline, which runs the fuzz test. +When the pipeline is finished running, you should see a security vulnerability +alert on the merge request page. + +To see more information on each vulnerability, select the individual **Uncaught-exception** links. + +You have successfully run the fuzz test and identified vulnerabilities to fix. + +## Fix the vulnerabilities + +The fuzz test identified two security vulnerabilities. To fix those +vulnerabilities, you use the `my-tools.js` library. + +To create the `my-tools.js` file: + +1. Make sure you are in the `add-fuzz-test` branch of the project. +1. Go to the root directory of your project and open the `my-tools.js` file. +1. Replace the contents of this file with the following code: + + ```javascript + const fs = require('fs') + + function sayHello(name) { + if(name.includes("z")) { + //throw new Error("😡 error name: " + name) + console.log("😡 error name: " + name) + } else { + return "😀 hello " + name + } + } + + function readmeContent(name) { + + let fileName = name => { + if(name.includes("w")) { + return "./README.txt" + } else { + return "./README.md" + } + } + + //const data = fs.readFileSync(fileName(name), 'utf8') + try { + const data = fs.readFileSync(fileName(name), 'utf8') + return data + } catch (err) { + console.error(err.message) + return "" + } + + } + + module.exports = { + sayHello, readmeContent + } + ``` + + You can also copy the code from the `fuzz-testing-demo/javascript/my-tools.js` + project file. + +1. Select **Commit changes**. This triggers another pipeline to run another fuzz test. +1. When the pipeline is finished, check the merge request **Overview** page. You + should see that the security scan detected no new potential vulnerabilities. +1. Merge your changes. + +Congratulations, you've successfully run a fuzz test and fixed the identified +security vulnerabilities! + +For more information, see [coverage-guided fuzz testing](../../user/application_security/coverage_fuzzing/index.md). |