0
点赞
收藏
分享

微信扫一扫

Handlebars 框架的XSS问题

爱写作的小土豆 2022-04-06 阅读 102
web安全xss

Handlebars框架【Handlebars】是一个JavaScript的一个模板语言,根据其首页的介绍:

Handlebars is a simple templating language.

在这里姑且整它为一种模板语言吧。它主要的功能就是使用模板和输入的对象输出HTML或者其他文本格式,它输出对象的方法如下:

<p>{{firstname}} {{lastname}}</p>

Handlebars输出的方式主要有两种,

一种方式是{{{data}}},这种格式输出的内容是原生输出,不做任何处理,也就是在输出时不对内容进行任何处理。这也就带来了风险:当输出的内容含有恶意的JavaScript脚本时,会导致恶意脚本的执行,也就是会发生XSS攻击。

第二种是{{data}},这种输出方式,会对data进行HTML的一些特殊字符进行escape,escape的主要字符如下表:

字符&<>"'`=
escape之后的值&amp;&lt;&gt;&quot;&#x27;&#x60;&#x3D;

这说明,Handlebars在设计的时候是考虑到如何处理XSS问题的。

不过,在handlebars的首页,有以下这么一句话:

 这里的警告就说明了,Handlebars是不会处理JavaScript字符串的,也就是说,当你输出数据到JavaScript代码中时,还是可能导致XSS问题的产生。下面就是一个非常简单的例子:

 这里可以看到,当输出的内容有特殊的脚本时,输出的Javascript的值是不正确的,导致输出的内容被改变。

这是就需要在输出内容到JavaScript代码时,对输出内容进行JavaScript编码【可以参考另外一篇博客:应用安全系列之二:XSS_jimmyleeee的博客-CSDN博客】。由于Handlebars没有提供对应的JavaScript输出方式,所以使用原生的Handlebars的输出时不能解决问题的。 但是,Handlebars提供了一个注册接口,可以注册扩展的Helper,然后在输出的时候使用自己的Helper输出,例如,注册一个Helper的名字是:encodeJS,输出的方式为:{{{encodeJS data}}}。encodeJS的样例代码如下:

public class EncodeJSHelper implements Helper<Object> {
	
	public static final String HELPER_NAME = "encodeJS";
	

	public static final Helper<Object> INSTANCE = new EncodeJSHelper();
	
	@Override
    public CharSequence apply(final Object context, final Options options) throws IOException {
        return Encoder.encodeJS(context.toString());
    }
	
}

根据 【另外一篇博客:应用安全系列之二:XSS_jimmyleeee的博客-CSDN博客】,输出的时候,可能会遇到复合编码的情况,如下:

<button onclick =”viewProduct( '<%=id%>')”>查看产品信息</button>

 id首先输出作为viewProduct函数的参数,这是作为Javascript的一部分,同时,又是标签<button>的一部分。在这种情况下,只做一种编码是不够的。需要进行复合编码。那么,一个helper怎么能够进行两种编码呢? 设计Handlebars的人员估计是考虑到输出时有特殊情况需要处理的,所以helper的接口体统了Options参数,可以通过这个Options参数传递,需要先进行什么处理,然后再调用Helper的调用。这里的例子,就使用option的参数为用于传递需要预先对数据进行什么处理。示例代码如下:

public class EncodeHTMLHelper implements Helper<Object> {
	
	public static final String HELPER_NAME = "encodeHTML";
	

	public static final Helper<Object> INSTANCE = new EncodeHTMLHelper();
	
	@Override
    public CharSequence apply(final Object context, final Options options) throws IOException {
		Boolean encodeJS = options.hash("encodeJS", Boolean.FALSE);
		String data = context.toString();
		if (encodeJS == Boolean.TRUE) {
			data = Encoder.encodeJS(data);
		}
        return Encoder.encodeHTML(data);
    }
	
}

添加了这个Helper之后,在应用程序启动时,记住要先注册才能使用。SpringBoot的应用的注册示例代码如下:

@SpringBootApplication
public class DemoApplication extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {

	@Autowired
	private HandlebarsViewResolver handlebarsViewResolver;
	
	public static void main(String[] args) {
		handlebarsViewResolver.registerHelper(EncodeHTMLHelper.HELPER_NAME, EncodeHTMLHelper.INSTANCE);
		handlebarsViewResolver.registerHelper(EncodeJSHelper.HELPER_NAME, EncodeJSHelper.INSTANCE);
		SpringApplication.run(LargestApplication.class, args);
	}
}

注册好了Helper之后,根据实际的Helper的设置,就可以将之前的复合编码的例子修改如下:

<button onclick =”viewProduct( '<%=encodeHTML id encodeJS=true %>')”>查看产品信息</button>

这样就可以解决Handlebars输出内容需要复合编码的情况。 

当然,如果输出的内容是URL的一部分时,需要先对数据进行URL编码,这里可以同样适用Options参数传递是否需要进行URL编码。

根据以上的实现,其实Handlebars其实可以自己实现以上操作,这样就可以自身提供全套的解决方案,但是不知道为啥却不提供。

另外,如果只是用JavaScript代码的话,同样可以使用JavaSript实现以上的代码实现,然后使用JavaScript代码注册编写的Helper,直接在JavaScript中实现XSS的全套解决方案。

举报

相关推荐

0 条评论