博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
年会抽奖程序的一些总结
阅读量:4599 次
发布时间:2019-06-09

本文共 2674 字,大约阅读时间需要 8 分钟。

起源

2019年年会的到来,当然免不了激动人心的抽奖环节啦,那直接延用上一年的抽奖程序吧,然而Boss希望今年的抽奖程序能够能让所有人都参与进来,一起来抢有限奖品,先到先得,而不是站在那里盯着屏幕。

OK,程序内容大概是这样子,每个人在手机浏览器打开抽奖程序界面,系统会随机给个数字,谁戳屏幕上的圆形最快最准,就能参与抽奖活动,有多少奖品就有多少场battle(仅限手机浏览器打开 & 每人仅限获得一个奖品

900334-20190127155357423-1761473457.jpg

重要的是,年会之前得把程序公布出来,让其他同事想办法作弊,硬件作弊软件作弊都允许,我们主要分析软件作弊并制定对应防御策略,就像是一场CTF,对方是攻击,我们是防御。

本文有引用他人文章,若有侵权或其它不当,会立即删除。

开发过程

我跟另一个同事完成这个项目,他负责后端,我负责前端,整体采用React+Nodejs+Express+MySQL的架构,这个项目有实时的需求,因此我们用到了

首先,我们分析了对方作弊的可能:

  1. 通过抓包分析,成功伪造点击请求
  2. 找到圆形位置,实现高准确率的点击
  3. 搞垮其他竞赛者的账号,自己稳步前进
  4. 直接搞掉服务器,修改数据库

对于作弊3,账号列表是年会抽奖前10分钟公布的,所以作弊者没有充足的准备时间。

对于作弊4,都是自己人,应该不会那么狠吧...

那么,我们主要针对作弊1作弊2做了以下防御:

后端防御

  • 校验请求参数是否有效
  • 分析正确点击频率,超过正常点击阀值则作惩罚处理
  • 点击错误次数过多则作惩罚处理

前端防御

  • 使用混淆打包js代码,加大代码分析难度
  • react-konva画圆形,防止对手轻易获取DOM节点并执行点击事件
  • 圆形的颜色和位置随机,防按键精灵之类的软件
  • 核心websocket请求采用
  • 普通请求采用rsa+aes混合加解密

经过了一个星期的开发和防御策略研究,我们把程序弄出来了,等待年会的到来。

900334-20190127160444603-1649193011.gif
900334-20190127160433727-2083057780.jpg

抽奖过程

年会抽奖那天,在大屏幕上面可以看到每个人的点击数,注意到有个同事的按击次数值飚得极快,很明显他作弊成功了,但我想不明白是怎么做到的。于是年会结束后我向他请教,才得知作弊手法。

结果分析

作弊手法如下,非常简单,在手机浏览器的地址栏输入下面一段代码,回车即可执行。跟我一样不知道浏览器地址栏可以执行js代码的童鞋,请看这篇文章

javascript:Math.random=function(){return 1;}

由于我在圆形随机位置和随机颜色的设置上用到了Math.random这个方法,此时,他的按击圆形就定死在同一个位置,众人皆动我独静,而且都是正常点击请求,必须赢呀!

// 修改前function getRandomNumber(min, max) {    const range = max - min;    const random = Math.random();    const num = min + range * random;    return num;}

代码修补

找到问题所在,很明显我需要找个随机函数方法替换Math.random,于是我google了几篇文章,都提到线性同余生成器(LCG, Linear Congruential Generator),貌似所有运行库都是采用这种算法生成伪随机数,我就把getRandomNumber函数改成下面的模样,问题得到了暂时的解决。

// 修改后const getRandomNumber = (function() {    let seed = Date.now();    function random() {        //线性同余生成器(LCG, Linear Congruential Generator)        seed = (seed * 9301 + 49297) % 233280;        return seed / (233280.0);    };    return function rand(min,max) {        const range = max - min;        const random_num = random();        const num = min + range * random_num;        return num;    };})();

经验分享

但是,getRandomNumber的代码功能还是非常容易改,毕竟混淆过的js依旧是裸奔着的,这一点是避免不了的。

比如说,我们都知道知乎可以设置文章的权限,例如禁止转载之类的,有一次我看到这篇知乎文章,想复制代码下来运行下却被告知禁止转载,打开chrome控制台查看代码块内容,可惜代码内容变成富文本内容形式,于是我另寻法子,直接在js上面修改。
900334-20190127160656093-194777478.jpg

首先,定位到复制功能触发的文件和代码段。

900334-20190127160803250-636437681.jpg

第二步,在控制台Sources->Overrides下,打勾Enable Local Overrides

900334-20190127160914582-375959069.jpg

第三步,在控制台下面Sources->Page下,找到刚刚定位到的代码文件,右键Save for overrides

900334-20190127161001376-1729693718.jpg

第四步,直接把handleCopy的处理逻辑注释掉,在控制台的Overrides下直接修改,或者在选定保存的本地文件夹中修改。

900334-20190127161128540-227966093.jpg
900334-20190127161138186-284497366.jpg
最后,保存修改后的代码,刷新页面,即可复制成功。

var SriPlugin = require('webpack-subresource-integrity');var HtmlWebpackPlugin = require('html-webpack-plugin');var ScriptExtInlineHtmlWebpackPlugin = require('script-ext-inline-html-webpack-plugin');var ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');var path = require('path');var WebpackAssetsManifest = require('webpack-assets-manifest');var writeJson = require('write-json');

Reference

转载于:https://www.cnblogs.com/DTBelieve/p/10323673.html

你可能感兴趣的文章
队列实现霍夫曼树
查看>>
【Java】图片高质量缩放类
查看>>
Python :类中设置默认属性并修改
查看>>
磁盘管理综合测试
查看>>
Unity3d Shader开发(三)Pass(Pass Tags,Name,BindChannels )
查看>>
UMLet
查看>>
从父控件移除控件
查看>>
calc()制作自适应布局
查看>>
Markdown-写作必备
查看>>
关于在Java中 a!=a 值为真的解释(摘抄)
查看>>
C#串口小助手
查看>>
详解定位与定位应用
查看>>
【前端开发】 5分钟创建 Mock Server
查看>>
一个Tomcat配置参数引发的血案
查看>>
java 从键盘录入的三种方法
查看>>
使用jQuery和YQL,以Ajax方式加载外部内容
查看>>
pyspider 示例
查看>>
Ubuntu下Sublime Text 3解决无法输入中文的方法
查看>>
电路板工艺中的NPTH和PTH
查看>>
JNI实现JAVA和C++互相调用
查看>>