added web challenge

This commit is contained in:
2024-03-01 18:21:45 +01:00
parent 4400d65c03
commit e9c312587d
11 changed files with 5257 additions and 0 deletions

200
bi0sctf23/web/src/index.js Normal file
View File

@@ -0,0 +1,200 @@
const express = require('express');
const fs = require('fs');
const protobuf = require('protobufjs');
const glob = require('glob');
const { healthCheck } = require('./bot');
const app = express();
const port = 3000;
function generateNoteId(length) {
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
result += characters.charAt(randomIndex);
}
return result;
}
let noteList = [];
let flag = process.env.FLAG;
if(!flag){
flag='{"title":"flag","content":"bi0sctf{fake_flag}"}';
}
else{
flag=`{"title":"flag","content":"${flag}"}`;
}
const flagid = generateNoteId(16);
const healthCheckId='Healthcheck';
fs.writeFileSync(`./notes/${flagid}.json`, flag);
fs.writeFileSync(`./notes/${healthCheckId}.json`, '{"title":"Healthcheck","content":"success"}');
app.use(express.json());
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
const restrictToLocalhost = (req, res, next) => {
const remoteAddress = req.connection.remoteAddress;
if (remoteAddress === '::1' || remoteAddress === '127.0.0.1' || remoteAddress === '::ffff:127.0.0.1') {
next();
} else {
res.status(403).json({ Message: 'Access denied' });
}
};
const cleanserver = () => {
Object.keys(require.cache).forEach(i => {
delete require.cache[i];
});
};
app.use('/search', restrictToLocalhost);
app.get('/delete', (req,res) => {
cleanserver();
return res.json({Message: 'Notes deleted successfully!'});
});
app.get('/search/:noteId', (req, res) => {
const noteId = req.params.noteId;
const notes=glob.sync(`./notes/${noteId}*`);
if(notes.length === 0){
return res.json({Message: "Not found"});
}
else{
try{
fs.accessSync(`./notes/${noteId}.json`);
return res.json({Message: "Note found"});
}
catch(err){
return res.status(500).json({ Message: 'Internal server error' });
}
}
})
app.get('/customise', (req, res) => {
return res.render('customise');
});
app.post('/customise',(req, res) => {
try {
const { data } = req.body;
let author = data.pop()['author'];
let title = data.pop()['title'];
let protoContents = fs.readFileSync('./settings.proto', 'utf-8').split('\n');
if (author) {
protoContents[5] = ` ${author} string author = 3 [default="user"];`;
}
if (title) {
protoContents[3] = ` ${title} string title = 1 [default="user"];`;
}
fs.writeFileSync('./settings.proto', protoContents.join('\n'), 'utf-8');
return res.json({ Message: 'Settings changed' });
} catch (error) {
console.error(error);
res.status(500).json({ Message: 'Internal server error' });
}
})
app.get('/create', (req, res) => {
return res.render('create', { noteList, Message: false });
});
app.post('/create', (req, res) => {
requestBody=req.body
try{
schema = fs.readFileSync('./settings.proto', 'utf-8');
root = protobuf.parse(schema).root;
Note = root.lookupType('Note');
errMsg = Note.verify(requestBody);
if (errMsg){
return res.json({ Message: `Verification failed: ${errMsg}` });
}
buffer = Note.encode(Note.create(requestBody)).finish();
decodedData = Note.decode(buffer).toJSON();
const noteId = generateNoteId(16);
fs.writeFileSync(`./notes/${noteId}.json`, JSON.stringify(decodedData));
noteList.push(noteId);
return res.json({Message: 'Note created successfully!',Noteid: noteId });
}
catch (error) {
console.error(error);
res.status(500).json({Message: 'Internal server error' });
}
});
app.get('/view/:noteId', (req, res) => {
const noteId = req.params.noteId;
try {
let note=require.resolve(`./notes/${noteId}`);
if(!note.endsWith(".json")){
return res.status(500).json({ Message: 'Internal Server Error' });
}
let noteData = require(`./notes/${noteId}`);
for (var key in module.constructor._pathCache) {
if (key.startsWith("./notes/"+noteId)){
if (!module.constructor._pathCache[key].endsWith(noteId+".json")){
if (noteId===healthCheckId){
cleanserver();
}
delete module.constructor._pathCache[key];
return res.status(500).json({ Message: 'Internal Server Error' });
}
}
}
if(req.query.temp !== undefined){
fs.unlink(`./notes/${noteId}.json`, (unlinkError) => {
if (unlinkError) {
console.error('File missing');
}
noteList=noteList.filter((value)=>value!=noteId);
});
}
return res.render('view', { noteData });
} catch (error) {
console.log(error)
return res.status(500).json({ Message: 'Internal Server Error' });
}
});
app.get('/healthcheck',async(req,res)=>{
try {
await healthCheck();
return res.json({ Message: 'healthcheck successful' });
} catch (error) {
console.error(error);
return res.json({ Message: 'healthcheck failed' });
}
});
app.get('/', (req, res) => {
return res.redirect('/create');
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Internal Server Error' });
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});