├── README.md
├── database-service
├── Dockerfile
└── setup.sql
├── docker-compose.yml
├── screenshots
├── 1.png
└── 2.png
└── web-service
├── Dockerfile
├── api
├── .gitignore
├── app.js
├── config
│ └── DataBaseHandler.js
├── package-lock.json
├── package.json
├── public
│ ├── javascript
│ │ └── index.js
│ └── stylesheets
│ │ └── style.css
├── routes
│ └── index.js
└── views
│ └── index.jade
└── start.sh
/README.md:
--------------------------------------------------------------------------------
1 | # NodeJS WebSocket SQLi vulnerable WebApp
2 |
3 | A one-day build of a vulnerable WebSocket app on NodeJS to practice boolean based SQLi over WebSocket.
4 |
5 | I made this for others to learn and automate SQLi over WebSocket, additionally an input box is added to the homepage to quickly test out a query. Here are some exercises for practice:
6 |
7 | * Try dumping some data from the DB through the input box on the homepage.
8 | * Build a script to automate dumping data via boolean-based blind SQLi over WebSocket.
9 | * Build a script to automate dumping data via Time-based blind SQLi over WebSocket.
10 | * Build a middle-ware HTTP Server script to relay SQLMap payloads to WebSocket.
11 |
12 | Check my blog post where I have shared the last exercise here: https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html
13 |
14 |
15 | ## Run
16 |
17 | 1. run : `docker-compose up`
18 | 2. visit : http://localhost:8156/
19 |
20 |
21 | ## ScreenShots
22 |
23 | 
24 |
25 | 
26 |
27 |
--------------------------------------------------------------------------------
/database-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mysql:8.0
2 |
3 | ENV MYSQL_ROOT_PASSWORD SuperStrongPassWord
4 | ENV MYSQL_DATABASE employeeDB
5 | ENV MYSQL_USER user_svc
6 | ENV MYSQL_PASSWORD SuperStrongPassWord
7 |
8 | ADD setup.sql /docker-entrypoint-initdb.d
9 |
--------------------------------------------------------------------------------
/database-service/setup.sql:
--------------------------------------------------------------------------------
1 | /***CREATING ALL TABLES*/
2 | CREATE TABLE EMPLOYEE (
3 | EmployeeId INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
4 | UserName VARCHAR(40) NULL,
5 | Email VARCHAR(100) NULL,
6 | Pin VARCHAR(100) NULL,
7 | CreationDate DATETIME NULL
8 | )
9 | ENGINE = INNODB;
10 |
11 | /* INSERT DATA */
12 | INSERT INTO EMPLOYEE (UserName, Email, Pin, CreationDate)
13 | VALUES ('sysadmin', 'sysadmin@rh0x01.local', '31333337', '2021-03-31 13:17:17');
14 |
15 | INSERT INTO EMPLOYEE (UserName, Email, Pin, CreationDate)
16 | VALUES ('intern1', 'intern_001@rh0x01.local', '90000008', '2021-03-31 13:17:17');
17 |
18 | INSERT INTO EMPLOYEE (UserName, Email, Pin, CreationDate)
19 | VALUES ('intern2', 'intern_002@rh0x01.local', '91111118', '2021-03-31 13:17:17');
20 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | web:
3 | build: ./web-service
4 | ports:
5 | - "8156:8156"
6 | depends_on:
7 | - db
8 | environment:
9 | - DATABASE_HOST=db
10 | volumes:
11 | - ./web-service/api:/app/api
12 | db:
13 | build: ./database-service
14 | command: --default-authentication-plugin=mysql_native_password
15 | restart: always
16 | ports:
17 | - 3318:3306
18 |
--------------------------------------------------------------------------------
/screenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rayhan0x01/nodejs-websocket-sqli/2fd5b02f133428fae6ad701605c1553314dc895d/screenshots/1.png
--------------------------------------------------------------------------------
/screenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rayhan0x01/nodejs-websocket-sqli/2fd5b02f133428fae6ad701605c1553314dc895d/screenshots/2.png
--------------------------------------------------------------------------------
/web-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:14.5.0
2 |
3 | ADD start.sh /start.sh
4 | RUN chmod 755 /start.sh
5 | CMD ["/start.sh"]
6 |
--------------------------------------------------------------------------------
/web-service/api/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # Snowpack dependency directory (https://snowpack.dev/)
45 | web_modules/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 | .parcel-cache
78 |
79 | # Next.js build output
80 | .next
81 | out
82 |
83 | # Nuxt.js build / generate output
84 | .nuxt
85 | dist
86 |
87 | # Gatsby files
88 | .cache/
89 | # Comment in the public line in if your project uses Gatsby and not Next.js
90 | # https://nextjs.org/blog/next-9-1#public-directory-support
91 | # public
92 |
93 | # vuepress build output
94 | .vuepress/dist
95 |
96 | # Serverless directories
97 | .serverless/
98 |
99 | # FuseBox cache
100 | .fusebox/
101 |
102 | # DynamoDB Local files
103 | .dynamodb/
104 |
105 | # TernJS port file
106 | .tern-port
107 |
108 | # Stores VSCode versions used for testing VSCode extensions
109 | .vscode-test
110 |
111 | # yarn v2
112 | .yarn/cache
113 | .yarn/unplugged
114 | .yarn/build-state.yml
115 | .yarn/install-state.gz
116 | .pnp.*
--------------------------------------------------------------------------------
/web-service/api/app.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 |
3 | var bodyParser = require('body-parser');
4 |
5 | var app = express();
6 |
7 | var expressWs = require('express-ws')(app);
8 |
9 | var index = require('./routes/index');
10 |
11 | app.set("view engine", "jade");
12 |
13 | app.use(bodyParser.json());
14 | app.use(bodyParser.urlencoded({extended: true}));
15 | app.use(express.static("public"));
16 | app.use('/', index);
17 |
18 | app.listen(8156);
19 |
--------------------------------------------------------------------------------
/web-service/api/config/DataBaseHandler.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Credits : https://github.com/CarlitosDroid/docker-compose-nodejs-mysql
3 | * Created by Carlos Leonardo Camilo Vargas HUuamán on 11/20/16.
4 | */
5 |
6 | var mysql = require("mysql");
7 |
8 | function DataBaseHandler() {
9 | this.connection = null;
10 | }
11 |
12 | DataBaseHandler.prototype.createConnection = function () {
13 |
14 | this.connection = mysql.createConnection({
15 | host: process.env.DATABASE_HOST || '127.0.0.1',
16 | user: 'root',
17 | password: 'SuperStrongPassWord',
18 | database: 'employeeDB',
19 | port: 3306
20 | });
21 |
22 | this.connection.connect(function (err) {
23 | if (err) {
24 | console.error("error connecting " + err.stack);
25 | return null;
26 | }
27 | console.log("connected as id " + this.threadId);
28 | });
29 | return this.connection;
30 | };
31 |
32 | module.exports = DataBaseHandler;
33 |
--------------------------------------------------------------------------------
/web-service/api/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodejs_websocket_sqli",
3 | "version": "0.0.1",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "accepts": {
8 | "version": "1.3.7",
9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
11 | "requires": {
12 | "mime-types": "~2.1.24",
13 | "negotiator": "0.6.2"
14 | }
15 | },
16 | "acorn": {
17 | "version": "2.7.0",
18 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
19 | "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc="
20 | },
21 | "acorn-globals": {
22 | "version": "1.0.9",
23 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz",
24 | "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=",
25 | "requires": {
26 | "acorn": "^2.1.0"
27 | }
28 | },
29 | "align-text": {
30 | "version": "0.1.4",
31 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
32 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
33 | "requires": {
34 | "kind-of": "^3.0.2",
35 | "longest": "^1.0.1",
36 | "repeat-string": "^1.5.2"
37 | }
38 | },
39 | "amdefine": {
40 | "version": "1.0.1",
41 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
42 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
43 | },
44 | "array-flatten": {
45 | "version": "1.1.1",
46 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
47 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
48 | },
49 | "asap": {
50 | "version": "1.0.0",
51 | "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz",
52 | "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0="
53 | },
54 | "async-limiter": {
55 | "version": "1.0.1",
56 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
57 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
58 | },
59 | "bignumber.js": {
60 | "version": "9.0.0",
61 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
62 | "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
63 | },
64 | "body-parser": {
65 | "version": "1.19.0",
66 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
67 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
68 | "requires": {
69 | "bytes": "3.1.0",
70 | "content-type": "~1.0.4",
71 | "debug": "2.6.9",
72 | "depd": "~1.1.2",
73 | "http-errors": "1.7.2",
74 | "iconv-lite": "0.4.24",
75 | "on-finished": "~2.3.0",
76 | "qs": "6.7.0",
77 | "raw-body": "2.4.0",
78 | "type-is": "~1.6.17"
79 | }
80 | },
81 | "bytes": {
82 | "version": "3.1.0",
83 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
84 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
85 | },
86 | "camelcase": {
87 | "version": "1.2.1",
88 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
89 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
90 | },
91 | "center-align": {
92 | "version": "0.1.3",
93 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
94 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
95 | "requires": {
96 | "align-text": "^0.1.3",
97 | "lazy-cache": "^1.0.3"
98 | }
99 | },
100 | "character-parser": {
101 | "version": "1.2.1",
102 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz",
103 | "integrity": "sha1-wN3kqxgnE7kZuXCVmhI+zBow/NY="
104 | },
105 | "clean-css": {
106 | "version": "3.4.28",
107 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
108 | "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
109 | "requires": {
110 | "commander": "2.8.x",
111 | "source-map": "0.4.x"
112 | },
113 | "dependencies": {
114 | "commander": {
115 | "version": "2.8.1",
116 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
117 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
118 | "requires": {
119 | "graceful-readlink": ">= 1.0.0"
120 | }
121 | }
122 | }
123 | },
124 | "cliui": {
125 | "version": "2.1.0",
126 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
127 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
128 | "requires": {
129 | "center-align": "^0.1.1",
130 | "right-align": "^0.1.1",
131 | "wordwrap": "0.0.2"
132 | },
133 | "dependencies": {
134 | "wordwrap": {
135 | "version": "0.0.2",
136 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
137 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
138 | }
139 | }
140 | },
141 | "commander": {
142 | "version": "2.6.0",
143 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz",
144 | "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0="
145 | },
146 | "constantinople": {
147 | "version": "3.0.2",
148 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz",
149 | "integrity": "sha1-S5RdmTeQe82Y7ldRIsOBdRZUQUE=",
150 | "requires": {
151 | "acorn": "^2.1.0"
152 | }
153 | },
154 | "content-disposition": {
155 | "version": "0.5.3",
156 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
157 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
158 | "requires": {
159 | "safe-buffer": "5.1.2"
160 | }
161 | },
162 | "content-type": {
163 | "version": "1.0.4",
164 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
165 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
166 | },
167 | "cookie": {
168 | "version": "0.4.0",
169 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
170 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
171 | },
172 | "cookie-signature": {
173 | "version": "1.0.6",
174 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
175 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
176 | },
177 | "core-util-is": {
178 | "version": "1.0.2",
179 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
180 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
181 | },
182 | "css": {
183 | "version": "1.0.8",
184 | "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz",
185 | "integrity": "sha1-k4aBHKgrzMnuf7WnMrHioxfIo+c=",
186 | "requires": {
187 | "css-parse": "1.0.4",
188 | "css-stringify": "1.0.5"
189 | }
190 | },
191 | "css-parse": {
192 | "version": "1.0.4",
193 | "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz",
194 | "integrity": "sha1-OLBQP7+dqfVOnB29pg4UXHcRe90="
195 | },
196 | "css-stringify": {
197 | "version": "1.0.5",
198 | "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz",
199 | "integrity": "sha1-sNBClG2ylTu50pKQCmy19tASIDE="
200 | },
201 | "debug": {
202 | "version": "2.6.9",
203 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
204 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
205 | "requires": {
206 | "ms": "2.0.0"
207 | }
208 | },
209 | "decamelize": {
210 | "version": "1.2.0",
211 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
212 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
213 | },
214 | "depd": {
215 | "version": "1.1.2",
216 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
217 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
218 | },
219 | "destroy": {
220 | "version": "1.0.4",
221 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
222 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
223 | },
224 | "ee-first": {
225 | "version": "1.1.1",
226 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
227 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
228 | },
229 | "encodeurl": {
230 | "version": "1.0.2",
231 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
232 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
233 | },
234 | "escape-html": {
235 | "version": "1.0.3",
236 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
237 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
238 | },
239 | "etag": {
240 | "version": "1.8.1",
241 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
242 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
243 | },
244 | "express": {
245 | "version": "4.17.1",
246 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
247 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
248 | "requires": {
249 | "accepts": "~1.3.7",
250 | "array-flatten": "1.1.1",
251 | "body-parser": "1.19.0",
252 | "content-disposition": "0.5.3",
253 | "content-type": "~1.0.4",
254 | "cookie": "0.4.0",
255 | "cookie-signature": "1.0.6",
256 | "debug": "2.6.9",
257 | "depd": "~1.1.2",
258 | "encodeurl": "~1.0.2",
259 | "escape-html": "~1.0.3",
260 | "etag": "~1.8.1",
261 | "finalhandler": "~1.1.2",
262 | "fresh": "0.5.2",
263 | "merge-descriptors": "1.0.1",
264 | "methods": "~1.1.2",
265 | "on-finished": "~2.3.0",
266 | "parseurl": "~1.3.3",
267 | "path-to-regexp": "0.1.7",
268 | "proxy-addr": "~2.0.5",
269 | "qs": "6.7.0",
270 | "range-parser": "~1.2.1",
271 | "safe-buffer": "5.1.2",
272 | "send": "0.17.1",
273 | "serve-static": "1.14.1",
274 | "setprototypeof": "1.1.1",
275 | "statuses": "~1.5.0",
276 | "type-is": "~1.6.18",
277 | "utils-merge": "1.0.1",
278 | "vary": "~1.1.2"
279 | }
280 | },
281 | "express-ws": {
282 | "version": "4.0.0",
283 | "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-4.0.0.tgz",
284 | "integrity": "sha512-KEyUw8AwRET2iFjFsI1EJQrJ/fHeGiJtgpYgEWG3yDv4l/To/m3a2GaYfeGyB3lsWdvbesjF5XCMx+SVBgAAYw==",
285 | "requires": {
286 | "ws": "^5.2.0"
287 | }
288 | },
289 | "finalhandler": {
290 | "version": "1.1.2",
291 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
292 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
293 | "requires": {
294 | "debug": "2.6.9",
295 | "encodeurl": "~1.0.2",
296 | "escape-html": "~1.0.3",
297 | "on-finished": "~2.3.0",
298 | "parseurl": "~1.3.3",
299 | "statuses": "~1.5.0",
300 | "unpipe": "~1.0.0"
301 | }
302 | },
303 | "forwarded": {
304 | "version": "0.1.2",
305 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
306 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
307 | },
308 | "fresh": {
309 | "version": "0.5.2",
310 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
311 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
312 | },
313 | "graceful-readlink": {
314 | "version": "1.0.1",
315 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
316 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
317 | },
318 | "http-errors": {
319 | "version": "1.7.2",
320 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
321 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
322 | "requires": {
323 | "depd": "~1.1.2",
324 | "inherits": "2.0.3",
325 | "setprototypeof": "1.1.1",
326 | "statuses": ">= 1.5.0 < 2",
327 | "toidentifier": "1.0.0"
328 | }
329 | },
330 | "iconv-lite": {
331 | "version": "0.4.24",
332 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
333 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
334 | "requires": {
335 | "safer-buffer": ">= 2.1.2 < 3"
336 | }
337 | },
338 | "inherits": {
339 | "version": "2.0.3",
340 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
341 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
342 | },
343 | "ipaddr.js": {
344 | "version": "1.9.1",
345 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
346 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
347 | },
348 | "is-buffer": {
349 | "version": "1.1.6",
350 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
351 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
352 | },
353 | "is-promise": {
354 | "version": "2.2.2",
355 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
356 | "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
357 | },
358 | "isarray": {
359 | "version": "1.0.0",
360 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
361 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
362 | },
363 | "jade": {
364 | "version": "1.11.0",
365 | "resolved": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz",
366 | "integrity": "sha1-nIDlOMEtP7lcjZu5VZ+gzAQEBf0=",
367 | "requires": {
368 | "character-parser": "1.2.1",
369 | "clean-css": "^3.1.9",
370 | "commander": "~2.6.0",
371 | "constantinople": "~3.0.1",
372 | "jstransformer": "0.0.2",
373 | "mkdirp": "~0.5.0",
374 | "transformers": "2.1.0",
375 | "uglify-js": "^2.4.19",
376 | "void-elements": "~2.0.1",
377 | "with": "~4.0.0"
378 | }
379 | },
380 | "jquery": {
381 | "version": "3.6.0",
382 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
383 | "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
384 | },
385 | "jstransformer": {
386 | "version": "0.0.2",
387 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-0.0.2.tgz",
388 | "integrity": "sha1-eq4pqQPRls+glz2IXT5HlH7Ndqs=",
389 | "requires": {
390 | "is-promise": "^2.0.0",
391 | "promise": "^6.0.1"
392 | }
393 | },
394 | "kind-of": {
395 | "version": "3.2.2",
396 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
397 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
398 | "requires": {
399 | "is-buffer": "^1.1.5"
400 | }
401 | },
402 | "lazy-cache": {
403 | "version": "1.0.4",
404 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
405 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
406 | },
407 | "longest": {
408 | "version": "1.0.1",
409 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
410 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
411 | },
412 | "media-typer": {
413 | "version": "0.3.0",
414 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
415 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
416 | },
417 | "merge-descriptors": {
418 | "version": "1.0.1",
419 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
420 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
421 | },
422 | "methods": {
423 | "version": "1.1.2",
424 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
425 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
426 | },
427 | "mime": {
428 | "version": "1.6.0",
429 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
430 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
431 | },
432 | "mime-db": {
433 | "version": "1.46.0",
434 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz",
435 | "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ=="
436 | },
437 | "mime-types": {
438 | "version": "2.1.29",
439 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz",
440 | "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==",
441 | "requires": {
442 | "mime-db": "1.46.0"
443 | }
444 | },
445 | "minimist": {
446 | "version": "1.2.5",
447 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
448 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
449 | },
450 | "mkdirp": {
451 | "version": "0.5.5",
452 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
453 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
454 | "requires": {
455 | "minimist": "^1.2.5"
456 | }
457 | },
458 | "ms": {
459 | "version": "2.0.0",
460 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
461 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
462 | },
463 | "mysql": {
464 | "version": "2.18.1",
465 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
466 | "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
467 | "requires": {
468 | "bignumber.js": "9.0.0",
469 | "readable-stream": "2.3.7",
470 | "safe-buffer": "5.1.2",
471 | "sqlstring": "2.3.1"
472 | }
473 | },
474 | "negotiator": {
475 | "version": "0.6.2",
476 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
477 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
478 | },
479 | "on-finished": {
480 | "version": "2.3.0",
481 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
482 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
483 | "requires": {
484 | "ee-first": "1.1.1"
485 | }
486 | },
487 | "optimist": {
488 | "version": "0.3.7",
489 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
490 | "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=",
491 | "requires": {
492 | "wordwrap": "~0.0.2"
493 | }
494 | },
495 | "parseurl": {
496 | "version": "1.3.3",
497 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
498 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
499 | },
500 | "path": {
501 | "version": "0.12.7",
502 | "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
503 | "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=",
504 | "requires": {
505 | "process": "^0.11.1",
506 | "util": "^0.10.3"
507 | }
508 | },
509 | "path-to-regexp": {
510 | "version": "0.1.7",
511 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
512 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
513 | },
514 | "process": {
515 | "version": "0.11.10",
516 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
517 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
518 | },
519 | "process-nextick-args": {
520 | "version": "2.0.1",
521 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
522 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
523 | },
524 | "promise": {
525 | "version": "6.1.0",
526 | "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
527 | "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=",
528 | "requires": {
529 | "asap": "~1.0.0"
530 | }
531 | },
532 | "proxy-addr": {
533 | "version": "2.0.6",
534 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
535 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
536 | "requires": {
537 | "forwarded": "~0.1.2",
538 | "ipaddr.js": "1.9.1"
539 | }
540 | },
541 | "qs": {
542 | "version": "6.7.0",
543 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
544 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
545 | },
546 | "range-parser": {
547 | "version": "1.2.1",
548 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
549 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
550 | },
551 | "raw-body": {
552 | "version": "2.4.0",
553 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
554 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
555 | "requires": {
556 | "bytes": "3.1.0",
557 | "http-errors": "1.7.2",
558 | "iconv-lite": "0.4.24",
559 | "unpipe": "1.0.0"
560 | }
561 | },
562 | "readable-stream": {
563 | "version": "2.3.7",
564 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
565 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
566 | "requires": {
567 | "core-util-is": "~1.0.0",
568 | "inherits": "~2.0.3",
569 | "isarray": "~1.0.0",
570 | "process-nextick-args": "~2.0.0",
571 | "safe-buffer": "~5.1.1",
572 | "string_decoder": "~1.1.1",
573 | "util-deprecate": "~1.0.1"
574 | }
575 | },
576 | "repeat-string": {
577 | "version": "1.6.1",
578 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
579 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
580 | },
581 | "right-align": {
582 | "version": "0.1.3",
583 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
584 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
585 | "requires": {
586 | "align-text": "^0.1.1"
587 | }
588 | },
589 | "safe-buffer": {
590 | "version": "5.1.2",
591 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
592 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
593 | },
594 | "safer-buffer": {
595 | "version": "2.1.2",
596 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
597 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
598 | },
599 | "send": {
600 | "version": "0.17.1",
601 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
602 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
603 | "requires": {
604 | "debug": "2.6.9",
605 | "depd": "~1.1.2",
606 | "destroy": "~1.0.4",
607 | "encodeurl": "~1.0.2",
608 | "escape-html": "~1.0.3",
609 | "etag": "~1.8.1",
610 | "fresh": "0.5.2",
611 | "http-errors": "~1.7.2",
612 | "mime": "1.6.0",
613 | "ms": "2.1.1",
614 | "on-finished": "~2.3.0",
615 | "range-parser": "~1.2.1",
616 | "statuses": "~1.5.0"
617 | },
618 | "dependencies": {
619 | "ms": {
620 | "version": "2.1.1",
621 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
622 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
623 | }
624 | }
625 | },
626 | "serve-static": {
627 | "version": "1.14.1",
628 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
629 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
630 | "requires": {
631 | "encodeurl": "~1.0.2",
632 | "escape-html": "~1.0.3",
633 | "parseurl": "~1.3.3",
634 | "send": "0.17.1"
635 | }
636 | },
637 | "setprototypeof": {
638 | "version": "1.1.1",
639 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
640 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
641 | },
642 | "source-map": {
643 | "version": "0.4.4",
644 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
645 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
646 | "requires": {
647 | "amdefine": ">=0.0.4"
648 | }
649 | },
650 | "sqlstring": {
651 | "version": "2.3.1",
652 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
653 | "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
654 | },
655 | "statuses": {
656 | "version": "1.5.0",
657 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
658 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
659 | },
660 | "string_decoder": {
661 | "version": "1.1.1",
662 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
663 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
664 | "requires": {
665 | "safe-buffer": "~5.1.0"
666 | }
667 | },
668 | "toidentifier": {
669 | "version": "1.0.0",
670 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
671 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
672 | },
673 | "transformers": {
674 | "version": "2.1.0",
675 | "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz",
676 | "integrity": "sha1-XSPLNVYd2F3Gf7hIIwm0fVPM6ac=",
677 | "requires": {
678 | "css": "~1.0.8",
679 | "promise": "~2.0",
680 | "uglify-js": "~2.2.5"
681 | },
682 | "dependencies": {
683 | "is-promise": {
684 | "version": "1.0.1",
685 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz",
686 | "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU="
687 | },
688 | "promise": {
689 | "version": "2.0.0",
690 | "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz",
691 | "integrity": "sha1-RmSKqdYFr10ucMMCS/WUNtoCuA4=",
692 | "requires": {
693 | "is-promise": "~1"
694 | }
695 | },
696 | "source-map": {
697 | "version": "0.1.43",
698 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
699 | "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
700 | "requires": {
701 | "amdefine": ">=0.0.4"
702 | }
703 | },
704 | "uglify-js": {
705 | "version": "2.2.5",
706 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz",
707 | "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=",
708 | "requires": {
709 | "optimist": "~0.3.5",
710 | "source-map": "~0.1.7"
711 | }
712 | }
713 | }
714 | },
715 | "type-is": {
716 | "version": "1.6.18",
717 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
718 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
719 | "requires": {
720 | "media-typer": "0.3.0",
721 | "mime-types": "~2.1.24"
722 | }
723 | },
724 | "uglify-js": {
725 | "version": "2.8.29",
726 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
727 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
728 | "requires": {
729 | "source-map": "~0.5.1",
730 | "uglify-to-browserify": "~1.0.0",
731 | "yargs": "~3.10.0"
732 | },
733 | "dependencies": {
734 | "source-map": {
735 | "version": "0.5.7",
736 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
737 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
738 | }
739 | }
740 | },
741 | "uglify-to-browserify": {
742 | "version": "1.0.2",
743 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
744 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
745 | "optional": true
746 | },
747 | "unpipe": {
748 | "version": "1.0.0",
749 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
750 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
751 | },
752 | "util": {
753 | "version": "0.10.4",
754 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
755 | "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
756 | "requires": {
757 | "inherits": "2.0.3"
758 | }
759 | },
760 | "util-deprecate": {
761 | "version": "1.0.2",
762 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
763 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
764 | },
765 | "utils-merge": {
766 | "version": "1.0.1",
767 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
768 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
769 | },
770 | "vary": {
771 | "version": "1.1.2",
772 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
773 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
774 | },
775 | "void-elements": {
776 | "version": "2.0.1",
777 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
778 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
779 | },
780 | "window-size": {
781 | "version": "0.1.0",
782 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
783 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
784 | },
785 | "with": {
786 | "version": "4.0.3",
787 | "resolved": "https://registry.npmjs.org/with/-/with-4.0.3.tgz",
788 | "integrity": "sha1-7v0VTp550sjTQXtkeo8U2f7M4U4=",
789 | "requires": {
790 | "acorn": "^1.0.1",
791 | "acorn-globals": "^1.0.3"
792 | },
793 | "dependencies": {
794 | "acorn": {
795 | "version": "1.2.2",
796 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz",
797 | "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ="
798 | }
799 | }
800 | },
801 | "wordwrap": {
802 | "version": "0.0.3",
803 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
804 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
805 | },
806 | "ws": {
807 | "version": "5.2.2",
808 | "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
809 | "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
810 | "requires": {
811 | "async-limiter": "~1.0.0"
812 | }
813 | },
814 | "yargs": {
815 | "version": "3.10.0",
816 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
817 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
818 | "requires": {
819 | "camelcase": "^1.0.2",
820 | "cliui": "^2.1.0",
821 | "decamelize": "^1.0.0",
822 | "window-size": "0.1.0"
823 | }
824 | }
825 | }
826 | }
827 |
--------------------------------------------------------------------------------
/web-service/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodejs_websocket_sqli",
3 | "version": "0.0.1",
4 | "description": "A NodeJS WebSocket SQLi vulnerable WebApp",
5 | "main": "app.js",
6 | "scripts": {
7 | "start": "node app.js"
8 | },
9 | "keywords": [
10 | "nodejs",
11 | "websocket",
12 | "sqli",
13 | "sqlmap",
14 | "rayhan0x01"
15 | ],
16 | "author": "Rayhan0x01",
17 | "dependencies": {
18 | "body-parser": "^1.15.2",
19 | "express": "^4.14.0",
20 | "express-ws": "^4.0.0",
21 | "jade": "^1.11.0",
22 | "jquery": "^3.1.1",
23 | "mysql": "^2.10.2",
24 | "path": "^0.12.7"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/web-service/api/public/javascript/index.js:
--------------------------------------------------------------------------------
1 |
2 | $(document).ready(function(){
3 | $('#res-container').text('try a blind SQLi payload, ex: 54 or 1=1#');
4 | open_ws();
5 | $( "#eID" ).on('keyup',function( event ) {
6 | check_employee();
7 | });
8 | });
9 |
10 | function open_ws(){
11 | var HOST = location.origin.replace(/^http/, 'ws');
12 | window.ws = new WebSocket(HOST+'/ws');
13 |
14 | ws.onopen = function(event) {
15 | setInterval(ping, 30000);
16 | };
17 |
18 | ws.onmessage = function (event) {
19 |
20 | if (event.data == '__pong__') {
21 | pong();
22 | return;
23 | }
24 |
25 | try{
26 | msg = JSON.parse(event.data);
27 | $('#res-container').html(msg.message);
28 | } catch(e){
29 | $('#res-container').html(event.data);
30 | }
31 |
32 | }
33 |
34 | ws.onerror = function(event){
35 | try{
36 | msg = JSON.parse(event.data);
37 | $('#res-container').text(msg.message);
38 | } catch(e){
39 | $('#res-container').text(event.data);
40 | }
41 | }
42 |
43 | ws.onclose = function(event){
44 | console.log('Connection closed!');
45 | }
46 |
47 | }
48 |
49 | function check_employee(){
50 | var eID = $("#eID").val();
51 | if(eID){
52 | $('#res-container').text('Processing..');
53 |
54 | var msg = JSON.stringify({ employeeID: eID });
55 |
56 | ws.send(msg);
57 |
58 |
59 |
60 | }
61 |
62 |
63 | }
64 |
65 | function ping() {
66 | ws.send('__ping__');
67 | tm = setTimeout(function () {
68 |
69 | }, 5000);
70 | }
71 |
72 | function pong() {
73 | clearTimeout(tm);
74 | }
--------------------------------------------------------------------------------
/web-service/api/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Rajdhani&display=swap');
2 |
3 | body{
4 | text-align:center;
5 | background-color: #131212;
6 | color: white;
7 | font-family: 'Rajdhani', sans-serif;
8 | font-size:26px;
9 | }
10 |
11 | h1 {
12 | margin: 0;
13 | padding: 0;
14 | }
15 | ul {
16 | list-style:none;
17 | }
18 | #eID{
19 | width: 80%;
20 | height: 26px;
21 | border: 1px solid #000000;
22 | font-family: sans-serif;
23 | font-size: 16px;
24 | }
25 |
26 | #container{
27 | width: 100%;
28 | text-align: center;
29 | }
30 |
31 | footer {
32 | position: absolute;
33 | bottom: 20px;
34 | left: 50%;
35 | transform: translate(-50%, -50%);
36 | }
37 |
38 | a {
39 | text-decoration: none;
40 | color: #4fef7d;
41 | }
42 |
43 | a:visited{
44 | color: #4fef7d;
45 | }
46 |
47 | .red {
48 | color: red;
49 | }
50 |
51 | .lime {
52 | color: lime;
53 | }
--------------------------------------------------------------------------------
/web-service/api/routes/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 |
3 | var router = express.Router();
4 | var DataBaseHandler = require("../config/DataBaseHandler");
5 | var dataBaseHandler = new DataBaseHandler();
6 |
7 | var connection = dataBaseHandler.createConnection();
8 |
9 |
10 | router.get('/', function (req, res, next) {
11 | connection.query('SELECT * FROM EMPLOYEE;', function (error, result, fields) {
12 | if (error) {
13 | res.status(500).send({
14 | status: "Error",
15 | message: "Internal Server Error"
16 | });
17 | }
18 | else if(result.length == 0){
19 | res.status(404).send({
20 | status : "ERROR",
21 | message: "User does not exist"
22 | });
23 | }else{
24 | res.status(202);
25 | res.render('index.jade', { data: result });
26 | }
27 | });
28 | });
29 |
30 | router.ws('/ws', function(ws, req) {
31 | ws.on('message', function(msg) {
32 | if(msg == '__ping__'){
33 | ws.send('__pong__');
34 | return;
35 | }
36 | try{
37 | eJson = JSON.parse(msg);
38 | eID = eJson.employeeID;
39 | console.log(eID);
40 | query = `SELECT * FROM EMPLOYEE WHERE EmployeeId=${eID};`;
41 | console.log(query);
42 | connection.query(query, function (error, result, fields) {
43 | if (error) {
44 | ws.send('{"message": "Employee not found."}');
45 | }
46 | else if(result.length == 0){
47 | ws.send('{"message": "Employee not found."}');
48 | }else{
49 | ws.send('{"message": "Employee exists."}');
50 | }
51 | });
52 |
53 | } catch (e) {
54 | ws.send('{"message":"invalid command!"}');
55 | }
56 | });
57 | });
58 |
59 | module.exports = router;
--------------------------------------------------------------------------------
/web-service/api/views/index.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html
3 | head
4 | title NodeJS WebSocket SQLi vulnerable WebApp
5 | link(rel='stylesheet', href='/stylesheets/style.css')
6 | script(src='https://code.jquery.com/jquery-2.2.0.min.js')
7 | script(src='/javascript/index.js')
8 | body
9 | h1 Employee List:
10 | ul
11 | each item in data
12 | li
13 | p ID: #{item.EmployeeId}, #{item.Email}
14 | p Check Employee by ID:
15 | input(type="text", placeholder="employee ID", id="eID")
16 | br
17 | p Result
18 | #res-container
19 | br
20 | footer </> with ♥ by
21 | a(href="https://www.twitter.com/rayhan0x01") Rayhan0x01
--------------------------------------------------------------------------------
/web-service/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sleep 30
4 | cd /app/api
5 | npm install
6 | npm start
7 |
--------------------------------------------------------------------------------