* Disconnect clients that attempt to login with banned usernames for Telnet as well

* Slow disconnects to thwart brute force attacks - these names won't exist anyway,
  but we want the attacking client to not DoS us
This commit is contained in:
Bryan Ashby 2018-12-25 00:18:04 -07:00
parent 06a1925288
commit ee93035bb8
4 changed files with 38 additions and 21 deletions

View File

@ -25,6 +25,7 @@ This document attempts to track **major** changes and additions in ENiGMA½. For
* NNTP support! See [NNTP docs](/docs/servers/nntp.md) for more information.
* `oputil.js user rm` and `oputil.js user info` are in! See [oputil CLI](/docs/admin/oputil.md).
* Performing a file scan/import using `oputil.js fb scan` now recognizes various `FILES.BBS` formats.
* Usernames found in the `config.users.badUserNames` are now not only disallowed from applying, but disconnected at any login attempt.
## 0.0.8-alpha

View File

@ -57,39 +57,46 @@ function SSHClient(clientConn) {
}
};
function terminateConnection() {
const terminateConnection = () => {
safeContextReject();
return clientConn.end();
}
};
function promptAndTerm(msg) {
// slow version to thwart brute force attacks
const slowTerminateConnection = () => {
setTimeout( () => {
return terminateConnection();
}, 2000);
};
const promptAndTerm = (msg, method = 'standard') => {
if('keyboard-interactive' === ctx.method) {
ctx.prompt(msg);
}
return terminateConnection();
}
return 'slow' === method ? slowTerminateConnection() : terminateConnection();
};
function accountAlreadyLoggedIn(username) {
const accountAlreadyLoggedIn = (username) => {
return promptAndTerm(`${username} is already connected to the system. Terminating connection.\n(Press any key to continue)`);
}
};
function accountDisabled(username) {
const accountDisabled = (username) => {
return promptAndTerm(`${username} is disabled.\n(Press any key to continue)`);
}
};
function accountInactive(username) {
const accountInactive = (username) => {
return promptAndTerm(`${username} is waiting for +op activation.\n(Press any key to continue)`);
}
};
function accountLocked(username) {
return promptAndTerm(`${username} is locked.\n(Press any key to continue)`);
}
const accountLocked = (username) => {
return promptAndTerm(`${username} is locked.\n(Press any key to continue)`, 'slow');
};
function isSpecialHandleError(err) {
const isSpecialHandleError = (err) => {
return [ ErrorReasons.AlreadyLoggedIn, ErrorReasons.Disabled, ErrorReasons.Inactive, ErrorReasons.Locked ].includes(err.reasonCode);
}
};
function handleSpecialError(err, username) {
const handleSpecialError = (err, username) => {
switch(err.reasonCode) {
case ErrorReasons.AlreadyLoggedIn : return accountAlreadyLoggedIn(username);
case ErrorReasons.Inactive : return accountInactive(username);
@ -97,7 +104,7 @@ function SSHClient(clientConn) {
case ErrorReasons.Locked : return accountLocked(username);
default : return terminateConnection();
}
}
};
//
// If the system is open and |isNewUser| is true, the login
@ -115,7 +122,7 @@ function SSHClient(clientConn) {
}
if(Errors.BadLogin().code === err.code) {
return terminateConnection();
return slowTerminateConnection();
}
return safeContextReject(SSHClient.ValidAuthMethods);
@ -143,7 +150,7 @@ function SSHClient(clientConn) {
}
if(Errors.BadLogin().code === err.code) {
return terminateConnection();
return slowTerminateConnection();
}
const artOpts = {

View File

@ -34,6 +34,11 @@ function login(callingMenu, formData, extraArgs, cb) {
return callingMenu.gotoMenu(callingMenu.menuConfig.config.tooNodeMenu, cb);
}
// banned username results in disconnect
if(ErrorReasons.NotAllowed === err.reasonCode) {
return logoff(callingMenu, {}, {}, cb);
}
const ReasonsMenus = [
ErrorReasons.TooMany, ErrorReasons.Disabled, ErrorReasons.Inactive, ErrorReasons.Locked
];

View File

@ -27,7 +27,11 @@ function userLogin(client, username, password, cb) {
if(config.users.badUserNames.includes(username.toLowerCase())) {
client.log.info( { username : username }, 'Attempt to login with banned username');
return cb(Errors.BadLogin(ErrorReasons.NotAllowed));
// slow down a bit to thwart brute force attacks
return setTimeout( () => {
return cb(Errors.BadLogin('Disallowed username', ErrorReasons.NotAllowed));
}, 2000);
}
client.user.authenticate(username, password, err => {