Injection problem analysis of Python template engine
- 2020-05-19 05:10:46
- OfStack
One of the most popular vulnerabilities in recent years is the injection of template engines such as jinjia2. By injecting 1 specific instruction format of the template engine, such as {{1+1}}, the return of 2 indicates the existence of the vulnerability. In practice, a similar problem exists with Python native strings, especially when Python 3.6 adds f strings, which should be noted, though not explicitly utilized.
The original %
userdata = {"user" : "jdoe", "password" : "secret" }
passwd = raw_input("Password: ")
if passwd != userdata["password"]:
print ("Password " + passwd + " is wrong for user %(user)s") % userdata
If the user enters %(password)s, you can get the user's real password.
The format method is related
https://docs.python.org/3/library/functions.html#format
payload ("Password "+ passwd +" is wrong for user {user}").format(**userdata
>>> import os
>>> '{0.system}'.format(os)
'<built-in function system>'
The 0 is replaced with the parameter in format, and then the relevant properties are retrieved.
But it looks like you can only get properties, you can't execute methods, right? But you can also get some sensitive information.
Example: http: / / lucumr. pocoo. org / 2016/12/29 / careful - with - str - format /
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)
If format_string is {event. s 53en. s 54en__ [CONFIG][SECRET_KEY]}, sensitive information can be disclosed.
f string in Python 3.6
This string is very powerful, similar to the template string in Javascript ES6, with the ability to get the current context variables.
https://docs.python.org/3/reference/lexical_analysis.html#f-strings
>>> a = "Hello"
>>> b = f"{a} World"
>>> b
'Hello World'
And it's not just restricted to properties, it's executable.
>>> import os
>>> f"{os.system('ls')}"
bin etc lib media proc run srv tmp var
dev home linuxrc mnt root sbin sys usr
'0'
>>> f"{(lambda x: x - 10)(100)}"
'90'
However, it seems that there is no way to convert 1 ordinary string into f string, which means that the user may not be able to control 1 f string and may not be able to make use of it, so he needs to continue to check 1.