| I don't think this is right. .format() is not running any attacker controlled code. It might be formatting attacker controlled input, but the attacker has no control over the execution. > o what stop them from spamming Well I can't imagine how I would actually get that to turn into anything other than just a raw string that gets printed to the screen? Like I said, unless there's an eval somewhere it's not an issue. edit: OK, I see the problem now. The flask article is a lot clearer. The attacker can't control execution at all, or even really cause execution. What they can do is get your string to include information it should not - quite a footgun, but nothing close to RCE. edit2: I maybe see a way this could be bad (if the attacker controls the format string that you call .format on), but I can't actually get it working myself. So here's the thing. The attack as you've described does not work. Python won't just execute that string, you'll get a KeyError. What you need to do is, given a value provided to the string, call some sort of methods on that value such that you can perform your attack. This should be possible. edit: I'm trying to get this attack to work. So far, nah. My assumptions are: 1. Attacker has full control over format string 2. `requests` is imported already (obviously you could just use the stdlib but I'm lazy) 3. An object or class is passed in In theory I can construct a class from an object like this: Foo.__class__('requests', (requests.Request,), dict())()
<Request [None]>
But so far that manifests as...>>> "{0.__class__('requests', (requests.Request,), dict())()}".format(Foo)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'Foo' has no attribute '__class__('requests', (requests' It seems that Python does not just naively execute what's inside of this thing. Similarly, >>> "{0.__init__((lambda: requests.get('google.com'))())}".format(Foo)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'Foo' has no attribute '__init__((lambda' If there's a way to exploit this for actual code execution I can't find it easily. |