mirror of https://github.com/calzoneman/sync.git
Add XSS filter
This commit is contained in:
parent
feca68538e
commit
551d5b2c36
|
@ -8,6 +8,7 @@ var AsyncQueue = require("./asyncqueue");
|
||||||
var MakeEmitter = require("./emitter");
|
var MakeEmitter = require("./emitter");
|
||||||
var InfoGetter = require("./get-info");
|
var InfoGetter = require("./get-info");
|
||||||
var ChatCommand = require("./chatcommand");
|
var ChatCommand = require("./chatcommand");
|
||||||
|
var XSS = require("./xss");
|
||||||
|
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
@ -572,16 +573,6 @@ Channel.prototype.part = function (user) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the MOTD and broadcast it to connected users
|
|
||||||
*/
|
|
||||||
Channel.prototype.setMOTD = function (message) {
|
|
||||||
this.motd.motd = message;
|
|
||||||
// TODO XSS filter
|
|
||||||
this.motd.html = message.replace(/\n/g, "<br>");
|
|
||||||
this.sendMOTD(this.users);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the MOTD to the given users
|
* Send the MOTD to the given users
|
||||||
*/
|
*/
|
||||||
|
@ -2194,9 +2185,9 @@ Channel.prototype.validateChatFilter = function (f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
f.replace = f.replace.substring(0, 1000);
|
f.replace = f.replace.substring(0, 1000);
|
||||||
|
f.replace = XSS.sanitizeHTML(f.replace);
|
||||||
f.flags = f.flags.substring(0, 4);
|
f.flags = f.flags.substring(0, 4);
|
||||||
|
|
||||||
// TODO XSS prevention
|
|
||||||
try {
|
try {
|
||||||
new RegExp(f.source, f.flags);
|
new RegExp(f.source, f.flags);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -2493,7 +2484,7 @@ Channel.prototype.handleSetJS = function (user, data) {
|
||||||
* Sets the MOTD
|
* Sets the MOTD
|
||||||
*/
|
*/
|
||||||
Channel.prototype.setMotd = function (motd) {
|
Channel.prototype.setMotd = function (motd) {
|
||||||
// TODO XSS
|
motd = XSS.sanitizeHTML(motd);
|
||||||
var html = motd.replace(/\n/g, "<br>");
|
var html = motd.replace(/\n/g, "<br>");
|
||||||
this.motd = {
|
this.motd = {
|
||||||
motd: motd,
|
motd: motd,
|
||||||
|
@ -2557,7 +2548,7 @@ Channel.prototype.handleChat = function (user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smuted) {
|
if (smuted) {
|
||||||
// TODO XSS
|
msg = XSS.sanitizeText(msg);
|
||||||
msg = this.filterMessage(msg);
|
msg = this.filterMessage(msg);
|
||||||
var msgobj = {
|
var msgobj = {
|
||||||
username: user.name,
|
username: user.name,
|
||||||
|
@ -2629,7 +2620,7 @@ Channel.prototype.filterMessage = function (msg) {
|
||||||
* Sends a chat message
|
* Sends a chat message
|
||||||
*/
|
*/
|
||||||
Channel.prototype.sendMessage = function (user, msg, meta) {
|
Channel.prototype.sendMessage = function (user, msg, meta) {
|
||||||
// TODO HTML escape
|
msg = XSS.sanitizeText(msg);
|
||||||
msg = this.filterMessage(msg);
|
msg = this.filterMessage(msg);
|
||||||
var msgobj = {
|
var msgobj = {
|
||||||
username: user.name,
|
username: user.name,
|
||||||
|
@ -2645,7 +2636,7 @@ Channel.prototype.sendMessage = function (user, msg, meta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.log("<" + user.name + (meta.addClass ? "." + meta.addClass : "") + "> " +
|
this.logger.log("<" + user.name + (meta.addClass ? "." + meta.addClass : "") + "> " +
|
||||||
msg);
|
XSS.decodeText(msg));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
40
lib/xss.js
40
lib/xss.js
|
@ -46,6 +46,16 @@ TagParser.prototype.readLiteral = function (regexp) {
|
||||||
str += this.text[this.i];
|
str += this.text[this.i];
|
||||||
this.i++;
|
this.i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
str = str.replace(/&#([0-9]{2,7});?/g, function (m, p1) {
|
||||||
|
return String.fromCharCode(parseInt(p1));
|
||||||
|
});
|
||||||
|
|
||||||
|
str = str.replace(/&#x([0-9a-fA-F]{2,7});?/g, function (m, p1) {
|
||||||
|
return String.fromCharCode(parseInt(p1, 16));
|
||||||
|
});
|
||||||
|
|
||||||
|
str = str.replace(/[\x00-\x1f]/g, "");
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,7 +63,7 @@ TagParser.prototype.readLiteral = function (regexp) {
|
||||||
a string. Otherwise, read a literal
|
a string. Otherwise, read a literal
|
||||||
*/
|
*/
|
||||||
TagParser.prototype.readLiteralOrString = function (regexp) {
|
TagParser.prototype.readLiteralOrString = function (regexp) {
|
||||||
if (this.text[this.i].match(/["']/)) {
|
if (this.text[this.i].match(/["'`]/)) {
|
||||||
return this.readString();
|
return this.readString();
|
||||||
}
|
}
|
||||||
return this.readLiteral(regexp);
|
return this.readLiteral(regexp);
|
||||||
|
@ -78,6 +88,16 @@ TagParser.prototype.readString = function () {
|
||||||
this.i++;
|
this.i++;
|
||||||
}
|
}
|
||||||
this.i++;
|
this.i++;
|
||||||
|
|
||||||
|
str = str.replace(/&#([0-9]{2,7});?/g, function (m, p1) {
|
||||||
|
return String.fromCharCode(parseInt(p1));
|
||||||
|
});
|
||||||
|
|
||||||
|
str = str.replace(/&#x([0-9a-fA-F]{2,7});?/g, function (m, p1) {
|
||||||
|
return String.fromCharCode(parseInt(p1, 16));
|
||||||
|
});
|
||||||
|
|
||||||
|
str = str.replace(/[\x00-\x1f]/g, "");
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,7 +140,7 @@ TagParser.prototype.parse = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.i++;
|
this.i++;
|
||||||
this.skipWhitespace();
|
//this.skipWhitespace();
|
||||||
var value = this.readLiteralOrString();
|
var value = this.readLiteralOrString();
|
||||||
if (key.trim().length > 0) {
|
if (key.trim().length > 0) {
|
||||||
attrs[key] = value;
|
attrs[key] = value;
|
||||||
|
@ -181,7 +201,8 @@ const badTags = new RegExp([
|
||||||
*/
|
*/
|
||||||
const badAttrs = new RegExp([
|
const badAttrs = new RegExp([
|
||||||
"\\bon\\S*",
|
"\\bon\\S*",
|
||||||
"\\bformaction"
|
"\\bformaction",
|
||||||
|
"\\baction"
|
||||||
].join("|"), "i");
|
].join("|"), "i");
|
||||||
|
|
||||||
/* These are things commonly used in the values of HTML attributes of
|
/* These are things commonly used in the values of HTML attributes of
|
||||||
|
@ -240,7 +261,14 @@ function sanitizeHTML(str) {
|
||||||
if (k.trim().length > 0) {
|
if (k.trim().length > 0) {
|
||||||
fmt += " " + k;
|
fmt += " " + k;
|
||||||
if (t.attributes[k].trim().length > 0) {
|
if (t.attributes[k].trim().length > 0) {
|
||||||
fmt += '="' + t.attributes[k] + '"';
|
var delim = '"';
|
||||||
|
if (t.attributes[k].match(/[^\\]"/)) {
|
||||||
|
delim = "'";
|
||||||
|
if (t.attributes[k].match(/[^\\]'/)) {
|
||||||
|
delim = "`";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt += "=" + delim + t.attributes[k] + delim;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,10 +292,10 @@ function sanitizeText(str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeText(str) {
|
function decodeText(str) {
|
||||||
str = str.replace(/&#([0-9]{2,4});?/g, function (m, p1) {
|
str = str.replace(/&#([0-9]{2,7});?/g, function (m, p1) {
|
||||||
return String.fromCharCode(parseInt(p1));
|
return String.fromCharCode(parseInt(p1));
|
||||||
});
|
});
|
||||||
str = str.replace(/&#x([0-9a-f]{2,4});?/ig, function (m, p1) {
|
str = str.replace(/&#x([0-9a-f]{2,7});?/ig, function (m, p1) {
|
||||||
return String.fromCharCode(parseInt(p1, 16));
|
return String.fromCharCode(parseInt(p1, 16));
|
||||||
});
|
});
|
||||||
str = str.replace(/</g, "<")
|
str = str.replace(/</g, "<")
|
||||||
|
|
Loading…
Reference in New Issue