前言

午休的时候在安全加看到一篇漏洞预警:CVE-2017-17522 Python webbrowser.py 命令执行漏洞分析,Python的webbrowser内置模块存在远程代码执行漏洞。本来对Python相关的安全问题比较感兴趣,看了下漏洞文件https:///python/cpython/blob/master/Lib/webbrowser.py,上下也就600来行代码,想来也复杂不到哪去,便想着跟一波。

webbrowser模块简介

无论是利用漏洞还是分析漏洞,都要讲究一个业务场景,要知道存在漏洞的模块在什么场景下会被调用,用来解决了什么问题。不然,即使是再牛逼的漏洞,价值也不大。

文档得第一段是这么说的:The webbrowser module provides a high-level interface to allow displaying Web-based documents to users. Under most circumstances, simply calling the open() function from this module will do the right thing.

就是说通过webbrowser模块可以对浏览器进行操作。

先来两行代码感受下:

>>> import webbrowser
>>> url = "https://www.baidu.com/"
>>> webbrowser.open(url)
True
>>>

调用webbrowser.open()将会启动系统默认的浏览器访问到我们指定的url。

漏洞分析Lib/webbrowser.py in Python through 3.6.3 does not validate strings before launching the program specified by the BROWSER environment variable, which might allow remote attackers to conduct argument-injection attacks via a crafted URL.

Lib/webbrowser.py模块的内置方法启动通过BROWSER环境变量指定的程序(浏览器)时,没有对传入的参数做过滤,可能导致远程代码执行漏洞。

通过描述可知漏洞出现在BROWSER环境变量。同时代码中有多次对subprocess.Popen()函数进行调用。屡一下思路那就应该是,通过传入url,控制了环境变量中BROWSER的值,带入到subprocess.Popen()函数中实现命令执行。(感谢有点鸡肋2333)

理清代码执行流程

第1步:设置环境变量

set BROWSER=C:\Program Files (x86)\Google\Chrome\Application\chrome.exe;C:\Program Files (x86)\Google\Chrome\

之前也没有设置过环境变量BROWSER的值,一般应该也用不到,设置浏览器driver的时候,用到它会比较方便。如图,BROWSER已经设置成功。

第2步:分析Lib/webbrowser.py的第621-634行

这是一个没有在函数、类下的if判断逻辑,当执行import webbrowser操作的时候,这部份代码就会执行。

print(cmd)可知,cmd内容为空

if cmd[1] is None:条件成立,会继续执行该if分支的代码,回溯下register(),GenericBrowser()的实现代码(124-148行):

在GenericBrowser类下的open()函数(138-148行)调用了subprocess.Popen()函数,传入参数cmdline,cmdline的值由环境变量中获得。

未完待续...困得不行了...指尖安全的大佬已经出分析了,有需要的可以去那边看:CVE-2017-17522 Python webbrowser.py 命令执行漏洞分析,我这边主要是做一个分析漏洞的笔记,想到哪里写到哪里,明天再更新。