Java 5 HTML 转义以防止 XSS

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2333586/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:39:21  来源:igfitidea点击:

Java 5 HTML escaping To Prevent XSS

javajspxss

提问by AJM

I'm looking into some XSS prevention in my Java application.

我正在研究 Java 应用程序中的一些 XSS 预防措施。

I currently have custom built routines that will escape any HTML stored in the database for safe display in my jsps. However I would rather use a built in/standard method to do this if possible.

我目前有自定义构建的例程,可以转义存储在数据库中的任何 HTML,以便在我的 jsps 中安全显示。但是,如果可能,我宁愿使用内置/标准方法来执行此操作。

I am not currently encoding data that gets sent to the database but would like to start doing that as well.

我目前没有对发送到数据库的数据进行编码,但也想开始这样做。

Are there any built in methods that can help me to achieve this?

是否有任何内置方法可以帮助我实现这一目标?

回答by BalusC

You normally escape XSS during display, not during store. In JSP you can use the JSTL(just drop jstl-1.2.jarin /WEB-INF/lib) <c:out>tag or fn:escapeXmlfunction for this. E.g.

您通常在显示期间而不是在存储期间逃脱 XSS 。在 JSP 中,您可以为此使用JSTL(只需将jstl-1.2.jar放入/WEB-INF/lib<c:out>标记或fn:escapeXml函数。例如

<input name="foo" value="<c:out value="${param.foo}" />">

or

或者

<input name="foo" value="${fn:escapeXml(param.foo)}">

That's it. If you do it during processing the input and/or storing in DB as well, then it's all spread over the business code and/or in the database. You should not do that, it's only maintenance trouble and you will risk double-escapes or more when you do it at different places (e.g. &would become &amp;amp;instead of &amp;so that the enduser would literally see &amp;instead of &in view. The code and DB are not sensitive for XSS. Only the view is. You should then escape it only right there.

而已。如果您在处理输入和/或在 DB 中存储时也这样做,那么它全部分布在业务代码和/或数据库中。你不应该这样做,这只是维护问题,当你在不同的地方做这件事时,你会冒双重逃逸或更多的风险(例如,&将变成&amp;amp;而不是&amp;这样最终用户会真正看到&amp;而不是&在视图中。代码和数据库不是对 XSS 敏感。只有视图是。然后你应该只在那里逃避它。

Update: you've posted 4 topics about the same subject:

更新:您已经发布了 4 个关于同一主题的主题:

I will only warn you: you do notneed to escape it in servlet/filter/javacode/database/whatever. You're only unnecessarily overcomplicating things. Just escape it during display. That's all.

我只提醒你:你不是需要逃离它的servlet /过滤/ javacode /数据库/不管。你只是把事情不必要地复杂化了。只需在显示期间将其转义即可。就这样。

回答by futtta

not built-in, but check out the owasp esapi filter, it should do what you're looking for and more. It is a great open source security library written by the smart guys&girls at Owasp ("Open Web Application Security Project").

不是内置的,但请查看owasp esapi 过滤器,它应该可以满足您的要求等等。这是一个很棒的开源安全库,由 Owasp(“开放 Web 应用程序安全项目”)的聪明人编写。

回答by Adam Gent

I have to say I rather disagree with the accepted answer of apparently escaping on output to prevent XSS.

我不得不说我相当不同意显然逃避输出以防止 XSS 的公认答案。

I believe the better approach is to sanitize on input which can easily be achieved with an aspect so that you don't have to put it all over the place. Sanitizing is different than escaping.

我相信更好的方法是对输入进行消毒,这可以通过一个方面轻松实现,这样您就不必把它放在所有地方。消毒不同于逃避

You can't just blindly escape:

你不能只是盲目地逃避:

  • You may want users to enter a subset of HTML (aka links and bold tags).
  • Escaping does not prevent XSS
  • 您可能希望用户输入 HTML 的子集(也称为链接和粗体标记)。
  • 转义并不能阻止 XSS

I recommend using OWASP Antisammy library with an Aspect or @futtta's recommendation of the filter.

我建议将 OWASP Antisammy 库与 Aspect 或 @futtta 的过滤器推荐一起使用。

Below is an aspect I wrote to sanitize user input using Spring MVC annotations (since we use that for all of our input).

下面是我编写的一个方面,用于使用 Spring MVC 注释清理用户输入(因为我们将其用于所有输入)。

@SuppressWarnings("unused")
@Aspect
public class UserInputSanitizerAdivsor {

    @Around("execution(@RequestMapping * * (..))")
    public Object check(final ProceedingJoinPoint jp) throws Throwable {
        Object[] args = jp.getArgs();
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                Object o = args[i];
                if (o != null && o instanceof String) {
                    String s = (String) o;
                    args[i] = UserInputSanitizer.sanitize(s);
                }
            }
        }
        return jp.proceed(args);
    }
}

You will still have to escape on output for non rich-text fields but you will never (and I believe should never) have malicious data in your database.

您仍然必须对非富文本字段的输出进行转义,但您永远不会(并且我相信永远不应该)在您的数据库中包含恶意数据。

If you don't want to sanitize on certain inputs you can always make annotation that will make the aspect not sanitize.

如果您不想对某些输入进行消毒,您可以随时进行注释,使方面不会被消毒。

The other reason you don't want malicious data in your database is if you provide any sort REST API to the Internet. You may do the right thing on output but your mashup partners may not.

您不希望数据库中包含恶意数据的另一个原因是,您是否向 Internet 提供了任何类型的 REST API。您可能会在输出方面做正确的事情,但您的混搭合作伙伴可能不会。

Sanitizing input or blocking input is ok (I mean most people have file upload limit right?). Most of the fields in a web application don't need script tags to be entered and more importantly most of your users probably do not need or want to enter script tags (obvious exception is stack overflow answers).

清理输入或阻止输入是可以的(我的意思是大多数人都有文件上传限制,对吗?)。Web 应用程序中的大多数字段不需要输入脚本标签,更重要的是,您的大多数用户可能不需要或不想输入脚本标签(明显的例外是堆栈溢出答案)。