文章源自【字节脉搏社区】-字节脉搏实验室
作者-Beginners
0x01 浅谈Url跳转漏洞
第一步,Url跳转漏洞是怎么产生的:
由于越来越多的需要和其他第三方应用交互,以及在自身应用内部根据不同的逻辑将用户引向到不同的页面,譬如一个典型的登录接口就经常需要在认证成功之后将用户引导到登录之前的页面,整个过程中如果实现不好就可能导致一些安全问题,该漏洞像XSS一样有多种绕过方式,防御过程中也常出现意想不到的情况,特定条件下可能引起严重的安全漏洞。
0x02 Url跳转漏洞的危害:
1.常被用黑产利用进行钓鱼、诈骗等目的。
2.突破常见的基于“白名单方式”的一些安全限制。
3.通过跳转收集数据之后再进一步挖掘更深层的漏洞。
0x03 Url跳转漏洞常见出现点:
1.用户登录、统一身份认证处,认证完后会跳转。
2.用户分享、收藏内容过后,会跳转。
3.跨站点认证、授权后,会跳转。
4.站内点击其它网址链接时,会跳转。
0x04 Url跳转漏洞常见的参数名:
代码语言:javascript
复制
代码语言:javascript复制url=
login=
redirect_to=
qurl=
logout=
data=
ext=
clickurl=
jump_to=
next=
to=
goto=
callback_url=
jump=
jump_url=
return=
click?u=
originUrl=
Redirect=
sp_url=
service=
redirect_url=
redirect=
rit_url=
forward_url=
callback=
forward=
success=
recurl=
j?url=
uri=
u=
allinurl=
q=
link=
src=
tc?src=
linkAddress=
location=
go=
pic=
burl=
request=
backurl=
RedirectUrl=
ReturnUrl=
origin=
Url=
desturl=
page=
u1=
action=
action_url=
target=
linkto=
domain=
dest=
0x05 Url跳转漏洞绕过:
1.利用问号绕过限制:
http://www.aaa.com/?url=http://www.baidu.com?http://login.aaa.com
2.利用@符号绕过限制:
http://www.aaa.com/?url=http://login.aaa.com@www.baidu.com
3.利用#符号绕过限制:
http://www.aaa.com/?url=http://www.baidu.com#login.aaa.com
4.利用/绕过限制:
http://www.aaa.com/?url=http://www.baidu.com/login.aaa.com
5.利用绕过限制:
http://www.aaa.com/?url=http://www.baidu.comlogin.aaa.com
(不允许超链 自行复制)
6.利用\绕过限制
http://www.aaa.com/?url=http://www.baidu.com\login.aaa.com
不允许超链 自行复制)
7.利用.绕过限制:
http://www.aaa.com/?url=http://www.baidu.com.login.aaa.com
不允许超链 自行复制)
8.利用缺失协议绕过限制:
http://www.aaa.com/?url=/www.baidu.com
http://www.aaa.com/?url=//www.baidu.com
9.利用”.”绕过限制:
http://www.aaa.com/?url=.www.baidu.com
10.利用跳转文件绕过
http://axomlfz.cn:81/tz.html
0x06 修复方式
1.我们需要对传入的URL做有效性的验证,保证该URL来自于正确的地方,限制的方式同防止csrf一样可以包括。
2.如果确定传递url参数进入的来源,我们可以通过该方式来实现安全限制,保证该url的有效性,避免恶意用户自己生成跳转链接。
防止url篡改
Web项目聚集地
图文教程,技术交流
如图,是我们模拟的一个从浏览器发送给服务器端的转账请求。久一的ID是 web_resource,正在操作100元的转账。
再如图,因为是通过浏览器 `url` 访问服务,这个时候金额被篡改成了 200,那么服务器接受到了200,直接扣除了200怎么解决?这就是本文要讲解的内容。
防止url被篡改的方式有很多种,本文就讲述最简单的一种,通过 secret 加密验证。
道理很简单,服务器接收到了 price 和 id,如果有办法校验一下他们是否被修改过不就就可以了吗?
那么我们传递的时候增加一个参数,叫做sign,sign是使用用户不可见的一个secret和price、id组合加密获得,然后传递给服务器端。当服务器端接收到请求的时候,获取到price、id,通过同样的secret加密和sign比较如果相同就通过校验,不同则被篡改过。
那么问题来了,如果参数特别多怎么办?
所以通用的做法是,把所有需要防止篡改的参数按照字母正序排序,然后顺序拼接到一起,再和secret组合加密得到 sign。具体的做法可以参照如下。
代码语言:javascript
复制
代码语言:javascript复制 public static String generateSign(Map<String, String> parameters) {
try {
List<String> names = new ArrayList<>();
parameters.forEach((k, v) -> {
if (v != null && !Objects.equals(v, "")
&& !Objects.equals(k, "sign")) {
names.add(k);
}
});
List sortedNames = names.stream().sorted()
.collect(Collectors.toList());
StringBuffer sb = new StringBuffer();
sortedNames.forEach(n ->
sb.append(String.format("%s=%s", n, parameters.get(n))));
String sign = md5(sb.toString());
return sign;
} catch (Exception e) {
return "";
}
}
private static String md5(String inputString)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(inputString.getBytes("UTF-8"));
byte[] digest = md.digest();
return convertByteToHex(digest);
}
private static String convertByteToHex(byte[] byteData) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteData.length; i ) {
sb.append(Integer.toString((byteData[i] & 0xff) 0x100, 16)
.substring(1));
}
return sb.toString();
}
generateSign 就是所有需要加密的参数,包括secret
有的同学担心,那么他万一猜到了我的加密算法怎么办,这个不用担心,你的secret是保持在服务器端的,不会暴漏出去的,所以他知道了算法也不会知道具体加密的内容。
那么问题又来了,如果小明通过抓包工具获取到了URL,他是不是可以无限制的访问这个地址呢?那就出现了“久一”的钱被一百一百的转空了。
那可怎么办?这里涉及到了另一个话题,接口的幂等,我们后面会详细讲解怎么通过幂等控制重复扣款。这里我们要讲解的是怎么控制 URL 失效。
这里又有一个通用的做法,就是再添加一个参数 timestamp。对的,就是当前的时间戳。服务器获取到 timestamp 以后检验一下是否在5分钟以内,如果不是直接返回请求失效就可以了?那么如果timestamp 被篡改了呢?不会的,因为我们按照上面的做法同样对 timestamp 做了加密防止篡改。
最简单的校验接口被篡改的方式,你学会了吗?