Get a Pentest and security assessment of your IT network.

Cyber Security

Python F-strings & User Input: Security Risks

TL;DR

Using Python f-strings directly with user input is dangerous. It can allow attackers to run arbitrary code on your system. Always sanitise or validate user input before using it in f-strings, or use safer alternatives like the format() method with explicit type specification.

Understanding the Problem

Python f-strings are a convenient way to embed expressions inside string literals. However, if you directly include unsanitised user input within an f-string, it’s possible for malicious code to be executed. This is because Python will evaluate anything inside the curly braces {} before creating the final string.

How It Works: Code Injection

Imagine you have a script that takes user input and uses it in an f-string:

user_input = input("Enter something:")
print(f"You entered: {user_input}")

If the user enters something harmless, like “Hello”, everything is fine. But if they enter {os.system('rm -rf /')} (don’t actually do this!), Python will try to execute that code.

Step-by-step Solution

  1. Never Trust User Input: Assume all user input is potentially malicious.
  2. Sanitise or Validate Input: This is the most important step. You have a few options:
    • Whitelisting: Only allow specific characters or patterns. For example, if you expect a number, only accept digits.
      import re
      user_input = input("Enter a number:")
      if re.match(r'^[0-9]+$', user_input):
        print(f"You entered: {user_input}")
      else:
        print("Invalid input!")
    • Blacklisting (Generally Avoid): Try to remove dangerous characters or patterns. This is less reliable as attackers can often find ways around your filters.
  3. Use format() with Explicit Types: The format() method offers more control and doesn’t automatically evaluate expressions in the same way f-strings do. Specify the expected data type to prevent code injection.
    user_input = input("Enter a number:")
    try:
      number = int(user_input)
      print("You entered: {}".format(number))
    except ValueError:
      print("Invalid input!")
  4. Escape Special Characters: If you absolutely must use f-strings with user input, escape any special characters that could be interpreted as code.
    user_input = input("Enter something:")
    escaped_input = user_input.replace('{', '{{').replace('}', '}}')
    print(f"You entered: {escaped_input}")

    Note: This is not a complete solution and should be used with extreme caution.

  5. Consider Alternatives: If possible, avoid using user input directly in f-strings altogether. Use pre-defined strings or data structures instead.

Example of a Vulnerable Scenario

Let’s say you’re building a simple web application that displays a welcome message:

username = input("Enter your username:")
print(f"Welcome, {username}!")

An attacker could enter {os.system('whoami')} to execute the whoami command on your server.

Key Takeaways

  • F-strings are powerful but can be dangerous with user input.
  • Always sanitise or validate user input before using it in f-strings.
  • The format() method is a safer alternative.
  • Prioritise security and assume all user input is malicious.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation