前几天看到浙江电信网上营业厅在搞签到得米粒的活动,每天可签到一次,每次获得一个米粒,首次签到可以获得21个米粒。
我玩了几天,发现了它的一个BUG。我们先看看页面,地址是http://zj.ct10000.com/qiandao
点击后就变灰了,当天就不能再次点了,如下图所示:
先来看看页面代码吧,用开发人员工具很容易就找到下面这个JS方法
注意红框的代码,它是根据前台传过去的参数来判断是否首次登陆。那么如果我们每次都传“登陆首次积分”这个字符串过去呢?
测试一下,先要登陆网上营业厅,然后在签到页面执行如下JS代码
$j.post('/zjpr/score/qiandao/checkin.html', {'type': 'WT_SIGNIN', 'name': encodeURI('登录首次积分')}, function(data){ alert(data); });
接着查询一下米粒数量看看:
果然是多了21个,说明它后台没做验证。这时如果再次执行就没效果了,因为后台做了同一天只能签到一次的验证。
那么如果在还没签到的时候,同时执行多次上面的JS代码,会怎么样呢?试验一下,执行如下代码:
for(var i=0;i<10;i++){ $j.post('/zjpr/score/qiandao/checkin.html', {'type': 'WT_SIGNIN', 'name': encodeURI('登录首次积分')}, function(data){ }); }
同时提交10个请求,看看后台是如何处理并发的。查询一下
存在了多条记录,米粒数从165涨到了249。说明后台没对代码加锁(C#中的lock,JAVA中的synchronized),导致存在并发问题。
结论:首先还是那句话,前台验证看需要,后台验证不可少;其次是建议对有特殊限制的操作的相应代码加锁,可以对session中的对
象加锁,这样既限制了同一用户的并发操作,又不影响其它用户。
续:刚才又找到一个漏洞,可以直接无限刷米粒。原理是这样,在签到页面有分享链接,可以分享到人人、开心等网站,分享一个
获得一个米粒。但是后台没有对分享的名称做过滤,于是我传了一个随机数过去,也分享成功,获得了一个米粒。JS代码如下:
$j.post(basePath+'zjpr/score/qiandao/checkin.html', {"type": "WT_SHARE", "channel": Math.random(), "name": encodeURI("分享渠道积分")}, function(data) { });
然后写个循环,你们懂得。我现在已经有1500多个米粒了
我已经把BUG报给在线客服了,能不能快速处理掉就看电信的办事效率了。