python格式化字符串漏洞_Python新型字符串格式漏洞分析及解决方案
最近一个python字符串格式化的漏洞引起了我的注意,今天就来说一下Python引入的一种格式化字符串的新型语法的安全漏洞进行了深入的分析,并提供了相应的安全解决方案。
当我们对不可信的用户输入使用str.format的时候,将会带来安全隐患——对于这个问题,其实我早就知道了,但是直到今天我才真正意识到它的严重性。因为攻击者可以利用它来绕过Jinja2沙盒,这会造成严重的信息泄露问题。同时,我在本文最后部分为str.format提供了一个新的安全版本。
需要提醒的是,这是一个相当严重的安全隐患,这里之所以撰文介绍,是因为大多数人很可能不知道它是多么容易被利用。
核心问题
从Python 2.6开始,Python受.NET启发而引入了一种格式化字符串的新型语法。当然,除了Python之外,Rust及其他一些编程语言也支持这种语法。借助于.format()方法,该语法可以应用到字节和unicode字符串(在Python 3中,只能用于unicode字符串)上面,此外,它还能映射为更加具有可定制性的string.Formatter API。
该语法的一个特点是,人们可以通过它确定出字符串格式的位置和关键字参数,并且随时可以显式对数据项重新排序。此外,它甚至可以访问对象的属性和数据项——这是导致这里的安全问题的根本原因。
总的来说,人们可以利用它来进行以下事情:>>> 'class of {0} is {0.__class__}'.format(42)
"class of 42 is "
实质上,任何能够控制格式字符串的人都有可能访问对象的各种内部属性。
问题出在哪里?
第一个问题是,如何控制格式字符串。可以从下列地方下手:
1.字符串文件中不可信的翻译器。我们很可能通过它们得手,因为许多被翻译成多种语言的应用程序都会用到这种新式Python字符串格式化方法,但是并非所有人都会对输入的所有字符串进行全面的审查。
2.用户暴露的配置。 由于一些系统用户可以对某些行为进行配置,而这些配置有可能以格式字符串的形式被暴露出来。需要特别提示的是,我就见过某些用户可以通过Web应用程序来配置通知邮件、日志消息格式或其他基本模板。
危险等级
如果只是向该格式字符串传递C解释器对象的话,倒是不会有太大的危险,因为这样的话,你最多会暴露一些整数类之类的东西。
然而,一旦Python对象被传递给这种格式字符串的话,那就麻烦了。这是因为,能够从Python函数暴露的东西的数量是相当惊人的。 下面是假想的Web应用程序的情形,这种情况下能够泄露密钥:
CONFIG = {
'SECRET_KEY': 'super secret key'
}
class Event(object):
def __init__(self, id, level, message):
self.id = id
self.level = level
self.message = message
def format_event(format_string, event):
return format_string.format(event=event)
如果用户可以在这里注入format_string,那么他们就能发现下面这样的秘密字符串:{event.__init__.__globals__[CONFIG][SECRET_KEY]}
将格式化作沙箱化处理
那么,如果需要让其他人提供格式化字符串,那该怎么办呢? 其实,可以利用某些未公开的内部机制来改变字符串格式化行为。from string import Formatter
from collections import Mapping
class MagicFormatMapping(Mapping):
"""This class implements a dummy wrapper to fix a bug in the Python
standard library for string formatting.
See http://bugs.python.org/issue13598 for information about why
this is necessary.
"""
def __init__(self, args, kwargs):
self._args = args
self._kwargs = kwargs
self._last_index = 0
def __getitem__(self, key):
if key == '':
idx = self._last_index
self._last_index += 1
try:
return self._args[idx]
except LookupError:
pass
key = str(idx)
return self._kwargs[key]
def __iter__(self):
return iter(self._kwargs)
def __len__(self):
return len(self._kwargs)
# This is a necessary API but it's undocumented and moved around
# between Python releases
try:
from _string import formatter_field_name_split
except ImportError:
formatter_field_name_split = lambda \
x: x._formatter_field_name_split()
{C}
class SafeFormatter(Formatter):
def get_field(self, field_name, args, kwargs):
first, rest = formatter_field_name_split(field_name)
obj = self.get_value(first, args, kwargs)
for is_attr, i in rest:
if is_attr:
obj = safe_getattr(obj, i)
else:
obj = obj[i]
return obj, first
def safe_getattr(obj, attr):
# Expand the logic here. For instance on 2.x you will also need
# to disallow func_globals, on 3.x you will also need to hide
# things like cr_frame and others. So ideally have a list of
# objects that are entirely unsafe to access.
if attr[:1] == '_':
raise AttributeError(attr)
return getattr(obj, attr)
def safe_format(_string, *args, **kwargs):
formatter = SafeFormatter()
kwargs = MagicFormatMapping(args, kwargs)
return formatter.vformat(_string, args, kwargs)
现在,我们就可以使用safe_format方法来替代str.format了:>>> '{0.__class__}'.format(42)
""
>>> safe_format('{0.__class__}', 42)
Traceback (most recent call last):
File "", line 1, in
AttributeError: __class__
总结:
程序开发中有这么一句话:任何时候不要相信用户的输入!现在看来这句话说得非常有道理。所以各位同学要谨记!
python格式化字符串漏洞_Python新型字符串格式漏洞分析及解决方案相关推荐
- python字符串输入_Python输入字符串的方法和实例代码
Python怎么输入字符串 首先,要显示字符串,直接 print(字符串) 就可以显示了. 字符串可以用单引号或者双引号,python中没有字符类型. 多个字符串直接连着写,就表示连接,字符串内部的转 ...
- python字符串添加元素_python向字符串中添加元素的实例方法
Python中的字符串对象是不能更改的,也即直接修改字符串中的某一位或几位字符是实现不了的,即python中字符串对象不可更改,但字符串对象的引用可更改,可重新指向新的字符串对象. + 直接字符串外+ ...
- python格式化输出(二)--字符串的格式化输出
** 字符串的格式化输出 ** 1.使用占位符 (1)三个常用占位符用法 ①d:将整数.浮点数转换成十进制表示.取整,不进行四舍五入. ②f:将整数.浮点数转换成浮点数表示,默认保留小数点后6位,四 ...
- python替换字符串元素_python替换字符串中的子串图文步骤
python替换字符串中的子串图文步骤 修改字符串本身是不可能的,因为字符串是不可变类型,只能是通过某些方法来产生它的副本.再把副本赋值给原字符串,达到类似替换的作用.这里介绍几种方法. 旧串换新串: ...
- python字符串排序_Python对字符串列表进行排序
在本教程中,我们将看到如何对字符串列表进行排序.我们将使用sort方法和sorted函数对给定的字符串列表进行排序.然后,我们将了解如何根据不同的条件(例如长度,值等)对字符串列表进行排序, 让我们看 ...
- python字符串转义序列_Python | 忽略字符串中的转义序列
python字符串转义序列 First see, how escape sequence works? 首先看,转义序列如何工作? In the below example, we are using ...
- [转载] python 遍历字符串 字符_python 遍历字符串(含汉字)实例详解
参考链接: Python字符串| rfind python 遍历字符串(含汉字)实例详解 python 遍历字符串(含汉字)实例详解 s = "中国china" for j in ...
- python字符串 切片_Python切片字符串
python字符串 切片 Python string supports slicing to create substring. Note that Python string is immutabl ...
- python 遍历字符串 字符_python 遍历字符串(含汉字)实例详解
python 遍历字符串(含汉字)实例详解 python 遍历字符串(含汉字)实例详解 s = "中国china" for j in s: print j 首先一个,你这个'a'是 ...
最新文章
- 头戴式AR/VR 光学标定
- Go语言11岁了,网友:他喵的,终于确定出「泛型」了
- 怎么设置java的精度值_Java:如何为double值设置Precision?
- php mysql备份类_php MYSQL 数据备份类
- 立冬节气主题海报你知道怎么做了么?灵感给你,学起来!
- AndroidStudio_开发工具调试入门---Android原生开发工作笔记70
- python连接mongodb数据库、创建用户_mongodb对数据库创建用户名和密码
- 快速备份和还原 MySQL 数据库的另一种方法
- 在Node中使用ES7新特征——async、await
- word如何批量免费转PDF
- 不同编码的MP4视频在各大游览器播放总结
- 什么是503服务不可用错误(以及如何解决)?
- ddos应急处理_DDoS攻击应急体系知多少?
- 2020-2021读书记录
- k8s学习笔记2-搭建harbor私有仓库
- crx什么意思_CRX文件怎么打开-CRX是什么格式-CRX文件是什么意思-腾牛网
- 深圳-银湖山郊野公园
- 离开腾讯首创业,贾佳亚谈人工智能 2.0 革命,技术究竟该如何变革?
- 神级操作丨用 Python 将微信热文转换成Word文档
- 【MySQL·水滴计划】第三话- SQL的基本概念
热门文章
- python dict()函数(用于创建一个字典)
- python 正则表达式 re.findall()方法
- YunYang1994/tensorflow-yolov3 Readme 翻译
- Visual Studio C/C++ 相对路径和绝对路径
- 获取表单内部元素的N种方法
- MySQL5.6解压版详细安装教程(附安装配置、MySQL数据库设置root管理员密码,MySQL字符集设置问题及解决办法)
- Mr. Main and Windmills 模拟,计算几何(昆明)
- android componentname activity,ComponentName的使用
- 石油大c语言答案,中国石油大学C语言答案
- Oracle导入报错:ORA-01653表 无法通过 128 (在表空间 MY_BASE_DATA 中) 扩展