-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp2.js
More file actions
221 lines (221 loc) · 6.64 KB
/
app2.js
File metadata and controls
221 lines (221 loc) · 6.64 KB
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
const express = require('express');
const mysql = require('mysql2');
const jwt = require('jsonwebtoken'); // For JWT token
const app = express();
// const fs = require('fs');
// const path = require('path');
const swaggerUi = require('swagger-ui-express');
const swaggerJsdoc = require('swagger-jsdoc');
// Middleware to parse JSON request bodies
app.use(express.json());
// ----------------- this section is only for debug purpose to generate the token in the console log to be used to test in the Postman-------------
// Payload (data) for the token
const payload = {
userId: 123, // Example user ID
username: 'testuser'
};
// Generate the token
const token = jwt.sign(payload, "this_is_not_really_a_JWT_secret", { expiresIn: '365d' });
console.log('Generated JWT Token:', token);
// ----------------- this section is only for debug purpose to generate the token in the console log to be used to test in the Postman-------------
// Create a MySQL connection pool
const pool = mysql.createPool({
host: 'mysql',
user: 'root',
password: 'password',
database: 'testdb',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// Promisify pool.query to use async/await (optional but convenient)
const poolPromise = pool.promise();
// Vulnerable route (SQL Injection)
// No authentication for this route, and it's vulnerable to SQL injection
app.get('/', (req, res) => {
res.send(`
<form action="/user" method="GET">
<label for="name">Enter user name:</label>
<input type="text" id="name" name="name">
<button type="submit">Submit</button>
</form>
`);
});
// SQL Injection vulnerability - no authentication required
app.get('/user', async (req, res) => {
const userName = req.query.name;
try {
// SQL Injection: User input is directly injected into the SQL query without sanitization
const [results] = await poolPromise.query(`SELECT * FROM users WHERE name = '${userName}'`);
if (results.length > 0) {
res.send(`User found: ${JSON.stringify(results)}`);
} else {
res.send('No user found');
}
} catch (err) {
console.error('Error executing query:', err);
res.status(500).send('Internal Server Error');
}
});
// Middleware to protect routes with JWT authentication
const authenticateJWT = (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer ')) {
const token = authHeader.split(' ')[1];
jwt.verify(token, "this_is_not_really_a_JWT_secret", (err, user) => {
if (err) {
return res.sendStatus(403);
}
req.user = user;
next();
});
} else {
res.sendStatus(401);
}
};
// XSS Vulnerability in /api/data API (with JWT authentication)
app.post('/api/data', authenticateJWT, (req, res) => {
const { inputData } = req.body;
// XSS vulnerability: No sanitization of user input
const responseData = `<div>User Input: ${inputData}</div>`;
// Send a 200 OK status code and the response
res.status(200).send({
message: 'Request was successful!',
data: responseData
});
});
// Insecure Deserialization Vulnerability
app.post('/api/deserialize', authenticateJWT, (req, res) => {
try {
// Vulnerable deserialization: User-provided JSON is parsed directly
const data = JSON.parse(req.body.serializedData);
// Example usage of deserialized data
res.status(200).send({
message: 'Data deserialized successfully',
data: data
});
} catch (error) {
res.status(400).send('Invalid input');
}
});
// app.get('/openapi.yml', (req, res) => {
// const yamlPath = path.join(__dirname, 'openapi.yaml');
// fs.readFile(yamlPath, 'utf8', (err, data) => {
// if (err) {
// res.status(500).send('Could not load OpenAPI YAML file');
// } else {
// res.setHeader('Content-Type', 'text/yaml');
// res.send(data);
// }
// });
// });
// Swagger definition setup
const swaggerDefinition = {
openapi: '3.0.0',
info: {
title: 'Vulnerable App API',
version: '1.0.0',
description: 'API documentation for the vulnerable app implementing OWASP top 10 vulnerabilities.',
},
servers: [
{
url: 'http://localhost:3000',
description: 'Local server',
},
],
};
const options = {
swaggerDefinition,
apis: ['./app.js'], // Path to the API docs
};
const swaggerSpec = swaggerJsdoc(options);
/**
* @swagger
* /:
* get:
* summary: SQL Injection vulnerability example
* description: This route demonstrates SQL injection by allowing unsanitized input directly into the SQL query.
* responses:
* 200:
* description: Form to submit username for SQL query.
*/
/**
* @swagger
* /user:
* get:
* summary: SQL Injection vulnerability
* description: Fetches user details based on unsanitized input, leading to SQL Injection vulnerability.
* parameters:
* - in: query
* name: name
* schema:
* type: string
* description: Name of the user to query
* responses:
* 200:
* description: User details
* 500:
* description: Internal server error
*/
/**
* @swagger
* /api/data:
* post:
* summary: XSS Vulnerability
* description: Returns user input without sanitization, leading to XSS vulnerability.
* security:
* - BearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* inputData:
* type: string
* responses:
* 200:
* description: User input echoed back
* 403:
* description: Forbidden
*/
/**
* @swagger
* /api/deserialize:
* post:
* summary: Insecure Deserialization Vulnerability
* description: Accepts user input and deserializes it without validation, leading to potential insecure deserialization vulnerability.
* security:
* - BearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* serializedData:
* type: string
* responses:
* 200:
* description: Successfully deserialized the data
* 400:
* description: Bad Request
*/
// Bearer Authentication definition
/**
* @swagger
* components:
* securitySchemes:
* BearerAuth:
* type: http
* scheme: bearer
* bearerFormat: JWT
*/
// Serve Swagger docs at /api-docs
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
// Start the application
app.listen(3000, () => {
console.log('Server is running on port 3000');
});