mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 19:46:01 +01:00
dont allow login with invalid ip, escape ip display on user/info page
This commit is contained in:
@@ -6,6 +6,7 @@ var passport = require('passport');
|
|||||||
var nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
var validator = require('validator');
|
var validator = require('validator');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var ipaddr = require('ipaddr.js');
|
||||||
|
|
||||||
var db = require('../database');
|
var db = require('../database');
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
@@ -289,12 +290,19 @@ authenticationController.doLogin = function (req, uid, callback) {
|
|||||||
|
|
||||||
authenticationController.onSuccessfulLogin = function (req, uid, callback) {
|
authenticationController.onSuccessfulLogin = function (req, uid, callback) {
|
||||||
var uuid = utils.generateUUID();
|
var uuid = utils.generateUUID();
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
meta.blacklist.test(req.ip, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
user.logIP(uid, req.ip, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
req.session.meta = {};
|
req.session.meta = {};
|
||||||
|
|
||||||
delete req.session.forceLogin;
|
delete req.session.forceLogin;
|
||||||
|
|
||||||
// Associate IP used during login with user account
|
// Associate IP used during login with user account
|
||||||
user.logIP(uid, req.ip);
|
|
||||||
req.session.meta.ip = req.ip;
|
req.session.meta.ip = req.ip;
|
||||||
|
|
||||||
// Associate metadata retrieved via user-agent
|
// Associate metadata retrieved via user-agent
|
||||||
@@ -306,9 +314,6 @@ authenticationController.onSuccessfulLogin = function (req, uid, callback) {
|
|||||||
version: req.useragent.version,
|
version: req.useragent.version,
|
||||||
});
|
});
|
||||||
|
|
||||||
async.waterfall([
|
|
||||||
async.apply(meta.blacklist.test, req.ip),
|
|
||||||
function (next) {
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function (next) {
|
function (next) {
|
||||||
user.auth.addSession(uid, req.sessionID, next);
|
user.auth.addSession(uid, req.sessionID, next);
|
||||||
|
|||||||
@@ -68,7 +68,12 @@ Blacklist.test = function (clientIp, callback) {
|
|||||||
// clientIp = '127.0.15.1:3443'; // IPv4 with port strip port to not fail
|
// clientIp = '127.0.15.1:3443'; // IPv4 with port strip port to not fail
|
||||||
clientIp = clientIp.split(':').length === 2 ? clientIp.split(':')[0] : clientIp;
|
clientIp = clientIp.split(':').length === 2 ? clientIp.split(':')[0] : clientIp;
|
||||||
|
|
||||||
var addr = ipaddr.parse(clientIp);
|
var addr;
|
||||||
|
try {
|
||||||
|
addr = ipaddr.parse(clientIp);
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
Blacklist._rules.ipv4.indexOf(clientIp) === -1 && // not explicitly specified in ipv4 list
|
Blacklist._rules.ipv4.indexOf(clientIp) === -1 && // not explicitly specified in ipv4 list
|
||||||
@@ -88,11 +93,7 @@ Blacklist.test = function (clientIp, callback) {
|
|||||||
analytics.increment('blacklist');
|
analytics.increment('blacklist');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof callback === 'function') {
|
|
||||||
callback(err);
|
callback(err);
|
||||||
} else {
|
|
||||||
return !!err;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var err = new Error('[[error:blacklisted-ip]]');
|
var err = new Error('[[error:blacklisted-ip]]');
|
||||||
@@ -100,11 +101,7 @@ Blacklist.test = function (clientIp, callback) {
|
|||||||
|
|
||||||
analytics.increment('blacklist');
|
analytics.increment('blacklist');
|
||||||
|
|
||||||
if (typeof callback === 'function') {
|
|
||||||
setImmediate(callback, err);
|
setImmediate(callback, err);
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,41 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
var winston = require('winston');
|
||||||
|
var validator = require('validator');
|
||||||
|
|
||||||
var db = require('../database');
|
var db = require('../database');
|
||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var winston = require('winston');
|
|
||||||
|
|
||||||
module.exports = function (User) {
|
module.exports = function (User) {
|
||||||
User.logIP = function (uid, ip) {
|
User.logIP = function (uid, ip, callback) {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
db.sortedSetAdd('uid:' + uid + ':ip', now, ip || 'Unknown');
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
db.sortedSetAdd('uid:' + uid + ':ip', now, ip || 'Unknown', next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
if (ip) {
|
if (ip) {
|
||||||
db.sortedSetAdd('ip:' + ip + ':uid', now, uid);
|
db.sortedSetAdd('ip:' + ip + ':uid', now, uid, next);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
User.getIPs = function (uid, stop, callback) {
|
User.getIPs = function (uid, stop, callback) {
|
||||||
db.getSortedSetRevRange('uid:' + uid + ':ip', 0, stop, callback);
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
db.getSortedSetRevRange('uid:' + uid + ':ip', 0, stop, next);
|
||||||
|
},
|
||||||
|
function (ips, next) {
|
||||||
|
ips = ips.map(function (ip) {
|
||||||
|
return validator.escape(String(ip));
|
||||||
|
});
|
||||||
|
next(null, ips);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
User.getUsersCSV = function (callback) {
|
User.getUsersCSV = function (callback) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var winston = require('winston');
|
var winston = require('winston');
|
||||||
|
var validator = require('validator');
|
||||||
var db = require('../database');
|
var db = require('../database');
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
var events = require('../events');
|
var events = require('../events');
|
||||||
@@ -126,12 +127,15 @@ module.exports = function (User) {
|
|||||||
next(err, sessions);
|
next(err, sessions);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
], function (err, sessions) {
|
function (sessions, next) {
|
||||||
callback(err, sessions ? sessions.map(function (sessObj) {
|
sessions = sessions.map(function (sessObj) {
|
||||||
sessObj.meta.datetimeISO = new Date(sessObj.meta.datetime).toISOString();
|
sessObj.meta.datetimeISO = new Date(sessObj.meta.datetime).toISOString();
|
||||||
|
sessObj.meta.ip = validator.escape(String(sessObj.meta.ip));
|
||||||
return sessObj.meta;
|
return sessObj.meta;
|
||||||
}) : undefined);
|
|
||||||
});
|
});
|
||||||
|
next(null, sessions);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
User.auth.addSession = function (uid, sessionId, callback) {
|
User.auth.addSession = function (uid, sessionId, callback) {
|
||||||
|
|||||||
@@ -235,6 +235,36 @@ describe('authentication', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fail to login if ip address if invalid', function (done) {
|
||||||
|
var jar = request.jar();
|
||||||
|
request({
|
||||||
|
url: nconf.get('url') + '/api/config',
|
||||||
|
json: true,
|
||||||
|
jar: jar,
|
||||||
|
}, function (err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.post(nconf.get('url') + '/login', {
|
||||||
|
form: {
|
||||||
|
username: 'regular',
|
||||||
|
password: 'regularpwd',
|
||||||
|
},
|
||||||
|
json: true,
|
||||||
|
jar: jar,
|
||||||
|
headers: {
|
||||||
|
'x-csrf-token': body.csrf_token,
|
||||||
|
'x-forwarded-for': '<script>alert("xss")</script>',
|
||||||
|
},
|
||||||
|
}, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 500);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should fail to login if user does not exist', function (done) {
|
it('should fail to login if user does not exist', function (done) {
|
||||||
loginUser('doesnotexist', 'nopassword', function (err, response, body) {
|
loginUser('doesnotexist', 'nopassword', function (err, response, body) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|||||||
@@ -49,32 +49,24 @@ describe('blacklist', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pass ip test against blacklist async', function (done) {
|
it('should pass ip test against blacklist', function (done) {
|
||||||
blacklist.test('3.3.3.3', function (err) {
|
blacklist.test('3.3.3.3', function (err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pass ip test against blacklist sync', function (done) {
|
it('should fail ip test against blacklist', function (done) {
|
||||||
assert(!blacklist.test('3.3.3.3'));
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail ip test against blacklist async', function (done) {
|
|
||||||
blacklist.test('1.1.1.1', function (err) {
|
blacklist.test('1.1.1.1', function (err) {
|
||||||
assert.equal(err.message, '[[error:blacklisted-ip]]');
|
assert.equal(err.message, '[[error:blacklisted-ip]]');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail ip test against blacklist sync', function (done) {
|
|
||||||
assert(blacklist.test('1.1.1.1'));
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should pass ip test and not crash with ipv6 address', function (done) {
|
it('should pass ip test and not crash with ipv6 address', function (done) {
|
||||||
assert(!blacklist.test('2001:db8:85a3:0:0:8a2e:370:7334'));
|
blacklist.test('2001:db8:85a3:0:0:8a2e:370:7334', function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user