diff --git a/webapp/lib/antisamy-1.4.4.jar b/webapp/lib/antisamy-1.4.4.jar new file mode 100644 index 000000000..45ce10b7d Binary files /dev/null and b/webapp/lib/antisamy-1.4.4.jar differ diff --git a/webapp/lib/batik-css.jar b/webapp/lib/batik-css.jar new file mode 100644 index 000000000..c1f1c9a88 Binary files /dev/null and b/webapp/lib/batik-css.jar differ diff --git a/webapp/lib/nekohtml.jar b/webapp/lib/nekohtml.jar new file mode 100644 index 000000000..16261d2eb Binary files /dev/null and b/webapp/lib/nekohtml.jar differ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/AntiScript.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/AntiScript.java new file mode 100644 index 000000000..96a9220e4 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/AntiScript.java @@ -0,0 +1,109 @@ +package edu.cornell.mannlib.vitro.webapp.web; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.servlet.ServletContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.owasp.validator.html.AntiSamy; +import org.owasp.validator.html.CleanResults; +import org.owasp.validator.html.Policy; +import org.owasp.validator.html.PolicyException; +import org.owasp.validator.html.ScanException; + +/** + * This is a class to provide methods to strip bad HTML from user input. + * The primary goal of this is to avoid XSS attacks. + */ +public class AntiScript { + + private static final Log log = LogFactory.getLog(AntiScript.class); + + + private static final String ANTI_SCRIPT_POLICY = "ANTI_SCRIPT_POLICY"; + private static final String ANTI_SCRIPT_SCANNER = "ANTI_SCRIPT_SCANNER"; + private static String ANTI_SCRIPT_POLICY_FILE = "/WEB-INF/classes/edu/cornell/mannlib/vitro/webapp/web/antisamy-vitro-1.4.4.xml"; + + /** + * This will attempt to return HTML that has been cleaned up according + * to the policy. + * + * If there is any error during the scan, an error message + * will be returned instead of the HTML. This might not be ideal so + * consider changing it once we see how this works. Other options include + * returning an empty string or some other error message. Returning + * the unscanned HTML is not a secure option as it may contain scripts. + * + * This will return null if dirtyInput is null. + */ + public static String cleanHtml( String dirtyInput, ServletContext context){ + if( dirtyInput == null ) + return null; + + AntiSamy as = getHTMLScanner(context); + CleanResults cr; + try { + cr = as.scan(dirtyInput); + return cr.getCleanHTML(); + } catch (ScanException e) { + log.error("Error while scaning HTML" ,e ); + } catch (PolicyException e) { + log.error("Error while scanning HTML", e); + } + return "AntiScript: HTML caused scan error."; + } + + /** + * Method to clean a URL or URI. Might do the same thing as cleanHTML(). + */ + public static String cleanURI( String dirtyInput, ServletContext context){ + return cleanHtml(dirtyInput,context); + } + + /** + * Try to get the policy from the servlet context, if none exists, create a new one. + * This is a anti-script policy for use with OWASP AntiSamy, not a vivo auth Policy. + * Returns null if no policy can be created. + */ + protected static Policy getAntiScriptPolicy(ServletContext context){ + Object obj = context.getAttribute( ANTI_SCRIPT_POLICY ); + if( obj == null ){ + Policy newPolicy; + try { + String url = ANTI_SCRIPT_POLICY_FILE; + URL policyFile= context.getResource( url ); + newPolicy = Policy.getInstance( policyFile ); + context.setAttribute(ANTI_SCRIPT_POLICY, newPolicy); + log.debug("anti-script policy loaded successfully"); + return newPolicy; + } catch (PolicyException e) { + log.error("Anti-Script policy not setup.", e); + return null; + } catch (MalformedURLException e) { + log.error("Anti-Script policy not setup.", e); + return null; + } + } else { + return (Policy)obj; + } + } + + /** + * Try to get an AntiSamy HTML scanner object that is sharied across + * the whole web application. This may return a scanner with a null + * policy if the policy is not setup correctly. + */ + protected static AntiSamy getHTMLScanner( ServletContext context){ + Object obj = context.getAttribute( ANTI_SCRIPT_SCANNER ); + if( obj == null ){ + AntiSamy scanner = new AntiSamy( getAntiScriptPolicy(context)); + context.setAttribute( ANTI_SCRIPT_SCANNER , scanner); + log.debug("anti-script scanner loaded successfully"); + return scanner; + }else{ + return (AntiSamy) obj; + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/antisamy-vitro-1.4.4.xml b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/antisamy-vitro-1.4.4.xml new file mode 100644 index 000000000..7f2a3371c --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/antisamy-vitro-1.4.4.xml @@ -0,0 +1,2669 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + g + + grin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/BaseTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/BaseTemplateModel.java index aca991be3..0cb8422b9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/BaseTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/BaseTemplateModel.java @@ -10,6 +10,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; +import edu.cornell.mannlib.vitro.webapp.web.AntiScript; public abstract class BaseTemplateModel { @@ -32,6 +33,22 @@ public abstract class BaseTemplateModel { return UrlBuilder.getUrl(path, params); } + /** + * Used to do any processing for display of URIs or URLs. + * Currently this only checks for XSS exploits. + */ + protected String cleanURIForDisplay( String dirty ){ + return AntiScript.cleanURI(dirty, getServletContext()); + } + + /** + * Used to do any processing for display of general text. + * Currently this only checks for XSS exploits. + */ + protected String cleanTextForDisplay( String dirty){ + return AntiScript.cleanHtml(dirty, getServletContext()); + } + public static ServletContext getServletContext() { return servletContext; } @@ -39,5 +56,6 @@ public abstract class BaseTemplateModel { public static void setServletContext(ServletContext context) { servletContext = context; } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java index aad1d07ff..c0f78ffdd 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/LinkTemplateModel.java @@ -30,7 +30,7 @@ public class LinkTemplateModel extends BaseTemplateModel { } public String getUrl() { - return url; + return cleanTextForDisplay( url ); } protected void setUrl(String path) { @@ -46,7 +46,7 @@ public class LinkTemplateModel extends BaseTemplateModel { } public String getText() { - return text; + return cleanTextForDisplay(text); } protected void setText(String text) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyStatementTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyStatementTemplateModel.java index 7aa11c09e..e39fd79d1 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyStatementTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyStatementTemplateModel.java @@ -36,7 +36,9 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat Literal literal, EditingPolicyHelper policyHelper, VitroRequest vreq) { super(subjectUri, propertyUri, policyHelper, vreq); - this.value = literal.getLexicalForm(); + //attempt to strip any odd HTML + this.value = cleanTextForDisplay( literal.getLexicalForm() ); + setEditAccess(literal, policyHelper, propertyUri); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java index f9d9480eb..71b0b514c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java @@ -39,7 +39,7 @@ public class NameStatementTemplateModel extends EditLiteral literal = iDao.getLabelEditLiteral(subjectUri); if (literal != null) { - value = literal.getLexicalForm(); + value = cleanTextForDisplay( literal.getLexicalForm() ); setEditAccess(literal, policyHelper); } else { // If the individual has no rdfs:label, use the local name. It will not be editable. (This replicates previous behavior; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java index d7bc8e9c0..300a94184 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java @@ -16,7 +16,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; -import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; public class ObjectPropertyStatementTemplateModel extends PropertyStatementTemplateModel { @@ -37,7 +36,7 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl super(subjectUri, propertyUri, policyHelper, vreq); this.data = data; - this.objectUri = data.get(objectKey); + this.objectUri = cleanURIForDisplay( data.get(objectKey) ); this.templateName = templateName; setEditAccess(policyHelper); } @@ -66,7 +65,7 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl /* Access methods for templates */ public Object get(String key) { - return data.get(key); + return cleanTextForDisplay( data.get(key) ); } public String getEditUrl() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individuallist/BaseListedIndividual.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individuallist/BaseListedIndividual.java index 0e3ae2af9..e6d9b0e92 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individuallist/BaseListedIndividual.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individuallist/BaseListedIndividual.java @@ -38,7 +38,7 @@ public abstract class BaseListedIndividual extends BaseTemplateModel { /* Access methods for templates */ public String getProfileUrl() { - return UrlBuilder.getIndividualProfileUrl(individual, vreq); + return cleanURIForDisplay( UrlBuilder.getIndividualProfileUrl(individual, vreq) ); } public String getImageUrl() { @@ -52,11 +52,11 @@ public abstract class BaseListedIndividual extends BaseTemplateModel { } public String getName() { - return individual.getName(); + return cleanTextForDisplay( individual.getName() ); } public String getUri() { - return individual.getURI(); + return cleanURIForDisplay( individual.getURI() ); } public List getMostSpecificTypes() {