简介

谈到 Python 中的路径拼接,大家会想到什么?

  • os
  • pathlib

以上两个模块都是 Python 内置的模块,可以很方便的帮助我们完成路径的拼接而不需要担心不同系统下的路径格式问题,但却存在一个严重的安全风险:路径穿越

# os.path.join
>>> os.path.join('/home/download', '../../opt/logo.png')
/home/download/../../opt/logo.png

# pathlib
>>> pathlib.Path('/home/download') / '../../opt/logo.png'
/home/download/../../opt/logo.png

倘若你未加校验便写入文件,期望中,文件被写入到 /home/download 目录下,实际却被写入到了 /opt 目录中

file_path = os.path.join('/home/download', '../../opt/logo.png')
with open(file_path, 'w') as f:
	f.write('hello')

利用

假设一个场景:

  • 你想要爬取一个 mm 网站的图片

  • 抓包之后,发现网站竟 “友善“ 地提供一个接口:

  • 不加思索,写下如下代码:

    for item in d:
    	img_content = requests.get(item['download_url']).content
    
    	with open(os.path.join('/home/download', item['file_name']), 'wb') as f:
    		f.write(img_content)
    
  • 当你美滋滋的查看美女图片时,殊不知,一个恶意文件已经下载到了你的电脑

进阶

也许,你会存在侥幸心理,只能拼接相对路径有什么用,我换一个路径执行不就失效了吗?

且慢,通过 Python 文档,我们可以发现这个方便却又危险的机制:

效果如下:

>>> os.path.join('/home/download', '/opt/logo.png')
/opt/logo.png

>>> pathlib.Path('/home/download') / '/opt/logo.png'
/opt/logo.png

基于此,恶意文件便可以存储至任意位置!