CVE-2017-7529 Nginx整数溢出漏洞分析2

2020-08-17 14:50:57 浏览数 (1)

漏洞原理

补丁发布的日期是2017年7月11日15:48:23

所以我们可以到 github上去查找修改的地方

可以看到做了一定的限制

  • 图一修改,防止因为end的问题,导致 content_length-end后的结果为负数,最后的结果无论如何都是0,而不会是负数了,对cache文件的读取也只能从0开始
  • 图二修改,防止溢出后小于了size后绕过判断

正常情况下,如果我们 传入一串完整的range,那么他会检查 start,保证不会溢出为负值

假如我们传入的范围是 1-1000那么这里就是将 -前后的两个数字分出来,分别赋值给 startend这两个函数,同时这里做了判断,不能是字符,同时也不能是负数,所以要动手脚的话,只能在后面运算的地方做

如果我们传入的end的值,是比 content_length,文件内容的值大的,那么相减,start的值就是负数

在这种情况下,因为end的值会设定成centent_length-1,所以在后面的判断里肯定为 ,因为range的范围早就超过了 content_length

代码语言:javascript复制
if (size > content_length) {
    return NGX_DECLINED;
}

正常情况来说,因为 -1的关系,range的长度肯定是小于原始文件的长度的,所以一旦到了这一步,就直接原始文件返回,不进行range处理,为了绕过if判断,就需要将size整数溢出了

-----分割线-----

我们在测试的时候,需要将start的值设置为负数,这样在读取的时候,nginx才会将缓存文件前面的内容读取出来

假设我们的值为 7877,那么为了读取前面的值,就得7877加上600=8477

我们给它第一个值为 -8477,这个值是函数 end的值,在运算的时候,start就等于了文件总长度7877减去end的值8477,最后等于负数-600,而end就等于8476

第一个值计算过后,此时的size值本应该不为8477的(下面为size的计算方法)

代码语言:javascript复制
size  = end - start

但是注意到第 362行的一个判断

因为前面算的end的值是大于文件长度的,所以在这里会被强行等于原始文件的长度,那么到后面计算的时候

就会变成了 7877-(-600)=7877 600=8477

因为需要整数溢出,所以最后size的值得是 0x8000000000000000,所以我们给的第二个range值要在这个基础上计算

那么 0x8000000000000000-8477的值就是range2的值了

这里计算出来的结果是 9223372036854767331‬

第二个值进入的时候,因为size是 =

所以就相当于是 range2 range1,最后的值刚好就能整数溢出了

于是便绕过了这个判断,最后请求的range范围便是-600到文件结束,从而导致信息泄露

代码语言:javascript复制
if (size > content_length) {
    return NGX_DECLINED;
}

0 人点赞