Python新型字符串格式漏洞分析

前言

本文对Python引入的一种格式化字符串的新型语法的安全漏洞进行了深入的分析,并提供了相应的安全解决方案。

当我们对不可信的用户输入使用str.format的时候,将会带来安全隐患——对于这个问题,其实我早就知道了,但是直到今天我才真正意识到它的严重性。因为攻击者可以利用它来绕过Jinja2沙盒,这会造成严重的信息泄露问题。同时,我在本文最后部分为str.format提供了一个新的安全版本。

需要提醒的是,这是一个相当严重的安全隐患,这里之所以撰文介绍,是因为大多数人很可能不知道它是多么容易被利用。

核心问题

从Python 2.6开始,Python受.NET启发而引入了一种格式化字符串的新型语法。当然,除了Python之外,Rust及其他一些编程语言也支持这种语法。借助于.format()方法,该语法可以应用到字节和unicode字符串(在Python 3中,只能用于unicode字符串)上面,此外,它还能映射为更加具有可定制性的string.Formatter API。

该语法的一个特点是,人们可以通过它确定出字符串格式的位置和关键字参数,并且随时可以显式对数据项重新排序。此外,它甚至可以访问对象的属性和数据项——这是导致这里的安全问题的根本原因。

总的来说,人们可以利用它来进行以下事情:


  1. >>> 'class of {0} is {0.__class__}'.format(42) 
  2. "class of 42 is <class 'int'>" 

实质上,任何能够控制格式字符串的人都有可能访问对象的各种内部属性。

问题出在哪里?

第一个问题是,如何控制格式字符串。可以从下列地方下手:

1.字符串文件中不可信的翻译器。我们很可能通过它们得手,因为许多被翻译成多种语言的应用程序都会用到这种新式Python字符串格式化方法,但是并非所有人都会对输入的所有字符串进行全面的审查。

2.用户暴露的配置。 由于一些系统用户可以对某些行为进行配置,而这些配置有可能以格式字符串的形式被暴露出来。需要特别提示的是,我就见过某些用户可以通过Web应用程序来配置通知邮件、日志消息格式或其他基本模板。

危险等级

如果只是向该格式字符串传递C解释器对象的话,倒是不会有太大的危险,因为这样的话,你最多会暴露一些整数类之类的东西。

