tldr dnsbl and bypass sucks cock

indiachan-spamvector
Thomas Lynch 2 years ago
parent 6798cb843e
commit 7b784283f8
  1. 14
      controllers/forms.js
  2. 6
      controllers/forms/index.js
  3. 118
      helpers/checks/blockbypass.js
  4. 14
      helpers/checks/dnsbl.js

@ -20,7 +20,7 @@ const express = require('express')
, useSession = require(__dirname+'/../helpers/usesession.js')
, sessionRefresh = require(__dirname+'/../helpers/sessionrefresh.js')
, dnsblCheck = require(__dirname+'/../helpers/checks/dnsbl.js')
, blockBypassCheck = require(__dirname+'/../helpers/checks/blockbypass.js')
, blockBypass = require(__dirname+'/../helpers/checks/blockbypass.js')
, fileMiddlewares = require(__dirname+'/../helpers/filemiddlewares.js')
//controllers
, { deleteBoardController, editBansController, appealController, globalActionController,
@ -30,14 +30,14 @@ const express = require('express')
resignController, deleteAccountController, loginController, registerController, changePasswordController,
deleteAccountsController, editAccountController, globalSettingsController, createBoardController, makePostController,
addStaffController, deleteStaffController, editStaffController, editCustomPageController, editPostController,
editRoleController, newCaptcha, blockBypass, logout, deleteSessionsController } = require(__dirname+'/forms/index.js');
editRoleController, newCaptchaForm, blockBypassForm, logoutForm, deleteSessionsController } = require(__dirname+'/forms/index.js');
//make new post
router.post('/board/:board/post', geoAndTor, fileMiddlewares.postsEarly, torPreBypassCheck, processIp, useSession, sessionRefresh, Boards.exists, calcPerms, banCheck, fileMiddlewares.posts,
makePostController.paramConverter, verifyCaptcha, numFiles, blockBypassCheck, dnsblCheck, imageHashes, makePostController.controller);
makePostController.paramConverter, verifyCaptcha, numFiles, blockBypass.middleware, dnsblCheck, imageHashes, makePostController.controller);
router.post('/board/:board/modpost', geoAndTor, fileMiddlewares.postsEarly, torPreBypassCheck, processIp, useSession, sessionRefresh, Boards.exists, calcPerms, banCheck, isLoggedIn,
hasPerms.one(Permissions.MANAGE_BOARD_GENERAL), fileMiddlewares.posts, makePostController.paramConverter, csrf, numFiles, blockBypassCheck, dnsblCheck, makePostController.controller); //mod post has token instead of captcha
hasPerms.one(Permissions.MANAGE_BOARD_GENERAL), fileMiddlewares.posts, makePostController.paramConverter, csrf, numFiles, blockBypass.middleware, dnsblCheck, makePostController.controller); //mod post has token instead of captcha
//post actions
router.post('/board/:board/actions', geoAndTor, torPreBypassCheck, processIp, useSession, sessionRefresh, Boards.exists, calcPerms, banCheck, actionController.paramConverter, verifyCaptcha, actionController.controller); //public, with captcha
@ -114,7 +114,7 @@ router.post('/create', geoAndTor, torPreBypassCheck, processIp, useSession, sess
//accounts
router.post('/login', useSession, loginController.paramConverter, loginController.controller);
router.post('/logout', useSession, logout);
router.post('/logout', useSession, logoutForm);
router.post('/register', geoAndTor, torPreBypassCheck, processIp, useSession, sessionRefresh, verifyCaptcha, calcPerms, registerController.paramConverter, registerController.controller);
router.post('/changepassword', geoAndTor, torPreBypassCheck, processIp, useSession, sessionRefresh, verifyCaptcha, changePasswordController.paramConverter, changePasswordController.controller);
router.post('/resign', useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, resignController.paramConverter, resignController.controller);
@ -122,9 +122,9 @@ router.post('/deleteaccount', useSession, sessionRefresh, csrf, calcPerms, isLog
router.post('/deletesessions', useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, deleteSessionsController.paramConverter, deleteSessionsController.controller);
//removes captcha cookie, for refreshing for noscript users
router.post('/newcaptcha', newCaptcha);
router.post('/newcaptcha', newCaptchaForm);
//solve captcha for block bypass
router.post('/blockbypass', geoAndTor, processIp, verifyCaptcha, blockBypass);
router.post('/blockbypass', geoAndTor, processIp, verifyCaptcha, blockBypassForm);
module.exports = router;

@ -39,8 +39,8 @@ module.exports = {
editRoleController: require(__dirname+'/editrole.js'),
//these dont have a "real" controller
newCaptcha: require(__dirname+'/../../models/forms/newcaptcha.js'),
blockBypass: require(__dirname+'/../../models/forms/blockbypass.js'),
logout: require(__dirname+'/../../models/forms/logout.js'),
newCaptchaForm: require(__dirname+'/../../models/forms/newcaptcha.js'),
blockBypassForm: require(__dirname+'/../../models/forms/blockbypass.js'),
logoutForm: require(__dirname+'/../../models/forms/logout.js'),
};

@ -7,73 +7,81 @@ const { Bypass } = require(__dirname+'/../../db/')
, dynamicResponse = require(__dirname+'/../dynamic.js')
, production = process.env.NODE_ENV === 'production';
module.exports = async (req, res, next) => {
module.exports = {
const { secureCookies, blockBypass } = config.get;
if (res.locals.preFetchedBypassId //if they already have a bypass
|| (!blockBypass.enabled //or if block bypass isnt enabled
&& (!blockBypass.forceAnonymizers //and we dont force it for anonymizer
|| !res.locals.anonymizer))) { //or they arent on an anonymizer
return next();
}
check: async (req, res, next) => {
const { secureCookies, blockBypass } = config.get;
//check if blockbypass exists and right length
const bypassId = req.signedCookies.bypassid;
if (!res.locals.solvedCaptcha && (!bypassId || bypassId.length !== 24)) {
deleteTempFiles(req).catch(e => console.error);
return dynamicResponse(req, res, 403, 'message', {
'title': 'Forbidden',
'message': 'Please complete a block bypass to continue',
'frame': '/bypass_minimal.html',
'link': {
'href': '/bypass.html',
'text': 'Get block bypass',
},
});
}
//try to get bypass from db and make sure uses < maxUses
let bypass;
if (bypassId && bypassId.length === 24) {
try {
const bypassMongoId = ObjectId(bypassId);
bypass = await Bypass.checkBypass(bypassMongoId, res.locals.anonymizer);
res.locals.blockBypass = true;
} catch (err) {
return next(err);
}
}
if (bypass //if they have a valid bypass
&& (bypass.uses < blockBypass.expireAfterUses //and its not overused
|| (res.locals.anonymizer
&& !blockBypass.forceAnonymizers))) { //OR its not forced for anonymizers
return next();
}
if (res.locals.solvedCaptcha) {
//they dont have a valid bypass, but just solved board captcha, so give them a new one
const newBypass = await Bypass.getBypass(res.locals.anonymizer);
const newBypassId = newBypass.insertedId;
res.locals.blockBypass = true;
res.cookie('bypassid', newBypassId.toString(), {
'maxAge': blockBypass.expireAfterTime,
'secure': production && secureCookies && (req.headers['x-forwarded-proto'] === 'https'),
'sameSite': 'strict',
'signed': true
});
return next();
}
//check if blockbypass exists and right length
const bypassId = req.signedCookies.bypassid;
if (!res.locals.solvedCaptcha && (!bypassId || bypassId.length !== 24)) {
deleteTempFiles(req).catch(e => console.error);
return dynamicResponse(req, res, 403, 'message', {
'title': 'Forbidden',
'message': 'Please complete a block bypass to continue',
'message': 'Block bypass expired or exceeded max uses',
'frame': '/bypass_minimal.html',
'link': {
'href': '/bypass.html',
'text': 'Get block bypass',
},
});
}
//try to get bypass from db and make sure uses < maxUses
let bypass;
if (bypassId && bypassId.length === 24) {
try {
const bypassMongoId = ObjectId(bypassId);
bypass = await Bypass.checkBypass(bypassMongoId, res.locals.anonymizer);
res.locals.blockBypass = true;
} catch (err) {
return next(err);
}
}
if (bypass //if they have a valid bypass
&& (bypass.uses < blockBypass.expireAfterUses //and its not overused
|| (res.locals.anonymizer
&& !blockBypass.forceAnonymizers))) { //OR its not forced for anonymizers
return next();
}
},
if (res.locals.solvedCaptcha) {
//they dont have a valid bypass, but just solved board captcha, so give them a new one
const newBypass = await Bypass.getBypass(res.locals.anonymizer);
const newBypassId = newBypass.insertedId;
res.locals.blockBypass = true;
res.cookie('bypassid', newBypassId.toString(), {
'maxAge': blockBypass.expireAfterTime,
'secure': production && secureCookies && (req.headers['x-forwarded-proto'] === 'https'),
'sameSite': 'strict',
'signed': true
});
return next();
}
deleteTempFiles(req).catch(e => console.error);
return dynamicResponse(req, res, 403, 'message', {
'title': 'Forbidden',
'message': 'Block bypass expired or exceeded max uses',
'frame': '/bypass_minimal.html',
'link': {
'href': '/bypass.html',
'text': 'Get block bypass',
},
});
middleware: async (req, res, next) => {
const { blockBypass } = config.get;
if (res.locals.preFetchedBypassId //if they already have a bypass
|| (!blockBypass.enabled //or if block bypass isnt enabled
&& (!blockBypass.forceAnonymizers //and we dont force it for anonymizer
|| !res.locals.anonymizer))) { //or they arent on an anonymizer
return next();
}
return module.exports.check(req, res, next);
},
}

@ -1,6 +1,7 @@
'use strict';
const cache = require(__dirname+'/../../redis.js')
, { check: blockBypassCheck } = require(__dirname+'/blockbypass.js')
, dynamicResponse = require(__dirname+'/../dynamic.js')
, deleteTempFiles = require(__dirname+'/../files/deletetempfiles.js')
, config = require(__dirname+'/../../config.js')
@ -9,9 +10,16 @@ const cache = require(__dirname+'/../../redis.js')
module.exports = async (req, res, next) => {
const { ipHeader, dnsbl, blockBypass } = config.get;
if (dnsbl.enabled && dnsbl.blacklists.length > 0 //if dnsbl enabled and has more than 0 blacklists
&& !res.locals.anonymizer //anonymizers cant be dnsbl'd
&& (!res.locals.blockBypass || !blockBypass.bypassDnsbl)) { //and there is no valid block bypass, or they do not bypass dnsbl
&& !res.locals.anonymizer) { //anonymizers cant be dnsbl'd
if (blockBypass.bypassDnsbl) {
if (!res.locals.blockBypass) {
return blockBypassCheck(req, res, next);
}
return next(); //already solved
}
//otherwise, bad block bypass or dnsbl cant be bypassed
const ip = req.headers[ipHeader] || req.connection.remoteAddress;
let isBlacklisted = await cache.get(`blacklisted:${ip}`);
if (isBlacklisted === null) { //not cached
@ -23,7 +31,7 @@ module.exports = async (req, res, next) => {
deleteTempFiles(req).catch(e => console.error);
return dynamicResponse(req, res, 403, 'message', {
'title': 'Forbidden',
'message': `Your request was blocked because your IP address is listed on a blacklist.${blockBypass.bypassDnsbl ? ' You can solve a "block bypass" to temporarily circumvent blacklisting.' : ''}`,
'message': `Your request was blocked because your IP address is listed on a blacklist.`,
'redirect': req.headers.referer || '/',
'link': blockBypass.bypassDnsbl ? { text: 'Solve block bypass', href: '/bypass.html' } : null,
});

Loading…
Cancel
Save