《实战开发》一个基于时间戳的控制失效二维码的漏洞

项目需求:第三方生成一个带13位时间戳参数的二维码,扫码后进入我的网站,我根据二维码中时间戳(二维码生成时间),和当前时间戳进行比较,如果详相减后大于某个值(10分钟、1天这种变量),则系统会提示二维码失效,否则,将会正常访问。

初步设计方案

获取二维码中的13位时间戳,用当前时间戳减去二维码中生成的时间戳(单位是毫秒),如果大于失效时间,则认位二维码失效,那么会返回一个错误页面。代码如下:

public class QrTest {

	public static void main(String[] args) {
		// 获得二维码的生成时间戳
		String	qct =1566447946620;

		String failTime = "1" ; // 这里默认失效为1秒
		// 二维码失效控制(单位:秒)
		long currentTime = System.currentTimeMillis();
		Long crTime = Long.parseLong(qct);
		
		// 如果失效,则返回错误信息
		if( (currentTime - crTime ) / 1000 >  Long.parseLong(failTime)) {
			System.out.println("失效");
		}else {
			System.out.println("有效");
		}
		System.out.println("当前时间戳:" + currentTime);
		System.out.println("二维码生成时间戳:" + crTime);
		System.out.println("失效时间:" + failTime);
		System.out.println("当前时间减去创建时间:" + (currentTime - crTime) );
		System.out.println("当前时间减去创建时间(单位秒):" + (currentTime - crTime ) / 1000);
		System.out.println("是否失效:" + ((currentTime - crTime ) / 1000 >  Long.parseLong(failTime)) );
	}
}

这样看起来是没有问题的,程序也可以正常处理。但是在做测试的时候,发现如果用一个未来的时间戳,或者用年月日时分秒这种格式的字符串,就可以失效绕过。代码如下:

		// 获得二维码的生成时间戳
		//String	qct = "1566447946620";
		String	qct = "1766556549896";//未来时间
	//	String	qct = "2019082113211";//2.2019082113211
	//	String	qct = "20190821132113";//3.20190821132113
		
		// 查询该银行的失效时间
		String failTime = "1" ; // 默认失效为1秒
		// 二维码失效控制(单位:秒)
		long currentTime = System.currentTimeMillis();
		Long crTime = Long.parseLong(qct);
		
		// 如果失效,则返回错误信息
		if( (currentTime - crTime ) / 1000 >  Long.parseLong(failTime)) {
			System.out.println("失效");
		}else {
			System.out.println("有效");
		}
		System.out.println("当前时间戳:" + currentTime);
		System.out.println("二维码生成时间戳:" + crTime);
		System.out.println("失效时间:" + failTime);
		System.out.println("当前时间减去创建时间:" + (currentTime - crTime) );
		System.out.println("当前时间减去创建时间(单位秒):" + (currentTime - crTime ) / 1000);

运行结果:
在这里插入图片描述

发现,上面三种情况均可以实现绕过失效的控制,随后发现,问题在于"当前时间减去创建时间:" (currentTime - crTime),上面三种情况下,相减结果必然是负数,那么根据这个思路进行优化。代码如下:


	//非法时间戳: 都会、造成currentTime - crTime为负数,这样和当前时间戳比较后均可以绕过,实现绕过
	//1.未来时间的时间戳
	//2.时间格式的日期:2019082113211
	//3..时间格式的日期:20190821132113
	public static void main(String[] args) {
		// 获得二维码的生成时间戳
		//String	qct = "1566447946620";
		String	qct = "1766556549896";//未来时间
	//	String	qct = "2019082113211";//2.2019082113211
	//	String	qct = "20190821132113";//3.20190821132113
		
		// 查询该银行的失效时间
		String failTime = "1" ; // 默认失效为1秒
		// 二维码失效控制(单位:秒)
		long currentTime = System.currentTimeMillis();
		Long crTime = Long.parseLong(qct);
		
		// 如果失效,则返回错误信息
		if( (currentTime - crTime ) / 1000 >  Long.parseLong(failTime)) {
			System.out.println("失效");
		}else {
			System.out.println("有效");
		}
		System.out.println("当前时间戳:" + currentTime);
		System.out.println("二维码生成时间戳:" + crTime);
		System.out.println("失效时间:" + failTime);
		System.out.println("当前时间减去创建时间:" + (currentTime - crTime) );
		System.out.println("当前时间减去创建时间(单位秒):" + (currentTime - crTime ) / 1000);
		System.out.println("是否失效:" + ((currentTime - crTime ) / 1000 >  Long.parseLong(failTime)) );
		
		//优化方案:"当前时间减去创建时间:" + (currentTime - crTime)  为负数,则存在绕过嫌疑,将直接判定为失效
		// 如果失效,则返回错误信息
		// 如果失效,则返回错误信息
		if( (currentTime - crTime ) / 1000 < 0) {
			System.out.println("优化后失效");
		} else 	if( (currentTime - crTime ) / 1000 >  Long.parseLong(failTime) ) {
			System.out.println("失效");
		} else {
			System.out.println("有效");
		}
		
	}

在这里插入图片描述

欢迎关注本人个人公众号,交流更多技术信息

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tomatocc

赏杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值