Open In App

Vulnerability in str.format() in Python

Last Updated : 06 Jan, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

str.format() is one of the string formatting methods in Python, which allows multiple substitutions and value formatting. This method lets us concatenate elements within a string through positional formatting. But the vulnerability comes when our Python app uses str.format in the user-controlled string.

Let’s understand with the help of an example:

Python
# Sensitive configuration data
CONFIG = {
    "KEY": "ASXFYFGK78989"
}

class Person:
    def __init__(self, s1, s2):
        self.s1 = s1
        self.s2 = s2

def fun(template, person):
    return template.format(person_obj=person)

# Create a person object
person = Person("GEEKS", "FORGEEKS")

# Case 1: Safe input
a= "Avatar_{person_obj.s1}_{person_obj.s2}"
print(fun(a, person)) 

# Case 2: Malicious input
b= "{person_obj.__init__.__globals__[CONFIG][KEY]}"
print(fun(b, person))

Output
Avatar_GEEKS_FORGEEKS
ASXFYFGK78989

Explanation:

  • Person Class: This class defines a template for creating people with s1 and s2 attributes.
  • fun Function: This function dynamically formats a string using the person object.
  • Case 1 (Safe input):This is the expected, safe result, where the placeholders are replaced with valid values from the person object.
  • Case 2(Malicious Input):This is a dangerous situation where a malicious user can exploit the str.format() method to retrieve sensitive data from the global context.

Why is Case 2 a Vulnerability?

str.format() method can evaluate expressions within the format string, allowing access to variables and object details. This means a user can manipulate the input to access sensitive data, like the CONFIG dictionary. This creates a security risk because attackers could retrieve information they should not have access to.

Using f-strings

f-strings provide a more controlled way of formatting strings and do not evaluate arbitrary expressions. They are safer and faster than str.format().

Python
class Person:
    def __init__(self, s1, s2):
        self.s1 = s1
        self.s2= s2

# Create a person object
person = Person("Geeks", "ForGeeks")

# Use f-string for formatting
a = f"Avatar_{person.s1}_{person.s2}"
print(a)

Output
Avatar_Geeks_ForGeeks

Explanation:

  • Class and Object : Person class is defined with attributes s1 and s2, and an object person is created with values "Geeks" fors1 and "ForGeeks" for s2.
  • f-string Formatting: This is used to format and print the string as "Avatar_Geeks_ForGeeks", inserting the values of person.s1and person.s2.

Using string.Template class

This is a simpler, safer alternative to str.format(), as it only supports simple placeholder replacements ($variable) and does not evaluate Python expressions.

Python
from string import Template

class Person:
    def __init__(self, s1, s2):
        self.s1 = s1
        self.s2= s2

# Create a person object
person = Person("Geeks", "ForGeeks")

# Safe way using string.Template
template = Template("Avatar_${s1}_${s2}")
a = template.substitute(s1=person.s1, s2=person.s2)
print(a)

Output
Avatar_Geeks_ForGeeks

Explanation:

  • Class and Object:Person class is created with s1 and s2 attributes, and a person object is initialized with "Geeks" and "ForGeeks".
  • Template Substitution:This substitutes ${s1} and ${s2} with the object’s attributes.


Next Article

Similar Reads