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.


Related articles: