Headline
CVE-2020-27602: Refactor connection definition of userId to wait for validateAuthToken · bigbluebutton/bigbluebutton@4bfd924
BigBlueButton before 2.2.7 does not have a protection mechanism for separator injection in meetingId, userId, and authToken.
@@ -2,6 +2,9 @@ import { check } from 'meteor/check’;
import Logger from '/imports/startup/server/logger’;
import Users from '/imports/api/users’;
import userJoin from './userJoin’;
import pendingAuthenticationsStore from '…/store/pendingAuthentications’;
import createDummyUser from '…/modifiers/createDummyUser’;
import setConnectionIdAndAuthToken from '…/modifiers/setConnectionIdAndAuthToken’;
const clearOtherSessions = (sessionUserId, current = false) => {
const serverSessions = Meteor.server.sessions;
@@ -12,12 +15,58 @@ const clearOtherSessions = (sessionUserId, current = false) => {
};
export default function handleValidateAuthToken({ body }, meetingId) {
const { userId, valid, waitForApproval } = body;
const { userId, valid, authToken, waitForApproval } = body;
check(userId, String);
check(authToken, String);
check(valid, Boolean);
check(waitForApproval, Boolean);
const pendingAuths = pendingAuthenticationsStore.take(meetingId, userId, authToken);
if(!valid) {
pendingAuths.forEach (
pendingAuth => {
try {
const {methodInvocationObject} = pendingAuth;
const connectionId = methodInvocationObject.connection.id;
methodInvocationObject.connection.close();
Logger.info(`Closed connection ${connectionId} due to invalid auth token.`);
} catch (e) {
Logger.error(`Error closing socket for meetingId '${meetingId}’, userId '${userId}’, authToken ${authToken}`);
}
}
);
return;
}
if(valid) {
// Define user ID on connections
pendingAuths.forEach (
pendingAuth => {
const {methodInvocationObject} = pendingAuth;
/* Logic migrated from validateAuthToken method ( postponed to only run in case of success response ) - Begin */
const sessionId = `${meetingId}–${userId}`;
methodInvocationObject.setUserId(sessionId);
const User = Users.findOne({
meetingId,
userId: userId,
});
if (!User) {
createDummyUser(meetingId, userId, authToken);
}
setConnectionIdAndAuthToken(meetingId, userId, methodInvocationObject.connection.id, authToken);
/* End of logic migrated from validateAuthToken */
}
);
}
const selector = {
meetingId,
userId,