├── Dockerfile ├── LICENSE ├── README.md ├── entrypoint.sh ├── install.sh └── ssrf-demo-app.js /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:alpine 2 | 3 | RUN mkdir -p /usr/src/app 4 | WORKDIR /usr/src/app 5 | COPY ssrf-demo-app.js ./ 6 | COPY entrypoint.sh ./ 7 | RUN npm install http express needle command-line-args 8 | ENTRYPOINT [ "node", "/usr/src/app/ssrf-demo-app.js", "-p" ] 9 | CMD ["8000"] 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Seth Art 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nodejs-SSRF-App 2 | Nodejs application intentionally vulnerable to SSRF 3 | 4 | ## Download and Setup 5 | 6 | ```ShellSession 7 | seth@ubuntu:/opt# sudo git clone https://github.com/sethsec/Nodejs-SSRF-App.git 8 | seth@ubuntu:/opt# cd Nodejs-SSRF-App/ 9 | seth@ubuntu:/opt/Nodejs-SSRF-App# sudo ./install.sh 10 | 11 | To start the server: 12 | sudo nodejs ssrf-demo-app.js 13 | sudo nodejs ssrf-demo-app.js -p 8080 14 | 15 | seth@ubuntu:/opt/Nodejs-SSRF-App# sudo nodejs ssrf-demo-app.js 16 | 17 | ################################################## 18 | # 19 | # Server listening for connections on port:80 20 | # Connect to server using the following url: 21 | # -- http://[server]:80/?url=[SSRF URL] 22 | # 23 | ################################################## 24 | 25 | ``` 26 | 27 | ## Build and run in a Docker container 28 | 29 | ```ShellSession 30 | ❯ git clone git@github.com:sethsec/Nodejs-SSRF-App.git 31 | ❯ cd Nodejs-SSRF-App/ 32 | ❯ docker build -t "nodejs-ssrf-app" . 33 | ❯ docker run -it -p 8000:8000 nodejs-ssrf-app:latest 34 | 35 | ################################################## 36 | # 37 | # Server listening for connections on port:8000 38 | # Connect to server using the following url: 39 | # -- http://[server]:8000/?url=[SSRF URL] 40 | # 41 | ################################################## 42 | ``` 43 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | node /usr/src/app/ssrf-demo-app.js -p 8000 3 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "[*] Installing Node and NPM" 4 | apt-get update 5 | apt-get -y install nodejs npm 6 | echo "[*] Installing node packages" 7 | npm install http express needle command-line-args 8 | echo 9 | echo "[*] Install complete!" 10 | echo 11 | echo " To start the server:" 12 | echo " sudo nodejs ssrf-demo-app.js" 13 | echo " sudo nodejs ssrf-demo-app.js -p 8080" 14 | echo 15 | -------------------------------------------------------------------------------- /ssrf-demo-app.js: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////// 2 | // SSRF Demo App 3 | // Node.js Application Vulnerable to SSRF 4 | // Written by Seth Art 5 | // MIT Licensed 6 | ////////////////////////////////////////// 7 | 8 | var http = require('http'); 9 | var needle = require('needle'); 10 | var express = require('express'); 11 | var app = express(); 12 | var commandLineArgs = require('command-line-args'); 13 | 14 | // Currently this app is also vulnerable to reflective XSS as well. Kind of an easter egg :) 15 | 16 | var cli = [ 17 | { name: 'port', alias: 'p', type: Number, defaultOption:80 } 18 | ] 19 | var options = commandLineArgs(cli) 20 | 21 | app.get('/', function(request, response){ 22 | var params = request.params; 23 | if (request.query['mime'] == 'plain'){ 24 | var mime = 'plain'; 25 | } else { 26 | var mime = 'html'; 27 | }; 28 | if (request.query['url'] ){ 29 | var url = request.query['url']; 30 | } else { 31 | response.writeHead(200, {'Content-Type': 'text/'+mime}); 32 | response.write('

Welcome to sethsec\'s SSRF demo.

\n\n'); 33 | response.write('

I am an application. I want to be useful, so if you specify the url parameter, I\'ll request the page for you:



\n\n\n'); 34 | response.write('

Example: http://IP:PORT/?url=https://ifconfig.me



\n\n\n'); 35 | 36 | response.end(); 37 | } 38 | 39 | console.log('New request: '+request.url); 40 | 41 | needle.get(url, { timeout: 3000 }, function(error, response1) { 42 | if (!error && response1.statusCode == 200) { 43 | response.writeHead(200, {'Content-Type': 'text/'+mime}); 44 | response.write('

Welcome to sethsec\'s SSRF demo.

\n\n'); 45 | response.write('

I am an application. I want to be useful, so I requested: '+url+' for you\n



\n\n\n'); 46 | console.log(response1.body); 47 | response.write(response1.body); 48 | response.end(); 49 | } else { 50 | response.writeHead(404, {'Content-Type': 'text/'+mime}); 51 | response.write('

Welcome to sethsec\'s SSRF demo.

\n\n'); 52 | response.write('

I wanted to be useful, but I could not find: '+url+' for you\n



\n\n\n'); 53 | response.end(); 54 | console.log('error') 55 | 56 | } 57 | }); 58 | }) 59 | if (options.port) { 60 | var port = options.port 61 | } else { 62 | var port = 80 63 | } 64 | 65 | app.listen(port); 66 | console.log('\n##################################################') 67 | console.log('#\n# Server listening for connections on port:'+port); 68 | console.log('# Connect to server using the following url: \n# -- http://[server]:'+port+'/?url=[SSRF URL]') 69 | console.log('#\n##################################################') 70 | --------------------------------------------------------------------------------