用户提供的url属性的ESAPI XSS预防

我的一个REST API期望一个属性“url”,它希望URL作为用户的输入。 我正在使用ESAPI来防止XSS攻击。 问题是用户提供的URL就像

http://example.com/alpha?abc=def&phil=key%3dbdj

来自ESAPI编码器的cannonicalize方法抛出入侵exception,声称输入具有混合编码,因为它是url编码的,并且片段’&phi’被视为HTML编码,因此是exception。

我有一个类似的问题,清理我的一个应用程序URL,其中第二个查询参数以’pa’或’pi’开头,并通过HTML解码转换为delta或pi字符。 请参阅我之前的Stackoverflow问题

现在问题在于,由于整个URL都是来自用户的输入,我不能简单地解析Query参数并单独清理它们,因为可以结合两个查询参数创建恶意输入并单独清理它们不会在那里工作案件。

示例:&ltscr来自第一个查询参数值和ipt&gtalert(0)的最后一部分; 或者某些东西作为下一个查询参数控制上下文的第一部分。

有没有人遇到过类似的问题? 我真的很想知道你们实施了哪些解决方案。 谢谢你的任何指示。

编辑:来自’avgvstvs’的以下答案不会引发入侵exception(谢谢!)。 但是,cannonicalize方法现在更改原始输入字符串。 ESAPI将查询参数的phi视为一些html编码的char并将其替换为’?’ 焦炭。 像我之前在这里链接的问题。 区别在于我的应用程序的URL,而这是用户输入。 我唯一的选择是在这里保留一份白名单吗?

您在这里遇到的问题是,对URL的不同部分进行编码有不同的规则 – 对于内存,URL中有4个具有不同编码规则的部分。 首先,了解为什么在Java中,您需要使用UriBuilder类构建URL。 URL 规范将有助于细节。

现在问题在于,由于整个URL都是来自用户的输入,我不能简单地解析Query参数并单独清理它们,因为可以结合两个查询参数创建恶意输入并单独清理它们不会在那里工作案件。

这里唯一真正的选择是java.net.URI

尝试这个:

 URI dirtyURI = new URI("http://example.com/alpha?abc=def&phil=key%3dbdj"); String cleanURIStr = enc.canonicalize( dirtyURI.getPath() ); 

URI.getPath()的调用应该给你一个非百分比编码的URL,如果enc.canonicalize()在那个阶段之后检测到双重编码,那么你真的有一个双重编码的字符串,并且应该通知调用者你将只接受单编码的URL字符串。 URI.getPath()非常智能,可以为URL字符串的每个部分使用解码规则。

如果它仍然给你一些麻烦,那么API引用还有其他方法可以提取URL的其他部分,如果你需要对URL的不同部分做不同的事情。 例如,如果你需要在GET请求上手动解析参数,你实际上可以让它自己返回查询字符串 – 它将对它进行解码传递。

============= JUNIT测试用例============

 package org.owasp.esapi; import java.net.URI; import java.net.URISyntaxException; import org.junit.Test; public class TestURLValidation { @Test public void test() throws URISyntaxException { Encoder enc = ESAPI.encoder(); String input = "http://example.com/alpha?abc=def&phil=key%3dbdj"; URI dirtyURI = new URI(input); enc.canonicalize(dirtyURI.getQuery()); } } 

=================回答更新的问题=====================

没有办法解决它: Encoder.canonicalize()旨在将转义的字符序列减少为简化的本机到Java格式。 url很可能被视为特殊情况,因此很可能会故意将其排除在考虑之外。 这是我处理你的情况的方式 – 没有白名单,它将保证你受Encoder.canonicalize()保护。

使用上面的代码获取输入的URI表示。

步骤1:规范化除URI.getQuery()之外的所有URI部分步骤2:使用库解析器将查询字符串解析为数据结构。 我会使用来自commons的httpclient-4.3.3.jar和httpcore-4.3.3.jar。 然后你会做这样的事情:

 import java.net.URI; import java.net.URISyntaxException; import java.util.Iterator; import java.util.List; import javax.ws.rs.core.UriBuilder; import org.apache.http.client.utils.URLEncodedUtils; import org.junit.Test; import org.owasp.esapi.ESAPI; import org.owasp.esapi.Encoder; public class TestURLValidation { @Test public void test() throws URISyntaxException { Encoder enc = ESAPI.encoder(); String input = "http://example.com/alpha?abc=def&phil=key%3dbdj"; URI dirtyURI = new URI(input); UriBuilder uriData = UriBuilder.fromUri(enc.canonicalize(dirtyURI.getScheme())); uriData.path(enc.canonicalize(enc.canonicalize(dirtyURI.getAuthority() + dirtyURI.getPath()))); println(uriData.build().toString()); List params = URLEncodedUtils.parse(dirtyURI, "UTF-8"); Iterator it = params.iterator(); while(it.hasNext()) { org.apache.http.NameValuePair nValuePair = it.next(); uriData.queryParam(enc.canonicalize(nValuePair.getName()), enc.canonicalize(nValuePair.getValue())); } String canonicalizedUrl = uriData.build().toString(); println(canonicalizedUrl); } public static void println(String s) { System.out.println(s); } } 

我们在这里真正做的是使用标准库来解析inputURL(从而减轻我们的负担),然后在我们解析每个部分之后规范化部分。

请注意,我列出的代码不适用于所有url类型…网页的部分比方案/权限/路径/查询更多。 (缺少userInfo或端口的可能性,如果需要,请相应地修改此代码。)