In this paper, we analyze the security vulnerabilities of a new type of syntax introduced in Python development, and provide the corresponding security solutions.
When we use Str.format for untrusted user input, there will be a security risk-and I know for sure, but until today I am really aware of its seriousness. Because an attacker can use it to bypass the JINJA2 sandbox, this can cause serious information disclosure problems. At the same time, I have provided a new secure version for Str.format in the last part of this article.
To be reminded, this is a fairly serious security risk, and the reason for this is that most people probably don't know how easy it is to be exploited.
Core issues
Starting with Python 2.6, Python was inspired by. NET to introduce a new syntax for formatting strings. Of course, in addition to Python, rust and some other programming languages support this syntax. With the. Format () method, the syntax can be applied to byte and Unicode strings (in Python 3, only for Unicode strings), and it can also be mapped to a more customizable string. Formatter API.
One feature of this syntax is that people can use it to determine the location and keyword parameters of a string format, and to reorder data items at any time. In addition, it can even access object properties and data items-the root cause of the security problems here.
In general, people can use it to do the following things:
>>> ' class of {0} is {0.__class__} '. Format (42)
"Class of"
In essence, any person who can control the format string has the potential to access various internal properties of the object.
Where is the problem?
The first question is how to control the format string. Can be done from the following places:
1. A translator that is not trusted in a string file. We are likely to succeed with them because many of the applications that are translated into multiple languages will use this new Python string format method, but not all of them will be fully vetted for all the strings entered.
2. User-exposed configuration. Because some system users can configure certain behaviors, these configurations may be exposed as format strings. In particular, I've seen that some users can configure notification messages, log message formats, or other basic templates through a Web application.
Hazard rating
If you just pass the C-interpreter object to the format string, it's not too dangerous, because then you'll expose something like integer classes.
However, once the Python object is passed to this format string, it is troublesome. This is because the number of things that can be exposed from a python function is quite astonishing. Here is the scenario for an imaginary Web application in which the key can be compromised:
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 (eventevent=event)
If the user can inject format_string here, then they can find the following secret string:
{Event.__init__.__globals__[config][secret_key]}
Turn formatting into sandboxed processing
So what if you need someone else to provide a formatted string? In fact, some of the undisclosed internal mechanisms can be used to change the behavior of string formatting.
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
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 was 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 ()
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
Objobj = Obj[i]
return obj, first
def safe_getattr (obj, attr):
# Expand the logic here. For instance on 2.x you'll also need
# to disallow Func_globals, on 3.x you'll also need to hide
# things like Cr_frame and others. So ideally has a list of
# objects that is 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)
Now, we can use the Safe_format method instead of Str.format:
>>> ' {0.__class__} '. Format (42)
""
>>> Safe_format (' {0.__class__} ', 42)
Traceback (most recent):
File "", Line 1, in
Attributeerror: __class__
Summary
In this paper, we analyze the security vulnerabilities of a new type of syntax introduced by Python, and provide the corresponding security solution, hoping to be helpful to the readers.
Source: 51CTO
Python program Ape-known new string format vulnerability