aiohttp路径遍历漏洞(CVE-2024-23334)漏洞复现
2024-03-02 03:10:54

很久没学习了~

看到这个:

https://gist.github.com/W01fh4cker/2b570b1d0df40aa94808184c231d7ecb

复现起来没什么难度:

image-20240302031300974

代码位置:

1
aiohttp.web_urldispatcher.StaticResource._handle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
async def _handle(self, request: Request) -> StreamResponse:
rel_url = request.match_info["filename"]
try:
filename = Path(rel_url)
if filename.anchor:
raise HTTPForbidden()
filepath = self._directory.joinpath(filename).resolve()
# 如果没有开启 _follow_symlinks,就进入 relative_to 函数
if not self._follow_symlinks:
filepath.relative_to(self._directory)
except (ValueError, FileNotFoundError) as error:
# relatively safe
raise HTTPNotFound() from error
except HTTPForbidden:
raise
except Exception as error:
request.app.logger.exception(error)
raise HTTPNotFound() from error
if filepath.is_dir():
if self._show_index:
try:
return Response(
text=self._directory_as_html(filepath), content_type="text/html"
)
except PermissionError:
raise HTTPForbidden()
else:
raise HTTPForbidden()
elif filepath.is_file():
# 如果文件存在,就进入这里直接返回文件内容,内部没有做过滤
return FileResponse(filepath, chunk_size=self._chunk_size)
else:
raise HTTPNotFound

为什么一定要开启 follow_symlinks 呢,因为如果不开启的话会进入 relative_to 函数。这个函数会做一些判断最后抛出一个异常:

image-20240302032905913

从文字上就能看出,传递的路径必须是设定路径的子目录,例如设定路是 /tmp/static/,那么要读的文件前缀就必须是 /tmp/static/,否则就抛出异常了。

在上面的代码中还可以看到 _show_index 这个属性,如果同时开启了 follow_symlinks 是否可以读目录呢?答案是不行的,因为进入到这里函数以后:

1
aiohttp.web_urldispatcher.StaticResource._directory_as_html

image-20240302033303699

这里也做了一遍 relative_to,然后抛出异常了。

最后就是修复了的代码了:

https://github.com/aio-libs/aiohttp/commit/9118a5831e8a65b8c839eb7e4ac983e040ff41df#diff-9632858c8fdd45d817126b2735f763b9a2e24fb2800122eb2cb0c9a3b89c85c1

image-20240302033615680

看着也很简单,就是即使没有开启 _follow_symlinks 也做一次 relative_to,里面就会自己报错了。

Prev
2024-03-02 03:10:54
Next