前幾天看到浙江電信網上營業廳在搞簽到得米粒的活動,每天可簽到一次,每次獲得一個米粒,首次簽到可以獲得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報給線上客服了,能不能快速處理掉就看電信的辦事效率了。