Skip to content

Commit

Permalink
Fix impersonation of web sockets exploit
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-eason committed Jan 14, 2024
1 parent 6aeec0d commit 6ec6908
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 25 deletions.
3 changes: 1 addition & 2 deletions client/src/views/game/Game.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ export default {
this.unsubscribeToSockets()
let socketData = {
gameId: this.$store.state.game._id,
userId: this.$store.state.userId
gameId: this.$store.state.game._id
}
let player = GameHelper.getUserPlayer(this.$store.state.game)
Expand Down
11 changes: 7 additions & 4 deletions server/api/express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ export default async (config: Config, app, container: DependencyContainer) => {

// ---------------
// Set up MongoDB session store
let store = new MongoDBStore({
let sessionStorage = new MongoDBStore({
uri: config.connectionString,
collection: 'sessions'
});

// Catch session store errors
store.on('error', function(err) {
sessionStorage.on('error', function(err) {
console.error(err);
});

Expand All @@ -37,7 +37,7 @@ export default async (config: Config, app, container: DependencyContainer) => {
secure: config.sessionSecureCookies, // Requires HTTPS
maxAge: 1000 * 60 * 60 * 24 * 365 // 1 Year
},
store
store: sessionStorage
}));

// ---------------
Expand Down Expand Up @@ -86,5 +86,8 @@ export default async (config: Config, app, container: DependencyContainer) => {

console.log('Express intialized.');

return app;
return {
app,
sessionStorage
};
};
8 changes: 5 additions & 3 deletions server/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ async function startServer() {
const app = express();
const server = http.createServer(app);

const io = socketLoader(server);
const container = containerLoader(config, io);
const container = containerLoader(config);

await expressLoader(config, app, container);
const { sessionStorage } = await expressLoader(config, app, container);

const io = socketLoader(config, server, sessionStorage);
container.broadcastService.setIOController(io);

server.listen(config.port, (err) => {
if (err) {
Expand Down
55 changes: 49 additions & 6 deletions server/api/sockets.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,53 @@
import { Config } from "../config/types/Config";

const socketio = require('socket.io');
const cookieParser = require('cookie-parser');
const cookie = require('cookie');

export default (server) => {
export default (config: Config, server, sessionStore) => {

const io = socketio(server);

io.on('connection', (socket) => {
const getUserId = async (socket, data) => {
return new Promise((resolve, reject) => {
const cookieString = socket.request.headers.cookie;

if (cookieString) {
const cookieParsed = cookie.parse(cookieString);
const sid = cookieParsed['connect.sid'];

if (sid) {
const sidParsed = cookieParser.signedCookie(sid, config.sessionSecret);

sessionStore.get(sidParsed, (err, session) => {
if (err) return reject(err);

if (session.userId) {
resolve(session.userId.toString())
} else {
resolve(null);
}
});
}
} else {
resolve(null);
}
})
}


io.on('connection', async (socket) => {

// When the user opens a game, they will be put
// into that room to receive web sockets scoped to the game room.
socket.on('gameRoomJoined', (data) => {
socket.on('gameRoomJoined', async (data) => {
const userId = await getUserId(socket, data);

if (userId) {
socket.join(userId); // Join a private room to receive user/player specific messages.
}

socket.join(data.gameId); // Join the game room to receive game-wide messages.
socket.join(data.userId); // Join a private room to receive user/player specific messages.

if (data.playerId) {
socket.join(data.playerId);
Expand All @@ -21,9 +59,14 @@ export default (server) => {
}
});

socket.on('gameRoomLeft', (data) => {
socket.on('gameRoomLeft', async (data) => {
const userId = await getUserId(socket, data);

if (userId) {
socket.leave(userId)
}

socket.leave(data.gameId)
socket.leave(data.userId)

if (data.playerId) {
socket.leave(data.playerId)
Expand Down
63 changes: 57 additions & 6 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"connect-mongodb-session": "^2.4.1",
"cookie": "^0.6.0",
"cookie-parser": "^1.4.6",
"discord.js": "^12.5.3",
"dotenv": "^8.2.0",
"elo-rating": "^1.0.1",
Expand Down
4 changes: 2 additions & 2 deletions server/services/broadcast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { LedgerType } from "./ledger";


export default class BroadcastService {
io;
io: any;

constructor(io) {
setIOController(io) {
this.io = io;
}

Expand Down
4 changes: 2 additions & 2 deletions server/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const guildRepository = new Repository<Guild>(GuildModel);
const paymentRepository = new Repository<Payment>(PaymentModel);
const reportRepository = new Repository<Report>(ReportModel);

export default (config, io): DependencyContainer => {
export default (config): DependencyContainer => {

// Poor man's dependency injection.

Expand All @@ -124,7 +124,7 @@ export default (config, io): DependencyContainer => {
const guildService = new GuildService(GuildModel, guildRepository, userRepository, userService);
const guildUserService = new GuildUserService(userRepository, guildService);

const broadcastService = new BroadcastService(io);
const broadcastService = new BroadcastService();
const distanceService = new DistanceService();
const randomService = new RandomService();
const cacheService = new CacheService(config);
Expand Down

0 comments on commit 6ec6908

Please sign in to comment.