1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
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 left sidebar, at the top, select **Search GitLab** (**{search}**) to find 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).
|