Fix ^^
This commit is contained in:
42
server.js
42
server.js
@@ -40,6 +40,13 @@ const dbAll = (sql, params = []) => new Promise((resolve, reject) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dbGet = (sql, params = []) => new Promise((resolve, reject) => {
|
||||||
|
db.get(sql, params, (err, row) => {
|
||||||
|
if (err) reject(err);
|
||||||
|
else resolve(row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Setup Storage
|
// Setup Storage
|
||||||
const uploadDir = path.join(__dirname, 'uploads');
|
const uploadDir = path.join(__dirname, 'uploads');
|
||||||
if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir);
|
if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir);
|
||||||
@@ -172,8 +179,23 @@ apiRouter.post('/auth/login', (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.get('/state', (req, res) => {
|
apiRouter.get('/state', async (req, res) => {
|
||||||
const state = { isStarted: false, teams: [], challenges: [], solves: [], blogs: [], config: {} };
|
const state = { isStarted: false, teams: [], challenges: [], solves: [], blogs: [], config: {} };
|
||||||
|
|
||||||
|
// Security Check: Identify requester and admin status
|
||||||
|
const authHeader = req.headers.authorization;
|
||||||
|
const teamId = authHeader ? authHeader.replace('Bearer mock-token-', '') : null;
|
||||||
|
let isAdmin = false;
|
||||||
|
|
||||||
|
if (teamId) {
|
||||||
|
try {
|
||||||
|
const team = await dbGet("SELECT isAdmin FROM teams WHERE id = ?", [teamId]);
|
||||||
|
isAdmin = team && team.isAdmin === 1;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Auth verify failed in state API:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db.all("SELECT key, value FROM config", (err, configRows) => {
|
db.all("SELECT key, value FROM config", (err, configRows) => {
|
||||||
if (err) return res.status(500).json({ error: 'Failed to fetch config' });
|
if (err) return res.status(500).json({ error: 'Failed to fetch config' });
|
||||||
configRows.forEach(row => { state.config[row.key] = row.value; });
|
configRows.forEach(row => { state.config[row.key] = row.value; });
|
||||||
@@ -189,11 +211,18 @@ apiRouter.get('/state', (req, res) => {
|
|||||||
if (err) return res.status(500).json({ error: 'Failed to fetch blogs' });
|
if (err) return res.status(500).json({ error: 'Failed to fetch blogs' });
|
||||||
state.solves = solves || [];
|
state.solves = solves || [];
|
||||||
state.blogs = blogs || [];
|
state.blogs = blogs || [];
|
||||||
state.challenges = (challenges || []).map(c => ({
|
state.challenges = (challenges || []).map(c => {
|
||||||
...c,
|
const enriched = {
|
||||||
files: JSON.parse(c.files || '[]'),
|
...c,
|
||||||
solves: state.solves.filter(s => s.challengeId === c.id).map(s => s.teamId)
|
files: JSON.parse(c.files || '[]'),
|
||||||
}));
|
solves: state.solves.filter(s => s.challengeId === c.id).map(s => s.teamId)
|
||||||
|
};
|
||||||
|
// CRITICAL SECURITY FIX: Hide flag if not admin
|
||||||
|
if (!isAdmin) {
|
||||||
|
delete enriched.flag;
|
||||||
|
}
|
||||||
|
return enriched;
|
||||||
|
});
|
||||||
res.json(state);
|
res.json(state);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -392,3 +421,4 @@ if (fs.existsSync(distPath)) {
|
|||||||
app.get('*', (req, res) => { if (!req.path.startsWith('/api') && !req.path.startsWith('/files')) res.sendFile(path.join(distPath, 'index.html')); else res.status(404).json({ error: 'Not found' }); });
|
app.get('*', (req, res) => { if (!req.path.startsWith('/api') && !req.path.startsWith('/files')) res.sendFile(path.join(distPath, 'index.html')); else res.status(404).json({ error: 'Not found' }); });
|
||||||
}
|
}
|
||||||
app.listen(port, '0.0.0.0', () => console.log(`CTF Backend running on port ${port}`));
|
app.listen(port, '0.0.0.0', () => console.log(`CTF Backend running on port ${port}`));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user