然而,一旦Python对象被传递给这种格式字符串的话,那就麻烦了。这是因为,能够从Python函数暴露的东西的数量是相当惊人的。 下面是假想的Web应用程序的情形,这种情况下能够泄露密钥:


  1. CONFIG = { 
  2.     'SECRET_KEY': 'super secret key' 
  3.    
  4. class Event(object): 
  5.     def __init__(self, id, level, message): 
  6.         self.id = id 
  7.         self.level = level 
  8.         self.message = message 
  9.    
  10. def format_event(format_string, event): 
  11.     return format_string.format(eventevent=event) 

如果用户可以在这里注入format_string,那么他们就能发现下面这样的秘密字符串:


  1. {event.__init__.__globals__[CONFIG][SECRET_KEY]} 

将格式化作沙箱化处理

那么,如果需要让其他人提供格式化字符串,那该怎么办呢? 其实,可以利用某些未公开的内部机制来改变字符串格式化行为。


  1. from string import Formatter 
  2. from collections import Mapping 
  3.    
  4. class MagicFormatMapping(Mapping): 
  5.     """This class implements a dummy wrapper to fix a bug in the Python 
  6.     standard library for string formatting. 
  7.    
  8.     See http://bugs.python.org/issue13598 for information about why 
  9.     this is necessary. 
  10.     """ 
  11.    
  12.     def __init__(self, args, kwargs): 
  13.         self._args = args 
  14.         self._kwargs = kwargs 
  15.         self._last_index = 0 
  16.    
  17.     def __getitem__(self, key): 
  18.         if key == '': 
  19.             idx = self._last_index 
  20.             self._last_index += 1 
  21.             try: 
  22.                 return self._args[idx] 
  23.             except LookupError: 
  24.                 pass 
  25.             key = str(idx) 
  26.         return self._kwargs[key] 
  27.    
  28.     def __iter__(self): 
  29.         return iter(self._kwargs) 
  30.    
  31.     def __len__(self): 
  32.         return len(self._kwargs) 
  33.    
  34. # This is a necessary API but it's undocumented and moved around 
  35. # between Python releases 
  36. try: 
  37.     from _string import formatter_field_name_split 
  38. except ImportError: 
  39.     formatter_field_name_split = lambda \ 
  40.         x: x._formatter_field_name_split() 
  41.    
  42. class SafeFormatter(Formatter): 
  43.    
  44.     def get_field(self, field_name, args, kwargs): 
  45.         first, rest = formatter_field_name_split(field_name) 
  46.         obj = self.get_value(first, args, kwargs) 
  47.         for is_attr, i in rest: 
  48.             if is_attr: 
  49.                 obj = safe_getattr(obj, i) 
  50.             else: 
  51.                 objobj = obj[i] 
  52.         return obj, first 
  53.    
  54. def safe_getattr(obj, attr): 
  55.     # Expand the logic here.  For instance on 2.x you will also need 
  56.     # to disallow func_globals, on 3.x you will also need to hide 
  57.     # things like cr_frame and others.  So ideally have a list of 
  58.     # objects that are entirely unsafe to access. 
  59.     if attr[:1] == '_': 
  60.         raise AttributeError(attr) 
  61.     return getattr(obj, attr) 
  62.    
  63. def safe_format(_string, *args, **kwargs): 
  64.     formatter = SafeFormatter() 
  65.     kwargs = MagicFormatMapping(args, kwargs) 
  66.     return formatter.vformat(_string, args, kwargs) 

现在,我们就可以使用safe_format方法来替代str.format了:


  1. >>> '{0.__class__}'.format(42) 
  2. "<type 'int'>" 
  3. >>> safe_format('{0.__class__}', 42) 
  4. Traceback (most recent call last): 
  5.   File "<stdin>", line 1, in <module> 
  6. AttributeError: __class__ 

小结

在本文中,我们对Python引入的一种格式化字符串的新型语法的安全漏洞进行了深入的分析,并提供了相应的安全解决方案,希望对读者能够有所帮助。

作者:shan66

来源:51CTO

时间: 2024-10-28 11:58:32

Python新型字符串格式漏洞分析的相关文章

字符串格式不正确 将一个字符串转换为datatime,先分析字符串以获取日期 。怎么改啊求高手帮忙

问题描述 字符串格式不正确 将一个字符串转换为datatime,先分析字符串以获取日期 .怎么改啊求高手帮忙 string sql1 = "insert into shuju(sid,m1,date,time1,time2,m2,state,m3,status,m4,tq_state,m5,msg_count,m6,msg_bytes) values ('" + Convert.ToSingle(sid.Trim()) + "','" + Convert.ToSin

思科Catalyst 2960交换机中的CVE-2017-3881漏洞分析

本文讲的是思科Catalyst 2960交换机中的CVE-2017-3881漏洞分析, 2017年3月17日,思科官方网站发布公告称Cisco IOS&IOS XE Software 集群管理协议(Cluster Management Protocol)存在远程执行代码漏洞(CVE-2017-3881). 该漏洞是思科在研究CIA泄漏文档"Vault 7"的过程中发现的,攻击者可以在未授权的情况下远程重启受影响的设备或越权执行代码.造成该漏洞的主要原因是由于没有限制CMP-sp

又被野外利用了!新曝光Office产品多个远程命令执行漏洞分析

本文讲的是又被野外利用了!新曝光Office产品多个远程命令执行漏洞分析, 早在2015年,FireEye曾发布过两次关于Office的Encapsulated PostScript (EPS)图形文件的漏洞攻击的研究分析,其中一次属于零日漏洞攻击. 今年3月开始,FireEye再一次在微软Office产品中陆续发现三个新的零日漏洞,发现时这些漏洞已被野外利用. 第一个漏洞出现在今年的3月下旬,CVE-2017-0261中描述了Office远程代码执行漏洞(RCE)漏洞,FireEye认为该漏洞

python判断字符串是否包含子字符串的方法

 这篇文章主要介绍了python判断字符串是否包含子字符串的方法,实例分析了Python中的in与find方法来实现这一功能,非常具有实用价值,需要的朋友可以参考下     本文实例讲述了python判断字符串是否包含子字符串的方法.分享给大家供大家参考.具体如下: python的string对象没有contains方法,不用使用string.contains的方法判断是否包含子字符串,但是python有更简单的方法来替换contains函数. 方法1:使用 in 方法实现contains的功能

python中字符串前面加r的作用

  本文实例讲述了python中字符串前面加r的作用.分享给大家供大家参考.具体分析如下: 字符串前面加r,表示的意思是禁止字符串转义 ? 1 2 3 4 5 6 7 8 >>> print "asfdasn" asfdas >>> print "asfdasn" asfdasn >>> print "asfdasn" asfdas >>> print r"asfd

python实现字符串和日期相互转换的方法

  本文实例讲述了python实现字符串和日期相互转换的方法.分享给大家供大家参考.具体分析如下: 这里用的分别是time和datetime函数 ? 1 2 3 4 5 6 7 8 9 10 ''' @author: jiangqh ''' import time,datetime # date to str print time.strftime("%Y-%m-%d %X", time.localtime()) #str to date t = time.strptime("

Windows Server中的 WINS 服务器远程内存损坏漏洞分析

本文讲的是Windows Server中的 WINS 服务器远程内存损坏漏洞分析, 漏洞概要 在2016年12月,FortiGuard Labs发现并报告了Microsoft Windows Server中的WINS Server远程内存损坏漏洞.在2017年6月,微软向FortiGuard实验室答复说:"要修复程序漏洞需要对代码进行全面彻底的检查,WINS所提供的功能会被DNS所取代,微软已经建议客户将其迁移出去.也就是说,由于修复漏洞所需要的工作量,Microsoft不会修补此漏洞.相反,M

Joomla 对象注入漏洞分析报告

本文讲的是 Joomla 对象注入漏洞分析报告,近日,Joomla再曝高危0day漏洞,可进行远程命令执行,阿里云云盾昨日已上线相应的拦截规则抵御该漏洞.同时,对云托管客户已经做了电话通知和自动漏洞修复.统计数据显示,截至16日凌晨,已有数百个恶意IP尝试使用该漏洞对阿里云网站发起攻击,云盾已成功拦截上万次攻击请求,其中攻击请求数排名第一的黑客在一小时内尝试入侵超过1000个 Joomla 网站. 根据此次漏洞情况,Joomla 官方已紧急放出了3.4.6版本.joomla用户除了尽快升级至最新

Pwn2Own2017专题:VMWARE UAF漏洞分析

本文讲的是Pwn2Own2017专题:VMWARE UAF漏洞分析, 本文将讨论各种VMware主题,包括利用,扭转和虚拟化VMware目标,从虚拟客户端到执行代码. 注意:VMware Workstation 12.5.2及更低版本中都存在此漏洞,不过随后的VMware Workstation 12.5.3版修补了这些漏洞.此处显示的所有分析都是在VMware Workstation 12.5.1上完成的. 漏洞分析 在我解释所涉及的漏洞的细节之前,请先浏览一下以下的视频:   这个漏洞的好处