Create and use the Security module.

Use it to replace code on the client and server side.
This commit is contained in:
Chad Weider 2012-01-18 03:58:13 -08:00
parent 363e168561
commit e0d23e3c5d
6 changed files with 74 additions and 65 deletions

View file

@ -19,6 +19,7 @@ var async = require("async");
var Changeset = CommonCode.require("/Changeset");
var padManager = require("../db/PadManager");
var ERR = require("async-stacktrace");
var Security = CommonCode.require('/security');
function getPadPlainText(pad, revNum)
{
@ -270,7 +271,7 @@ function getHTMLFromAtext(pad, atext)
//from but they break the abiword parser and are completly useless
s = s.replace(String.fromCharCode(12), "");
assem.append(_escapeHTML(s));
assem.append(_encodeWhitespace(Security.escapeHTML(s)));
} // end iteration over spans in line
var tags2close = [];
@ -293,7 +294,7 @@ function getHTMLFromAtext(pad, atext)
var url = urlData[1];
var urlLength = url.length;
processNextChars(startIndex - idx);
assem.append('<a href="' + _escapeHTML(url) + '">');
assem.append('<a href="' + Security.escapeHTMLAttribute(url) + '">');
processNextChars(urlLength);
assem.append('</a>');
});
@ -494,25 +495,7 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
});
}
function _escapeHTML(s)
{
var re = /[&"<>]/g;
if (!re.MAP)
{
// persisted across function calls!
re.MAP = {
'&': '&amp;',
'"': '&quot;',
'<': '&lt;',
'>': '&gt;'
};
}
s = s.replace(re, function (c)
{
return re.MAP[c];
});
function _encodeWhitespace(s) {
return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c)
{
return "&#" +c.charCodeAt(0) + ";"

View file

@ -1,6 +1,7 @@
{
"pad.js": [
"jquery.js"
, "security.js"
, "pad.js"
, "ace2_common.js"
, "pad_utils.js"
@ -25,6 +26,7 @@
]
, "timeslider.js": [
"jquery.js"
, "security.js"
, "plugins.js"
, "undo-xpopup.js"
, "json2.js"
@ -53,6 +55,7 @@
"ace2_common.js"
, "AttributePoolFactory.js"
, "Changeset.js"
, "security.js"
, "skiplist.js"
, "virtual_lines.js"
, "cssmanager.js"

View file

@ -20,6 +20,7 @@
* limitations under the License.
*/
var Security = require('/security');
function isNodeText(node)
{
@ -137,14 +138,7 @@ function binarySearchInfinite(expectedLength, func)
function htmlPrettyEscape(str)
{
return str.replace(/[&"<>]/g, function (c) {
return {
'&': '&amp;',
'"': '&quot;',
'<': '&lt;',
'>': '&gt;'
}[c] || c;
}).replace(/\r?\n/g, '\\n');
return Security.escapeHTML(str).replace(/\r?\n/g, '\\n');
}
exports.isNodeText = isNodeText;

View file

@ -26,6 +26,7 @@
// requires: plugins
// requires: undefined
var Security = require('/security');
var plugins = require('/plugins').plugins;
var map = require('/ace2_common').map;
@ -103,17 +104,17 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
if (listType)
{
listType = listType[1];
start = start?'start="'+start[1]+'"':'';
start = start?'start="'+Security.escapeHTMLAttribute(start[1])+'"':'';
if (listType)
{
if(listType.indexOf("number") < 0)
{
preHtml = '<ul class="list-' + listType + '"><li>';
preHtml = '<ul class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
postHtml = '</li></ul>';
}
else
{
preHtml = '<ol '+start+' class="list-' + listType + '"><li>';
preHtml = '<ol '+start+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
postHtml = '</li></ol>';
}
}
@ -168,7 +169,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
{
href = "http://"+href;
}
extraOpenTags = extraOpenTags + '<a href="' + domline.escapeHTML(href) + '">';
extraOpenTags = extraOpenTags + '<a href="' + Security.escapeHTMLAttribute(href) + '">';
extraCloseTags = '</a>' + extraCloseTags;
}
if (simpleTags)
@ -178,7 +179,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
simpleTags.reverse();
extraCloseTags = '</' + simpleTags.join('></') + '>' + extraCloseTags;
}
html.push('<span class="', cls || '', '">', extraOpenTags, perTextNodeProcess(domline.escapeHTML(txt)), extraCloseTags, '</span>');
html.push('<span class="', Security.escapeHTMLAttribute(cls || ''), '">', extraOpenTags, perTextNodeProcess(Security.escapeHTML(txt)), extraCloseTags, '</span>');
}
};
result.clearSpans = function()
@ -224,27 +225,6 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
return result;
};
domline.escapeHTML = function(s)
{
var re = /[&<>'"]/g;
/']/; // stupid indentation thing
if (!re.MAP)
{
// persisted across function calls!
re.MAP = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
};
}
return s.replace(re, function(c)
{
return re.MAP[c];
});
};
domline.processSpaces = function(s, doesWrap)
{
if (s.indexOf("<") < 0 && !doesWrap)

View file

@ -20,6 +20,8 @@
* limitations under the License.
*/
var Security = require('/security');
/**
* Generates a random String with the given length. Is needed to generate the Author, Group, readonly, session Ids
*/
@ -69,14 +71,7 @@ function readCookie(name)
var padutils = {
escapeHtml: function(x)
{
return String(x).replace(/[&"<>]/g, function (c) {
return {
'&': '&amp;',
'"': '&quot;',
'<': '&lt;',
'>': '&gt;'
}[c] || c;
});
return Security.escapeHTML(String(x));
},
uniqueId: function()
{
@ -205,7 +200,7 @@ var padutils = {
{
if (i > idx)
{
pieces.push(padutils.escapeHtml(text.substring(idx, i)));
pieces.push(Security.escapeHTML(text.substring(idx, i)));
idx = i;
}
}
@ -216,7 +211,7 @@ var padutils = {
var startIndex = urls[j][0];
var href = urls[j][1];
advanceTo(startIndex);
pieces.push('<a ', (target ? 'target="' + target + '" ' : ''), 'href="', padutils.escapeHtml(href), '">');
pieces.push('<a ', (target ? 'target="' + Security.escapeHTMLAttribute(target) + '" ' : ''), 'href="', Security.escapeHTMLAttribute(href), '">');
advanceTo(startIndex + href.length);
pieces.push('</a>');
}

54
static/js/security.js Normal file
View file

@ -0,0 +1,54 @@
/**
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var HTML_ENTITY_MAP = {
'&': '&amp;'
, '<': '&lt;'
, '>': '&gt;'
, '"': '&quot;'
, "'": '&#x27;'
, '/': '&#x2F;'
};
// OSWASP Guidlines: &, <, >, ", ' plus forward slash.
var HTML_CHARACTERS_EXPRESSION = /[&"'<>\/]/g;
function escapeHTML(text) {
return text && text.replace(HTML_CHARACTERS_EXPRESSION, function (c) {
return HTML_ENTITY_MAP[c] || c;
});
}
// OSWASP Guidlines: escape all non alphanumeric characters in ASCII space.
var HTML_ATTRIBUTE_CHARACTERS_EXPRESSION =
/[\x00-\x2F\x3A-\x40\5B-\x60\x7B-\xFF]/g;
function escapeHTMLAttribute(text) {
return text && text.replace(HTML_ATTRIBUTE_CHARACTERS_EXPRESSION, function (c) {
return "&#x" + ('00' + c.charCodeAt(0).toString(16)).slice(-2) + ";";
});
};
// OSWASP Guidlines: escape all non alphanumeric characters in ASCII space.
var JAVASCRIPT_CHARACTERS_EXPRESSION =
/[\x00-\x2F\x3A-\x40\5B-\x60\x7B-\xFF]/g;
function escapeJavaScriptData(text) {
return text && text.replace(JAVASCRIPT_CHARACTERS_EXPRESSION, function (c) {
return "\\x" + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
});
}
exports.escapeHTML = escapeHTML;
exports.escapeHTMLAttribute = escapeHTMLAttribute;
exports.escapeJavaScriptData = escapeJavaScriptData;