[Erp5-report] r25842 - in /erp5/trunk/products/PortalTransforms: ./ transforms/
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Mar 3 21:44:37 CET 2009
Author: kazuhiko
Date: Tue Mar 3 21:44:36 2009
New Revision: 25842
URL: http://svn.erp5.org?rev=25842&view=rev
Log:
1.4.1-nexedi - 2009-03-03
=========================
* Allowed the abbr, acronym, var, dfn, samp, address, bdo, thead, tfoot,
col, and colgroup tags by default, since they are harmless, valid XHTML
and shouldn't be filtered. Fixes:
http://dev.plone.org/plone/ticket/6712 and
http://dev.plone.org/plone/ticket/7251
[limi] (backport from 1.5.5-final)
* Add another XSS fix from for handling extraneous brackets.
[dunny] (backport from 1.5.3-final)
* Add XSS fixes from Anton Stonor to safe_html transform.
[alecm, stonor] (backport from 1.5.3-final)
* casting to int is evil without previous check of the type. so we assume as
in CMFPlone just zero for non-int-castable values.
[jensens] (backport from 1.5.0-a1)
* the values in the safe_html valid tag dictionary can become strings when
modifying them via the ZMI. Explicitly convert them to integers before
testing their value.
[wichert] (backport from 1.5.0-a1)
Modified:
erp5/trunk/products/PortalTransforms/HISTORY.txt
erp5/trunk/products/PortalTransforms/transforms/safe_html.py
erp5/trunk/products/PortalTransforms/utils.py
Modified: erp5/trunk/products/PortalTransforms/HISTORY.txt
URL: http://svn.erp5.org/erp5/trunk/products/PortalTransforms/HISTORY.txt?rev=25842&r1=25841&r2=25842&view=diff
==============================================================================
--- erp5/trunk/products/PortalTransforms/HISTORY.txt [utf8] (original)
+++ erp5/trunk/products/PortalTransforms/HISTORY.txt [utf8] Tue Mar 3 21:44:36 2009
@@ -1,10 +1,35 @@
+1.4.1-nexedi - 2009-03-03
+=========================
+
+ * Allowed the abbr, acronym, var, dfn, samp, address, bdo, thead, tfoot,
+ col, and colgroup tags by default, since they are harmless, valid XHTML
+ and shouldn't be filtered. Fixes:
+ http://dev.plone.org/plone/ticket/6712 and
+ http://dev.plone.org/plone/ticket/7251
+ [limi] (backport from 1.5.5-final)
+
+ * Add another XSS fix from for handling extraneous brackets.
+ [dunny] (backport from 1.5.3-final)
+
+ * Add XSS fixes from Anton Stonor to safe_html transform.
+ [alecm, stonor] (backport from 1.5.3-final)
+
+ * casting to int is evil without previous check of the type. so we assume as
+ in CMFPlone just zero for non-int-castable values.
+ [jensens] (backport from 1.5.0-a1)
+
+ * the values in the safe_html valid tag dictionary can become strings when
+ modifying them via the ZMI. Explicitly convert them to integers before
+ testing their value.
+ [wichert] (backport from 1.5.0-a1)
+
1.4.0-nexedi - 2008-10-24
-========================
+=========================
* fixed an infinite loop bug.
* remove PortalTransforms/configure.zcml that is not compatible with
- Zope-2.8's five.
+ Zope-2.8's Five (1.0.2).
* let the user configure 'initial_header_level' (cf
'rest-header-level' directive).
@@ -16,7 +41,7 @@
transform tool will be copied and this transform will be removed
from copied one.
-1.4.0-final - 2006-06-16
+1.4.1-final - 2006-09-08
========================
* Shut down a noisy logging message to DEBUG level.
Modified: erp5/trunk/products/PortalTransforms/transforms/safe_html.py
URL: http://svn.erp5.org/erp5/trunk/products/PortalTransforms/transforms/safe_html.py?rev=25842&r1=25841&r2=25842&view=diff
==============================================================================
--- erp5/trunk/products/PortalTransforms/transforms/safe_html.py [utf8] (original)
+++ erp5/trunk/products/PortalTransforms/transforms/safe_html.py [utf8] Tue Mar 3 21:44:36 2009
@@ -1,5 +1,7 @@
import logging
from sgmllib import SGMLParser
+import re
+from cgi import escape
from Products.PortalTransforms.interfaces import itransform
from Products.PortalTransforms.utils import log
@@ -8,23 +10,62 @@
from Products.CMFDefault.utils import SimpleHTMLParser
from Products.CMFDefault.utils import VALID_TAGS
from Products.CMFDefault.utils import NASTY_TAGS
+from Products.PortalTransforms.utils import safeToInt
# tag mapping: tag -> short or long tag
VALID_TAGS = VALID_TAGS.copy()
NASTY_TAGS = NASTY_TAGS.copy()
-# add some tags to allowed types. This should be fixed in CMFDefault
+# add some tags to allowed types. These should be backported to CMFDefault.
VALID_TAGS['ins'] = 1
VALID_TAGS['del'] = 1
VALID_TAGS['q'] = 1
-VALID_TAGS['map']=1
-VALID_TAGS['area']=1
+VALID_TAGS['map'] = 1
+VALID_TAGS['area'] = 1
+VALID_TAGS['abbr'] = 1
+VALID_TAGS['acronym'] = 1
+VALID_TAGS['var'] = 1
+VALID_TAGS['dfn'] = 1
+VALID_TAGS['samp'] = 1
+VALID_TAGS['address'] = 1
+VALID_TAGS['bdo'] = 1
+VALID_TAGS['thead'] = 1
+VALID_TAGS['tfoot'] = 1
+VALID_TAGS['col'] = 1
+VALID_TAGS['colgroup'] = 1
msg_pat = """
<div class="system-message">
<p class="system-message-title">System message: %s</p>
%s</d>
"""
+
+def hasScript(s):
+ """ Dig out evil Java/VB script inside an HTML attribute """
+
+ # look for "script" and "expression"
+ javascript_pattern = re.compile("([\s\n]*?s[\s\n]*?c[\s\n]*?r[\s\n]*?i[\s\n]*?p[\s\n]*?t[\s\n]*?:)|([\s\n]*?e[\s\n]*?x[\s\n]*?p[\s\n]*?r[\s\n]*?e[\s\n]*?s[\s\n]*?s[\s\n]*?i[\s\n]*?o[\s\n]*?n)", re.DOTALL|re.IGNORECASE)
+ s = decode_htmlentities(s)
+ return javascript_pattern.findall(s)
+
+def decode_htmlentities(s):
+ """ XSS code can be hidden with htmlentities """
+
+ entity_pattern = re.compile("&#(?P<htmlentity>x?\w+)?;?")
+ s = entity_pattern.sub(decode_htmlentity,s)
+ return s
+
+def decode_htmlentity(m):
+ entity_value = m.groupdict()['htmlentity']
+ if entity_value.lower().startswith('x'):
+ try:
+ return chr(int('0'+entity_value,16))
+ except ValueError:
+ return entity_value
+ try:
+ return chr(int(entity_value))
+ except ValueError:
+ return entity_value
class StrippingParser(SGMLParser):
"""Pass only allowed tags; raise exception for known-bad.
@@ -47,7 +88,7 @@
def handle_data(self, data):
if self.suppress: return
if data:
- self.result.append(data)
+ self.result.append(escape(data))
def handle_charref(self, name):
if self.suppress: return
@@ -74,23 +115,24 @@
"""
if self.suppress: return
- #if self.remove_javascript and tag == script and :
if self.valid.has_key(tag):
self.result.append('<' + tag)
+ remove_script = getattr(self,'remove_javascript',True)
+
for k, v in attrs:
- if self.remove_javascript and k.strip().lower().startswith('on'):
+ if remove_script and k.strip().lower().startswith('on'):
if not self.raise_error: continue
- else: raise IllegalHTML, 'Javascript event "%s" not allowed.' % k
- elif self.remove_javascript and v.strip().lower().startswith('javascript:' ):
+ else: raise IllegalHTML, 'Script event "%s" not allowed.' % k
+ elif remove_script and hasScript(v):
if not self.raise_error: continue
- else: raise IllegalHTML, 'Javascript URI "%s" not allowed.' % v
+ else: raise IllegalHTML, 'Script URI "%s" not allowed.' % v
else:
self.result.append(' %s="%s"' % (k, v))
#UNUSED endTag = '</%s>' % tag
- if self.valid.get(tag):
+ if safeToInt(self.valid.get(tag)):
self.result.append('>')
else:
self.result.append(' />')
@@ -103,10 +145,10 @@
pass
def unknown_endtag(self, tag):
- if self.nasty.has_key(tag):
+ if self.nasty.has_key(tag) and not self.valid.has_key(tag):
self.suppress = False
if self.suppress: return
- if self.valid.get(tag):
+ if safeToInt(self.valid.get(tag)):
self.result.append('</%s>' % tag)
#remTag = '</%s>' % tag
@@ -127,13 +169,19 @@
class SafeHTML:
"""Simple transform which uses CMFDefault functions to
- clean potentially bad tags.
- Tags must explicit be allowed in valid_tags to pass. Only the tags
- themself are removed, not their contents. If tags are
- removed and in nasty_tags, they are removed with
- all of their contents.
- Be aware that you may need to clean the cache to let a Object
- call the transform again.
+ clean potentially bad tags.
+
+ Tags must explicit be allowed in valid_tags to pass. Only
+ the tags themself are removed, not their contents. If tags
+ are removed and in nasty_tags, they are removed with
+ all of their contents.
+
+ Objects will not be transformed again with changed settings.
+ You need to clear the cache by e.g.
+ 1.) restarting your zope or
+ 2.) empty the zodb-cache via ZMI -> Control_Panel
+ -> Database Management -> main || other_used_database
+ -> Flush Cache.
"""
__implements__ = itransform
Modified: erp5/trunk/products/PortalTransforms/utils.py
URL: http://svn.erp5.org/erp5/trunk/products/PortalTransforms/utils.py?rev=25842&r1=25841&r2=25842&view=diff
==============================================================================
--- erp5/trunk/products/PortalTransforms/utils.py [utf8] (original)
+++ erp5/trunk/products/PortalTransforms/utils.py [utf8] Tue Mar 3 21:44:36 2009
@@ -28,3 +28,12 @@
import os.path
_www = os.path.join(os.path.dirname(__file__), 'www')
skins_dir = None
+
+def safeToInt(value):
+ """Convert value to integer or just return 0 if we can't"""
+ try:
+ return int(value)
+ except ValueError:
+ return 0
+ except TypeError:
+ return 0
More information about the Erp5-report
mailing list