Reproduce a Timing Attack with Node.js - node.js

I'm trying to recreate a Timing Attack with Node.js for training purpose.
I think I'm doing something wrong, because I was expecting other results.
I've created a simple and basic Node app:
const express = require('express');
const app = express();
const PORT = 3000;
app.get('/', (req, res) => {
const password = 'cbfa'
const input = req.query.input
console.log(password, input)
setTimeout(() => {
res.set('Connection', 'close')
if(password === input) {
res.send('ok')
} else {
res.send('no')
}
}, 3000)
})
app.listen(PORT, (error) =>{
if(!error)
console.log('App is listening on port ' + PORT)
else
console.log('Error occurred', error)
}
)
When hitting http://localhost:3001/, it looks for an input parameter and compare it with the password, in this case 'cbfa'.
I've also created a curl-format.txt that shows the URL being called and the time total:
url: %{url}\n
time_total: %{time_total}\n
--------------------------------------------\n
and a urls.txt that contains the URL to be called:
url = "http://localhost:3000?input=aaaa"
url = "http://localhost:3000?input=bbbb"
url = "http://localhost:3000?input=cccc"
url = "http://localhost:3000?input=dddd"
With the app running, I run this:
curl --parallel --parallel-max 4 --config urls.txt -v -o /dev/null -s -w "#curl-format.txt"
Being the password 'cbfa', I was expecting the URL with ?input=cccc to take more time than the other, but this is the result:
url: http://localhost:3000?input=aaaa
time_total: 3.036737
--------------------------------------------
url: http://localhost:3000?input=bbbb
time_total: 3.055791
--------------------------------------------
url: http://localhost:3000?input=cccc
time_total: 3.056294
--------------------------------------------
url: http://localhost:3000?input=dddd
time_total: 3.070444
--------------------------------------------
What am I missing? What am I doing wrong?
Many thanks

Related

Posting data from EJS to Node.js

