- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的一个 REST API 需要一个属性“url”,它需要一个 URL 作为用户输入。我正在使用 ESAPI 来防止 XSS 攻击。问题是用户提供的 URL 类似于
http://example.com/alpha?abc=def&phil=key%3dbdj
来自 ESAPI 编码器的 cannonicalize 方法在这里抛出入侵异常,声称输入具有混合编码,因为它是 url 编码的,并且片段 '&phi' 被视为 HTML 编码,因此是异常。
我在清理我的一个应用程序 URL 时遇到了类似的问题,其中第二个查询参数以“pa”或“pi”开头,并通过 HTML 解码转换为 delta 或 pi 字符。请引用我的previous Stackoverflow question here
现在的问题是,由于整个 URL 都是来自用户的输入,我不能简单地解析出查询参数并单独清理它们,因为恶意输入可以结合两个查询参数创建并单独清理它们不会在那种情况下工作。
示例:<scr 是第一个查询参数值和 ipt>alert(0) 的最后一部分;或者作为下一个查询参数控制上下文的第一部分出现的东西。
有人遇到过类似的问题吗?我真的很想知道你们实现了哪些解决方案。感谢您的指点。
编辑:'avgvstvs' 的以下回答不会抛出入侵异常(谢谢!!)。但是,cannonicalize 方法现在会更改原始输入字符串。 ESAPI 将查询参数的 &phi 视为一些 html 编码的字符并将其替换为 '?'字符。类似于我之前的问题,链接在这里。不同之处在于,这是我的应用程序的 URL,而这是用户输入。我唯一的选择是在这里维护白名单吗?
最佳答案
您在这里面临的问题是,对 URL 的不同部分进行编码有不同的规则——根据内存,URL 中有 4 个部分具有不同的编码规则。首先,了解为什么在 Java 中,您需要使用 UriBuilder
构建 URL类(class)。网址 specification将帮助解决细节问题。
Now since the problem is that since the entire URL is coming as inputfrom the user, I cannot simply parse out the Query parameters andsanitize them individually, since malicious input can be createdcombining the two query parameters and sanitizing them individuallywont work in that case.
这里唯一真实的选项是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 reference如果您需要对 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<org.apache.http.NameValuePair> params = URLEncodedUtils.parse(dirtyURI, "UTF-8");
Iterator<org.apache.http.NameValuePair> 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 类型...URL 的部分比方案/授权/路径/查询更多。 (缺少的是 userInfo 或 port 的可能性,如果您需要这些,请相应地修改此代码。)
关于java - 针对用户提供的 url 属性的 ESAPI XSS 预防,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23434156/
在为 Web 应用程序用例图建模时,为用户可以拥有的每个角色创建一个角色是否更好?或拥有一个角色、用户和一个具有特权的矩阵? guest < 用户 < 版主 < 管理员 1: guest 、用户、版主
我无法使用 Elixir 连接到 Postgres: ** (Mix) The database for PhoenixChat.Repo couldn't be created: FATAL 28P
这个问题已经有答案了: Group by field name in Java (7 个回答) 已关闭 7 年前。 我必须编写一个需要 List 的方法并返回 Map> . User包含 Person
感谢您的帮助,首先我将显示代码: $dotaz = "Select * from customers JOIN contracts where customers.user_id ='".$_SESS
我只想向所有用户中的一个用户显示一个按钮。我尝试了 orderByKey() 但没有成功! 用户模型有 id 成员,我尝试使用 orderByChild("id") 但结果相同! 我什至尝试了以下技巧
我们在工作中从 MongoDB 切换到 Postgres,我正在建立一个 BDR 组。 在这一步,我正在考虑安全性并尽可能锁定。因此,我希望设置一个 replication 用户(角色)并让 BDR
export class UserListComponent implements OnInit{ users; constructor(private userService: UserS
我可以使用 Sonata User Bundle 将 FOS 包集成到 sonata Admin 包中。我的登录功能正常。现在我想添加 FOSUserBundle 中的更改密码等功能到 sonata
在 LinkedIn 中创建新应用程序时,我得到 4 个单独的代码: API key 秘钥 OAuth 用户 token OAuth 用户密码 我在 OAuth 流程中使用前两个。 的目的是什么?最后
所以..我几乎解决了所有问题。但现在我要处理另一个问题。我使用了这个连接字符串: SqlConnection con = new SqlConnection(@"Data Source=.\SQLEX
我有一组“用户”和一组“订单”。我想列出每个 user_id 的所有 order_id。 var users = { 0: { user_id: 111, us
我已经为我的Django应用创建了一个用户模型 class User(Model): """ The Authentication model. This contains the u
我被这个问题困住了,找不到解决方案。寻找一些方向。我正在用 laravel 开发一个新的项目,目前正致力于用户认证。我正在使用 Laravels 5.8 身份验证模块。 对密码恢复 View 做了一些
安装后我正在使用ansible配置几台计算机。 为此,我在机器上本地运行 ansible。安装中的“主要”用户通常具有不同的名称。我想将该用户用于诸如 become_user 之类的变量. “主要”用
我正在尝试制作一个运行 syncdb 的批处理文件来创建一个数据库文件,然后使用用户名“admin”和密码“admin”创建一个 super 用户。 到目前为止我的代码: python manage.
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 6 年前。 Improv
我已在 Azure 数据库服务器上设置异地复制。 服务器上运行的数据库之一具有我通过 SSMS 创建的登录名和用户: https://learn.microsoft.com/en-us/azure/s
我有一个 ionic 2 应用程序,正在使用 native FB Login 来检索名称/图片并将其保存到 NativeStorage。流程是我打开WelcomePage、登录并保存数据。从那里,na
这是我的用户身份验证方法: def user_login(request): if request.method == 'POST': username = request.P
我试图获取来自特定用户的所有推文,但是当我迭代在模板中抛出推文时,我得到“User”对象不可迭代 观看次数 tweets = User.objects.get(username__iexact='us
我是一名优秀的程序员,十分优秀!