漏洞描述

攻击点比较多。这里以activate.php文件的 token参数为例。

首先以任意邮件地址注册freeshell,然后开始猜验证地址的token:

循环第一位:

  • 第01次尝试:a0000000000000000000000000
  • 第26次尝试:z0000000000000000000000000
  • 第27次尝试:A0000000000000000000000000
  • 第52次尝试:Z0000000000000000000000000
  • 第53次尝试:00000000000000000000000000
  • 第62次尝试:90000000000000000000000000
  • 第63次尝试:a0000000000000000000000000

如此循环,记下每次尝试的时间。会发现某个字符的时间比较长,固定这一位,继续猜第二位,直到猜完30位。猜完freeshell也就注册好了。

漏洞原理

请看比较代码

<pre style="color: #000000;">```
if ($info['token'] !== $_GET['token'])


我没见过底层是怎么实现的,但可以想象,如果第一位正确,就会比较第二位;如果第一位不正确,那么就直接判断为不相等。

虽然这之间的时间差比较小,但统计学告诉我们,所有微小的差距,在大数据量统计中都会被放大。

### 测试

我获得的地址是:[https://freeshell.ustc.edu.cn/activate.php?appid=1450&amp;token=COf4aFFJsEO73f8P1bjkW7zmFbl7vthX5mS5SlE8](https://freeshell.ustc.edu.cn/activate.php?appid=1450&token=COf4aFFJsEO73f8P1bjkW7zmFbl7vthX5mS5SlE8)

第一位是“C”,测试结果见图(矢量图请见 <http://z.gaoyifan.com/side-channel-freeshell/>)

[![freeshell-side-channel](https://servers.blog.ustc.edu.cn/wp-content/uploads/2014/05/freeshell-side-channel.png)](https://servers.blog.ustc.edu.cn/wp-content/uploads/2014/05/freeshell-side-channel.png)

可以从图中明显看出,编号28的那位(也就是“C”),花费时间比较久。(注:数据已经经过一次清洗,去除了一些噪点)

在服务器负载比较小的时候,猜测一位大约需要3~5分钟,这也就意味着30位的token一个半小时就破解了

### 修复

修改为:

```
if(hash_hmac("sha256",$info['token'],$appid) !== hash_hmac("sha256",$_GET['token'],$appid))
```
```

这样经过一次hash后,比较的串变成随机的,时间差就被随机化了。

感谢boj深夜修复bug:<https://gitlab.lug.ustc.edu.cn/boj/freeshell/commit/74ea87e829ffaacc65b5f4fb1099fc2146cbef98>