Example #1
0
        /// <summary> Go through <global-tag-attributes> section of the policy file.</summary>
        /// <param name="globalAttributeListNode">Top level of <global-tag-attributes>
        /// </param>
        /// <returns> A HashMap of global Attributes that need validation for every tag.
        /// </returns>
        /// <throws>  PolicyException  </throws>
        private Hashtable parseGlobalAttributes(XmlNode globalAttributeListNode)
        {
            XmlNodeList globalAttributeNodes = globalAttributeListNode.SelectNodes("attribute");
            Hashtable   globalAttributes     = new Hashtable();
            string      _name = "";

            //string _value = "";
            foreach (XmlNode node in globalAttributeNodes)
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    _name = node.Attributes[0].Value;
                    //_value = node.Attributes[1].Value;
                    Attribute toAdd = getCommonAttributeByName(_name);
                    if (toAdd != null)
                    {
                        globalAttributes.Add(_name, toAdd);
                    }
                    else
                    {
                        throw new PolicyException("Global attribute '" + _name + "' was not defined in <common-attributes>");
                    }
                    //if (!globalAttributes.ContainsKey(_name))
                    //    globalAttributes.Add(_name, new AntiSamyPattern(_name, _value));
                }
            }
            return(globalAttributes);
        }
Example #2
0
        /// <summary> Private method for parsing the <tag-rules> from the XML file.</summary>
        /// <param name="root">The root element for <tag-rules>
        /// </param>
        /// <returns> A List<Tag> containing the rules.
        /// </returns>
        /// <throws>  PolicyException  </throws>
        private Hashtable parseTagRules(XmlNode tagAttributeListNode)
        {
            Hashtable tags = new Hashtable();
            XmlNodeList tagList = tagAttributeListNode.SelectNodes("tag");
            foreach (XmlNode tagNode in tagList)
            {
                if (tagNode.NodeType == XmlNodeType.Element)
                {
                    String name = (tagNode.Attributes["name"] == null ? null : tagNode.Attributes["name"].Value);
                    String action = (tagNode.Attributes["action"] == null ? null : tagNode.Attributes["action"].Value);

                    Tag tag = new Tag(name);
                    if (tagNames == null)
                        tagNames = new ArrayList();

                    tagNames.Add(name);
                    tag.Action = action;
                    //XmlNodeList attributeList = tagNode.SelectNodes("attribute");
                    XmlNodeList attributeList = tagNode.SelectNodes("attribute");
                    foreach (XmlNode attributeNode in attributeList)
                    {
                        if (!attributeNode.HasChildNodes)
                        {
                            Attribute attribute = getCommonAttributeByName(attributeNode.Attributes["name"].Value);

                            if (attribute != null)
                            {
                                String onInvalid = (attributeNode.Attributes["onInvalid"] == null ? null : attributeNode.Attributes["onInvalid"].Value);
                                String description = (attributeNode.Attributes["description"] == null ? null : attributeNode.Attributes["description"].Value);
                                if (onInvalid != null && onInvalid.Length > 0)
                                    attribute.OnInvalid = onInvalid;
                                if (description != null && description.Length > 0)
                                    attribute.Description = description;

                                tag.addAttribute((org.owasp.validator.html.model.Attribute)attribute.Clone());
                            }
                            else
                            {
                                //TODO: make this work with .NET
                                //throw new PolicyException("Attribute '"+XMLUtil.getAttributeValue(attributeNode,"name")+"' was referenced as a common attribute in definition of '"+tag.getName()+"', but does not exist in <common-attributes>");

                            }
                        }
                        else
                        {
                            /* Custom attribute for this tag */
                            Attribute attribute = new Attribute(attributeNode.Attributes["name"].Value);
                            attribute.OnInvalid = (attributeNode.Attributes["onInvalid"] != null ? attributeNode.Attributes["onInvalid"].Value : null);
                            attribute.Description = (attributeNode.Attributes["description"] != null ? attributeNode.Attributes["description"].Value : null);
                            XmlNode regExpListNode = attributeNode.SelectNodes("regexp-list")[0];
                            if (regExpListNode != null)
                            {
                                XmlNodeList regExpList = regExpListNode.SelectNodes("regexp");
                                foreach (XmlNode regExpNode in regExpList)
                                {
                                    string regExpName = (regExpNode.Attributes["name"] == null ? null : regExpNode.Attributes["name"].Value);
                                    string value = (regExpNode.Attributes["value"] == null ? null : regExpNode.Attributes["value"].Value);
                                    if (regExpName != null && regExpName.Length > 0)
                                    {
                                        //AntiSamyPattern pattern = getRegularExpression(regExpName);
                                        string pattern = getRegularExpression(regExpName);
                                        if (pattern != null)
                                            attribute.addAllowedRegExp(pattern);
                                        //attribute.addAllowedRegExp(pattern.Pattern);
                                        else
                                        {
                                            throw new PolicyException("Regular expression '" + regExpName + "' was referenced as a common regexp in definition of '" + tag.Name + "', but does not exist in <common-regexp>");
                                        }
                                    }
                                    else if (value != null && value.Length > 0)
                                    {
                                        //TODO: see if I need to reimplement pattern.compile
                                        attribute.addAllowedRegExp(REGEXP_BEGIN + value + REGEXP_END);
                                    }
                                }
                            }
                            XmlNode literalListNode = attributeNode.SelectNodes("literal-list")[0];
                            if (literalListNode != null)
                            {
                                XmlNodeList literalNodes = literalListNode.SelectNodes("literal");
                                foreach (XmlNode literalNode in literalNodes)
                                {
                                    string value = (literalNode.Attributes["value"] == null ? null : literalNode.Attributes["value"].Value);
                                    if (value != null && value.Length > 0)
                                    {
                                        attribute.addAllowedValue(value);
                                    }
                                    else if (literalNode.Value != null)
                                    {
                                        attribute.addAllowedValue(literalNode.Value);
                                    }
                                }
                            }
                            tag.addAttribute(attribute);
                        }
                    }
                    tags.Add(name, tag);
                }
            }
            return tags;
        }
        private void recursiveValidateTag(HtmlNode node)
        {
            int maxinputsize = int.Parse(policy.getDirective("maxInputSize"));

            num++;

            HtmlNode parentNode = node.ParentNode;
            HtmlNode tmp        = null;
            string   tagName    = node.Name;

            //check this out
            //might not be robust enough
            if (tagName.ToLower().Equals("#text"))  // || tagName.ToLower().Equals("#comment"))
            {
                return;
            }

            Tag tag = policy.getTagByName(tagName.ToLower());

            if (tag == null || "filter".Equals(tag.Action))
            {
                StringBuilder errBuff = new StringBuilder();
                if (tagName == null || tagName.Trim().Equals(""))
                {
                    errBuff.Append("An unprocessable ");
                }
                else
                {
                    errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName.ToLower()) + "</b> ");
                }

                errBuff.Append("tag has been filtered for security reasons. The contents of the tag will ");
                errBuff.Append("remain in place.");

                errorMessages.Add(errBuff.ToString());

                for (int i = 0; i < node.ChildNodes.Count; i++)
                {
                    tmp = node.ChildNodes[i];
                    recursiveValidateTag(tmp);

                    if (tmp.ParentNode == null)
                    {
                        i--;
                    }
                }
                promoteChildren(node);
                return;
            }
            else if ("validate".Equals(tag.Action))
            {
                if ("style".Equals(tagName.ToLower()) && policy.getTagByName("style") != null)
                {
                    CssScanner styleScanner = new CssScanner(policy);
                    try
                    {
                        CleanResults cr = styleScanner.scanStyleSheet(node.FirstChild.InnerHtml, maxinputsize);

                        foreach (string msg in cr.getErrorMessages())
                        {
                            errorMessages.Add(msg.ToString());
                        }

                        /*
                         * If IE gets an empty style tag, i.e. <style/>
                         * it will break all CSS on the page. I wish I
                         * was kidding. So, if after validation no CSS
                         * properties are left, we would normally be left
                         * with an empty style tag and break all CSS. To
                         * prevent that, we have this check.
                         */

                        if (cr.getCleanHTML() == null || cr.getCleanHTML().Equals(""))
                        {
                            //node.getFirstChild().setNodeValue("/* */");
                            node.FirstChild.InnerHtml = "/* */";
                        }
                        else
                        {
                            //node.getFirstChild().setNodeValue(cr.getCleanHTML());
                            node.FirstChild.InnerHtml = cr.getCleanHTML();
                        }
                    }
                    //    catch (DomException e)
                    //    {
                    //        addError(ErrorMessageUtil.ERROR_CSS_TAG_MALFORMED, new Object[] { HTMLEntityEncoder.htmlEntityEncode(node.getFirstChild().getNodeValue()) });
                    //        parentNode.removeChild(node);
                    //    }
                    catch (ScanException e)
                    {
                        Console.WriteLine("Scan Exception: " + e.Message);

                        //addError(ErrorMessageUtil.ERROR_CSS_TAG_MALFORMED, new Object[] { HTMLEntityEncoder.htmlEntityEncode(node.getFirstChild().getNodeValue()) });
                        parentNode.RemoveChild(node);
                    }
                }

                HtmlAttribute attribute = null;
                for (int currentAttributeIndex = 0; currentAttributeIndex < node.Attributes.Count; currentAttributeIndex++)
                {
                    attribute = node.Attributes[currentAttributeIndex];

                    string name   = attribute.Name;
                    string _value = attribute.Value;

                    Attribute attr = tag.getAttributeByName(name);

                    if (attr == null)
                    {
                        attr = policy.getGlobalAttributeByName(name);
                    }

                    bool isAttributeValid = false;

                    if ("style".Equals(name.ToLower()) && attr != null)
                    {
                        CssScanner styleScanner = new CssScanner(policy);

                        try
                        {
                            CleanResults cr = styleScanner.scanInlineStyle(_value, tagName, maxinputsize);

                            //attribute.setNodeValue(cr.getCleanHTML());
                            attribute.Value = cr.getCleanHTML();

                            ArrayList cssScanErrorMessages = cr.getErrorMessages();

                            foreach (string msg in cr.getErrorMessages())
                            {
                                errorMessages.Add(msg.ToString());
                            }
                        }

                        /*
                         * catch (DOMException e)
                         * {
                         *
                         *  addError(ErrorMessageUtil.ERROR_CSS_ATTRIBUTE_MALFORMED, new Object[] { tagName, HTMLEntityEncoder.htmlEntityEncode(node.getNodeValue()) });
                         *
                         *  ele.removeAttribute(name);
                         *  currentAttributeIndex--;
                         *
                         * }
                         */
                        catch (ScanException ex)
                        {
                            Console.WriteLine(ex.Message);
                            //addError(ErrorMessageUtil.ERROR_CSS_ATTRIBUTE_MALFORMED, new Object[] { tagName, HTMLEntityEncoder.htmlEntityEncode(node.getNodeValue()) });
                            //ele.removeAttribute(name);
                            currentAttributeIndex--;
                        }
                    }
                    else
                    {
                        if (attr != null)
                        {
                            //try to find out how robust this is - do I need to do this in a loop?
                            _value = HtmlEntity.DeEntitize(_value);

                            foreach (string allowedValue in attr.AllowedValues)
                            {
                                if (isAttributeValid)
                                {
                                    break;
                                }

                                if (allowedValue != null && allowedValue.ToLower().Equals(_value.ToLower()))
                                {
                                    isAttributeValid = true;
                                }
                            }

                            foreach (string ptn in attr.AllowedRegExp)
                            {
                                if (isAttributeValid)
                                {
                                    break;
                                }
                                string pattern = "^" + ptn + "$";
                                Match  m       = Regex.Match(_value, pattern);
                                if (m.Success)
                                {
                                    isAttributeValid = true;
                                }
                            }

                            if (!isAttributeValid)
                            {
                                string        onInvalidAction = attr.OnInvalid;
                                StringBuilder errBuff         = new StringBuilder();

                                errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag contained an attribute that we couldn't process. ");
                                errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(name) + "</b> attribute had a value of <u>" + HTMLEntityEncoder.htmlEntityEncode(_value) + "</u>. ");
                                errBuff.Append("This value could not be accepted for security reasons. We have chosen to ");

                                //Console.WriteLine(policy);

                                if ("removeTag".Equals(onInvalidAction))
                                {
                                    parentNode.RemoveChild(node);
                                    errBuff.Append("remove the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag and its contents in order to process this input. ");
                                }
                                else if ("filterTag".Equals(onInvalidAction))
                                {
                                    for (int i = 0; i < node.ChildNodes.Count; i++)
                                    {
                                        tmp = node.ChildNodes[i];
                                        recursiveValidateTag(tmp);
                                        if (tmp.ParentNode == null)
                                        {
                                            i--;
                                        }
                                    }

                                    promoteChildren(node);

                                    errBuff.Append("filter the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag and leave its contents in place so that we could process this input.");
                                }
                                else
                                {
                                    node.Attributes.Remove(attr.Name);
                                    currentAttributeIndex--;
                                    errBuff.Append("remove the <b>" + HTMLEntityEncoder.htmlEntityEncode(name) + "</b> attribute from the tag and leave everything else in place so that we could process this input.");
                                }

                                errorMessages.Add(errBuff.ToString());

                                if ("removeTag".Equals(onInvalidAction) || "filterTag".Equals(onInvalidAction))
                                {
                                    return; // can't process any more if we remove/filter the tag
                                }
                            }
                        }
                        else
                        {
                            StringBuilder errBuff = new StringBuilder();

                            errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(name));
                            errBuff.Append("</b> attribute of the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag has been removed for security reasons. ");
                            errBuff.Append("This removal should not affect the display of the HTML submitted.");

                            errorMessages.Add(errBuff.ToString());
                            node.Attributes.Remove(name);
                            currentAttributeIndex--;
                        } // end if attribute is or is not found in policy file
                    }     // end if style.equals("name")
                }         // end while loop through attributes


                for (int i = 0; i < node.ChildNodes.Count; i++)
                {
                    tmp = node.ChildNodes[i];
                    recursiveValidateTag(tmp);
                    if (tmp.ParentNode == null)
                    {
                        i--;
                    }
                }
            }
            else if ("truncate".Equals(tag.Action))
            {
                Console.WriteLine("truncate");
                HtmlAttributeCollection nnmap = node.Attributes;

                while (nnmap.Count > 0)
                {
                    StringBuilder errBuff = new StringBuilder();

                    errBuff.Append("The <b>" + HTMLEntityEncoder.htmlEntityEncode(nnmap[0].Name));
                    errBuff.Append("</b> attribute of the <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag has been removed for security reasons. ");
                    errBuff.Append("This removal should not affect the display of the HTML submitted.");
                    node.Attributes.Remove(nnmap[0].Name);
                    errorMessages.Add(errBuff.ToString());
                }

                HtmlNodeCollection cList = node.ChildNodes;

                int i      = 0;
                int j      = 0;
                int length = cList.Count;

                while (i < length)
                {
                    HtmlNode nodeToRemove = cList[j];
                    if (nodeToRemove.NodeType != HtmlNodeType.Text && nodeToRemove.NodeType != HtmlNodeType.Comment)
                    {
                        node.RemoveChild(nodeToRemove);
                    }
                    else
                    {
                        j++;
                    }
                    i++;
                }
            }
            else
            {
                errorMessages.Add("The <b>" + HTMLEntityEncoder.htmlEntityEncode(tagName) + "</b> tag has been removed for security reasons.");
                parentNode.RemoveChild(node);
            }
        }
