我想了想还是单独贴出来让更多的人看到,大家一起看一下可行性以及是否存在问题。
体验可以到这里 http://blog.eqoe.cn/ 在右边进行搜索
我们可以看到点击搜索的时候客户端发送了 3 次请求。
var tk = "获得的TOKEN内容";
var str = 10000;
var lasthash = "";
while(lasthash.indexOf("0000") != 0){ //如果 lasthash 前4位不是0则持续循环
str++;
lasthash = sha1(tk+str.toString()); //把 Token 和 数字拼接起来
}; //经过多次测试 PC端计算大约需要1-3秒 移动端需要2-5秒
如果需要的话你可以对我的 blog 进行压力测试,别打太狠就行。。。
假设使用 C 语言制作客户端计算一个 Hash 需要 2 秒,攻击者使用 16 核电脑和若干代理IP,那么你的服务器每秒只会收到 8 个以下的请求,这种算法应对一般的攻击应该可以无压力的防住吧?
1
ihacku 2014-12-24 07:01:07 +08:00
|
2
typcn OP @ihacku 思路都一样吧,具体实现稍有不同。在计算的时候浏览器会假死,用户打字会超难受,而且没法根据输入内容动态生成key。
这个明显有问题,在计算出key之后,使用相同的时间和key可以提交很多次,经过超时时间后再之重新计算,要是针对的话基本跟没有一样。 |
3
zeraba 2014-12-24 07:52:11 +08:00
貌似还有通过解析器进行判断的 nginx+ lua
|
4
RIcter 2014-12-24 08:02:10 +08:00 via iPad
这种算法是不是需要在后端计算出lasthash?
如果我大量POST前四位为0但是后面随机的hash,后端会不会因为大量的计算而卡死? |
5
RIcter 2014-12-24 08:04:57 +08:00 via iPad
又看了一遍…后端没验证hash是否正确,只验证了前四位是不是0?
这样不还是可以bypass么… |
6
typcn OP @RIcter 先校验 TOKEN 是否符合,才计算 lasthash 的,一个 IP 地址同一时间只能拥有一个 TOKEN,在发放 TOKEN 的程序做一些限制就好了。
另外做 hash 运算不算什么吧? PHP 的 SESSION 也需要计算 hash 啊。 |
9
wy315700 2014-12-24 08:09:37 +08:00 via Android
hash前四位是0 不就是挖坑的思路吗
|
10
typcn OP @RIcter 如果严格一点的话, POST 的时候不需要上传 token,后端自动根据用户的 IP 地址到数据库/内存缓存中取 token,然后拼接 token 和 用户计算出的数字,验证 lasthash 。 如果验证成功删除这个 IP 地址对应的 token 。
|
11
a2z 2014-12-24 08:18:31 +08:00
@RIcter
计算完POST过去的时候内容是: TK:4ceda3e028287b9b6d1e1a2ba904e4b4d75761af ua:20389 两个拼起来hash的确是00008e2609258df65582eea4e51c91259f3b780d 但是这个hash并没有发送到服务器。 服务器只需要把TK和ua拼起来计算下sha1是否前四位是0000就行了,也就是说客户端要计算几万次sha1,服务器只用计算1次。 有种挖比特币的感觉。 |
15
typcn OP @a2z 这个倒是。
我开启 IP 验证是因为怕碰到代理狂魔。vps 上开着 Minecraft 服务器,各种数据库,剩的资源很少,太容易被打挂,每个月已经 700 多了,0 收入,实在不想加钱了。 |
17
rrfeng 2014-12-24 08:38:39 +08:00
我感觉到一种很容易针对这种策略的攻击的可能性
比普通的 CC 可能还要高效…… |
18
kslr 2014-12-24 08:40:36 +08:00
就是个令牌桶算法++
|
21
procen424 2014-12-24 08:53:44 +08:00 via Android
楼主找个强一点的工作量证明算法吧
SHA1用显卡或FPGA跑 会把CPU虐哭的 而且都是现成的代码 |
22
icedx 2014-12-24 09:37:05 +08:00
博客是WP?
|
23
lijun20020229 2014-12-24 09:51:38 +08:00
比特币的工作量证明据说早就有了,1996年Adam Back开发的“Hashcash"用来反垃圾邮件。
|
25
binux 2014-12-24 09:57:46 +08:00
我直接压 sha1 就完了,按照几万次 sha1 就需要1秒计算,只要我每秒请求超过几万次,你就挂了。
|
26
typcn OP @binux 防火墙吃干饭啊。。。你1秒还没请求10次就被封IP了,而且在服务端也可以加验证,验证失败X次进行拦截,X个同段IP失败拦截IP段。
|
29
typcn OP @binux 真要有超多IP,打静态文件也打挂了,别说仅仅是 SHA1。 还有,执行一次 sha1 比执行一次搜索耗费的资源小了无数倍
|
30
geew 2014-12-24 10:46:54 +08:00
就用户体验来说 我觉得这种方法不好 用更简单的频率限制不挺好的么 过高的频率直接打入黑名单 限制一定的时间再开放
|
33
nilai 2014-12-24 10:58:17 +08:00
@typcn 有一个问题想问你, 你一个长40 位的字符串 再后面拼接了一个 1--10000的随机数 再进行sha1加密, 生成的这1万个hash中。 一定会有一个hash的前4位为0么?
|
34
typcn OP @binux 静态资源也会发生散列哈希运算,磁盘读取之后,计算服务器上文件的 ETag ,将 header 等信息发送给用户。
大部分静态资源服务器有这个。 |
36
hellogbk 2014-12-24 11:00:02 +08:00
感觉客户端会卡死呢。
|
38
typcn OP |
39
binux 2014-12-24 11:19:40 +08:00
其实这个是有效的,攻击找的是系统中最消耗资源的请求。
而将搜索用 sha1 验证,降低了搜索的请求消耗。 其实也不一定要用 sha1 ,关键是拉大客户端和服务器端的计算压力差,比如这里是 0xffff : 1。换成 md5 也是一样的,服务器还算得快一点。 |
43
lecher 2014-12-24 12:35:45 +08:00
这个仅仅就是防单机单ip发起的cc。
但是就像binux大神说的,单机多ip代理无限构造0000+随即字符串,根本不用算正确的请求,就可以打死了。 和打有验证码的一个道理,不用突破到数据库处理层面,直接多ip代理打服务器,服务器光是计算hash和缓存hash的结果就要算到死了。 也不一定是打搜索页面,比如打注册账号验证用户名是否有效和邮箱是否有效的请求,这个一般网站为了一致性,缓存找不到的一定回去数据库查的,而校验用户名有效性这个请求,一般都没有做校验就直接打到数据库了。多ip代理打过去,服务器的压力要比单机的压力大一些。 |
44
millken 2014-12-24 12:51:41 +08:00
方法很新颖,我去尝试下。
真正的防御应该是应用层验证(js,flash,captcha),提交验证未通过的ip到防火墙。 |
45
lqs 2014-12-24 14:02:54 +08:00
把while循环改成for一个固定次数加setTimeout 1ms,就不会让浏览器卡住了
|
47
zhicheng 2014-12-24 23:25:22 +08:00
hashcash 必然是有效的,要不然 bitcoin 早就被攻击死了。
LS们讨论的大量IP+0000随机数的不太现实。。。 sha1 大部分语言 100K/s hash 轻轻松松的。但你不太可能有那么多 IP 地址。或者说,如果真有这么大的资源,也无所谓攻击这个地址了,静态页面都能打死了,光流量服务器都撑不住。完全不在一个讨论层次上。 小规模的单服务器网站,直接在存 session 在页面渲染出挑战值就可以。 大规模的多服务器网站,可以用 hmac(ip + timestamp) 做挑战值,验证写到 nginx 里,性能损失可以忽略。 |
48
kocd 2014-12-26 16:04:22 +08:00
我事先得知一个前4位是0的一条tk_after,返回给你tk和tk-tk_after。。。
是不是能不停的攻击你。。。 |
50
kocd 2014-12-27 07:05:08 +08:00
@typcn 你的服务器端好像只判断(tk+一个数字的hash)前4位是0,我每次请求你都给我一个tk,我只要返回tk和我已知的随便一个tk_after的tk_after-tk对吧,没做过网站,单纯从逻辑考虑的。
|