I have an index.html EJS rendered by a koa/Node.js app which contains a javascript snippet to post data about the current page to the same app, to an endpoint to save in a database.
The javascript code ( an AJAX fetch POST) reaches the Node.js endpoint but doesn't transmit any data. I don't see any typo in the code.
[CORRECTION] indeed a typo with the bodyparser
# index.js
const Koa = require("koa");
const path = require("path");
const render = require("koa-ejs");
const bodyParser = require("koa-bodyparser");
const router = require("./routes/routes.js");
const app = new Koa();
render(app, {
root: path.join(__dirname, "/views"),
layout: false,
viewExt: "html",
});
app
.use(bodyParser())
.use(router.routes())
.use(router.allowedMethods())
.use(staticCache("./images", { maxAge: 600000 }))
.listen(PORT, () => {
console.log(`Running on port ${PORT}`);
});
In the index.html, I have a button that triggers a POST request to an endpoint (/node/insert) of the koaRouter. The action is to save information about the current page (say, document.location.href) in a Postgres database.
# /views/index.html
[...]
<form id="newRow">
<input type="submit" value="New row">
</form>
[...]
<script type="module" src="fetch.js" async></script>
where:
# /views/fetch.js
const data = {
app: "Node",
url: document.location.href,
...
};
document.getElementById("newRow").addEventListener("submit", (e) => {
e.preventDefault();
fetch("/node/insert", {
method: "POST",
headers: {
"Content-Type": "application/json; charset-UTF-8",
},
body: JSON.stringify(data),
})
.then((res) => {
if (res.ok) {
return res.json();
}
return Promise.reject(res);
})
.then((res) => console.log("front", res))
.catch((err) => console.warn(err));
Among the routes, I defined an endpoint /node/insert to respond to this action:
# routes.js
const koaRouter = require("koa-router");
const router = new koaRouter();
router.post("/node/insert", async (ctx) => {
console.log("posted", ctx.request.body);
^^^ "posted" is positively printed in terminal after submit
if (ctx.request.body) {
return (ctx.response.status = 200)
} else {
return (ctx.response.status = 404); <-- check
}
})
The endpoint "/node/insert" is reached since I can console.log positively, but the body isn't passed to the endpoint: ctx.request.body = {}. I have the following error:
"SyntaxError: Unexpected token O in JSON at position 0"
detected from fetch.js (probably because the body is {}?).
I don't see what is wrong.
Note: the Node app runs in a container (pm2-runtime start index.js) and use Nginx as reverse proxy, static files server and load-balancer`
Try:
const koaJson = require(koa-json);
app.use(koaJson());
Just a typo in the bodyparser as Evert pointed and bad positioning of the middleware
curl --data "app=Node" HTTP://localhost:8000/node responds normaly.

How to set up Google Domains Dynamic DNS with Node.js & express?

I have set up a Node.Js website on my Raspberry Pi running express.
I want to update my google DNS domain, using Dynamic DNS, from Node.JS/Express
What I have attempted:
function domainUpdate() {
console.log(`[SERVER] Posting to Google's Servers...`)
let username = process.env.USERNAME || ``;
let password = process.env.PASSWORD || ``;
let hostname = process.env.HOSTNAME || ``;
let url = `https://${username}:${password}#domains.google.com/nic/update?hostname=${hostname}`;
https.request(url, (res) => {
console.log(`status - ${res.statusCode}`);
console.log(`output - ${res.complete}`)
}).on("error", (e) => {
if (e) throw e
})
Using curl commands it would look something like this:
curl https://$USERNAME:$PASSWORD#domains.google.com/nic/update?hostname=$HOSTNAME&myip=$IP_ADDRESS
there is no output except from "[SERVER] Posting to Google's Servers..."
Give something like Axios a try for making the actual request. It handles a lot of the heavy lifting for you:
const axios = require('axios');
function domainUpdate() {
console.log(`[SERVER] Posting to Google's Servers...`)
let username = process.env.USERNAME || ``;
let password = process.env.PASSWORD || ``;
let hostname = process.env.HOSTNAME || ``;
let url = `https://${username}:${password}#domains.google.com/nic/update?hostname=${hostname}`;
axios.get(url)
.then(res => {
console.log(`status - ${res.status}`);
console.log(`output - ${res.data}`);
})
.catch(err => {
throw err;
})
}
It looks like that endpoint returns a 200 as long as the request is formatted properly. The Google support article that you linked to lists the possible responses, which will be in the data property of your Axios response object.

Server Push with Nodejs pushStream method is not working

I am studying http2 on nodejs, but find out a issue pushStream method not working
(client side do not show "Pushed/[fileName]" on developer tool)
I wonder if the reason is nodejs version (I installed the latest version v9.8.0)
My codes is the following :
server.js
'use strict'
const fs = require('fs');
const path = require('path');
const http2 = require('http2');
const utils = require('./utils');
const { HTTP2_HEADER_PATH } = http2.constants;
const PORT = process.env.PORT || 3000;
// The files are pushed to stream here
function push(stream, path) {
const file = utils.getFile(path);
if (!file) {
return;
}
stream.pushStream({ [HTTP2_HEADER_PATH]: path}, (err, pushStream, headers) => {
if (err) throw err;
pushStream.respondWithFD(file.content, file.headers)
});
}
// Request handler
function onRequest(req, res) {
const reqPath = req.headers[':path'] === '/' ? '/index.html' : req.headers[':path']
const file = utils.getFile(reqPath);
// 404 - File not found
if (!file) {
res.statusCode = 404;
res.end();
return;
}
// Push with index.html
if (reqPath === '/index.html') {
push(res.stream, '/assets/main.js');
push(res.stream, '/assets/style.css');
} else {
console.log("requiring non index.html")
}
// Serve file
res.stream.respondWithFD(file.content, file.headers);
}
// creating an http2 server
const server = http2.createSecureServer({
cert: fs.readFileSync(path.join(__dirname, '/certificate.crt')),
key: fs.readFileSync(path.join(__dirname, '/privateKey.key'))
}, onRequest);
// start listening
server.listen(PORT, (err) => {
if (err) {
console.error(err);
return -1;
}
console.log(`Server listening to port ${PORT}`);
});
utils.js
'use strict';
const fs = require('fs');
const mime = require('mime');
module.exports = {
getFile: function (path) {
const filePath = `${__dirname}/public${path}`;
try {
const content = fs.openSync(filePath, 'r');
const contentType = mime.getType(filePath);
return {
content,
headers: {
'content-type': contentType
}
};
} catch (e) {
return null;
}
}
}
Updated 2020 01 28
Resolved: The reason is the latest version of chrome v65. has bug, cause client do not trust PUSH_PROMISE frame. I backup chrome v64 then it working now.
I haven’t tried to run your code but have noticed that Chrome does not allow HTTP/2 push with an untrusted HTTPS certificate (e.g. a self-signed one not yet added to the trust store). Raised a bug with the Chrome team.
If you have the red unsecure padlock item then you could be hitting this issue too. Add the certificate into your trust store, restart Chrome and reload the site where you should get a green padlock.
Note Chrome needs a certificate with a Subject Alternative Name (SAN) field matching the domain so if you’ve just got the older Subject field then it won’t go green even after adding it to your trust store.
Another option is to look at the Chrome HTTP2 frames by typing this into your URL:
chrome://net- internals/#http2
If you see the push promise frames (with a promised_stream_id), followed by the headers and data on that promised_stream_id then you know the sever side is working.

Node/Express - How to send get request to check a status code

I am trying to make a URL shortener. I need to take a given URL as a parameter and send a request to that URL just to get the status code. If status = 200, I know I've got a functioning URL, and I'll go ahead and add it to the DB and shorten it.
Problem is, when I make that request, the connection times out.
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const nofavicon = require('express-no-favicons')
const Shortener = require('./shortener')
const app = express()
app.disable('x-powered-by')
app.use(cors())
app.use(nofavicon())
app.use(express.static(__dirname + '/static'))
mongoose.connect(
process.env.MONGODB_URI || 'mongodb://heroku_x7hcc5zd:39c8i70697o7qrpjn4rd6kslch#ds123371.mlab.com:23371/heroku_x7hcc5zd'
)
app.get('/url/:urlParam(*)', (request, response) => {
let urlParam = request.params.urlParam
let urlRegEx = /[A-Za-z]+[://]+[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&;?#/.=]+/g
if (urlRegEx.test(urlParam)) {
let shortRandomNum = Math.floor(Math.random() * 10000).toString()
// Shortener here refers to a mongoose Schema in external file
let lmao = new Shortener({
url: urlParam,
urlmao: 'localhost:8080/lol/' + shortRandomNum,
})
// Request header from passed URL to verify legitimacy
// Check statusCode and end request.
app.head(urlParam, (req, res) => {
let end = res.end
// Override standard res.end function with custom function
res.end = () => {
if (res.statusCode == 200) {
lmao.save((error) => {
if (error) {
response.send('Unable to write to collection')
}
})
console.log('pass')
response.json({lmao})
}
}
res.end = end
res.end()
})
} else {
// If passed URL does not satisfy regEx, return error message.
urlParam = 'unfunny url. http(s):// prefix required. check url and retry.'
console.log('invalid url')
response.json({
url: urlParam,
})
}
})
app.listen(process.env.PORT || 8080, () => {
console.log('live connection')
})
Most baffingly, the code shown here worked on Friday. Tested it last night, no dice. Any insight would be greatly, greatly appreciated.
app.head(urlParam, [Function]) doesn't make a request to the url, it defines a new route on your application so that it responds to HEADrequests on that url.
To check if the URL is alive you need to use another package to make requests. One of my favourites is Request. To use it simply replace app.head with request and add the require('request') to the top of your file.

Collect all redirected URL of Origin URL using NodeJS

I want to retrieve a list of urls that are redirected from Origin URL X and it may have many redirected URLs but i want all list of it.
For example:
http://www.example.com/origin-url
It will redirect to
http://www.example.com/first-redirect
Again it will redirect to
http://www.example.com/second-redicect
And finally it goes to this
http://www.example.com/final-url
So what i want is list of all this URLs using NodeJs or Express
http://www.example.com/origin-url -->> http://www.example.com/first-redirect
-->> http://www.example.com/second-redicect -->> http://www.example.com/final-url
Give me suggestion for this and which node module should i have to use to achieve this.
Thanks in advance.
You can use the http module of NodeJS. You will need to check the statusCode, which for redirect is between 300-400. Please look at the below code.
var http = require('http')
function listAllRedirectURL(path) {
var reqPath = path;
return new Promise((resolve, reject) => {
var redirectArr = [];
function get(reqPath, cb){
http.get({
hostname: 'localhost',
port: 3000,
path: reqPath,
agent: false // create a new agent just for this one request
}, (res) => {
cb(res)
});
}
function callback(res) {
if (res.headers.hasOwnProperty('location') && res.statusCode >= 300 && res.statusCode < 400) {
console.log(res.headers.location);
redirectArr.push(res.headers.location);
reqPath = (res.headers.location);
get(reqPath, callback);
} else {
resolve(redirectArr);
}
}
get(reqPath, callback);
})
}
listAllRedirectURL('/');

Resources