Example #4
0
        /// <summary> Private method for parsing the <tag-rules> from the XML file.</summary>
        /// <param name="root">The root element for <tag-rules>
        /// </param>
        /// <returns> A List<Tag> containing the rules.
        /// </returns>
        /// <throws>  PolicyException  </throws>
        private Hashtable parseTagRules(XmlNode tagAttributeListNode)
        {
            Hashtable   tags    = new Hashtable();
            XmlNodeList tagList = tagAttributeListNode.SelectNodes("tag");

            foreach (XmlNode tagNode in tagList)
            {
                if (tagNode.NodeType == XmlNodeType.Element)
                {
                    String name   = (tagNode.Attributes["name"] == null ? null : tagNode.Attributes["name"].Value);
                    String action = (tagNode.Attributes["action"] == null ? null : tagNode.Attributes["action"].Value);

                    Tag tag = new Tag(name);
                    if (tagNames == null)
                    {
                        tagNames = new ArrayList();
                    }

                    tagNames.Add(name);
                    tag.Action = action;
                    //XmlNodeList attributeList = tagNode.SelectNodes("attribute");
                    XmlNodeList attributeList = tagNode.SelectNodes("attribute");
                    foreach (XmlNode attributeNode in attributeList)
                    {
                        if (!attributeNode.HasChildNodes)
                        {
                            Attribute attribute = getCommonAttributeByName(attributeNode.Attributes["name"].Value);

                            if (attribute != null)
                            {
                                String onInvalid   = (attributeNode.Attributes["onInvalid"] == null ? null : attributeNode.Attributes["onInvalid"].Value);
                                String description = (attributeNode.Attributes["description"] == null ? null : attributeNode.Attributes["description"].Value);
                                if (onInvalid != null && onInvalid.Length > 0)
                                {
                                    attribute.OnInvalid = onInvalid;
                                }
                                if (description != null && description.Length > 0)
                                {
                                    attribute.Description = description;
                                }

                                tag.addAttribute((org.owasp.validator.html.model.Attribute)attribute.Clone());
                            }
                            else
                            {
                                //TODO: make this work with .NET
                                //throw new PolicyException("Attribute '"+XMLUtil.getAttributeValue(attributeNode,"name")+"' was referenced as a common attribute in definition of '"+tag.getName()+"', but does not exist in <common-attributes>");
                            }
                        }
                        else
                        {
                            /* Custom attribute for this tag */
                            Attribute attribute = new Attribute(attributeNode.Attributes["name"].Value);
                            attribute.OnInvalid   = (attributeNode.Attributes["onInvalid"] != null ? attributeNode.Attributes["onInvalid"].Value : null);
                            attribute.Description = (attributeNode.Attributes["description"] != null ? attributeNode.Attributes["description"].Value : null);
                            XmlNode regExpListNode = attributeNode.SelectNodes("regexp-list")[0];
                            if (regExpListNode != null)
                            {
                                XmlNodeList regExpList = regExpListNode.SelectNodes("regexp");
                                foreach (XmlNode regExpNode in regExpList)
                                {
                                    string regExpName = (regExpNode.Attributes["name"] == null ? null : regExpNode.Attributes["name"].Value);
                                    string value      = (regExpNode.Attributes["value"] == null ? null : regExpNode.Attributes["value"].Value);
                                    if (regExpName != null && regExpName.Length > 0)
                                    {
                                        //AntiSamyPattern pattern = getRegularExpression(regExpName);
                                        string pattern = getRegularExpression(regExpName);
                                        if (pattern != null)
                                        {
                                            attribute.addAllowedRegExp(pattern);
                                        }
                                        //attribute.addAllowedRegExp(pattern.Pattern);
                                        else
                                        {
                                            throw new PolicyException("Regular expression '" + regExpName + "' was referenced as a common regexp in definition of '" + tag.Name + "', but does not exist in <common-regexp>");
                                        }
                                    }
                                    else if (value != null && value.Length > 0)
                                    {
                                        //TODO: see if I need to reimplement pattern.compile
                                        attribute.addAllowedRegExp(REGEXP_BEGIN + value + REGEXP_END);
                                    }
                                }
                            }
                            XmlNode literalListNode = attributeNode.SelectNodes("literal-list")[0];
                            if (literalListNode != null)
                            {
                                XmlNodeList literalNodes = literalListNode.SelectNodes("literal");
                                foreach (XmlNode literalNode in literalNodes)
                                {
                                    string value = (literalNode.Attributes["value"] == null ? null : literalNode.Attributes["value"].Value);
                                    if (value != null && value.Length > 0)
                                    {
                                        attribute.addAllowedValue(value);
                                    }
                                    else if (literalNode.Value != null)
                                    {
                                        attribute.addAllowedValue(literalNode.Value);
                                    }
                                }
                            }
                            tag.addAttribute(attribute);
                        }
                    }
                    tags.Add(name, tag);
                }
            }
            return(tags);
        }