Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulnerable 2 #3

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/mapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
sarif-report: mapi.sarif
html-report: mapi.html
target: forallsecure-demo/mapi-node-example/node
duration: 6001

- name: Shut down API
run: pgrep node | xargs kill || true; sleep 5
Expand All @@ -64,7 +65,7 @@ jobs:
flags: vulnerability-tests
fail_ci_if_error: true

- name: Archive Mayhem for API report
- name: Archive Mayhem for API report
uses: actions/upload-artifact@v3
with:
name: mapi-report
Expand All @@ -73,4 +74,4 @@ jobs:
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: mapi.sarif
sarif_file: mapi.sarif
41 changes: 41 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const express = require('express');
const sqlite3 = require('sqlite3').verbose(); // Verbose for easier debugging
const fs = require('fs');
const path = require('path');
const app = express();
const port = 3000;

Expand All @@ -22,7 +24,46 @@
app.get('/', (req, res) => {
res.send('Hello, World!');
});

// Login endpoint (Unsafe)
app.get('/login', (req, res) => {
const { email, password } = req.query;

Check warning

Code scanning / CodeQL

Sensitive data read from GET request Medium

Route handler
for GET requests uses query parameter as sensitive data.

if (!email || !password) {
return res.status(400).send('Email and password are required');
}
const query = `SELECT * FROM users WHERE email = '${email}' and password = '${password}'`;

db.get(query, [], (err, row) => {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.
This query string depends on a
user-provided value
.
if (err) {
return res.status(500).send(`{"error": "${err.stack}"}`);

Check warning

Code scanning / CodeQL

Exception text reinterpreted as HTML Medium

Exception text
is reinterpreted as HTML without escaping meta-characters.
Exception text
is reinterpreted as HTML without escaping meta-characters.
}
return res.send('Login successful');
});
});
Comment on lines +29 to +43

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.


// Vulnerable attachment endpoint
app.get('/attachment/:name', (req, res) => {
// This line directly takes the user input and appends it to the directory path
const attachmentName = req.params.name;
const attachmentPath = path.join(__dirname, 'attachments', attachmentName);

// Check if file exists
if (!fs.existsSync(attachmentPath)) {

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.
return res.status(404).send('Attachment not found');
}

// Read the file and send it in the response
fs.readFile(attachmentPath, (err, data) => {

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.
if (err) {
return res.status(500).send('Error reading file');
}
res.setHeader('Content-Type', 'text/plain');
res.send(data);
});
});
Comment on lines +47 to +65

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a file system access
, but is not rate-limited.
This route handler performs
a file system access
, but is not rate-limited.

const server = app.listen(port, () => {
console.log(`Listening at http://localhost:${port}`);
});
Expand Down
1 change: 1 addition & 0 deletions attachments/a
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello
1 change: 1 addition & 0 deletions attachments/test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello
1 change: 1 addition & 0 deletions attachments/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello World
68 changes: 67 additions & 1 deletion openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,70 @@ paths:
type: string
example: Hello, World!


/login:
get:
summary: User login
description: "Allows user to log in (Note: this is an unsafe method and not recommended for production use)."
parameters:
- in: query
name: email
required: true
description: User's email
schema:
type: string
format: email
- in: query
name: password
required: true
description: User's password
schema:
type: string
responses:
'200':
description: Login successful
content:
text/html:
schema:
type: string
example: "<p>Login successful</p>"
'400':
description: Bad request, parameters missing or invalid
content:
text/html:
schema:
type: string
example: "<p>Bad request</p>"

/attachment/{name}:
get:
summary: Retrieve attachment
description: "Endpoint to retrieve an attachment by name. Warning: This endpoint is vulnerable to path traversal attacks and is only for demo purposes."
parameters:
- in: path
name: name
required: true
description: The name of the attachment to retrieve, such as "test.txt"
schema:
type: string
responses:
'200':
description: Attachment retrieved successfully
content:
text/plain:
schema:
type: string
example: "Contents of the file..."
'400':
description: Bad request, parameters missing or invalid
content:
text/html:
schema:
type: string
example: "<p>Bad request</p>"
'404':
description: Attachment not found
content:
text/html:
schema:
type: string
example: "<p>Attachment not found</p>"
Loading