4 ms·
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 co
by staticassertion 5y ago
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.